Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--BuildToolsVersion.txt2
-rw-r--r--CodeAnalysis.ruleset9
-rw-r--r--Documentation/coding-guidelines/coding-style.md1
-rw-r--r--Documentation/project-docs/developer-guide.md71
-rw-r--r--Documentation/project-docs/issue-guide.md31
-rw-r--r--Packaging.props6
-rw-r--r--PinvokeAnalyzer_OneCoreApis.txt7275
-rw-r--r--PinvokeAnalyzer_UWPApis.txt2298
-rw-r--r--build.cmd4
-rw-r--r--build.proj15
-rwxr-xr-xbuild.sh52
-rw-r--r--buildpipeline/DotNet-Trusted-Publish.json28
-rw-r--r--config.json35
-rw-r--r--cross/arm-softfp/sources.list.jessie6
-rw-r--r--cross/arm/sources.list.xenial11
-rw-r--r--cross/arm64/sources.list.xenial11
-rw-r--r--cross/armel/sources.list.jessie7
-rw-r--r--cross/armel/toolchain.cmake (renamed from cross/arm-softfp/toolchain.cmake)0
-rw-r--r--cross/armel/tryrun.cmake (renamed from cross/arm-softfp/tryrun.cmake)0
-rwxr-xr-xcross/build-rootfs.sh28
-rw-r--r--cross/x86/sources.list.trusty11
-rw-r--r--cross/x86/sources.list.vivid11
-rw-r--r--cross/x86/sources.list.wily11
-rw-r--r--cross/x86/sources.list.xenial11
-rw-r--r--cross/x86/toolchain.cmake23
-rw-r--r--cross/x86/tryrun.cmake7
-rw-r--r--dependencies.props8
-rw-r--r--dir.props40
-rw-r--r--dir.targets8
-rw-r--r--layout/ApiCompatBaseline.netfx461.txt226
-rw-r--r--layout/ApiCompatBaseline.netstandard20.txt209
-rw-r--r--netci.groovy2
-rw-r--r--pkg/Microsoft.NETCore.Platforms/runtime.json438
-rw-r--r--pkg/Microsoft.Private.PackageBaseline/packageIndex.json43
-rw-r--r--pkg/baseline/packageBaseline.1.1.json449
-rw-r--r--pkg/descriptions.json8
-rw-r--r--pkg/useSharedDesignerContext.txt0
-rwxr-xr-xrun-test.sh6
-rw-r--r--src/Common/src/Interop/OSX/Interop.CommonCrypto.cs2
-rw-r--r--src/Common/src/Interop/OSX/Interop.SystemConfiguration.cs2
-rw-r--r--src/Common/src/Interop/OSX/Interop.libproc.cs14
-rw-r--r--src/Common/src/Interop/OSX/System.Native/Interop.ProtocolStatistics.cs12
-rw-r--r--src/Common/src/Interop/OSX/System.Native/Interop.TcpConnectionInfo.cs8
-rw-r--r--src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Random.cs2
-rw-r--r--src/Common/src/Interop/Unix/Interop.Errors.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Globalization.Native/Interop.Idna.cs4
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.GetCwd.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.GetEnviron.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.GetNameInfo.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.GetPeerID.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.GetPeerUserName.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs4
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.Poll.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.Read.Pipe.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.Read.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.ReadLink.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.ReadStdinUnbuffered.cs6
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.SNPrintF.cs4
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.SendFile.cs14
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.StdinReady.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.Write.Pipe.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Native/Interop.Write.cs4
-rw-r--r--src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Pkcs12.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.RAND.cs2
-rw-r--r--src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs4
-rw-r--r--src/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs2
-rw-r--r--src/Common/src/Interop/Windows/BCrypt/Interop.Blobs.cs4
-rw-r--r--src/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs50
-rw-r--r--src/Common/src/Interop/Windows/Interop.Libraries.cs2
-rw-r--r--src/Common/src/Interop/Windows/NCrypt/Interop.EncryptDecrypt.cs8
-rw-r--r--src/Common/src/Interop/Windows/NCrypt/Interop.SignVerify.cs4
-rw-r--r--src/Common/src/Interop/Windows/SChannel/UnmanagedCertificateContext.cs2
-rw-r--r--src/Common/src/Interop/Windows/Winsock/Interop.TransmitFile.cs32
-rw-r--r--src/Common/src/Interop/Windows/Winsock/Interop.WSASocketW.SafeCloseSocket.cs2
-rw-r--r--src/Common/src/Interop/Windows/Winsock/Interop.recv.cs2
-rw-r--r--src/Common/src/Interop/Windows/Winsock/Interop.recvfrom.cs2
-rw-r--r--src/Common/src/Interop/Windows/Winsock/Interop.send.cs2
-rw-r--r--src/Common/src/Interop/Windows/Winsock/Interop.sendto.cs2
-rw-r--r--src/Common/src/Interop/Windows/advapi32/Interop.ControlService.cs2
-rw-r--r--src/Common/src/Interop/Windows/advapi32/Interop.EventWriteTransfer.cs2
-rw-r--r--src/Common/src/Interop/Windows/advapi32/Interop.RegEnumKeyEx.cs2
-rw-r--r--src/Common/src/Interop/Windows/advapi32/Interop.RegEnumValue.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.CancelIoEx.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.ConnectNamedPipe.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.Encoding.Constants.cs12
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.GetCPInfoEx.cs41
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.GetFullPathNameW.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.MultiByteToWideChar.cs (renamed from src/Common/src/Interop/Windows/kernel32/Interop.GetLastError.cs)6
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.Normalization.cs40
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.ReadConsole.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.ReadConsoleOutput.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.ReadDirectoryChangesW.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_IntPtr.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.SetConsoleWindowInfo.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.SetFileInformationByHandle.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.SetNamedPipeHandleState.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.ThreadPoolIO.cs8
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.WideCharToMultiByte.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.WriteConsole.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.WriteConsoleOutput.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_IntPtr.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs2
-rw-r--r--src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs2
-rw-r--r--src/Common/src/Interop/Windows/normaliz/Interop.Idna.cs37
-rw-r--r--src/Common/src/Interop/Windows/shell32/Interop.SHGetKnownFolderPath.cs2
-rw-r--r--src/Common/src/Interop/Windows/sspicli/Interop.SSPI.cs26
-rw-r--r--src/Common/src/Interop/Windows/sspicli/SSPIWrapper.cs6
-rw-r--r--src/Common/src/Interop/Windows/sspicli/SecuritySafeHandles.cs24
-rw-r--r--src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs41
-rw-r--r--src/Common/src/System/Dynamic/Utils/CacheDict.cs36
-rw-r--r--src/Common/src/System/Dynamic/Utils/CollectionExtensions.AddFirst.cs19
-rw-r--r--src/Common/src/System/Dynamic/Utils/CollectionExtensions.Map.cs24
-rw-r--r--src/Common/src/System/Dynamic/Utils/CollectionExtensions.cs100
-rw-r--r--src/Common/src/System/Dynamic/Utils/ContractUtils.cs7
-rw-r--r--src/Common/src/System/Dynamic/Utils/DelegateHelpers.cs23
-rw-r--r--src/Common/src/System/Dynamic/Utils/ExpressionVisitorUtils.cs36
-rw-r--r--src/Common/src/System/Globalization/FormatProvider.Number.cs10
-rw-r--r--src/Common/src/System/Globalization/IdnMapping.Windows.cs113
-rw-r--r--src/Common/src/System/Globalization/IdnMapping.cs157
-rw-r--r--src/Common/src/System/IO/PathInternal.Windows.StringBuffer.cs2
-rw-r--r--src/Common/src/System/IO/PathInternal.Windows.cs8
-rw-r--r--src/Common/src/System/IO/PathInternal.cs2
-rw-r--r--src/Common/src/System/IO/StreamHelpers.CopyValidation.cs2
-rw-r--r--src/Common/src/System/LocalAppContext.cs38
-rw-r--r--src/Common/src/System/Net/ContextFlagsAdapterPal.Windows.cs4
-rw-r--r--src/Common/src/System/Net/HttpKnownHeaderNames.TryGetHeaderName.cs4
-rw-r--r--src/Common/src/System/Net/IPEndPointStatics.cs4
-rw-r--r--src/Common/src/System/Net/NTAuthentication.Common.cs (renamed from src/Common/src/System/Net/NTAuthentication.cs)90
-rw-r--r--src/Common/src/System/Net/NegotiationInfoClass.cs3
-rw-r--r--src/Common/src/System/Net/SafeCloseSocket.Unix.cs6
-rw-r--r--src/Common/src/System/Net/SafeCloseSocket.Windows.cs4
-rw-r--r--src/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs11
-rw-r--r--src/Common/src/System/Net/Security/NegotiateStreamPal.Windows.cs13
-rw-r--r--src/Common/src/System/Net/Security/NetEventSource.Security.Windows.cs (renamed from src/System.Net.Mail/src/System/Net/Security/NetEventSource.Security.Windows.cs)0
-rw-r--r--src/Common/src/System/Net/Security/NetEventSource.Security.cs (renamed from src/System.Net.Mail/src/System/Net/Security/NetEventSource.Security.cs)0
-rw-r--r--src/Common/src/System/Net/Security/SecurityBufferType.cs2
-rw-r--r--src/Common/src/System/Net/SecurityStatusAdapterPal.Windows.cs3
-rw-r--r--src/Common/src/System/Net/SocketAddress.cs4
-rw-r--r--src/Common/src/System/Net/SocketAddressPal.Unix.cs4
-rw-r--r--src/Common/src/System/Net/WebHeaderEncoding.cs4
-rw-r--r--src/Common/src/System/Numerics/Hashing/HashHelpers.cs8
-rw-r--r--src/Common/src/System/Runtime/InteropServices/Marshal.Unix.cs2
-rw-r--r--src/Common/src/System/Runtime/InteropServices/Marshal.Win32.cs15
-rw-r--r--src/Common/src/System/Runtime/InteropServices/NativeBuffer.cs4
-rw-r--r--src/Common/src/System/SR.cs2
-rw-r--r--src/Common/src/System/Security/IdentityHelper.cs141
-rw-r--r--src/Common/src/System/StringNormalizationExtensions.Windows.cs133
-rw-r--r--src/Common/src/System/StringNormalizationExtensions.cs27
-rw-r--r--src/Common/src/System/SystemException.cs30
-rw-r--r--src/Common/src/System/Text/DBCSDecoder.cs294
-rw-r--r--src/Common/src/System/Text/EncodingHelper.Windows.cs (renamed from src/Common/src/System/Text/EncodingHelper.cs)16
-rw-r--r--src/Common/src/System/Text/NormalizationForm.cs20
-rw-r--r--src/Common/src/System/Text/OSEncoder.cs253
-rw-r--r--src/Common/src/System/Text/OSEncoding.Windows.cs259
-rw-r--r--src/Common/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs2
-rw-r--r--src/Common/src/System/Xml/XmlCharType.cs4
-rw-r--r--src/Common/tests/Common.Tests.csproj31
-rw-r--r--src/Common/tests/System/Collections/ICollection.Generic.Tests.cs107
-rw-r--r--src/Common/tests/System/Collections/IEnumerable.Generic.Tests.cs150
-rw-r--r--src/Common/tests/System/Collections/IList.Generic.Tests.cs164
-rw-r--r--src/Common/tests/System/Collections/IList.NonGeneric.Tests.cs54
-rw-r--r--src/Common/tests/System/Net/Configuration.Http.cs26
-rw-r--r--src/Common/tests/System/Net/Configuration.Security.cs2
-rw-r--r--src/Common/tests/System/Net/Configuration.WebSockets.cs12
-rw-r--r--src/Common/tests/System/Net/Configuration.cs2
-rw-r--r--src/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/AssemblyInfo.cs8
-rw-r--r--src/Common/tests/System/Net/VirtualNetwork/VirtualNetworkStream.cs28
-rw-r--r--src/Common/tests/System/PlatformDetection.cs6
-rw-r--r--src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs110
-rw-r--r--src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs2
-rw-r--r--src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs4
-rw-r--r--src/Common/tests/System/Xml/BaseLibManaged/Globalization.cs4
-rw-r--r--src/Common/tests/System/Xml/ModuleCore/ccommon.cs12
-rw-r--r--src/Common/tests/System/Xml/ModuleCore/cerror.cs70
-rw-r--r--src/Common/tests/System/Xml/ModuleCore/cmodinfo.cs18
-rw-r--r--src/Common/tests/System/Xml/ModuleCore/cparser.cs4
-rw-r--r--src/Common/tests/System/Xml/XmlCoreTest/MiscUtil.cs2
-rw-r--r--src/Common/tests/Tests/System/Collections/Generic/LargeArrayBuilderTests.cs37
-rw-r--r--src/Common/tests/Tests/System/Security/IdentityHelperTests.cs71
-rw-r--r--src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Binding/Better.cs2
-rw-r--r--src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/BindingContextBase.cs2
-rw-r--r--src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs6
-rw-r--r--src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs2
-rw-r--r--src/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs4
-rw-r--r--src/Native/Unix/CMakeLists.txt9
-rw-r--r--src/Native/Unix/Common/pal_config.h.in3
-rw-r--r--src/Native/Unix/System.Native/pal_io.cpp6
-rw-r--r--src/Native/Unix/System.Native/pal_networking.cpp56
-rw-r--r--src/Native/Unix/System.Native/pal_networking.h2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt88
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp20
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp56
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h623
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_bignum.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_bio.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_types.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp1
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.cpp15
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.h4
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_ecdsa.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.cpp1
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_err.cpp2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_err.h1
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_evp.h2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.h2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_dsa.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_eckey.h4
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp1
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h1
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.cpp2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.cpp2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.h5
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_x509.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h3
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.h2
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_x509ext.h3
-rw-r--r--src/Native/Unix/configure.cmake12
-rwxr-xr-xsrc/Native/Unix/gen-buildsys-clang.sh2
-rwxr-xr-xsrc/Native/Unix/verify-so.sh8
-rw-r--r--src/Native/Windows/FailedLoads/_tools_BinscopeFilter_packages_Newtonsoft.Json.9.0.1_lib_net45_Newtonsoft.Json.txtbin0 -> 26 bytes
-rw-r--r--src/Native/Windows/gen-buildsys-win.bat2
-rwxr-xr-xsrc/Native/build-native.sh30
-rw-r--r--src/Native/pkg/runtime.native.System.IO.Compression/linux/runtime.native.System.IO.Compression.pkgproj15
-rw-r--r--src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.builds18
-rw-r--r--src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.pkgproj11
-rw-r--r--src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/14.04/runtime.native.System.IO.Compression.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.04/runtime.native.System.IO.Compression.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.10/runtime.native.System.IO.Compression.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Http/linux/runtime.native.System.Net.Http.pkgproj15
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.builds18
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.pkgproj11
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Http/ubuntu/14.04/runtime.native.System.Net.Http.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.04/runtime.native.System.Net.Http.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.10/runtime.native.System.Net.Http.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Security/linux/runtime.native.System.Net.Security.pkgproj15
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.builds16
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.pkgproj11
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Security/ubuntu/14.04/runtime.native.System.Net.Security.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.04/runtime.native.System.Net.Security.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.10/runtime.native.System.Net.Security.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.Apple/osx/runtime.native.System.Security.Cryptography.Apple.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/alpine/3.4.3/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/debian/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/23/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/24/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/linux/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj15
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/13.2/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/42.1/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/osx/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/rhel/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.builds18
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj9
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/14.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj7
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj7
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.10/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj7
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/alpine/3.4.3/runtime.native.System.Security.Cryptography.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/debian/runtime.native.System.Security.Cryptography.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/23/runtime.native.System.Security.Cryptography.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/24/runtime.native.System.Security.Cryptography.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/linux/runtime.native.System.Security.Cryptography.pkgproj15
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/13.2/runtime.native.System.Security.Cryptography.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/42.1/runtime.native.System.Security.Cryptography.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/osx/runtime.native.System.Security.Cryptography.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/rhel/runtime.native.System.Security.Cryptography.pkgproj5
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.builds18
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.pkgproj11
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/14.04/runtime.native.System.Security.Cryptography.pkgproj11
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.04/runtime.native.System.Security.Cryptography.pkgproj7
-rw-r--r--src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.10/runtime.native.System.Security.Cryptography.pkgproj7
-rw-r--r--src/Native/pkg/runtime.native.System/linux/runtime.native.System.pkgproj18
-rw-r--r--src/Native/pkg/runtime.native.System/runtime.native.System.builds16
-rw-r--r--src/Native/pkg/runtime.native.System/runtime.native.System.pkgproj11
-rw-r--r--src/Native/pkg/runtime.native.System/ubuntu/14.04/runtime.native.System.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System/ubuntu/16.04/runtime.native.System.pkgproj2
-rw-r--r--src/Native/pkg/runtime.native.System/ubuntu/16.10/runtime.native.System.pkgproj2
-rw-r--r--src/System.Buffers/src/System/Buffers/ArrayPoolEventSource.cs2
-rw-r--r--src/System.CodeDom/pkg/System.CodeDom.pkgproj2
-rw-r--r--src/System.CodeDom/src/Configurations.props2
-rw-r--r--src/System.CodeDom/src/System.CodeDom.csproj8
-rw-r--r--src/System.CodeDom/src/System/CodeDom/Compiler/CodeDomProvider.cs6
-rw-r--r--src/System.CodeDom/tests/CodeCollections/CodeNamespaceImportCollectionTests.cs1
-rw-r--r--src/System.Collections.Concurrent/pkg/System.Collections.Concurrent.pkgproj4
-rw-r--r--src/System.Collections.Concurrent/ref/Configurations.props9
-rw-r--r--src/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs6
-rw-r--r--src/System.Collections.Concurrent/ref/System.Collections.Concurrent.csproj3
-rw-r--r--src/System.Collections.Concurrent/src/Resources/Strings.resx7
-rw-r--r--src/System.Collections.Concurrent/src/System.Collections.Concurrent.csproj1
-rw-r--r--src/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs2
-rw-r--r--src/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs5
-rw-r--r--src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentBag.cs1208
-rw-r--r--src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs96
-rw-r--r--src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentQueue.cs1389
-rw-r--r--src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentStack.cs8
-rw-r--r--src/System.Collections.Concurrent/tests/ConcurrentBagTests.cs522
-rw-r--r--src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionary.Generic.Tests.cs (renamed from src/System.Collections.Concurrent/tests/ConcurrentDicionary/ConcurrentDictionary.Generic.Tests.cs)2
-rw-r--r--src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionary.NonGeneric.Tests.cs (renamed from src/System.Collections.Concurrent/tests/ConcurrentDicionary/ConcurrentDictionary.NonGeneric.Tests.cs)0
-rw-r--r--src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionaryExtensions.cs59
-rw-r--r--src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionaryTests.cs (renamed from src/System.Collections.Concurrent/tests/ConcurrentDicionary/ConcurrentDictionaryTests.cs)49
-rw-r--r--src/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs337
-rw-r--r--src/System.Collections.Concurrent/tests/ConcurrentStackTests.cs506
-rw-r--r--src/System.Collections.Concurrent/tests/ProducerConsumerCollectionTests.cs1073
-rw-r--r--src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.builds3
-rw-r--r--src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.csproj14
-rw-r--r--src/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj2
-rw-r--r--src/System.Collections/System.Collections.sln20
-rw-r--r--src/System.Collections/ref/System.Collections.cs8
-rw-r--r--src/System.Collections/src/System/Collections/BitArray.cs121
-rw-r--r--src/System.Collections/src/System/Collections/Generic/BitHelper.cs2
-rw-r--r--src/System.Collections/src/System/Collections/Generic/Dictionary.cs17
-rw-r--r--src/System.Collections/src/System/Collections/Generic/LinkedList.cs2
-rw-r--r--src/System.Collections/tests/BitArray/BitArray_CtorTests.cs10
-rw-r--r--src/System.Collections/tests/BitArray/BitArray_GetSetTests.cs37
-rw-r--r--src/System.Collections/tests/BitArray/BitArray_OperatorsTests.cs3
-rw-r--r--src/System.Collections/tests/BitArray/BitArray_OperatorsTests.netcoreapp1.1.cs130
-rw-r--r--src/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs2
-rw-r--r--src/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.netcoreapp1.1.cs37
-rw-r--r--src/System.Collections/tests/System.Collections.Tests.csproj4
-rw-r--r--src/System.ComponentModel.Primitives/src/FxCopBaseline.cs3
-rw-r--r--src/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj3
-rw-r--r--src/System.ComponentModel.Primitives/src/System/ComponentModel/Component.cs1
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AddingNewEventArgs.cs21
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs38
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeCollection.cs52
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeProviderAttribute.cs27
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BaseNumberConverter.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindableAttribute.cs32
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindingList.cs159
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BooleanConverter.cs6
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ByteConverter.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionChangeEventArgs.cs23
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComplexBindingPropertiesAttribute.cs32
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs3
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs49
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CultureInfoConverter.cs54
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs42
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectAttribute.cs14
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectFieldAttribute.cs45
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectMethodAttribute.cs25
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DecimalConverter.cs16
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultBindingPropertyAttribute.cs15
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultEventAttribute.cs17
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultPropertyAttribute.cs17
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ActiveDocumentEvent.cs30
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CheckoutException.cs2
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CommandID.cs29
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangedEvent.cs45
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangingEvent.cs23
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentEvent.cs12
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentRenameEvent.cs34
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs144
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransaction.cs41
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransactionCloseEvent.cs23
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContext.cs15
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentCollection.cs40
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentEventArgs.cs12
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/HelpKeywordAttribute.cs14
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/InheritanceAttribute.cs16
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/MenuCommand.cs53
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/PropertyTabAttribute.cs39
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DefaultSerializationProviderAttribute.cs14
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerLoader.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerSerializerAttribute.cs32
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/InstanceDescriptor.cs64
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs35
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/ResolveNameEventArgs.cs27
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/RootDesignerSerializerAttribute.cs47
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ServiceObjectContainer.cs32
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ToolboxItemAttribute.cs2
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignTimeVisibleAttribute.cs16
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignerAttribute.cs50
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DoubleConverter.cs16
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EditorAttribute.cs42
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs77
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EventDescriptorCollection.cs123
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtendedPropertyDescriptor.cs36
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtenderProvidedPropertyAttribute.cs38
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/HandledEventArgs.cs1
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstallerTypeAttribute.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstanceCreationEditor.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int16Converter.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int32Converter.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int64Converter.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs14
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseContext.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseException.cs17
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseManager.cs39
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseProviderAttribute.cs4
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListBindableAttribute.cs17
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListChangedEventArgs.cs51
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescription.cs30
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescriptionCollection.cs41
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LookupBindingPropertiesAttribute.cs61
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MarshalByValueComponent.cs36
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs323
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MemberDescriptor.cs86
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NestedContainer.cs52
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs92
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PasswordPropertyTextAttribute.cs14
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs24
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptorCollection.cs182
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ProvidePropertyAttribute.cs39
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RecommendedAsConfigurableAttribute.cs16
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReferenceConverter.cs25
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectEventDescriptor.cs36
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs83
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs28
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs56
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RefreshEventArgs.cs25
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RunInstallerAttribute.cs15
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SByteConverter.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SettingsBindableAttribute.cs16
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SingleConverter.cs16
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ToolboxItemFilterAttribute.cs40
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs69
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverterAttribute.cs20
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs21
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProviderAttribute.cs14
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs313
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt16Converter.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt32Converter.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt64Converter.cs8
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WarningException.cs31
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WeakHashtable.cs12
-rw-r--r--src/System.ComponentModel.TypeConverter/src/System/Timers/Timer.cs9
-rw-r--r--src/System.ComponentModel.TypeConverter/tests/SampleClasses.cs2
-rw-r--r--src/System.Composition.Convention/src/System/Composition/Convention/PartConventionBuilder.cs4
-rw-r--r--src/System.Composition.Hosting/src/Microsoft/Internal/ThrowHelper.cs6
-rw-r--r--src/System.Configuration/System.Configuration.sln54
-rw-r--r--src/System.Configuration/dir.props7
-rw-r--r--src/System.Configuration/pkg/System.Configuration.builds9
-rw-r--r--src/System.Configuration/pkg/System.Configuration.pkgproj12
-rw-r--r--src/System.Configuration/ref/System.Configuration.cs1109
-rw-r--r--src/System.Configuration/ref/System.Configuration.csproj17
-rw-r--r--src/System.Configuration/src/Resources/Strings.resx718
-rw-r--r--src/System.Configuration/src/System.Configuration.builds8
-rw-r--r--src/System.Configuration/src/System.Configuration.csproj195
-rw-r--r--src/System.Configuration/src/System/Configuration/AppSettingsSection.cs144
-rw-r--r--src/System.Configuration/src/System/Configuration/BaseConfigurationRecord.cs3817
-rw-r--r--src/System.Configuration/src/System/Configuration/CallbackValidator.cs36
-rw-r--r--src/System.Configuration/src/System/Configuration/CallbackValidatorAttribute.cs66
-rw-r--r--src/System.Configuration/src/System/Configuration/ClientConfigPaths.cs354
-rw-r--r--src/System.Configuration/src/System/Configuration/ClientConfigurationHost.cs492
-rw-r--r--src/System.Configuration/src/System/Configuration/ClientConfigurationSystem.cs225
-rw-r--r--src/System.Configuration/src/System/Configuration/CommaDelimitedStringAttributeCollectionConverter.cs26
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigDefinitionUpdates.cs60
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigPathUtility.cs101
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigXmlAttribute.cs39
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigXmlCDataSection.cs38
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigXmlComment.cs38
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigXmlElement.cs39
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigXmlReader.cs56
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigXmlSignificantWhitespace.cs38
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigXmlText.cs38
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigXmlWhitespace.cs38
-rw-r--r--src/System.Configuration/src/System/Configuration/Configuration.cs233
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationAllowDefinition.cs14
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationAllowExeDefinition.cs14
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationCollectionAttribute.cs58
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationConverterBase.cs27
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationElement.cs2025
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationElementCollection.cs1298
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationElementCollectionType.cs58
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationElementProperty.cs22
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationErrorsException.cs264
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationException.cs106
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationFileMap.cs61
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationLocation.cs24
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationLocationCollection.cs18
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationLockCollection.cs335
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationLockCollectionType.cs14
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationManager.cs268
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationPermission.cs151
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationProperty.cs379
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationPropertyAttribute.cs57
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationPropertyCollection.cs83
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationPropertyOptions.cs18
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationSaveMode.cs22
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationSchemaErrors.cs99
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationSection.cs98
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationSectionCollection.cs144
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationSectionGroup.cs171
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationSectionGroupCollection.cs144
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationUserLevel.cs14
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationValidatorAttribute.cs60
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationValidatorBase.cs16
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationValue.cs21
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationValueFlags.cs16
-rw-r--r--src/System.Configuration/src/System/Configuration/ConfigurationValues.cs215
-rw-r--r--src/System.Configuration/src/System/Configuration/ConnectionStringSettings.cs76
-rw-r--r--src/System.Configuration/src/System/Configuration/ConnectionStringSettingsCollection.cs86
-rw-r--r--src/System.Configuration/src/System/Configuration/ConnectionStringsSection.cs33
-rw-r--r--src/System.Configuration/src/System/Configuration/ContextInformation.cs56
-rw-r--r--src/System.Configuration/src/System/Configuration/DateTimeConfigurationCollection.cs57
-rw-r--r--src/System.Configuration/src/System/Configuration/DateTimeConfigurationElement.cs55
-rw-r--r--src/System.Configuration/src/System/Configuration/DeclarationUpdate.cs11
-rw-r--r--src/System.Configuration/src/System/Configuration/DefaultSection.cs64
-rw-r--r--src/System.Configuration/src/System/Configuration/DefaultValidator.cs21
-rw-r--r--src/System.Configuration/src/System/Configuration/DefinitionUpdate.cs17
-rw-r--r--src/System.Configuration/src/System/Configuration/ElementInformation.cs84
-rw-r--r--src/System.Configuration/src/System/Configuration/EmptyImpersonationContext.cs19
-rw-r--r--src/System.Configuration/src/System/Configuration/ErrorInfoXmlDocument.cs122
-rw-r--r--src/System.Configuration/src/System/Configuration/ErrorsHelper.cs64
-rw-r--r--src/System.Configuration/src/System/Configuration/ExceptionAction.cs24
-rw-r--r--src/System.Configuration/src/System/Configuration/ExceptionUtil.cs89
-rw-r--r--src/System.Configuration/src/System/Configuration/ExeConfigurationFileMap.cs45
-rw-r--r--src/System.Configuration/src/System/Configuration/ExeContext.cs25
-rw-r--r--src/System.Configuration/src/System/Configuration/FactoryId.cs26
-rw-r--r--src/System.Configuration/src/System/Configuration/FactoryRecord.cs275
-rw-r--r--src/System.Configuration/src/System/Configuration/GenericEnumConverter.cs69
-rw-r--r--src/System.Configuration/src/System/Configuration/HResults.cs11
-rw-r--r--src/System.Configuration/src/System/Configuration/IConfigurationSectionHandler.cs38
-rw-r--r--src/System.Configuration/src/System/Configuration/IgnoreSection.cs64
-rw-r--r--src/System.Configuration/src/System/Configuration/IgnoreSectionHandler.cs20
-rw-r--r--src/System.Configuration/src/System/Configuration/ImplicitMachineConfigHost.cs72
-rw-r--r--src/System.Configuration/src/System/Configuration/InfiniteIntConverter.cs27
-rw-r--r--src/System.Configuration/src/System/Configuration/InfiniteTimeSpanConverter.cs33
-rw-r--r--src/System.Configuration/src/System/Configuration/IntegerValidator.cs58
-rw-r--r--src/System.Configuration/src/System/Configuration/IntegerValidatorAttribute.cs41
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/ConfigSystem.cs30
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/ConfigurationManagerInternal.cs36
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/DelegatingConfigHost.cs228
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/FileVersion.cs38
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IConfigErrorInfo.cs12
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IConfigSystem.cs13
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IConfigurationManagerHelper.cs16
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IConfigurationManagerInternal.cs26
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IInternalConfigClientHost.cs18
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IInternalConfigConfigurationFactory.cs14
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IInternalConfigHost.cs100
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IInternalConfigHostPaths.cs17
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IInternalConfigRecord.cs27
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IInternalConfigRoot.cs30
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IInternalConfigSettingsFactory.cs (renamed from src/Common/src/Interop/Windows/kernel32/Interop.SetLastError.cs)11
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/IInternalConfigSystem.cs19
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/InternalConfigConfigurationFactory.cs22
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/InternalConfigEventArgs.cs16
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/InternalConfigEventHandler.cs8
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/InternalConfigHost.cs301
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/InternalConfigRoot.cs311
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/InternalConfigSettingsFactory.cs21
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/StreamChangeCallback.cs (renamed from src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/CompressionMode.cs)11
-rw-r--r--src/System.Configuration/src/System/Configuration/Internal/WriteFileContext.cs221
-rw-r--r--src/System.Configuration/src/System/Configuration/InvalidPropValue.cs20
-rw-r--r--src/System.Configuration/src/System/Configuration/KeyValueConfigurationCollection.cs77
-rw-r--r--src/System.Configuration/src/System/Configuration/KeyValueConfigurationElement.cs64
-rw-r--r--src/System.Configuration/src/System/Configuration/KeyValueInternalCollection.cs37
-rw-r--r--src/System.Configuration/src/System/Configuration/LocationSectionRecord.cs37
-rw-r--r--src/System.Configuration/src/System/Configuration/LocationUpdates.cs30
-rw-r--r--src/System.Configuration/src/System/Configuration/LongValidator.cs58
-rw-r--r--src/System.Configuration/src/System/Configuration/LongValidatorAttribute.cs39
-rw-r--r--src/System.Configuration/src/System/Configuration/MgmtConfigurationRecord.cs3186
-rw-r--r--src/System.Configuration/src/System/Configuration/NameValueConfigurationCollection.cs69
-rw-r--r--src/System.Configuration/src/System/Configuration/NameValueConfigurationElement.cs43
-rw-r--r--src/System.Configuration/src/System/Configuration/NamespaceChange.cs (renamed from src/System.Net.HttpListener/src/System/Net/NTAuthentication.cs)12
-rw-r--r--src/System.Configuration/src/System/Configuration/OverrideMode.cs23
-rw-r--r--src/System.Configuration/src/System/Configuration/OverrideModeSetting.cs353
-rw-r--r--src/System.Configuration/src/System/Configuration/PositiveTimeSpanValidator.cs22
-rw-r--r--src/System.Configuration/src/System/Configuration/PositiveTimeSpanValidatorAttribute.cs12
-rw-r--r--src/System.Configuration/src/System/Configuration/PrivilegedConfigurationManager.cs16
-rw-r--r--src/System.Configuration/src/System/Configuration/PropertyInformation.cs95
-rw-r--r--src/System.Configuration/src/System/Configuration/PropertyInformationCollection.cs65
-rw-r--r--src/System.Configuration/src/System/Configuration/PropertySourceInfo.cs36
-rw-r--r--src/System.Configuration/src/System/Configuration/PropertyValueOrigin.cs13
-rw-r--r--src/System.Configuration/src/System/Configuration/ProtectedConfiguration.cs37
-rw-r--r--src/System.Configuration/src/System/Configuration/ProtectedConfigurationProvider.cs15
-rw-r--r--src/System.Configuration/src/System/Configuration/ProtectedConfigurationProviderCollection.cs28
-rw-r--r--src/System.Configuration/src/System/Configuration/ProtectedConfigurationSection.cs117
-rw-r--r--src/System.Configuration/src/System/Configuration/ProtectedProviderSettings.cs28
-rw-r--r--src/System.Configuration/src/System/Configuration/Provider/ProviderBase.cs42
-rw-r--r--src/System.Configuration/src/System/Configuration/Provider/ProviderCollection.cs77
-rw-r--r--src/System.Configuration/src/System/Configuration/Provider/ProviderException.cs26
-rw-r--r--src/System.Configuration/src/System/Configuration/ProviderSettings.cs190
-rw-r--r--src/System.Configuration/src/System/Configuration/ProviderSettingsCollection.cs67
-rw-r--r--src/System.Configuration/src/System/Configuration/RegexStringValidator.cs38
-rw-r--r--src/System.Configuration/src/System/Configuration/RegexStringValidatorAttribute.cs19
-rw-r--r--src/System.Configuration/src/System/Configuration/RuntimeConfigurationRecord.cs191
-rw-r--r--src/System.Configuration/src/System/Configuration/SafeBitVector32.cs45
-rw-r--r--src/System.Configuration/src/System/Configuration/SectionInformation.cs684
-rw-r--r--src/System.Configuration/src/System/Configuration/SectionInput.cs69
-rw-r--r--src/System.Configuration/src/System/Configuration/SectionRecord.cs298
-rw-r--r--src/System.Configuration/src/System/Configuration/SectionUpdates.cs248
-rw-r--r--src/System.Configuration/src/System/Configuration/SectionXmlInfo.cs66
-rw-r--r--src/System.Configuration/src/System/Configuration/SimpleBitVector32.cs32
-rw-r--r--src/System.Configuration/src/System/Configuration/StreamInfo.cs46
-rw-r--r--src/System.Configuration/src/System/Configuration/StreamUpdate.cs21
-rw-r--r--src/System.Configuration/src/System/Configuration/StringAttributeCollection.cs147
-rw-r--r--src/System.Configuration/src/System/Configuration/StringUtil.cs38
-rw-r--r--src/System.Configuration/src/System/Configuration/StringValidator.cs57
-rw-r--r--src/System.Configuration/src/System/Configuration/StringValidatorAttribute.cs42
-rw-r--r--src/System.Configuration/src/System/Configuration/SubclassTypeValidator.cs39
-rw-r--r--src/System.Configuration/src/System/Configuration/SubclassTypeValidatorAttribute.cs19
-rw-r--r--src/System.Configuration/src/System/Configuration/TimeSpanMinutesConverter.cs29
-rw-r--r--src/System.Configuration/src/System/Configuration/TimeSpanMinutesOrInfiniteConverter.cs27
-rw-r--r--src/System.Configuration/src/System/Configuration/TimeSpanSecondsConverter.cs37
-rw-r--r--src/System.Configuration/src/System/Configuration/TimeSpanSecondsOrInfiniteConverter.cs27
-rw-r--r--src/System.Configuration/src/System/Configuration/TimeSpanValidator.cs58
-rw-r--r--src/System.Configuration/src/System/Configuration/TimeSpanValidatorAttribute.cs52
-rw-r--r--src/System.Configuration/src/System/Configuration/TypeNameConverter.cs33
-rw-r--r--src/System.Configuration/src/System/Configuration/TypeUtil.cs188
-rw-r--r--src/System.Configuration/src/System/Configuration/Update.cs26
-rw-r--r--src/System.Configuration/src/System/Configuration/UpdateConfigHost.cs134
-rw-r--r--src/System.Configuration/src/System/Configuration/UrlPath.cs139
-rw-r--r--src/System.Configuration/src/System/Configuration/ValidatorCallback.cs9
-rw-r--r--src/System.Configuration/src/System/Configuration/ValidatorUtils.cs89
-rw-r--r--src/System.Configuration/src/System/Configuration/WhiteSpaceTrimStringConverter.cs26
-rw-r--r--src/System.Configuration/src/System/Configuration/XmlUtil.cs1110
-rw-r--r--src/System.Configuration/src/System/Configuration/XmlUtilWriter.cs388
-rw-r--r--src/System.Configuration/tests/Resources/Strings.Designer.cs226
-rw-r--r--src/System.Configuration/tests/Resources/Strings.resx179
-rw-r--r--src/System.Configuration/tests/System.Configuration.Tests.builds8
-rw-r--r--src/System.Configuration/tests/System.Configuration.Tests.csproj65
-rw-r--r--src/System.Configuration/tests/System/Configuration/AppSettingsTests.cs87
-rw-r--r--src/System.Configuration/tests/System/Configuration/ConfigPathUtilityTests.cs66
-rw-r--r--src/System.Configuration/tests/System/Configuration/ExceptionUtilTests.cs130
-rw-r--r--src/System.Configuration/tests/System/Configuration/ImplicitMachineConfigTests.cs65
-rw-r--r--src/System.Configuration/tests/System/Configuration/SmokeTest.cs23
-rw-r--r--src/System.Configuration/tests/System/Configuration/StringUtilTests.cs96
-rw-r--r--src/System.Configuration/tests/System/Configuration/TempConfig.cs30
-rw-r--r--src/System.Configuration/tests/System/Configuration/TestData.cs23
-rw-r--r--src/System.Configuration/tests/System/Configuration/TypeUtilTests.cs288
-rw-r--r--src/System.Configuration/tests/System/Configuration/ValidatiorUtilsTests.cs83
-rw-r--r--src/System.Console/src/FxCopBaseline.cs49
-rw-r--r--src/System.Console/src/Resources/Strings.resx27
-rw-r--r--src/System.Console/src/System.Console.csproj30
-rw-r--r--src/System.Console/src/System/ConsolePal.Unix.cs2
-rw-r--r--src/System.Console/src/System/ConsolePal.Windows.cs4
-rw-r--r--src/System.Console/tests/ConsoleEncoding.cs79
-rw-r--r--src/System.Console/tests/ManualTests/ManualTests.cs8
-rw-r--r--src/System.Console/tests/System.Console.Tests.csproj4
-rw-r--r--src/System.Console/tests/WindowAndCursorProps.cs2
-rw-r--r--src/System.Data.Common/src/System/Data/Common/DBSchemaTable.cs2
-rw-r--r--src/System.Data.Common/src/System/Data/Common/DataStorage.cs4
-rw-r--r--src/System.Data.Common/src/System/Data/DataColumn.cs2
-rw-r--r--src/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs6
-rw-r--r--src/System.Data.SqlClient/src/Interop/SNINativeMethodWrapper.Windows.cs4
-rw-r--r--src/System.Data.SqlClient/src/Microsoft/SqlServer/Server/MetadataUtilsSmi.cs16
-rw-r--r--src/System.Data.SqlClient/src/System/Data/Common/AdapterUtil.cs280
-rw-r--r--src/System.Data.SqlClient/src/System/Data/Common/DbConnectionOptions.cs12
-rw-r--r--src/System.Data.SqlClient/src/System/Data/DataException.cs6
-rw-r--r--src/System.Data.SqlClient/src/System/Data/OperationAbortedException.cs2
-rw-r--r--src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs2
-rw-r--r--src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs4
-rw-r--r--src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.cs2
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCachedBuffer.cs2
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs8
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnection.cs8
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnectionString.cs2
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs2
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/SqlEnums.cs4
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/SqlException.cs6
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/SqlStatistics.cs4
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/SqlUtil.cs276
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs6
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserHelperClasses.cs2
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserSafeHandles.cs4
-rw-r--r--src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStaticMethods.cs18
-rw-r--r--src/System.Data.SqlClient/tests/FunctionalTests/SqlConnectionTest.cs6
-rw-r--r--src/System.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs4
-rw-r--r--src/System.Data.SqlClient/tests/StressTests/System.Data.StressRunner/Program.cs8
-rw-r--r--src/System.Data.SqlClient/tests/Tools/TDS/TDS.EndPoint/SSPI/SecurityWrapper.cs20
-rw-r--r--src/System.Diagnostics.Debug/tests/DebugTests.cs2
-rw-r--r--src/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md16
-rw-r--r--src/System.Diagnostics.Process/src/FxCopBaseline.cs5
-rw-r--r--src/System.Diagnostics.Process/src/Resources/Strings.resx30
-rw-r--r--src/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj28
-rw-r--r--src/System.Diagnostics.Process/tests/ProcessStandardConsoleTests.cs10
-rw-r--r--src/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs1
-rw-r--r--src/System.Diagnostics.Process/tests/ProcessStartInfoTests.netstandard1.7.cs7
-rw-r--r--src/System.Diagnostics.Process/tests/ProcessTests.cs9
-rw-r--r--src/System.Diagnostics.StackTrace/src/System/Diagnostics/StackTraceSymbols.CoreCLR.cs4
-rw-r--r--src/System.Diagnostics.TextWriterTraceListener/src/FxCopBaseline.cs3
-rw-r--r--src/System.Diagnostics.TextWriterTraceListener/src/System.Diagnostics.TextWriterTraceListener.csproj3
-rw-r--r--src/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs6
-rw-r--r--src/System.Diagnostics.TraceSource/src/FxCopBaseline.cs21
-rw-r--r--src/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj3
-rw-r--r--src/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceInternal.cs2
-rw-r--r--src/System.Diagnostics.Tracing/pkg/System.Diagnostics.Tracing.pkgproj8
-rw-r--r--src/System.Diagnostics.Tracing/src/ApiCompatBaseline.net461.txt3
-rw-r--r--src/System.Diagnostics.Tracing/src/Configurations.props2
-rw-r--r--src/System.Diagnostics.Tracing/src/FxCopBaseline.cs5
-rw-r--r--src/System.Diagnostics.Tracing/src/System.Diagnostics.Tracing.csproj9
-rw-r--r--src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventProvider.cs4
-rw-r--r--src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventSource.cs20
-rw-r--r--src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs2
-rw-r--r--src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs2
-rw-r--r--src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs2
-rw-r--r--src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/EventSourceTestParser.cs72
-rw-r--r--src/System.Diagnostics.Tracing/tests/CustomEventSources/EventSourceTest.cs2
-rw-r--r--src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/EventSourceForReflection.cs2
-rw-r--r--src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/Properties/AssemblyInfo.cs8
-rw-r--r--src/System.DirectoryServices.AccountManagement/System.DirectoryServices.AccountManagement.sln107
-rw-r--r--src/System.DirectoryServices.AccountManagement/dir.props7
-rw-r--r--src/System.DirectoryServices.AccountManagement/pkg/System.DirectoryServices.AccountManagement.builds10
-rw-r--r--src/System.DirectoryServices.AccountManagement/pkg/System.DirectoryServices.AccountManagement.pkgproj17
-rw-r--r--src/System.DirectoryServices.AccountManagement/ref/System.DirectoryServices.AccountManagement.cs8
-rw-r--r--src/System.DirectoryServices.AccountManagement/ref/System.DirectoryServices.AccountManagement.csproj15
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/Resources/System.DirectoryServices.AccountManagement.StringResources.txt127
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.builds13
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj100
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADAMStoreCtx.cs496
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADDNConstraintLinkedAttrSet.cs151
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADDNLinkedAttrSet.cs1425
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADEntriesSet.cs125
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx.cs2619
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs1728
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_Query.cs1190
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreKey.cs87
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADUtils.cs550
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/DSPropertyCollection.cs89
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/QBEMatchType.cs44
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/RangeRetriever.cs257
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSCache.cs228
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSUtils.cs957
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SidList.cs339
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/TokenGroupsSet.cs168
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AccountInfo.cs620
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AdvancedFilters.cs256
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AuthZSet.cs848
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AuthenticablePrincipal.cs646
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/CertificateCollectionDeltas.cs48
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Computer.cs191
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ConfigurationHandler.cs133
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs1310
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ContextOptions.cs20
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ContextType.cs21
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/CredentialTypes.cs15
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/EmptySet.cs51
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionAttributes.cs95
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionCache.cs70
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionHelper.cs144
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExternDll.cs83
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/FindResult.cs100
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/FindResultEnumerator.cs228
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalConfig.cs48
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalDebug.cs101
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalSuppressions.cs117
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Group.cs419
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GroupType.cs24
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityClaim.cs32
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityReference.cs32
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityType.cs41
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/MatchType.cs18
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/NetCred.cs113
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Pair.cs43
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PasswordInfo.cs458
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Principal.cs1546
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalCollection.cs904
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalCollectionEnumerator.cs366
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalSearcher.cs419
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/QbeFilterDescription.cs361
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/RejectedClaimChange.cs17
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Resources.cs196
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ResultSet.cs43
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMGroupsSet.cs112
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMMembersSet.cs631
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMQuerySet.cs926
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx.cs1116
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx_LoadStore.cs1190
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx_Query.cs157
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreKey.cs54
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMUtils.cs251
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SidType.cs17
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/StoreCtx.cs476
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/StoreKey.cs13
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/TrackedCollection.cs319
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/TrackedCollectionEnumerator.cs192
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/UnknownPrincipal.cs61
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/UrnScheme.cs19
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/User.cs474
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Utils.cs1000
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueCollection.cs528
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueCollectionEnumerator.cs97
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueList.cs409
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueListEnumerator.cs79
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/config.cs37
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/constants.cs159
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/exceptions.cs357
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/interopt.cs872
-rw-r--r--src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/testobj.cs426
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/AuthoringTests.txt135
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs76
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs69
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs110
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs200
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/Properties/AssemblyInfo.cs31
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj43
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.builds12
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs106
-rw-r--r--src/System.DirectoryServices.AccountManagement/tests/testobj.cs449
-rw-r--r--src/System.DirectoryServices.Protocols/System.DirectoryServices.Protocols.sln82
-rw-r--r--src/System.DirectoryServices.Protocols/dir.props7
-rw-r--r--src/System.DirectoryServices.Protocols/pkg/System.DirectoryServices.Protocols.builds10
-rw-r--r--src/System.DirectoryServices.Protocols/pkg/System.DirectoryServices.Protocols.pkgproj17
-rw-r--r--src/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs8
-rw-r--r--src/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.csproj15
-rw-r--r--src/System.DirectoryServices.Protocols/src/Resources/System.DirectoryServices.Protocols.txt132
-rw-r--r--src/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.builds13
-rw-r--r--src/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj62
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ExternDll.cs83
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/AuthTypes.cs29
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs631
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DereferenceAlias.cs14
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryAttribute.cs708
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryAttributeOperation.cs13
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryConnection.cs85
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryControl.cs1507
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryException.cs96
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryIdentifier.cs16
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryOperation.cs16
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryRequest.cs1038
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryResponse.cs767
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/PartialResultsCollection.cs42
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/ReferralChasingOption.cs16
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/ResultCode.cs126
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/SearchResults.cs368
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/SearchScope.cs13
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlAsyncResult.cs108
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlConstants.cs79
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDirectoryIdentifier.cs40
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDocument.cs751
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDocumentProcessing.cs36
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlException.cs55
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlSoapConnection.cs45
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlSoapHttpConnection.cs823
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/adreqresp2.cs112
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/dsmlfilterwriter.cs237
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/filterparser.cs431
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/utils.cs136
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapAsyncResult.cs130
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs1897
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapDirectoryIdentifier.cs104
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapException.cs191
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapPartialResultsProcessor.cs354
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs1266
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs108
-rw-r--r--src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs419
-rw-r--r--src/System.DirectoryServices/System.DirectoryServices.sln82
-rw-r--r--src/System.DirectoryServices/dir.props7
-rw-r--r--src/System.DirectoryServices/pkg/System.DirectoryServices.builds10
-rw-r--r--src/System.DirectoryServices/pkg/System.DirectoryServices.pkgproj17
-rw-r--r--src/System.DirectoryServices/ref/System.DirectoryServices.cs7
-rw-r--r--src/System.DirectoryServices/ref/System.DirectoryServices.csproj15
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsAuthentication.cs20
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsOptions.cs19
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsPropertyOperation.cs24
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsSearchColumn.cs20
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsSearchPreferenceInfo.cs20
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsSearchPreferences.cs30
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsSortKey.cs18
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsStatus.cs14
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsType.cs40
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsValue2.cs47
-rw-r--r--src/System.DirectoryServices/src/Interop/AdsValueHelper2.cs287
-rw-r--r--src/System.DirectoryServices/src/Interop/NativeMethods.cs32
-rw-r--r--src/System.DirectoryServices/src/Interop/SafeNativeMethods.cs151
-rw-r--r--src/System.DirectoryServices/src/Interop/UnsafeNativeMethods.cs506
-rw-r--r--src/System.DirectoryServices/src/Resources/System.DirectoryServices.txt231
-rw-r--r--src/System.DirectoryServices/src/Resources/System/DirectoryServices/DirectoryEntry.bmpbin0 -> 824 bytes
-rw-r--r--src/System.DirectoryServices/src/Resources/System/DirectoryServices/DirectorySearcher.bmpbin0 -> 824 bytes
-rw-r--r--src/System.DirectoryServices/src/System.DirectoryServices.builds13
-rw-r--r--src/System.DirectoryServices/src/System.DirectoryServices.csproj152
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs957
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstanceCollection.cs73
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADSearcher.cs88
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryInterSiteTransport.cs370
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryPartition.cs96
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryReplicationMetaData.cs103
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchedule.cs261
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchema.cs587
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClass.cs1522
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClassCollection.cs374
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaProperty.cs1451
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaPropertyCollection.cs394
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySite.cs1502
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteCollection.cs247
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs733
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkBridge.cs389
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkCollection.cs241
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnet.cs411
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnetCollection.cs294
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySyntax.cs108
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ApplicationPartition.cs1281
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ApplicationPartitionCollection.cs73
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/AttributeMetaData.cs136
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/AttributeMetadataCollection.cs68
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ConfigSet.cs795
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryContext.cs875
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryEntryManager.cs389
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServer.cs955
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServerCollection.cs411
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Domain.cs1538
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainCollection.cs81
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainController.cs1449
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainControllerCollection.cs68
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Exception.cs558
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Forest.cs1259
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustCollision.cs99
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustDomainInfoCollection.cs50
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustDomainInformation.cs97
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustRelationshipInformation.cs476
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/GlobalCatalog.cs491
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/GlobalCatalogCollection.cs68
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Locator.cs307
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/LocatorFlag.cs63
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/NativeMethods.cs994
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/PropertyManager.cs185
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyActiveDirectorySchemaClassCollection.cs68
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyActiveDirectorySchemaPropertyCollection.cs67
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyDirectoryServerCollection.cs86
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteCollection.cs91
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteLinkBridgeCollection.cs80
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteLinkCollection.cs81
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyStringCollection.cs84
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnection.cs1001
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnectionCollection.cs79
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationCursor.cs105
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationCursorCollection.cs95
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationFailure.cs102
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationFailureCollection.cs81
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationNeighbor.cs200
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationNeighborCollection.cs75
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperation.cs127
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperationCollection.cs82
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperationInformation.cs46
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/RoleOwner.cs23
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/RoleOwnerCollection.cs140
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SafeHandle.cs61
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SecurityLevel.cs15
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SystemFlag.cs14
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TopLevelName.cs60
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TopLevelNameCollection.cs53
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustHelper.cs1053
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustRelationshipInformation.cs93
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustRelationshipInformationCollection.cs66
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/UnsafeNativeMethods.cs872
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs2453
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/WellKnownDN.cs23
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectorySecurity.cs1441
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/AdsVLV.cs21
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/AuthenticationTypes.cs93
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/BinaryCompatibility.cs45
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DerefAlias.cs27
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/Design/DirectoryEntryConverter.cs122
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryDescriptionAttribute.cs47
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntries.cs204
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs1409
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntryConfiguration.cs128
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs1240
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesCOMException.cs90
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermission.cs92
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionAccess.cs28
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionAttribute.cs59
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionEntry.cs57
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionEntryCollection.cs118
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectorySynchronization.cs145
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectorySynchronizationFlags.cs16
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryVirtualListView.cs250
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/DirectoryVirtualListViewContext.cs49
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ExtendedDn.cs24
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ExternDll.cs83
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/PasswordEncodingMethod.cs12
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/PrivilegedConfigurationManager.cs28
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs575
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/PropertyValueCollection.cs410
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ReferalChasingOption.cs37
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ResultPropertyCollection.cs89
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/ResultPropertyValueCollection.cs69
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/SchemaNameCollection.cs369
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/SearchResult.cs77
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/SearchResultCollection.cs562
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/SearchScope.cs30
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/SearchWaitHandler.cs70
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/SecurityMasks.cs31
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/SortDirection.cs23
-rw-r--r--src/System.DirectoryServices/src/System/DirectoryServices/SortOption.cs91
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.delegateEvent.delegate.cs72
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.indexer.regclass.cs4
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.genclass.cs2
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs4
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.compound.basic.cs2
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.genclass.cs4
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.regclass.cs6
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.genclass.cs2
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.regclass.cs2
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.formalParameter.Methods.cs6
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.returnType.methods.cs2
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.basic.cs2
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.conversions.cs4
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.formalParameter.cs8
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.overloadResolution.method.1class.2param.cs6
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.NamedAndOptional/Conformance.dynamic.namedandoptional.decl.opOverload.cs16
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Other/Conformance.dynamic.ClsCompliance.cs4
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Methods.2class2methods.cs4
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.1class2operators.conversion.cs2
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.PointerOperator.cs8
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.basic.cs48
-rw-r--r--src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/conformance.dynamic.unsafe.context.cs2
-rw-r--r--src/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetInstance.cs36
-rw-r--r--src/System.IO.Compression/src/Interop/Interop.zlib.Unix.cs2
-rw-r--r--src/System.IO.Compression/src/Interop/Interop.zlib.Windows.cs14
-rw-r--r--src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoder.cs6
-rw-r--r--src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoderStatus.cs4
-rw-r--r--src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs4
-rw-r--r--src/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs6
-rw-r--r--src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs19
-rw-r--r--src/System.IO.FileSystem/src/System/IO/FileStream.Win32.cs8
-rw-r--r--src/System.IO.FileSystem/src/System/IO/FileStreamCompletionSource.Win32.cs2
-rw-r--r--src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs79
-rw-r--r--src/System.IO.FileSystem/tests/FileStream/ctor_str_fm_fa_fs_buffer_fo.cs14
-rw-r--r--src/System.IO.IsolatedStorage/pkg/System.IO.IsolatedStorage.pkgproj2
-rw-r--r--src/System.IO.IsolatedStorage/src/Configurations.props2
-rw-r--r--src/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj13
-rw-r--r--src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32.Unix.cs6
-rw-r--r--src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.cs127
-rw-r--r--src/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj3
-rw-r--r--src/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/HelperTests.cs57
-rw-r--r--src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs2
-rw-r--r--src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Unix.cs2
-rw-r--r--src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs2
-rw-r--r--src/System.IO.Packaging/src/System/IO/Packaging/XmlCompatibilityReader.cs2
-rw-r--r--src/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs2
-rw-r--r--src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs4
-rw-r--r--src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs2
-rw-r--r--src/System.IO.Pipes/tests/Interop.cs4
-rw-r--r--src/System.IO/pkg/System.IO.pkgproj8
-rw-r--r--src/System.IO/src/Configurations.props2
-rw-r--r--src/System.IO/src/System.IO.csproj12
-rw-r--r--src/System.IO/tests/BufferedStream/BufferedStream.FlushTests.cs77
-rw-r--r--src/System.IO/tests/System.IO.Tests.csproj3
-rw-r--r--src/System.Linq.Expressions/pkg/System.Linq.Expressions.pkgproj6
-rw-r--r--src/System.Linq.Expressions/src/ApiCompatBaseline.net461.txt (renamed from src/System.Linq.Expressions/src/ApiCompatBaseline.net463.txt)0
-rw-r--r--src/System.Linq.Expressions/src/Configurations.props2
-rw-r--r--src/System.Linq.Expressions/src/Resources/Strings.resx5
-rw-r--r--src/System.Linq.Expressions/src/System.Linq.Expressions.csproj51
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/BinaryOperationBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/BindingRestrictions.cs2
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/CallInfo.cs36
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/ConvertBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/CreateInstanceBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/DeleteIndexBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/DeleteMemberBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObject.cs10
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs301
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs24
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/GetIndexBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/GetMemberBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/IDynamicMetaObjectProvider.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/InvokeBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/InvokeMemberBinder.cs7
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/SetIndexBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/SetMemberBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/UnaryOperationBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/Utils/CachedReflectionInfo.cs61
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/Utils/CollectionExtensions.cs110
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/Utils/EmptyReadOnlyCollection.cs (renamed from src/Common/src/System/Dynamic/Utils/EmptyReadOnlyCollection.cs)4
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/Utils/ExpressionVisitorUtils.cs27
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/Utils/ListArgumentProvider.cs (renamed from src/Common/src/System/Dynamic/Utils/ListArgumentProvider.cs)0
-rw-r--r--src/System.Linq.Expressions/src/System/Dynamic/Utils/TypeExtensions.cs5
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/HoistedLocals.cs2
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/DynamicExpression.cs258
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Error.cs17
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/ExpressionStringBuilder.cs7
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/IndexExpression.cs82
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AddInstruction.cs79
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AndInstruction.cs71
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ArrayOperations.cs12
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs17
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ControlFlowInstructions.cs13
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DecrementInstruction.cs49
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DefaultValueInstruction.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DivInstruction.cs211
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/EqualInstruction.cs92
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ExclusiveOrInstruction.cs70
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/FieldOperations.cs8
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/GreaterThanInstruction.cs382
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/GreaterThanOrEqualInstruction.cs324
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/IncrementInstruction.cs49
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/InstructionList.cs16
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LeftShiftInstruction.cs46
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LessThanInstruction.cs381
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LessThanOrEqualInstruction.cs322
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightCompiler.cs15
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.Generated.cs33
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.cs17
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs31
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ModuloInstruction.cs191
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/MulInstruction.cs78
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NegateInstruction.cs68
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NewInstruction.cs10
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotEqualInstruction.cs91
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotInstruction.cs69
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NullCheckInstruction.cs2
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NumericConvertInstruction.cs2
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OnesComplementInstruction.cs43
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OrInstruction.cs70
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/RightShiftInstruction.cs46
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/StackOperations.cs13
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/SubInstruction.cs78
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs148
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/Utilities.cs74
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/ListInitExpression.cs2
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/NewArrayExpression.cs2
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/NewExpression.cs2
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Strings.cs7
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/UnaryExpression.cs16
-rw-r--r--src/System.Linq.Expressions/src/System/Linq/Expressions/Utils.cs14
-rw-r--r--src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSite.cs96
-rw-r--r--src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSiteBinder.cs4
-rw-r--r--src/System.Linq.Expressions/src/System/Runtime/CompilerServices/ReadOnlyCollectionBuilder.cs106
-rw-r--r--src/System.Linq.Expressions/src/System/Runtime/CompilerServices/TrueReadOnlyCollection.cs (renamed from src/Common/src/System/Runtime/CompilerServices/TrueReadOnlyCollection.cs)0
-rw-r--r--src/System.Linq.Expressions/tests/Array/ArrayAccessTests.cs76
-rw-r--r--src/System.Linq.Expressions/tests/Array/ArrayArrayIndexTests.cs56
-rw-r--r--src/System.Linq.Expressions/tests/Array/ArrayIndexTests.cs101
-rw-r--r--src/System.Linq.Expressions/tests/Array/ArrayLengthTests.cs29
-rw-r--r--src/System.Linq.Expressions/tests/Cast/AsNullable.cs72
-rw-r--r--src/System.Linq.Expressions/tests/CompilerTests.cs23
-rw-r--r--src/System.Linq.Expressions/tests/Dynamic/BinaryOperationTests.cs33
-rw-r--r--src/System.Linq.Expressions/tests/Dynamic/DynamicObjectTests.cs812
-rw-r--r--src/System.Linq.Expressions/tests/Dynamic/ExpandoObjectTests.cs188
-rw-r--r--src/System.Linq.Expressions/tests/Dynamic/SetIndexBinderTests.cs144
-rw-r--r--src/System.Linq.Expressions/tests/Dynamic/SetMemberBinderTests.cs93
-rw-r--r--src/System.Linq.Expressions/tests/Dynamic/UnaryOperationTests.cs (renamed from src/System.Linq.Expressions/tests/Dynamic/UnaryOperationTests.cs .cs)0
-rw-r--r--src/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs28
-rw-r--r--src/System.Linq.Expressions/tests/IndexExpression/IndexExpressionTests.cs580
-rw-r--r--src/System.Linq.Expressions/tests/InterpreterTests.cs98
-rw-r--r--src/System.Linq.Expressions/tests/MemberInit/BindTests.cs2
-rw-r--r--src/System.Linq.Expressions/tests/ReadOnlyCollectionBuilderTests.cs914
-rw-r--r--src/System.Linq.Expressions/tests/StackSpillerTests.cs8
-rw-r--r--src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj10
-rw-r--r--src/System.Linq.Expressions/tests/Unary/IncrementDecrementTests.cs132
-rw-r--r--src/System.Linq.Expressions/tests/Unary/UnaryDecrementNullableTests.cs81
-rw-r--r--src/System.Linq.Expressions/tests/Unary/UnaryDecrementTests.cs50
-rw-r--r--src/System.Linq.Expressions/tests/Unary/UnaryIncrementNullableTests.cs81
-rw-r--r--src/System.Linq.Expressions/tests/Unary/UnaryIncrementTests.cs50
-rw-r--r--src/System.Linq.Expressions/tests/Unary/UnaryQuoteTests.cs32
-rw-r--r--src/System.Linq/pkg/System.Linq.pkgproj6
-rw-r--r--src/System.Linq/ref/System.Linq.cs2
-rw-r--r--src/System.Linq/src/ApiCompatBaseline.net461.txt (renamed from src/System.Linq/src/ApiCompatBaseline.net463.txt)0
-rw-r--r--src/System.Linq/src/Configurations.props2
-rw-r--r--src/System.Linq/src/System.Linq.csproj6
-rw-r--r--src/System.Linq/src/System/Linq/AppendPrepend.cs49
-rw-r--r--src/System.Linq/src/System/Linq/Buffer.cs15
-rw-r--r--src/System.Linq/src/System/Linq/Concat.cs21
-rw-r--r--src/System.Linq/src/System/Linq/Distinct.cs4
-rw-r--r--src/System.Linq/src/System/Linq/First.cs89
-rw-r--r--src/System.Linq/src/System/Linq/Iterator.cs75
-rw-r--r--src/System.Linq/src/System/Linq/Last.cs160
-rw-r--r--src/System.Linq/src/System/Linq/OrderBy.cs2
-rw-r--r--src/System.Linq/src/System/Linq/OrderedEnumerable.cs72
-rw-r--r--src/System.Linq/src/System/Linq/Partition.cs379
-rw-r--r--src/System.Linq/src/System/Linq/Range.cs3
-rw-r--r--src/System.Linq/src/System/Linq/Repeat.cs4
-rw-r--r--src/System.Linq/src/System/Linq/Reverse.cs4
-rw-r--r--src/System.Linq/src/System/Linq/Select.cs134
-rw-r--r--src/System.Linq/src/System/Linq/SelectMany.cs137
-rw-r--r--src/System.Linq/src/System/Linq/Set.cs89
-rw-r--r--src/System.Linq/src/System/Linq/Skip.cs21
-rw-r--r--src/System.Linq/src/System/Linq/Take.cs14
-rw-r--r--src/System.Linq/src/System/Linq/Union.cs14
-rw-r--r--src/System.Linq/src/System/Linq/Utilities.cs29
-rw-r--r--src/System.Linq/src/System/Linq/Where.cs44
-rw-r--r--src/System.Linq/tests/AggregateTests.cs39
-rw-r--r--src/System.Linq/tests/AllTests.cs6
-rw-r--r--src/System.Linq/tests/AnyTests.cs13
-rw-r--r--src/System.Linq/tests/AppendPrependTests.cs9
-rw-r--r--src/System.Linq/tests/AsEnumerableTests.cs8
-rw-r--r--src/System.Linq/tests/AverageTests.cs14
-rw-r--r--src/System.Linq/tests/CastTests.cs21
-rw-r--r--src/System.Linq/tests/ConcatTests.cs16
-rw-r--r--src/System.Linq/tests/ContainsTests.cs45
-rw-r--r--src/System.Linq/tests/CountTests.cs20
-rw-r--r--src/System.Linq/tests/DefaultIfEmptyTests.cs11
-rw-r--r--src/System.Linq/tests/DistinctTests.cs34
-rw-r--r--src/System.Linq/tests/ElementAtOrDefaultTests.cs7
-rw-r--r--src/System.Linq/tests/ElementAtTests.cs7
-rw-r--r--src/System.Linq/tests/EnumerableTests.cs24
-rw-r--r--src/System.Linq/tests/ExceptTests.cs26
-rw-r--r--src/System.Linq/tests/FirstOrDefaultTests.cs14
-rw-r--r--src/System.Linq/tests/FirstTests.cs14
-rw-r--r--src/System.Linq/tests/GroupByTests.cs45
-rw-r--r--src/System.Linq/tests/GroupJoinTests.cs59
-rw-r--r--src/System.Linq/tests/IntersectTests.cs24
-rw-r--r--src/System.Linq/tests/LastOrDefaultTests.cs24
-rw-r--r--src/System.Linq/tests/LastTests.cs24
-rw-r--r--src/System.Linq/tests/LongCountTests.cs14
-rw-r--r--src/System.Linq/tests/MaxTests.cs14
-rw-r--r--src/System.Linq/tests/MinTests.cs13
-rw-r--r--src/System.Linq/tests/OfTypeTests.cs9
-rw-r--r--src/System.Linq/tests/OrderByDescendingTests.cs9
-rw-r--r--src/System.Linq/tests/OrderByTests.cs59
-rw-r--r--src/System.Linq/tests/OrderedSubsetting.cs14
-rw-r--r--src/System.Linq/tests/ReverseTests.cs112
-rw-r--r--src/System.Linq/tests/SelectManyTests.cs131
-rw-r--r--src/System.Linq/tests/SelectTests.cs76
-rw-r--r--src/System.Linq/tests/SequenceEqualTests.cs9
-rw-r--r--src/System.Linq/tests/SingleOrDefaultTests.cs10
-rw-r--r--src/System.Linq/tests/SingleTests.cs10
-rw-r--r--src/System.Linq/tests/SkipTests.cs52
-rw-r--r--src/System.Linq/tests/SkipWhileTests.cs9
-rw-r--r--src/System.Linq/tests/SumTests.cs12
-rw-r--r--src/System.Linq/tests/System.Linq.Tests.csproj1
-rw-r--r--src/System.Linq/tests/TakeTests.cs84
-rw-r--r--src/System.Linq/tests/TakeWhileTests.cs11
-rw-r--r--src/System.Linq/tests/TestExtensions.cs127
-rw-r--r--src/System.Linq/tests/ThenByDescendingTests.cs16
-rw-r--r--src/System.Linq/tests/ThenByTests.cs24
-rw-r--r--src/System.Linq/tests/ToArrayTests.cs8
-rw-r--r--src/System.Linq/tests/ToDictionaryTests.cs8
-rw-r--r--src/System.Linq/tests/ToHashSetTests.netcoreapp1.1.cs6
-rw-r--r--src/System.Linq/tests/ToListTests.cs5
-rw-r--r--src/System.Linq/tests/ToLookupTests.cs18
-rw-r--r--src/System.Linq/tests/UnionTests.cs28
-rw-r--r--src/System.Linq/tests/WhereTests.cs8
-rw-r--r--src/System.Linq/tests/ZipTests.cs11
-rw-r--r--src/System.Memory/pkg/System.Memory.pkgproj5
-rw-r--r--src/System.Memory/ref/System.Memory.cs4
-rw-r--r--src/System.Memory/src/ApiCompatBaseline.txt3
-rw-r--r--src/System.Memory/src/Configurations.props1
-rw-r--r--src/System.Memory/src/System.Memory.csproj4
-rw-r--r--src/System.Memory/src/System/ReadOnlySpan.cs2
-rw-r--r--src/System.Memory/src/System/Span.cs2
-rw-r--r--src/System.Memory/tests/ReadOnlySpan/CtorArray.cs10
-rw-r--r--src/System.Memory/tests/Span/Overflow.cs2
-rw-r--r--src/System.Memory/tests/System.Memory.Tests.builds2
-rw-r--r--src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseParser.cs8
-rw-r--r--src/System.Net.Http.WinHttpHandler/tests/UnitTests/SafeWinHttpHandleTest.cs12
-rw-r--r--src/System.Net.Http/src/System.Net.Http.csproj6
-rw-r--r--src/System.Net.Http/src/System/Net/Http/HttpRequestException.cs1
-rw-r--r--src/System.Net.Http/src/netcore50/System/Net/HttpHandlerToFilter.cs2
-rw-r--r--src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.cs4
-rw-r--r--src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.cs4
-rw-r--r--src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs20
-rw-r--r--src/System.Net.Http/tests/FunctionalTests/PostScenarioTest.cs8
-rw-r--r--src/System.Net.Http/tests/UnitTests/Headers/CurlResponseHeaderReaderTest.cs8
-rw-r--r--src/System.Net.HttpListener/System.Net.HttpListener.sln36
-rw-r--r--src/System.Net.HttpListener/pkg/System.Net.HttpListener.pkgproj2
-rw-r--r--src/System.Net.HttpListener/ref/System.Net.HttpListener.cs21
-rw-r--r--src/System.Net.HttpListener/src/Configurations.props2
-rw-r--r--src/System.Net.HttpListener/src/Resources/Strings.resx47
-rw-r--r--src/System.Net.HttpListener/src/System.Net.HttpListener.csproj218
-rw-r--r--src/System.Net.HttpListener/src/System/Net/AuthConstants.cs15
-rw-r--r--src/System.Net.HttpListener/src/System/Net/AuthenticationTypes.cs13
-rw-r--r--src/System.Net.HttpListener/src/System/Net/HttpListener.Unix.cs219
-rw-r--r--src/System.Net.HttpListener/src/System/Net/HttpListener.cs160
-rw-r--r--src/System.Net.HttpListener/src/System/Net/HttpListenerContext.Unix.cs65
-rw-r--r--src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.Unix.cs268
-rw-r--r--src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.cs19
-rw-r--r--src/System.Net.HttpListener/src/System/Net/HttpListenerRequestUriBuilder.cs20
-rw-r--r--src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.Unix.cs198
-rw-r--r--src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs86
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/ChunkStream.cs406
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/ChunkedInputStream.cs186
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpConnection.cs551
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointListener.cs401
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointManager.cs182
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpHeaderStrings.cs15
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpListener.Managed.cs384
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerContext.Managed.cs144
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerPrefixCollection.Managed.cs122
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerRequest.Managed.cs656
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerResponse.Managed.cs475
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerTimeoutManager.Managed.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpListenerTimeoutManager.Unix.cs)3
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpRequestStream.Managed.cs229
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpResponseStream.Managed.cs275
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/HttpStreamAsyncResult.cs106
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/ListenerAsyncResult.Managed.cs208
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Managed/ListenerPrefix.cs175
-rw-r--r--src/System.Net.HttpListener/src/System/Net/WebSockets/WebSocketHelpers.cs2
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/AsyncRequestContext.cs (renamed from src/System.Net.HttpListener/src/System/Net/AsyncRequestContext.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/BoundaryType.cs (renamed from src/System.Net.HttpListener/src/System/Net/BoundaryType.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/ContextFlags.cs (renamed from src/System.Net.HttpListener/src/System/Net/ContextFlags.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/CookieExtensions.cs (renamed from src/System.Net.HttpListener/src/System/Net/CookieExtensions.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/EntitySendFormat.cs (renamed from src/System.Net.HttpListener/src/System/Net/EntitySendFormat.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpListener.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpListener.Windows.cs)892
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerContext.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpListenerContext.Windows.cs)2
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerPrefixCollection.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpListenerPrefixCollection.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerRequest.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.Windows.cs)22
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerRequestContext.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpListenerRequestContext.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerResponse.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.Windows.cs)126
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerTimeoutManager.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpListenerTimeoutManager.Windows.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpRequestQueueV2Handle.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpRequestQueueV2Handle.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpRequestStream.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpRequestStream.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpResponseStream.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpResponseStream.cs)6
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpResponseStreamAsyncResult.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpResponseStreamAsyncResult.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/HttpServerSessionHandle.cs (renamed from src/System.Net.HttpListener/src/System/Net/HttpServerSessionHandle.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/ListenerAsyncResult.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/ListenerAsyncResult.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/ListenerClientCertAsyncResult.Windows.cs (renamed from src/System.Net.HttpListener/src/System/Net/ListenerClientCertAsyncResult.cs)12
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/ListenerClientCertState.cs (renamed from src/System.Net.HttpListener/src/System/Net/ListenerClientCertState.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/RequestContextBase.cs (renamed from src/System.Net.HttpListener/src/System/Net/RequestContextBase.cs)0
-rw-r--r--src/System.Net.HttpListener/src/System/Net/Windows/SyncRequestContext.cs (renamed from src/System.Net.HttpListener/src/System/Net/SyncRequestContext.cs)0
-rw-r--r--src/System.Net.HttpListener/tests/AuthenticationTests.cs152
-rw-r--r--src/System.Net.HttpListener/tests/SimpleHttpTest.cs5
-rw-r--r--src/System.Net.HttpListener/tests/System.Net.HttpListener.Tests.csproj4
-rw-r--r--src/System.Net.Mail/pkg/System.Net.Mail.pkgproj2
-rw-r--r--src/System.Net.Mail/src/Configurations.props2
-rw-r--r--src/System.Net.Mail/src/System.Net.Mail.csproj20
-rw-r--r--src/System.Net.Mail/src/System/Net/Base64Stream.cs2
-rw-r--r--src/System.Net.Mail/src/System/Net/Mail/SmtpCommands.cs38
-rw-r--r--src/System.Net.Mail/src/System/Net/Mime/QEncodedStream.cs2
-rw-r--r--src/System.Net.Mail/src/System/Net/Mime/QuotedPrintableStream.cs2
-rw-r--r--src/System.Net.Mail/src/System/Net/Mime/SmtpDateTime.cs4
-rw-r--r--src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxNetworkInterface.cs2
-rw-r--r--src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Windows.cs14
-rw-r--r--src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/OsxNetworkInterface.cs2
-rw-r--r--src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/TeredoHelper.cs2
-rw-r--r--src/System.Net.Primitives/ref/System.Net.Primitives.cs7
-rw-r--r--src/System.Net.Primitives/src/System/Net/Cookie.cs4
-rw-r--r--src/System.Net.Primitives/src/System/Net/NetworkCredential.cs126
-rw-r--r--src/System.Net.Primitives/tests/FunctionalTests/NetworkCredentialTest.cs2
-rw-r--r--src/System.Net.Primitives/tests/FunctionalTests/NetworkCredentialTest.netstandard1.7.cs131
-rw-r--r--src/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj3
-rw-r--r--src/System.Net.Requests/ref/System.Net.Requests.cs32
-rw-r--r--src/System.Net.Requests/src/FxCopBaseline.cs12
-rw-r--r--src/System.Net.Requests/src/System.Net.Requests.csproj3
-rw-r--r--src/System.Net.Requests/src/System/Net/FtpDataStream.cs2
-rw-r--r--src/System.Net.Requests/src/System/Net/HttpWebRequest.cs172
-rw-r--r--src/System.Net.Requests/src/System/Net/HttpWebResponse.cs18
-rw-r--r--src/System.Net.Requests/src/System/Net/WebException.cs9
-rw-r--r--src/System.Net.Requests/tests/HttpRequestResponseSerializationTest.cs47
-rw-r--r--src/System.Net.Requests/tests/HttpWebRequestHeaderTest.cs141
-rw-r--r--src/System.Net.Requests/tests/HttpWebRequestTest.cs4
-rw-r--r--src/System.Net.Requests/tests/HttpWebRequestTest.netstandard1.7.cs28
-rw-r--r--src/System.Net.Requests/tests/HttpWebResponseHeaderTest.cs25
-rw-r--r--src/System.Net.Requests/tests/System.Net.Requests.Tests.csproj5
-rw-r--r--src/System.Net.Security/ref/System.Net.Security.cs8
-rw-r--r--src/System.Net.Security/src/System.Net.Security.csproj4
-rw-r--r--src/System.Net.Security/src/System/Net/FixedSizeReader.cs24
-rw-r--r--src/System.Net.Security/src/System/Net/NTAuthentication.cs102
-rw-r--r--src/System.Net.Security/src/System/Net/Security/InternalNegotiateStream.cs20
-rw-r--r--src/System.Net.Security/src/System/Net/Security/NegotiateStream.cs75
-rw-r--r--src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Unix.cs11
-rw-r--r--src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Windows.cs11
-rw-r--r--src/System.Net.Security/src/System/Net/Security/SslState.cs47
-rw-r--r--src/System.Net.Security/src/System/Net/Security/SslStream.cs5
-rw-r--r--src/System.Net.Security/src/System/Net/Security/SslStreamInternal.cs21
-rw-r--r--src/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs2
-rw-r--r--src/System.Net.Security/src/System/Net/StreamFramer.cs19
-rw-r--r--src/System.Net.Security/src/System/PinnableBufferCache.cs4
-rw-r--r--src/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs56
-rw-r--r--src/System.Net.Security/tests/FunctionalTests/NegotiateStreamStreamToStreamTest.cs33
-rw-r--r--src/System.Net.Security/tests/FunctionalTests/NegotiateStreamTestForUnix.cs2
-rw-r--r--src/System.Net.Security/tests/FunctionalTests/NotifyReadVirtualNetworkStream.cs25
-rw-r--r--src/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs101
-rw-r--r--src/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj1
-rw-r--r--src/System.Net.Security/tests/UnitTests/Fakes/FakeSslState.cs17
-rw-r--r--src/System.Net.ServicePoint/pkg/System.Net.ServicePoint.pkgproj2
-rw-r--r--src/System.Net.ServicePoint/src/Configurations.props2
-rw-r--r--src/System.Net.ServicePoint/src/System.Net.ServicePoint.csproj8
-rw-r--r--src/System.Net.Sockets/ref/System.Net.Sockets.cs10
-rw-r--r--src/System.Net.Sockets/src/Resources/Strings.resx3
-rw-r--r--src/System.Net.Sockets/src/System.Net.Sockets.csproj7
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/AcceptOverlappedAsyncResult.Windows.cs2
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Windows.cs12
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/ConnectOverlappedAsyncResult.Windows.cs2
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/DynamicWinsockMethods.cs2
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Unix.cs2
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Windows.cs4
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.cs2
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/Socket.Unix.cs127
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs101
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs96
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs137
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs13
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs10
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/SocketInformation.cs1
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs82
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs76
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/TransmitFileAsyncResult.Windows.cs65
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs10
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs6
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/SendFile.cs211
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs63
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/SocketAPMExtensions.cs10
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/SocketAsyncEventArgsTest.cs8
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj1
-rw-r--r--src/System.Net.WebClient/pkg/System.Net.WebClient.pkgproj2
-rw-r--r--src/System.Net.WebClient/src/Configurations.props2
-rw-r--r--src/System.Net.WebClient/src/System.Net.WebClient.csproj8
-rw-r--r--src/System.Net.WebClient/tests/WebClientTest.cs2
-rw-r--r--src/System.Net.WebHeaderCollection/ref/System.Net.WebHeaderCollection.cs3
-rw-r--r--src/System.Net.WebHeaderCollection/src/System/Net/HttpRequestHeader.cs2
-rw-r--r--src/System.Net.WebHeaderCollection/src/System/Net/HttpResponseHeader.cs2
-rw-r--r--src/System.Net.WebHeaderCollection/tests/WebHeaderCollectionTest.netstandard17.cs32
-rw-r--r--src/System.Net.WebProxy/pkg/System.Net.WebProxy.pkgproj2
-rw-r--r--src/System.Net.WebProxy/src/Configurations.props2
-rw-r--r--src/System.Net.WebProxy/src/System.Net.WebProxy.csproj8
-rw-r--r--src/System.Net.WebSockets.Client/src/System/Net/WebSockets/ManagedWebSocket.cs153
-rw-r--r--src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs2
-rw-r--r--src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinHttpWebSocket.cs14
-rw-r--r--src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinRTWebSocket.cs8
-rw-r--r--src/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs4
-rw-r--r--src/System.Numerics.Vectors/src/System/Numerics/Vector.cs4
-rw-r--r--src/System.Numerics.Vectors/src/System/Numerics/Vector.tt5
-rw-r--r--src/System.ObjectModel/pkg/System.ObjectModel.pkgproj2
-rw-r--r--src/System.ObjectModel/ref/Configurations.props9
-rw-r--r--src/System.ObjectModel/ref/System.ObjectModel.cs3
-rw-r--r--src/System.ObjectModel/ref/System.ObjectModel.csproj3
-rw-r--r--src/System.ObjectModel/src/System.ObjectModel.csproj5
-rw-r--r--src/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs41
-rw-r--r--src/System.ObjectModel/tests/Configurations.props1
-rw-r--r--src/System.ObjectModel/tests/KeyedCollection/TestMethods.cs2
-rw-r--r--src/System.ObjectModel/tests/KeyedCollection/TestMethods.netcoreapp1.1.cs65
-rw-r--r--src/System.ObjectModel/tests/System.ObjectModel.Tests.csproj1
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs2
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs18
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DictionaryGlobals.cs72
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/EnumDataContract.cs2
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs2
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ByteArrayHelperWithString.cs2
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs8
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/PrimitiveDataContract.cs4
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionClassWriter.cs10
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionReader.cs30
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs26
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializer.cs4
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XsdDataContractExporter.cs6
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Text/Base64Encoding.cs10
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Text/BinHexEncoding.cs4
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/ArrayHelper.cs40
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/EncodingStreamWrapper.cs6
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/PrefixHandle.cs12
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/StringHandle.cs12
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs16
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlBaseReader.cs4
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryWriter.cs40
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs16
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs108
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionary.cs2
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryReaderQuotas.cs2
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryString.cs4
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlExceptionHelper.cs82
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs16
-rw-r--r--src/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs6
-rw-r--r--src/System.Private.Uri/pkg/unix/System.Private.Uri.pkgproj5
-rw-r--r--src/System.Private.Uri/pkg/win/System.Private.Uri.pkgproj6
-rw-r--r--src/System.Private.Uri/src/Configurations.props2
-rw-r--r--src/System.Private.Uri/src/FxCopBaseline.cs4
-rw-r--r--src/System.Private.Uri/src/System.Private.Uri.csproj51
-rw-r--r--src/System.Private.Uri/src/System/DomainNameHelper.cs16
-rw-r--r--src/System.Private.Uri/src/System/IPv4AddressHelper.cs10
-rw-r--r--src/System.Private.Uri/src/System/IPv6AddressHelper.cs14
-rw-r--r--src/System.Private.Uri/src/System/UncNameHelper.cs2
-rw-r--r--src/System.Private.Uri/src/System/Uri.cs12
-rw-r--r--src/System.Private.Uri/src/System/UriHelper.cs8
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XCData.cs24
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XComment.cs19
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XContainer.cs290
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocument.cs244
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocumentType.cs21
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XElement.cs259
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XLinq.cs80
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XName.cs1
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XNode.cs75
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XProcessingInstruction.cs19
-rw-r--r--src/System.Private.Xml.Linq/src/System/Xml/Linq/XText.cs23
-rw-r--r--src/System.Private.Xml.Linq/tests/System.Private.Xml.Linq.Tests.builds52
-rw-r--r--src/System.Private.Xml.Linq/tests/TreeManipulation/LoadFromStream.cs2
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Common/BridgeHelpers.cs2
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Common/CXmlCache.cs2
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Common/DNException.cs4
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Common/HelperExtensionMethods.cs2
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Common/XDocument.Common.csproj3
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/XDocument.Test.ModuleCore.csproj3
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testlog.cs76
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testparser.cs4
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testproperties.cs12
-rw-r--r--src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/util.cs6
-rw-r--r--src/System.Private.Xml.Linq/tests/XPath/XDocument/XDocumentXPathTest.cs4
-rw-r--r--src/System.Private.Xml.Linq/tests/misc/LoadSaveAsyncTests.cs206
-rw-r--r--src/System.Private.Xml.Linq/tests/misc/System.Xml.Linq.Misc.Tests.csproj2
-rw-r--r--src/System.Private.Xml/src/System.Private.Xml.csproj2
-rw-r--r--src/System.Private.Xml/src/System/Xml/BinaryXml/SqlUtils.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs4
-rw-r--r--src/System.Private.Xml/src/System/Xml/Core/LocalAppContextSwitches.cs20
-rw-r--r--src/System.Private.Xml/src/System/Xml/Core/XmlReader.cs16
-rw-r--r--src/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs4
-rw-r--r--src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs10
-rw-r--r--src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImplAsync.cs8
-rw-r--r--src/System.Private.Xml/src/System/Xml/Core/XmlWellFormedWriter.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Dom/XmlDocument.cs10
-rw-r--r--src/System.Private.Xml/src/System/Xml/Dom/XmlLoader.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/MTNameTable.cs4
-rw-r--r--src/System.Private.Xml/src/System/Xml/Schema/Asttree.cs4
-rw-r--r--src/System.Private.Xml/src/System/Xml/Schema/BitSet.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs124
-rw-r--r--src/System.Private.Xml/src/System/Xml/Schema/DtdParser.cs8
-rw-r--r--src/System.Private.Xml/src/System/Xml/Schema/DtdParserAsync.cs8
-rw-r--r--src/System.Private.Xml/src/System/Xml/Serialization/CodeGenerator.cs6
-rw-r--r--src/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationWriter.cs113
-rw-r--r--src/System.Private.Xml/src/System/Xml/Serialization/Types.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Serialization/XmlSchemaExporter.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationILGen.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs6
-rw-r--r--src/System.Private.Xml/src/System/Xml/XPath/Internal/CacheChildrenQuery.cs3
-rw-r--r--src/System.Private.Xml/src/System/Xml/XPath/Internal/Operator.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/XPath/XPathNavigatorReader.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/XmlCharType.cs6
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/IlGen/GenerateHelper.cs4
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/IlGen/XmlILModule.cs6
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/QIL/QilValidationVisitor.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/Runtime/WhitespaceRuleReader.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/Runtime/XsltLibrary.cs53
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs8
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/XmlIlGenerator.cs6
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs6
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/Xslt/MatcherBuilder.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XPathPatternParser.cs4
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XslAstAnalyzer.cs6
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltInput.cs2
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/HtmlProps.cs16
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/StringOutput.cs4
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs44
-rw-r--r--src/System.Private.Xml/src/System/Xml/Xslt/XslTransform.cs24
-rw-r--r--src/System.Private.Xml/tests/Readers/CustomReader/CReaderTestModule.cs2
-rw-r--r--src/System.Private.Xml/tests/Readers/NameTable/CNameTableTestModule.cs18
-rw-r--r--src/System.Private.Xml/tests/Readers/NameTable/TestFiles.cs10
-rw-r--r--src/System.Private.Xml/tests/Readers/ReaderSettings/CReaderTestModule.cs50
-rw-r--r--src/System.Private.Xml/tests/Readers/ReaderSettings/MaxSettings.cs4
-rw-r--r--src/System.Private.Xml/tests/Readers/ReaderSettings/TCMaxSettings.cs4
-rw-r--r--src/System.Private.Xml/tests/System.Private.Xml.Tests.builds1
-rw-r--r--src/System.Private.Xml/tests/Writers/RwFactory/CFactoryModule.cs4
-rw-r--r--src/System.Private.Xml/tests/Writers/XmlWriterApi/CommonTests.cs7
-rw-r--r--src/System.Private.Xml/tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs6
-rw-r--r--src/System.Private.Xml/tests/Writers/XmlWriterApi/TCFullEndElement.cs4
-rw-r--r--src/System.Private.Xml/tests/Writers/XmlWriterApi/TCXmlWriterTestModule.cs60
-rw-r--r--src/System.Private.Xml/tests/XPath/XPathDocument/XmlReaderXPathTest.cs4
-rw-r--r--src/System.Private.Xml/tests/XPath/XmlDocument/XmlDocumentXPathTest.cs4
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/TestFiles/TestData/xmlresolver_v4.xsd22
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/TestFiles/TestData/xmlresolver_v5.xsd3
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/CError.cs6
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet.cs5
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Reader.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Schema.cs3
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_SchemaSet.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_URL.cs4
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_AllowXmlAttributes.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Compile.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Constructors.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_ns.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_schema.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_CopyTo.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_EnableUpaCheck.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalAttributes.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalElements.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalTypes.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Imports.cs6
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Includes.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Misc.cs16
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ProhibitDTD.cs14
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Remove.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_RemoveRecursive.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Reprocess.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ValidationEventHandler.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlNameTable.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlResolver.cs96
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CXmlTestResolver.cs5
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Constructor_AddSchema.cs4
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CustomImplementations.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ExceptionVerifier.cs399
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedAttributes.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedParticles.cs1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Initialize_EndValidation.cs71
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/PropertiesTests.cs9
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/System.Xml.XmlSchema.XmlSchemaValidatorApi.Tests.csproj1
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute.cs16
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute_String.cs9
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateElement.cs31
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateMisc.cs2
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_EndElement.cs59
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_String.cs16
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateWhitespace_String.cs14
-rw-r--r--src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidatorModule.cs4
-rw-r--r--src/System.Private.Xml/tests/XmlSerializer/ReflectionOnly/System.Xml.XmlSerializer.ReflectionOnly.Tests.csproj21
-rw-r--r--src/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.csproj14
-rw-r--r--src/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.settings.targets23
-rw-r--r--src/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs29
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/398968repro.xsl9
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/QFE505_multith_customer_repro_with_or_expr.xml1
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/QFE505_multith_customer_repro_with_or_expr.xsl516
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/Straße.xml1
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings11.xsl7
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings14-inc.xsl7
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings14.xsl4
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings15.xsl11
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings9.xsl8
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/baseline/DefaultResolver.txt1
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/coupons.xsl538
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/layout.xsl226
-rw-r--r--src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/xmlResolver_document_function_absolute_uri.xsl2
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/Errata4.cs13
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/OutputSettings.cs5
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/Program.cs17
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/TempFiles.cs588
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs1996
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslTransformMultith.cs115
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltApiV2.cs305
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentList.cs1832
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentListMultith.cs4
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs101
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/CThreads.cs1
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/CXmlCache.cs17
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTArgumentList.cs2616
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs1480
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransformMultith.cs12
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltArgumentListMultith.cs4
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltChecksum.cs1
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/DataHelper.cs1
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/ExceptionVerifier.cs18
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/MyNavigator.cs1
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/Program.cs17
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/XSLTransform.cs287
-rw-r--r--src/System.Private.Xml/tests/Xslt/XslTransformApi/cthread.cs5
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/ApiTests/XsltcApiTest.cs66
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestBasicFunctionality.cs83
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCaseBase.cs13
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestClassname.cs107
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCompile.cs48
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestOut.cs118
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestPlatform.cs22
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestSettings.cs43
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/Program.cs30
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/TestStylesheet.dllbin4096 -> 0 bytes
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCommon.cs3
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCompiler.Tests.csproj14
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltcModule.cs18
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltScenarios/AspNet.cs156
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltScenarios/EXslt.cs379
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltScenarios/GotDotNet.Exslt.dllbin73728 -> 0 bytes
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltScenarios/Schematron.cs163
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltScenarios/Utils.cs184
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltScenarios/XsltScenarios.cs47
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltScenarios/XsltScenarios.xml568
-rw-r--r--src/System.Private.Xml/tests/Xslt/XsltScenarios/XunitAssemblyAttribute.cs10
-rw-r--r--src/System.Reflection.Emit.ILGeneration/tests/CustomAttributeBuilderTests.cs32
-rw-r--r--src/System.Reflection.Emit.Lightweight/tests/DynamicMethodGetILGenerator.cs22
-rw-r--r--src/System.Reflection.Emit/tests/AssemblyBuilderTests.cs67
-rw-r--r--src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs6
-rw-r--r--src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.cs2
-rw-r--r--src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableByteArrayInterop.cs2
-rw-r--r--src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/MemoryMapLightUp.cs2
-rw-r--r--src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs2
-rw-r--r--src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs2
-rw-r--r--src/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs4
-rw-r--r--src/System.Reflection.Metadata/tests/Metadata/Ecma335/MetadataAggregatorTests.cs2
-rw-r--r--src/System.Reflection.Metadata/tests/Metadata/PortablePdb/StandalonePortablePdbStreamTests.cs2
-rw-r--r--src/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs6
-rw-r--r--src/System.Reflection.Metadata/tests/Resources/Interop/Interop.Mock01.cs1
-rw-r--r--src/System.Reflection.Metadata/tests/TestUtilities/LoaderUtilities.cs2
-rw-r--r--src/System.Reflection.Primitives/src/System/Reflection/Emit/FlowControl.cs1
-rw-r--r--src/System.Reflection.Primitives/src/System/Reflection/Emit/OpCodes.cs2
-rw-r--r--src/System.Reflection.Primitives/src/System/Reflection/Emit/Opcode.cs1
-rw-r--r--src/System.Reflection.Primitives/src/System/Reflection/Emit/OpcodeType.cs1
-rw-r--r--src/System.Reflection.Primitives/src/System/Reflection/Emit/OperandType.cs1
-rw-r--r--src/System.Reflection.Primitives/src/System/Reflection/Emit/PackingSize.cs1
-rw-r--r--src/System.Reflection.Primitives/src/System/Reflection/Emit/StackBehaviour.cs1
-rw-r--r--src/System.Reflection/pkg/System.Reflection.pkgproj8
-rw-r--r--src/System.Reflection/src/ApiCompatBaseline.txt4
-rw-r--r--src/System.Reflection/src/Configurations.props2
-rw-r--r--src/System.Reflection/src/System.Reflection.csproj8
-rw-r--r--src/System.Resources.Reader/pkg/System.Resources.Reader.pkgproj2
-rw-r--r--src/System.Resources.Writer/pkg/System.Resources.Writer.pkgproj2
-rw-r--r--src/System.Runtime.CompilerServices.Unsafe/pkg/System.Runtime.CompilerServices.Unsafe.pkgproj1
-rw-r--r--src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.il12
-rw-r--r--src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.xml8
-rw-r--r--src/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs27
-rw-r--r--src/System.Runtime.CompilerServices.VisualC/ref/System.Runtime.CompilerServices.VisualC.cs7
-rw-r--r--src/System.Runtime.CompilerServices.VisualC/src/System/Runtime/CompilerServices/Attributes.cs8
-rw-r--r--src/System.Runtime.Extensions/System.Runtime.Extensions.sln62
-rw-r--r--src/System.Runtime.Extensions/pkg/System.Runtime.Extensions.pkgproj10
-rw-r--r--src/System.Runtime.Extensions/pkg/win/System.Runtime.Extensions.pkgproj5
-rw-r--r--src/System.Runtime.Extensions/src/ApiCompatBaseline.netstandard15aot.txt4
-rw-r--r--src/System.Runtime.Extensions/src/ApiCompatBaseline.uap101aot.txt77
-rw-r--r--src/System.Runtime.Extensions/src/Configurations.props3
-rw-r--r--src/System.Runtime.Extensions/src/Resources/Strings.netcore50aot.resx231
-rw-r--r--src/System.Runtime.Extensions/src/Resources/Strings.resx50
-rw-r--r--src/System.Runtime.Extensions/src/System.Runtime.Extensions.csproj185
-rw-r--r--src/System.Runtime.Extensions/src/System/BitConverter.cs14
-rw-r--r--src/System.Runtime.Extensions/src/System/Context.cs1
-rw-r--r--src/System.Runtime.Extensions/src/System/Environment.Uap.cs100
-rw-r--r--src/System.Runtime.Extensions/src/System/Environment.Unix.cs105
-rw-r--r--src/System.Runtime.Extensions/src/System/Environment.Win32.Unix.cs50
-rw-r--r--src/System.Runtime.Extensions/src/System/Environment.Win32.cs233
-rw-r--r--src/System.Runtime.Extensions/src/System/Environment.cs100
-rw-r--r--src/System.Runtime.Extensions/src/System/IO/BinaryReader.cs2
-rw-r--r--src/System.Runtime.Extensions/src/System/IO/BufferedStream.cs24
-rw-r--r--src/System.Runtime.Extensions/src/System/IO/EndOfStreamException.cs3
-rw-r--r--src/System.Runtime.Extensions/src/System/IO/PathHelper.Windows.cs2
-rw-r--r--src/System.Runtime.Extensions/src/System/Net/Configuration/UnicodeDecodingConformance.cs58
-rw-r--r--src/System.Runtime.Extensions/src/System/Net/Configuration/UnicodeEncodingConformance.cs45
-rw-r--r--src/System.Runtime.Extensions/src/System/Reflection/AssemblyNameProxy.cs1
-rw-r--r--src/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj1
-rw-r--r--src/System.Runtime.Extensions/tests/System/Environment.GetEnvironmentVariable.cs48
-rw-r--r--src/System.Runtime.Extensions/tests/System/EnvironmentTests.cs2
-rw-r--r--src/System.Runtime.Extensions/tests/System/UnloadingAndProcessExitTests.netcoreapp1.1.cs37
-rw-r--r--src/System.Runtime.InteropServices/pkg/System.Runtime.InteropServices.pkgproj8
-rw-r--r--src/System.Runtime.InteropServices/src/ApiCompatBaseline.uap101aot.txt3
-rw-r--r--src/System.Runtime.InteropServices/src/Configurations.props2
-rw-r--r--src/System.Runtime.InteropServices/src/System.Runtime.InteropServices.csproj12
-rw-r--r--src/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/MarshalTests.cs5
-rw-r--r--src/System.Runtime.Loader/pkg/System.Runtime.Loader.pkgproj2
-rw-r--r--src/System.Runtime.Loader/ref/System.Runtime.Loader.cs2
-rw-r--r--src/System.Runtime.Loader/tests/DefaultContext/System.Runtime.Loader.DefaultContext.Tests.csproj1
-rw-r--r--src/System.Runtime.Loader/tests/RefEmitLoadContext/System.Runtime.Loader.RefEmitLoadContext.Tests.csproj1
-rw-r--r--src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.AddSub.cs14
-rw-r--r--src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs12
-rw-r--r--src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.FastReducer.cs4
-rw-r--r--src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs10
-rw-r--r--src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs4
-rw-r--r--src/System.Runtime.Numerics/tests/BigInteger/divrem.cs16
-rw-r--r--src/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs3
-rw-r--r--src/System.Runtime.Serialization.Json/tests/System.Runtime.Serialization.Json.Tests.builds2
-rw-r--r--src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs31
-rw-r--r--src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs5
-rw-r--r--src/System.Runtime.Serialization.Xml/tests/System.Runtime.Serialization.Xml.Tests.builds2
-rw-r--r--src/System.Runtime.Serialization.Xml/tests/XmlDictionaryWriterTest.cs33
-rw-r--r--src/System.Runtime.WindowsRuntime.UI.Xaml/pkg/System.Runtime.WindowsRuntime.UI.Xaml.pkgproj2
-rw-r--r--src/System.Runtime.WindowsRuntime/pkg/System.Runtime.WindowsRuntime.pkgproj2
-rw-r--r--src/System.Runtime.WindowsRuntime/src/System/InternalHelpers.cs2
-rw-r--r--src/System.Runtime.WindowsRuntime/src/System/Runtime/InteropServices/WindowsRuntime/MarshalingHelpers.cs10
-rw-r--r--src/System.Runtime.WindowsRuntime/src/System/Windows/Rect.cs2
-rw-r--r--src/System.Runtime.WindowsRuntime/src/System/Windows/Size.cs4
-rw-r--r--src/System.Runtime/pkg/System.Runtime.pkgproj11
-rw-r--r--src/System.Runtime/pkg/any/System.Runtime.pkgproj5
-rw-r--r--src/System.Runtime/ref/System.Runtime.cs27
-rw-r--r--src/System.Runtime/src/ApiCompatBaseline.netcoreapp1.2corert.txt387
-rw-r--r--src/System.Runtime/src/ApiCompatBaseline.txt9
-rw-r--r--src/System.Runtime/src/ApiCompatBaseline.uap101aot.txt188
-rw-r--r--src/System.Runtime/src/Configurations.props4
-rw-r--r--src/System.Runtime/src/System.Runtime.csproj24
-rw-r--r--src/System.Runtime/src/System/ComponentModel/DefaultValueAttribute.cs40
-rw-r--r--src/System.Runtime/src/System/ComponentModel/EditorBrowsableAttribute.cs48
-rw-r--r--src/System.Runtime/tests/System.Runtime.Tests.csproj23
-rw-r--r--src/System.Runtime/tests/System/ArraySegmentTests.cs242
-rw-r--r--src/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.cs2
-rw-r--r--src/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.netcoreapp1.1.cs21
-rw-r--r--src/System.Runtime/tests/System/Reflection/ModuleTests.cs2
-rw-r--r--src/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.cs255
-rw-r--r--src/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.netcoreapp1.1.cs36
-rw-r--r--src/System.Runtime/tests/System/StringTests.cs23
-rw-r--r--src/System.Runtime/tests/System/TimeSpanTests.cs1
-rw-r--r--src/System.Runtime/tests/System/TimeZoneInfoTests.cs2
-rw-r--r--src/System.Runtime/tests/TimeZoneInfoTests.netstandard1.7.cs23
-rw-r--r--src/System.Security.AccessControl/src/System/Security/AccessControl/ACL.cs12
-rw-r--r--src/System.Security.AccessControl/src/System/Security/AccessControl/NativeObjectSecurity.cs2
-rw-r--r--src/System.Security.AccessControl/src/System/Security/AccessControl/ObjectSecurity.cs4
-rw-r--r--src/System.Security.AccessControl/src/System/Security/AccessControl/PrivilegeNotHeldException.cs2
-rw-r--r--src/System.Security.AccessControl/src/System/Security/AccessControl/Rules.cs4
-rw-r--r--src/System.Security.Claims/src/System/Security/Claims/GenericIdentity.cs1
-rw-r--r--src/System.Security.Claims/src/System/Security/Claims/GenericPrincipal.cs1
-rw-r--r--src/System.Security.Claims/src/System/Security/Claims/RoleClaimProvider.cs1
-rw-r--r--src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs11
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx6
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj12
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs123
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACMD5.cs11
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA1.cs11
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA256.cs11
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA384.cs11
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA512.cs11
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs11
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs11
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs9
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs9
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs9
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs9
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs9
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs9
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs9
-rw-r--r--src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs9
-rw-r--r--src/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs65
-rw-r--r--src/System.Security.Cryptography.Algorithms/tests/PaddingModeTests.cs147
-rw-r--r--src/System.Security.Cryptography.Algorithms/tests/Rfc2898Tests.cs10
-rw-r--r--src/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj1
-rw-r--r--src/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj9
-rw-r--r--src/System.Security.Cryptography.Cng/src/Internal/Cryptography/BasicSymmetricCipherNCrypt.cs4
-rw-r--r--src/System.Security.Cryptography.Cng/tests/DSACngTests.cs2
-rw-r--r--src/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs24
-rw-r--r--src/System.Security.Cryptography.Csp/src/Resources/Strings.resx15
-rw-r--r--src/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj8
-rw-r--r--src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.cs194
-rw-r--r--src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.cs4
-rw-r--r--src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs4
-rw-r--r--src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs327
-rw-r--r--src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.cs4
-rw-r--r--src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs4
-rw-r--r--src/System.Security.Cryptography.Csp/tests/PasswordDeriveBytesTests.cs552
-rw-r--r--src/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj1
-rw-r--r--src/System.Security.Cryptography.OpenSsl/pkg/System.Security.Cryptography.OpenSsl.pkgproj2
-rw-r--r--src/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/HelpersWindows.cs2
-rw-r--r--src/System.Security.Cryptography.Pkcs/src/Interop/Windows/Crypt32/Interop.CryptMsgOpenToEncode.cs2
-rw-r--r--src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs1
-rw-r--r--src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj1
-rw-r--r--src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HMAC.cs4
-rw-r--r--src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs17
-rw-r--r--src/System.Security.Cryptography.Primitives/tests/CryptoStream.cs48
-rw-r--r--src/System.Security.Cryptography.Primitives/tests/Length32Hash.cs7
-rw-r--r--src/System.Security.Cryptography.Primitives/tests/Sum32Hash.cs7
-rw-r--r--src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs31
-rw-r--r--src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs16
-rw-r--r--src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/SafeHandles.cs33
-rw-r--r--src/System.Security.Cryptography.X509Certificates/tests/CertTests.cs59
-rw-r--r--src/System.Security.Cryptography.X509Certificates/tests/CtorTests.cs15
-rw-r--r--src/System.Security.Cryptography.Xml/System.Security.Cryptography.Xml.sln28
-rw-r--r--src/System.Security.Cryptography.Xml/dir.props7
-rw-r--r--src/System.Security.Cryptography.Xml/pkg/System.Security.Cryptography.Xml.builds10
-rw-r--r--src/System.Security.Cryptography.Xml/pkg/System.Security.Cryptography.Xml.pkgproj19
-rw-r--r--src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.builds10
-rw-r--r--src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs7
-rw-r--r--src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj15
-rw-r--r--src/System.Security.Cryptography.Xml/src/Resources/System.Security.txt129
-rw-r--r--src/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.builds11
-rw-r--r--src/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj94
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AncestralNamespaceContextManager.cs99
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AttributeSortOrder.cs29
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/C14NAncestralNamespaceContextManager.cs100
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXml.cs128
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlAttribute.cs49
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlCDataSection.cs45
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlComment.cs74
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlDocument.cs119
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlElement.cs177
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlEntityReference.cs43
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlNodeList.cs113
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlProcessingInstruction.cs77
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlSignificantWhitespace.cs47
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlText.cs47
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlWhitespace.cs47
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalizationDispatcher.cs68
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CertUsageType.cs25
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherData.cs126
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherReference.cs90
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoSignedXmlRecursionException.cs28
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs107
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DataObject.cs155
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DataReference.cs28
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DocPosition.cs16
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedData.cs120
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedKey.cs231
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedReference.cs128
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedType.cs129
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedXml.cs919
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionMethod.cs104
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionProperty.cs93
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionPropertyCollection.cs172
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ExcAncestralNamespaceContextManager.cs90
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ExcCanonicalXml.cs122
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ICanonicalizableNode.cs27
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/IRelDecryptor.cs13
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfo.cs147
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoClause.cs30
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoEncryptedKey.cs52
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoName.cs66
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoNode.cs62
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoRetrievalMethod.cs83
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoX509Data.cs305
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyReference.cs28
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/MyXmlDocument.cs25
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceFrame.cs48
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceSortOrder.cs31
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAKeyValue.cs80
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs461
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ReferenceList.cs138
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ReferenceTargetType.cs16
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Signature.cs215
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedInfo.cs268
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs1199
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs1080
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SymmetricKeyWrap.cs193
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Transform.cs229
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformChain.cs213
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformInputType.cs16
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs822
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/X509IssuerSerial.cs55
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs272
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigBase64Transform.cs139
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs93
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NWithCommentsTransform.cs26
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs199
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs123
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NWithCommentsTransform.cs34
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs195
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXsltTransform.cs156
-rw-r--r--src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs195
-rw-r--r--src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.builds11
-rw-r--r--src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj26
-rw-r--r--src/System.Security.Permissions/pkg/System.Security.Permissions.pkgproj2
-rw-r--r--src/System.Security.Permissions/src/Configurations.props2
-rw-r--r--src/System.Security.Permissions/src/System.Security.Permissions.csproj8
-rw-r--r--src/System.Security.Principal/src/Configurations.props1
-rw-r--r--src/System.Text.Encoding.CodePages/pkg/System.Text.Encoding.CodePages.pkgproj2
-rw-r--r--src/System.Text.Encoding.CodePages/src/System.Text.Encoding.CodePages.csproj5
-rw-r--r--src/System.Text.Encoding.CodePages/src/System/Text/GB18030Encoding.cs4
-rw-r--r--src/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj5
-rw-r--r--src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/BufferInternal.cs2
-rw-r--r--src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/HtmlEncoder.cs4
-rw-r--r--src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/JavaScriptEncoder.cs6
-rw-r--r--src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs4
-rw-r--r--src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UnicodeHelpers.cs2
-rw-r--r--src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UrlEncoder.cs2
-rw-r--r--src/System.Text.RegularExpressions/pkg/System.Text.RegularExpressions.pkgproj6
-rw-r--r--src/System.Text.RegularExpressions/src/Configurations.props2
-rw-r--r--src/System.Text.RegularExpressions/src/System.Text.RegularExpressions.csproj12
-rw-r--r--src/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs1
-rw-r--r--src/System.Text.RegularExpressions/tests/Regex.Ctor.Tests.cs2
-rw-r--r--src/System.Threading.AccessControl/src/System/Security/AccessControl/SemaphoreSecurity.cs2
-rw-r--r--src/System.Threading.Overlapped/ref/System.Threading.Overlapped.cs6
-rw-r--r--src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandle.cs2
-rw-r--r--src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandleOverlapped.cs2
-rw-r--r--src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolBoundHandle.cs2
-rw-r--r--src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs14
-rw-r--r--src/System.Threading.Overlapped/tests/DllImport.cs2
-rw-r--r--src/System.Threading.Overlapped/tests/OverlappedTests.cs14
-rw-r--r--src/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs10
-rw-r--r--src/System.Threading.Tasks.Dataflow/src/Internal/ActionOnDispose.cs2
-rw-r--r--src/System.Threading.Tasks.Dataflow/src/Internal/Common.cs4
-rw-r--r--src/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs2
-rw-r--r--src/System.Threading.Tasks.Dataflow/src/Internal/ImmutableArray.cs2
-rw-r--r--src/System.Threading.Tasks.Extensions/tests/AsyncValueTaskMethodBuilderTests.cs20
-rw-r--r--src/System.Threading.Tasks/tests/Task/TaskContinueWhenAnyTests.cs2
-rw-r--r--src/System.Threading.Thread/pkg/System.Threading.Thread.pkgproj2
-rw-r--r--src/System.Threading.Thread/ref/System.Threading.Thread.cs5
-rw-r--r--src/System.Threading.Thread/src/Configurations.props2
-rw-r--r--src/System.Threading.Thread/src/System.Threading.Thread.csproj10
-rw-r--r--src/System.Threading.Thread/src/System/Threading/ThreadAbortException.cs2
-rw-r--r--src/System.Threading.ThreadPool/ref/System.Threading.ThreadPool.cs2
-rw-r--r--src/System.Threading.ThreadPool/tests/ThreadPoolTests.cs3
-rw-r--r--src/System.Threading.Timer/ref/System.Threading.Timer.Manual.cs23
-rw-r--r--src/System.Threading.Timer/ref/System.Threading.Timer.cs4
-rw-r--r--src/System.Threading.Timer/ref/System.Threading.Timer.csproj1
-rw-r--r--src/System.Threading/src/System/Collections/Concurrent/LowLevelConcurrentQueue.cs615
-rw-r--r--src/System.Transactions/pkg/System.Transactions.pkgproj4
-rw-r--r--src/System.Transactions/src/System/Transactions/TransactionException.cs14
-rw-r--r--src/System.Transactions/src/System/Transactions/TransactionState.cs50
-rw-r--r--src/System.Transactions/src/System/Transactions/TransactionsEtwProvider.cs231
-rw-r--r--src/System.Transactions/tests/AsyncTransactionScopeTests.cs496
-rw-r--r--src/System.Transactions/tests/HelperFunctions.cs50
-rw-r--r--src/System.Transactions/tests/System.Transactions.Tests.csproj1
-rw-r--r--src/System.Transactions/tests/TransactionTracingEventListener.cs122
-rw-r--r--src/System.ValueTuple/src/System/ValueTuple/ValueTuple.cs17
-rw-r--r--src/System.ValueTuple/tests/TupleElementNamesTests.cs23
-rw-r--r--src/System.ValueTuple/tests/ValueTupleTests.cs30
-rw-r--r--src/System.Xml.XDocument/ref/Configurations.props9
-rw-r--r--src/System.Xml.XDocument/ref/System.Xml.XDocument.cs47
-rw-r--r--src/System.Xml.XDocument/ref/System.Xml.XDocument.csproj3
-rw-r--r--src/System.Xml.XDocument/src/ApiCompatBaseline.net463.txt23
-rw-r--r--src/System.Xml.XPath.XmlDocument/pkg/System.Xml.XPath.XmlDocument.pkgproj2
-rw-r--r--src/System.Xml.XPath.XmlDocument/src/Configurations.props2
-rw-r--r--src/System.Xml.XPath.XmlDocument/src/System.Xml.XPath.XmlDocument.csproj2
1974 files changed, 165924 insertions, 32906 deletions
diff --git a/.gitignore b/.gitignore
index 544bb1466e..c21764a6f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,8 @@ msbuild.wrn
# Cross building rootfs
cross/rootfs/
+# add x86 as it is ignored in 'Build results'
+!cross/x86
# Visual Studio 2015
.vs/
@@ -173,6 +175,7 @@ ClientBin/
node_modules/
*.metaproj
*.metaproj.tmp
+bin.localpkg/
# RIA/Silverlight projects
Generated_Code/
diff --git a/BuildToolsVersion.txt b/BuildToolsVersion.txt
index 25393bbf69..7170a3c427 100644
--- a/BuildToolsVersion.txt
+++ b/BuildToolsVersion.txt
@@ -1 +1 @@
-1.0.27-prerelease-01010-02
+1.0.27-prerelease-01121-01
diff --git a/CodeAnalysis.ruleset b/CodeAnalysis.ruleset
index 6eb689b870..785a687fc1 100644
--- a/CodeAnalysis.ruleset
+++ b/CodeAnalysis.ruleset
@@ -16,10 +16,10 @@
<Rule Id="CA1036" Action="None" /> <!-- Overload comparison operators when implementing System.IComparable -->
<Rule Id="CA1715" Action="None" /> <!-- Type parameters names should be prefixed with T -->
<Rule Id="CA2213" Action="None" /> <!-- Disposable Fields should be disposed -->
- <Rule Id="CA2229" Action="None" /> <!-- Serializable type doesn't have a serialization constructor -->
+ <Rule Id="CA2229" Action="Error" /> <!-- Serializable type doesn't have a serialization constructor -->
<Rule Id="CA2235" Action="None" /> <!-- Serializable type has non serializable field -->
<Rule Id="CA2231" Action="None" /> <!-- Overload operator equals when overriding ValueType.Equals -->
- <Rule Id="CA2237" Action="None" /> <!-- Add [Serializable] to types that implement ISerializable -->
+ <Rule Id="CA2237" Action="Error" /> <!-- Add [Serializable] to types that implement ISerializable -->
<Rule Id="CA2200" Action="None"/> <!-- Rethrowing caught exception changes stack information -->
@@ -29,10 +29,7 @@
<Rule Id="CA2214" Action="None" /> <!-- Do not call overridable methods in constructors -->
</Rules>
<Rules AnalyzerId="System.Runtime.Analyzers" RuleNamespace="System.Runtime.Analyzers">
- <Rule Id="CA2002" Action="None" /> <!-- Do not lock on objects with weak identity -->
- </Rules>
- <Rules AnalyzerId="System.Runtime.CSharp.Analyzers" RuleNamespace="System.Runtime.CSharp.Analyzers">
- <Rule Id="CA2002" Action="None" /> <!-- Do not lock on objects with weak identity -->
+ <Rule Id="CA2002" Action="Error" /> <!-- Do not lock on objects with weak identity -->
</Rules>
<Rules AnalyzerId="System.Security.Cryptography.Hashing.Algorithms.Analyzers" RuleNamespace="System.Security.Cryptography.Hashing.Algorithms.Analyzers">
<Rule Id="CA5350" Action="Error" /> <!-- Do not use Weak/Broken cryptographic algorithms -->
diff --git a/Documentation/coding-guidelines/coding-style.md b/Documentation/coding-guidelines/coding-style.md
index 8808a17d4b..e91ee3e367 100644
--- a/Documentation/coding-guidelines/coding-style.md
+++ b/Documentation/coding-guidelines/coding-style.md
@@ -28,6 +28,7 @@ The general rule we follow is "use Visual Studio defaults".
12. We use PascalCasing to name all our constant local variables and fields. The only exception is for interop code where the constant value should exactly match the name and value of the code you are calling via interop.
13. We use ```nameof(...)``` instead of ```"..."``` whenever possible and relevant.
14. Fields should be specified at the top within type declarations.
+15. When including non-ASCII characters in the source code use Unicode escape sequences (\uXXXX) instead of literal characters. Literal non-ASCII characters occasionally get garbled by a tool or editor.
We have provided a Visual Studio 2013 vssettings file (`corefx.vssettings`) at the root of the corefx repository, enabling C# auto-formatting conforming to the above guidelines. Note that rules 7 and 8 are not covered by the vssettings, since these are not rules currently supported by VS formatting.
diff --git a/Documentation/project-docs/developer-guide.md b/Documentation/project-docs/developer-guide.md
index 893642609b..2a2568139b 100644
--- a/Documentation/project-docs/developer-guide.md
+++ b/Documentation/project-docs/developer-guide.md
@@ -158,10 +158,9 @@ One can build in Debug or Release mode from the root by doing `build -release` o
One can build 32- or 64-bit binaries or for any architecture by specifying in the root `build -buildArch=[value]` or in a project `/p:Platform=[value]` after the `msbuild` command.
-
### Tests
-We use the OSS testing framework [xunit](http://xunit.github.io/).
+We use the OSS testing framework [xunit](http://xunit.github.io/) with the [BuildTools test targets](https://github.com/dotnet/buildtools/blob/master/Documentation/test-targets-usage.md).
#### Running tests on the command line
@@ -179,9 +178,9 @@ cd src\System.Collections.Immutable\tests
msbuild System.Collections.Immutable.Tests.builds
```
-What that will do is to build the tests against all of the available configurations, and then apply some filtering to run only the project configurations that support the default TestTFM(more about this on the next section). This is the prefered way since even though we only run the tests on a specific TFM, we will cross compile the tests against all its available configurations, which is good in order to make sure that you are not breaking the test build. This is also how CI will run the tests, so if you are able to build the .builds file succesfully, chances are that CI will too.
+What that will do is to build the tests against all of the available configurations, and then apply some filtering to run only the project configurations that support the default TestTFM (more about this in the next section). This is the preferred way since even though we only run the tests on a specific TFM, we will cross compile the tests against all its available configurations, which is good in order to make sure that you are not breaking the test build. This is also how CI will run the tests, so if you are able to build the .builds file successfully, chances are that CI will too.
-The second way to do it, is to build the .csproj and select to run the `BuildAndTest` target:
+The second way to do it is to build the .csproj and select to run the `BuildAndTest` target:
```cmd
cd src\System.Collections.Immutable\tests
@@ -196,28 +195,28 @@ msbuild /t:Test "/p:XunitOptions=-class Test.ClassUnderTests"
There may be multiple projects in some directories so you may need to specify the path to a specific test project to get it to build and run the tests.
-Tests participate in the incremental build. This means that if tests have already been run, and inputs to the incremental build have not changed, rerunning the tests target will not execute the test runner again. To force re-executing tests in this situation, use `msbuild /t:RebuildAndTest`.
+Tests participate in the incremental build. This means that if tests have already been run, and inputs to the incremental build have not changed, rerunning the tests target will not execute the test runner again. To force re-executing tests in this situation, use `/p:ForceRunTests=true`.
#### What is TestTFM and what possible values can it have
-`TestTFM` is the Framework that we will use to run your tests on. The same test assembly can be used to run tests on two different frameworks, for example, AssemblyWithMyTests.dll can be used to run your tests in TFM `A` and `B` as long as framworks `A` and `B` provide/support the NetStandard surface area needed for the test assembly to compile. For this reason, when you write your tests, you might want to run them against different frameworks, and the next section will point out how to do that.
+`TestTFM` is the Framework that we will use to run your tests on. The same test assembly can be used to run tests on two different frameworks, for example, AssemblyWithMyTests.dll can be used to run your tests in TFM `A` and `B` as long as frameworks `A` and `B` provide/support the NetStandard surface area needed for the test assembly to compile. For this reason, when you write your tests, you might want to run them against different frameworks, and the next section will point out how to do that.
Some of the possible values for `TestTFM` are:
-_**`netcoreapp1.1` or `netcoreapp1.0`**_
+- _**`netcoreapp1.1` or `netcoreapp1.0`**_
NetStandard implementations that run in CoreCLR.
-_**`netcore50` or `uap101aot`**_
+- _**`netcore50` or `uap101aot`**_
NetStandard implementations for UWP.
--**`net46` or `net462` or `net463`**-
+- _**`net46` or `net462` or `net463`**_
NetStandard implementations for Desktop.
#### Running tests in a different TFM
-Each test project corresponds to a test .builds file. There are some tests that might be OS specific, or might be testing API that is available only on some TFMs, which is what this tests.builds files are for. By default, we will build all of these different configurations always, but we will only execute the tests on one TFM. By default, our `TestTFM` is set to `netcoreapp1.1` [here](https://github.com/dotnet/corefx/blob/master/dir.props#L495) which means that we will run tests for the configurations that either:
-- Have `netcoreapp1.1` inside their `<TestTFMs>...</TestTFMs>` clause on the .builds files, or
-- Don't have a `<TestTFMs>...</TestTFMs>` metadata in the .builds file at all because we default it to netcoreapp1.1 [here](https://github.com/dotnet/corefx/blob/master/dir.traversal.targets#L146-L147)
+Each test project corresponds to a test .builds file. There are some tests that might be OS-specific, or might be testing an API that is available only on some TFMs, so the tests.builds specifies the valid configurations. By default, we will build all of these different configurations always, but we will only execute the tests on one TFM. By default, our `TestTFM` is set to `netcoreapp1.1` [here](https://github.com/dotnet/corefx/blob/80ab4804aeb7bed16e64b988c7460c705fddd5cc/dir.props#L529) (see latest value of `DefaultTestTFM` [in dir.props](https://github.com/dotnet/corefx/blob/master/dir.props)), which means that we will run tests for the `Project`s in the .builds file that either:
+- Have `netcoreapp1.1` inside their `TestTFMs` metadata, or
+- Don't have `TestTFMs` metadata, indicating the default TFM.
The rest of the configurations will still get built, but they won't be executed by default, or as part of the CI. In order to use a different TestTFM, pass in the `FilterToTestTFM` property like:
@@ -226,9 +225,9 @@ cd src\System.Runtime\tests
msbuild System.Runtime.Tests.builds /p:FilterToTestTFM=net462
```
-The previous example will again build the System.Runtime csproj in all of it's different configurations, but will only execute the tests that have `net462` in their `<TestTFMs>...</TestTFMs>` metadata on System.Runtime.Tests.builds
+The previous example will again build the System.Runtime csproj in all of its different configurations, but will only execute the configurations that have `net462` in their `TestTFMs` metadata in System.Runtime.Tests.builds.
-One more way to run tests on a specific TFM, is to do it by building the test csproj directly and set the value of `TestTFM` like:
+One more way to run tests on a specific TFM is to build the test csproj directly and set the value of `TestTFM` like:
```cmd
cd src\System.Runtime\tests
@@ -237,7 +236,7 @@ msbuild System.Runtime.Tests.csproj /t:BuildAndTest /p:TestTFM=net462
#### Filtering tests using traits
-The tests can also be filtered based on xunit trait attributes defined in [`xunit.netcore.extensions`](https://github.com/dotnet/buildtools/tree/master/src/xunit.netcore.extensions). These attributes are to be specified over the test method. The available attributes are:
+The tests can also be filtered based on xunit trait attributes defined in [`xunit.netcore.extensions`](https://github.com/dotnet/buildtools/tree/master/src/xunit.netcore.extensions). These attributes are specified above the test method's definition. The available attributes are:
_**`OuterLoop`:**_
Tests marked as `Outerloop` are for scenarios that don't need to run every build. They may take longer than normal tests, cover seldom hit code paths, or require special setup or resources to execute. These tests are excluded by default when testing through msbuild but can be enabled manually by adding the `Outerloop` property e.g.
@@ -248,54 +247,44 @@ build-managed -Outerloop
To run <b>only</b> the Outerloop tests, use the following command:
```cmd
-xunit.console.netcore.exe *.dll -trait category=outerloop
-msbuild *.csproj /p:WithCategories=OuterLoop
+msbuild <csproj_file> /t:BuildAndTest /p:WithCategories=OuterLoop
```
_**`PlatformSpecific(TestPlatforms platforms)`:**_
Use this attribute on test methods to specify that this test may only be run on the specified platforms. This attribute returns the following categories based on platform
+- `nonwindowstests` for tests that don't run on Windows
+- `nonlinuxtests` for tests that don't run on Linux
+- `nonosxtests` for tests that don't run on OS X
- - `nonwindowstests`: for tests that don't run on Windows
- - `nonlinuxtests`: for tests that don't run on Linux
- - `nonosxtests`: for tests that don't run on OS X
-
-To run Linux-specific tests on a Linux box, use the following command line:
+When running tests by building a test project, tests that don't apply to the `OSGroup` are not run. For example, to run Linux-specific tests on a Linux box, use the following command line:
```sh
-xunit.console.netcore.exe *.dll -notrait category=nonlinuxtests
+<repo-root>/Tools/msbuild.sh <csproj_file> /t:BuildAndTest /p:OSGroup=Linux
```
_**`ActiveIssue(int issue, TestPlatforms platforms)`:**_
-Use this attribute over test methods, to skip failing tests only on the specific platforms, if no platforms are specified, then the test is skipped on all platforms. This attribute returns the 'failing' category, so to run all acceptable tests on Linux that are not failing, use the following commandline,
-```sh
-xunit.console.netcore.exe *.dll -notrait category=failing -notrait category=nonlinuxtests
-```
+Use this attribute over test methods to skip failing tests only on the specific platforms; if no platforms are specified, then the test is skipped on all platforms. This attribute returns the 'failing' category, which is disabled by default.
-And to run all Linux-compatible tests that are failing:
+To run all Linux-compatible tests that are failing:
```sh
-xunit.console.netcore.exe *.dll -trait category=failing -notrait category=nonlinuxtests
+<repo-root>/Tools/msbuild.sh <csproj_file> /t:BuildAndTest /p:OSGroup=Linux /p:WithCategories=failing
```
_**A few common examples with the above attributes:**_
-- Run all tests acceptable on Windows:
+- Run all tests acceptable on Windows that are not failing:
```cmd
-xunit.console.netcore.exe *.dll -notrait category=nonwindowstests
+msbuild <csproj_file> /t:BuildAndTest /p:OSGroup=Windows_NT
```
-- Run all inner loop tests acceptable on Linux:
+- Run all outer loop tests acceptable on OS X that are currently associated with active issues:
```sh
-xunit.console.netcore.exe *.dll -notrait category=nonlinuxtests -notrait category=OuterLoop
+<repo-root>/Tools/msbuild.sh <csproj_file> /t:BuildAndTest /p:OSGroup=OSX /p:WithCategories="OuterLoop;failing""
```
-- Run all outer loop tests acceptable on OS X that are not currently associated with active issues:
-```sh
-xunit.console.netcore.exe *.dll -notrait category=nonosxtests -trait category=OuterLoop -notrait category=failing
-```
-- Run all tests acceptable on Linux that are currently associated with active issues:
+
+Alternatively, you can directly invoke the XUnit executable by changing your working directory to the test execution directory at `bin\tests\{OSPlatformConfig)\{Project}.Tests\{TargetGroup}.{TestTFM}\` which is created when the test project is built. For example, the following command runs all Linux-supported inner-loop tests:
```sh
-xunit.console.netcore.exe *.dll -notrait category=nonlinuxtests -trait category=failing
+./corerun xunit.console.netcore.exe <test_dll_file> -notrait category=nonlinuxtests -notrait category=OuterLoop
```
-All the required dlls to run a test project can be found in `bin\tests\{Configration}\{Project}.Tests\netcoreapp1.0\` which should be created when the test project is built.
-
### Code Coverage
Code coverage is built into the corefx build system. It utilizes OpenCover for generating coverage data and ReportGenerator for generating reports about that data. To run:
diff --git a/Documentation/project-docs/issue-guide.md b/Documentation/project-docs/issue-guide.md
index ad7a046a29..00d896874f 100644
--- a/Documentation/project-docs/issue-guide.md
+++ b/Documentation/project-docs/issue-guide.md
@@ -42,8 +42,8 @@ Areas are tracked by labels area-&#42; (e.g. area-System.Collections). Each area
| Area | Owners / experts | Description |
|-----------------------------------------------------------------------------------------------|------------------|-------------|
-| [area-Infrastructure](https://github.com/dotnet/corefx/labels/area-Infrastructure) | [@mellinoe](https://github.com/mellinoe), [@ericstj](https://github.com/ericstj), [@weshaggard](https://github.com/weshaggard) |Covers:<ul><li>Packaging</li><li>Build and test infra</li><li>VS intergation</li></ul><br/>**Pending triage** |
-| [area-Meta](https://github.com/dotnet/corefx/labels/area-Meta) | [@tarekgh](https://github.com/tarekgh) | Issues without clear association to any specific API/contract, e.g. <ul><li>new contract proposals</li><li>cross-cutting code/test pattern changes (e.g. FxCop failures)</li><li>project-wide docs</li></ul> **Pending triage** |
+| [area-Infrastructure](https://github.com/dotnet/corefx/labels/area-Infrastructure) | [@mellinoe](https://github.com/mellinoe), [@ericstj](https://github.com/ericstj), [@weshaggard](https://github.com/weshaggard) |Covers:<ul><li>Packaging</li><li>Build and test infra</li><li>VS intergation</li></ul><br/>**Triage in progress** |
+| [area-Meta](https://github.com/dotnet/corefx/labels/area-Meta) | [@tarekgh](https://github.com/tarekgh) | Issues without clear association to any specific API/contract, e.g. <ul><li>new contract proposals</li><li>cross-cutting code/test pattern changes (e.g. FxCop failures)</li><li>project-wide docs</li></ul> **Triage in progress** |
| [area-Serialization](https://github.com/dotnet/corefx/labels/area-Serialization) | [@shmao](https://github.com/shmao), [@zhenlan](https://github.com/zhenlan) | Packages:<ul><li>System.Runtime.Serialization.Xml</li><li>System.Runtime.Serialization.Json</li><li>System.Private.DataContractSerialization</li><li>System.Xml.XmlSerialization</li></ul> Excluded:<ul><li>System.Runtime.Serialization.Formatters</li></ul> |
| **System contract assemblies** | | |
| [System.AppContext](https://github.com/dotnet/corefx/labels/area-System.AppContext) | [@AlexGhiondea](https://github.com/AlexGhiondea) | | |
@@ -52,43 +52,44 @@ Areas are tracked by labels area-&#42; (e.g. area-System.Collections). Each area
| [System.Collections](https://github.com/dotnet/corefx/labels/area-System.Collections) | [@Priya91](https://github.com/Priya91), [@ianhays](https://github.com/ianhays) | |
| [System.ComponentModel](https://github.com/dotnet/corefx/labels/area-System.ComponentModel) | [@safern](https://github.com/safern), [@AlexGhiondea](https://github.com/AlexGhiondea) | |
| [System.ComponentModel.DataAnnotations](https://github.com/dotnet/corefx/labels/area-System.ComponentModel.DataAnnotations) | [@lajones](https://github.com/lajones), [@divega](https://github.com/divega) | **Pending triage** |
-| [System.Composition](https://github.com/dotnet/corefx/labels/area-System.Composition) | [@AlexGhiondea](https://github.com/AlexGhiondea) | **Pending triage** |
+| [System.Composition](https://github.com/dotnet/corefx/labels/area-System.Composition) | [@AlexGhiondea](https://github.com/AlexGhiondea) | |
+| [System.Configuration](https://github.com/dotnet/corefx/labels/area-System.Configuration) | [@JeremyKuhne](https://github.com/JeremyKuhne) | |
| [System.Console](https://github.com/dotnet/corefx/labels/area-System.Console) | [@ianhays](https://github.com/ianhays) | |
| [System.Data](https://github.com/dotnet/corefx/labels/area-System.Data) | [@saurabh500](https://github.com/saurabh500), [@YoungGah](https://github.com/YoungGah) | |
| [System.Data.SqlClient](https://github.com/dotnet/corefx/labels/area-System.Data.SqlClient) | [@saurabh500](https://github.com/saurabh500), [@YoungGah](https://github.com/YoungGah) | **Pending triage** |
| [System.Diagnostics](https://github.com/dotnet/corefx/labels/area-System.Diagnostics) | [@joperezr](https://github.com/dotnet/joperezr) | |
-| [System.Diagnostics.Process](https://github.com/dotnet/corefx/labels/area-System.Diagnostics.Process) | [@Priya91](https://github.com/Priya91) | **Pending triage** |
+| [System.Diagnostics.Process](https://github.com/dotnet/corefx/labels/area-System.Diagnostics.Process) | [@Priya91](https://github.com/Priya91) | |
| [System.Diagnostics.Tracing](https://github.com/dotnet/corefx/labels/area-System.Diagnostics.Tracing) | | **Pending triage** |
| [System.DirectoryServices](https://github.com/dotnet/corefx/labels/area-System.DirectoryServices) | [@tquerec](https://github.com/tquerec) | |
| [System.Drawing](https://github.com/dotnet/corefx/labels/area-System.Drawing) | [@alexperovich](https://github.com/alexperovich) | |
| [System.Dynamic.Runtime](https://github.com/dotnet/corefx/labels/area-System.Dynamic.Runtime) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | |
| [System.Globalization](https://github.com/dotnet/corefx/labels/area-System.Globalization) | [@krwq](https://github.com/krwq), [@tarekgh](https://github.com/tarekgh) | |
-| [System.IO](https://github.com/dotnet/corefx/labels/area-System.IO) | [@JeremyKhune](https://github.com/JeremyKuhne), [@ianhays](https://github.com/ianhays) | |
+| [System.IO](https://github.com/dotnet/corefx/labels/area-System.IO) | [@JeremyKuhne](https://github.com/JeremyKuhne), [@ianhays](https://github.com/ianhays) | |
| [System.IO.Compression](https://github.com/dotnet/corefx/labels/area-System.IO.Compression) | [@ianhays](https://github.com/ianhays) | |
-| [System.Linq](https://github.com/dotnet/corefx/labels/area-System.Linq) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | **Pending triage** |
-| [System.Linq.Expressions](https://github.com/dotnet/corefx/labels/area-System.Linq.Expressions) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | **Pending triage** |
+| [System.Linq](https://github.com/dotnet/corefx/labels/area-System.Linq) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | |
+| [System.Linq.Expressions](https://github.com/dotnet/corefx/labels/area-System.Linq.Expressions) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | |
| [System.Linq.Parallel](https://github.com/dotnet/corefx/labels/area-System.Linq.Parallel) | [@alexperovich](https://github.com/alexperovich), [@kouvel](https://github.com/kouvel) | |
-| [System.Net](https://github.com/dotnet/corefx/labels/area-System.Net) | | **Pending triage** |
+| [System.Net](https://github.com/dotnet/corefx/labels/area-System.Net) | | **Triage in progress** |
| [System.Numerics](https://github.com/dotnet/corefx/labels/area-System.Numerics) | [@mellinoe](https://github.com/mellinoe) | |
-| [System.Reflection](https://github.com/dotnet/corefx/labels/area-System.Reflection) | | **Pending triage** |
-| [System.Reflection.Emit](https://github.com/dotnet/corefx/labels/area-System.Reflection.Emit) | | **Pending triage** |
+| [System.Reflection](https://github.com/dotnet/corefx/labels/area-System.Reflection) | [@dnlharvey](https://github.com/dnlharvey), [@AtsushiKan](https://github.com/AtsushiKan) | **Pending triage** |
+| [System.Reflection.Emit](https://github.com/dotnet/corefx/labels/area-System.Reflection.Emit) | [@dnlharvey](https://github.com/dnlharvey), [@AtsushiKan](https://github.com/AtsushiKan) | **Pending triage** |
| [System.Reflection.Metadata](https://github.com/dotnet/corefx/labels/area-System.Reflection.Metadata) | [@tmat](https://github.com/tmat), [@nguerrera](https://github.com/nguerrera) | |
| [System.Resources](https://github.com/dotnet/corefx/labels/area-System.Resources) | [@ramarag](https://github.com/ramarag), [@tarekgh](https://github.com/tarekgh) | **Pending triage** |
-| [System.Runtime](https://github.com/dotnet/corefx/labels/area-System.Runtime) | [@AlexGhiondea](https://github.com/AlexGhiondea), [@joperezr](https://github.com/dotnet/joperezr) | Included:<ul><li>System.Runtime.Serialization.Formatters</li><li>System.Runtime.InteropServices.RuntimeInfo</li></ul>Excluded:<ul><li>Path -> System.IO</li><li>StopWatch -> System.Diagnostics</li><li>WebUtility -> System.Net</li></ul> **Pending triage** |
+| [System.Runtime](https://github.com/dotnet/corefx/labels/area-System.Runtime) | [@AlexGhiondea](https://github.com/AlexGhiondea), [@joperezr](https://github.com/dotnet/joperezr) | Included:<ul><li>System.Runtime.Serialization.Formatters</li><li>System.Runtime.InteropServices.RuntimeInfo</li></ul>Excluded:<ul><li>Path -> System.IO</li><li>StopWatch -> System.Diagnostics</li><li>WebUtility -> System.Net</li></ul> |
| [System.Runtime.CompilerServices](https://github.com/dotnet/corefx/labels/area-System.Runtime.CompilerServices) | [@AlexGhiondea](https://github.com/AlexGhiondea), [@joperezr](https://github.com/dotnet/joperezr) | |
| [System.Runtime.Extensions](https://github.com/dotnet/corefx/labels/area-System.Runtime.Extensions) | [@AlexGhiondea](https://github.com/AlexGhiondea), [@joperezr](https://github.com/dotnet/joperezr) | **Pending triage** |
| [System.Runtime.InteropServices](https://github.com/dotnet/corefx/labels/area-System.Runtime.InteropServices) | [@tijoytom](https://github.com/tijoytom), [@yizhang82](https://github.com/yizhang82) | Excluded:<ul><li>System.Runtime.InteropServices.RuntimeInfo</li></ul> |
-| [System.Security](https://github.com/dotnet/corefx/labels/area-System.Security) | [@bartonjs](https://github.com/bartonjs), [@steveharter](https://github.com/steveharter) | **Pending triage** |
+| [System.Security](https://github.com/dotnet/corefx/labels/area-System.Security) | [@bartonjs](https://github.com/bartonjs), [@steveharter](https://github.com/steveharter) | |
| System.ServiceModel | N/A | [dotnet/wcf](https://github.com/dotnet/wcf) |
| [System.ServiceProcess](https://github.com/dotnet/corefx/labels/area-System.ServiceProcess) | [@Priya91](https://github.com/Priya91) | |
| [System.Text.Encoding](https://github.com/dotnet/corefx/labels/area-System.Text.Encoding) | [@krwq](https://github.com/krwq), [@tarekgh](https://github.com/tarekgh) | |
-| [System.Text.RegularExpressions](https://github.com/dotnet/corefx/labels/area-System.Text.RegularExpressions) | [@Priya91](https://github.com/Priya91) | **Pending triage** |
+| [System.Text.RegularExpressions](https://github.com/dotnet/corefx/labels/area-System.Text.RegularExpressions) | [@Priya91](https://github.com/Priya91) | |
| [System.Threading](https://github.com/dotnet/corefx/labels/area-System.Threading) | [@kouvel](https://github.com/kouvel), [@alexperovich](https://github.com/alexperovich) | |
| [System.Transactions](https://github.com/dotnet/corefx/labels/area-System.Transactions) | [@jimcarley](https://github.com/jimcarley), [@qizhanMS](https://github.com/qizhanMS), [@dmetzgar](https://github.com/dmetzgar) | |
| [System.Xml](https://github.com/dotnet/corefx/labels/area-System.Xml) | [@sepidehMS](https://github.com/sepidehMS), [@krwq](https://github.com/krwq) | |
| **Microsoft contract assemblies** | | |
-| [Microsoft.CSharp](https://github.com/dotnet/corefx/labels/area-Microsoft.CSharp) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | **Pending triage** |
-| [Microsoft.VisualBasic](https://github.com/dotnet/corefx/labels/area-Microsoft.VisualBasic) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | **Pending triage** |
+| [Microsoft.CSharp](https://github.com/dotnet/corefx/labels/area-Microsoft.CSharp) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | |
+| [Microsoft.VisualBasic](https://github.com/dotnet/corefx/labels/area-Microsoft.VisualBasic) | [@VSadov](https://github.com/VSadov), [@OmarTawfik](https://github.com/OmarTawfik) | |
| [Microsoft.Win32](https://github.com/dotnet/corefx/labels/area-Microsoft.Win32) | [@sepidehMS](https://github.com/sepidehMS) | |
diff --git a/Packaging.props b/Packaging.props
index 182ccd7379..8b89c9054f 100644
--- a/Packaging.props
+++ b/Packaging.props
@@ -61,5 +61,11 @@
Include="$(SyncInfoFile)" >
<SkipPackageFileCheck>true</SkipPackageFileCheck>
</File>
+
+ <!-- Add a marker to help the designer optimize & share .NET Core packages -->
+ <File Condition="'$(IncludeDesignerMarker)' != 'false'"
+ Include="$(ProjectDir)pkg/useSharedDesignerContext.txt">
+ <SkipPackageFileCheck>true</SkipPackageFileCheck>
+ </File>
</ItemGroup>
</Project>
diff --git a/PinvokeAnalyzer_OneCoreApis.txt b/PinvokeAnalyzer_OneCoreApis.txt
deleted file mode 100644
index b08e728dea..0000000000
--- a/PinvokeAnalyzer_OneCoreApis.txt
+++ /dev/null
@@ -1,7275 +0,0 @@
-ntdll.dll!RtlActivateActivationContextUnsafeFast
-ntdll.dll!RtlDeactivateActivationContextUnsafeFast
-ntdll.dll!RtlInterlockedPushListSList
-ntdll.dll!RtlUlongByteSwap
-ntdll.dll!RtlUlonglongByteSwap
-ntdll.dll!RtlUshortByteSwap
-ntdll.dll!AlpcAdjustCompletionListConcurrencyCount
-ntdll.dll!AlpcFreeCompletionListMessage
-ntdll.dll!AlpcGetCompletionListLastMessageInformation
-ntdll.dll!AlpcGetCompletionListMessageAttributes
-ntdll.dll!AlpcGetHeaderSize
-ntdll.dll!AlpcGetMessageAttribute
-ntdll.dll!AlpcGetMessageFromCompletionList
-ntdll.dll!AlpcGetOutstandingCompletionListMessageCount
-ntdll.dll!AlpcInitializeMessageAttribute
-ntdll.dll!AlpcMaxAllowedMessageLength
-ntdll.dll!AlpcRegisterCompletionList
-ntdll.dll!AlpcRegisterCompletionListWorkerThread
-ntdll.dll!AlpcRundownCompletionList
-ntdll.dll!AlpcUnregisterCompletionList
-ntdll.dll!AlpcUnregisterCompletionListWorkerThread
-ntdll.dll!CsrAllocateCaptureBuffer
-ntdll.dll!CsrAllocateMessagePointer
-ntdll.dll!CsrCaptureMessageBuffer
-ntdll.dll!CsrCaptureMessageMultiUnicodeStringsInPlace
-ntdll.dll!CsrCaptureMessageString
-ntdll.dll!CsrCaptureTimeout
-ntdll.dll!CsrClientCallServer
-ntdll.dll!CsrClientConnectToServer
-ntdll.dll!CsrFreeCaptureBuffer
-ntdll.dll!CsrGetProcessId
-ntdll.dll!CsrIdentifyAlertableThread
-ntdll.dll!CsrSetPriorityClass
-ntdll.dll!CsrVerifyRegion
-ntdll.dll!DbgBreakPoint
-ntdll.dll!DbgPrint
-ntdll.dll!DbgPrintEx
-ntdll.dll!DbgPrintReturnControlC
-ntdll.dll!DbgPrompt
-ntdll.dll!DbgQueryDebugFilterState
-ntdll.dll!DbgSetDebugFilterState
-ntdll.dll!DbgUiConnectToDbg
-ntdll.dll!DbgUiContinue
-ntdll.dll!DbgUiConvertStateChangeStructure
-ntdll.dll!DbgUiConvertStateChangeStructureEx
-ntdll.dll!DbgUiDebugActiveProcess
-ntdll.dll!DbgUiGetThreadDebugObject
-ntdll.dll!DbgUiIssueRemoteBreakin
-ntdll.dll!DbgUiRemoteBreakin
-ntdll.dll!DbgUiSetThreadDebugObject
-ntdll.dll!DbgUiStopDebugging
-ntdll.dll!DbgUiWaitStateChange
-ntdll.dll!DbgUserBreakPoint
-ntdll.dll!EtwCreateTraceInstanceId
-ntdll.dll!EtwDeliverDataBlock
-ntdll.dll!EtwEnumerateProcessRegGuids
-ntdll.dll!EtwEventActivityIdControl
-ntdll.dll!EtwEventEnabled
-ntdll.dll!EtwEventProviderEnabled
-ntdll.dll!EtwEventRegister
-ntdll.dll!EtwEventSetInformation
-ntdll.dll!EtwEventUnregister
-ntdll.dll!EtwEventWrite
-ntdll.dll!EtwEventWriteEndScenario
-ntdll.dll!EtwEventWriteEx
-ntdll.dll!EtwEventWriteFull
-ntdll.dll!EtwEventWriteNoRegistration
-ntdll.dll!EtwEventWriteStartScenario
-ntdll.dll!EtwEventWriteString
-ntdll.dll!EtwEventWriteTransfer
-ntdll.dll!EtwGetTraceEnableFlags
-ntdll.dll!EtwGetTraceEnableLevel
-ntdll.dll!EtwGetTraceLoggerHandle
-ntdll.dll!EtwLogTraceEvent
-ntdll.dll!EtwNotificationRegister
-ntdll.dll!EtwNotificationUnregister
-ntdll.dll!EtwProcessPrivateLoggerRequest
-ntdll.dll!EtwRegisterSecurityProvider
-ntdll.dll!EtwRegisterTraceGuidsA
-ntdll.dll!EtwRegisterTraceGuidsW
-ntdll.dll!EtwReplyNotification
-ntdll.dll!EtwSendNotification
-ntdll.dll!EtwTraceEventInstance
-ntdll.dll!EtwTraceMessage
-ntdll.dll!EtwTraceMessageVa
-ntdll.dll!EtwUnregisterTraceGuids
-ntdll.dll!EtwWriteUMSecurityEvent
-ntdll.dll!EtwpCreateEtwThread
-ntdll.dll!EtwpGetCpuSpeed
-ntdll.dll!EvtIntReportAuthzEventAndSourceAsync
-ntdll.dll!EvtIntReportEventAndSourceAsync
-ntdll.dll!LdrAccessResource
-ntdll.dll!LdrAddDllDirectory
-ntdll.dll!LdrAddLoadAsDataTable
-ntdll.dll!LdrAddRefDll
-ntdll.dll!LdrAppxHandleIntegrityFailure
-ntdll.dll!LdrDisableThreadCalloutsForDll
-ntdll.dll!LdrEnumResources
-ntdll.dll!LdrEnumerateLoadedModules
-ntdll.dll!LdrFastFailInLoaderCallout
-ntdll.dll!LdrFindEntryForAddress
-ntdll.dll!LdrFindResourceDirectory_U
-ntdll.dll!LdrFindResourceEx_U
-ntdll.dll!LdrFindResource_U
-ntdll.dll!LdrFlushAlternateResourceModules
-ntdll.dll!LdrGetDllDirectory
-ntdll.dll!LdrGetDllFullName
-ntdll.dll!LdrGetDllHandle
-ntdll.dll!LdrGetDllHandleByMapping
-ntdll.dll!LdrGetDllHandleByName
-ntdll.dll!LdrGetDllHandleEx
-ntdll.dll!LdrGetDllPath
-ntdll.dll!LdrGetFileNameFromLoadAsDataTable
-ntdll.dll!LdrGetProcedureAddress
-ntdll.dll!LdrGetProcedureAddressEx
-ntdll.dll!LdrGetProcedureAddressForCaller
-ntdll.dll!LdrInitShimEngineDynamic
-ntdll.dll!LdrLoadAlternateResourceModule
-ntdll.dll!LdrLoadAlternateResourceModuleEx
-ntdll.dll!LdrLoadDll
-ntdll.dll!LdrLockLoaderLock
-ntdll.dll!LdrOpenImageFileOptionsKey
-ntdll.dll!LdrProcessRelocationBlock
-ntdll.dll!LdrProcessRelocationBlockEx
-ntdll.dll!LdrQueryImageFileExecutionOptions
-ntdll.dll!LdrQueryImageFileExecutionOptionsEx
-ntdll.dll!LdrQueryImageFileKeyOption
-ntdll.dll!LdrQueryModuleServiceTags
-ntdll.dll!LdrQueryOptionalDelayLoadedAPI
-ntdll.dll!LdrQueryProcessModuleInformation
-ntdll.dll!LdrRemoveDllDirectory
-ntdll.dll!LdrRemoveLoadAsDataTable
-ntdll.dll!LdrResFindResource
-ntdll.dll!LdrResFindResourceDirectory
-ntdll.dll!LdrResRelease
-ntdll.dll!LdrResSearchResource
-ntdll.dll!LdrResolveDelayLoadedAPI
-ntdll.dll!LdrResolveDelayLoadsFromDll
-ntdll.dll!LdrSetAppCompatDllRedirectionCallback
-ntdll.dll!LdrSetDefaultDllDirectories
-ntdll.dll!LdrSetDllDirectory
-ntdll.dll!LdrSetDllManifestProber
-ntdll.dll!LdrSetMUICacheType
-ntdll.dll!LdrShutdownProcess
-ntdll.dll!LdrShutdownThread
-ntdll.dll!LdrSystemDllInitBlock
-ntdll.dll!LdrUnloadAlternateResourceModule
-ntdll.dll!LdrUnloadAlternateResourceModuleEx
-ntdll.dll!LdrUnloadDll
-ntdll.dll!LdrUnlockLoaderLock
-ntdll.dll!LdrVerifyImageMatchesChecksum
-ntdll.dll!LdrVerifyImageMatchesChecksumEx
-ntdll.dll!LdrpResGetMappingSize
-ntdll.dll!LdrpResGetResourceDirectory
-ntdll.dll!NlsAnsiCodePage
-ntdll.dll!NlsMbCodePageTag
-ntdll.dll!NlsMbOemCodePageTag
-ntdll.dll!NtAcceptConnectPort
-ntdll.dll!NtAccessCheck
-ntdll.dll!NtAccessCheckAndAuditAlarm
-ntdll.dll!NtAccessCheckByType
-ntdll.dll!NtAccessCheckByTypeAndAuditAlarm
-ntdll.dll!NtAccessCheckByTypeResultList
-ntdll.dll!NtAccessCheckByTypeResultListAndAuditAlarm
-ntdll.dll!NtAccessCheckByTypeResultListAndAuditAlarmByHandle
-ntdll.dll!NtAddAtom
-ntdll.dll!NtAddAtomEx
-ntdll.dll!NtAddBootEntry
-ntdll.dll!NtAddDriverEntry
-ntdll.dll!NtAdjustGroupsToken
-ntdll.dll!NtAdjustPrivilegesToken
-ntdll.dll!NtAdjustTokenClaimsAndDeviceGroups
-ntdll.dll!NtAlertResumeThread
-ntdll.dll!NtAlertThread
-ntdll.dll!NtAlertThreadByThreadId
-ntdll.dll!NtAllocateLocallyUniqueId
-ntdll.dll!NtAllocateReserveObject
-ntdll.dll!NtAllocateUserPhysicalPages
-ntdll.dll!NtAllocateUuids
-ntdll.dll!NtAllocateVirtualMemory
-ntdll.dll!NtAlpcAcceptConnectPort
-ntdll.dll!NtAlpcCancelMessage
-ntdll.dll!NtAlpcConnectPort
-ntdll.dll!NtAlpcConnectPortEx
-ntdll.dll!NtAlpcCreatePort
-ntdll.dll!NtAlpcCreatePortSection
-ntdll.dll!NtAlpcCreateResourceReserve
-ntdll.dll!NtAlpcCreateSectionView
-ntdll.dll!NtAlpcCreateSecurityContext
-ntdll.dll!NtAlpcDeletePortSection
-ntdll.dll!NtAlpcDeleteResourceReserve
-ntdll.dll!NtAlpcDeleteSectionView
-ntdll.dll!NtAlpcDeleteSecurityContext
-ntdll.dll!NtAlpcDisconnectPort
-ntdll.dll!NtAlpcImpersonateClientContainerOfPort
-ntdll.dll!NtAlpcImpersonateClientOfPort
-ntdll.dll!NtAlpcOpenSenderProcess
-ntdll.dll!NtAlpcOpenSenderThread
-ntdll.dll!NtAlpcQueryInformation
-ntdll.dll!NtAlpcQueryInformationMessage
-ntdll.dll!NtAlpcRevokeSecurityContext
-ntdll.dll!NtAlpcSendWaitReceivePort
-ntdll.dll!NtAlpcSetInformation
-ntdll.dll!NtApphelpCacheControl
-ntdll.dll!NtAreMappedFilesTheSame
-ntdll.dll!NtAssignProcessToJobObject
-ntdll.dll!NtAssociateWaitCompletionPacket
-ntdll.dll!NtCallbackReturn
-ntdll.dll!NtCancelIoFile
-ntdll.dll!NtCancelIoFileEx
-ntdll.dll!NtCancelSynchronousIoFile
-ntdll.dll!NtCancelTimer2
-ntdll.dll!NtCancelTimer
-ntdll.dll!NtCancelWaitCompletionPacket
-ntdll.dll!NtClearEvent
-ntdll.dll!NtClose
-ntdll.dll!NtCloseObjectAuditAlarm
-ntdll.dll!NtCommitComplete
-ntdll.dll!NtCommitEnlistment
-ntdll.dll!NtCommitTransaction
-ntdll.dll!NtCompactKeys
-ntdll.dll!NtCompareObjects
-ntdll.dll!NtCompareTokens
-ntdll.dll!NtCompleteConnectPort
-ntdll.dll!NtCompressKey
-ntdll.dll!NtConnectPort
-ntdll.dll!NtContinue
-ntdll.dll!NtCreateDebugObject
-ntdll.dll!NtCreateDirectoryObject
-ntdll.dll!NtCreateDirectoryObjectEx
-ntdll.dll!NtCreateEnlistment
-ntdll.dll!NtCreateEvent
-ntdll.dll!NtCreateEventPair
-ntdll.dll!NtCreateFile
-ntdll.dll!NtCreateIRTimer
-ntdll.dll!NtCreateIoCompletion
-ntdll.dll!NtCreateJobObject
-ntdll.dll!NtCreateJobSet
-ntdll.dll!NtCreateKey
-ntdll.dll!NtCreateKeyTransacted
-ntdll.dll!NtCreateKeyedEvent
-ntdll.dll!NtCreateLowBoxToken
-ntdll.dll!NtCreateMailslotFile
-ntdll.dll!NtCreateMutant
-ntdll.dll!NtCreateNamedPipeFile
-ntdll.dll!NtCreatePagingFile
-ntdll.dll!NtCreatePartition
-ntdll.dll!NtCreatePort
-ntdll.dll!NtCreatePrivateNamespace
-ntdll.dll!NtCreateProcess
-ntdll.dll!NtCreateProcessEx
-ntdll.dll!NtCreateProfile
-ntdll.dll!NtCreateProfileEx
-ntdll.dll!NtCreateResourceManager
-ntdll.dll!NtCreateSection
-ntdll.dll!NtCreateSemaphore
-ntdll.dll!NtCreateSymbolicLinkObject
-ntdll.dll!NtCreateThread
-ntdll.dll!NtCreateThreadEx
-ntdll.dll!NtCreateTimer2
-ntdll.dll!NtCreateTimer
-ntdll.dll!NtCreateToken
-ntdll.dll!NtCreateTokenEx
-ntdll.dll!NtCreateTransaction
-ntdll.dll!NtCreateTransactionManager
-ntdll.dll!NtCreateUserProcess
-ntdll.dll!NtCreateWaitCompletionPacket
-ntdll.dll!NtCreateWaitablePort
-ntdll.dll!NtCreateWnfStateName
-ntdll.dll!NtCreateWorkerFactory
-ntdll.dll!NtCurrentTeb
-ntdll.dll!NtDebugActiveProcess
-ntdll.dll!NtDebugContinue
-ntdll.dll!NtDelayExecution
-ntdll.dll!NtDeleteAtom
-ntdll.dll!NtDeleteBootEntry
-ntdll.dll!NtDeleteDriverEntry
-ntdll.dll!NtDeleteFile
-ntdll.dll!NtDeleteKey
-ntdll.dll!NtDeleteObjectAuditAlarm
-ntdll.dll!NtDeletePrivateNamespace
-ntdll.dll!NtDeleteValueKey
-ntdll.dll!NtDeleteWnfStateData
-ntdll.dll!NtDeleteWnfStateName
-ntdll.dll!NtDeviceIoControlFile
-ntdll.dll!NtDisableLastKnownGood
-ntdll.dll!NtDisplayString
-ntdll.dll!NtDrawText
-ntdll.dll!NtDuplicateObject
-ntdll.dll!NtDuplicateToken
-ntdll.dll!NtEnableLastKnownGood
-ntdll.dll!NtEnumerateBootEntries
-ntdll.dll!NtEnumerateDriverEntries
-ntdll.dll!NtEnumerateKey
-ntdll.dll!NtEnumerateSystemEnvironmentValuesEx
-ntdll.dll!NtEnumerateTransactionObject
-ntdll.dll!NtEnumerateValueKey
-ntdll.dll!NtExtendSection
-ntdll.dll!NtFilterBootOption
-ntdll.dll!NtFilterToken
-ntdll.dll!NtFilterTokenEx
-ntdll.dll!NtFindAtom
-ntdll.dll!NtFlushBuffersFile
-ntdll.dll!NtFlushBuffersFileEx
-ntdll.dll!NtFlushInstallUILanguage
-ntdll.dll!NtFlushInstructionCache
-ntdll.dll!NtFlushKey
-ntdll.dll!NtFlushProcessWriteBuffers
-ntdll.dll!NtFlushVirtualMemory
-ntdll.dll!NtFlushWriteBuffer
-ntdll.dll!NtFreeUserPhysicalPages
-ntdll.dll!NtFreeVirtualMemory
-ntdll.dll!NtFreezeRegistry
-ntdll.dll!NtFreezeTransactions
-ntdll.dll!NtFsControlFile
-ntdll.dll!NtGetCachedSigningLevel
-ntdll.dll!NtGetCompleteWnfStateSubscription
-ntdll.dll!NtGetContextThread
-ntdll.dll!NtGetCurrentProcessorNumber
-ntdll.dll!NtGetCurrentProcessorNumberEx
-ntdll.dll!NtGetDevicePowerState
-ntdll.dll!NtGetMUIRegistryInfo
-ntdll.dll!NtGetNextProcess
-ntdll.dll!NtGetNextThread
-ntdll.dll!NtGetNlsSectionPtr
-ntdll.dll!NtGetNotificationResourceManager
-ntdll.dll!NtGetTickCount
-ntdll.dll!NtGetWriteWatch
-ntdll.dll!NtImpersonateAnonymousToken
-ntdll.dll!NtImpersonateClientOfPort
-ntdll.dll!NtImpersonateThread
-ntdll.dll!NtInitializeNlsFiles
-ntdll.dll!NtInitializeRegistry
-ntdll.dll!NtInitiatePowerAction
-ntdll.dll!NtIsProcessInJob
-ntdll.dll!NtIsSystemResumeAutomatic
-ntdll.dll!NtIsUILanguageComitted
-ntdll.dll!NtListenPort
-ntdll.dll!NtLoadDriver
-ntdll.dll!NtLoadKey2
-ntdll.dll!NtLoadKey
-ntdll.dll!NtLoadKeyEx
-ntdll.dll!NtLockFile
-ntdll.dll!NtLockProductActivationKeys
-ntdll.dll!NtLockRegistryKey
-ntdll.dll!NtLockVirtualMemory
-ntdll.dll!NtMakePermanentObject
-ntdll.dll!NtMakeTemporaryObject
-ntdll.dll!NtManagePartition
-ntdll.dll!NtMapCMFModule
-ntdll.dll!NtMapUserPhysicalPages
-ntdll.dll!NtMapUserPhysicalPagesScatter
-ntdll.dll!NtMapViewOfSection
-ntdll.dll!NtModifyBootEntry
-ntdll.dll!NtModifyDriverEntry
-ntdll.dll!NtNotifyChangeDirectoryFile
-ntdll.dll!NtNotifyChangeKey
-ntdll.dll!NtNotifyChangeMultipleKeys
-ntdll.dll!NtNotifyChangeSession
-ntdll.dll!NtOpenDirectoryObject
-ntdll.dll!NtOpenEnlistment
-ntdll.dll!NtOpenEvent
-ntdll.dll!NtOpenEventPair
-ntdll.dll!NtOpenFile
-ntdll.dll!NtOpenIoCompletion
-ntdll.dll!NtOpenJobObject
-ntdll.dll!NtOpenKey
-ntdll.dll!NtOpenKeyEx
-ntdll.dll!NtOpenKeyTransacted
-ntdll.dll!NtOpenKeyTransactedEx
-ntdll.dll!NtOpenKeyedEvent
-ntdll.dll!NtOpenMutant
-ntdll.dll!NtOpenObjectAuditAlarm
-ntdll.dll!NtOpenPartition
-ntdll.dll!NtOpenPrivateNamespace
-ntdll.dll!NtOpenProcess
-ntdll.dll!NtOpenProcessToken
-ntdll.dll!NtOpenProcessTokenEx
-ntdll.dll!NtOpenResourceManager
-ntdll.dll!NtOpenSection
-ntdll.dll!NtOpenSemaphore
-ntdll.dll!NtOpenSession
-ntdll.dll!NtOpenSymbolicLinkObject
-ntdll.dll!NtOpenThread
-ntdll.dll!NtOpenThreadToken
-ntdll.dll!NtOpenThreadTokenEx
-ntdll.dll!NtOpenTimer
-ntdll.dll!NtOpenTransaction
-ntdll.dll!NtOpenTransactionManager
-ntdll.dll!NtPlugPlayControl
-ntdll.dll!NtPowerInformation
-ntdll.dll!NtPrePrepareComplete
-ntdll.dll!NtPrePrepareEnlistment
-ntdll.dll!NtPrepareComplete
-ntdll.dll!NtPrepareEnlistment
-ntdll.dll!NtPrivilegeCheck
-ntdll.dll!NtPrivilegeObjectAuditAlarm
-ntdll.dll!NtPrivilegedServiceAuditAlarm
-ntdll.dll!NtPropagationComplete
-ntdll.dll!NtPropagationFailed
-ntdll.dll!NtProtectVirtualMemory
-ntdll.dll!NtPulseEvent
-ntdll.dll!NtQueryAttributesFile
-ntdll.dll!NtQueryBootEntryOrder
-ntdll.dll!NtQueryBootOptions
-ntdll.dll!NtQueryDebugFilterState
-ntdll.dll!NtQueryDefaultLocale
-ntdll.dll!NtQueryDefaultUILanguage
-ntdll.dll!NtQueryDirectoryFile
-ntdll.dll!NtQueryDirectoryObject
-ntdll.dll!NtQueryDriverEntryOrder
-ntdll.dll!NtQueryEaFile
-ntdll.dll!NtQueryEvent
-ntdll.dll!NtQueryFullAttributesFile
-ntdll.dll!NtQueryInformationAtom
-ntdll.dll!NtQueryInformationEnlistment
-ntdll.dll!NtQueryInformationFile
-ntdll.dll!NtQueryInformationJobObject
-ntdll.dll!NtQueryInformationPort
-ntdll.dll!NtQueryInformationProcess
-ntdll.dll!NtQueryInformationResourceManager
-ntdll.dll!NtQueryInformationThread
-ntdll.dll!NtQueryInformationToken
-ntdll.dll!NtQueryInformationTransaction
-ntdll.dll!NtQueryInformationTransactionManager
-ntdll.dll!NtQueryInformationWorkerFactory
-ntdll.dll!NtQueryInstallUILanguage
-ntdll.dll!NtQueryIntervalProfile
-ntdll.dll!NtQueryIoCompletion
-ntdll.dll!NtQueryKey
-ntdll.dll!NtQueryLicenseValue
-ntdll.dll!NtQueryMultipleValueKey
-ntdll.dll!NtQueryMutant
-ntdll.dll!NtQueryObject
-ntdll.dll!NtQueryOpenSubKeys
-ntdll.dll!NtQueryOpenSubKeysEx
-ntdll.dll!NtQueryPerformanceCounter
-ntdll.dll!NtQueryPortInformationProcess
-ntdll.dll!NtQueryQuotaInformationFile
-ntdll.dll!NtQuerySection
-ntdll.dll!NtQuerySecurityAttributesToken
-ntdll.dll!NtQuerySecurityObject
-ntdll.dll!NtQuerySemaphore
-ntdll.dll!NtQuerySymbolicLinkObject
-ntdll.dll!NtQuerySystemEnvironmentValue
-ntdll.dll!NtQuerySystemEnvironmentValueEx
-ntdll.dll!NtQuerySystemInformation
-ntdll.dll!NtQuerySystemInformationEx
-ntdll.dll!NtQuerySystemTime
-ntdll.dll!NtQueryTimer
-ntdll.dll!NtQueryTimerResolution
-ntdll.dll!NtQueryValueKey
-ntdll.dll!NtQueryVirtualMemory
-ntdll.dll!NtQueryVolumeInformationFile
-ntdll.dll!NtQueryWnfStateData
-ntdll.dll!NtQueryWnfStateNameInformation
-ntdll.dll!NtQueueApcThread
-ntdll.dll!NtQueueApcThreadEx
-ntdll.dll!NtRaiseException
-ntdll.dll!NtRaiseHardError
-ntdll.dll!NtReadFile
-ntdll.dll!NtReadFileScatter
-ntdll.dll!NtReadOnlyEnlistment
-ntdll.dll!NtReadRequestData
-ntdll.dll!NtReadVirtualMemory
-ntdll.dll!NtRecoverEnlistment
-ntdll.dll!NtRecoverResourceManager
-ntdll.dll!NtRecoverTransactionManager
-ntdll.dll!NtRegisterProtocolAddressInformation
-ntdll.dll!NtRegisterThreadTerminatePort
-ntdll.dll!NtReleaseKeyedEvent
-ntdll.dll!NtReleaseMutant
-ntdll.dll!NtReleaseSemaphore
-ntdll.dll!NtReleaseWorkerFactoryWorker
-ntdll.dll!NtRemoveIoCompletion
-ntdll.dll!NtRemoveIoCompletionEx
-ntdll.dll!NtRemoveProcessDebug
-ntdll.dll!NtRenameKey
-ntdll.dll!NtRenameTransactionManager
-ntdll.dll!NtReplaceKey
-ntdll.dll!NtReplacePartitionUnit
-ntdll.dll!NtReplyPort
-ntdll.dll!NtReplyWaitReceivePort
-ntdll.dll!NtReplyWaitReceivePortEx
-ntdll.dll!NtReplyWaitReplyPort
-ntdll.dll!NtRequestPort
-ntdll.dll!NtRequestWaitReplyPort
-ntdll.dll!NtResetEvent
-ntdll.dll!NtResetWriteWatch
-ntdll.dll!NtRestoreKey
-ntdll.dll!NtResumeProcess
-ntdll.dll!NtResumeThread
-ntdll.dll!NtRevertContainerImpersonation
-ntdll.dll!NtRollbackComplete
-ntdll.dll!NtRollbackEnlistment
-ntdll.dll!NtRollbackTransaction
-ntdll.dll!NtRollforwardTransactionManager
-ntdll.dll!NtSaveKey
-ntdll.dll!NtSaveKeyEx
-ntdll.dll!NtSaveMergedKeys
-ntdll.dll!NtSecureConnectPort
-ntdll.dll!NtSerializeBoot
-ntdll.dll!NtSetBootEntryOrder
-ntdll.dll!NtSetBootOptions
-ntdll.dll!NtSetCachedSigningLevel
-ntdll.dll!NtSetContextThread
-ntdll.dll!NtSetDebugFilterState
-ntdll.dll!NtSetDefaultHardErrorPort
-ntdll.dll!NtSetDefaultLocale
-ntdll.dll!NtSetDefaultUILanguage
-ntdll.dll!NtSetDriverEntryOrder
-ntdll.dll!NtSetEaFile
-ntdll.dll!NtSetEvent
-ntdll.dll!NtSetEventBoostPriority
-ntdll.dll!NtSetHighEventPair
-ntdll.dll!NtSetHighWaitLowEventPair
-ntdll.dll!NtSetIRTimer
-ntdll.dll!NtSetInformationDebugObject
-ntdll.dll!NtSetInformationEnlistment
-ntdll.dll!NtSetInformationFile
-ntdll.dll!NtSetInformationJobObject
-ntdll.dll!NtSetInformationKey
-ntdll.dll!NtSetInformationObject
-ntdll.dll!NtSetInformationProcess
-ntdll.dll!NtSetInformationResourceManager
-ntdll.dll!NtSetInformationSymbolicLink
-ntdll.dll!NtSetInformationThread
-ntdll.dll!NtSetInformationToken
-ntdll.dll!NtSetInformationTransaction
-ntdll.dll!NtSetInformationTransactionManager
-ntdll.dll!NtSetInformationVirtualMemory
-ntdll.dll!NtSetInformationWorkerFactory
-ntdll.dll!NtSetIntervalProfile
-ntdll.dll!NtSetIoCompletion
-ntdll.dll!NtSetIoCompletionEx
-ntdll.dll!NtSetLdtEntries
-ntdll.dll!NtSetLowEventPair
-ntdll.dll!NtSetLowWaitHighEventPair
-ntdll.dll!NtSetQuotaInformationFile
-ntdll.dll!NtSetSecurityObject
-ntdll.dll!NtSetSystemEnvironmentValue
-ntdll.dll!NtSetSystemEnvironmentValueEx
-ntdll.dll!NtSetSystemInformation
-ntdll.dll!NtSetSystemPowerState
-ntdll.dll!NtSetSystemTime
-ntdll.dll!NtSetThreadExecutionState
-ntdll.dll!NtSetTimer2
-ntdll.dll!NtSetTimer
-ntdll.dll!NtSetTimerEx
-ntdll.dll!NtSetTimerResolution
-ntdll.dll!NtSetUuidSeed
-ntdll.dll!NtSetValueKey
-ntdll.dll!NtSetVolumeInformationFile
-ntdll.dll!NtSetWnfProcessNotificationEvent
-ntdll.dll!NtShutdownSystem
-ntdll.dll!NtShutdownWorkerFactory
-ntdll.dll!NtSignalAndWaitForSingleObject
-ntdll.dll!NtSinglePhaseReject
-ntdll.dll!NtStartProfile
-ntdll.dll!NtStopProfile
-ntdll.dll!NtSubscribeWnfStateChange
-ntdll.dll!NtSuspendProcess
-ntdll.dll!NtSuspendThread
-ntdll.dll!NtSystemDebugControl
-ntdll.dll!NtTerminateJobObject
-ntdll.dll!NtTerminateProcess
-ntdll.dll!NtTerminateThread
-ntdll.dll!NtTestAlert
-ntdll.dll!NtThawRegistry
-ntdll.dll!NtThawTransactions
-ntdll.dll!NtTraceControl
-ntdll.dll!NtTraceEvent
-ntdll.dll!NtTranslateFilePath
-ntdll.dll!NtUmsThreadYield
-ntdll.dll!NtUnloadDriver
-ntdll.dll!NtUnloadKey2
-ntdll.dll!NtUnloadKey
-ntdll.dll!NtUnloadKeyEx
-ntdll.dll!NtUnlockFile
-ntdll.dll!NtUnlockVirtualMemory
-ntdll.dll!NtUnmapViewOfSection
-ntdll.dll!NtUnmapViewOfSectionEx
-ntdll.dll!NtUnsubscribeWnfStateChange
-ntdll.dll!NtUpdateWnfStateData
-ntdll.dll!NtVdmControl
-ntdll.dll!NtWaitForAlertByThreadId
-ntdll.dll!NtWaitForDebugEvent
-ntdll.dll!NtWaitForKeyedEvent
-ntdll.dll!NtWaitForMultipleObjects32
-ntdll.dll!NtWaitForMultipleObjects
-ntdll.dll!NtWaitForSingleObject
-ntdll.dll!NtWaitForWorkViaWorkerFactory
-ntdll.dll!NtWaitHighEventPair
-ntdll.dll!NtWaitLowEventPair
-ntdll.dll!NtWorkerFactoryWorkerReady
-ntdll.dll!NtWriteFile
-ntdll.dll!NtWriteFileGather
-ntdll.dll!NtWriteRequestData
-ntdll.dll!NtWriteVirtualMemory
-ntdll.dll!NtYieldExecution
-ntdll.dll!PfxFindPrefix
-ntdll.dll!PfxInitialize
-ntdll.dll!PfxInsertPrefix
-ntdll.dll!PfxRemovePrefix
-ntdll.dll!PssNtCaptureSnapshot
-ntdll.dll!PssNtDuplicateSnapshot
-ntdll.dll!PssNtFreeRemoteSnapshot
-ntdll.dll!PssNtFreeSnapshot
-ntdll.dll!PssNtFreeWalkMarker
-ntdll.dll!PssNtQuerySnapshot
-ntdll.dll!PssNtValidateDescriptor
-ntdll.dll!PssNtWalkSnapshot
-ntdll.dll!RtlAbortRXact
-ntdll.dll!RtlAbsoluteToSelfRelativeSD
-ntdll.dll!RtlAcquirePebLock
-ntdll.dll!RtlAcquirePrivilege
-ntdll.dll!RtlAcquireReleaseSRWLockExclusive
-ntdll.dll!RtlAcquireResourceExclusive
-ntdll.dll!RtlAcquireResourceShared
-ntdll.dll!RtlAcquireSRWLockExclusive
-ntdll.dll!RtlAcquireSRWLockShared
-ntdll.dll!RtlActivateActivationContext
-ntdll.dll!RtlActivateActivationContextEx
-ntdll.dll!RtlAddAccessAllowedAce
-ntdll.dll!RtlAddAccessAllowedAceEx
-ntdll.dll!RtlAddAccessAllowedObjectAce
-ntdll.dll!RtlAddAccessDeniedAce
-ntdll.dll!RtlAddAccessDeniedAceEx
-ntdll.dll!RtlAddAccessDeniedObjectAce
-ntdll.dll!RtlAddAce
-ntdll.dll!RtlAddActionToRXact
-ntdll.dll!RtlAddAtomToAtomTable
-ntdll.dll!RtlAddAttributeActionToRXact
-ntdll.dll!RtlAddAuditAccessAce
-ntdll.dll!RtlAddAuditAccessAceEx
-ntdll.dll!RtlAddAuditAccessObjectAce
-ntdll.dll!RtlAddIntegrityLabelToBoundaryDescriptor
-ntdll.dll!RtlAddMandatoryAce
-ntdll.dll!RtlAddProcessTrustLabelAce
-ntdll.dll!RtlAddRefActivationContext
-ntdll.dll!RtlAddResourceAttributeAce
-ntdll.dll!RtlAddSIDToBoundaryDescriptor
-ntdll.dll!RtlAddScopedPolicyIDAce
-ntdll.dll!RtlAddVectoredContinueHandler
-ntdll.dll!RtlAddVectoredExceptionHandler
-ntdll.dll!RtlAddressInSectionTable
-ntdll.dll!RtlAdjustPrivilege
-ntdll.dll!RtlAllocateActivationContextStack
-ntdll.dll!RtlAllocateAndInitializeSid
-ntdll.dll!RtlAllocateAndInitializeSidEx
-ntdll.dll!RtlAllocateHandle
-ntdll.dll!RtlAllocateHeap
-ntdll.dll!RtlAllocateMemoryBlockLookaside
-ntdll.dll!RtlAllocateMemoryZone
-ntdll.dll!RtlAllocateWnfSerializationGroup
-ntdll.dll!RtlAnsiCharToUnicodeChar
-ntdll.dll!RtlAnsiStringToUnicodeSize
-ntdll.dll!RtlAnsiStringToUnicodeString
-ntdll.dll!RtlAppendAsciizToString
-ntdll.dll!RtlAppendPathElement
-ntdll.dll!RtlAppendStringToString
-ntdll.dll!RtlAppendUnicodeStringToString
-ntdll.dll!RtlAppendUnicodeToString
-ntdll.dll!RtlApplicationVerifierStop
-ntdll.dll!RtlApplyRXact
-ntdll.dll!RtlApplyRXactNoFlush
-ntdll.dll!RtlAreAllAccessesGranted
-ntdll.dll!RtlAreAnyAccessesGranted
-ntdll.dll!RtlAreBitsClear
-ntdll.dll!RtlAreBitsSet
-ntdll.dll!RtlAssert
-ntdll.dll!RtlAvlInsertNodeEx
-ntdll.dll!RtlAvlRemoveNode
-ntdll.dll!RtlCancelTimer
-ntdll.dll!RtlCanonicalizeDomainName
-ntdll.dll!RtlCapabilityCheck
-ntdll.dll!RtlCaptureStackContext
-ntdll.dll!RtlCharToInteger
-ntdll.dll!RtlCheckForOrphanedCriticalSections
-ntdll.dll!RtlCheckPortableOperatingSystem
-ntdll.dll!RtlCheckRegistryKey
-ntdll.dll!RtlCheckSandboxedToken
-ntdll.dll!RtlCheckTokenCapability
-ntdll.dll!RtlCheckTokenMembership
-ntdll.dll!RtlCheckTokenMembershipEx
-ntdll.dll!RtlCleanUpTEBLangLists
-ntdll.dll!RtlClearAllBits
-ntdll.dll!RtlClearBit
-ntdll.dll!RtlClearBits
-ntdll.dll!RtlCloneUserProcess
-ntdll.dll!RtlCmDecodeMemIoResource
-ntdll.dll!RtlCmEncodeMemIoResource
-ntdll.dll!RtlCommitDebugInfo
-ntdll.dll!RtlCompactHeap
-ntdll.dll!RtlCompareAltitudes
-ntdll.dll!RtlCompareMemoryUlong
-ntdll.dll!RtlCompareString
-ntdll.dll!RtlCompareUnicodeString
-ntdll.dll!RtlCompareUnicodeStrings
-ntdll.dll!RtlCompressBuffer
-ntdll.dll!RtlComputeCrc32
-ntdll.dll!RtlComputeImportTableHash
-ntdll.dll!RtlComputePrivatizedDllName_U
-ntdll.dll!RtlConnectToSm
-ntdll.dll!RtlConsoleMultiByteToUnicodeN
-ntdll.dll!RtlContractHashTable
-ntdll.dll!RtlConvertDeviceFamilyInfoToString
-ntdll.dll!RtlConvertExclusiveToShared
-ntdll.dll!RtlConvertLCIDToString
-ntdll.dll!RtlConvertLongToLargeInteger
-ntdll.dll!RtlConvertSRWLockExclusiveToShared
-ntdll.dll!RtlConvertSharedToExclusive
-ntdll.dll!RtlConvertSidToUnicodeString
-ntdll.dll!RtlConvertToAutoInheritSecurityObject
-ntdll.dll!RtlConvertUlongToLargeInteger
-ntdll.dll!RtlCopyBitMap
-ntdll.dll!RtlCopyLuid
-ntdll.dll!RtlCopyLuidAndAttributesArray
-ntdll.dll!RtlCopyMappedMemory
-ntdll.dll!RtlCopySecurityDescriptor
-ntdll.dll!RtlCopySid
-ntdll.dll!RtlCopySidAndAttributesArray
-ntdll.dll!RtlCopyString
-ntdll.dll!RtlCopyUnicodeString
-ntdll.dll!RtlCrc32
-ntdll.dll!RtlCrc64
-ntdll.dll!RtlCreateAcl
-ntdll.dll!RtlCreateActivationContext
-ntdll.dll!RtlCreateAndSetSD
-ntdll.dll!RtlCreateAtomTable
-ntdll.dll!RtlCreateBootStatusDataFile
-ntdll.dll!RtlCreateBoundaryDescriptor
-ntdll.dll!RtlCreateEnvironment
-ntdll.dll!RtlCreateEnvironmentEx
-ntdll.dll!RtlCreateHashTable
-ntdll.dll!RtlCreateHashTableEx
-ntdll.dll!RtlCreateHeap
-ntdll.dll!RtlCreateMemoryBlockLookaside
-ntdll.dll!RtlCreateMemoryZone
-ntdll.dll!RtlCreateProcessParameters
-ntdll.dll!RtlCreateProcessParametersEx
-ntdll.dll!RtlCreateProcessReflection
-ntdll.dll!RtlCreateQueryDebugBuffer
-ntdll.dll!RtlCreateRegistryKey
-ntdll.dll!RtlCreateSecurityDescriptor
-ntdll.dll!RtlCreateServiceSid
-ntdll.dll!RtlCreateSystemVolumeInformationFolder
-ntdll.dll!RtlCreateTagHeap
-ntdll.dll!RtlCreateTimer
-ntdll.dll!RtlCreateTimerQueue
-ntdll.dll!RtlCreateUnicodeString
-ntdll.dll!RtlCreateUnicodeStringFromAsciiz
-ntdll.dll!RtlCreateUserProcess
-ntdll.dll!RtlCreateUserSecurityObject
-ntdll.dll!RtlCreateUserStack
-ntdll.dll!RtlCreateUserThread
-ntdll.dll!RtlCreateVirtualAccountSid
-ntdll.dll!RtlCultureNameToLCID
-ntdll.dll!RtlCustomCPToUnicodeN
-ntdll.dll!RtlCutoverTimeToSystemTime
-ntdll.dll!RtlDeCommitDebugInfo
-ntdll.dll!RtlDeNormalizeProcessParams
-ntdll.dll!RtlDeactivateActivationContext
-ntdll.dll!RtlDebugPrintTimes
-ntdll.dll!RtlDecodePointer
-ntdll.dll!RtlDecodeRemotePointer
-ntdll.dll!RtlDecodeSystemPointer
-ntdll.dll!RtlDecompressBuffer
-ntdll.dll!RtlDecompressBufferEx
-ntdll.dll!RtlDecompressFragment
-ntdll.dll!RtlDefaultNpAcl
-ntdll.dll!RtlDelete
-ntdll.dll!RtlDeleteAce
-ntdll.dll!RtlDeleteAtomFromAtomTable
-ntdll.dll!RtlDeleteBoundaryDescriptor
-ntdll.dll!RtlDeleteCriticalSection
-ntdll.dll!RtlDeleteElementGenericTable
-ntdll.dll!RtlDeleteElementGenericTableAvl
-ntdll.dll!RtlDeleteElementGenericTableAvlEx
-ntdll.dll!RtlDeleteHashTable
-ntdll.dll!RtlDeleteNoSplay
-ntdll.dll!RtlDeleteRegistryValue
-ntdll.dll!RtlDeleteResource
-ntdll.dll!RtlDeleteSecurityObject
-ntdll.dll!RtlDeleteTimer
-ntdll.dll!RtlDeleteTimerQueue
-ntdll.dll!RtlDeleteTimerQueueEx
-ntdll.dll!RtlDeregisterSecureMemoryCacheCallback
-ntdll.dll!RtlDeregisterWait
-ntdll.dll!RtlDeregisterWaitEx
-ntdll.dll!RtlDeriveCapabilitySidsFromName
-ntdll.dll!RtlDestroyAtomTable
-ntdll.dll!RtlDestroyEnvironment
-ntdll.dll!RtlDestroyHandleTable
-ntdll.dll!RtlDestroyHeap
-ntdll.dll!RtlDestroyMemoryBlockLookaside
-ntdll.dll!RtlDestroyMemoryZone
-ntdll.dll!RtlDestroyProcessParameters
-ntdll.dll!RtlDestroyQueryDebugBuffer
-ntdll.dll!RtlDetectHeapLeaks
-ntdll.dll!RtlDetermineDosPathNameType_U
-ntdll.dll!RtlDisableThreadProfiling
-ntdll.dll!RtlDllShutdownInProgress
-ntdll.dll!RtlDnsHostNameToComputerName
-ntdll.dll!RtlDoesFileExists_U
-ntdll.dll!RtlDosApplyFileIsolationRedirection_Ustr
-ntdll.dll!RtlDosPathNameToNtPathName_U
-ntdll.dll!RtlDosPathNameToNtPathName_U_WithStatus
-ntdll.dll!RtlDosPathNameToRelativeNtPathName_U
-ntdll.dll!RtlDosPathNameToRelativeNtPathName_U_WithStatus
-ntdll.dll!RtlDosSearchPath_U
-ntdll.dll!RtlDosSearchPath_Ustr
-ntdll.dll!RtlDowncaseUnicodeChar
-ntdll.dll!RtlDowncaseUnicodeString
-ntdll.dll!RtlDumpResource
-ntdll.dll!RtlDuplicateUnicodeString
-ntdll.dll!RtlEmptyAtomTable
-ntdll.dll!RtlEnableEarlyCriticalSectionEventCreation
-ntdll.dll!RtlEnableThreadProfiling
-ntdll.dll!RtlEncodePointer
-ntdll.dll!RtlEncodeRemotePointer
-ntdll.dll!RtlEncodeSystemPointer
-ntdll.dll!RtlEndEnumerationHashTable
-ntdll.dll!RtlEndStrongEnumerationHashTable
-ntdll.dll!RtlEndWeakEnumerationHashTable
-ntdll.dll!RtlEnlargedIntegerMultiply
-ntdll.dll!RtlEnlargedUnsignedMultiply
-ntdll.dll!RtlEnterCriticalSection
-ntdll.dll!RtlEnumProcessHeaps
-ntdll.dll!RtlEnumerateEntryHashTable
-ntdll.dll!RtlEnumerateGenericTable
-ntdll.dll!RtlEnumerateGenericTableAvl
-ntdll.dll!RtlEnumerateGenericTableLikeADirectory
-ntdll.dll!RtlEnumerateGenericTableWithoutSplaying
-ntdll.dll!RtlEnumerateGenericTableWithoutSplayingAvl
-ntdll.dll!RtlEqualComputerName
-ntdll.dll!RtlEqualDomainName
-ntdll.dll!RtlEqualLuid
-ntdll.dll!RtlEqualPrefixSid
-ntdll.dll!RtlEqualSid
-ntdll.dll!RtlEqualString
-ntdll.dll!RtlEqualUnicodeString
-ntdll.dll!RtlEqualWnfChangeStamps
-ntdll.dll!RtlEraseUnicodeString
-ntdll.dll!RtlEthernetAddressToStringA
-ntdll.dll!RtlEthernetAddressToStringW
-ntdll.dll!RtlEthernetStringToAddressA
-ntdll.dll!RtlEthernetStringToAddressW
-ntdll.dll!RtlExitUserProcess
-ntdll.dll!RtlExitUserThread
-ntdll.dll!RtlExpandEnvironmentStrings
-ntdll.dll!RtlExpandEnvironmentStrings_U
-ntdll.dll!RtlExpandHashTable
-ntdll.dll!RtlExtendMemoryBlockLookaside
-ntdll.dll!RtlExtendMemoryZone
-ntdll.dll!RtlExtendedIntegerMultiply
-ntdll.dll!RtlExtendedLargeIntegerDivide
-ntdll.dll!RtlExtendedMagicDivide
-ntdll.dll!RtlExtractBitMap
-ntdll.dll!RtlFillMemory
-ntdll.dll!RtlFillMemoryUlong
-ntdll.dll!RtlFillMemoryUlonglong
-ntdll.dll!RtlFindAceByType
-ntdll.dll!RtlFindActivationContextSectionGuid
-ntdll.dll!RtlFindActivationContextSectionString
-ntdll.dll!RtlFindCharInUnicodeString
-ntdll.dll!RtlFindClearBits
-ntdll.dll!RtlFindClearBitsAndSet
-ntdll.dll!RtlFindClearRuns
-ntdll.dll!RtlFindClosestEncodableLength
-ntdll.dll!RtlFindLastBackwardRunClear
-ntdll.dll!RtlFindLeastSignificantBit
-ntdll.dll!RtlFindLongestRunClear
-ntdll.dll!RtlFindMessage
-ntdll.dll!RtlFindMostSignificantBit
-ntdll.dll!RtlFindNextForwardRunClear
-ntdll.dll!RtlFindSetBits
-ntdll.dll!RtlFindSetBitsAndClear
-ntdll.dll!RtlFindUnicodeSubstring
-ntdll.dll!RtlFirstEntrySList
-ntdll.dll!RtlFirstFreeAce
-ntdll.dll!RtlFlsAlloc
-ntdll.dll!RtlFlsFree
-ntdll.dll!RtlFlushSecureMemoryCache
-ntdll.dll!RtlFormatCurrentUserKeyPath
-ntdll.dll!RtlFormatMessage
-ntdll.dll!RtlFormatMessageEx
-ntdll.dll!RtlFreeActivationContextStack
-ntdll.dll!RtlFreeAnsiString
-ntdll.dll!RtlFreeHandle
-ntdll.dll!RtlFreeHeap
-ntdll.dll!RtlFreeMemoryBlockLookaside
-ntdll.dll!RtlFreeOemString
-ntdll.dll!RtlFreeSid
-ntdll.dll!RtlFreeThreadActivationContextStack
-ntdll.dll!RtlFreeUnicodeString
-ntdll.dll!RtlFreeUserStack
-ntdll.dll!RtlGUIDFromString
-ntdll.dll!RtlGenerate8dot3Name
-ntdll.dll!RtlGetAce
-ntdll.dll!RtlGetActiveActivationContext
-ntdll.dll!RtlGetAppContainerNamedObjectPath
-ntdll.dll!RtlGetAppContainerParent
-ntdll.dll!RtlGetAppContainerSidType
-ntdll.dll!RtlGetCallersAddress
-ntdll.dll!RtlGetCompressionWorkSpaceSize
-ntdll.dll!RtlGetControlSecurityDescriptor
-ntdll.dll!RtlGetCriticalSectionRecursionCount
-ntdll.dll!RtlGetCurrentDirectory_U
-ntdll.dll!RtlGetCurrentPeb
-ntdll.dll!RtlGetCurrentProcessorNumber
-ntdll.dll!RtlGetCurrentProcessorNumberEx
-ntdll.dll!RtlGetCurrentTransaction
-ntdll.dll!RtlGetDaclSecurityDescriptor
-ntdll.dll!RtlGetDeviceFamilyInfoEnum
-ntdll.dll!RtlGetElementGenericTable
-ntdll.dll!RtlGetElementGenericTableAvl
-ntdll.dll!RtlGetExePath
-ntdll.dll!RtlGetFileMUIPath
-ntdll.dll!RtlGetFrame
-ntdll.dll!RtlGetFullPathName_U
-ntdll.dll!RtlGetFullPathName_UEx
-ntdll.dll!RtlGetFullPathName_UstrEx
-ntdll.dll!RtlGetGroupSecurityDescriptor
-ntdll.dll!RtlGetIntegerAtom
-ntdll.dll!RtlGetInterruptTimePrecise
-ntdll.dll!RtlGetLastNtStatus
-ntdll.dll!RtlGetLastWin32Error
-ntdll.dll!RtlGetLengthWithoutLastFullDosOrNtPathElement
-ntdll.dll!RtlGetLengthWithoutTrailingPathSeperators
-ntdll.dll!RtlGetLocaleFileMappingAddress
-ntdll.dll!RtlGetLongestNtPathLength
-ntdll.dll!RtlGetNativeSystemInformation
-ntdll.dll!RtlGetNextEntryHashTable
-ntdll.dll!RtlGetNtGlobalFlags
-ntdll.dll!RtlGetNtProductType
-ntdll.dll!RtlGetNtVersionNumbers
-ntdll.dll!RtlGetOwnerSecurityDescriptor
-ntdll.dll!RtlGetProcessHeaps
-ntdll.dll!RtlGetProductInfo
-ntdll.dll!RtlGetSaclSecurityDescriptor
-ntdll.dll!RtlGetSearchPath
-ntdll.dll!RtlGetSecurityDescriptorRMControl
-ntdll.dll!RtlGetSetBootStatusData
-ntdll.dll!RtlGetSystemPreferredUILanguages
-ntdll.dll!RtlGetSystemTimePrecise
-ntdll.dll!RtlGetThreadErrorMode
-ntdll.dll!RtlGetThreadLangIdByIndex
-ntdll.dll!RtlGetThreadPreferredUILanguages
-ntdll.dll!RtlGetUILanguageInfo
-ntdll.dll!RtlGetUnloadEventTrace
-ntdll.dll!RtlGetUnloadEventTraceEx
-ntdll.dll!RtlGetUserInfoHeap
-ntdll.dll!RtlGetUserPreferredUILanguages
-ntdll.dll!RtlGetVersion
-ntdll.dll!RtlHashUnicodeString
-ntdll.dll!RtlHeapTrkInitialize
-ntdll.dll!RtlIdentifierAuthoritySid
-ntdll.dll!RtlIdnToAscii
-ntdll.dll!RtlIdnToNameprepUnicode
-ntdll.dll!RtlIdnToUnicode
-ntdll.dll!RtlImageDirectoryEntryToData
-ntdll.dll!RtlImageNtHeader
-ntdll.dll!RtlImageNtHeaderEx
-ntdll.dll!RtlImageRvaToSection
-ntdll.dll!RtlImageRvaToVa
-ntdll.dll!RtlImpersonateSelf
-ntdll.dll!RtlImpersonateSelfEx
-ntdll.dll!RtlInitAnsiString
-ntdll.dll!RtlInitAnsiStringEx
-ntdll.dll!RtlInitCodePageTable
-ntdll.dll!RtlInitEnumerationHashTable
-ntdll.dll!RtlInitNlsTables
-ntdll.dll!RtlInitString
-ntdll.dll!RtlInitStringEx
-ntdll.dll!RtlInitStrongEnumerationHashTable
-ntdll.dll!RtlInitUnicodeString
-ntdll.dll!RtlInitUnicodeStringEx
-ntdll.dll!RtlInitWeakEnumerationHashTable
-ntdll.dll!RtlInitializeAtomPackage
-ntdll.dll!RtlInitializeBitMap
-ntdll.dll!RtlInitializeConditionVariable
-ntdll.dll!RtlInitializeCriticalSection
-ntdll.dll!RtlInitializeCriticalSectionAndSpinCount
-ntdll.dll!RtlInitializeCriticalSectionEx
-ntdll.dll!RtlInitializeExceptionChain
-ntdll.dll!RtlInitializeGenericTable
-ntdll.dll!RtlInitializeGenericTableAvl
-ntdll.dll!RtlInitializeHandleTable
-ntdll.dll!RtlInitializeRXact
-ntdll.dll!RtlInitializeResource
-ntdll.dll!RtlInitializeSListHead
-ntdll.dll!RtlInitializeSRWLock
-ntdll.dll!RtlInitializeSid
-ntdll.dll!RtlInitializeSidEx
-ntdll.dll!RtlInsertElementGenericTable
-ntdll.dll!RtlInsertElementGenericTableAvl
-ntdll.dll!RtlInsertElementGenericTableFull
-ntdll.dll!RtlInsertElementGenericTableFullAvl
-ntdll.dll!RtlInsertEntryHashTable
-ntdll.dll!RtlInt64ToUnicodeString
-ntdll.dll!RtlIntegerToChar
-ntdll.dll!RtlIntegerToUnicodeString
-ntdll.dll!RtlInterlockedClearBitRun
-ntdll.dll!RtlInterlockedCompareExchange64
-ntdll.dll!RtlInterlockedFlushSList
-ntdll.dll!RtlInterlockedPopEntrySList
-ntdll.dll!RtlInterlockedPushEntrySList
-ntdll.dll!RtlInterlockedPushListSListEx
-ntdll.dll!RtlInterlockedSetBitRun
-ntdll.dll!RtlIoDecodeMemIoResource
-ntdll.dll!RtlIoEncodeMemIoResource
-ntdll.dll!RtlIpv4AddressToStringA
-ntdll.dll!RtlIpv4AddressToStringExA
-ntdll.dll!RtlIpv4AddressToStringExW
-ntdll.dll!RtlIpv4AddressToStringW
-ntdll.dll!RtlIpv4StringToAddressA
-ntdll.dll!RtlIpv4StringToAddressExA
-ntdll.dll!RtlIpv4StringToAddressExW
-ntdll.dll!RtlIpv4StringToAddressW
-ntdll.dll!RtlIpv6AddressToStringA
-ntdll.dll!RtlIpv6AddressToStringExA
-ntdll.dll!RtlIpv6AddressToStringExW
-ntdll.dll!RtlIpv6AddressToStringW
-ntdll.dll!RtlIpv6StringToAddressA
-ntdll.dll!RtlIpv6StringToAddressExA
-ntdll.dll!RtlIpv6StringToAddressExW
-ntdll.dll!RtlIpv6StringToAddressW
-ntdll.dll!RtlIsActivationContextActive
-ntdll.dll!RtlIsCapabilitySid
-ntdll.dll!RtlIsCriticalSectionLocked
-ntdll.dll!RtlIsCriticalSectionLockedByThread
-ntdll.dll!RtlIsDosDeviceName_U
-ntdll.dll!RtlIsGenericTableEmpty
-ntdll.dll!RtlIsGenericTableEmptyAvl
-ntdll.dll!RtlIsMultiSessionSku
-ntdll.dll!RtlIsNameInExpression
-ntdll.dll!RtlIsNameLegalDOS8Dot3
-ntdll.dll!RtlIsNormalizedString
-ntdll.dll!RtlIsPackageSid
-ntdll.dll!RtlIsParentOfChildAppContainer
-ntdll.dll!RtlIsProcessorFeaturePresent
-ntdll.dll!RtlIsTextUnicode
-ntdll.dll!RtlIsThreadWithinLoaderCallout
-ntdll.dll!RtlIsUntrustedObject
-ntdll.dll!RtlIsValidHandle
-ntdll.dll!RtlIsValidIndexHandle
-ntdll.dll!RtlIsValidLocaleName
-ntdll.dll!RtlIsValidProcessTrustLabelSid
-ntdll.dll!RtlKnownExceptionFilter
-ntdll.dll!RtlLCIDToCultureName
-ntdll.dll!RtlLargeIntegerAdd
-ntdll.dll!RtlLargeIntegerArithmeticShift
-ntdll.dll!RtlLargeIntegerDivide
-ntdll.dll!RtlLargeIntegerNegate
-ntdll.dll!RtlLargeIntegerShiftLeft
-ntdll.dll!RtlLargeIntegerShiftRight
-ntdll.dll!RtlLargeIntegerSubtract
-ntdll.dll!RtlLargeIntegerToChar
-ntdll.dll!RtlLcidToLocaleName
-ntdll.dll!RtlLeaveCriticalSection
-ntdll.dll!RtlLengthRequiredSid
-ntdll.dll!RtlLengthSecurityDescriptor
-ntdll.dll!RtlLengthSid
-ntdll.dll!RtlLocalTimeToSystemTime
-ntdll.dll!RtlLocaleNameToLcid
-ntdll.dll!RtlLockBootStatusData
-ntdll.dll!RtlLockCurrentThread
-ntdll.dll!RtlLockHeap
-ntdll.dll!RtlLockMemoryBlockLookaside
-ntdll.dll!RtlLockMemoryZone
-ntdll.dll!RtlLockModuleSection
-ntdll.dll!RtlLogStackBackTrace
-ntdll.dll!RtlLookupAtomInAtomTable
-ntdll.dll!RtlLookupElementGenericTable
-ntdll.dll!RtlLookupElementGenericTableAvl
-ntdll.dll!RtlLookupElementGenericTableFull
-ntdll.dll!RtlLookupElementGenericTableFullAvl
-ntdll.dll!RtlLookupEntryHashTable
-ntdll.dll!RtlMakeSelfRelativeSD
-ntdll.dll!RtlMapGenericMask
-ntdll.dll!RtlMapSecurityErrorToNtStatus
-ntdll.dll!RtlMoveMemory
-ntdll.dll!RtlMultiAppendUnicodeStringBuffer
-ntdll.dll!RtlMultiByteToUnicodeN
-ntdll.dll!RtlMultiByteToUnicodeSize
-ntdll.dll!RtlMultipleAllocateHeap
-ntdll.dll!RtlMultipleFreeHeap
-ntdll.dll!RtlNewInstanceSecurityObject
-ntdll.dll!RtlNewSecurityGrantedAccess
-ntdll.dll!RtlNewSecurityObject
-ntdll.dll!RtlNewSecurityObjectEx
-ntdll.dll!RtlNewSecurityObjectWithMultipleInheritance
-ntdll.dll!RtlNormalizeProcessParams
-ntdll.dll!RtlNormalizeString
-ntdll.dll!RtlNtPathNameToDosPathName
-ntdll.dll!RtlNtStatusToDosError
-ntdll.dll!RtlNtStatusToDosErrorNoTeb
-ntdll.dll!RtlNumberGenericTableElements
-ntdll.dll!RtlNumberGenericTableElementsAvl
-ntdll.dll!RtlNumberOfClearBits
-ntdll.dll!RtlNumberOfClearBitsInRange
-ntdll.dll!RtlNumberOfSetBits
-ntdll.dll!RtlNumberOfSetBitsInRange
-ntdll.dll!RtlNumberOfSetBitsUlongPtr
-ntdll.dll!RtlOemStringToUnicodeSize
-ntdll.dll!RtlOemStringToUnicodeString
-ntdll.dll!RtlOemToUnicodeN
-ntdll.dll!RtlOpenCurrentUser
-ntdll.dll!RtlOsDeploymentState
-ntdll.dll!RtlOwnerAcesPresent
-ntdll.dll!RtlPinAtomInAtomTable
-ntdll.dll!RtlPopFrame
-ntdll.dll!RtlPrefixString
-ntdll.dll!RtlPrefixUnicodeString
-ntdll.dll!RtlProcessFlsData
-ntdll.dll!RtlPublishWnfStateData
-ntdll.dll!RtlPushFrame
-ntdll.dll!RtlQueryActivationContextApplicationSettings
-ntdll.dll!RtlQueryAtomInAtomTable
-ntdll.dll!RtlQueryDepthSList
-ntdll.dll!RtlQueryDynamicTimeZoneInformation
-ntdll.dll!RtlQueryElevationFlags
-ntdll.dll!RtlQueryEnvironmentVariable
-ntdll.dll!RtlQueryEnvironmentVariable_U
-ntdll.dll!RtlQueryHeapInformation
-ntdll.dll!RtlQueryInformationAcl
-ntdll.dll!RtlQueryInformationActivationContext
-ntdll.dll!RtlQueryInformationActiveActivationContext
-ntdll.dll!RtlQueryPackageClaims
-ntdll.dll!RtlQueryPackageIdentity
-ntdll.dll!RtlQueryPackageIdentityEx
-ntdll.dll!RtlQueryPerformanceCounter
-ntdll.dll!RtlQueryPerformanceFrequency
-ntdll.dll!RtlQueryProcessBackTraceInformation
-ntdll.dll!RtlQueryProcessDebugInformation
-ntdll.dll!RtlQueryProcessLockInformation
-ntdll.dll!RtlQueryProtectedPolicy
-ntdll.dll!RtlQueryRegistryValues
-ntdll.dll!RtlQueryRegistryValuesEx
-ntdll.dll!RtlQuerySecurityObject
-ntdll.dll!RtlQueryThreadProfiling
-ntdll.dll!RtlQueryTimeZoneInformation
-ntdll.dll!RtlQueryUnbiasedInterruptTime
-ntdll.dll!RtlQueryValidationRunlevel
-ntdll.dll!RtlQueryWnfMetaNotification
-ntdll.dll!RtlQueryWnfStateData
-ntdll.dll!RtlQueryWnfStateDataWithExplicitScope
-ntdll.dll!RtlQueueApcWow64Thread
-ntdll.dll!RtlQueueWorkItem
-ntdll.dll!RtlRaiseStatus
-ntdll.dll!RtlRandom
-ntdll.dll!RtlRandomEx
-ntdll.dll!RtlRbInsertNodeEx
-ntdll.dll!RtlRbRemoveNode
-ntdll.dll!RtlReAllocateHeap
-ntdll.dll!RtlReadThreadProfilingData
-ntdll.dll!RtlRealPredecessor
-ntdll.dll!RtlRealSuccessor
-ntdll.dll!RtlRegisterForWnfMetaNotification
-ntdll.dll!RtlRegisterSecureMemoryCacheCallback
-ntdll.dll!RtlRegisterThreadWithCsrss
-ntdll.dll!RtlRegisterWait
-ntdll.dll!RtlReleaseActivationContext
-ntdll.dll!RtlReleasePath
-ntdll.dll!RtlReleasePebLock
-ntdll.dll!RtlReleasePrivilege
-ntdll.dll!RtlReleaseRelativeName
-ntdll.dll!RtlReleaseResource
-ntdll.dll!RtlReleaseSRWLockExclusive
-ntdll.dll!RtlReleaseSRWLockShared
-ntdll.dll!RtlRemoteCall
-ntdll.dll!RtlRemoveEntryHashTable
-ntdll.dll!RtlRemovePrivileges
-ntdll.dll!RtlRemoveVectoredContinueHandler
-ntdll.dll!RtlRemoveVectoredExceptionHandler
-ntdll.dll!RtlReplaceSidInSd
-ntdll.dll!RtlReportException
-ntdll.dll!RtlReportSilentProcessExit
-ntdll.dll!RtlReportSqmEscalation
-ntdll.dll!RtlResetMemoryBlockLookaside
-ntdll.dll!RtlResetRtlTranslations
-ntdll.dll!RtlRestoreLastWin32Error
-ntdll.dll!RtlRunDecodeUnicodeString
-ntdll.dll!RtlRunEncodeUnicodeString
-ntdll.dll!RtlRunOnceBeginInitialize
-ntdll.dll!RtlRunOnceComplete
-ntdll.dll!RtlRunOnceExecuteOnce
-ntdll.dll!RtlRunOnceInitialize
-ntdll.dll!RtlSecondsSince1970ToTime
-ntdll.dll!RtlSecondsSince1980ToTime
-ntdll.dll!RtlSelfRelativeToAbsoluteSD2
-ntdll.dll!RtlSelfRelativeToAbsoluteSD
-ntdll.dll!RtlSendMsgToSm
-ntdll.dll!RtlSetAllBits
-ntdll.dll!RtlSetBit
-ntdll.dll!RtlSetBits
-ntdll.dll!RtlSetControlSecurityDescriptor
-ntdll.dll!RtlSetCriticalSectionSpinCount
-ntdll.dll!RtlSetCurrentDirectory_U
-ntdll.dll!RtlSetCurrentEnvironment
-ntdll.dll!RtlSetCurrentTransaction
-ntdll.dll!RtlSetDaclSecurityDescriptor
-ntdll.dll!RtlSetDynamicTimeZoneInformation
-ntdll.dll!RtlSetEnvironmentStrings
-ntdll.dll!RtlSetEnvironmentVar
-ntdll.dll!RtlSetEnvironmentVariable
-ntdll.dll!RtlSetGroupSecurityDescriptor
-ntdll.dll!RtlSetHeapInformation
-ntdll.dll!RtlSetInformationAcl
-ntdll.dll!RtlSetIoCompletionCallback
-ntdll.dll!RtlSetLastWin32Error
-ntdll.dll!RtlSetLastWin32ErrorAndNtStatusFromNtStatus
-ntdll.dll!RtlSetOwnerSecurityDescriptor
-ntdll.dll!RtlSetPortableOperatingSystem
-ntdll.dll!RtlSetProcessDebugInformation
-ntdll.dll!RtlSetProcessIsCritical
-ntdll.dll!RtlSetProtectedPolicy
-ntdll.dll!RtlSetSaclSecurityDescriptor
-ntdll.dll!RtlSetSearchPathMode
-ntdll.dll!RtlSetSecurityDescriptorRMControl
-ntdll.dll!RtlSetSecurityObject
-ntdll.dll!RtlSetSecurityObjectEx
-ntdll.dll!RtlSetThreadErrorMode
-ntdll.dll!RtlSetThreadIsCritical
-ntdll.dll!RtlSetThreadPoolStartFunc
-ntdll.dll!RtlSetThreadPreferredUILanguages
-ntdll.dll!RtlSetThreadSubProcessTag
-ntdll.dll!RtlSetTimeZoneInformation
-ntdll.dll!RtlSetTimer
-ntdll.dll!RtlSetUnhandledExceptionFilter
-ntdll.dll!RtlSetUserFlagsHeap
-ntdll.dll!RtlSetUserValueHeap
-ntdll.dll!RtlSidDominates
-ntdll.dll!RtlSidDominatesForTrust
-ntdll.dll!RtlSidEqualLevel
-ntdll.dll!RtlSidHashInitialize
-ntdll.dll!RtlSidHashLookup
-ntdll.dll!RtlSidIsHigherLevel
-ntdll.dll!RtlSizeHeap
-ntdll.dll!RtlSleepConditionVariableCS
-ntdll.dll!RtlSleepConditionVariableSRW
-ntdll.dll!RtlSplay
-ntdll.dll!RtlStartRXact
-ntdll.dll!RtlStringFromGUID
-ntdll.dll!RtlStringFromGUIDEx
-ntdll.dll!RtlStronglyEnumerateEntryHashTable
-ntdll.dll!RtlSubAuthorityCountSid
-ntdll.dll!RtlSubAuthoritySid
-ntdll.dll!RtlSubscribeWnfStateChangeNotification
-ntdll.dll!RtlSubtreePredecessor
-ntdll.dll!RtlSubtreeSuccessor
-ntdll.dll!RtlSwitchedVVI
-ntdll.dll!RtlSystemTimeToLocalTime
-ntdll.dll!RtlTestAndPublishWnfStateData
-ntdll.dll!RtlTestBit
-ntdll.dll!RtlTestProtectedAccess
-ntdll.dll!RtlTimeFieldsToTime
-ntdll.dll!RtlTimeToElapsedTimeFields
-ntdll.dll!RtlTimeToSecondsSince1970
-ntdll.dll!RtlTimeToSecondsSince1980
-ntdll.dll!RtlTimeToTimeFields
-ntdll.dll!RtlTraceDatabaseAdd
-ntdll.dll!RtlTraceDatabaseCreate
-ntdll.dll!RtlTraceDatabaseDestroy
-ntdll.dll!RtlTraceDatabaseEnumerate
-ntdll.dll!RtlTraceDatabaseFind
-ntdll.dll!RtlTraceDatabaseLock
-ntdll.dll!RtlTraceDatabaseUnlock
-ntdll.dll!RtlTraceDatabaseValidate
-ntdll.dll!RtlTryAcquirePebLock
-ntdll.dll!RtlTryAcquireSRWLockExclusive
-ntdll.dll!RtlTryAcquireSRWLockShared
-ntdll.dll!RtlTryConvertSRWLockSharedToExclusiveOrRelease
-ntdll.dll!RtlTryEnterCriticalSection
-ntdll.dll!RtlUTF8ToUnicodeN
-ntdll.dll!RtlUnhandledExceptionFilter2
-ntdll.dll!RtlUnhandledExceptionFilter
-ntdll.dll!RtlUnicodeStringToAnsiSize
-ntdll.dll!RtlUnicodeStringToAnsiString
-ntdll.dll!RtlUnicodeStringToCountedOemString
-ntdll.dll!RtlUnicodeStringToInteger
-ntdll.dll!RtlUnicodeStringToOemSize
-ntdll.dll!RtlUnicodeStringToOemString
-ntdll.dll!RtlUnicodeToCustomCPN
-ntdll.dll!RtlUnicodeToMultiByteN
-ntdll.dll!RtlUnicodeToMultiByteSize
-ntdll.dll!RtlUnicodeToOemN
-ntdll.dll!RtlUnicodeToUTF8N
-ntdll.dll!RtlUniform
-ntdll.dll!RtlUnlockBootStatusData
-ntdll.dll!RtlUnlockCurrentThread
-ntdll.dll!RtlUnlockHeap
-ntdll.dll!RtlUnlockMemoryBlockLookaside
-ntdll.dll!RtlUnlockMemoryZone
-ntdll.dll!RtlUnlockModuleSection
-ntdll.dll!RtlUnsubscribeWnfNotificationWaitForCompletion
-ntdll.dll!RtlUnsubscribeWnfNotificationWithCompletionCallback
-ntdll.dll!RtlUnsubscribeWnfStateChangeNotification
-ntdll.dll!RtlUpcaseUnicodeChar
-ntdll.dll!RtlUpcaseUnicodeString
-ntdll.dll!RtlUpcaseUnicodeStringToCountedOemString
-ntdll.dll!RtlUpcaseUnicodeStringToOemString
-ntdll.dll!RtlUpcaseUnicodeToCustomCPN
-ntdll.dll!RtlUpcaseUnicodeToMultiByteN
-ntdll.dll!RtlUpcaseUnicodeToOemN
-ntdll.dll!RtlUpdateClonedCriticalSection
-ntdll.dll!RtlUpdateClonedSRWLock
-ntdll.dll!RtlUpdateTimer
-ntdll.dll!RtlUpperChar
-ntdll.dll!RtlUpperString
-ntdll.dll!RtlValidAcl
-ntdll.dll!RtlValidProcessProtection
-ntdll.dll!RtlValidRelativeSecurityDescriptor
-ntdll.dll!RtlValidSecurityDescriptor
-ntdll.dll!RtlValidSid
-ntdll.dll!RtlValidateHeap
-ntdll.dll!RtlValidateProcessHeaps
-ntdll.dll!RtlValidateUnicodeString
-ntdll.dll!RtlVerifyVersionInfo
-ntdll.dll!RtlWaitForWnfMetaNotification
-ntdll.dll!RtlWaitOnAddress
-ntdll.dll!RtlWakeAddressAll
-ntdll.dll!RtlWakeAddressAllNoFence
-ntdll.dll!RtlWakeAddressSingle
-ntdll.dll!RtlWakeAddressSingleNoFence
-ntdll.dll!RtlWakeAllConditionVariable
-ntdll.dll!RtlWakeConditionVariable
-ntdll.dll!RtlWalkFrameChain
-ntdll.dll!RtlWalkHeap
-ntdll.dll!RtlWeaklyEnumerateEntryHashTable
-ntdll.dll!RtlWerpReportException
-ntdll.dll!RtlWnfCompareChangeStamp
-ntdll.dll!RtlWnfDllUnloadCallback
-ntdll.dll!RtlWow64CallFunction64
-ntdll.dll!RtlWow64EnableFsRedirection
-ntdll.dll!RtlWow64EnableFsRedirectionEx
-ntdll.dll!RtlWriteRegistryValue
-ntdll.dll!RtlZeroMemory
-ntdll.dll!RtlZombifyActivationContext
-ntdll.dll!RtlpApplyLengthFunction
-ntdll.dll!RtlpCheckDynamicTimeZoneInformation
-ntdll.dll!RtlpCleanupRegistryKeys
-ntdll.dll!RtlpConvertAbsoluteToRelativeSecurityAttribute
-ntdll.dll!RtlpConvertCultureNamesToLCIDs
-ntdll.dll!RtlpConvertLCIDsToCultureNames
-ntdll.dll!RtlpConvertRelativeToAbsoluteSecurityAttribute
-ntdll.dll!RtlpCreateProcessRegistryInfo
-ntdll.dll!RtlpEnsureBufferSize
-ntdll.dll!RtlpGetLCIDFromLangInfoNode
-ntdll.dll!RtlpGetNameFromLangInfoNode
-ntdll.dll!RtlpGetSystemDefaultUILanguage
-ntdll.dll!RtlpGetUserOrMachineUILanguage4NLS
-ntdll.dll!RtlpInitializeLangRegistryInfo
-ntdll.dll!RtlpIsQualifiedLanguage
-ntdll.dll!RtlpLoadMachineUIByPolicy
-ntdll.dll!RtlpLoadUserUIByPolicy
-ntdll.dll!RtlpMergeSecurityAttributeInformation
-ntdll.dll!RtlpMuiFreeLangRegistryInfo
-ntdll.dll!RtlpMuiRegCreateRegistryInfo
-ntdll.dll!RtlpMuiRegFreeRegistryInfo
-ntdll.dll!RtlpMuiRegLoadRegistryInfo
-ntdll.dll!RtlpNotOwnerCriticalSection
-ntdll.dll!RtlpNtCreateKey
-ntdll.dll!RtlpNtEnumerateSubKey
-ntdll.dll!RtlpNtMakeTemporaryKey
-ntdll.dll!RtlpNtOpenKey
-ntdll.dll!RtlpNtQueryValueKey
-ntdll.dll!RtlpNtSetValueKey
-ntdll.dll!RtlpQueryDefaultUILanguage
-ntdll.dll!RtlpRefreshCachedUILanguage
-ntdll.dll!RtlpSetInstallLanguage
-ntdll.dll!RtlpSetPreferredUILanguages
-ntdll.dll!RtlpSetUserPreferredUILanguages
-ntdll.dll!RtlpUnWaitCriticalSection
-ntdll.dll!RtlpVerifyAndCommitUILanguageSettings
-ntdll.dll!RtlpWaitForCriticalSection
-ntdll.dll!RtlxAnsiStringToUnicodeSize
-ntdll.dll!RtlxOemStringToUnicodeSize
-ntdll.dll!RtlxUnicodeStringToAnsiSize
-ntdll.dll!RtlxUnicodeStringToOemSize
-ntdll.dll!ShipAssert
-ntdll.dll!ShipAssertGetBufferInfo
-ntdll.dll!ShipAssertMsgA
-ntdll.dll!ShipAssertMsgW
-ntdll.dll!TpAllocAlpcCompletion
-ntdll.dll!TpAllocCleanupGroup
-ntdll.dll!TpAllocIoCompletion
-ntdll.dll!TpAllocJobNotification
-ntdll.dll!TpAllocPool
-ntdll.dll!TpAllocTimer
-ntdll.dll!TpAllocWait
-ntdll.dll!TpAllocWork
-ntdll.dll!TpCallbackDetectedUnrecoverableError
-ntdll.dll!TpCallbackLeaveCriticalSectionOnCompletion
-ntdll.dll!TpCallbackMayRunLong
-ntdll.dll!TpCallbackReleaseMutexOnCompletion
-ntdll.dll!TpCallbackReleaseSemaphoreOnCompletion
-ntdll.dll!TpCallbackSetEventOnCompletion
-ntdll.dll!TpCallbackUnloadDllOnCompletion
-ntdll.dll!TpCancelAsyncIoOperation
-ntdll.dll!TpCaptureCaller
-ntdll.dll!TpCheckTerminateWorker
-ntdll.dll!TpDisassociateCallback
-ntdll.dll!TpIsTimerSet
-ntdll.dll!TpPostWork
-ntdll.dll!TpQueryPoolStackInformation
-ntdll.dll!TpReleaseAlpcCompletion
-ntdll.dll!TpReleaseCleanupGroup
-ntdll.dll!TpReleaseCleanupGroupMembers
-ntdll.dll!TpReleaseIoCompletion
-ntdll.dll!TpReleaseJobNotification
-ntdll.dll!TpReleasePool
-ntdll.dll!TpReleaseTimer
-ntdll.dll!TpReleaseWait
-ntdll.dll!TpReleaseWork
-ntdll.dll!TpSetPoolMaxThreads
-ntdll.dll!TpSetPoolMaxThreadsSoftLimit
-ntdll.dll!TpSetPoolMinThreads
-ntdll.dll!TpSetPoolStackInformation
-ntdll.dll!TpSetPoolWorkerThreadIdleTimeout
-ntdll.dll!TpSetTimer
-ntdll.dll!TpSetTimerEx
-ntdll.dll!TpSetWait
-ntdll.dll!TpSetWaitEx
-ntdll.dll!TpSimpleTryPost
-ntdll.dll!TpStartAsyncIoOperation
-ntdll.dll!TpTrimPools
-ntdll.dll!TpWaitForAlpcCompletion
-ntdll.dll!TpWaitForIoCompletion
-ntdll.dll!TpWaitForJobNotification
-ntdll.dll!TpWaitForTimer
-ntdll.dll!TpWaitForWait
-ntdll.dll!TpWaitForWork
-ntdll.dll!WerReportSQMEvent
-ntdll.dll!WinSqmAddToAverageDWORD
-ntdll.dll!WinSqmAddToStream
-ntdll.dll!WinSqmAddToStreamEx
-ntdll.dll!WinSqmCheckEscalationAddToStreamEx
-ntdll.dll!WinSqmCheckEscalationSetDWORD64
-ntdll.dll!WinSqmCheckEscalationSetDWORD
-ntdll.dll!WinSqmCheckEscalationSetString
-ntdll.dll!WinSqmCommonDatapointDelete
-ntdll.dll!WinSqmCommonDatapointSetDWORD64
-ntdll.dll!WinSqmCommonDatapointSetDWORD
-ntdll.dll!WinSqmCommonDatapointSetStreamEx
-ntdll.dll!WinSqmCommonDatapointSetString
-ntdll.dll!WinSqmEndSession
-ntdll.dll!WinSqmEventEnabled
-ntdll.dll!WinSqmEventWrite
-ntdll.dll!WinSqmGetEscalationRuleStatus
-ntdll.dll!WinSqmGetInstrumentationProperty
-ntdll.dll!WinSqmIncrementDWORD
-ntdll.dll!WinSqmIsOptedIn
-ntdll.dll!WinSqmIsOptedInEx
-ntdll.dll!WinSqmIsSessionDisabled
-ntdll.dll!WinSqmSetDWORD64
-ntdll.dll!WinSqmSetDWORD
-ntdll.dll!WinSqmSetEscalationInfo
-ntdll.dll!WinSqmSetIfMaxDWORD
-ntdll.dll!WinSqmSetIfMinDWORD
-ntdll.dll!WinSqmSetString
-ntdll.dll!WinSqmStartSession
-ntdll.dll!WinSqmStartSessionForPartner
-ntdll.dll!ZwAcceptConnectPort
-ntdll.dll!ZwAccessCheck
-ntdll.dll!ZwAccessCheckAndAuditAlarm
-ntdll.dll!ZwAccessCheckByType
-ntdll.dll!ZwAccessCheckByTypeAndAuditAlarm
-ntdll.dll!ZwAccessCheckByTypeResultList
-ntdll.dll!ZwAccessCheckByTypeResultListAndAuditAlarm
-ntdll.dll!ZwAccessCheckByTypeResultListAndAuditAlarmByHandle
-ntdll.dll!ZwAddAtom
-ntdll.dll!ZwAddAtomEx
-ntdll.dll!ZwAddBootEntry
-ntdll.dll!ZwAddDriverEntry
-ntdll.dll!ZwAdjustGroupsToken
-ntdll.dll!ZwAdjustPrivilegesToken
-ntdll.dll!ZwAdjustTokenClaimsAndDeviceGroups
-ntdll.dll!ZwAlertResumeThread
-ntdll.dll!ZwAlertThread
-ntdll.dll!ZwAlertThreadByThreadId
-ntdll.dll!ZwAllocateLocallyUniqueId
-ntdll.dll!ZwAllocateReserveObject
-ntdll.dll!ZwAllocateUserPhysicalPages
-ntdll.dll!ZwAllocateUuids
-ntdll.dll!ZwAllocateVirtualMemory
-ntdll.dll!ZwAlpcAcceptConnectPort
-ntdll.dll!ZwAlpcCancelMessage
-ntdll.dll!ZwAlpcConnectPort
-ntdll.dll!ZwAlpcConnectPortEx
-ntdll.dll!ZwAlpcCreatePort
-ntdll.dll!ZwAlpcCreatePortSection
-ntdll.dll!ZwAlpcCreateResourceReserve
-ntdll.dll!ZwAlpcCreateSectionView
-ntdll.dll!ZwAlpcCreateSecurityContext
-ntdll.dll!ZwAlpcDeletePortSection
-ntdll.dll!ZwAlpcDeleteResourceReserve
-ntdll.dll!ZwAlpcDeleteSectionView
-ntdll.dll!ZwAlpcDeleteSecurityContext
-ntdll.dll!ZwAlpcDisconnectPort
-ntdll.dll!ZwAlpcImpersonateClientContainerOfPort
-ntdll.dll!ZwAlpcImpersonateClientOfPort
-ntdll.dll!ZwAlpcOpenSenderProcess
-ntdll.dll!ZwAlpcOpenSenderThread
-ntdll.dll!ZwAlpcQueryInformation
-ntdll.dll!ZwAlpcQueryInformationMessage
-ntdll.dll!ZwAlpcRevokeSecurityContext
-ntdll.dll!ZwAlpcSendWaitReceivePort
-ntdll.dll!ZwAlpcSetInformation
-ntdll.dll!ZwApphelpCacheControl
-ntdll.dll!ZwAreMappedFilesTheSame
-ntdll.dll!ZwAssignProcessToJobObject
-ntdll.dll!ZwAssociateWaitCompletionPacket
-ntdll.dll!ZwCallbackReturn
-ntdll.dll!ZwCancelIoFile
-ntdll.dll!ZwCancelIoFileEx
-ntdll.dll!ZwCancelSynchronousIoFile
-ntdll.dll!ZwCancelTimer2
-ntdll.dll!ZwCancelTimer
-ntdll.dll!ZwCancelWaitCompletionPacket
-ntdll.dll!ZwClearEvent
-ntdll.dll!ZwClose
-ntdll.dll!ZwCloseObjectAuditAlarm
-ntdll.dll!ZwCommitComplete
-ntdll.dll!ZwCommitEnlistment
-ntdll.dll!ZwCommitTransaction
-ntdll.dll!ZwCompactKeys
-ntdll.dll!ZwCompareObjects
-ntdll.dll!ZwCompareTokens
-ntdll.dll!ZwCompleteConnectPort
-ntdll.dll!ZwCompressKey
-ntdll.dll!ZwConnectPort
-ntdll.dll!ZwContinue
-ntdll.dll!ZwCreateDebugObject
-ntdll.dll!ZwCreateDirectoryObject
-ntdll.dll!ZwCreateDirectoryObjectEx
-ntdll.dll!ZwCreateEnlistment
-ntdll.dll!ZwCreateEvent
-ntdll.dll!ZwCreateEventPair
-ntdll.dll!ZwCreateFile
-ntdll.dll!ZwCreateIRTimer
-ntdll.dll!ZwCreateIoCompletion
-ntdll.dll!ZwCreateJobObject
-ntdll.dll!ZwCreateJobSet
-ntdll.dll!ZwCreateKey
-ntdll.dll!ZwCreateKeyTransacted
-ntdll.dll!ZwCreateKeyedEvent
-ntdll.dll!ZwCreateLowBoxToken
-ntdll.dll!ZwCreateMailslotFile
-ntdll.dll!ZwCreateMutant
-ntdll.dll!ZwCreateNamedPipeFile
-ntdll.dll!ZwCreatePagingFile
-ntdll.dll!ZwCreatePartition
-ntdll.dll!ZwCreatePort
-ntdll.dll!ZwCreatePrivateNamespace
-ntdll.dll!ZwCreateProcess
-ntdll.dll!ZwCreateProcessEx
-ntdll.dll!ZwCreateProfile
-ntdll.dll!ZwCreateProfileEx
-ntdll.dll!ZwCreateResourceManager
-ntdll.dll!ZwCreateSection
-ntdll.dll!ZwCreateSemaphore
-ntdll.dll!ZwCreateSymbolicLinkObject
-ntdll.dll!ZwCreateThread
-ntdll.dll!ZwCreateThreadEx
-ntdll.dll!ZwCreateTimer2
-ntdll.dll!ZwCreateTimer
-ntdll.dll!ZwCreateToken
-ntdll.dll!ZwCreateTokenEx
-ntdll.dll!ZwCreateTransaction
-ntdll.dll!ZwCreateTransactionManager
-ntdll.dll!ZwCreateUserProcess
-ntdll.dll!ZwCreateWaitCompletionPacket
-ntdll.dll!ZwCreateWaitablePort
-ntdll.dll!ZwCreateWnfStateName
-ntdll.dll!ZwCreateWorkerFactory
-ntdll.dll!ZwDebugActiveProcess
-ntdll.dll!ZwDebugContinue
-ntdll.dll!ZwDelayExecution
-ntdll.dll!ZwDeleteAtom
-ntdll.dll!ZwDeleteBootEntry
-ntdll.dll!ZwDeleteDriverEntry
-ntdll.dll!ZwDeleteFile
-ntdll.dll!ZwDeleteKey
-ntdll.dll!ZwDeleteObjectAuditAlarm
-ntdll.dll!ZwDeletePrivateNamespace
-ntdll.dll!ZwDeleteValueKey
-ntdll.dll!ZwDeleteWnfStateData
-ntdll.dll!ZwDeleteWnfStateName
-ntdll.dll!ZwDeviceIoControlFile
-ntdll.dll!ZwDisableLastKnownGood
-ntdll.dll!ZwDisplayString
-ntdll.dll!ZwDrawText
-ntdll.dll!ZwDuplicateObject
-ntdll.dll!ZwDuplicateToken
-ntdll.dll!ZwEnableLastKnownGood
-ntdll.dll!ZwEnumerateBootEntries
-ntdll.dll!ZwEnumerateDriverEntries
-ntdll.dll!ZwEnumerateKey
-ntdll.dll!ZwEnumerateSystemEnvironmentValuesEx
-ntdll.dll!ZwEnumerateTransactionObject
-ntdll.dll!ZwEnumerateValueKey
-ntdll.dll!ZwExtendSection
-ntdll.dll!ZwFilterBootOption
-ntdll.dll!ZwFilterToken
-ntdll.dll!ZwFilterTokenEx
-ntdll.dll!ZwFindAtom
-ntdll.dll!ZwFlushBuffersFile
-ntdll.dll!ZwFlushBuffersFileEx
-ntdll.dll!ZwFlushInstallUILanguage
-ntdll.dll!ZwFlushInstructionCache
-ntdll.dll!ZwFlushKey
-ntdll.dll!ZwFlushProcessWriteBuffers
-ntdll.dll!ZwFlushVirtualMemory
-ntdll.dll!ZwFlushWriteBuffer
-ntdll.dll!ZwFreeUserPhysicalPages
-ntdll.dll!ZwFreeVirtualMemory
-ntdll.dll!ZwFreezeRegistry
-ntdll.dll!ZwFreezeTransactions
-ntdll.dll!ZwFsControlFile
-ntdll.dll!ZwGetCachedSigningLevel
-ntdll.dll!ZwGetCompleteWnfStateSubscription
-ntdll.dll!ZwGetContextThread
-ntdll.dll!ZwGetCurrentProcessorNumber
-ntdll.dll!ZwGetCurrentProcessorNumberEx
-ntdll.dll!ZwGetDevicePowerState
-ntdll.dll!ZwGetMUIRegistryInfo
-ntdll.dll!ZwGetNextProcess
-ntdll.dll!ZwGetNextThread
-ntdll.dll!ZwGetNlsSectionPtr
-ntdll.dll!ZwGetNotificationResourceManager
-ntdll.dll!ZwGetWriteWatch
-ntdll.dll!ZwImpersonateAnonymousToken
-ntdll.dll!ZwImpersonateClientOfPort
-ntdll.dll!ZwImpersonateThread
-ntdll.dll!ZwInitializeNlsFiles
-ntdll.dll!ZwInitializeRegistry
-ntdll.dll!ZwInitiatePowerAction
-ntdll.dll!ZwIsProcessInJob
-ntdll.dll!ZwIsSystemResumeAutomatic
-ntdll.dll!ZwIsUILanguageComitted
-ntdll.dll!ZwListenPort
-ntdll.dll!ZwLoadDriver
-ntdll.dll!ZwLoadKey2
-ntdll.dll!ZwLoadKey
-ntdll.dll!ZwLoadKeyEx
-ntdll.dll!ZwLockFile
-ntdll.dll!ZwLockProductActivationKeys
-ntdll.dll!ZwLockRegistryKey
-ntdll.dll!ZwLockVirtualMemory
-ntdll.dll!ZwMakePermanentObject
-ntdll.dll!ZwMakeTemporaryObject
-ntdll.dll!ZwManagePartition
-ntdll.dll!ZwMapCMFModule
-ntdll.dll!ZwMapUserPhysicalPages
-ntdll.dll!ZwMapUserPhysicalPagesScatter
-ntdll.dll!ZwMapViewOfSection
-ntdll.dll!ZwModifyBootEntry
-ntdll.dll!ZwModifyDriverEntry
-ntdll.dll!ZwNotifyChangeDirectoryFile
-ntdll.dll!ZwNotifyChangeKey
-ntdll.dll!ZwNotifyChangeMultipleKeys
-ntdll.dll!ZwNotifyChangeSession
-ntdll.dll!ZwOpenDirectoryObject
-ntdll.dll!ZwOpenEnlistment
-ntdll.dll!ZwOpenEvent
-ntdll.dll!ZwOpenEventPair
-ntdll.dll!ZwOpenFile
-ntdll.dll!ZwOpenIoCompletion
-ntdll.dll!ZwOpenJobObject
-ntdll.dll!ZwOpenKey
-ntdll.dll!ZwOpenKeyEx
-ntdll.dll!ZwOpenKeyTransacted
-ntdll.dll!ZwOpenKeyTransactedEx
-ntdll.dll!ZwOpenKeyedEvent
-ntdll.dll!ZwOpenMutant
-ntdll.dll!ZwOpenObjectAuditAlarm
-ntdll.dll!ZwOpenPartition
-ntdll.dll!ZwOpenPrivateNamespace
-ntdll.dll!ZwOpenProcess
-ntdll.dll!ZwOpenProcessToken
-ntdll.dll!ZwOpenProcessTokenEx
-ntdll.dll!ZwOpenResourceManager
-ntdll.dll!ZwOpenSection
-ntdll.dll!ZwOpenSemaphore
-ntdll.dll!ZwOpenSession
-ntdll.dll!ZwOpenSymbolicLinkObject
-ntdll.dll!ZwOpenThread
-ntdll.dll!ZwOpenThreadToken
-ntdll.dll!ZwOpenThreadTokenEx
-ntdll.dll!ZwOpenTimer
-ntdll.dll!ZwOpenTransaction
-ntdll.dll!ZwOpenTransactionManager
-ntdll.dll!ZwPlugPlayControl
-ntdll.dll!ZwPowerInformation
-ntdll.dll!ZwPrePrepareComplete
-ntdll.dll!ZwPrePrepareEnlistment
-ntdll.dll!ZwPrepareComplete
-ntdll.dll!ZwPrepareEnlistment
-ntdll.dll!ZwPrivilegeCheck
-ntdll.dll!ZwPrivilegeObjectAuditAlarm
-ntdll.dll!ZwPrivilegedServiceAuditAlarm
-ntdll.dll!ZwPropagationComplete
-ntdll.dll!ZwPropagationFailed
-ntdll.dll!ZwProtectVirtualMemory
-ntdll.dll!ZwPulseEvent
-ntdll.dll!ZwQueryAttributesFile
-ntdll.dll!ZwQueryBootEntryOrder
-ntdll.dll!ZwQueryBootOptions
-ntdll.dll!ZwQueryDebugFilterState
-ntdll.dll!ZwQueryDefaultLocale
-ntdll.dll!ZwQueryDefaultUILanguage
-ntdll.dll!ZwQueryDirectoryFile
-ntdll.dll!ZwQueryDirectoryObject
-ntdll.dll!ZwQueryDriverEntryOrder
-ntdll.dll!ZwQueryEaFile
-ntdll.dll!ZwQueryEvent
-ntdll.dll!ZwQueryFullAttributesFile
-ntdll.dll!ZwQueryInformationAtom
-ntdll.dll!ZwQueryInformationEnlistment
-ntdll.dll!ZwQueryInformationFile
-ntdll.dll!ZwQueryInformationJobObject
-ntdll.dll!ZwQueryInformationPort
-ntdll.dll!ZwQueryInformationProcess
-ntdll.dll!ZwQueryInformationResourceManager
-ntdll.dll!ZwQueryInformationThread
-ntdll.dll!ZwQueryInformationToken
-ntdll.dll!ZwQueryInformationTransaction
-ntdll.dll!ZwQueryInformationTransactionManager
-ntdll.dll!ZwQueryInformationWorkerFactory
-ntdll.dll!ZwQueryInstallUILanguage
-ntdll.dll!ZwQueryIntervalProfile
-ntdll.dll!ZwQueryIoCompletion
-ntdll.dll!ZwQueryKey
-ntdll.dll!ZwQueryLicenseValue
-ntdll.dll!ZwQueryMultipleValueKey
-ntdll.dll!ZwQueryMutant
-ntdll.dll!ZwQueryObject
-ntdll.dll!ZwQueryOpenSubKeys
-ntdll.dll!ZwQueryOpenSubKeysEx
-ntdll.dll!ZwQueryPerformanceCounter
-ntdll.dll!ZwQueryPortInformationProcess
-ntdll.dll!ZwQueryQuotaInformationFile
-ntdll.dll!ZwQuerySection
-ntdll.dll!ZwQuerySecurityAttributesToken
-ntdll.dll!ZwQuerySecurityObject
-ntdll.dll!ZwQuerySemaphore
-ntdll.dll!ZwQuerySymbolicLinkObject
-ntdll.dll!ZwQuerySystemEnvironmentValue
-ntdll.dll!ZwQuerySystemEnvironmentValueEx
-ntdll.dll!ZwQuerySystemInformation
-ntdll.dll!ZwQuerySystemInformationEx
-ntdll.dll!ZwQuerySystemTime
-ntdll.dll!ZwQueryTimer
-ntdll.dll!ZwQueryTimerResolution
-ntdll.dll!ZwQueryValueKey
-ntdll.dll!ZwQueryVirtualMemory
-ntdll.dll!ZwQueryVolumeInformationFile
-ntdll.dll!ZwQueryWnfStateData
-ntdll.dll!ZwQueryWnfStateNameInformation
-ntdll.dll!ZwQueueApcThread
-ntdll.dll!ZwQueueApcThreadEx
-ntdll.dll!ZwRaiseException
-ntdll.dll!ZwRaiseHardError
-ntdll.dll!ZwReadFile
-ntdll.dll!ZwReadFileScatter
-ntdll.dll!ZwReadOnlyEnlistment
-ntdll.dll!ZwReadRequestData
-ntdll.dll!ZwReadVirtualMemory
-ntdll.dll!ZwRecoverEnlistment
-ntdll.dll!ZwRecoverResourceManager
-ntdll.dll!ZwRecoverTransactionManager
-ntdll.dll!ZwRegisterProtocolAddressInformation
-ntdll.dll!ZwRegisterThreadTerminatePort
-ntdll.dll!ZwReleaseKeyedEvent
-ntdll.dll!ZwReleaseMutant
-ntdll.dll!ZwReleaseSemaphore
-ntdll.dll!ZwReleaseWorkerFactoryWorker
-ntdll.dll!ZwRemoveIoCompletion
-ntdll.dll!ZwRemoveIoCompletionEx
-ntdll.dll!ZwRemoveProcessDebug
-ntdll.dll!ZwRenameKey
-ntdll.dll!ZwRenameTransactionManager
-ntdll.dll!ZwReplaceKey
-ntdll.dll!ZwReplacePartitionUnit
-ntdll.dll!ZwReplyPort
-ntdll.dll!ZwReplyWaitReceivePort
-ntdll.dll!ZwReplyWaitReceivePortEx
-ntdll.dll!ZwReplyWaitReplyPort
-ntdll.dll!ZwRequestPort
-ntdll.dll!ZwRequestWaitReplyPort
-ntdll.dll!ZwResetEvent
-ntdll.dll!ZwResetWriteWatch
-ntdll.dll!ZwRestoreKey
-ntdll.dll!ZwResumeProcess
-ntdll.dll!ZwResumeThread
-ntdll.dll!ZwRevertContainerImpersonation
-ntdll.dll!ZwRollbackComplete
-ntdll.dll!ZwRollbackEnlistment
-ntdll.dll!ZwRollbackTransaction
-ntdll.dll!ZwRollforwardTransactionManager
-ntdll.dll!ZwSaveKey
-ntdll.dll!ZwSaveKeyEx
-ntdll.dll!ZwSaveMergedKeys
-ntdll.dll!ZwSecureConnectPort
-ntdll.dll!ZwSerializeBoot
-ntdll.dll!ZwSetBootEntryOrder
-ntdll.dll!ZwSetBootOptions
-ntdll.dll!ZwSetCachedSigningLevel
-ntdll.dll!ZwSetContextThread
-ntdll.dll!ZwSetDebugFilterState
-ntdll.dll!ZwSetDefaultHardErrorPort
-ntdll.dll!ZwSetDefaultLocale
-ntdll.dll!ZwSetDefaultUILanguage
-ntdll.dll!ZwSetDriverEntryOrder
-ntdll.dll!ZwSetEaFile
-ntdll.dll!ZwSetEvent
-ntdll.dll!ZwSetEventBoostPriority
-ntdll.dll!ZwSetHighEventPair
-ntdll.dll!ZwSetHighWaitLowEventPair
-ntdll.dll!ZwSetIRTimer
-ntdll.dll!ZwSetInformationDebugObject
-ntdll.dll!ZwSetInformationEnlistment
-ntdll.dll!ZwSetInformationFile
-ntdll.dll!ZwSetInformationJobObject
-ntdll.dll!ZwSetInformationKey
-ntdll.dll!ZwSetInformationObject
-ntdll.dll!ZwSetInformationProcess
-ntdll.dll!ZwSetInformationResourceManager
-ntdll.dll!ZwSetInformationSymbolicLink
-ntdll.dll!ZwSetInformationThread
-ntdll.dll!ZwSetInformationToken
-ntdll.dll!ZwSetInformationTransaction
-ntdll.dll!ZwSetInformationTransactionManager
-ntdll.dll!ZwSetInformationVirtualMemory
-ntdll.dll!ZwSetInformationWorkerFactory
-ntdll.dll!ZwSetIntervalProfile
-ntdll.dll!ZwSetIoCompletion
-ntdll.dll!ZwSetIoCompletionEx
-ntdll.dll!ZwSetLdtEntries
-ntdll.dll!ZwSetLowEventPair
-ntdll.dll!ZwSetLowWaitHighEventPair
-ntdll.dll!ZwSetQuotaInformationFile
-ntdll.dll!ZwSetSecurityObject
-ntdll.dll!ZwSetSystemEnvironmentValue
-ntdll.dll!ZwSetSystemEnvironmentValueEx
-ntdll.dll!ZwSetSystemInformation
-ntdll.dll!ZwSetSystemPowerState
-ntdll.dll!ZwSetSystemTime
-ntdll.dll!ZwSetThreadExecutionState
-ntdll.dll!ZwSetTimer2
-ntdll.dll!ZwSetTimer
-ntdll.dll!ZwSetTimerEx
-ntdll.dll!ZwSetTimerResolution
-ntdll.dll!ZwSetUuidSeed
-ntdll.dll!ZwSetValueKey
-ntdll.dll!ZwSetVolumeInformationFile
-ntdll.dll!ZwSetWnfProcessNotificationEvent
-ntdll.dll!ZwShutdownSystem
-ntdll.dll!ZwShutdownWorkerFactory
-ntdll.dll!ZwSignalAndWaitForSingleObject
-ntdll.dll!ZwSinglePhaseReject
-ntdll.dll!ZwStartProfile
-ntdll.dll!ZwStopProfile
-ntdll.dll!ZwSubscribeWnfStateChange
-ntdll.dll!ZwSuspendProcess
-ntdll.dll!ZwSuspendThread
-ntdll.dll!ZwSystemDebugControl
-ntdll.dll!ZwTerminateJobObject
-ntdll.dll!ZwTerminateProcess
-ntdll.dll!ZwTerminateThread
-ntdll.dll!ZwTestAlert
-ntdll.dll!ZwThawRegistry
-ntdll.dll!ZwThawTransactions
-ntdll.dll!ZwTraceControl
-ntdll.dll!ZwTraceEvent
-ntdll.dll!ZwTranslateFilePath
-ntdll.dll!ZwUmsThreadYield
-ntdll.dll!ZwUnloadDriver
-ntdll.dll!ZwUnloadKey2
-ntdll.dll!ZwUnloadKey
-ntdll.dll!ZwUnloadKeyEx
-ntdll.dll!ZwUnlockFile
-ntdll.dll!ZwUnlockVirtualMemory
-ntdll.dll!ZwUnmapViewOfSection
-ntdll.dll!ZwUnmapViewOfSectionEx
-ntdll.dll!ZwUnsubscribeWnfStateChange
-ntdll.dll!ZwUpdateWnfStateData
-ntdll.dll!ZwVdmControl
-ntdll.dll!ZwWaitForAlertByThreadId
-ntdll.dll!ZwWaitForDebugEvent
-ntdll.dll!ZwWaitForKeyedEvent
-ntdll.dll!ZwWaitForMultipleObjects32
-ntdll.dll!ZwWaitForMultipleObjects
-ntdll.dll!ZwWaitForSingleObject
-ntdll.dll!ZwWaitForWorkViaWorkerFactory
-ntdll.dll!ZwWaitHighEventPair
-ntdll.dll!ZwWaitLowEventPair
-ntdll.dll!ZwWorkerFactoryWorkerReady
-ntdll.dll!ZwWriteFile
-ntdll.dll!ZwWriteFileGather
-ntdll.dll!ZwWriteRequestData
-ntdll.dll!ZwWriteVirtualMemory
-ntdll.dll!ZwYieldExecution
-ntdll.dll!vDbgPrintEx
-ntdll.dll!vDbgPrintExWithPrefix
-AUTHZ.dll!AuthzAccessCheck
-AUTHZ.dll!AuthzAddSidsToContext
-AUTHZ.dll!AuthzCachedAccessCheck
-AUTHZ.dll!AuthzEnumerateSecurityEventSources
-AUTHZ.dll!AuthzEvaluateSacl
-AUTHZ.dll!AuthzFreeAuditEvent
-AUTHZ.dll!AuthzFreeCentralAccessPolicyCache
-AUTHZ.dll!AuthzFreeContext
-AUTHZ.dll!AuthzFreeHandle
-AUTHZ.dll!AuthzFreeResourceManager
-AUTHZ.dll!AuthzGetInformationFromContext
-AUTHZ.dll!AuthziLogAuditEvent
-AUTHZ.dll!AuthzInitializeCompoundContext
-AUTHZ.dll!AuthzInitializeContextFromAuthzContext
-AUTHZ.dll!AuthzInitializeContextFromSid
-AUTHZ.dll!AuthzInitializeContextFromToken
-AUTHZ.dll!AuthzInitializeObjectAccessAuditEvent
-AUTHZ.dll!AuthzInitializeObjectAccessAuditEvent2
-AUTHZ.dll!AuthzInitializeRemoteAccessCheck
-AUTHZ.dll!AuthzInitializeRemoteResourceManager
-AUTHZ.dll!AuthzInitializeResourceManager
-AUTHZ.dll!AuthzInitializeResourceManagerEx
-AUTHZ.dll!AuthzInstallSecurityEventSource
-AUTHZ.dll!AuthzModifyClaims
-AUTHZ.dll!AuthzModifySecurityAttributes
-AUTHZ.dll!AuthzModifySids
-AUTHZ.dll!AuthzOpenObjectAudit
-AUTHZ.dll!AuthzRegisterCapChangeNotification
-AUTHZ.dll!AuthzRegisterSecurityEventSource
-AUTHZ.dll!AuthzReportSecurityEvent
-AUTHZ.dll!AuthzReportSecurityEventFromParams
-AUTHZ.dll!AuthzSetAppContainerInformation
-AUTHZ.dll!AuthzShutdownRemoteAccessCheck
-AUTHZ.dll!AuthzUninstallSecurityEventSource
-AUTHZ.dll!AuthzUnregisterCapChangeNotification
-AUTHZ.dll!AuthzUnregisterSecurityEventSource
-bcrypt.dll!BCryptAddContextFunction
-bcrypt.dll!BCryptCloseAlgorithmProvider
-bcrypt.dll!BCryptConfigureContext
-bcrypt.dll!BCryptConfigureContextFunction
-bcrypt.dll!BCryptCreateContext
-bcrypt.dll!BCryptCreateHash
-bcrypt.dll!BCryptCreateMultiHash
-bcrypt.dll!BCryptDecrypt
-bcrypt.dll!BCryptDeleteContext
-bcrypt.dll!BCryptDeriveKey
-bcrypt.dll!BCryptDeriveKeyCapi
-bcrypt.dll!BCryptDeriveKeyPBKDF2
-bcrypt.dll!BCryptDestroyHash
-bcrypt.dll!BCryptDestroyKey
-bcrypt.dll!BCryptDestroySecret
-bcrypt.dll!BCryptDuplicateHash
-bcrypt.dll!BCryptDuplicateKey
-bcrypt.dll!BCryptEncrypt
-bcrypt.dll!BCryptEnumAlgorithms
-bcrypt.dll!BCryptEnumContextFunctionProviders
-bcrypt.dll!BCryptEnumContextFunctions
-bcrypt.dll!BCryptEnumContexts
-bcrypt.dll!BCryptEnumProviders
-bcrypt.dll!BCryptEnumRegisteredProviders
-bcrypt.dll!BCryptExportKey
-bcrypt.dll!BCryptFinalizeKeyPair
-bcrypt.dll!BCryptFinishHash
-bcrypt.dll!BCryptFreeBuffer
-bcrypt.dll!BCryptGenerateKeyPair
-bcrypt.dll!BCryptGenerateSymmetricKey
-bcrypt.dll!BCryptGenRandom
-bcrypt.dll!BCryptGetFipsAlgorithmMode
-bcrypt.dll!BCryptGetProperty
-bcrypt.dll!BCryptHash
-bcrypt.dll!BCryptHashData
-bcrypt.dll!BCryptImportKey
-bcrypt.dll!BCryptImportKeyPair
-bcrypt.dll!BCryptKeyDerivation
-bcrypt.dll!BCryptOpenAlgorithmProvider
-bcrypt.dll!BCryptProcessMultiOperations
-bcrypt.dll!BCryptQueryContextConfiguration
-bcrypt.dll!BCryptQueryContextFunctionConfiguration
-bcrypt.dll!BCryptQueryContextFunctionProperty
-bcrypt.dll!BCryptQueryProviderRegistration
-bcrypt.dll!BCryptRegisterConfigChangeNotify
-bcrypt.dll!BCryptRemoveContextFunction
-bcrypt.dll!BCryptResolveProviders
-bcrypt.dll!BCryptSecretAgreement
-bcrypt.dll!BCryptSetAuditingInterface
-bcrypt.dll!BCryptSetContextFunctionProperty
-bcrypt.dll!BCryptSetProperty
-bcrypt.dll!BCryptSignHash
-bcrypt.dll!BCryptUnregisterConfigChangeNotify
-bcrypt.dll!BCryptVerifySignature
-Cabinet.dll!CloseCompressor
-Cabinet.dll!CloseDecompressor
-Cabinet.dll!Compress
-Cabinet.dll!CreateCompressor
-Cabinet.dll!CreateDecompressor
-Cabinet.dll!Decompress
-Cabinet.dll!DeleteExtractedFiles
-Cabinet.dll!DllGetVersion
-Cabinet.dll!Extract
-Cabinet.dll!FCIAddFile
-Cabinet.dll!FCICreate
-Cabinet.dll!FCIDestroy
-Cabinet.dll!FCIFlushCabinet
-Cabinet.dll!FCIFlushFolder
-Cabinet.dll!FDICopy
-Cabinet.dll!FDICreate
-Cabinet.dll!FDIDestroy
-Cabinet.dll!FDIIsCabinet
-Cabinet.dll!FDITruncateCabinet
-Cabinet.dll!GetDllVersion
-Cabinet.dll!QueryCompressorInformation
-Cabinet.dll!QueryDecompressorInformation
-Cabinet.dll!ResetCompressor
-Cabinet.dll!ResetDecompressor
-Cabinet.dll!SetCompressorInformation
-Cabinet.dll!SetDecompressorInformation
-CFGMGR32.dll!CM_Add_Empty_Log_Conf
-CFGMGR32.dll!CM_Add_Empty_Log_Conf_Ex
-CFGMGR32.dll!CM_Add_ID_ExA
-CFGMGR32.dll!CM_Add_ID_ExW
-CFGMGR32.dll!CM_Add_IDA
-CFGMGR32.dll!CM_Add_IDW
-CFGMGR32.dll!CM_Add_Range
-CFGMGR32.dll!CM_Add_Res_Des
-CFGMGR32.dll!CM_Add_Res_Des_Ex
-CFGMGR32.dll!CM_Connect_MachineA
-CFGMGR32.dll!CM_Connect_MachineW
-CFGMGR32.dll!CM_Create_DevNode_ExA
-CFGMGR32.dll!CM_Create_DevNode_ExW
-CFGMGR32.dll!CM_Create_DevNodeA
-CFGMGR32.dll!CM_Create_DevNodeW
-CFGMGR32.dll!CM_Create_Range_List
-CFGMGR32.dll!CM_Delete_Class_Key_Ex
-CFGMGR32.dll!CM_Delete_Device_Interface_Key_ExA
-CFGMGR32.dll!CM_Delete_Device_Interface_Key_ExW
-CFGMGR32.dll!CM_Delete_Device_Interface_KeyA
-CFGMGR32.dll!CM_Delete_DevNode_Key_Ex
-CFGMGR32.dll!CM_Delete_Range
-CFGMGR32.dll!CM_Detect_Resource_Conflict
-CFGMGR32.dll!CM_Detect_Resource_Conflict_Ex
-CFGMGR32.dll!CM_Disable_DevNode_Ex
-CFGMGR32.dll!CM_Disconnect_Machine
-CFGMGR32.dll!CM_Dup_Range_List
-CFGMGR32.dll!CM_Enable_DevNode_Ex
-CFGMGR32.dll!CM_Enumerate_Classes
-CFGMGR32.dll!CM_Enumerate_Classes_Ex
-CFGMGR32.dll!CM_Enumerate_Enumerators_ExA
-CFGMGR32.dll!CM_Enumerate_Enumerators_ExW
-CFGMGR32.dll!CM_Enumerate_EnumeratorsA
-CFGMGR32.dll!CM_Enumerate_EnumeratorsW
-CFGMGR32.dll!CM_Find_Range
-CFGMGR32.dll!CM_First_Range
-CFGMGR32.dll!CM_Free_Log_Conf
-CFGMGR32.dll!CM_Free_Log_Conf_Ex
-CFGMGR32.dll!CM_Free_Log_Conf_Handle
-CFGMGR32.dll!CM_Free_Range_List
-CFGMGR32.dll!CM_Free_Res_Des
-CFGMGR32.dll!CM_Free_Res_Des_Ex
-CFGMGR32.dll!CM_Free_Res_Des_Handle
-CFGMGR32.dll!CM_Free_Resource_Conflict_Handle
-CFGMGR32.dll!CM_Get_Child_Ex
-CFGMGR32.dll!CM_Get_Class_Key_Name_ExA
-CFGMGR32.dll!CM_Get_Class_Key_Name_ExW
-CFGMGR32.dll!CM_Get_Class_Key_NameA
-CFGMGR32.dll!CM_Get_Class_Key_NameW
-CFGMGR32.dll!CM_Get_Class_Name_ExA
-CFGMGR32.dll!CM_Get_Class_Name_ExW
-CFGMGR32.dll!CM_Get_Class_NameA
-CFGMGR32.dll!CM_Get_Class_NameW
-CFGMGR32.dll!CM_Get_Class_Property_ExW
-CFGMGR32.dll!CM_Get_Class_Property_Keys_Ex
-CFGMGR32.dll!CM_Get_Class_Registry_PropertyA
-CFGMGR32.dll!CM_Get_Depth_Ex
-CFGMGR32.dll!CM_Get_Device_ID_ExA
-CFGMGR32.dll!CM_Get_Device_ID_ExW
-CFGMGR32.dll!CM_Get_Device_ID_List_ExA
-CFGMGR32.dll!CM_Get_Device_ID_List_ExW
-CFGMGR32.dll!CM_Get_Device_ID_List_Size_ExA
-CFGMGR32.dll!CM_Get_Device_ID_List_Size_ExW
-CFGMGR32.dll!CM_Get_Device_ID_List_SizeA
-CFGMGR32.dll!CM_Get_Device_ID_ListA
-CFGMGR32.dll!CM_Get_Device_ID_Size_Ex
-CFGMGR32.dll!CM_Get_Device_IDA
-CFGMGR32.dll!CM_Get_Device_Interface_Alias_ExA
-CFGMGR32.dll!CM_Get_Device_Interface_Alias_ExW
-CFGMGR32.dll!CM_Get_Device_Interface_AliasA
-CFGMGR32.dll!CM_Get_Device_Interface_AliasW
-CFGMGR32.dll!CM_Get_Device_Interface_List_ExA
-CFGMGR32.dll!CM_Get_Device_Interface_List_ExW
-CFGMGR32.dll!CM_Get_Device_Interface_List_Size_ExA
-CFGMGR32.dll!CM_Get_Device_Interface_List_Size_ExW
-CFGMGR32.dll!CM_Get_Device_Interface_List_SizeA
-CFGMGR32.dll!CM_Get_Device_Interface_ListA
-CFGMGR32.dll!CM_Get_Device_Interface_Property_ExW
-CFGMGR32.dll!CM_Get_Device_Interface_Property_Keys_ExW
-CFGMGR32.dll!CM_Get_DevNode_Custom_Property_ExA
-CFGMGR32.dll!CM_Get_DevNode_Custom_Property_ExW
-CFGMGR32.dll!CM_Get_DevNode_Custom_PropertyA
-CFGMGR32.dll!CM_Get_DevNode_Custom_PropertyW
-CFGMGR32.dll!CM_Get_DevNode_Property_ExW
-CFGMGR32.dll!CM_Get_DevNode_Property_Keys_Ex
-CFGMGR32.dll!CM_Get_DevNode_Registry_Property_ExA
-CFGMGR32.dll!CM_Get_DevNode_Registry_Property_ExW
-CFGMGR32.dll!CM_Get_DevNode_Registry_PropertyA
-CFGMGR32.dll!CM_Get_DevNode_Status_Ex
-CFGMGR32.dll!CM_Get_First_Log_Conf
-CFGMGR32.dll!CM_Get_First_Log_Conf_Ex
-CFGMGR32.dll!CM_Get_Global_State
-CFGMGR32.dll!CM_Get_Global_State_Ex
-CFGMGR32.dll!CM_Get_Hardware_Profile_Info_ExA
-CFGMGR32.dll!CM_Get_Hardware_Profile_Info_ExW
-CFGMGR32.dll!CM_Get_Hardware_Profile_InfoA
-CFGMGR32.dll!CM_Get_Hardware_Profile_InfoW
-CFGMGR32.dll!CM_Get_HW_Prof_Flags_ExA
-CFGMGR32.dll!CM_Get_HW_Prof_Flags_ExW
-CFGMGR32.dll!CM_Get_HW_Prof_FlagsA
-CFGMGR32.dll!CM_Get_HW_Prof_FlagsW
-CFGMGR32.dll!CM_Get_Log_Conf_Priority
-CFGMGR32.dll!CM_Get_Log_Conf_Priority_Ex
-CFGMGR32.dll!CM_Get_Next_Log_Conf
-CFGMGR32.dll!CM_Get_Next_Log_Conf_Ex
-CFGMGR32.dll!CM_Get_Next_Res_Des
-CFGMGR32.dll!CM_Get_Next_Res_Des_Ex
-CFGMGR32.dll!CM_Get_Parent_Ex
-CFGMGR32.dll!CM_Get_Res_Des_Data
-CFGMGR32.dll!CM_Get_Res_Des_Data_Ex
-CFGMGR32.dll!CM_Get_Res_Des_Data_Size
-CFGMGR32.dll!CM_Get_Res_Des_Data_Size_Ex
-CFGMGR32.dll!CM_Get_Resource_Conflict_Count
-CFGMGR32.dll!CM_Get_Resource_Conflict_DetailsA
-CFGMGR32.dll!CM_Get_Resource_Conflict_DetailsW
-CFGMGR32.dll!CM_Get_Sibling_Ex
-CFGMGR32.dll!CM_Get_Version
-CFGMGR32.dll!CM_Get_Version_Ex
-CFGMGR32.dll!CM_Intersect_Range_List
-CFGMGR32.dll!CM_Invert_Range_List
-CFGMGR32.dll!CM_Is_Dock_Station_Present
-CFGMGR32.dll!CM_Is_Dock_Station_Present_Ex
-CFGMGR32.dll!CM_Is_Version_Available
-CFGMGR32.dll!CM_Is_Version_Available_Ex
-CFGMGR32.dll!CM_Locate_DevNode_ExA
-CFGMGR32.dll!CM_Locate_DevNode_ExW
-CFGMGR32.dll!CM_Locate_DevNodeA
-CFGMGR32.dll!CM_Merge_Range_List
-CFGMGR32.dll!CM_Modify_Res_Des
-CFGMGR32.dll!CM_Modify_Res_Des_Ex
-CFGMGR32.dll!CM_Move_DevNode
-CFGMGR32.dll!CM_Move_DevNode_Ex
-CFGMGR32.dll!CM_Next_Range
-CFGMGR32.dll!CM_Open_Class_Key_ExA
-CFGMGR32.dll!CM_Open_Class_Key_ExW
-CFGMGR32.dll!CM_Open_Class_KeyA
-CFGMGR32.dll!CM_Open_Device_Interface_Key_ExA
-CFGMGR32.dll!CM_Open_Device_Interface_Key_ExW
-CFGMGR32.dll!CM_Open_Device_Interface_KeyA
-CFGMGR32.dll!CM_Open_DevNode_Key_Ex
-CFGMGR32.dll!CM_Query_And_Remove_SubTree_ExA
-CFGMGR32.dll!CM_Query_And_Remove_SubTree_ExW
-CFGMGR32.dll!CM_Query_And_Remove_SubTreeA
-CFGMGR32.dll!CM_Query_Arbitrator_Free_Data
-CFGMGR32.dll!CM_Query_Arbitrator_Free_Data_Ex
-CFGMGR32.dll!CM_Query_Arbitrator_Free_Size
-CFGMGR32.dll!CM_Query_Arbitrator_Free_Size_Ex
-CFGMGR32.dll!CM_Query_Remove_SubTree
-CFGMGR32.dll!CM_Query_Remove_SubTree_Ex
-CFGMGR32.dll!CM_Query_Resource_Conflict_List
-CFGMGR32.dll!CM_Reenumerate_DevNode
-CFGMGR32.dll!CM_Reenumerate_DevNode_Ex
-CFGMGR32.dll!CM_Register_Device_Driver
-CFGMGR32.dll!CM_Register_Device_Driver_Ex
-CFGMGR32.dll!CM_Register_Device_Interface_ExA
-CFGMGR32.dll!CM_Register_Device_Interface_ExW
-CFGMGR32.dll!CM_Register_Device_InterfaceA
-CFGMGR32.dll!CM_Register_Device_InterfaceW
-CFGMGR32.dll!CM_Remove_SubTree
-CFGMGR32.dll!CM_Remove_SubTree_Ex
-CFGMGR32.dll!CM_Request_Device_Eject_ExA
-CFGMGR32.dll!CM_Request_Device_Eject_ExW
-CFGMGR32.dll!CM_Request_Device_EjectA
-CFGMGR32.dll!CM_Request_Device_EjectW
-CFGMGR32.dll!CM_Request_Eject_PC
-CFGMGR32.dll!CM_Request_Eject_PC_Ex
-CFGMGR32.dll!CM_Run_Detection
-CFGMGR32.dll!CM_Run_Detection_Ex
-CFGMGR32.dll!CM_Set_Class_Property_ExW
-CFGMGR32.dll!CM_Set_Class_Registry_PropertyA
-CFGMGR32.dll!CM_Set_Device_Interface_Property_ExW
-CFGMGR32.dll!CM_Set_DevNode_Problem
-CFGMGR32.dll!CM_Set_DevNode_Problem_Ex
-CFGMGR32.dll!CM_Set_DevNode_Property_ExW
-CFGMGR32.dll!CM_Set_DevNode_Registry_Property_ExA
-CFGMGR32.dll!CM_Set_DevNode_Registry_Property_ExW
-CFGMGR32.dll!CM_Set_DevNode_Registry_PropertyA
-CFGMGR32.dll!CM_Set_HW_Prof
-CFGMGR32.dll!CM_Set_HW_Prof_Ex
-CFGMGR32.dll!CM_Set_HW_Prof_Flags_ExA
-CFGMGR32.dll!CM_Set_HW_Prof_Flags_ExW
-CFGMGR32.dll!CM_Set_HW_Prof_FlagsA
-CFGMGR32.dll!CM_Set_HW_Prof_FlagsW
-CFGMGR32.dll!CM_Setup_DevNode_Ex
-CFGMGR32.dll!CM_Test_Range_Available
-CFGMGR32.dll!CM_Uninstall_DevNode_Ex
-CFGMGR32.dll!CM_Unregister_Device_Interface_ExA
-CFGMGR32.dll!CM_Unregister_Device_Interface_ExW
-CFGMGR32.dll!CM_Unregister_Device_InterfaceA
-CFGMGR32.dll!CM_Unregister_Device_InterfaceW
-CFGMGR32.dll!CMP_GetServerSideDeviceInstallFlags
-CFGMGR32.dll!CMP_WaitNoPendingInstallEvents
-CRYPT32.dll!CertAddCertificateContextToStore
-CRYPT32.dll!CertAddCertificateLinkToStore
-CRYPT32.dll!CertAddCRLContextToStore
-CRYPT32.dll!CertAddCRLLinkToStore
-CRYPT32.dll!CertAddCTLContextToStore
-CRYPT32.dll!CertAddCTLLinkToStore
-CRYPT32.dll!CertAddEncodedCertificateToStore
-CRYPT32.dll!CertAddEncodedCertificateToSystemStoreA
-CRYPT32.dll!CertAddEncodedCertificateToSystemStoreW
-CRYPT32.dll!CertAddEncodedCRLToStore
-CRYPT32.dll!CertAddEncodedCTLToStore
-CRYPT32.dll!CertAddEnhancedKeyUsageIdentifier
-CRYPT32.dll!CertAddRefServerOcspResponse
-CRYPT32.dll!CertAddRefServerOcspResponseContext
-CRYPT32.dll!CertAddSerializedElementToStore
-CRYPT32.dll!CertAddStoreToCollection
-CRYPT32.dll!CertAlgIdToOID
-CRYPT32.dll!CertCloseServerOcspResponse
-CRYPT32.dll!CertCloseStore
-CRYPT32.dll!CertCompareCertificate
-CRYPT32.dll!CertCompareCertificateName
-CRYPT32.dll!CertCompareIntegerBlob
-CRYPT32.dll!CertComparePublicKeyInfo
-CRYPT32.dll!CertControlStore
-CRYPT32.dll!CertCreateCertificateChainEngine
-CRYPT32.dll!CertCreateCertificateContext
-CRYPT32.dll!CertCreateContext
-CRYPT32.dll!CertCreateCRLContext
-CRYPT32.dll!CertCreateCTLContext
-CRYPT32.dll!CertCreateCTLEntryFromCertificateContextProperties
-CRYPT32.dll!CertCreateSelfSignCertificate
-CRYPT32.dll!CertDeleteCertificateFromStore
-CRYPT32.dll!CertDeleteCRLFromStore
-CRYPT32.dll!CertDeleteCTLFromStore
-CRYPT32.dll!CertDuplicateCertificateChain
-CRYPT32.dll!CertDuplicateCertificateContext
-CRYPT32.dll!CertDuplicateCRLContext
-CRYPT32.dll!CertDuplicateCTLContext
-CRYPT32.dll!CertDuplicateStore
-CRYPT32.dll!CertEnumCertificateContextProperties
-CRYPT32.dll!CertEnumCertificatesInStore
-CRYPT32.dll!CertEnumCRLContextProperties
-CRYPT32.dll!CertEnumCRLsInStore
-CRYPT32.dll!CertEnumCTLContextProperties
-CRYPT32.dll!CertEnumCTLsInStore
-CRYPT32.dll!CertEnumPhysicalStore
-CRYPT32.dll!CertEnumSubjectInSortedCTL
-CRYPT32.dll!CertEnumSystemStore
-CRYPT32.dll!CertEnumSystemStoreLocation
-CRYPT32.dll!CertFindAttribute
-CRYPT32.dll!CertFindCertificateInCRL
-CRYPT32.dll!CertFindCertificateInStore
-CRYPT32.dll!CertFindChainInStore
-CRYPT32.dll!CertFindCRLInStore
-CRYPT32.dll!CertFindCTLInStore
-CRYPT32.dll!CertFindExtension
-CRYPT32.dll!CertFindRDNAttr
-CRYPT32.dll!CertFindSubjectInCTL
-CRYPT32.dll!CertFindSubjectInSortedCTL
-CRYPT32.dll!CertFreeCertificateChain
-CRYPT32.dll!CertFreeCertificateChainEngine
-CRYPT32.dll!CertFreeCertificateChainList
-CRYPT32.dll!CertFreeCertificateContext
-CRYPT32.dll!CertFreeCRLContext
-CRYPT32.dll!CertFreeCTLContext
-CRYPT32.dll!CertFreeServerOcspResponseContext
-CRYPT32.dll!CertGetCertificateChain
-CRYPT32.dll!CertGetCertificateContextProperty
-CRYPT32.dll!CertGetCRLContextProperty
-CRYPT32.dll!CertGetCRLFromStore
-CRYPT32.dll!CertGetCTLContextProperty
-CRYPT32.dll!CertGetEnhancedKeyUsage
-CRYPT32.dll!CertGetIntendedKeyUsage
-CRYPT32.dll!CertGetIssuerCertificateFromStore
-CRYPT32.dll!CertGetNameStringA
-CRYPT32.dll!CertGetNameStringW
-CRYPT32.dll!CertGetPublicKeyLength
-CRYPT32.dll!CertGetServerOcspResponseContext
-CRYPT32.dll!CertGetStoreProperty
-CRYPT32.dll!CertGetSubjectCertificateFromStore
-CRYPT32.dll!CertGetValidUsages
-CRYPT32.dll!CertIsRDNAttrsInCertificateName
-CRYPT32.dll!CertIsStrongHashToSign
-CRYPT32.dll!CertIsValidCRLForCertificate
-CRYPT32.dll!CertIsWeakHash
-CRYPT32.dll!CertNameToStrA
-CRYPT32.dll!CertNameToStrW
-CRYPT32.dll!CertOIDToAlgId
-CRYPT32.dll!CertOpenServerOcspResponse
-CRYPT32.dll!CertOpenStore
-CRYPT32.dll!CertOpenSystemStoreA
-CRYPT32.dll!CertOpenSystemStoreW
-CRYPT32.dll!CertRDNValueToStrA
-CRYPT32.dll!CertRDNValueToStrW
-CRYPT32.dll!CertRegisterPhysicalStore
-CRYPT32.dll!CertRegisterSystemStore
-CRYPT32.dll!CertRemoveEnhancedKeyUsageIdentifier
-CRYPT32.dll!CertRemoveStoreFromCollection
-CRYPT32.dll!CertResyncCertificateChainEngine
-CRYPT32.dll!CertRetrieveLogoOrBiometricInfo
-CRYPT32.dll!CertSaveStore
-CRYPT32.dll!CertSelectCertificateChains
-CRYPT32.dll!CertSerializeCertificateStoreElement
-CRYPT32.dll!CertSerializeCRLStoreElement
-CRYPT32.dll!CertSerializeCTLStoreElement
-CRYPT32.dll!CertSetCertificateContextPropertiesFromCTLEntry
-CRYPT32.dll!CertSetCertificateContextProperty
-CRYPT32.dll!CertSetCRLContextProperty
-CRYPT32.dll!CertSetCTLContextProperty
-CRYPT32.dll!CertSetEnhancedKeyUsage
-CRYPT32.dll!CertSetStoreProperty
-CRYPT32.dll!CertStrToNameA
-CRYPT32.dll!CertStrToNameW
-CRYPT32.dll!CertUnregisterPhysicalStore
-CRYPT32.dll!CertUnregisterSystemStore
-CRYPT32.dll!CertVerifyCertificateChainPolicy
-CRYPT32.dll!CertVerifyCRLRevocation
-CRYPT32.dll!CertVerifyCRLTimeValidity
-CRYPT32.dll!CertVerifyCTLUsage
-CRYPT32.dll!CertVerifyRevocation
-CRYPT32.dll!CertVerifySubjectCertificateContext
-CRYPT32.dll!CertVerifyTimeValidity
-CRYPT32.dll!CertVerifyValidityNesting
-CRYPT32.dll!CryptAcquireCertificatePrivateKey
-CRYPT32.dll!CryptBinaryToStringA
-CRYPT32.dll!CryptBinaryToStringW
-CRYPT32.dll!CryptCloseAsyncHandle
-CRYPT32.dll!CryptCreateAsyncHandle
-CRYPT32.dll!CryptCreateKeyIdentifierFromCSP
-CRYPT32.dll!CryptDecodeMessage
-CRYPT32.dll!CryptDecodeObject
-CRYPT32.dll!CryptDecodeObjectEx
-CRYPT32.dll!CryptDecryptAndVerifyMessageSignature
-CRYPT32.dll!CryptDecryptMessage
-CRYPT32.dll!CryptEncodeObject
-CRYPT32.dll!CryptEncodeObjectEx
-CRYPT32.dll!CryptEncryptMessage
-CRYPT32.dll!CryptEnumKeyIdentifierProperties
-CRYPT32.dll!CryptEnumOIDFunction
-CRYPT32.dll!CryptEnumOIDInfo
-CRYPT32.dll!CryptExportPKCS8
-CRYPT32.dll!CryptExportPublicKeyInfo
-CRYPT32.dll!CryptExportPublicKeyInfoEx
-CRYPT32.dll!CryptExportPublicKeyInfoFromBCryptKeyHandle
-CRYPT32.dll!CryptFindCertificateKeyProvInfo
-CRYPT32.dll!CryptFindLocalizedName
-CRYPT32.dll!CryptFindOIDInfo
-CRYPT32.dll!CryptFormatObject
-CRYPT32.dll!CryptFreeOIDFunctionAddress
-CRYPT32.dll!CryptGetAsyncParam
-CRYPT32.dll!CryptGetDefaultOIDDllList
-CRYPT32.dll!CryptGetDefaultOIDFunctionAddress
-CRYPT32.dll!CryptGetKeyIdentifierProperty
-CRYPT32.dll!CryptGetMessageCertificates
-CRYPT32.dll!CryptGetMessageSignerCount
-CRYPT32.dll!CryptGetOIDFunctionAddress
-CRYPT32.dll!CryptGetOIDFunctionValue
-CRYPT32.dll!CryptHashCertificate
-CRYPT32.dll!CryptHashCertificate2
-CRYPT32.dll!CryptHashMessage
-CRYPT32.dll!CryptHashPublicKeyInfo
-CRYPT32.dll!CryptHashToBeSigned
-CRYPT32.dll!CryptImportPKCS8
-CRYPT32.dll!CryptImportPublicKeyInfo
-CRYPT32.dll!CryptImportPublicKeyInfoEx
-CRYPT32.dll!CryptImportPublicKeyInfoEx2
-CRYPT32.dll!CryptInitOIDFunctionSet
-CRYPT32.dll!CryptInstallDefaultContext
-CRYPT32.dll!CryptInstallOIDFunctionAddress
-CRYPT32.dll!CryptLoadSip
-CRYPT32.dll!CryptMemAlloc
-CRYPT32.dll!CryptMemFree
-CRYPT32.dll!CryptMemRealloc
-CRYPT32.dll!CryptMsgCalculateEncodedLength
-CRYPT32.dll!CryptMsgClose
-CRYPT32.dll!CryptMsgControl
-CRYPT32.dll!CryptMsgCountersign
-CRYPT32.dll!CryptMsgCountersignEncoded
-CRYPT32.dll!CryptMsgDuplicate
-CRYPT32.dll!CryptMsgEncodeAndSignCTL
-CRYPT32.dll!CryptMsgGetAndVerifySigner
-CRYPT32.dll!CryptMsgGetParam
-CRYPT32.dll!CryptMsgOpenToDecode
-CRYPT32.dll!CryptMsgOpenToEncode
-CRYPT32.dll!CryptMsgSignCTL
-CRYPT32.dll!CryptMsgUpdate
-CRYPT32.dll!CryptMsgVerifyCountersignatureEncoded
-CRYPT32.dll!CryptMsgVerifyCountersignatureEncodedEx
-CRYPT32.dll!CryptProtectData
-CRYPT32.dll!CryptProtectMemory
-CRYPT32.dll!CryptQueryObject
-CRYPT32.dll!CryptRegisterDefaultOIDFunction
-CRYPT32.dll!CryptRegisterOIDFunction
-CRYPT32.dll!CryptRegisterOIDInfo
-CRYPT32.dll!CryptRetrieveTimeStamp
-CRYPT32.dll!CryptSetAsyncParam
-CRYPT32.dll!CryptSetKeyIdentifierProperty
-CRYPT32.dll!CryptSetOIDFunctionValue
-CRYPT32.dll!CryptSignAndEncodeCertificate
-CRYPT32.dll!CryptSignAndEncryptMessage
-CRYPT32.dll!CryptSignCertificate
-CRYPT32.dll!CryptSignMessage
-CRYPT32.dll!CryptSignMessageWithKey
-CRYPT32.dll!CryptSIPAddProvider
-CRYPT32.dll!CryptSIPCreateIndirectData
-CRYPT32.dll!CryptSIPGetCaps
-CRYPT32.dll!CryptSIPGetSealedDigest
-CRYPT32.dll!CryptSIPGetSignedDataMsg
-CRYPT32.dll!CryptSIPLoad
-CRYPT32.dll!CryptSIPPutSignedDataMsg
-CRYPT32.dll!CryptSIPRemoveProvider
-CRYPT32.dll!CryptSIPRemoveSignedDataMsg
-CRYPT32.dll!CryptSIPRetrieveSubjectGuid
-CRYPT32.dll!CryptSIPRetrieveSubjectGuidForCatalogFile
-CRYPT32.dll!CryptSIPVerifyIndirectData
-CRYPT32.dll!CryptStringToBinaryA
-CRYPT32.dll!CryptStringToBinaryW
-CRYPT32.dll!CryptUninstallDefaultContext
-CRYPT32.dll!CryptUnprotectData
-CRYPT32.dll!CryptUnprotectMemory
-CRYPT32.dll!CryptUnregisterDefaultOIDFunction
-CRYPT32.dll!CryptUnregisterOIDFunction
-CRYPT32.dll!CryptUnregisterOIDInfo
-CRYPT32.dll!CryptUpdateProtectedState
-CRYPT32.dll!CryptVerifyCertificateSignature
-CRYPT32.dll!CryptVerifyCertificateSignatureEx
-CRYPT32.dll!CryptVerifyDetachedMessageHash
-CRYPT32.dll!CryptVerifyDetachedMessageSignature
-CRYPT32.dll!CryptVerifyMessageHash
-CRYPT32.dll!CryptVerifyMessageSignature
-CRYPT32.dll!CryptVerifyMessageSignatureWithKey
-CRYPT32.dll!CryptVerifyTimeStampSignature
-CRYPT32.dll!DbgInitOSS
-CRYPT32.dll!DbgPrintf
-CRYPT32.dll!PFXExportCertStore
-CRYPT32.dll!PFXExportCertStore2
-CRYPT32.dll!PFXExportCertStoreEx
-CRYPT32.dll!PFXImportCertStore
-CRYPT32.dll!PFXIsPFXBlob
-CRYPT32.dll!PFXVerifyPassword
-CRYPTBASE.dll!SystemFunction001
-CRYPTBASE.dll!SystemFunction002
-CRYPTBASE.dll!SystemFunction003
-CRYPTBASE.dll!SystemFunction004
-CRYPTBASE.dll!SystemFunction005
-CRYPTBASE.dll!SystemFunction028
-CRYPTBASE.dll!SystemFunction029
-CRYPTBASE.dll!SystemFunction034
-cryptdll.dll!aesCTSDecryptMsg
-cryptdll.dll!aesCTSEncryptMsg
-cryptdll.dll!CDBuildIntegrityVect
-cryptdll.dll!CDBuildVect
-cryptdll.dll!CDFindCommonCSystem
-cryptdll.dll!CDFindCommonCSystemWithKey
-cryptdll.dll!CDGenerateRandomBits
-cryptdll.dll!CDGetIntegrityVect
-cryptdll.dll!CDLocateCheckSum
-cryptdll.dll!CDLocateCSystem
-cryptdll.dll!CDLocateRng
-cryptdll.dll!CDRegisterCheckSum
-cryptdll.dll!CDRegisterCSystem
-cryptdll.dll!CDRegisterRng
-cryptdll.dll!HMACwithSHA
-cryptdll.dll!KRBFXCF2
-cryptdll.dll!MD5Final
-cryptdll.dll!MD5Init
-cryptdll.dll!MD5Update
-cryptdll.dll!PBKDF2
-CRYPTNET.dll!CryptGetObjectUrl
-CRYPTNET.dll!CryptInstallCancelRetrieval
-CRYPTNET.dll!CryptRetrieveObjectByUrlA
-CRYPTNET.dll!CryptRetrieveObjectByUrlW
-CRYPTNET.dll!CryptUninstallCancelRetrieval
-dfscli.dll!NetDfsAdd
-dfscli.dll!NetDfsAddFtRoot
-dfscli.dll!NetDfsAddRootTarget
-dfscli.dll!NetDfsAddStdRoot
-dfscli.dll!NetDfsAddStdRootForced
-dfscli.dll!NetDfsEnum
-dfscli.dll!NetDfsGetClientInfo
-dfscli.dll!NetDfsGetDcAddress
-dfscli.dll!NetDfsGetFtContainerSecurity
-dfscli.dll!NetDfsGetInfo
-dfscli.dll!NetDfsGetSecurity
-dfscli.dll!NetDfsGetStdContainerSecurity
-dfscli.dll!NetDfsGetSupportedNamespaceVersion
-dfscli.dll!NetDfsManagerInitialize
-dfscli.dll!NetDfsManagerSendSiteInfo
-dfscli.dll!NetDfsMove
-dfscli.dll!NetDfsRemove
-dfscli.dll!NetDfsRemoveFtRoot
-dfscli.dll!NetDfsRemoveFtRootForced
-dfscli.dll!NetDfsRemoveRootTarget
-dfscli.dll!NetDfsRemoveStdRoot
-dfscli.dll!NetDfsSetClientInfo
-dfscli.dll!NetDfsSetFtContainerSecurity
-dfscli.dll!NetDfsSetInfo
-dfscli.dll!NetDfsSetSecurity
-dfscli.dll!NetDfsSetStdContainerSecurity
-DNSAPI.dll!AdaptiveTimeout_ClearInterfaceSpecificConfiguration
-DNSAPI.dll!AdaptiveTimeout_ResetAdaptiveTimeout
-DNSAPI.dll!AddRefQueryBlobEx
-DNSAPI.dll!BreakRecordsIntoBlob
-DNSAPI.dll!Coalesce_UpdateNetVersion
-DNSAPI.dll!CombineRecordsInBlob
-DNSAPI.dll!DelaySortDAServerlist
-DNSAPI.dll!DeRefQueryBlobEx
-DNSAPI.dll!Dns_AddRecordsToMessage
-DNSAPI.dll!Dns_AllocateMsgBuf
-DNSAPI.dll!Dns_BuildPacket
-DNSAPI.dll!Dns_CacheServiceCleanup
-DNSAPI.dll!Dns_CacheServiceInit
-DNSAPI.dll!Dns_CacheServiceStopIssued
-DNSAPI.dll!Dns_CleanupWinsock
-DNSAPI.dll!Dns_CloseConnection
-DNSAPI.dll!Dns_CloseSocket
-DNSAPI.dll!Dns_CreateMulticastSocket
-DNSAPI.dll!Dns_CreateSocket
-DNSAPI.dll!Dns_CreateSocketEx
-DNSAPI.dll!Dns_ExtractRecordsFromMessage
-DNSAPI.dll!Dns_FindAuthoritativeZoneLib
-DNSAPI.dll!Dns_FreeMsgBuf
-DNSAPI.dll!Dns_GetRandomXid
-DNSAPI.dll!Dns_InitializeMsgBuf
-DNSAPI.dll!Dns_InitializeMsgRemoteSockaddr
-DNSAPI.dll!Dns_InitializeWinsock
-DNSAPI.dll!Dns_OpenTcpConnectionAndSend
-DNSAPI.dll!Dns_ParseMessage
-DNSAPI.dll!Dns_ParsePacketRecord
-DNSAPI.dll!Dns_PingAdapterServers
-DNSAPI.dll!Dns_ReadPacketName
-DNSAPI.dll!Dns_ReadPacketNameAllocate
-DNSAPI.dll!Dns_ReadRecordStructureFromPacket
-DNSAPI.dll!Dns_RecvTcp
-DNSAPI.dll!Dns_ResetNetworkInfo
-DNSAPI.dll!Dns_SendAndRecvUdp
-DNSAPI.dll!Dns_SendEx
-DNSAPI.dll!Dns_SetRecordDatalength
-DNSAPI.dll!Dns_SetRecordsSection
-DNSAPI.dll!Dns_SetRecordsTtl
-DNSAPI.dll!Dns_SkipPacketName
-DNSAPI.dll!Dns_SkipToRecord
-DNSAPI.dll!Dns_UpdateLib
-DNSAPI.dll!Dns_UpdateLibEx
-DNSAPI.dll!Dns_WriteDottedNameToPacket
-DNSAPI.dll!Dns_WriteQuestionToMessage
-DNSAPI.dll!Dns_WriteRecordStructureToPacketEx
-DNSAPI.dll!DnsAcquireContextHandle_A
-DNSAPI.dll!DnsAcquireContextHandle_W
-DNSAPI.dll!DnsAllocateRecord
-DNSAPI.dll!DnsApiAlloc
-DNSAPI.dll!DnsApiAllocZero
-DNSAPI.dll!DnsApiFree
-DNSAPI.dll!DnsApiHeapReset
-DNSAPI.dll!DnsApiRealloc
-DNSAPI.dll!DnsApiSetDebugGlobals
-DNSAPI.dll!DnsAsyncRegisterHostAddrs
-DNSAPI.dll!DnsAsyncRegisterInit
-DNSAPI.dll!DnsAsyncRegisterTerm
-DNSAPI.dll!DnsCancelQuery
-DNSAPI.dll!DnsCopyStringEx
-DNSAPI.dll!DnsCreateReverseNameStringForIpAddress
-DNSAPI.dll!DnsCreateStandardDnsNameCopy
-DNSAPI.dll!DnsCreateStringCopy
-DNSAPI.dll!DnsDeRegisterLocal
-DNSAPI.dll!DnsDhcpRegisterAddrs
-DNSAPI.dll!DnsDhcpRegisterHostAddrs
-DNSAPI.dll!DnsDhcpRegisterInit
-DNSAPI.dll!DnsDhcpRegisterTerm
-DNSAPI.dll!DnsDhcpRemoveRegistrations
-DNSAPI.dll!DnsDhcpSrvRegisterHostAddr
-DNSAPI.dll!DnsDhcpSrvRegisterHostAddrEx
-DNSAPI.dll!DnsDhcpSrvRegisterHostName
-DNSAPI.dll!DnsDhcpSrvRegisterHostNameEx
-DNSAPI.dll!DnsDhcpSrvRegisterInit
-DNSAPI.dll!DnsDhcpSrvRegisterInitialize
-DNSAPI.dll!DnsDhcpSrvRegisterTerm
-DNSAPI.dll!DnsDisableIdnEncoding
-DNSAPI.dll!DnsDowncaseDnsNameLabel
-DNSAPI.dll!DnsExtractRecordsFromMessage_UTF8
-DNSAPI.dll!DnsExtractRecordsFromMessage_W
-DNSAPI.dll!DnsFindAuthoritativeZone
-DNSAPI.dll!DnsFlushResolverCache
-DNSAPI.dll!DnsFlushResolverCacheEntry_A
-DNSAPI.dll!DnsFlushResolverCacheEntry_UTF8
-DNSAPI.dll!DnsFlushResolverCacheEntry_W
-DNSAPI.dll!DnsFree
-DNSAPI.dll!DnsFreeConfigStructure
-DNSAPI.dll!DnsFreePolicyConfig
-DNSAPI.dll!DnsFreeProxyName
-DNSAPI.dll!DnsGetBufferLengthForStringCopy
-DNSAPI.dll!DnsGetCacheDataTable
-DNSAPI.dll!DnsGetDnsServerList
-DNSAPI.dll!DnsGetDomainName
-DNSAPI.dll!DnsGetLastFailedUpdateInfo
-DNSAPI.dll!DnsGetPolicyTableInfo
-DNSAPI.dll!DnsGetPolicyTableInfoPrivate
-DNSAPI.dll!DnsGetPrimaryDomainName_A
-DNSAPI.dll!DnsGetProxyInfoPrivate
-DNSAPI.dll!DnsGetProxyInformation
-DNSAPI.dll!DnsGetQueryRetryTimeouts
-DNSAPI.dll!DnsGlobals
-DNSAPI.dll!DnsIpv6AddressToString
-DNSAPI.dll!DnsIpv6StringToAddress
-DNSAPI.dll!DnsIsAMailboxType
-DNSAPI.dll!DnsIsNSECType
-DNSAPI.dll!DnsIsStatusRcode
-DNSAPI.dll!DnsIsStringCountValidForTextType
-DNSAPI.dll!DnsLogEvent
-DNSAPI.dll!DnsMapRcodeToStatus
-DNSAPI.dll!DnsModifyRecordsInSet_A
-DNSAPI.dll!DnsModifyRecordsInSet_UTF8
-DNSAPI.dll!DnsModifyRecordsInSet_W
-DNSAPI.dll!DnsNameCompare_A
-DNSAPI.dll!DnsNameCompare_UTF8
-DNSAPI.dll!DnsNameCompare_W
-DNSAPI.dll!DnsNameCompareEx_A
-DNSAPI.dll!DnsNameCompareEx_UTF8
-DNSAPI.dll!DnsNameCompareEx_W
-DNSAPI.dll!DnsNameCopy
-DNSAPI.dll!DnsNameCopyAllocate
-DNSAPI.dll!DnsNetworkInfo_CreateFromFAZ
-DNSAPI.dll!DnsNetworkInformation_CreateFromFAZ
-DNSAPI.dll!DnsNotifyResolver
-DNSAPI.dll!DnsNotifyResolverClusterIp
-DNSAPI.dll!DnsNotifyResolverEx
-DNSAPI.dll!DnsQuery_A
-DNSAPI.dll!DnsQuery_UTF8
-DNSAPI.dll!DnsQuery_W
-DNSAPI.dll!DnsQueryConfig
-DNSAPI.dll!DnsQueryConfigAllocEx
-DNSAPI.dll!DnsQueryConfigDword
-DNSAPI.dll!DnsQueryEx
-DNSAPI.dll!DnsQueryExA
-DNSAPI.dll!DnsQueryExUTF8
-DNSAPI.dll!DnsQueryExW
-DNSAPI.dll!DnsRecordBuild_UTF8
-DNSAPI.dll!DnsRecordBuild_W
-DNSAPI.dll!DnsRecordCompare
-DNSAPI.dll!DnsRecordCopyEx
-DNSAPI.dll!DnsRecordListFree
-DNSAPI.dll!DnsRecordListUnmapV4MappedAAAAInPlace
-DNSAPI.dll!DnsRecordSetCompare
-DNSAPI.dll!DnsRecordSetCopyEx
-DNSAPI.dll!DnsRecordSetDetach
-DNSAPI.dll!DnsRecordStringForType
-DNSAPI.dll!DnsRecordStringForWritableType
-DNSAPI.dll!DnsRecordTypeForName
-DNSAPI.dll!DnsRegisterLocal
-DNSAPI.dll!DnsReleaseContextHandle
-DNSAPI.dll!DnsRemoveRegistrations
-DNSAPI.dll!DnsReplaceRecordSetA
-DNSAPI.dll!DnsReplaceRecordSetUTF8
-DNSAPI.dll!DnsReplaceRecordSetW
-DNSAPI.dll!DnsResetQueryRetryTimeouts
-DNSAPI.dll!DnsResolverOp
-DNSAPI.dll!DnsScreenLocalAddrsForRegistration
-DNSAPI.dll!DnsServiceBrowse
-DNSAPI.dll!DnsServiceBrowseCancel
-DNSAPI.dll!DnsServiceConstructInstance
-DNSAPI.dll!DnsServiceCopyInstance
-DNSAPI.dll!DnsServiceDeRegister
-DNSAPI.dll!DnsServiceFreeInstance
-DNSAPI.dll!DnsServiceRegister
-DNSAPI.dll!DnsServiceRegisterCancel
-DNSAPI.dll!DnsServiceResolve
-DNSAPI.dll!DnsServiceResolveCancel
-DNSAPI.dll!DnsSetConfigDword
-DNSAPI.dll!DnsSetQueryRetryTimeouts
-DNSAPI.dll!DnsStartMulticastQuery
-DNSAPI.dll!DnsStatusString
-DNSAPI.dll!DnsStopMulticastQuery
-DNSAPI.dll!DnsStringCopyAllocateEx
-DNSAPI.dll!DnsTraceServerConfig
-DNSAPI.dll!DnsUnicodeToUtf8
-DNSAPI.dll!DnsUpdate
-DNSAPI.dll!DnsUpdateMachinePresence
-DNSAPI.dll!DnsUpdateTest_A
-DNSAPI.dll!DnsUpdateTest_UTF8
-DNSAPI.dll!DnsUpdateTest_W
-DNSAPI.dll!DnsUtf8ToUnicode
-DNSAPI.dll!DnsValidateName_A
-DNSAPI.dll!DnsValidateName_UTF8
-DNSAPI.dll!DnsValidateName_W
-DNSAPI.dll!DnsValidateNameOrIp_TempW
-DNSAPI.dll!DnsValidateServer_A
-DNSAPI.dll!DnsValidateServer_W
-DNSAPI.dll!DnsValidateServerArray_A
-DNSAPI.dll!DnsValidateServerArray_W
-DNSAPI.dll!DnsValidateServerStatus
-DNSAPI.dll!DnsValidateUtf8Byte
-DNSAPI.dll!DnsWriteQuestionToBuffer_UTF8
-DNSAPI.dll!DnsWriteQuestionToBuffer_W
-DNSAPI.dll!DnsWriteReverseNameStringForIpAddress
-DNSAPI.dll!ExtraInfo_Init
-DNSAPI.dll!Faz_AreServerListsInSameNameSpace
-DNSAPI.dll!FlushDnsPolicyUnreachableStatus
-DNSAPI.dll!GetCurrentTimeInSeconds
-DNSAPI.dll!HostsFile_Close
-DNSAPI.dll!HostsFile_Open
-DNSAPI.dll!HostsFile_ReadLine
-DNSAPI.dll!IpHelp_IsAddrOnLink
-DNSAPI.dll!Local_GetRecordsForLocalName
-DNSAPI.dll!Local_GetRecordsForLocalNameEx
-DNSAPI.dll!NetInfo_Build
-DNSAPI.dll!NetInfo_Clean
-DNSAPI.dll!NetInfo_Copy
-DNSAPI.dll!NetInfo_CopyNetworkIndex
-DNSAPI.dll!NetInfo_CreatePerNetworkNetinfo
-DNSAPI.dll!NetInfo_Free
-DNSAPI.dll!NetInfo_GetAdapterByAddress
-DNSAPI.dll!NetInfo_GetAdapterByInterfaceIndex
-DNSAPI.dll!NetInfo_GetAdapterByName
-DNSAPI.dll!NetInfo_IsAddrConfig
-DNSAPI.dll!NetInfo_IsForUpdate
-DNSAPI.dll!NetInfo_IsTcpipConfigChange
-DNSAPI.dll!NetInfo_ResetServerPriorities
-DNSAPI.dll!NetInfo_UpdateDnsInterfaceConfigChange
-DNSAPI.dll!NetInfo_UpdateNetworkProperties
-DNSAPI.dll!NetInfo_UpdateServerReachability
-DNSAPI.dll!Query_Cancel
-DNSAPI.dll!Query_Main
-DNSAPI.dll!QueryDirectEx
-DNSAPI.dll!Reg_FreeUpdateInfo
-DNSAPI.dll!Reg_GetValueEx
-DNSAPI.dll!Reg_ReadGlobalsEx
-DNSAPI.dll!Reg_ReadUpdateInfo
-DNSAPI.dll!Security_ContextListTimeout
-DNSAPI.dll!Send_AndRecvUdpWithParam
-DNSAPI.dll!Send_MessagePrivate
-DNSAPI.dll!Send_MessagePrivateEx
-DNSAPI.dll!Send_OpenTcpConnectionAndSend
-DNSAPI.dll!Socket_CacheCleanup
-DNSAPI.dll!Socket_CacheInit
-DNSAPI.dll!Socket_CleanupWinsock
-DNSAPI.dll!Socket_ClearMessageSockets
-DNSAPI.dll!Socket_CloseEx
-DNSAPI.dll!Socket_CloseMessageSockets
-DNSAPI.dll!Socket_Create
-DNSAPI.dll!Socket_CreateMulticast
-DNSAPI.dll!Socket_InitWinsock
-DNSAPI.dll!Socket_JoinMulticast
-DNSAPI.dll!Socket_RecvFrom
-DNSAPI.dll!Socket_SetMulticastInterface
-DNSAPI.dll!Socket_SetMulticastLoopBack
-DNSAPI.dll!Socket_SetTtl
-DNSAPI.dll!Socket_TcpListen
-DNSAPI.dll!Trace_Reset
-DNSAPI.dll!Update_ReplaceAddressRecordsW
-DNSAPI.dll!Util_IsIp6Running
-DSPARSE.dll!DsCrackSpn2A
-DSPARSE.dll!DsCrackSpn2W
-DSPARSE.dll!DsCrackSpn3W
-DSPARSE.dll!DsCrackSpn4W
-DSPARSE.dll!DsCrackSpnA
-DSPARSE.dll!DsCrackSpnW
-DSPARSE.dll!DsCrackUnquotedMangledRdnA
-DSPARSE.dll!DsCrackUnquotedMangledRdnW
-DSPARSE.dll!DsGetRdnW
-DSPARSE.dll!DsIsMangledDnA
-DSPARSE.dll!DsIsMangledDnW
-DSPARSE.dll!DsIsMangledRdnValueA
-DSPARSE.dll!DsIsMangledRdnValueW
-DSPARSE.dll!DsMakeSpnA
-DSPARSE.dll!DsMakeSpnW
-DSPARSE.dll!DsQuoteRdnValueA
-DSPARSE.dll!DsQuoteRdnValueW
-DSPARSE.dll!DsUnquoteRdnValueA
-DSPARSE.dll!DsUnquoteRdnValueW
-DSROLE.dll!DsRoleFreeMemory
-DSROLE.dll!DsRoleGetPrimaryDomainInformation
-httpapi.dll!HttpAddFragmentToCache
-httpapi.dll!HttpAddUrl
-httpapi.dll!HttpAddUrlToUrlGroup
-httpapi.dll!HttpCancelHttpRequest
-httpapi.dll!HttpCloseRequestQueue
-httpapi.dll!HttpCloseServerSession
-httpapi.dll!HttpCloseUrlGroup
-httpapi.dll!HttpCreateHttpHandle
-httpapi.dll!HttpCreateRequestQueue
-httpapi.dll!HttpCreateServerSession
-httpapi.dll!HttpCreateUrlGroup
-httpapi.dll!HttpDeclarePush
-httpapi.dll!HttpDeleteServiceConfiguration
-httpapi.dll!HttpFlushResponseCache
-httpapi.dll!HttpInitialize
-httpapi.dll!HttpPrepareUrl
-httpapi.dll!HttpQueryRequestQueueProperty
-httpapi.dll!HttpQueryServerSessionProperty
-httpapi.dll!HttpQueryServiceConfiguration
-httpapi.dll!HttpQueryUrlGroupProperty
-httpapi.dll!HttpReadFragmentFromCache
-httpapi.dll!HttpReceiveClientCertificate
-httpapi.dll!HttpReceiveHttpRequest
-httpapi.dll!HttpReceiveRequestEntityBody
-httpapi.dll!HttpRemoveUrl
-httpapi.dll!HttpRemoveUrlFromUrlGroup
-httpapi.dll!HttpSendHttpResponse
-httpapi.dll!HttpSendResponseEntityBody
-httpapi.dll!HttpSetRequestQueueProperty
-httpapi.dll!HttpSetServerSessionProperty
-httpapi.dll!HttpSetServiceConfiguration
-httpapi.dll!HttpSetUrlGroupProperty
-httpapi.dll!HttpShutdownRequestQueue
-httpapi.dll!HttpTerminate
-httpapi.dll!HttpWaitForDemandStart
-httpapi.dll!HttpWaitForDisconnect
-imagehlp.dll!BindImage
-imagehlp.dll!BindImageEx
-imagehlp.dll!CheckSumMappedFile
-imagehlp.dll!EnumerateLoadedModules
-imagehlp.dll!EnumerateLoadedModules64
-imagehlp.dll!EnumerateLoadedModulesEx
-imagehlp.dll!EnumerateLoadedModulesExW
-imagehlp.dll!EnumerateLoadedModulesW64
-imagehlp.dll!FindDebugInfoFile
-imagehlp.dll!FindDebugInfoFileEx
-imagehlp.dll!FindExecutableImage
-imagehlp.dll!FindExecutableImageEx
-imagehlp.dll!FindFileInPath
-imagehlp.dll!FindFileInSearchPath
-imagehlp.dll!GetImageConfigInformation
-imagehlp.dll!GetImageUnusedHeaderBytes
-imagehlp.dll!GetSymLoadError
-imagehlp.dll!GetTimestampForLoadedLibrary
-imagehlp.dll!ImageAddCertificate
-imagehlp.dll!ImageDirectoryEntryToData
-imagehlp.dll!ImageDirectoryEntryToDataEx
-imagehlp.dll!ImageEnumerateCertificates
-imagehlp.dll!ImageGetCertificateData
-imagehlp.dll!ImageGetCertificateHeader
-imagehlp.dll!ImageGetDigestStream
-imagehlp.dll!ImagehlpApiVersion
-imagehlp.dll!ImagehlpApiVersionEx
-imagehlp.dll!ImageLoad
-imagehlp.dll!ImageNtHeader
-imagehlp.dll!ImageRemoveCertificate
-imagehlp.dll!ImageRvaToSection
-imagehlp.dll!ImageRvaToVa
-imagehlp.dll!ImageUnload
-imagehlp.dll!MakeSureDirectoryPathExists
-imagehlp.dll!MapAndLoad
-imagehlp.dll!MapDebugInformation
-imagehlp.dll!MapFileAndCheckSumA
-imagehlp.dll!MapFileAndCheckSumW
-imagehlp.dll!ReBaseImage
-imagehlp.dll!ReBaseImage64
-imagehlp.dll!RemoveInvalidModuleList
-imagehlp.dll!ReportSymbolLoadSummary
-imagehlp.dll!SearchTreeForFile
-imagehlp.dll!SetCheckUserInterruptShared
-imagehlp.dll!SetImageConfigInformation
-imagehlp.dll!SetSymLoadError
-imagehlp.dll!SplitSymbols
-imagehlp.dll!StackWalk
-imagehlp.dll!StackWalk64
-imagehlp.dll!StackWalkEx
-imagehlp.dll!SymAddrIncludeInlineTrace
-imagehlp.dll!SymCleanup
-imagehlp.dll!SymCompareInlineTrace
-imagehlp.dll!SymEnumerateModules
-imagehlp.dll!SymEnumerateModules64
-imagehlp.dll!SymEnumerateSymbols
-imagehlp.dll!SymEnumerateSymbols64
-imagehlp.dll!SymEnumerateSymbolsW
-imagehlp.dll!SymEnumerateSymbolsW64
-imagehlp.dll!SymEnumSym
-imagehlp.dll!SymEnumSymbols
-imagehlp.dll!SymEnumSymbolsEx
-imagehlp.dll!SymEnumSymbolsExW
-imagehlp.dll!SymEnumSymbolsForAddr
-imagehlp.dll!SymEnumTypes
-imagehlp.dll!SymEnumTypesByName
-imagehlp.dll!SymEnumTypesByNameW
-imagehlp.dll!SymEnumTypesW
-imagehlp.dll!SymFindFileInPath
-imagehlp.dll!SymFindFileInPathW
-imagehlp.dll!SymFreeDiaString
-imagehlp.dll!SymFromAddr
-imagehlp.dll!SymFromInlineContext
-imagehlp.dll!SymFromInlineContextW
-imagehlp.dll!SymFromName
-imagehlp.dll!SymFunctionTableAccess
-imagehlp.dll!SymFunctionTableAccess64
-imagehlp.dll!SymFunctionTableAccess64AccessRoutines
-imagehlp.dll!SymGetDiaSession
-imagehlp.dll!SymGetLineFromAddr
-imagehlp.dll!SymGetLineFromAddr64
-imagehlp.dll!SymGetLineFromInlineContext
-imagehlp.dll!SymGetLineFromInlineContextW
-imagehlp.dll!SymGetLineFromName
-imagehlp.dll!SymGetLineFromName64
-imagehlp.dll!SymGetLineNext
-imagehlp.dll!SymGetLineNext64
-imagehlp.dll!SymGetLinePrev
-imagehlp.dll!SymGetLinePrev64
-imagehlp.dll!SymGetModuleBase
-imagehlp.dll!SymGetModuleBase64
-imagehlp.dll!SymGetModuleInfo
-imagehlp.dll!SymGetModuleInfo64
-imagehlp.dll!SymGetModuleInfoW
-imagehlp.dll!SymGetModuleInfoW64
-imagehlp.dll!SymGetOptions
-imagehlp.dll!SymGetSearchPath
-imagehlp.dll!SymGetSourceFileFromTokenW
-imagehlp.dll!SymGetSourceFileTokenW
-imagehlp.dll!SymGetSourceVarFromTokenW
-imagehlp.dll!SymGetSymbolFile
-imagehlp.dll!SymGetSymbolFileW
-imagehlp.dll!SymGetSymFromAddr
-imagehlp.dll!SymGetSymFromAddr64
-imagehlp.dll!SymGetSymFromName
-imagehlp.dll!SymGetSymFromName64
-imagehlp.dll!SymGetSymNext
-imagehlp.dll!SymGetSymNext64
-imagehlp.dll!SymGetSymPrev
-imagehlp.dll!SymGetSymPrev64
-imagehlp.dll!SymGetTypeFromName
-imagehlp.dll!SymGetTypeFromNameW
-imagehlp.dll!SymGetTypeInfo
-imagehlp.dll!SymGetTypeInfoEx
-imagehlp.dll!SymInitialize
-imagehlp.dll!SymLoadModule
-imagehlp.dll!SymLoadModule64
-imagehlp.dll!SymMatchFileName
-imagehlp.dll!SymMatchFileNameW
-imagehlp.dll!SymMatchString
-imagehlp.dll!SymMatchStringA
-imagehlp.dll!SymMatchStringW
-imagehlp.dll!SymQueryInlineTrace
-imagehlp.dll!SymRegisterCallback
-imagehlp.dll!SymRegisterCallback64
-imagehlp.dll!SymRegisterFunctionEntryCallback
-imagehlp.dll!SymRegisterFunctionEntryCallback64
-imagehlp.dll!SymSetContext
-imagehlp.dll!SymSetOptions
-imagehlp.dll!SymSetScopeFromAddr
-imagehlp.dll!SymSetScopeFromIndex
-imagehlp.dll!SymSetScopeFromInlineContext
-imagehlp.dll!SymSetSearchPath
-imagehlp.dll!SymSrvGetFileIndexes
-imagehlp.dll!SymSrvGetFileIndexesW
-imagehlp.dll!SymSrvGetFileIndexString
-imagehlp.dll!SymSrvGetFileIndexStringW
-imagehlp.dll!SymUnDName
-imagehlp.dll!SymUnDName64
-imagehlp.dll!SymUnloadModule
-imagehlp.dll!SymUnloadModule64
-imagehlp.dll!TouchFileTimes
-imagehlp.dll!UnDecorateSymbolName
-imagehlp.dll!UnMapAndLoad
-imagehlp.dll!UnmapDebugInformation
-imagehlp.dll!UpdateDebugInfoFile
-imagehlp.dll!UpdateDebugInfoFileEx
-IPHLPAPI.DLL!_PfAddFiltersToInterface@24
-IPHLPAPI.DLL!_PfAddGlobalFilterToInterface@8
-IPHLPAPI.DLL!_PfBindInterfaceToIndex@16
-IPHLPAPI.DLL!_PfBindInterfaceToIPAddress@12
-IPHLPAPI.DLL!_PfCreateInterface@24
-IPHLPAPI.DLL!_PfDeleteInterface@4
-IPHLPAPI.DLL!_PfDeleteLog@0
-IPHLPAPI.DLL!_PfGetInterfaceStatistics@16
-IPHLPAPI.DLL!_PfMakeLog@4
-IPHLPAPI.DLL!_PfRebindFilters@8
-IPHLPAPI.DLL!_PfRemoveFilterHandles@12
-IPHLPAPI.DLL!_PfRemoveFiltersFromInterface@20
-IPHLPAPI.DLL!_PfRemoveGlobalFilterFromInterface@8
-IPHLPAPI.DLL!_PfSetLogBuffer@28
-IPHLPAPI.DLL!_PfTestPacket@20
-IPHLPAPI.DLL!_PfUnBindInterface@4
-IPHLPAPI.DLL!AddIPAddress
-IPHLPAPI.DLL!AllocateAndGetInterfaceInfoFromStack
-IPHLPAPI.DLL!AllocateAndGetIpAddrTableFromStack
-IPHLPAPI.DLL!CancelIPChangeNotify
-IPHLPAPI.DLL!CancelMibChangeNotify2
-IPHLPAPI.DLL!CloseCompartment
-IPHLPAPI.DLL!CloseGetIPPhysicalInterfaceForDestination
-IPHLPAPI.DLL!ConvertCompartmentGuidToId
-IPHLPAPI.DLL!ConvertCompartmentIdToGuid
-IPHLPAPI.DLL!ConvertGuidToStringA
-IPHLPAPI.DLL!ConvertGuidToStringW
-IPHLPAPI.DLL!ConvertInterfaceAliasToLuid
-IPHLPAPI.DLL!ConvertInterfaceGuidToLuid
-IPHLPAPI.DLL!ConvertInterfaceIndexToLuid
-IPHLPAPI.DLL!ConvertInterfaceLuidToAlias
-IPHLPAPI.DLL!ConvertInterfaceLuidToGuid
-IPHLPAPI.DLL!ConvertInterfaceLuidToIndex
-IPHLPAPI.DLL!ConvertInterfaceLuidToNameA
-IPHLPAPI.DLL!ConvertInterfaceLuidToNameW
-IPHLPAPI.DLL!ConvertInterfaceNameToLuidA
-IPHLPAPI.DLL!ConvertInterfaceNameToLuidW
-IPHLPAPI.DLL!ConvertInterfacePhysicalAddressToLuid
-IPHLPAPI.DLL!ConvertIpv4MaskToLength
-IPHLPAPI.DLL!ConvertLengthToIpv4Mask
-IPHLPAPI.DLL!ConvertRemoteInterfaceAliasToLuid
-IPHLPAPI.DLL!ConvertRemoteInterfaceGuidToLuid
-IPHLPAPI.DLL!ConvertRemoteInterfaceIndexToLuid
-IPHLPAPI.DLL!ConvertRemoteInterfaceLuidToAlias
-IPHLPAPI.DLL!ConvertRemoteInterfaceLuidToGuid
-IPHLPAPI.DLL!ConvertRemoteInterfaceLuidToIndex
-IPHLPAPI.DLL!ConvertStringToGuidA
-IPHLPAPI.DLL!ConvertStringToGuidW
-IPHLPAPI.DLL!ConvertStringToInterfacePhysicalAddress
-IPHLPAPI.DLL!CreateAnycastIpAddressEntry
-IPHLPAPI.DLL!CreateCompartment
-IPHLPAPI.DLL!CreateIpForwardEntry
-IPHLPAPI.DLL!CreateIpForwardEntry2
-IPHLPAPI.DLL!CreateIpNetEntry
-IPHLPAPI.DLL!CreateIpNetEntry2
-IPHLPAPI.DLL!CreatePersistentTcpPortReservation
-IPHLPAPI.DLL!CreatePersistentUdpPortReservation
-IPHLPAPI.DLL!CreateProxyArpEntry
-IPHLPAPI.DLL!CreateSortedAddressPairs
-IPHLPAPI.DLL!CreateUnicastIpAddressEntry
-IPHLPAPI.DLL!DeleteAnycastIpAddressEntry
-IPHLPAPI.DLL!DeleteCompartment
-IPHLPAPI.DLL!DeleteIPAddress
-IPHLPAPI.DLL!DeleteIpForwardEntry
-IPHLPAPI.DLL!DeleteIpForwardEntry2
-IPHLPAPI.DLL!DeleteIpNetEntry
-IPHLPAPI.DLL!DeleteIpNetEntry2
-IPHLPAPI.DLL!DeletePersistentTcpPortReservation
-IPHLPAPI.DLL!DeletePersistentUdpPortReservation
-IPHLPAPI.DLL!DeleteProxyArpEntry
-IPHLPAPI.DLL!DeleteUnicastIpAddressEntry
-IPHLPAPI.DLL!DisableMediaSense
-IPHLPAPI.DLL!EnableRouter
-IPHLPAPI.DLL!FlushIpNetTable
-IPHLPAPI.DLL!FlushIpNetTable2
-IPHLPAPI.DLL!FlushIpPathTable
-IPHLPAPI.DLL!FreeMibTable
-IPHLPAPI.DLL!GetAdapterIndex
-IPHLPAPI.DLL!GetAdapterOrderMap
-IPHLPAPI.DLL!GetAdaptersAddresses
-IPHLPAPI.DLL!GetAdaptersInfo
-IPHLPAPI.DLL!GetAnycastIpAddressEntry
-IPHLPAPI.DLL!GetAnycastIpAddressTable
-IPHLPAPI.DLL!GetBestInterface
-IPHLPAPI.DLL!GetBestInterfaceEx
-IPHLPAPI.DLL!GetBestRoute
-IPHLPAPI.DLL!GetBestRoute2
-IPHLPAPI.DLL!GetCurrentThreadCompartmentId
-IPHLPAPI.DLL!GetCurrentThreadCompartmentScope
-IPHLPAPI.DLL!GetExtendedTcpTable
-IPHLPAPI.DLL!GetExtendedUdpTable
-IPHLPAPI.DLL!GetFriendlyIfIndex
-IPHLPAPI.DLL!GetIcmpStatistics
-IPHLPAPI.DLL!GetIcmpStatisticsEx
-IPHLPAPI.DLL!GetIfEntry
-IPHLPAPI.DLL!GetIfEntry2
-IPHLPAPI.DLL!GetIfStackTable
-IPHLPAPI.DLL!GetIfTable
-IPHLPAPI.DLL!GetIfTable2
-IPHLPAPI.DLL!GetIfTable2Ex
-IPHLPAPI.DLL!GetInterfaceInfo
-IPHLPAPI.DLL!GetInvertedIfStackTable
-IPHLPAPI.DLL!GetIpAddrTable
-IPHLPAPI.DLL!GetIpErrorString
-IPHLPAPI.DLL!GetIpForwardEntry2
-IPHLPAPI.DLL!GetIpForwardTable
-IPHLPAPI.DLL!GetIpForwardTable2
-IPHLPAPI.DLL!GetIpInterfaceEntry
-IPHLPAPI.DLL!GetIpInterfaceTable
-IPHLPAPI.DLL!GetIpNetEntry2
-IPHLPAPI.DLL!GetIpNetTable
-IPHLPAPI.DLL!GetIpNetTable2
-IPHLPAPI.DLL!GetIpNetworkConnectionBandwidthEstimates
-IPHLPAPI.DLL!GetIpPathEntry
-IPHLPAPI.DLL!GetIpPathTable
-IPHLPAPI.DLL!GetIpStatistics
-IPHLPAPI.DLL!GetIpStatisticsEx
-IPHLPAPI.DLL!GetJobCompartmentId
-IPHLPAPI.DLL!GetMulticastIpAddressEntry
-IPHLPAPI.DLL!GetMulticastIpAddressTable
-IPHLPAPI.DLL!GetNetworkInformation
-IPHLPAPI.DLL!GetNetworkParams
-IPHLPAPI.DLL!GetNumberOfInterfaces
-IPHLPAPI.DLL!GetOwnerModuleFromPidAndInfo
-IPHLPAPI.DLL!GetOwnerModuleFromTcp6Entry
-IPHLPAPI.DLL!GetOwnerModuleFromTcpEntry
-IPHLPAPI.DLL!GetOwnerModuleFromUdp6Entry
-IPHLPAPI.DLL!GetOwnerModuleFromUdpEntry
-IPHLPAPI.DLL!GetPerAdapterInfo
-IPHLPAPI.DLL!GetPerTcp6ConnectionEStats
-IPHLPAPI.DLL!GetPerTcp6ConnectionStats
-IPHLPAPI.DLL!GetPerTcpConnectionEStats
-IPHLPAPI.DLL!GetPerTcpConnectionStats
-IPHLPAPI.DLL!GetRTTAndHopCount
-IPHLPAPI.DLL!GetSessionCompartmentId
-IPHLPAPI.DLL!GetTcp6Table
-IPHLPAPI.DLL!GetTcp6Table2
-IPHLPAPI.DLL!GetTcpStatistics
-IPHLPAPI.DLL!GetTcpStatisticsEx
-IPHLPAPI.DLL!GetTcpTable
-IPHLPAPI.DLL!GetTcpTable2
-IPHLPAPI.DLL!GetTeredoPort
-IPHLPAPI.DLL!GetUdp6Table
-IPHLPAPI.DLL!GetUdpStatistics
-IPHLPAPI.DLL!GetUdpStatisticsEx
-IPHLPAPI.DLL!GetUdpTable
-IPHLPAPI.DLL!GetUnicastIpAddressEntry
-IPHLPAPI.DLL!GetUnicastIpAddressTable
-IPHLPAPI.DLL!GetUniDirectionalAdapterInfo
-IPHLPAPI.DLL!GetWPAOACSupportLevel
-IPHLPAPI.DLL!Icmp6CreateFile
-IPHLPAPI.DLL!Icmp6ParseReplies
-IPHLPAPI.DLL!Icmp6SendEcho2
-IPHLPAPI.DLL!IcmpCloseHandle
-IPHLPAPI.DLL!IcmpCreateFile
-IPHLPAPI.DLL!IcmpParseReplies
-IPHLPAPI.DLL!IcmpSendEcho
-IPHLPAPI.DLL!IcmpSendEcho2
-IPHLPAPI.DLL!IcmpSendEcho2Ex
-IPHLPAPI.DLL!if_indextoname
-IPHLPAPI.DLL!if_nametoindex
-IPHLPAPI.DLL!InitializeCompartmentEntry
-IPHLPAPI.DLL!InitializeIpForwardEntry
-IPHLPAPI.DLL!InitializeIpInterfaceEntry
-IPHLPAPI.DLL!InitializeUnicastIpAddressEntry
-IPHLPAPI.DLL!InternalCleanupPersistentStore
-IPHLPAPI.DLL!InternalCreateAnycastIpAddressEntry
-IPHLPAPI.DLL!InternalCreateIpForwardEntry
-IPHLPAPI.DLL!InternalCreateIpForwardEntry2
-IPHLPAPI.DLL!InternalCreateIpNetEntry
-IPHLPAPI.DLL!InternalCreateIpNetEntry2
-IPHLPAPI.DLL!InternalCreateUnicastIpAddressEntry
-IPHLPAPI.DLL!InternalDeleteAnycastIpAddressEntry
-IPHLPAPI.DLL!InternalDeleteIpForwardEntry
-IPHLPAPI.DLL!InternalDeleteIpForwardEntry2
-IPHLPAPI.DLL!InternalDeleteIpNetEntry
-IPHLPAPI.DLL!InternalDeleteIpNetEntry2
-IPHLPAPI.DLL!InternalDeleteUnicastIpAddressEntry
-IPHLPAPI.DLL!InternalFindInterfaceByAddress
-IPHLPAPI.DLL!InternalGetAnycastIpAddressEntry
-IPHLPAPI.DLL!InternalGetAnycastIpAddressTable
-IPHLPAPI.DLL!InternalGetBoundTcp6EndpointTable
-IPHLPAPI.DLL!InternalGetBoundTcpEndpointTable
-IPHLPAPI.DLL!InternalGetForwardIpTable2
-IPHLPAPI.DLL!InternalGetIfEntry2
-IPHLPAPI.DLL!InternalGetIfTable
-IPHLPAPI.DLL!InternalGetIfTable2
-IPHLPAPI.DLL!InternalGetIpAddrTable
-IPHLPAPI.DLL!InternalGetIpForwardEntry2
-IPHLPAPI.DLL!InternalGetIpForwardTable
-IPHLPAPI.DLL!InternalGetIpInterfaceEntry
-IPHLPAPI.DLL!InternalGetIpInterfaceTable
-IPHLPAPI.DLL!InternalGetIpNetEntry2
-IPHLPAPI.DLL!InternalGetIpNetTable
-IPHLPAPI.DLL!InternalGetIpNetTable2
-IPHLPAPI.DLL!InternalGetIPPhysicalInterfaceForDestination
-IPHLPAPI.DLL!InternalGetMulticastIpAddressEntry
-IPHLPAPI.DLL!InternalGetMulticastIpAddressTable
-IPHLPAPI.DLL!InternalGetRtcSlotInformation
-IPHLPAPI.DLL!InternalGetTcp6Table2
-IPHLPAPI.DLL!InternalGetTcp6TableWithOwnerModule
-IPHLPAPI.DLL!InternalGetTcp6TableWithOwnerPid
-IPHLPAPI.DLL!InternalGetTcpTable
-IPHLPAPI.DLL!InternalGetTcpTable2
-IPHLPAPI.DLL!InternalGetTcpTableEx
-IPHLPAPI.DLL!InternalGetTcpTableWithOwnerModule
-IPHLPAPI.DLL!InternalGetTcpTableWithOwnerPid
-IPHLPAPI.DLL!InternalGetTunnelPhysicalAdapter
-IPHLPAPI.DLL!InternalGetUdp6TableWithOwnerModule
-IPHLPAPI.DLL!InternalGetUdp6TableWithOwnerPid
-IPHLPAPI.DLL!InternalGetUdpTable
-IPHLPAPI.DLL!InternalGetUdpTableEx
-IPHLPAPI.DLL!InternalGetUdpTableWithOwnerModule
-IPHLPAPI.DLL!InternalGetUdpTableWithOwnerPid
-IPHLPAPI.DLL!InternalGetUnicastIpAddressEntry
-IPHLPAPI.DLL!InternalGetUnicastIpAddressTable
-IPHLPAPI.DLL!InternalIcmpCreateFileEx
-IPHLPAPI.DLL!InternalSetIfEntry
-IPHLPAPI.DLL!InternalSetIpForwardEntry
-IPHLPAPI.DLL!InternalSetIpForwardEntry2
-IPHLPAPI.DLL!InternalSetIpInterfaceEntry
-IPHLPAPI.DLL!InternalSetIpNetEntry
-IPHLPAPI.DLL!InternalSetIpNetEntry2
-IPHLPAPI.DLL!InternalSetIpStats
-IPHLPAPI.DLL!InternalSetTcpEntry
-IPHLPAPI.DLL!InternalSetTeredoPort
-IPHLPAPI.DLL!InternalSetUnicastIpAddressEntry
-IPHLPAPI.DLL!IpReleaseAddress
-IPHLPAPI.DLL!IpRenewAddress
-IPHLPAPI.DLL!LookupPersistentTcpPortReservation
-IPHLPAPI.DLL!LookupPersistentUdpPortReservation
-IPHLPAPI.DLL!NhGetGuidFromInterfaceName
-IPHLPAPI.DLL!NhGetInterfaceDescriptionFromGuid
-IPHLPAPI.DLL!NhGetInterfaceNameFromDeviceGuid
-IPHLPAPI.DLL!NhGetInterfaceNameFromGuid
-IPHLPAPI.DLL!NhpAllocateAndGetInterfaceInfoFromStack
-IPHLPAPI.DLL!NotifyAddrChange
-IPHLPAPI.DLL!NotifyCompartmentChange
-IPHLPAPI.DLL!NotifyIpInterfaceChange
-IPHLPAPI.DLL!NotifyRouteChange
-IPHLPAPI.DLL!NotifyRouteChange2
-IPHLPAPI.DLL!NotifyStableUnicastIpAddressTable
-IPHLPAPI.DLL!NotifyTeredoPortChange
-IPHLPAPI.DLL!NotifyUnicastIpAddressChange
-IPHLPAPI.DLL!NTPTimeToNTFileTime
-IPHLPAPI.DLL!NTTimeToNTPTime
-IPHLPAPI.DLL!OpenCompartment
-IPHLPAPI.DLL!ParseNetworkString
-IPHLPAPI.DLL!ResolveIpNetEntry2
-IPHLPAPI.DLL!ResolveNeighbor
-IPHLPAPI.DLL!RestoreMediaSense
-IPHLPAPI.DLL!SendARP
-IPHLPAPI.DLL!SetAdapterIpAddress
-IPHLPAPI.DLL!SetCurrentThreadCompartmentId
-IPHLPAPI.DLL!SetCurrentThreadCompartmentScope
-IPHLPAPI.DLL!SetIfEntry
-IPHLPAPI.DLL!SetIpForwardEntry
-IPHLPAPI.DLL!SetIpForwardEntry2
-IPHLPAPI.DLL!SetIpInterfaceEntry
-IPHLPAPI.DLL!SetIpNetEntry
-IPHLPAPI.DLL!SetIpNetEntry2
-IPHLPAPI.DLL!SetIpStatistics
-IPHLPAPI.DLL!SetIpStatisticsEx
-IPHLPAPI.DLL!SetIpTTL
-IPHLPAPI.DLL!SetJobCompartmentId
-IPHLPAPI.DLL!SetNetworkInformation
-IPHLPAPI.DLL!SetPerTcp6ConnectionEStats
-IPHLPAPI.DLL!SetPerTcp6ConnectionStats
-IPHLPAPI.DLL!SetPerTcpConnectionEStats
-IPHLPAPI.DLL!SetPerTcpConnectionStats
-IPHLPAPI.DLL!SetSessionCompartmentId
-IPHLPAPI.DLL!SetTcpEntry
-IPHLPAPI.DLL!SetUnicastIpAddressEntry
-IPHLPAPI.DLL!UnenableRouter
-logoncli.dll!DsAddressToSiteNamesA
-logoncli.dll!DsAddressToSiteNamesExA
-logoncli.dll!DsAddressToSiteNamesExW
-logoncli.dll!DsAddressToSiteNamesW
-logoncli.dll!DsDeregisterDnsHostRecordsA
-logoncli.dll!DsDeregisterDnsHostRecordsW
-logoncli.dll!DsEnumerateDomainTrustsA
-logoncli.dll!DsEnumerateDomainTrustsW
-logoncli.dll!DsGetDcCloseW
-logoncli.dll!DsGetDcNameA
-logoncli.dll!DsGetDcNameW
-logoncli.dll!DsGetDcNameWithAccountA
-logoncli.dll!DsGetDcNameWithAccountW
-logoncli.dll!DsGetDcNextA
-logoncli.dll!DsGetDcNextW
-logoncli.dll!DsGetDcOpenA
-logoncli.dll!DsGetDcOpenW
-logoncli.dll!DsGetDcSiteCoverageA
-logoncli.dll!DsGetDcSiteCoverageW
-logoncli.dll!DsGetForestTrustInformationW
-logoncli.dll!DsGetSiteNameA
-logoncli.dll!DsGetSiteNameW
-logoncli.dll!DsMergeForestTrustInformationW
-logoncli.dll!DsValidateSubnetNameA
-logoncli.dll!DsValidateSubnetNameW
-logoncli.dll!NetAddServiceAccount
-logoncli.dll!NetEnumerateServiceAccounts
-logoncli.dll!NetGetAnyDCName
-logoncli.dll!NetGetDCName
-logoncli.dll!NetIsServiceAccount
-logoncli.dll!NetLogonGetTimeServiceParentDomain
-logoncli.dll!NetQueryServiceAccount
-logoncli.dll!NetRemoveServiceAccount
-logoncli.dll!NlSetDsIsCloningPDC
-MPR.dll!MultinetGetConnectionPerformanceA
-MPR.dll!MultinetGetConnectionPerformanceW
-MPR.dll!WNetAddConnection2A
-MPR.dll!WNetAddConnection2W
-MPR.dll!WNetAddConnection3A
-MPR.dll!WNetAddConnection3W
-MPR.dll!WNetAddConnectionA
-MPR.dll!WNetAddConnectionW
-MPR.dll!WNetCancelConnection2A
-MPR.dll!WNetCancelConnection2W
-MPR.dll!WNetCancelConnectionA
-MPR.dll!WNetCancelConnectionW
-MPR.dll!WNetCloseEnum
-MPR.dll!WNetConnectionDialog1A
-MPR.dll!WNetDisconnectDialog1A
-MPR.dll!WNetEnumResourceA
-MPR.dll!WNetEnumResourceW
-MPR.dll!WNetGetConnectionA
-MPR.dll!WNetGetConnectionW
-MPR.dll!WNetGetLastErrorA
-MPR.dll!WNetGetLastErrorW
-MPR.dll!WNetGetNetworkInformationA
-MPR.dll!WNetGetNetworkInformationW
-MPR.dll!WNetGetProviderNameA
-MPR.dll!WNetGetProviderNameW
-MPR.dll!WNetGetResourceInformationA
-MPR.dll!WNetGetResourceInformationW
-MPR.dll!WNetGetResourceParentA
-MPR.dll!WNetGetResourceParentW
-MPR.dll!WNetGetUniversalNameA
-MPR.dll!WNetGetUniversalNameW
-MPR.dll!WNetGetUserA
-MPR.dll!WNetGetUserW
-MPR.dll!WNetOpenEnumA
-MPR.dll!WNetOpenEnumW
-MPR.dll!WNetSetLastErrorA
-MPR.dll!WNetSetLastErrorW
-MPR.dll!WNetUseConnectionA
-MPR.dll!WNetUseConnectionW
-MSWSOCK.dll!AcceptEx
-MSWSOCK.dll!dn_expand
-MSWSOCK.dll!EnumProtocolsA
-MSWSOCK.dll!EnumProtocolsW
-MSWSOCK.dll!GetAcceptExSockaddrs
-MSWSOCK.dll!GetAddressByNameA
-MSWSOCK.dll!GetAddressByNameW
-MSWSOCK.dll!GetNameByTypeA
-MSWSOCK.dll!GetNameByTypeW
-MSWSOCK.dll!getnetbyname
-MSWSOCK.dll!GetServiceA
-MSWSOCK.dll!GetServiceW
-MSWSOCK.dll!GetSocketErrorMessageW
-MSWSOCK.dll!GetTypeByNameA
-MSWSOCK.dll!GetTypeByNameW
-MSWSOCK.dll!inet_network
-MSWSOCK.dll!MigrateWinsockConfiguration
-MSWSOCK.dll!MigrateWinsockConfigurationEx
-MSWSOCK.dll!NPLoadNameSpaces
-MSWSOCK.dll!rcmd
-MSWSOCK.dll!rexec
-MSWSOCK.dll!rresvport
-MSWSOCK.dll!s_perror
-MSWSOCK.dll!sethostname
-MSWSOCK.dll!SetServiceA
-MSWSOCK.dll!SetServiceW
-MSWSOCK.dll!TransmitFile
-MSWSOCK.dll!WSARecvEx
-ncrypt.dll!GetIsolationServerInterface
-ncrypt.dll!GetKeyStorageInterface
-ncrypt.dll!GetSChannelInterface
-ncrypt.dll!NCryptCloseProtectionDescriptor
-ncrypt.dll!NCryptCreateClaim
-ncrypt.dll!NCryptCreatePersistedKey
-ncrypt.dll!NCryptCreateProtectionDescriptor
-ncrypt.dll!NCryptDecrypt
-ncrypt.dll!NCryptDeleteKey
-ncrypt.dll!NCryptDeriveKey
-ncrypt.dll!NCryptEncrypt
-ncrypt.dll!NCryptEnumAlgorithms
-ncrypt.dll!NCryptEnumKeys
-ncrypt.dll!NCryptEnumStorageProviders
-ncrypt.dll!NCryptExportKey
-ncrypt.dll!NCryptFinalizeKey
-ncrypt.dll!NCryptFreeBuffer
-ncrypt.dll!NCryptFreeObject
-ncrypt.dll!NCryptGetProperty
-ncrypt.dll!NCryptGetProtectionDescriptorInfo
-ncrypt.dll!NCryptImportKey
-ncrypt.dll!NCryptIsAlgSupported
-ncrypt.dll!NCryptIsKeyHandle
-ncrypt.dll!NCryptKeyDerivation
-ncrypt.dll!NCryptNotifyChangeKey
-ncrypt.dll!NCryptOpenKey
-ncrypt.dll!NCryptOpenStorageProvider
-ncrypt.dll!NCryptProtectSecret
-ncrypt.dll!NCryptQueryProtectionDescriptorName
-ncrypt.dll!NCryptRegisterProtectionDescriptorName
-ncrypt.dll!NCryptSecretAgreement
-ncrypt.dll!NCryptSetAuditingInterface
-ncrypt.dll!NCryptSetProperty
-ncrypt.dll!NCryptSignHash
-ncrypt.dll!NCryptStreamClose
-ncrypt.dll!NCryptStreamOpenToProtect
-ncrypt.dll!NCryptStreamOpenToUnprotect
-ncrypt.dll!NCryptStreamOpenToUnprotectEx
-ncrypt.dll!NCryptStreamUpdate
-ncrypt.dll!NCryptTranslateHandle
-ncrypt.dll!NCryptUnprotectSecret
-ncrypt.dll!NCryptVerifyClaim
-ncrypt.dll!NCryptVerifySignature
-ncrypt.dll!SslChangeNotify
-ncrypt.dll!SslComputeClientAuthHash
-ncrypt.dll!SslComputeEapKeyBlock
-ncrypt.dll!SslComputeFinishedHash
-ncrypt.dll!SslComputeSessionHash
-ncrypt.dll!SslCreateClientAuthHash
-ncrypt.dll!SslCreateEphemeralKey
-ncrypt.dll!SslCreateHandshakeHash
-ncrypt.dll!SslDecrementProviderReferenceCount
-ncrypt.dll!SslDecryptPacket
-ncrypt.dll!SslEncryptPacket
-ncrypt.dll!SslEnumCipherSuites
-ncrypt.dll!SslEnumEccCurves
-ncrypt.dll!SslEnumProtocolProviders
-ncrypt.dll!SslExportKey
-ncrypt.dll!SslExportKeyingMaterial
-ncrypt.dll!SslFreeBuffer
-ncrypt.dll!SslFreeObject
-ncrypt.dll!SslGenerateMasterKey
-ncrypt.dll!SslGeneratePreMasterKey
-ncrypt.dll!SslGenerateSessionKeys
-ncrypt.dll!SslGetCipherSuitePRFHashAlgorithm
-ncrypt.dll!SslGetKeyProperty
-ncrypt.dll!SslGetProviderProperty
-ncrypt.dll!SslHashHandshake
-ncrypt.dll!SslImportKey
-ncrypt.dll!SslImportMasterKey
-ncrypt.dll!SslIncrementProviderReferenceCount
-ncrypt.dll!SslLookupCipherLengths
-ncrypt.dll!SslLookupCipherSuiteInfo
-ncrypt.dll!SslOpenPrivateKey
-ncrypt.dll!SslOpenProvider
-ncrypt.dll!SslSignHash
-ncrypt.dll!SslVerifySignature
-netutils.dll!NetApiBufferAllocate
-netutils.dll!NetApiBufferFree
-netutils.dll!NetApiBufferReallocate
-netutils.dll!NetApiBufferSize
-netutils.dll!NetRemoteComputerSupports
-NTMARTA.dll!AccConvertAccessMaskToActrlAccess
-NTMARTA.dll!AccConvertAccessToSD
-NTMARTA.dll!AccConvertAccessToSecurityDescriptor
-NTMARTA.dll!AccConvertAclToAccess
-NTMARTA.dll!AccConvertSDToAccess
-NTMARTA.dll!AccFreeIndexArray
-NTMARTA.dll!AccGetAccessForTrustee
-NTMARTA.dll!AccGetExplicitEntries
-NTMARTA.dll!AccGetInheritanceSource
-NTMARTA.dll!AccLookupAccountName
-NTMARTA.dll!AccLookupAccountSid
-NTMARTA.dll!AccLookupAccountTrustee
-NTMARTA.dll!AccProvCancelOperation
-NTMARTA.dll!AccProvGetAccessInfoPerObjectType
-NTMARTA.dll!AccProvGetAllRights
-NTMARTA.dll!AccProvGetCapabilities
-NTMARTA.dll!AccProvGetOperationResults
-NTMARTA.dll!AccProvGetTrusteesAccess
-NTMARTA.dll!AccProvGrantAccessRights
-NTMARTA.dll!AccProvHandleGetAccessInfoPerObjectType
-NTMARTA.dll!AccProvHandleGetAllRights
-NTMARTA.dll!AccProvHandleGetTrusteesAccess
-NTMARTA.dll!AccProvHandleGrantAccessRights
-NTMARTA.dll!AccProvHandleIsAccessAudited
-NTMARTA.dll!AccProvHandleIsObjectAccessible
-NTMARTA.dll!AccProvHandleRevokeAccessRights
-NTMARTA.dll!AccProvHandleRevokeAuditRights
-NTMARTA.dll!AccProvHandleSetAccessRights
-NTMARTA.dll!AccProvIsAccessAudited
-NTMARTA.dll!AccProvIsObjectAccessible
-NTMARTA.dll!AccProvRevokeAccessRights
-NTMARTA.dll!AccProvRevokeAuditRights
-NTMARTA.dll!AccProvSetAccessRights
-NTMARTA.dll!AccRewriteGetExplicitEntriesFromAcl
-NTMARTA.dll!AccRewriteGetHandleRights
-NTMARTA.dll!AccRewriteGetNamedRights
-NTMARTA.dll!AccRewriteSetEntriesInAcl
-NTMARTA.dll!AccRewriteSetHandleRights
-NTMARTA.dll!AccRewriteSetNamedRights
-NTMARTA.dll!AccSetEntriesInAList
-NTMARTA.dll!AccTreeResetNamedSecurityInfo
-NTMARTA.dll!EventGuidToName
-NTMARTA.dll!EventNameFree
-NTMARTA.dll!GetMartaExtensionInterface
-OLEAUT32.dll!BSTR_UserFree
-OLEAUT32.dll!BSTR_UserMarshal
-OLEAUT32.dll!BSTR_UserSize
-OLEAUT32.dll!BSTR_UserUnmarshal
-OLEAUT32.dll!BstrFromVector
-OLEAUT32.dll!ClearCustData
-OLEAUT32.dll!CreateDispTypeInfo
-OLEAUT32.dll!CreateErrorInfo
-OLEAUT32.dll!CreateStdDispatch
-OLEAUT32.dll!CreateTypeLib
-OLEAUT32.dll!CreateTypeLib2
-OLEAUT32.dll!DispCallFunc
-OLEAUT32.dll!DispGetIDsOfNames
-OLEAUT32.dll!DispGetParam
-OLEAUT32.dll!DispInvoke
-OLEAUT32.dll!DosDateTimeToVariantTime
-OLEAUT32.dll!GetActiveObject
-OLEAUT32.dll!GetAltMonthNames
-OLEAUT32.dll!GetErrorInfo
-OLEAUT32.dll!GetRecordInfoFromGuids
-OLEAUT32.dll!GetRecordInfoFromTypeInfo
-OLEAUT32.dll!GetVarConversionLocaleSetting
-OLEAUT32.dll!LHashValOfNameSys
-OLEAUT32.dll!LHashValOfNameSysA
-OLEAUT32.dll!LoadRegTypeLib
-OLEAUT32.dll!LoadTypeLib
-OLEAUT32.dll!LoadTypeLibEx
-OLEAUT32.dll!LPSAFEARRAY_Marshal
-OLEAUT32.dll!LPSAFEARRAY_Size
-OLEAUT32.dll!LPSAFEARRAY_Unmarshal
-OLEAUT32.dll!LPSAFEARRAY_UserFree
-OLEAUT32.dll!LPSAFEARRAY_UserMarshal
-OLEAUT32.dll!LPSAFEARRAY_UserSize
-OLEAUT32.dll!LPSAFEARRAY_UserUnmarshal
-OLEAUT32.dll!OaBuildVersion
-OLEAUT32.dll!OACreateTypeLib2
-OLEAUT32.dll!OaEnablePerUserTLibRegistration
-OLEAUT32.dll!OleCreateFontIndirect
-OLEAUT32.dll!OleCreatePictureIndirect
-OLEAUT32.dll!OleCreatePropertyFrame
-OLEAUT32.dll!OleCreatePropertyFrameIndirect
-OLEAUT32.dll!OleIconToCursor
-OLEAUT32.dll!OleLoadPicture
-OLEAUT32.dll!OleLoadPictureEx
-OLEAUT32.dll!OleLoadPictureFile
-OLEAUT32.dll!OleLoadPictureFileEx
-OLEAUT32.dll!OleLoadPicturePath
-OLEAUT32.dll!OleSavePictureFile
-OLEAUT32.dll!OleTranslateColor
-OLEAUT32.dll!QueryPathOfRegTypeLib
-OLEAUT32.dll!RegisterActiveObject
-OLEAUT32.dll!RegisterTypeLib
-OLEAUT32.dll!RegisterTypeLibForUser
-OLEAUT32.dll!RevokeActiveObject
-OLEAUT32.dll!SafeArrayAccessData
-OLEAUT32.dll!SafeArrayAllocData
-OLEAUT32.dll!SafeArrayAllocDescriptor
-OLEAUT32.dll!SafeArrayAllocDescriptorEx
-OLEAUT32.dll!SafeArrayCopy
-OLEAUT32.dll!SafeArrayCopyData
-OLEAUT32.dll!SafeArrayCreate
-OLEAUT32.dll!SafeArrayCreateEx
-OLEAUT32.dll!SafeArrayCreateVector
-OLEAUT32.dll!SafeArrayCreateVectorEx
-OLEAUT32.dll!SafeArrayDestroy
-OLEAUT32.dll!SafeArrayDestroyData
-OLEAUT32.dll!SafeArrayDestroyDescriptor
-OLEAUT32.dll!SafeArrayGetDim
-OLEAUT32.dll!SafeArrayGetElement
-OLEAUT32.dll!SafeArrayGetElemsize
-OLEAUT32.dll!SafeArrayGetIID
-OLEAUT32.dll!SafeArrayGetLBound
-OLEAUT32.dll!SafeArrayGetRecordInfo
-OLEAUT32.dll!SafeArrayGetUBound
-OLEAUT32.dll!SafeArrayGetVartype
-OLEAUT32.dll!SafeArrayLock
-OLEAUT32.dll!SafeArrayPtrOfIndex
-OLEAUT32.dll!SafeArrayPutElement
-OLEAUT32.dll!SafeArrayRedim
-OLEAUT32.dll!SafeArraySetIID
-OLEAUT32.dll!SafeArraySetRecordInfo
-OLEAUT32.dll!SafeArrayUnaccessData
-OLEAUT32.dll!SafeArrayUnlock
-OLEAUT32.dll!SetErrorInfo
-OLEAUT32.dll!SetOaNoCache
-OLEAUT32.dll!SetVarConversionLocaleSetting
-OLEAUT32.dll!SysAllocString
-OLEAUT32.dll!SysAllocStringByteLen
-OLEAUT32.dll!SysAllocStringLen
-OLEAUT32.dll!SysFreeString
-OLEAUT32.dll!SysReAllocString
-OLEAUT32.dll!SysReAllocStringLen
-OLEAUT32.dll!SysStringByteLen
-OLEAUT32.dll!SysStringLen
-OLEAUT32.dll!SystemTimeToVariantTime
-OLEAUT32.dll!UnRegisterTypeLib
-OLEAUT32.dll!UnRegisterTypeLibForUser
-OLEAUT32.dll!VarAbs
-OLEAUT32.dll!VarAdd
-OLEAUT32.dll!VarAnd
-OLEAUT32.dll!VarBoolFromCy
-OLEAUT32.dll!VarBoolFromDate
-OLEAUT32.dll!VarBoolFromDec
-OLEAUT32.dll!VarBoolFromDisp
-OLEAUT32.dll!VarBoolFromI1
-OLEAUT32.dll!VarBoolFromI2
-OLEAUT32.dll!VarBoolFromI4
-OLEAUT32.dll!VarBoolFromI8
-OLEAUT32.dll!VarBoolFromR4
-OLEAUT32.dll!VarBoolFromR8
-OLEAUT32.dll!VarBoolFromStr
-OLEAUT32.dll!VarBoolFromUI1
-OLEAUT32.dll!VarBoolFromUI2
-OLEAUT32.dll!VarBoolFromUI4
-OLEAUT32.dll!VarBoolFromUI8
-OLEAUT32.dll!VarBstrCat
-OLEAUT32.dll!VarBstrCmp
-OLEAUT32.dll!VarBstrFromBool
-OLEAUT32.dll!VarBstrFromCy
-OLEAUT32.dll!VarBstrFromDate
-OLEAUT32.dll!VarBstrFromDec
-OLEAUT32.dll!VarBstrFromDisp
-OLEAUT32.dll!VarBstrFromI1
-OLEAUT32.dll!VarBstrFromI2
-OLEAUT32.dll!VarBstrFromI4
-OLEAUT32.dll!VarBstrFromI8
-OLEAUT32.dll!VarBstrFromR4
-OLEAUT32.dll!VarBstrFromR8
-OLEAUT32.dll!VarBstrFromUI1
-OLEAUT32.dll!VarBstrFromUI2
-OLEAUT32.dll!VarBstrFromUI4
-OLEAUT32.dll!VarBstrFromUI8
-OLEAUT32.dll!VarCat
-OLEAUT32.dll!VarCmp
-OLEAUT32.dll!VarCyAbs
-OLEAUT32.dll!VarCyAdd
-OLEAUT32.dll!VarCyCmp
-OLEAUT32.dll!VarCyCmpR8
-OLEAUT32.dll!VarCyFix
-OLEAUT32.dll!VarCyFromBool
-OLEAUT32.dll!VarCyFromDate
-OLEAUT32.dll!VarCyFromDec
-OLEAUT32.dll!VarCyFromDisp
-OLEAUT32.dll!VarCyFromI1
-OLEAUT32.dll!VarCyFromI2
-OLEAUT32.dll!VarCyFromI4
-OLEAUT32.dll!VarCyFromI8
-OLEAUT32.dll!VarCyFromR4
-OLEAUT32.dll!VarCyFromR8
-OLEAUT32.dll!VarCyFromStr
-OLEAUT32.dll!VarCyFromUI1
-OLEAUT32.dll!VarCyFromUI2
-OLEAUT32.dll!VarCyFromUI4
-OLEAUT32.dll!VarCyFromUI8
-OLEAUT32.dll!VarCyInt
-OLEAUT32.dll!VarCyMul
-OLEAUT32.dll!VarCyMulI4
-OLEAUT32.dll!VarCyMulI8
-OLEAUT32.dll!VarCyNeg
-OLEAUT32.dll!VarCyRound
-OLEAUT32.dll!VarCySub
-OLEAUT32.dll!VarDateFromBool
-OLEAUT32.dll!VarDateFromCy
-OLEAUT32.dll!VarDateFromDec
-OLEAUT32.dll!VarDateFromDisp
-OLEAUT32.dll!VarDateFromI1
-OLEAUT32.dll!VarDateFromI2
-OLEAUT32.dll!VarDateFromI4
-OLEAUT32.dll!VarDateFromI8
-OLEAUT32.dll!VarDateFromR4
-OLEAUT32.dll!VarDateFromR8
-OLEAUT32.dll!VarDateFromStr
-OLEAUT32.dll!VarDateFromUdate
-OLEAUT32.dll!VarDateFromUdateEx
-OLEAUT32.dll!VarDateFromUI1
-OLEAUT32.dll!VarDateFromUI2
-OLEAUT32.dll!VarDateFromUI4
-OLEAUT32.dll!VarDateFromUI8
-OLEAUT32.dll!VarDecAbs
-OLEAUT32.dll!VarDecAdd
-OLEAUT32.dll!VarDecCmp
-OLEAUT32.dll!VarDecCmpR8
-OLEAUT32.dll!VarDecDiv
-OLEAUT32.dll!VarDecFix
-OLEAUT32.dll!VarDecFromBool
-OLEAUT32.dll!VarDecFromCy
-OLEAUT32.dll!VarDecFromDate
-OLEAUT32.dll!VarDecFromDisp
-OLEAUT32.dll!VarDecFromI1
-OLEAUT32.dll!VarDecFromI2
-OLEAUT32.dll!VarDecFromI4
-OLEAUT32.dll!VarDecFromI8
-OLEAUT32.dll!VarDecFromR4
-OLEAUT32.dll!VarDecFromR8
-OLEAUT32.dll!VarDecFromStr
-OLEAUT32.dll!VarDecFromUI1
-OLEAUT32.dll!VarDecFromUI2
-OLEAUT32.dll!VarDecFromUI4
-OLEAUT32.dll!VarDecFromUI8
-OLEAUT32.dll!VarDecInt
-OLEAUT32.dll!VarDecMul
-OLEAUT32.dll!VarDecNeg
-OLEAUT32.dll!VarDecRound
-OLEAUT32.dll!VarDecSub
-OLEAUT32.dll!VarDiv
-OLEAUT32.dll!VarEqv
-OLEAUT32.dll!VarFix
-OLEAUT32.dll!VarFormat
-OLEAUT32.dll!VarFormatCurrency
-OLEAUT32.dll!VarFormatDateTime
-OLEAUT32.dll!VarFormatFromTokens
-OLEAUT32.dll!VarFormatNumber
-OLEAUT32.dll!VarFormatPercent
-OLEAUT32.dll!VarI1FromBool
-OLEAUT32.dll!VarI1FromCy
-OLEAUT32.dll!VarI1FromDate
-OLEAUT32.dll!VarI1FromDec
-OLEAUT32.dll!VarI1FromDisp
-OLEAUT32.dll!VarI1FromI2
-OLEAUT32.dll!VarI1FromI4
-OLEAUT32.dll!VarI1FromI8
-OLEAUT32.dll!VarI1FromR4
-OLEAUT32.dll!VarI1FromR8
-OLEAUT32.dll!VarI1FromStr
-OLEAUT32.dll!VarI1FromUI1
-OLEAUT32.dll!VarI1FromUI2
-OLEAUT32.dll!VarI1FromUI4
-OLEAUT32.dll!VarI1FromUI8
-OLEAUT32.dll!VarI2FromBool
-OLEAUT32.dll!VarI2FromCy
-OLEAUT32.dll!VarI2FromDate
-OLEAUT32.dll!VarI2FromDec
-OLEAUT32.dll!VarI2FromDisp
-OLEAUT32.dll!VarI2FromI1
-OLEAUT32.dll!VarI2FromI4
-OLEAUT32.dll!VarI2FromI8
-OLEAUT32.dll!VarI2FromR4
-OLEAUT32.dll!VarI2FromR8
-OLEAUT32.dll!VarI2FromStr
-OLEAUT32.dll!VarI2FromUI1
-OLEAUT32.dll!VarI2FromUI2
-OLEAUT32.dll!VarI2FromUI4
-OLEAUT32.dll!VarI2FromUI8
-OLEAUT32.dll!VarI4FromBool
-OLEAUT32.dll!VarI4FromCy
-OLEAUT32.dll!VarI4FromDate
-OLEAUT32.dll!VarI4FromDec
-OLEAUT32.dll!VarI4FromDisp
-OLEAUT32.dll!VarI4FromI1
-OLEAUT32.dll!VarI4FromI2
-OLEAUT32.dll!VarI4FromI8
-OLEAUT32.dll!VarI4FromR4
-OLEAUT32.dll!VarI4FromR8
-OLEAUT32.dll!VarI4FromStr
-OLEAUT32.dll!VarI4FromUI1
-OLEAUT32.dll!VarI4FromUI2
-OLEAUT32.dll!VarI4FromUI4
-OLEAUT32.dll!VarI4FromUI8
-OLEAUT32.dll!VarI8FromBool
-OLEAUT32.dll!VarI8FromCy
-OLEAUT32.dll!VarI8FromDate
-OLEAUT32.dll!VarI8FromDec
-OLEAUT32.dll!VarI8FromDisp
-OLEAUT32.dll!VarI8FromI1
-OLEAUT32.dll!VarI8FromI2
-OLEAUT32.dll!VarI8FromR4
-OLEAUT32.dll!VarI8FromR8
-OLEAUT32.dll!VarI8FromStr
-OLEAUT32.dll!VarI8FromUI1
-OLEAUT32.dll!VarI8FromUI2
-OLEAUT32.dll!VarI8FromUI4
-OLEAUT32.dll!VarI8FromUI8
-OLEAUT32.dll!VARIANT_UserFree
-OLEAUT32.dll!VARIANT_UserMarshal
-OLEAUT32.dll!VARIANT_UserSize
-OLEAUT32.dll!VARIANT_UserUnmarshal
-OLEAUT32.dll!VariantChangeType
-OLEAUT32.dll!VariantChangeTypeEx
-OLEAUT32.dll!VariantClear
-OLEAUT32.dll!VariantCopy
-OLEAUT32.dll!VariantCopyInd
-OLEAUT32.dll!VariantInit
-OLEAUT32.dll!VariantTimeToDosDateTime
-OLEAUT32.dll!VariantTimeToSystemTime
-OLEAUT32.dll!VarIdiv
-OLEAUT32.dll!VarImp
-OLEAUT32.dll!VarInt
-OLEAUT32.dll!VarMod
-OLEAUT32.dll!VarMonthName
-OLEAUT32.dll!VarMul
-OLEAUT32.dll!VarNeg
-OLEAUT32.dll!VarNot
-OLEAUT32.dll!VarNumFromParseNum
-OLEAUT32.dll!VarOr
-OLEAUT32.dll!VarParseNumFromStr
-OLEAUT32.dll!VarPow
-OLEAUT32.dll!VarR4CmpR8
-OLEAUT32.dll!VarR4FromBool
-OLEAUT32.dll!VarR4FromCy
-OLEAUT32.dll!VarR4FromDate
-OLEAUT32.dll!VarR4FromDec
-OLEAUT32.dll!VarR4FromDisp
-OLEAUT32.dll!VarR4FromI1
-OLEAUT32.dll!VarR4FromI2
-OLEAUT32.dll!VarR4FromI4
-OLEAUT32.dll!VarR4FromI8
-OLEAUT32.dll!VarR4FromR8
-OLEAUT32.dll!VarR4FromStr
-OLEAUT32.dll!VarR4FromUI1
-OLEAUT32.dll!VarR4FromUI2
-OLEAUT32.dll!VarR4FromUI4
-OLEAUT32.dll!VarR4FromUI8
-OLEAUT32.dll!VarR8FromBool
-OLEAUT32.dll!VarR8FromCy
-OLEAUT32.dll!VarR8FromDate
-OLEAUT32.dll!VarR8FromDec
-OLEAUT32.dll!VarR8FromDisp
-OLEAUT32.dll!VarR8FromI1
-OLEAUT32.dll!VarR8FromI2
-OLEAUT32.dll!VarR8FromI4
-OLEAUT32.dll!VarR8FromI8
-OLEAUT32.dll!VarR8FromR4
-OLEAUT32.dll!VarR8FromStr
-OLEAUT32.dll!VarR8FromUI1
-OLEAUT32.dll!VarR8FromUI2
-OLEAUT32.dll!VarR8FromUI4
-OLEAUT32.dll!VarR8FromUI8
-OLEAUT32.dll!VarR8Pow
-OLEAUT32.dll!VarR8Round
-OLEAUT32.dll!VarRound
-OLEAUT32.dll!VarSub
-OLEAUT32.dll!VarTokenizeFormatString
-OLEAUT32.dll!VarUdateFromDate
-OLEAUT32.dll!VarUI1FromBool
-OLEAUT32.dll!VarUI1FromCy
-OLEAUT32.dll!VarUI1FromDate
-OLEAUT32.dll!VarUI1FromDec
-OLEAUT32.dll!VarUI1FromDisp
-OLEAUT32.dll!VarUI1FromI1
-OLEAUT32.dll!VarUI1FromI2
-OLEAUT32.dll!VarUI1FromI4
-OLEAUT32.dll!VarUI1FromI8
-OLEAUT32.dll!VarUI1FromR4
-OLEAUT32.dll!VarUI1FromR8
-OLEAUT32.dll!VarUI1FromStr
-OLEAUT32.dll!VarUI1FromUI2
-OLEAUT32.dll!VarUI1FromUI4
-OLEAUT32.dll!VarUI1FromUI8
-OLEAUT32.dll!VarUI2FromBool
-OLEAUT32.dll!VarUI2FromCy
-OLEAUT32.dll!VarUI2FromDate
-OLEAUT32.dll!VarUI2FromDec
-OLEAUT32.dll!VarUI2FromDisp
-OLEAUT32.dll!VarUI2FromI1
-OLEAUT32.dll!VarUI2FromI2
-OLEAUT32.dll!VarUI2FromI4
-OLEAUT32.dll!VarUI2FromI8
-OLEAUT32.dll!VarUI2FromR4
-OLEAUT32.dll!VarUI2FromR8
-OLEAUT32.dll!VarUI2FromStr
-OLEAUT32.dll!VarUI2FromUI1
-OLEAUT32.dll!VarUI2FromUI4
-OLEAUT32.dll!VarUI2FromUI8
-OLEAUT32.dll!VarUI4FromBool
-OLEAUT32.dll!VarUI4FromCy
-OLEAUT32.dll!VarUI4FromDate
-OLEAUT32.dll!VarUI4FromDec
-OLEAUT32.dll!VarUI4FromDisp
-OLEAUT32.dll!VarUI4FromI1
-OLEAUT32.dll!VarUI4FromI2
-OLEAUT32.dll!VarUI4FromI4
-OLEAUT32.dll!VarUI4FromI8
-OLEAUT32.dll!VarUI4FromR4
-OLEAUT32.dll!VarUI4FromR8
-OLEAUT32.dll!VarUI4FromStr
-OLEAUT32.dll!VarUI4FromUI1
-OLEAUT32.dll!VarUI4FromUI2
-OLEAUT32.dll!VarUI4FromUI8
-OLEAUT32.dll!VarUI8FromBool
-OLEAUT32.dll!VarUI8FromCy
-OLEAUT32.dll!VarUI8FromDate
-OLEAUT32.dll!VarUI8FromDec
-OLEAUT32.dll!VarUI8FromDisp
-OLEAUT32.dll!VarUI8FromI1
-OLEAUT32.dll!VarUI8FromI2
-OLEAUT32.dll!VarUI8FromI8
-OLEAUT32.dll!VarUI8FromR4
-OLEAUT32.dll!VarUI8FromR8
-OLEAUT32.dll!VarUI8FromStr
-OLEAUT32.dll!VarUI8FromUI1
-OLEAUT32.dll!VarUI8FromUI2
-OLEAUT32.dll!VarUI8FromUI4
-OLEAUT32.dll!VarWeekdayName
-OLEAUT32.dll!VarXor
-OLEAUT32.dll!VectorFromBstr
-POWRPROF.dll!CanUserWritePwrScheme
-POWRPROF.dll!DeletePwrScheme
-POWRPROF.dll!DevicePowerClose
-POWRPROF.dll!DevicePowerEnumDevices
-POWRPROF.dll!DevicePowerOpen
-POWRPROF.dll!DevicePowerSetDeviceState
-POWRPROF.dll!EnumPwrSchemes
-POWRPROF.dll!GetActivePwrScheme
-POWRPROF.dll!GetCurrentPowerPolicies
-POWRPROF.dll!GetPwrDiskSpindownRange
-POWRPROF.dll!GUIDFormatToGlobalPowerPolicy
-POWRPROF.dll!GUIDFormatToPowerPolicy
-POWRPROF.dll!IsAdminOverrideActive
-POWRPROF.dll!IsPwrHibernateAllowed
-POWRPROF.dll!IsPwrShutdownAllowed
-POWRPROF.dll!IsPwrSuspendAllowed
-POWRPROF.dll!LoadCurrentPwrScheme
-POWRPROF.dll!MergeLegacyPwrScheme
-POWRPROF.dll!PowerApplyPowerRequestOverride
-POWRPROF.dll!PowerCanRestoreIndividualDefaultPowerScheme
-POWRPROF.dll!PowerCreatePossibleSetting
-POWRPROF.dll!PowerCreateSetting
-POWRPROF.dll!PowerCustomizePlatformPowerSettings
-POWRPROF.dll!PowerDebugDifPowerPolicies
-POWRPROF.dll!PowerDebugDifSystemPowerPolicies
-POWRPROF.dll!PowerDebugDumpPowerPolicy
-POWRPROF.dll!PowerDebugDumpPowerScheme
-POWRPROF.dll!PowerDebugDumpSystemPowerCapabilities
-POWRPROF.dll!PowerDebugDumpSystemPowerPolicy
-POWRPROF.dll!PowerDeleteScheme
-POWRPROF.dll!PowerDeterminePlatformRole
-POWRPROF.dll!PowerDuplicateScheme
-POWRPROF.dll!PowerEnumerate
-POWRPROF.dll!PowerImportPowerScheme
-POWRPROF.dll!PowerIsSettingRangeDefined
-POWRPROF.dll!PowerOpenSystemPowerKey
-POWRPROF.dll!PowerOpenUserPowerKey
-POWRPROF.dll!PowerPolicyToGUIDFormat
-POWRPROF.dll!PowerReadACDefaultIndex
-POWRPROF.dll!PowerReadACValueIndex
-POWRPROF.dll!PowerReadDCDefaultIndex
-POWRPROF.dll!PowerReadDCValueIndex
-POWRPROF.dll!PowerReadDescription
-POWRPROF.dll!PowerReadFriendlyName
-POWRPROF.dll!PowerReadIconResourceSpecifier
-POWRPROF.dll!PowerReadPossibleDescription
-POWRPROF.dll!PowerReadPossibleFriendlyName
-POWRPROF.dll!PowerReadPossibleValue
-POWRPROF.dll!PowerReadSecurityDescriptor
-POWRPROF.dll!PowerReadSettingAttributes
-POWRPROF.dll!PowerReadValueIncrement
-POWRPROF.dll!PowerReadValueMax
-POWRPROF.dll!PowerReadValueMin
-POWRPROF.dll!PowerReadValueUnitsSpecifier
-POWRPROF.dll!PowerRemovePowerSetting
-POWRPROF.dll!PowerReplaceDefaultPowerSchemes
-POWRPROF.dll!PowerReportThermalEvent
-POWRPROF.dll!PowerRestoreDefaultPowerSchemes
-POWRPROF.dll!PowerRestoreIndividualDefaultPowerScheme
-POWRPROF.dll!PowerSetAlsBrightnessOffset
-POWRPROF.dll!PowerSettingAccessCheck
-POWRPROF.dll!PowerSettingAccessCheckEx
-POWRPROF.dll!PowerWriteACDefaultIndex
-POWRPROF.dll!PowerWriteDCDefaultIndex
-POWRPROF.dll!PowerWriteDescription
-POWRPROF.dll!PowerWriteFriendlyName
-POWRPROF.dll!PowerWriteIconResourceSpecifier
-POWRPROF.dll!PowerWritePossibleDescription
-POWRPROF.dll!PowerWritePossibleFriendlyName
-POWRPROF.dll!PowerWritePossibleValue
-POWRPROF.dll!PowerWriteSecurityDescriptor
-POWRPROF.dll!PowerWriteSettingAttributes
-POWRPROF.dll!PowerWriteValueIncrement
-POWRPROF.dll!PowerWriteValueMax
-POWRPROF.dll!PowerWriteValueMin
-POWRPROF.dll!PowerWriteValueUnitsSpecifier
-POWRPROF.dll!ReadGlobalPwrPolicy
-POWRPROF.dll!ReadProcessorPwrScheme
-POWRPROF.dll!ReadPwrScheme
-POWRPROF.dll!SetActivePwrScheme
-POWRPROF.dll!SetSuspendState
-POWRPROF.dll!ValidatePowerPolicies
-POWRPROF.dll!WriteGlobalPwrPolicy
-POWRPROF.dll!WriteProcessorPwrScheme
-POWRPROF.dll!WritePwrScheme
-RPCRT4.dll!CreateProxyFromTypeInfo
-RPCRT4.dll!CreateStubFromTypeInfo
-RPCRT4.dll!CStdStubBuffer_AddRef
-RPCRT4.dll!CStdStubBuffer_Connect
-RPCRT4.dll!CStdStubBuffer_CountRefs
-RPCRT4.dll!CStdStubBuffer_DebugServerQueryInterface
-RPCRT4.dll!CStdStubBuffer_DebugServerRelease
-RPCRT4.dll!CStdStubBuffer_Disconnect
-RPCRT4.dll!CStdStubBuffer_Invoke
-RPCRT4.dll!CStdStubBuffer_IsIIDSupported
-RPCRT4.dll!CStdStubBuffer_QueryInterface
-RPCRT4.dll!DceErrorInqTextA
-RPCRT4.dll!DceErrorInqTextW
-RPCRT4.dll!I_RpcAllocate
-RPCRT4.dll!I_RpcAsyncAbortCall
-RPCRT4.dll!I_RpcAsyncSetHandle
-RPCRT4.dll!I_RpcBCacheAllocate
-RPCRT4.dll!I_RpcBCacheFree
-RPCRT4.dll!I_RpcBindingCopy
-RPCRT4.dll!I_RpcBindingCreateNP
-RPCRT4.dll!I_RpcBindingHandleToAsyncHandle
-RPCRT4.dll!I_RpcBindingInqClientTokenAttributes
-RPCRT4.dll!I_RpcBindingInqCurrentModifiedId
-RPCRT4.dll!I_RpcBindingInqDynamicEndpoint
-RPCRT4.dll!I_RpcBindingInqDynamicEndpointA
-RPCRT4.dll!I_RpcBindingInqDynamicEndpointW
-RPCRT4.dll!I_RpcBindingInqLocalClientPID
-RPCRT4.dll!I_RpcBindingInqMarshalledTargetInfo
-RPCRT4.dll!I_RpcBindingInqSecurityContext
-RPCRT4.dll!I_RpcBindingInqSecurityContextKeyInfo
-RPCRT4.dll!I_RpcBindingInqTransportType
-RPCRT4.dll!I_RpcBindingInqWireIdForSnego
-RPCRT4.dll!I_RpcBindingIsClientLocal
-RPCRT4.dll!I_RpcBindingIsServerLocal
-RPCRT4.dll!I_RpcBindingSetPrivateOption
-RPCRT4.dll!I_RpcBindingToStaticStringBindingW
-RPCRT4.dll!I_RpcCertProcessAndProvision
-RPCRT4.dll!I_RpcClearMutex
-RPCRT4.dll!I_RpcCompleteAndFree
-RPCRT4.dll!I_RpcConnectionInqSockBuffSize
-RPCRT4.dll!I_RpcConnectionSetSockBuffSize
-RPCRT4.dll!I_RpcDeleteMutex
-RPCRT4.dll!I_RpcEnableWmiTrace
-RPCRT4.dll!I_RpcExceptionFilter
-RPCRT4.dll!I_RpcFilterDCOMActivation
-RPCRT4.dll!I_RpcFree
-RPCRT4.dll!I_RpcFreeBuffer
-RPCRT4.dll!I_RpcFreePipeBuffer
-RPCRT4.dll!I_RpcFwThisIsTheManager
-RPCRT4.dll!I_RpcGetBuffer
-RPCRT4.dll!I_RpcGetBufferWithObject
-RPCRT4.dll!I_RpcGetCurrentCallHandle
-RPCRT4.dll!I_RpcGetDefaultSD
-RPCRT4.dll!I_RpcGetExtendedError
-RPCRT4.dll!I_RpcGetPortAllocationData
-RPCRT4.dll!I_RpcIfInqTransferSyntaxes
-RPCRT4.dll!I_RpcInitNdrImports
-RPCRT4.dll!I_RpcLogEvent
-RPCRT4.dll!I_RpcMapWin32Status
-RPCRT4.dll!I_RpcMarshalBindingHandleAndInterfaceForNDF
-RPCRT4.dll!I_RpcMgmtEnableDedicatedThreadPool
-RPCRT4.dll!I_RpcMgmtQueryDedicatedThreadPool
-RPCRT4.dll!I_RpcNDRCGetWireRepresentation
-RPCRT4.dll!I_RpcNDRSContextEmergencyCleanup
-RPCRT4.dll!I_RpcNegotiateTransferSyntax
-RPCRT4.dll!I_RpcNsBindingSetEntryName
-RPCRT4.dll!I_RpcNsBindingSetEntryNameA
-RPCRT4.dll!I_RpcNsBindingSetEntryNameW
-RPCRT4.dll!I_RpcNsInterfaceExported
-RPCRT4.dll!I_RpcNsInterfaceUnexported
-RPCRT4.dll!I_RpcOpenClientProcess
-RPCRT4.dll!I_RpcOpenClientThread
-RPCRT4.dll!I_RpcParseSecurity
-RPCRT4.dll!I_RpcPauseExecution
-RPCRT4.dll!I_RpcReallocPipeBuffer
-RPCRT4.dll!I_RpcReceive
-RPCRT4.dll!I_RpcRecordCalloutFailure
-RPCRT4.dll!I_RpcRequestMutex
-RPCRT4.dll!I_RpcSend
-RPCRT4.dll!I_RpcSendReceive
-RPCRT4.dll!I_RpcServerAllocateIpPort
-RPCRT4.dll!I_RpcServerCheckClientRestriction
-RPCRT4.dll!I_RpcServerDisableExceptionFilter
-RPCRT4.dll!I_RpcServerGetAssociationID
-RPCRT4.dll!I_RpcServerInqAddressChangeFn
-RPCRT4.dll!I_RpcServerInqLocalConnAddress
-RPCRT4.dll!I_RpcServerInqRemoteConnAddress
-RPCRT4.dll!I_RpcServerInqTransportType
-RPCRT4.dll!I_RpcServerIsClientDisconnected
-RPCRT4.dll!I_RpcServerRegisterForwardFunction
-RPCRT4.dll!I_RpcServerSetAddressChangeFn
-RPCRT4.dll!I_RpcServerStartService
-RPCRT4.dll!I_RpcServerSubscribeForDisconnectNotification
-RPCRT4.dll!I_RpcServerTurnOnOffKeepalives
-RPCRT4.dll!I_RpcServerUseProtseq2A
-RPCRT4.dll!I_RpcServerUseProtseq2W
-RPCRT4.dll!I_RpcServerUseProtseqEp2A
-RPCRT4.dll!I_RpcServerUseProtseqEp2W
-RPCRT4.dll!I_RpcSessionStrictContextHandle
-RPCRT4.dll!I_RpcSetDCOMAppId
-RPCRT4.dll!I_RpcSNCHOption
-RPCRT4.dll!I_RpcSsDontSerializeContext
-RPCRT4.dll!I_RpcSystemFunction001
-RPCRT4.dll!I_RpcTransConnectionAllocatePacket
-RPCRT4.dll!I_RpcTransConnectionFreePacket
-RPCRT4.dll!I_RpcTransConnectionReallocPacket
-RPCRT4.dll!I_RpcTransDatagramAllocate
-RPCRT4.dll!I_RpcTransDatagramAllocate2
-RPCRT4.dll!I_RpcTransDatagramFree
-RPCRT4.dll!I_RpcTransGetThreadEvent
-RPCRT4.dll!I_RpcTransGetThreadEventThreadOptional
-RPCRT4.dll!I_RpcTransIoCancelled
-RPCRT4.dll!I_RpcTransServerNewConnection
-RPCRT4.dll!I_RpcTurnOnEEInfoPropagation
-RPCRT4.dll!I_UuidCreate
-RPCRT4.dll!IUnknown_AddRef_Proxy
-RPCRT4.dll!IUnknown_QueryInterface_Proxy
-RPCRT4.dll!IUnknown_Release_Proxy
-RPCRT4.dll!MesBufferHandleReset
-RPCRT4.dll!MesDecodeBufferHandleCreate
-RPCRT4.dll!MesDecodeIncrementalHandleCreate
-RPCRT4.dll!MesEncodeDynBufferHandleCreate
-RPCRT4.dll!MesEncodeFixedBufferHandleCreate
-RPCRT4.dll!MesEncodeIncrementalHandleCreate
-RPCRT4.dll!MesHandleFree
-RPCRT4.dll!MesIncrementalHandleReset
-RPCRT4.dll!MesInqProcEncodingId
-RPCRT4.dll!NdrAllocate
-RPCRT4.dll!NdrAsyncClientCall
-RPCRT4.dll!NdrAsyncClientCall2
-RPCRT4.dll!NdrAsyncServerCall
-RPCRT4.dll!NdrByteCountPointerBufferSize
-RPCRT4.dll!NdrByteCountPointerFree
-RPCRT4.dll!NdrByteCountPointerMarshall
-RPCRT4.dll!NdrByteCountPointerUnmarshall
-RPCRT4.dll!NDRCContextBinding
-RPCRT4.dll!NDRCContextMarshall
-RPCRT4.dll!NDRCContextUnmarshall
-RPCRT4.dll!NdrClearOutParameters
-RPCRT4.dll!NdrClientCall
-RPCRT4.dll!NdrClientCall2
-RPCRT4.dll!NdrClientCall4
-RPCRT4.dll!NdrClientContextMarshall
-RPCRT4.dll!NdrClientContextUnmarshall
-RPCRT4.dll!NdrClientInitialize
-RPCRT4.dll!NdrClientInitializeNew
-RPCRT4.dll!NdrComplexArrayBufferSize
-RPCRT4.dll!NdrComplexArrayFree
-RPCRT4.dll!NdrComplexArrayMarshall
-RPCRT4.dll!NdrComplexArrayMemorySize
-RPCRT4.dll!NdrComplexArrayUnmarshall
-RPCRT4.dll!NdrComplexStructBufferSize
-RPCRT4.dll!NdrComplexStructFree
-RPCRT4.dll!NdrComplexStructMarshall
-RPCRT4.dll!NdrComplexStructMemorySize
-RPCRT4.dll!NdrComplexStructUnmarshall
-RPCRT4.dll!NdrConformantArrayBufferSize
-RPCRT4.dll!NdrConformantArrayFree
-RPCRT4.dll!NdrConformantArrayMarshall
-RPCRT4.dll!NdrConformantArrayMemorySize
-RPCRT4.dll!NdrConformantArrayUnmarshall
-RPCRT4.dll!NdrConformantStringBufferSize
-RPCRT4.dll!NdrConformantStringMarshall
-RPCRT4.dll!NdrConformantStringMemorySize
-RPCRT4.dll!NdrConformantStringUnmarshall
-RPCRT4.dll!NdrConformantStructBufferSize
-RPCRT4.dll!NdrConformantStructFree
-RPCRT4.dll!NdrConformantStructMarshall
-RPCRT4.dll!NdrConformantStructMemorySize
-RPCRT4.dll!NdrConformantStructUnmarshall
-RPCRT4.dll!NdrConformantVaryingArrayBufferSize
-RPCRT4.dll!NdrConformantVaryingArrayFree
-RPCRT4.dll!NdrConformantVaryingArrayMarshall
-RPCRT4.dll!NdrConformantVaryingArrayMemorySize
-RPCRT4.dll!NdrConformantVaryingArrayUnmarshall
-RPCRT4.dll!NdrConformantVaryingStructBufferSize
-RPCRT4.dll!NdrConformantVaryingStructFree
-RPCRT4.dll!NdrConformantVaryingStructMarshall
-RPCRT4.dll!NdrConformantVaryingStructMemorySize
-RPCRT4.dll!NdrConformantVaryingStructUnmarshall
-RPCRT4.dll!NdrContextHandleInitialize
-RPCRT4.dll!NdrContextHandleSize
-RPCRT4.dll!NdrConvert
-RPCRT4.dll!NdrConvert2
-RPCRT4.dll!NdrCorrelationFree
-RPCRT4.dll!NdrCorrelationInitialize
-RPCRT4.dll!NdrCorrelationPass
-RPCRT4.dll!NdrCreateServerInterfaceFromStub
-RPCRT4.dll!NdrCStdStubBuffer_Release
-RPCRT4.dll!NdrCStdStubBuffer2_Release
-RPCRT4.dll!NdrDcomAsyncClientCall
-RPCRT4.dll!NdrDcomAsyncStubCall
-RPCRT4.dll!NdrDllCanUnloadNow
-RPCRT4.dll!NdrDllGetClassObject
-RPCRT4.dll!NdrDllRegisterProxy
-RPCRT4.dll!NdrDllUnregisterProxy
-RPCRT4.dll!NdrEncapsulatedUnionBufferSize
-RPCRT4.dll!NdrEncapsulatedUnionFree
-RPCRT4.dll!NdrEncapsulatedUnionMarshall
-RPCRT4.dll!NdrEncapsulatedUnionMemorySize
-RPCRT4.dll!NdrEncapsulatedUnionUnmarshall
-RPCRT4.dll!NdrFixedArrayBufferSize
-RPCRT4.dll!NdrFixedArrayFree
-RPCRT4.dll!NdrFixedArrayMarshall
-RPCRT4.dll!NdrFixedArrayMemorySize
-RPCRT4.dll!NdrFixedArrayUnmarshall
-RPCRT4.dll!NdrFreeBuffer
-RPCRT4.dll!NdrFullPointerFree
-RPCRT4.dll!NdrFullPointerInsertRefId
-RPCRT4.dll!NdrFullPointerQueryPointer
-RPCRT4.dll!NdrFullPointerQueryRefId
-RPCRT4.dll!NdrFullPointerXlatFree
-RPCRT4.dll!NdrFullPointerXlatInit
-RPCRT4.dll!NdrGetBaseInterfaceFromStub
-RPCRT4.dll!NdrGetBuffer
-RPCRT4.dll!NdrGetDcomProtocolVersion
-RPCRT4.dll!NdrGetSimpleTypeBufferAlignment
-RPCRT4.dll!NdrGetSimpleTypeBufferSize
-RPCRT4.dll!NdrGetSimpleTypeMemorySize
-RPCRT4.dll!NdrGetTypeFlags
-RPCRT4.dll!NdrGetUserMarshalInfo
-RPCRT4.dll!NdrInterfacePointerBufferSize
-RPCRT4.dll!NdrInterfacePointerFree
-RPCRT4.dll!NdrInterfacePointerMarshall
-RPCRT4.dll!NdrInterfacePointerMemorySize
-RPCRT4.dll!NdrInterfacePointerUnmarshall
-RPCRT4.dll!NdrMapCommAndFaultStatus
-RPCRT4.dll!NdrMesProcEncodeDecode
-RPCRT4.dll!NdrMesProcEncodeDecode2
-RPCRT4.dll!NdrMesSimpleTypeAlignSize
-RPCRT4.dll!NdrMesSimpleTypeDecode
-RPCRT4.dll!NdrMesSimpleTypeEncode
-RPCRT4.dll!NdrMesTypeAlignSize
-RPCRT4.dll!NdrMesTypeAlignSize2
-RPCRT4.dll!NdrMesTypeDecode
-RPCRT4.dll!NdrMesTypeDecode2
-RPCRT4.dll!NdrMesTypeEncode
-RPCRT4.dll!NdrMesTypeEncode2
-RPCRT4.dll!NdrMesTypeFree2
-RPCRT4.dll!NdrNonConformantStringBufferSize
-RPCRT4.dll!NdrNonConformantStringMarshall
-RPCRT4.dll!NdrNonConformantStringMemorySize
-RPCRT4.dll!NdrNonConformantStringUnmarshall
-RPCRT4.dll!NdrNonEncapsulatedUnionBufferSize
-RPCRT4.dll!NdrNonEncapsulatedUnionFree
-RPCRT4.dll!NdrNonEncapsulatedUnionMarshall
-RPCRT4.dll!NdrNonEncapsulatedUnionMemorySize
-RPCRT4.dll!NdrNonEncapsulatedUnionUnmarshall
-RPCRT4.dll!NdrNsGetBuffer
-RPCRT4.dll!NdrNsSendReceive
-RPCRT4.dll!NdrOleAllocate
-RPCRT4.dll!NdrOleFree
-RPCRT4.dll!NdrOutInit
-RPCRT4.dll!NdrPartialIgnoreClientBufferSize
-RPCRT4.dll!NdrPartialIgnoreClientMarshall
-RPCRT4.dll!NdrPartialIgnoreServerInitialize
-RPCRT4.dll!NdrPartialIgnoreServerUnmarshall
-RPCRT4.dll!NdrpCreateProxy
-RPCRT4.dll!NdrpCreateStub
-RPCRT4.dll!NdrpGetProcFormatString
-RPCRT4.dll!NdrpGetTypeFormatString
-RPCRT4.dll!NdrpGetTypeGenCookie
-RPCRT4.dll!NdrpMemoryIncrement
-RPCRT4.dll!NdrPointerBufferSize
-RPCRT4.dll!NdrPointerFree
-RPCRT4.dll!NdrPointerMarshall
-RPCRT4.dll!NdrPointerMemorySize
-RPCRT4.dll!NdrPointerUnmarshall
-RPCRT4.dll!NdrpReleaseTypeFormatString
-RPCRT4.dll!NdrpReleaseTypeGenCookie
-RPCRT4.dll!NdrProxyErrorHandler
-RPCRT4.dll!NdrProxyFreeBuffer
-RPCRT4.dll!NdrProxyGetBuffer
-RPCRT4.dll!NdrProxyInitialize
-RPCRT4.dll!NdrProxySendReceive
-RPCRT4.dll!NdrpVarVtOfTypeDesc
-RPCRT4.dll!NdrRangeUnmarshall
-RPCRT4.dll!NdrRpcSmClientAllocate
-RPCRT4.dll!NdrRpcSmClientFree
-RPCRT4.dll!NdrRpcSmSetClientToOsf
-RPCRT4.dll!NdrRpcSsDefaultAllocate
-RPCRT4.dll!NdrRpcSsDefaultFree
-RPCRT4.dll!NdrRpcSsDisableAllocate
-RPCRT4.dll!NdrRpcSsEnableAllocate
-RPCRT4.dll!NDRSContextMarshall
-RPCRT4.dll!NDRSContextMarshall2
-RPCRT4.dll!NDRSContextMarshallEx
-RPCRT4.dll!NDRSContextUnmarshall
-RPCRT4.dll!NDRSContextUnmarshall2
-RPCRT4.dll!NDRSContextUnmarshallEx
-RPCRT4.dll!NdrSendReceive
-RPCRT4.dll!NdrServerCall
-RPCRT4.dll!NdrServerCall2
-RPCRT4.dll!NdrServerContextMarshall
-RPCRT4.dll!NdrServerContextNewMarshall
-RPCRT4.dll!NdrServerContextNewUnmarshall
-RPCRT4.dll!NdrServerContextUnmarshall
-RPCRT4.dll!NdrServerInitialize
-RPCRT4.dll!NdrServerInitializeMarshall
-RPCRT4.dll!NdrServerInitializeNew
-RPCRT4.dll!NdrServerInitializePartial
-RPCRT4.dll!NdrServerInitializeUnmarshall
-RPCRT4.dll!NdrServerMarshall
-RPCRT4.dll!NdrServerUnmarshall
-RPCRT4.dll!NdrSimpleStructBufferSize
-RPCRT4.dll!NdrSimpleStructFree
-RPCRT4.dll!NdrSimpleStructMarshall
-RPCRT4.dll!NdrSimpleStructMemorySize
-RPCRT4.dll!NdrSimpleStructUnmarshall
-RPCRT4.dll!NdrSimpleTypeMarshall
-RPCRT4.dll!NdrSimpleTypeUnmarshall
-RPCRT4.dll!NdrStubCall
-RPCRT4.dll!NdrStubCall2
-RPCRT4.dll!NdrStubForwardingFunction
-RPCRT4.dll!NdrStubGetBuffer
-RPCRT4.dll!NdrStubInitialize
-RPCRT4.dll!NdrStubInitializeMarshall
-RPCRT4.dll!NdrTypeFlags
-RPCRT4.dll!NdrTypeFree
-RPCRT4.dll!NdrTypeMarshall
-RPCRT4.dll!NdrTypeSize
-RPCRT4.dll!NdrTypeUnmarshall
-RPCRT4.dll!NdrUnmarshallBasetypeInline
-RPCRT4.dll!NdrUserMarshalBufferSize
-RPCRT4.dll!NdrUserMarshalFree
-RPCRT4.dll!NdrUserMarshalMarshall
-RPCRT4.dll!NdrUserMarshalMemorySize
-RPCRT4.dll!NdrUserMarshalSimpleTypeConvert
-RPCRT4.dll!NdrUserMarshalUnmarshall
-RPCRT4.dll!NdrVaryingArrayBufferSize
-RPCRT4.dll!NdrVaryingArrayFree
-RPCRT4.dll!NdrVaryingArrayMarshall
-RPCRT4.dll!NdrVaryingArrayMemorySize
-RPCRT4.dll!NdrVaryingArrayUnmarshall
-RPCRT4.dll!NdrXmitOrRepAsBufferSize
-RPCRT4.dll!NdrXmitOrRepAsFree
-RPCRT4.dll!NdrXmitOrRepAsMarshall
-RPCRT4.dll!NdrXmitOrRepAsMemorySize
-RPCRT4.dll!NdrXmitOrRepAsUnmarshall
-RPCRT4.dll!pfnFreeRoutines
-RPCRT4.dll!pfnMarshallRoutines
-RPCRT4.dll!pfnSizeRoutines
-RPCRT4.dll!pfnUnmarshallRoutines
-RPCRT4.dll!RpcAsyncAbortCall
-RPCRT4.dll!RpcAsyncCancelCall
-RPCRT4.dll!RpcAsyncCompleteCall
-RPCRT4.dll!RpcAsyncGetCallStatus
-RPCRT4.dll!RpcAsyncInitializeHandle
-RPCRT4.dll!RpcAsyncRegisterInfo
-RPCRT4.dll!RpcBindingBind
-RPCRT4.dll!RpcBindingCopy
-RPCRT4.dll!RpcBindingCreateA
-RPCRT4.dll!RpcBindingCreateW
-RPCRT4.dll!RpcBindingFree
-RPCRT4.dll!RpcBindingFromStringBindingA
-RPCRT4.dll!RpcBindingFromStringBindingW
-RPCRT4.dll!RpcBindingInqAuthClientA
-RPCRT4.dll!RpcBindingInqAuthClientExA
-RPCRT4.dll!RpcBindingInqAuthClientExW
-RPCRT4.dll!RpcBindingInqAuthClientW
-RPCRT4.dll!RpcBindingInqAuthInfoA
-RPCRT4.dll!RpcBindingInqAuthInfoExA
-RPCRT4.dll!RpcBindingInqAuthInfoExW
-RPCRT4.dll!RpcBindingInqAuthInfoW
-RPCRT4.dll!RpcBindingInqObject
-RPCRT4.dll!RpcBindingInqOption
-RPCRT4.dll!RpcBindingReset
-RPCRT4.dll!RpcBindingServerFromClient
-RPCRT4.dll!RpcBindingSetAuthInfoA
-RPCRT4.dll!RpcBindingSetAuthInfoExA
-RPCRT4.dll!RpcBindingSetAuthInfoExW
-RPCRT4.dll!RpcBindingSetAuthInfoW
-RPCRT4.dll!RpcBindingSetObject
-RPCRT4.dll!RpcBindingSetOption
-RPCRT4.dll!RpcBindingToStringBindingA
-RPCRT4.dll!RpcBindingToStringBindingW
-RPCRT4.dll!RpcBindingUnbind
-RPCRT4.dll!RpcBindingVectorFree
-RPCRT4.dll!RpcCancelThread
-RPCRT4.dll!RpcCancelThreadEx
-RPCRT4.dll!RpcCertGeneratePrincipalNameA
-RPCRT4.dll!RpcCertGeneratePrincipalNameW
-RPCRT4.dll!RpcEpRegisterA
-RPCRT4.dll!RpcEpRegisterNoReplaceA
-RPCRT4.dll!RpcEpRegisterNoReplaceW
-RPCRT4.dll!RpcEpRegisterW
-RPCRT4.dll!RpcEpResolveBinding
-RPCRT4.dll!RpcEpUnregister
-RPCRT4.dll!RpcErrorAddRecord
-RPCRT4.dll!RpcErrorClearInformation
-RPCRT4.dll!RpcErrorEndEnumeration
-RPCRT4.dll!RpcErrorGetNextRecord
-RPCRT4.dll!RpcErrorGetNumberOfRecords
-RPCRT4.dll!RpcErrorLoadErrorInfo
-RPCRT4.dll!RpcErrorResetEnumeration
-RPCRT4.dll!RpcErrorSaveErrorInfo
-RPCRT4.dll!RpcErrorStartEnumeration
-RPCRT4.dll!RpcExceptionFilter
-RPCRT4.dll!RpcFreeAuthorizationContext
-RPCRT4.dll!RpcGetAuthorizationContextForClient
-RPCRT4.dll!RpcIfIdVectorFree
-RPCRT4.dll!RpcIfInqId
-RPCRT4.dll!RpcImpersonateClient
-RPCRT4.dll!RpcImpersonateClient2
-RPCRT4.dll!RpcImpersonateClientContainer
-RPCRT4.dll!RpcMgmtEnableIdleCleanup
-RPCRT4.dll!RpcMgmtEpEltInqBegin
-RPCRT4.dll!RpcMgmtEpEltInqDone
-RPCRT4.dll!RpcMgmtEpEltInqNextA
-RPCRT4.dll!RpcMgmtEpEltInqNextW
-RPCRT4.dll!RpcMgmtEpUnregister
-RPCRT4.dll!RpcMgmtInqComTimeout
-RPCRT4.dll!RpcMgmtInqDefaultProtectLevel
-RPCRT4.dll!RpcMgmtInqIfIds
-RPCRT4.dll!RpcMgmtInqServerPrincNameA
-RPCRT4.dll!RpcMgmtInqServerPrincNameW
-RPCRT4.dll!RpcMgmtInqStats
-RPCRT4.dll!RpcMgmtIsServerListening
-RPCRT4.dll!RpcMgmtSetAuthorizationFn
-RPCRT4.dll!RpcMgmtSetCancelTimeout
-RPCRT4.dll!RpcMgmtSetComTimeout
-RPCRT4.dll!RpcMgmtSetServerStackSize
-RPCRT4.dll!RpcMgmtStatsVectorFree
-RPCRT4.dll!RpcMgmtStopServerListening
-RPCRT4.dll!RpcMgmtWaitServerListen
-RPCRT4.dll!RpcNetworkInqProtseqsA
-RPCRT4.dll!RpcNetworkInqProtseqsW
-RPCRT4.dll!RpcNetworkIsProtseqValidA
-RPCRT4.dll!RpcNetworkIsProtseqValidW
-RPCRT4.dll!RpcNsBindingInqEntryNameA
-RPCRT4.dll!RpcNsBindingInqEntryNameW
-RPCRT4.dll!RpcObjectInqType
-RPCRT4.dll!RpcObjectSetInqFn
-RPCRT4.dll!RpcObjectSetType
-RPCRT4.dll!RpcProtseqVectorFreeA
-RPCRT4.dll!RpcProtseqVectorFreeW
-RPCRT4.dll!RpcRaiseException
-RPCRT4.dll!RpcRevertContainerImpersonation
-RPCRT4.dll!RpcRevertToSelf
-RPCRT4.dll!RpcRevertToSelfEx
-RPCRT4.dll!RpcServerCompleteSecurityCallback
-RPCRT4.dll!RpcServerInqBindingHandle
-RPCRT4.dll!RpcServerInqBindings
-RPCRT4.dll!RpcServerInqCallAttributesA
-RPCRT4.dll!RpcServerInqCallAttributesW
-RPCRT4.dll!RpcServerInqDefaultPrincNameA
-RPCRT4.dll!RpcServerInqDefaultPrincNameW
-RPCRT4.dll!RpcServerInqIf
-RPCRT4.dll!RpcServerInterfaceGroupActivate
-RPCRT4.dll!RpcServerInterfaceGroupClose
-RPCRT4.dll!RpcServerInterfaceGroupCreateA
-RPCRT4.dll!RpcServerInterfaceGroupCreateW
-RPCRT4.dll!RpcServerInterfaceGroupDeactivate
-RPCRT4.dll!RpcServerInterfaceGroupInqBindings
-RPCRT4.dll!RpcServerListen
-RPCRT4.dll!RpcServerRegisterAuthInfoA
-RPCRT4.dll!RpcServerRegisterAuthInfoW
-RPCRT4.dll!RpcServerRegisterIf
-RPCRT4.dll!RpcServerRegisterIf2
-RPCRT4.dll!RpcServerRegisterIf3
-RPCRT4.dll!RpcServerRegisterIfEx
-RPCRT4.dll!RpcServerSubscribeForNotification
-RPCRT4.dll!RpcServerTestCancel
-RPCRT4.dll!RpcServerUnregisterIf
-RPCRT4.dll!RpcServerUnregisterIfEx
-RPCRT4.dll!RpcServerUnsubscribeForNotification
-RPCRT4.dll!RpcServerUseAllProtseqs
-RPCRT4.dll!RpcServerUseAllProtseqsEx
-RPCRT4.dll!RpcServerUseAllProtseqsIf
-RPCRT4.dll!RpcServerUseAllProtseqsIfEx
-RPCRT4.dll!RpcServerUseProtseqA
-RPCRT4.dll!RpcServerUseProtseqEpA
-RPCRT4.dll!RpcServerUseProtseqEpExA
-RPCRT4.dll!RpcServerUseProtseqEpExW
-RPCRT4.dll!RpcServerUseProtseqEpW
-RPCRT4.dll!RpcServerUseProtseqExA
-RPCRT4.dll!RpcServerUseProtseqExW
-RPCRT4.dll!RpcServerUseProtseqIfA
-RPCRT4.dll!RpcServerUseProtseqIfExA
-RPCRT4.dll!RpcServerUseProtseqIfExW
-RPCRT4.dll!RpcServerUseProtseqIfW
-RPCRT4.dll!RpcServerUseProtseqW
-RPCRT4.dll!RpcServerYield
-RPCRT4.dll!RpcSmAllocate
-RPCRT4.dll!RpcSmClientFree
-RPCRT4.dll!RpcSmDestroyClientContext
-RPCRT4.dll!RpcSmDisableAllocate
-RPCRT4.dll!RpcSmEnableAllocate
-RPCRT4.dll!RpcSmFree
-RPCRT4.dll!RpcSmGetThreadHandle
-RPCRT4.dll!RpcSmSetClientAllocFree
-RPCRT4.dll!RpcSmSetThreadHandle
-RPCRT4.dll!RpcSmSwapClientAllocFree
-RPCRT4.dll!RpcSsAllocate
-RPCRT4.dll!RpcSsContextLockExclusive
-RPCRT4.dll!RpcSsContextLockShared
-RPCRT4.dll!RpcSsDestroyClientContext
-RPCRT4.dll!RpcSsDisableAllocate
-RPCRT4.dll!RpcSsDontSerializeContext
-RPCRT4.dll!RpcSsEnableAllocate
-RPCRT4.dll!RpcSsFree
-RPCRT4.dll!RpcSsGetContextBinding
-RPCRT4.dll!RpcSsGetThreadHandle
-RPCRT4.dll!RpcSsSetClientAllocFree
-RPCRT4.dll!RpcSsSetThreadHandle
-RPCRT4.dll!RpcSsSwapClientAllocFree
-RPCRT4.dll!RpcStringBindingComposeA
-RPCRT4.dll!RpcStringBindingComposeW
-RPCRT4.dll!RpcStringBindingParseA
-RPCRT4.dll!RpcStringBindingParseW
-RPCRT4.dll!RpcStringFreeA
-RPCRT4.dll!RpcStringFreeW
-RPCRT4.dll!RpcTestCancel
-RPCRT4.dll!RpcUserFree
-RPCRT4.dll!SimpleTypeAlignment
-RPCRT4.dll!SimpleTypeBufferSize
-RPCRT4.dll!SimpleTypeMemorySize
-RPCRT4.dll!TowerConstruct
-RPCRT4.dll!TowerExplode
-RPCRT4.dll!UuidCompare
-RPCRT4.dll!UuidCreate
-RPCRT4.dll!UuidCreateNil
-RPCRT4.dll!UuidCreateSequential
-RPCRT4.dll!UuidEqual
-RPCRT4.dll!UuidFromStringA
-RPCRT4.dll!UuidFromStringW
-RPCRT4.dll!UuidHash
-RPCRT4.dll!UuidIsNil
-RPCRT4.dll!UuidToStringA
-RPCRT4.dll!UuidToStringW
-samcli.dll!NetGetDisplayInformationIndex
-samcli.dll!NetGroupAdd
-samcli.dll!NetGroupAddUser
-samcli.dll!NetGroupDel
-samcli.dll!NetGroupDelUser
-samcli.dll!NetGroupEnum
-samcli.dll!NetGroupGetInfo
-samcli.dll!NetGroupGetUsers
-samcli.dll!NetGroupSetInfo
-samcli.dll!NetGroupSetUsers
-samcli.dll!NetLocalGroupAdd
-samcli.dll!NetLocalGroupAddMember
-samcli.dll!NetLocalGroupAddMembers
-samcli.dll!NetLocalGroupDel
-samcli.dll!NetLocalGroupDelMember
-samcli.dll!NetLocalGroupDelMembers
-samcli.dll!NetLocalGroupEnum
-samcli.dll!NetLocalGroupGetInfo
-samcli.dll!NetLocalGroupGetMembers
-samcli.dll!NetLocalGroupSetInfo
-samcli.dll!NetLocalGroupSetMembers
-samcli.dll!NetQueryDisplayInformation
-samcli.dll!NetUserAdd
-samcli.dll!NetUserChangePassword
-samcli.dll!NetUserDel
-samcli.dll!NetUserEnum
-samcli.dll!NetUserGetGroups
-samcli.dll!NetUserGetInfo
-samcli.dll!NetUserGetInternetIdentityInfo
-samcli.dll!NetUserGetLocalGroups
-samcli.dll!NetUserModalsGet
-samcli.dll!NetUserModalsSet
-samcli.dll!NetUserSetGroups
-samcli.dll!NetUserSetInfo
-samcli.dll!NetValidatePasswordPolicy
-samcli.dll!NetValidatePasswordPolicyFree
-schedcli.dll!NetScheduleJobAdd
-schedcli.dll!NetScheduleJobDel
-schedcli.dll!NetScheduleJobEnum
-schedcli.dll!NetScheduleJobGetInfo
-srvcli.dll!LocalAliasGet
-srvcli.dll!LocalFileClose
-srvcli.dll!LocalFileEnum
-srvcli.dll!LocalFileEnumEx
-srvcli.dll!LocalFileGetInfo
-srvcli.dll!LocalFileGetInfoEx
-srvcli.dll!LocalSessionDel
-srvcli.dll!LocalSessionEnum
-srvcli.dll!LocalSessionEnumEx
-srvcli.dll!LocalSessionGetInfo
-srvcli.dll!LocalSessionGetInfoEx
-srvcli.dll!LocalShareAdd
-srvcli.dll!LocalShareDelEx
-srvcli.dll!LocalShareEnum
-srvcli.dll!LocalShareEnumEx
-srvcli.dll!LocalShareGetInfo
-srvcli.dll!LocalShareGetInfoEx
-srvcli.dll!LocalShareSetInfo
-srvcli.dll!NetConnectionEnum
-srvcli.dll!NetFileClose
-srvcli.dll!NetFileEnum
-srvcli.dll!NetFileGetInfo
-srvcli.dll!NetRemoteTOD
-srvcli.dll!NetServerAliasAdd
-srvcli.dll!NetServerAliasDel
-srvcli.dll!NetServerAliasEnum
-srvcli.dll!NetServerComputerNameAdd
-srvcli.dll!NetServerComputerNameDel
-srvcli.dll!NetServerDiskEnum
-srvcli.dll!NetServerGetInfo
-srvcli.dll!NetServerSetInfo
-srvcli.dll!NetServerStatisticsGet
-srvcli.dll!NetServerTransportAdd
-srvcli.dll!NetServerTransportAddEx
-srvcli.dll!NetServerTransportDel
-srvcli.dll!NetServerTransportEnum
-srvcli.dll!NetSessionDel
-srvcli.dll!NetSessionEnum
-srvcli.dll!NetSessionGetInfo
-srvcli.dll!NetShareAdd
-srvcli.dll!NetShareCheck
-srvcli.dll!NetShareDel
-srvcli.dll!NetShareDelEx
-srvcli.dll!NetShareDelSticky
-srvcli.dll!NetShareEnum
-srvcli.dll!NetShareEnumSticky
-srvcli.dll!NetShareGetInfo
-srvcli.dll!NetShareSetInfo
-SspiCli.dll!AcceptSecurityContext
-SspiCli.dll!AcquireCredentialsHandleA
-SspiCli.dll!AcquireCredentialsHandleW
-SspiCli.dll!AddCredentialsA
-SspiCli.dll!AddCredentialsW
-SspiCli.dll!AddSecurityPackageA
-SspiCli.dll!AddSecurityPackageW
-SspiCli.dll!ApplyControlToken
-SspiCli.dll!ChangeAccountPasswordA
-SspiCli.dll!ChangeAccountPasswordW
-SspiCli.dll!CompleteAuthToken
-SspiCli.dll!DecryptMessage
-SspiCli.dll!DeleteSecurityContext
-SspiCli.dll!DeleteSecurityPackageA
-SspiCli.dll!DeleteSecurityPackageW
-SspiCli.dll!EncryptMessage
-SspiCli.dll!EnumerateSecurityPackagesA
-SspiCli.dll!EnumerateSecurityPackagesW
-SspiCli.dll!ExportSecurityContext
-SspiCli.dll!FreeContextBuffer
-SspiCli.dll!FreeCredentialsHandle
-SspiCli.dll!GetUserNameExA
-SspiCli.dll!GetUserNameExW
-SspiCli.dll!ImpersonateSecurityContext
-SspiCli.dll!ImportSecurityContextA
-SspiCli.dll!ImportSecurityContextW
-SspiCli.dll!InitializeSecurityContextA
-SspiCli.dll!InitializeSecurityContextW
-SspiCli.dll!InitSecurityInterfaceA
-SspiCli.dll!InitSecurityInterfaceW
-SspiCli.dll!LogonUserExExW
-SspiCli.dll!LsaCallAuthenticationPackage
-SspiCli.dll!LsaConnectUntrusted
-SspiCli.dll!LsaDeregisterLogonProcess
-SspiCli.dll!LsaEnumerateLogonSessions
-SspiCli.dll!LsaFreeReturnBuffer
-SspiCli.dll!LsaGetLogonSessionData
-SspiCli.dll!LsaLogonUser
-SspiCli.dll!LsaLookupAuthenticationPackage
-SspiCli.dll!LsaRegisterLogonProcess
-SspiCli.dll!LsaRegisterPolicyChangeNotification
-SspiCli.dll!LsaUnregisterPolicyChangeNotification
-SspiCli.dll!MakeSignature
-SspiCli.dll!QueryContextAttributesA
-SspiCli.dll!QueryContextAttributesExA
-SspiCli.dll!QueryContextAttributesExW
-SspiCli.dll!QueryContextAttributesW
-SspiCli.dll!QueryCredentialsAttributesA
-SspiCli.dll!QueryCredentialsAttributesExA
-SspiCli.dll!QueryCredentialsAttributesExW
-SspiCli.dll!QueryCredentialsAttributesW
-SspiCli.dll!QuerySecurityContextToken
-SspiCli.dll!QuerySecurityPackageInfoA
-SspiCli.dll!QuerySecurityPackageInfoW
-SspiCli.dll!RevertSecurityContext
-SspiCli.dll!SaslAcceptSecurityContext
-SspiCli.dll!SaslEnumerateProfilesA
-SspiCli.dll!SaslEnumerateProfilesW
-SspiCli.dll!SaslGetContextOption
-SspiCli.dll!SaslGetProfilePackageA
-SspiCli.dll!SaslGetProfilePackageW
-SspiCli.dll!SaslIdentifyPackageA
-SspiCli.dll!SaslIdentifyPackageW
-SspiCli.dll!SaslInitializeSecurityContextA
-SspiCli.dll!SaslInitializeSecurityContextW
-SspiCli.dll!SaslSetContextOption
-SspiCli.dll!SealMessage
-SspiCli.dll!SetContextAttributesA
-SspiCli.dll!SetContextAttributesW
-SspiCli.dll!SetCredentialsAttributesA
-SspiCli.dll!SetCredentialsAttributesW
-SspiCli.dll!SspiCompareAuthIdentities
-SspiCli.dll!SspiCopyAuthIdentity
-SspiCli.dll!SspiDecryptAuthIdentity
-SspiCli.dll!SspiDecryptAuthIdentityEx
-SspiCli.dll!SspiEncodeAuthIdentityAsStrings
-SspiCli.dll!SspiEncodeStringsAsAuthIdentity
-SspiCli.dll!SspiEncryptAuthIdentity
-SspiCli.dll!SspiEncryptAuthIdentityEx
-SspiCli.dll!SspiExcludePackage
-SspiCli.dll!SspiFreeAuthIdentity
-SspiCli.dll!SspiGetTargetHostName
-SspiCli.dll!SspiIsAuthIdentityEncrypted
-SspiCli.dll!SspiLocalFree
-SspiCli.dll!SspiMarshalAuthIdentity
-SspiCli.dll!SspiPrepareForCredRead
-SspiCli.dll!SspiPrepareForCredWrite
-SspiCli.dll!SspiUnmarshalAuthIdentity
-SspiCli.dll!SspiValidateAuthIdentity
-SspiCli.dll!SspiZeroAuthIdentity
-SspiCli.dll!UnsealMessage
-SspiCli.dll!VerifySignature
-TOKENBINDING.dll!TokenBindingDeleteBinding
-TOKENBINDING.dll!TokenBindingGenerateBinding
-TOKENBINDING.dll!TokenBindingGenerateMessage
-TOKENBINDING.dll!TokenBindingGetKeyTypesClient
-TOKENBINDING.dll!TokenBindingGetKeyTypesServer
-TOKENBINDING.dll!TokenBindingVerifyMessage
-USERENV.dll!AreThereVisibleLogoffScripts
-USERENV.dll!AreThereVisibleShutdownScripts
-USERENV.dll!CheckDirectoryOwnership
-USERENV.dll!CheckXForestLogon
-USERENV.dll!CopyProfileDirectoryEx2
-USERENV.dll!CreateAppContainerProfile
-USERENV.dll!CreateAppContainerProfileInternal
-USERENV.dll!CreateDirectoryJunctionsForSystem
-USERENV.dll!CreateDirectoryJunctionsForUserProfile
-USERENV.dll!CreateEnvironmentBlock
-USERENV.dll!CreateGroupEx
-USERENV.dll!CreateLinkFileEx
-USERENV.dll!CreateProfile
-USERENV.dll!DeleteAppContainerProfile
-USERENV.dll!DeleteAppContainerProfileInternal
-USERENV.dll!DeleteGroup
-USERENV.dll!DeleteLinkFile
-USERENV.dll!DeleteProfileA
-USERENV.dll!DeleteProfileDirectory
-USERENV.dll!DeleteProfileW
-USERENV.dll!DeriveAppContainerSidFromAppContainerName
-USERENV.dll!DeriveRestrictedAppContainerSidFromAppContainerSidAndRestrictedName
-USERENV.dll!DestroyEnvironmentBlock
-USERENV.dll!EnterCriticalPolicySection
-USERENV.dll!ExpandEnvironmentStringsForUserA
-USERENV.dll!ExpandEnvironmentStringsForUserW
-USERENV.dll!ForceSyncFgPolicy
-USERENV.dll!FreeGPOListA
-USERENV.dll!FreeGPOListW
-USERENV.dll!GenerateGPNotification
-USERENV.dll!GetAllUsersProfileDirectoryA
-USERENV.dll!GetAllUsersProfileDirectoryW
-USERENV.dll!GetAppContainerFolderPath
-USERENV.dll!GetAppContainerRegistryLocation
-USERENV.dll!GetAppliedGPOListA
-USERENV.dll!GetAppliedGPOListW
-USERENV.dll!GetDefaultUserProfileDirectoryA
-USERENV.dll!GetDefaultUserProfileDirectoryW
-USERENV.dll!GetGPOListA
-USERENV.dll!GetGPOListW
-USERENV.dll!GetLongProfilePathName
-USERENV.dll!GetNextFgPolicyRefreshInfo
-USERENV.dll!GetPreviousFgPolicyRefreshInfo
-USERENV.dll!GetProfilesDirectoryA
-USERENV.dll!GetProfilesDirectoryW
-USERENV.dll!GetProfileType
-USERENV.dll!GetUserProfileDirectoryA
-USERENV.dll!GetUserProfileDirectoryForUserSidW
-USERENV.dll!GetUserProfileDirectoryW
-USERENV.dll!HasPolicyForegroundProcessingCompleted
-USERENV.dll!LeaveCriticalPolicySection
-USERENV.dll!LoadUserProfileA
-USERENV.dll!LoadUserProfileW
-USERENV.dll!LookupAppContainerDisplayName
-USERENV.dll!PingComputer
-USERENV.dll!ProcessGroupPolicyCompleted
-USERENV.dll!ProcessGroupPolicyCompletedEx
-USERENV.dll!RefreshPolicy
-USERENV.dll!RefreshPolicyEx
-USERENV.dll!RegisterGPNotification
-USERENV.dll!RemapProfile
-USERENV.dll!RsopAccessCheckByType
-USERENV.dll!RsopFileAccessCheck
-USERENV.dll!RsopLoggingEnabled
-USERENV.dll!RsopResetPolicySettingStatus
-USERENV.dll!RsopSetPolicySettingStatus
-USERENV.dll!UnloadUserProfile
-USERENV.dll!UnregisterGPNotification
-USERENV.dll!UpdateAppContainerProfile
-USERENV.dll!WaitForMachinePolicyForegroundProcessing
-USERENV.dll!WaitForUserPolicyForegroundProcessing
-websocket.dll!WebSocketAbortHandle
-websocket.dll!WebSocketBeginClientHandshake
-websocket.dll!WebSocketBeginServerHandshake
-websocket.dll!WebSocketCompleteAction
-websocket.dll!WebSocketCreateClientHandle
-websocket.dll!WebSocketCreateServerHandle
-websocket.dll!WebSocketDeleteHandle
-websocket.dll!WebSocketEndClientHandshake
-websocket.dll!WebSocketEndServerHandshake
-websocket.dll!WebSocketGetAction
-websocket.dll!WebSocketGetGlobalProperty
-websocket.dll!WebSocketReceive
-websocket.dll!WebSocketSend
-WINHTTP.dll!SvchostPushServiceGlobals
-WINHTTP.dll!WinHttpAddRequestHeaders
-WINHTTP.dll!WinHttpAutoProxySvcMain
-WINHTTP.dll!WinHttpCheckPlatform
-WINHTTP.dll!WinHttpCloseHandle
-WINHTTP.dll!WinHttpConnect
-WINHTTP.dll!WinHttpConnectionDeleteProxyInfo
-WINHTTP.dll!WinHttpConnectionFreeNameList
-WINHTTP.dll!WinHttpConnectionFreeProxyInfo
-WINHTTP.dll!WinHttpConnectionFreeProxyList
-WINHTTP.dll!WinHttpConnectionGetNameList
-WINHTTP.dll!WinHttpConnectionGetProxyInfo
-WINHTTP.dll!WinHttpConnectionGetProxyList
-WINHTTP.dll!WinHttpConnectionSetProxyInfo
-WINHTTP.dll!WinHttpCrackUrl
-WINHTTP.dll!WinHttpCreateProxyResolver
-WINHTTP.dll!WinHttpCreateUrl
-WINHTTP.dll!WinHttpDetectAutoProxyConfigUrl
-WINHTTP.dll!WinHttpFreeProxyResult
-WINHTTP.dll!WinHttpGetDefaultProxyConfiguration
-WINHTTP.dll!WinHttpGetIEProxyConfigForCurrentUser
-WINHTTP.dll!WinHttpGetProxyForUrl
-WINHTTP.dll!WinHttpGetProxyForUrlEx
-WINHTTP.dll!WinHttpGetProxyResult
-WINHTTP.dll!WinHttpGetTunnelSocket
-WINHTTP.dll!WinHttpOpen
-WINHTTP.dll!WinHttpOpenRequest
-WINHTTP.dll!WinHttpProbeConnectivity
-WINHTTP.dll!WinHttpQueryAuthSchemes
-WINHTTP.dll!WinHttpQueryDataAvailable
-WINHTTP.dll!WinHttpQueryHeaders
-WINHTTP.dll!WinHttpQueryOption
-WINHTTP.dll!WinHttpReadData
-WINHTTP.dll!WinHttpReceiveResponse
-WINHTTP.dll!WinHttpResetAutoProxy
-WINHTTP.dll!WinHttpSaveProxyCredentials
-WINHTTP.dll!WinHttpSendRequest
-WINHTTP.dll!WinHttpSetCredentials
-WINHTTP.dll!WinHttpSetDefaultProxyConfiguration
-WINHTTP.dll!WinHttpSetOption
-WINHTTP.dll!WinHttpSetStatusCallback
-WINHTTP.dll!WinHttpSetTimeouts
-WINHTTP.dll!WinHttpTimeFromSystemTime
-WINHTTP.dll!WinHttpTimeToSystemTime
-WINHTTP.dll!WinHttpWebSocketClose
-WINHTTP.dll!WinHttpWebSocketCompleteUpgrade
-WINHTTP.dll!WinHttpWebSocketQueryCloseStatus
-WINHTTP.dll!WinHttpWebSocketReceive
-WINHTTP.dll!WinHttpWebSocketSend
-WINHTTP.dll!WinHttpWebSocketShutdown
-WINHTTP.dll!WinHttpWriteData
-wkscli.dll!NetAddAlternateComputerName
-wkscli.dll!NetEnumerateComputerNames
-wkscli.dll!NetGetJoinableOUs
-wkscli.dll!NetGetJoinInformation
-wkscli.dll!NetJoinDomain
-wkscli.dll!NetRemoveAlternateComputerName
-wkscli.dll!NetRenameMachineInDomain
-wkscli.dll!NetSetPrimaryComputerName
-wkscli.dll!NetUnjoinDomain
-wkscli.dll!NetUseAdd
-wkscli.dll!NetUseDel
-wkscli.dll!NetUseEnum
-wkscli.dll!NetUseGetInfo
-wkscli.dll!NetValidateName
-wkscli.dll!NetWkstaGetInfo
-wkscli.dll!NetWkstaSetInfo
-wkscli.dll!NetWkstaStatisticsGet
-wkscli.dll!NetWkstaTransportAdd
-wkscli.dll!NetWkstaTransportDel
-wkscli.dll!NetWkstaTransportEnum
-wkscli.dll!NetWkstaUserEnum
-wkscli.dll!NetWkstaUserGetInfo
-wkscli.dll!NetWkstaUserSetInfo
-WLDAP32.dll!ber_alloc_t
-WLDAP32.dll!ber_bvdup
-WLDAP32.dll!ber_bvecfree
-WLDAP32.dll!ber_bvfree
-WLDAP32.dll!ber_first_element
-WLDAP32.dll!ber_flatten
-WLDAP32.dll!ber_free
-WLDAP32.dll!ber_init
-WLDAP32.dll!ber_next_element
-WLDAP32.dll!ber_peek_tag
-WLDAP32.dll!ber_printf
-WLDAP32.dll!ber_scanf
-WLDAP32.dll!ber_skip_tag
-WLDAP32.dll!cldap_open
-WLDAP32.dll!cldap_openA
-WLDAP32.dll!cldap_openW
-WLDAP32.dll!ldap_abandon
-WLDAP32.dll!ldap_add
-WLDAP32.dll!ldap_add_ext
-WLDAP32.dll!ldap_add_ext_s
-WLDAP32.dll!ldap_add_ext_sA
-WLDAP32.dll!ldap_add_ext_sW
-WLDAP32.dll!ldap_add_extA
-WLDAP32.dll!ldap_add_extW
-WLDAP32.dll!ldap_add_s
-WLDAP32.dll!ldap_add_sA
-WLDAP32.dll!ldap_add_sW
-WLDAP32.dll!ldap_addA
-WLDAP32.dll!ldap_addW
-WLDAP32.dll!ldap_bind
-WLDAP32.dll!ldap_bind_s
-WLDAP32.dll!ldap_bind_sA
-WLDAP32.dll!ldap_bind_sW
-WLDAP32.dll!ldap_bindA
-WLDAP32.dll!ldap_bindW
-WLDAP32.dll!ldap_check_filterA
-WLDAP32.dll!ldap_check_filterW
-WLDAP32.dll!ldap_cleanup
-WLDAP32.dll!ldap_close_extended_op
-WLDAP32.dll!ldap_compare
-WLDAP32.dll!ldap_compare_ext
-WLDAP32.dll!ldap_compare_ext_s
-WLDAP32.dll!ldap_compare_ext_sA
-WLDAP32.dll!ldap_compare_ext_sW
-WLDAP32.dll!ldap_compare_extA
-WLDAP32.dll!ldap_compare_extW
-WLDAP32.dll!ldap_compare_s
-WLDAP32.dll!ldap_compare_sA
-WLDAP32.dll!ldap_compare_sW
-WLDAP32.dll!ldap_compareA
-WLDAP32.dll!ldap_compareW
-WLDAP32.dll!ldap_conn_from_msg
-WLDAP32.dll!ldap_connect
-WLDAP32.dll!ldap_control_free
-WLDAP32.dll!ldap_control_freeA
-WLDAP32.dll!ldap_control_freeW
-WLDAP32.dll!ldap_controls_free
-WLDAP32.dll!ldap_controls_freeA
-WLDAP32.dll!ldap_controls_freeW
-WLDAP32.dll!ldap_count_entries
-WLDAP32.dll!ldap_count_references
-WLDAP32.dll!ldap_count_values
-WLDAP32.dll!ldap_count_values_len
-WLDAP32.dll!ldap_count_valuesA
-WLDAP32.dll!ldap_count_valuesW
-WLDAP32.dll!ldap_create_page_control
-WLDAP32.dll!ldap_create_page_controlA
-WLDAP32.dll!ldap_create_page_controlW
-WLDAP32.dll!ldap_create_sort_control
-WLDAP32.dll!ldap_create_sort_controlA
-WLDAP32.dll!ldap_create_sort_controlW
-WLDAP32.dll!ldap_create_vlv_controlA
-WLDAP32.dll!ldap_create_vlv_controlW
-WLDAP32.dll!ldap_delete
-WLDAP32.dll!ldap_delete_ext
-WLDAP32.dll!ldap_delete_ext_s
-WLDAP32.dll!ldap_delete_ext_sA
-WLDAP32.dll!ldap_delete_ext_sW
-WLDAP32.dll!ldap_delete_extA
-WLDAP32.dll!ldap_delete_extW
-WLDAP32.dll!ldap_delete_s
-WLDAP32.dll!ldap_delete_sA
-WLDAP32.dll!ldap_delete_sW
-WLDAP32.dll!ldap_deleteA
-WLDAP32.dll!ldap_deleteW
-WLDAP32.dll!ldap_dn2ufn
-WLDAP32.dll!ldap_dn2ufnA
-WLDAP32.dll!ldap_dn2ufnW
-WLDAP32.dll!ldap_encode_sort_controlA
-WLDAP32.dll!ldap_encode_sort_controlW
-WLDAP32.dll!ldap_err2string
-WLDAP32.dll!ldap_err2stringA
-WLDAP32.dll!ldap_err2stringW
-WLDAP32.dll!ldap_escape_filter_element
-WLDAP32.dll!ldap_escape_filter_elementA
-WLDAP32.dll!ldap_escape_filter_elementW
-WLDAP32.dll!ldap_explode_dn
-WLDAP32.dll!ldap_explode_dnA
-WLDAP32.dll!ldap_explode_dnW
-WLDAP32.dll!ldap_extended_operation
-WLDAP32.dll!ldap_extended_operation_sA
-WLDAP32.dll!ldap_extended_operation_sW
-WLDAP32.dll!ldap_extended_operationA
-WLDAP32.dll!ldap_extended_operationW
-WLDAP32.dll!ldap_first_attribute
-WLDAP32.dll!ldap_first_attributeA
-WLDAP32.dll!ldap_first_attributeW
-WLDAP32.dll!ldap_first_entry
-WLDAP32.dll!ldap_first_reference
-WLDAP32.dll!ldap_free_controls
-WLDAP32.dll!ldap_free_controlsA
-WLDAP32.dll!ldap_free_controlsW
-WLDAP32.dll!ldap_get_dn
-WLDAP32.dll!ldap_get_dnA
-WLDAP32.dll!ldap_get_dnW
-WLDAP32.dll!ldap_get_next_page
-WLDAP32.dll!ldap_get_next_page_s
-WLDAP32.dll!ldap_get_option
-WLDAP32.dll!ldap_get_optionA
-WLDAP32.dll!ldap_get_optionW
-WLDAP32.dll!ldap_get_paged_count
-WLDAP32.dll!ldap_get_values
-WLDAP32.dll!ldap_get_values_len
-WLDAP32.dll!ldap_get_values_lenA
-WLDAP32.dll!ldap_get_values_lenW
-WLDAP32.dll!ldap_get_valuesA
-WLDAP32.dll!ldap_get_valuesW
-WLDAP32.dll!ldap_init
-WLDAP32.dll!ldap_initA
-WLDAP32.dll!ldap_initW
-WLDAP32.dll!ldap_memfree
-WLDAP32.dll!ldap_memfreeA
-WLDAP32.dll!ldap_memfreeW
-WLDAP32.dll!ldap_modify
-WLDAP32.dll!ldap_modify_ext
-WLDAP32.dll!ldap_modify_ext_s
-WLDAP32.dll!ldap_modify_ext_sA
-WLDAP32.dll!ldap_modify_ext_sW
-WLDAP32.dll!ldap_modify_extA
-WLDAP32.dll!ldap_modify_extW
-WLDAP32.dll!ldap_modify_s
-WLDAP32.dll!ldap_modify_sA
-WLDAP32.dll!ldap_modify_sW
-WLDAP32.dll!ldap_modifyA
-WLDAP32.dll!ldap_modifyW
-WLDAP32.dll!ldap_modrdn
-WLDAP32.dll!ldap_modrdn_s
-WLDAP32.dll!ldap_modrdn_sA
-WLDAP32.dll!ldap_modrdn_sW
-WLDAP32.dll!ldap_modrdn2
-WLDAP32.dll!ldap_modrdn2_s
-WLDAP32.dll!ldap_modrdn2_sA
-WLDAP32.dll!ldap_modrdn2_sW
-WLDAP32.dll!ldap_modrdn2A
-WLDAP32.dll!ldap_modrdn2W
-WLDAP32.dll!ldap_modrdnA
-WLDAP32.dll!ldap_modrdnW
-WLDAP32.dll!ldap_msgfree
-WLDAP32.dll!ldap_next_attribute
-WLDAP32.dll!ldap_next_attributeA
-WLDAP32.dll!ldap_next_attributeW
-WLDAP32.dll!ldap_next_entry
-WLDAP32.dll!ldap_next_reference
-WLDAP32.dll!ldap_open
-WLDAP32.dll!ldap_openA
-WLDAP32.dll!ldap_openW
-WLDAP32.dll!ldap_parse_extended_resultA
-WLDAP32.dll!ldap_parse_extended_resultW
-WLDAP32.dll!ldap_parse_page_control
-WLDAP32.dll!ldap_parse_page_controlA
-WLDAP32.dll!ldap_parse_page_controlW
-WLDAP32.dll!ldap_parse_reference
-WLDAP32.dll!ldap_parse_referenceA
-WLDAP32.dll!ldap_parse_referenceW
-WLDAP32.dll!ldap_parse_result
-WLDAP32.dll!ldap_parse_resultA
-WLDAP32.dll!ldap_parse_resultW
-WLDAP32.dll!ldap_parse_sort_control
-WLDAP32.dll!ldap_parse_sort_controlA
-WLDAP32.dll!ldap_parse_sort_controlW
-WLDAP32.dll!ldap_parse_vlv_controlA
-WLDAP32.dll!ldap_parse_vlv_controlW
-WLDAP32.dll!ldap_perror
-WLDAP32.dll!ldap_rename_ext
-WLDAP32.dll!ldap_rename_ext_s
-WLDAP32.dll!ldap_rename_ext_sA
-WLDAP32.dll!ldap_rename_ext_sW
-WLDAP32.dll!ldap_rename_extA
-WLDAP32.dll!ldap_rename_extW
-WLDAP32.dll!ldap_result
-WLDAP32.dll!ldap_result2error
-WLDAP32.dll!ldap_sasl_bind_sA
-WLDAP32.dll!ldap_sasl_bind_sW
-WLDAP32.dll!ldap_sasl_bindA
-WLDAP32.dll!ldap_sasl_bindW
-WLDAP32.dll!ldap_search
-WLDAP32.dll!ldap_search_abandon_page
-WLDAP32.dll!ldap_search_ext
-WLDAP32.dll!ldap_search_ext_s
-WLDAP32.dll!ldap_search_ext_sA
-WLDAP32.dll!ldap_search_ext_sW
-WLDAP32.dll!ldap_search_extA
-WLDAP32.dll!ldap_search_extW
-WLDAP32.dll!ldap_search_init_page
-WLDAP32.dll!ldap_search_init_pageA
-WLDAP32.dll!ldap_search_init_pageW
-WLDAP32.dll!ldap_search_s
-WLDAP32.dll!ldap_search_sA
-WLDAP32.dll!ldap_search_st
-WLDAP32.dll!ldap_search_stA
-WLDAP32.dll!ldap_search_stW
-WLDAP32.dll!ldap_search_sW
-WLDAP32.dll!ldap_searchA
-WLDAP32.dll!ldap_searchW
-WLDAP32.dll!ldap_set_dbg_flags
-WLDAP32.dll!ldap_set_dbg_routine
-WLDAP32.dll!ldap_set_option
-WLDAP32.dll!ldap_set_optionA
-WLDAP32.dll!ldap_set_optionW
-WLDAP32.dll!ldap_simple_bind
-WLDAP32.dll!ldap_simple_bind_s
-WLDAP32.dll!ldap_simple_bind_sA
-WLDAP32.dll!ldap_simple_bind_sW
-WLDAP32.dll!ldap_simple_bindA
-WLDAP32.dll!ldap_simple_bindW
-WLDAP32.dll!ldap_sslinit
-WLDAP32.dll!ldap_sslinitA
-WLDAP32.dll!ldap_sslinitW
-WLDAP32.dll!ldap_start_tls_sA
-WLDAP32.dll!ldap_start_tls_sW
-WLDAP32.dll!ldap_startup
-WLDAP32.dll!ldap_stop_tls_s
-WLDAP32.dll!ldap_ufn2dn
-WLDAP32.dll!ldap_ufn2dnA
-WLDAP32.dll!ldap_ufn2dnW
-WLDAP32.dll!ldap_unbind
-WLDAP32.dll!ldap_unbind_s
-WLDAP32.dll!ldap_value_free
-WLDAP32.dll!ldap_value_free_len
-WLDAP32.dll!ldap_value_freeA
-WLDAP32.dll!ldap_value_freeW
-WLDAP32.dll!LdapGetLastError
-WLDAP32.dll!LdapMapErrorToWin32
-WLDAP32.dll!LdapUnicodeToUTF8
-WLDAP32.dll!LdapUTF8ToUnicode
-WS2_32.dll!__WSAFDIsSet
-WS2_32.dll!accept
-WS2_32.dll!bind
-WS2_32.dll!closesocket
-WS2_32.dll!connect
-WS2_32.dll!freeaddrinfo
-WS2_32.dll!FreeAddrInfoEx
-WS2_32.dll!FreeAddrInfoExW
-WS2_32.dll!FreeAddrInfoW
-WS2_32.dll!getaddrinfo
-WS2_32.dll!GetAddrInfoExA
-WS2_32.dll!GetAddrInfoExCancel
-WS2_32.dll!GetAddrInfoExOverlappedResult
-WS2_32.dll!GetAddrInfoExW
-WS2_32.dll!GetAddrInfoW
-WS2_32.dll!gethostbyaddr
-WS2_32.dll!gethostbyname
-WS2_32.dll!gethostname
-WS2_32.dll!GetHostNameW
-WS2_32.dll!getnameinfo
-WS2_32.dll!GetNameInfoW
-WS2_32.dll!getpeername
-WS2_32.dll!getprotobyname
-WS2_32.dll!getprotobynumber
-WS2_32.dll!getservbyname
-WS2_32.dll!getservbyport
-WS2_32.dll!getsockname
-WS2_32.dll!getsockopt
-WS2_32.dll!htonl
-WS2_32.dll!htons
-WS2_32.dll!inet_addr
-WS2_32.dll!inet_ntoa
-WS2_32.dll!inet_ntop
-WS2_32.dll!inet_pton
-WS2_32.dll!InetNtopW
-WS2_32.dll!InetPtonW
-WS2_32.dll!ioctlsocket
-WS2_32.dll!listen
-WS2_32.dll!ntohl
-WS2_32.dll!ntohs
-WS2_32.dll!recv
-WS2_32.dll!recvfrom
-WS2_32.dll!select
-WS2_32.dll!send
-WS2_32.dll!sendto
-WS2_32.dll!SetAddrInfoExA
-WS2_32.dll!SetAddrInfoExW
-WS2_32.dll!setsockopt
-WS2_32.dll!shutdown
-WS2_32.dll!socket
-WS2_32.dll!WahCloseApcHelper
-WS2_32.dll!WahCloseHandleHelper
-WS2_32.dll!WahCloseNotificationHandleHelper
-WS2_32.dll!WahCloseSocketHandle
-WS2_32.dll!WahCloseThread
-WS2_32.dll!WahCompleteRequest
-WS2_32.dll!WahCreateHandleContextTable
-WS2_32.dll!WahCreateNotificationHandle
-WS2_32.dll!WahCreateSocketHandle
-WS2_32.dll!WahDestroyHandleContextTable
-WS2_32.dll!WahDisableNonIFSHandleSupport
-WS2_32.dll!WahEnableNonIFSHandleSupport
-WS2_32.dll!WahEnumerateHandleContexts
-WS2_32.dll!WahInsertHandleContext
-WS2_32.dll!WahNotifyAllProcesses
-WS2_32.dll!WahOpenApcHelper
-WS2_32.dll!WahOpenCurrentThread
-WS2_32.dll!WahOpenHandleHelper
-WS2_32.dll!WahOpenNotificationHandleHelper
-WS2_32.dll!WahQueueUserApc
-WS2_32.dll!WahReferenceContextByHandle
-WS2_32.dll!WahRemoveHandleContext
-WS2_32.dll!WahWaitForNotification
-WS2_32.dll!WahWriteLSPEvent
-WS2_32.dll!WEP
-WS2_32.dll!WPUCompleteOverlappedRequest
-WS2_32.dll!WPUGetProviderPathEx
-WS2_32.dll!WSAAccept
-WS2_32.dll!WSAAddressToStringA
-WS2_32.dll!WSAAddressToStringW
-WS2_32.dll!WSAAdvertiseProvider
-WS2_32.dll!WSAAsyncGetHostByAddr
-WS2_32.dll!WSAAsyncGetHostByName
-WS2_32.dll!WSAAsyncGetProtoByName
-WS2_32.dll!WSAAsyncGetProtoByNumber
-WS2_32.dll!WSAAsyncGetServByName
-WS2_32.dll!WSAAsyncGetServByPort
-WS2_32.dll!WSAAsyncSelect
-WS2_32.dll!WSACancelAsyncRequest
-WS2_32.dll!WSACancelBlockingCall
-WS2_32.dll!WSACleanup
-WS2_32.dll!WSACloseEvent
-WS2_32.dll!WSAConnect
-WS2_32.dll!WSAConnectByList
-WS2_32.dll!WSAConnectByNameA
-WS2_32.dll!WSAConnectByNameW
-WS2_32.dll!WSACreateEvent
-WS2_32.dll!WSADuplicateSocketA
-WS2_32.dll!WSADuplicateSocketW
-WS2_32.dll!WSAEnumNameSpaceProvidersA
-WS2_32.dll!WSAEnumNameSpaceProvidersExA
-WS2_32.dll!WSAEnumNameSpaceProvidersExW
-WS2_32.dll!WSAEnumNameSpaceProvidersW
-WS2_32.dll!WSAEnumNetworkEvents
-WS2_32.dll!WSAEnumProtocolsA
-WS2_32.dll!WSAEnumProtocolsW
-WS2_32.dll!WSAEventSelect
-WS2_32.dll!WSAGetLastError
-WS2_32.dll!WSAGetOverlappedResult
-WS2_32.dll!WSAGetQOSByName
-WS2_32.dll!WSAGetServiceClassInfoA
-WS2_32.dll!WSAGetServiceClassInfoW
-WS2_32.dll!WSAGetServiceClassNameByClassIdA
-WS2_32.dll!WSAGetServiceClassNameByClassIdW
-WS2_32.dll!WSAHtonl
-WS2_32.dll!WSAHtons
-WS2_32.dll!WSAInstallServiceClassA
-WS2_32.dll!WSAInstallServiceClassW
-WS2_32.dll!WSAIoctl
-WS2_32.dll!WSAIsBlocking
-WS2_32.dll!WSAJoinLeaf
-WS2_32.dll!WSALookupServiceBeginA
-WS2_32.dll!WSALookupServiceBeginW
-WS2_32.dll!WSALookupServiceEnd
-WS2_32.dll!WSALookupServiceNextA
-WS2_32.dll!WSALookupServiceNextW
-WS2_32.dll!WSANSPIoctl
-WS2_32.dll!WSANtohl
-WS2_32.dll!WSANtohs
-WS2_32.dll!WSAPoll
-WS2_32.dll!WSAProviderCompleteAsyncCall
-WS2_32.dll!WSAProviderConfigChange
-WS2_32.dll!WSApSetPostRoutine
-WS2_32.dll!WSARecv
-WS2_32.dll!WSARecvDisconnect
-WS2_32.dll!WSARecvFrom
-WS2_32.dll!WSARemoveServiceClass
-WS2_32.dll!WSAResetEvent
-WS2_32.dll!WSASend
-WS2_32.dll!WSASendDisconnect
-WS2_32.dll!WSASendMsg
-WS2_32.dll!WSASendTo
-WS2_32.dll!WSASetBlockingHook
-WS2_32.dll!WSASetEvent
-WS2_32.dll!WSASetLastError
-WS2_32.dll!WSASetServiceA
-WS2_32.dll!WSASetServiceW
-WS2_32.dll!WSASocketA
-WS2_32.dll!WSASocketW
-WS2_32.dll!WSAStartup
-WS2_32.dll!WSAStringToAddressA
-WS2_32.dll!WSAStringToAddressW
-WS2_32.dll!WSAUnadvertiseProvider
-WS2_32.dll!WSAUnhookBlockingHook
-WS2_32.dll!WSAWaitForMultipleEvents
-WS2_32.dll!WSCDeinstallProvider
-WS2_32.dll!WSCDeinstallProviderEx
-WS2_32.dll!WSCEnableNSProvider
-WS2_32.dll!WSCEnumProtocols
-WS2_32.dll!WSCEnumProtocolsEx
-WS2_32.dll!WSCGetApplicationCategory
-WS2_32.dll!WSCGetApplicationCategoryEx
-WS2_32.dll!WSCGetProviderInfo
-WS2_32.dll!WSCGetProviderPath
-WS2_32.dll!WSCInstallNameSpace
-WS2_32.dll!WSCInstallNameSpaceEx
-WS2_32.dll!WSCInstallNameSpaceEx2
-WS2_32.dll!WSCInstallProvider
-WS2_32.dll!WSCInstallProviderAndChains
-WS2_32.dll!WSCInstallProviderEx
-WS2_32.dll!WSCSetApplicationCategory
-WS2_32.dll!WSCSetApplicationCategoryEx
-WS2_32.dll!WSCSetProviderInfo
-WS2_32.dll!WSCUnInstallNameSpace
-WS2_32.dll!WSCUnInstallNameSpaceEx2
-WS2_32.dll!WSCUpdateProvider
-WS2_32.dll!WSCUpdateProviderEx
-WS2_32.dll!WSCWriteNameSpaceOrder
-WS2_32.dll!WSCWriteProviderOrder
-WS2_32.dll!WSCWriteProviderOrderEx
-XmlLite.dll!CreateXmlReader
-XmlLite.dll!CreateXmlReaderInputWithEncodingCodePage
-XmlLite.dll!CreateXmlReaderInputWithEncodingName
-XmlLite.dll!CreateXmlWriter
-XmlLite.dll!CreateXmlWriterOutputWithEncodingCodePage
-XmlLite.dll!CreateXmlWriterOutputWithEncodingName
-advapi32.dll!AbortSystemShutdownW
-advapi32.dll!AccessCheck
-advapi32.dll!AccessCheckAndAuditAlarmW
-advapi32.dll!AccessCheckByType
-advapi32.dll!AccessCheckByTypeAndAuditAlarmW
-advapi32.dll!AccessCheckByTypeResultList
-advapi32.dll!AccessCheckByTypeResultListAndAuditAlarmByHandleW
-advapi32.dll!AccessCheckByTypeResultListAndAuditAlarmW
-advapi32.dll!AddAccessAllowedAce
-advapi32.dll!AddAccessAllowedAceEx
-advapi32.dll!AddAccessAllowedObjectAce
-advapi32.dll!AddAccessDeniedAce
-advapi32.dll!AddAccessDeniedAceEx
-advapi32.dll!AddAccessDeniedObjectAce
-advapi32.dll!AddAce
-advapi32.dll!AddAuditAccessAce
-advapi32.dll!AddAuditAccessAceEx
-advapi32.dll!AddAuditAccessObjectAce
-advapi32.dll!AddMandatoryAce
-advapi32.dll!AdjustTokenGroups
-advapi32.dll!AdjustTokenPrivileges
-advapi32.dll!AllocateAndInitializeSid
-advapi32.dll!AllocateLocallyUniqueId
-advapi32.dll!AreAllAccessesGranted
-advapi32.dll!AreAnyAccessesGranted
-advapi32.dll!AuditComputeEffectivePolicyBySid
-advapi32.dll!AuditEnumerateCategories
-advapi32.dll!AuditEnumeratePerUserPolicy
-advapi32.dll!AuditEnumerateSubCategories
-advapi32.dll!AuditFree
-advapi32.dll!AuditLookupCategoryNameW
-advapi32.dll!AuditLookupSubCategoryNameW
-advapi32.dll!AuditQueryGlobalSaclW
-advapi32.dll!AuditQueryPerUserPolicy
-advapi32.dll!AuditQuerySecurity
-advapi32.dll!AuditQuerySystemPolicy
-advapi32.dll!AuditSetGlobalSaclW
-advapi32.dll!AuditSetPerUserPolicy
-advapi32.dll!AuditSetSecurity
-advapi32.dll!AuditSetSystemPolicy
-advapi32.dll!BuildExplicitAccessWithNameW
-advapi32.dll!BuildImpersonateTrusteeW
-advapi32.dll!BuildSecurityDescriptorW
-advapi32.dll!BuildTrusteeWithNameW
-advapi32.dll!BuildTrusteeWithObjectsAndSidW
-advapi32.dll!BuildTrusteeWithSidW
-advapi32.dll!ChangeServiceConfig2A
-advapi32.dll!ChangeServiceConfig2W
-advapi32.dll!ChangeServiceConfigA
-advapi32.dll!ChangeServiceConfigW
-advapi32.dll!CheckTokenMembership
-advapi32.dll!CloseServiceHandle
-advapi32.dll!CloseTrace
-advapi32.dll!ControlService
-advapi32.dll!ControlServiceExA
-advapi32.dll!ControlServiceExW
-advapi32.dll!ControlTraceA
-advapi32.dll!ControlTraceW
-advapi32.dll!ConvertSecurityDescriptorToStringSecurityDescriptorW
-advapi32.dll!ConvertSidToStringSidA
-advapi32.dll!ConvertSidToStringSidW
-advapi32.dll!ConvertStringSecurityDescriptorToSecurityDescriptorW
-advapi32.dll!ConvertStringSidToSidA
-advapi32.dll!ConvertStringSidToSidW
-advapi32.dll!ConvertToAutoInheritPrivateObjectSecurity
-advapi32.dll!CopySid
-advapi32.dll!CreatePrivateObjectSecurity
-advapi32.dll!CreatePrivateObjectSecurityEx
-advapi32.dll!CreatePrivateObjectSecurityWithMultipleInheritance
-advapi32.dll!CreateProcessAsUserA
-advapi32.dll!CreateProcessAsUserW
-advapi32.dll!CreateProcessWithLogonW
-advapi32.dll!CreateProcessWithTokenW
-advapi32.dll!CreateRestrictedToken
-advapi32.dll!CreateServiceA
-advapi32.dll!CreateServiceW
-advapi32.dll!CreateWellKnownSid
-advapi32.dll!CredDeleteA
-advapi32.dll!CredDeleteW
-advapi32.dll!CredEnumerateA
-advapi32.dll!CredEnumerateW
-advapi32.dll!CredFindBestCredentialA
-advapi32.dll!CredFindBestCredentialW
-advapi32.dll!CredFree
-advapi32.dll!CredGetSessionTypes
-advapi32.dll!CredGetTargetInfoA
-advapi32.dll!CredGetTargetInfoW
-advapi32.dll!CredIsMarshaledCredentialW
-advapi32.dll!CredIsProtectedA
-advapi32.dll!CredIsProtectedW
-advapi32.dll!CredMarshalCredentialA
-advapi32.dll!CredMarshalCredentialW
-advapi32.dll!CredProtectA
-advapi32.dll!CredProtectW
-advapi32.dll!CredReadA
-advapi32.dll!CredReadDomainCredentialsA
-advapi32.dll!CredReadDomainCredentialsW
-advapi32.dll!CredReadW
-advapi32.dll!CredUnmarshalCredentialA
-advapi32.dll!CredUnmarshalCredentialW
-advapi32.dll!CredUnprotectA
-advapi32.dll!CredUnprotectW
-advapi32.dll!CredWriteA
-advapi32.dll!CredWriteDomainCredentialsA
-advapi32.dll!CredWriteDomainCredentialsW
-advapi32.dll!CredWriteW
-advapi32.dll!CryptAcquireContextA
-advapi32.dll!CryptAcquireContextW
-advapi32.dll!CryptContextAddRef
-advapi32.dll!CryptCreateHash
-advapi32.dll!CryptDecrypt
-advapi32.dll!CryptDeriveKey
-advapi32.dll!CryptDestroyHash
-advapi32.dll!CryptDestroyKey
-advapi32.dll!CryptDuplicateHash
-advapi32.dll!CryptDuplicateKey
-advapi32.dll!CryptEncrypt
-advapi32.dll!CryptEnumProvidersA
-advapi32.dll!CryptEnumProvidersW
-advapi32.dll!CryptEnumProviderTypesA
-advapi32.dll!CryptEnumProviderTypesW
-advapi32.dll!CryptExportKey
-advapi32.dll!CryptGenKey
-advapi32.dll!CryptGenRandom
-advapi32.dll!CryptGetDefaultProviderA
-advapi32.dll!CryptGetDefaultProviderW
-advapi32.dll!CryptGetHashParam
-advapi32.dll!CryptGetKeyParam
-advapi32.dll!CryptGetProvParam
-advapi32.dll!CryptGetUserKey
-advapi32.dll!CryptHashData
-advapi32.dll!CryptHashSessionKey
-advapi32.dll!CryptImportKey
-advapi32.dll!CryptReleaseContext
-advapi32.dll!CryptSetHashParam
-advapi32.dll!CryptSetKeyParam
-advapi32.dll!CryptSetProviderA
-advapi32.dll!CryptSetProviderExA
-advapi32.dll!CryptSetProviderExW
-advapi32.dll!CryptSetProviderW
-advapi32.dll!CryptSetProvParam
-advapi32.dll!CryptSignHashA
-advapi32.dll!CryptSignHashW
-advapi32.dll!CryptVerifySignatureA
-advapi32.dll!CryptVerifySignatureW
-advapi32.dll!DeleteAce
-advapi32.dll!DeleteService
-advapi32.dll!DeregisterEventSource
-advapi32.dll!DestroyPrivateObjectSecurity
-advapi32.dll!DuplicateToken
-advapi32.dll!DuplicateTokenEx
-advapi32.dll!ElfDeregisterEventSource
-advapi32.dll!ElfFlushEventLog
-advapi32.dll!ElfRegisterEventSourceW
-advapi32.dll!ElfReportEventW
-advapi32.dll!EnableTrace
-advapi32.dll!EnableTraceEx
-advapi32.dll!EnableTraceEx2
-advapi32.dll!EnumDependentServicesW
-advapi32.dll!EnumDynamicTimeZoneInformation
-advapi32.dll!EnumerateTraceGuids
-advapi32.dll!EnumerateTraceGuidsEx
-advapi32.dll!EnumServicesStatusExA
-advapi32.dll!EnumServicesStatusExW
-advapi32.dll!EqualDomainSid
-advapi32.dll!EqualPrefixSid
-advapi32.dll!EqualSid
-advapi32.dll!EventAccessControl
-advapi32.dll!EventAccessQuery
-advapi32.dll!EventAccessRemove
-advapi32.dll!EventActivityIdControl
-advapi32.dll!EventEnabled
-advapi32.dll!EventProviderEnabled
-advapi32.dll!EventRegister
-advapi32.dll!EventSetInformation
-advapi32.dll!EventUnregister
-advapi32.dll!EventWrite
-advapi32.dll!EventWriteEx
-advapi32.dll!EventWriteString
-advapi32.dll!EventWriteTransfer
-advapi32.dll!FindFirstFreeAce
-advapi32.dll!FlushTraceA
-advapi32.dll!FlushTraceW
-advapi32.dll!FreeSid
-advapi32.dll!GetAce
-advapi32.dll!GetAclInformation
-advapi32.dll!GetAuditedPermissionsFromAclW
-advapi32.dll!GetDynamicTimeZoneInformationEffectiveYears
-advapi32.dll!GetEffectiveRightsFromAclW
-advapi32.dll!GetEventLogInformation
-advapi32.dll!GetExplicitEntriesFromAclA
-advapi32.dll!GetExplicitEntriesFromAclW
-advapi32.dll!GetFileSecurityA
-advapi32.dll!GetFileSecurityW
-advapi32.dll!GetKernelObjectSecurity
-advapi32.dll!GetLengthSid
-advapi32.dll!GetNamedSecurityInfoA
-advapi32.dll!GetNamedSecurityInfoW
-advapi32.dll!GetPrivateObjectSecurity
-advapi32.dll!GetSecurityDescriptorControl
-advapi32.dll!GetSecurityDescriptorDacl
-advapi32.dll!GetSecurityDescriptorGroup
-advapi32.dll!GetSecurityDescriptorLength
-advapi32.dll!GetSecurityDescriptorOwner
-advapi32.dll!GetSecurityDescriptorRMControl
-advapi32.dll!GetSecurityDescriptorSacl
-advapi32.dll!GetSecurityInfo
-advapi32.dll!GetServiceDisplayNameA
-advapi32.dll!GetServiceDisplayNameW
-advapi32.dll!GetServiceKeyNameA
-advapi32.dll!GetServiceKeyNameW
-advapi32.dll!GetSidIdentifierAuthority
-advapi32.dll!GetSidLengthRequired
-advapi32.dll!GetSidSubAuthority
-advapi32.dll!GetSidSubAuthorityCount
-advapi32.dll!GetTokenInformation
-advapi32.dll!GetTraceEnableFlags
-advapi32.dll!GetTraceEnableLevel
-advapi32.dll!GetTraceLoggerHandle
-advapi32.dll!GetUserNameA
-advapi32.dll!GetUserNameW
-advapi32.dll!GetWindowsAccountDomainSid
-advapi32.dll!I_ScSetServiceBitsA
-advapi32.dll!I_ScSetServiceBitsW
-advapi32.dll!ImpersonateAnonymousToken
-advapi32.dll!ImpersonateLoggedOnUser
-advapi32.dll!ImpersonateNamedPipeClient
-advapi32.dll!ImpersonateSelf
-advapi32.dll!InitializeAcl
-advapi32.dll!InitializeSecurityDescriptor
-advapi32.dll!InitializeSid
-advapi32.dll!InitiateShutdownW
-advapi32.dll!InitiateSystemShutdownExW
-advapi32.dll!IsTextUnicode
-advapi32.dll!IsTokenRestricted
-advapi32.dll!IsValidAcl
-advapi32.dll!IsValidRelativeSecurityDescriptor
-advapi32.dll!IsValidSecurityDescriptor
-advapi32.dll!IsValidSid
-advapi32.dll!IsWellKnownSid
-advapi32.dll!LogonUserA
-advapi32.dll!LogonUserExA
-advapi32.dll!LogonUserExW
-advapi32.dll!LogonUserW
-advapi32.dll!LookupAccountNameA
-advapi32.dll!LookupAccountNameW
-advapi32.dll!LookupAccountSidA
-advapi32.dll!LookupAccountSidW
-advapi32.dll!LookupPrivilegeDisplayNameA
-advapi32.dll!LookupPrivilegeDisplayNameW
-advapi32.dll!LookupPrivilegeNameA
-advapi32.dll!LookupPrivilegeNameW
-advapi32.dll!LookupPrivilegeValueA
-advapi32.dll!LookupPrivilegeValueW
-advapi32.dll!LsaAddAccountRights
-advapi32.dll!LsaClose
-advapi32.dll!LsaCreateSecret
-advapi32.dll!LsaDelete
-advapi32.dll!LsaEnumerateAccountRights
-advapi32.dll!LsaEnumerateAccountsWithUserRight
-advapi32.dll!LsaEnumerateTrustedDomains
-advapi32.dll!LsaFreeMemory
-advapi32.dll!LsaICLookupNames
-advapi32.dll!LsaICLookupNamesWithCreds
-advapi32.dll!LsaICLookupSids
-advapi32.dll!LsaICLookupSidsWithCreds
-advapi32.dll!LsaLookupNames2
-advapi32.dll!LsaLookupSids
-advapi32.dll!LsaLookupSids2
-advapi32.dll!LsaManageSidNameMapping
-advapi32.dll!LsaOpenPolicy
-advapi32.dll!LsaOpenSecret
-advapi32.dll!LsaQueryInformationPolicy
-advapi32.dll!LsaQuerySecret
-advapi32.dll!LsaRemoveAccountRights
-advapi32.dll!LsaRetrievePrivateData
-advapi32.dll!LsaSetInformationPolicy
-advapi32.dll!LsaSetSecret
-advapi32.dll!LsaStorePrivateData
-advapi32.dll!MakeAbsoluteSD
-advapi32.dll!MakeAbsoluteSD2
-advapi32.dll!MakeSelfRelativeSD
-advapi32.dll!MapGenericMask
-advapi32.dll!NotifyBootConfigStatus
-advapi32.dll!NotifyServiceStatusChangeA
-advapi32.dll!NotifyServiceStatusChangeW
-advapi32.dll!ObjectCloseAuditAlarmW
-advapi32.dll!ObjectDeleteAuditAlarmW
-advapi32.dll!ObjectOpenAuditAlarmW
-advapi32.dll!ObjectPrivilegeAuditAlarmW
-advapi32.dll!OpenProcessToken
-advapi32.dll!OpenSCManagerA
-advapi32.dll!OpenSCManagerW
-advapi32.dll!OpenServiceA
-advapi32.dll!OpenServiceW
-advapi32.dll!OpenThreadToken
-advapi32.dll!OpenTraceA
-advapi32.dll!OpenTraceW
-advapi32.dll!PerfAddCounters
-advapi32.dll!PerfCloseQueryHandle
-advapi32.dll!PerfCreateInstance
-advapi32.dll!PerfDecrementULongCounterValue
-advapi32.dll!PerfDecrementULongLongCounterValue
-advapi32.dll!PerfDeleteCounters
-advapi32.dll!PerfDeleteInstance
-advapi32.dll!PerfEnumerateCounterSet
-advapi32.dll!PerfEnumerateCounterSetInstances
-advapi32.dll!PerfIncrementULongCounterValue
-advapi32.dll!PerfIncrementULongLongCounterValue
-advapi32.dll!PerfOpenQueryHandle
-advapi32.dll!PerfQueryCounterData
-advapi32.dll!PerfQueryCounterInfo
-advapi32.dll!PerfQueryCounterSetRegistrationInfo
-advapi32.dll!PerfQueryInstance
-advapi32.dll!PerfSetCounterRefValue
-advapi32.dll!PerfSetCounterSetInfo
-advapi32.dll!PerfSetULongCounterValue
-advapi32.dll!PerfSetULongLongCounterValue
-advapi32.dll!PerfStartProvider
-advapi32.dll!PerfStartProviderEx
-advapi32.dll!PerfStopProvider
-advapi32.dll!PrivilegeCheck
-advapi32.dll!PrivilegedServiceAuditAlarmW
-advapi32.dll!ProcessTrace
-advapi32.dll!QueryAllTracesA
-advapi32.dll!QueryAllTracesW
-advapi32.dll!QuerySecurityAccessMask
-advapi32.dll!QueryServiceConfig2A
-advapi32.dll!QueryServiceConfig2W
-advapi32.dll!QueryServiceConfigA
-advapi32.dll!QueryServiceConfigW
-advapi32.dll!QueryServiceDynamicInformation
-advapi32.dll!QueryServiceObjectSecurity
-advapi32.dll!QueryServiceStatus
-advapi32.dll!QueryServiceStatusEx
-advapi32.dll!QueryTraceA
-advapi32.dll!QueryTraceW
-advapi32.dll!RegCloseKey
-advapi32.dll!RegConnectRegistryA
-advapi32.dll!RegConnectRegistryExA
-advapi32.dll!RegConnectRegistryExW
-advapi32.dll!RegConnectRegistryW
-advapi32.dll!RegCopyTreeA
-advapi32.dll!RegCopyTreeW
-advapi32.dll!RegCreateKeyA
-advapi32.dll!RegCreateKeyExA
-advapi32.dll!RegCreateKeyExW
-advapi32.dll!RegCreateKeyTransactedA
-advapi32.dll!RegCreateKeyTransactedW
-advapi32.dll!RegCreateKeyW
-advapi32.dll!RegDeleteKeyA
-advapi32.dll!RegDeleteKeyExA
-advapi32.dll!RegDeleteKeyExW
-advapi32.dll!RegDeleteKeyTransactedA
-advapi32.dll!RegDeleteKeyTransactedW
-advapi32.dll!RegDeleteKeyValueA
-advapi32.dll!RegDeleteKeyValueW
-advapi32.dll!RegDeleteKeyW
-advapi32.dll!RegDeleteTreeA
-advapi32.dll!RegDeleteTreeW
-advapi32.dll!RegDeleteValueA
-advapi32.dll!RegDeleteValueW
-advapi32.dll!RegDisablePredefinedCache
-advapi32.dll!RegDisablePredefinedCacheEx
-advapi32.dll!RegEnumKeyA
-advapi32.dll!RegEnumKeyExA
-advapi32.dll!RegEnumKeyExW
-advapi32.dll!RegEnumKeyW
-advapi32.dll!RegEnumValueA
-advapi32.dll!RegEnumValueW
-advapi32.dll!RegFlushKey
-advapi32.dll!RegGetKeySecurity
-advapi32.dll!RegGetValueA
-advapi32.dll!RegGetValueW
-advapi32.dll!RegisterEventSourceA
-advapi32.dll!RegisterEventSourceW
-advapi32.dll!RegisterServiceCtrlHandlerA
-advapi32.dll!RegisterServiceCtrlHandlerExA
-advapi32.dll!RegisterServiceCtrlHandlerExW
-advapi32.dll!RegisterServiceCtrlHandlerW
-advapi32.dll!RegisterTraceGuidsA
-advapi32.dll!RegisterTraceGuidsW
-advapi32.dll!RegLoadAppKeyA
-advapi32.dll!RegLoadAppKeyW
-advapi32.dll!RegLoadKeyA
-advapi32.dll!RegLoadKeyW
-advapi32.dll!RegLoadMUIStringA
-advapi32.dll!RegLoadMUIStringW
-advapi32.dll!RegNotifyChangeKeyValue
-advapi32.dll!RegOpenCurrentUser
-advapi32.dll!RegOpenKeyA
-advapi32.dll!RegOpenKeyExA
-advapi32.dll!RegOpenKeyExW
-advapi32.dll!RegOpenKeyTransactedA
-advapi32.dll!RegOpenKeyTransactedW
-advapi32.dll!RegOpenKeyW
-advapi32.dll!RegOpenUserClassesRoot
-advapi32.dll!RegOverridePredefKey
-advapi32.dll!RegQueryInfoKeyA
-advapi32.dll!RegQueryInfoKeyW
-advapi32.dll!RegQueryMultipleValuesA
-advapi32.dll!RegQueryMultipleValuesW
-advapi32.dll!RegQueryValueA
-advapi32.dll!RegQueryValueExA
-advapi32.dll!RegQueryValueExW
-advapi32.dll!RegQueryValueW
-advapi32.dll!RegRenameKey
-advapi32.dll!RegReplaceKeyA
-advapi32.dll!RegReplaceKeyW
-advapi32.dll!RegRestoreKeyA
-advapi32.dll!RegRestoreKeyW
-advapi32.dll!RegSaveKeyA
-advapi32.dll!RegSaveKeyExA
-advapi32.dll!RegSaveKeyExW
-advapi32.dll!RegSaveKeyW
-advapi32.dll!RegSetKeySecurity
-advapi32.dll!RegSetKeyValueA
-advapi32.dll!RegSetKeyValueW
-advapi32.dll!RegSetValueA
-advapi32.dll!RegSetValueExA
-advapi32.dll!RegSetValueExW
-advapi32.dll!RegSetValueW
-advapi32.dll!RegUnLoadKeyA
-advapi32.dll!RegUnLoadKeyW
-advapi32.dll!RemoveTraceCallback
-advapi32.dll!ReportEventA
-advapi32.dll!ReportEventW
-advapi32.dll!RevertToSelf
-advapi32.dll!SetAclInformation
-advapi32.dll!SetEntriesInAclA
-advapi32.dll!SetEntriesInAclW
-advapi32.dll!SetFileSecurityA
-advapi32.dll!SetFileSecurityW
-advapi32.dll!SetKernelObjectSecurity
-advapi32.dll!SetNamedSecurityInfoA
-advapi32.dll!SetNamedSecurityInfoW
-advapi32.dll!SetPrivateObjectSecurity
-advapi32.dll!SetPrivateObjectSecurityEx
-advapi32.dll!SetSecurityAccessMask
-advapi32.dll!SetSecurityDescriptorControl
-advapi32.dll!SetSecurityDescriptorDacl
-advapi32.dll!SetSecurityDescriptorGroup
-advapi32.dll!SetSecurityDescriptorOwner
-advapi32.dll!SetSecurityDescriptorRMControl
-advapi32.dll!SetSecurityDescriptorSacl
-advapi32.dll!SetSecurityInfo
-advapi32.dll!SetServiceObjectSecurity
-advapi32.dll!SetServiceStatus
-advapi32.dll!SetThreadToken
-advapi32.dll!SetTokenInformation
-advapi32.dll!SetTraceCallback
-advapi32.dll!StartServiceA
-advapi32.dll!StartServiceCtrlDispatcherA
-advapi32.dll!StartServiceCtrlDispatcherW
-advapi32.dll!StartServiceW
-advapi32.dll!StartTraceA
-advapi32.dll!StartTraceW
-advapi32.dll!StopTraceA
-advapi32.dll!StopTraceW
-advapi32.dll!SystemFunction036
-advapi32.dll!SystemFunction040
-advapi32.dll!SystemFunction041
-advapi32.dll!TraceEvent
-advapi32.dll!TraceMessage
-advapi32.dll!TraceMessageVa
-advapi32.dll!TraceQueryInformation
-advapi32.dll!TraceSetInformation
-advapi32.dll!UnregisterTraceGuids
-advapi32.dll!UpdateTraceA
-advapi32.dll!UpdateTraceW
-advapi32.dll!WaitServiceState
-kernel32.dll!_lclose
-kernel32.dll!_lcreat
-kernel32.dll!_llseek
-kernel32.dll!_lopen
-kernel32.dll!_lread
-kernel32.dll!_lwrite
-kernel32.dll!AcquireSRWLockExclusive
-kernel32.dll!AcquireSRWLockShared
-kernel32.dll!ActivateActCtx
-kernel32.dll!AddAtomA
-kernel32.dll!AddAtomW
-kernel32.dll!AddDllDirectory
-kernel32.dll!AddLocalAlternateComputerNameA
-kernel32.dll!AddLocalAlternateComputerNameW
-kernel32.dll!AddRefActCtx
-kernel32.dll!AddResourceAttributeAce
-kernel32.dll!AddScopedPolicyIDAce
-kernel32.dll!AddSIDToBoundaryDescriptor
-kernel32.dll!AddVectoredContinueHandler
-kernel32.dll!AddVectoredExceptionHandler
-kernel32.dll!AllocateUserPhysicalPages
-kernel32.dll!AllocateUserPhysicalPagesNuma
-kernel32.dll!AllocConsole
-kernel32.dll!AreFileApisANSI
-kernel32.dll!AssignProcessToJobObject
-kernel32.dll!AttachConsole
-kernel32.dll!BackupRead
-kernel32.dll!BackupWrite
-kernel32.dll!BaseSetLastNTError
-kernel32.dll!Beep
-kernel32.dll!BindIoCompletionCallback
-kernel32.dll!CallbackMayRunLong
-kernel32.dll!CancelIo
-kernel32.dll!CancelIoEx
-kernel32.dll!CancelSynchronousIo
-kernel32.dll!CancelThreadpoolIo
-kernel32.dll!CancelWaitableTimer
-kernel32.dll!CeipIsOptedIn
-kernel32.dll!ChangeTimerQueueTimer
-kernel32.dll!CheckElevation
-kernel32.dll!CheckElevationEnabled
-kernel32.dll!CheckRemoteDebuggerPresent
-kernel32.dll!CheckTokenCapability
-kernel32.dll!CheckTokenMembershipEx
-kernel32.dll!ClearCommBreak
-kernel32.dll!ClearCommError
-kernel32.dll!CloseHandle
-kernel32.dll!ClosePrivateNamespace
-kernel32.dll!CloseThreadpool
-kernel32.dll!CloseThreadpoolCleanupGroup
-kernel32.dll!CloseThreadpoolCleanupGroupMembers
-kernel32.dll!CloseThreadpoolIo
-kernel32.dll!CloseThreadpoolTimer
-kernel32.dll!CloseThreadpoolWait
-kernel32.dll!CloseThreadpoolWork
-kernel32.dll!CompareFileTime
-kernel32.dll!CompareStringA
-kernel32.dll!CompareStringEx
-kernel32.dll!CompareStringOrdinal
-kernel32.dll!CompareStringW
-kernel32.dll!ConnectNamedPipe
-kernel32.dll!ContinueDebugEvent
-kernel32.dll!ConvertDefaultLocale
-kernel32.dll!ConvertFiberToThread
-kernel32.dll!ConvertThreadToFiber
-kernel32.dll!ConvertThreadToFiberEx
-kernel32.dll!CopyContext
-kernel32.dll!CopyFile2
-kernel32.dll!CopyFileA
-kernel32.dll!CopyFileExA
-kernel32.dll!CopyFileExW
-kernel32.dll!CopyFileW
-kernel32.dll!CreateActCtxA
-kernel32.dll!CreateActCtxW
-kernel32.dll!CreateBoundaryDescriptorA
-kernel32.dll!CreateBoundaryDescriptorW
-kernel32.dll!CreateConsoleScreenBuffer
-kernel32.dll!CreateDirectoryA
-kernel32.dll!CreateDirectoryExA
-kernel32.dll!CreateDirectoryExW
-kernel32.dll!CreateDirectoryW
-kernel32.dll!CreateEventA
-kernel32.dll!CreateEventExA
-kernel32.dll!CreateEventExW
-kernel32.dll!CreateEventW
-kernel32.dll!CreateFiber
-kernel32.dll!CreateFiberEx
-kernel32.dll!CreateFile2
-kernel32.dll!CreateFileA
-kernel32.dll!CreateFileMappingA
-kernel32.dll!CreateFileMappingFromApp
-kernel32.dll!CreateFileMappingNumaA
-kernel32.dll!CreateFileMappingNumaW
-kernel32.dll!CreateFileMappingW
-kernel32.dll!CreateFileTransactedA
-kernel32.dll!CreateFileTransactedW
-kernel32.dll!CreateFileW
-kernel32.dll!CreateHardLinkA
-kernel32.dll!CreateHardLinkW
-kernel32.dll!CreateIoCompletionPort
-kernel32.dll!CreateJobObjectA
-kernel32.dll!CreateJobObjectW
-kernel32.dll!CreateMailslotA
-kernel32.dll!CreateMailslotW
-kernel32.dll!CreateMemoryResourceNotification
-kernel32.dll!CreateMutexA
-kernel32.dll!CreateMutexExA
-kernel32.dll!CreateMutexExW
-kernel32.dll!CreateMutexW
-kernel32.dll!CreateNamedPipeA
-kernel32.dll!CreateNamedPipeW
-kernel32.dll!CreatePipe
-kernel32.dll!CreatePrivateNamespaceA
-kernel32.dll!CreatePrivateNamespaceW
-kernel32.dll!CreateProcessA
-kernel32.dll!CreateProcessW
-kernel32.dll!CreateRemoteThread
-kernel32.dll!CreateRemoteThreadEx
-kernel32.dll!CreateSemaphoreA
-kernel32.dll!CreateSemaphoreExA
-kernel32.dll!CreateSemaphoreExW
-kernel32.dll!CreateSemaphoreW
-kernel32.dll!CreateSymbolicLinkA
-kernel32.dll!CreateSymbolicLinkW
-kernel32.dll!CreateThread
-kernel32.dll!CreateThreadpool
-kernel32.dll!CreateThreadpoolCleanupGroup
-kernel32.dll!CreateThreadpoolIo
-kernel32.dll!CreateThreadpoolTimer
-kernel32.dll!CreateThreadpoolWait
-kernel32.dll!CreateThreadpoolWork
-kernel32.dll!CreateTimerQueue
-kernel32.dll!CreateTimerQueueTimer
-kernel32.dll!CreateToolhelp32Snapshot
-kernel32.dll!CreateWaitableTimerA
-kernel32.dll!CreateWaitableTimerExA
-kernel32.dll!CreateWaitableTimerExW
-kernel32.dll!CreateWaitableTimerW
-kernel32.dll!DeactivateActCtx
-kernel32.dll!DebugActiveProcess
-kernel32.dll!DebugActiveProcessStop
-kernel32.dll!DebugBreak
-kernel32.dll!DecodePointer
-kernel32.dll!DecodeSystemPointer
-kernel32.dll!DefineDosDeviceA
-kernel32.dll!DefineDosDeviceW
-kernel32.dll!DelayLoadFailureHook
-kernel32.dll!DeleteAtom
-kernel32.dll!DeleteBoundaryDescriptor
-kernel32.dll!DeleteCriticalSection
-kernel32.dll!DeleteFiber
-kernel32.dll!DeleteFileA
-kernel32.dll!DeleteFileW
-kernel32.dll!DeleteProcThreadAttributeList
-kernel32.dll!DeleteSynchronizationBarrier
-kernel32.dll!DeleteTimerQueueEx
-kernel32.dll!DeleteTimerQueueTimer
-kernel32.dll!DeleteVolumeMountPointA
-kernel32.dll!DeleteVolumeMountPointW
-kernel32.dll!DeviceIoControl
-kernel32.dll!DisableThreadLibraryCalls
-kernel32.dll!DisassociateCurrentThreadFromCallback
-kernel32.dll!DiscardVirtualMemory
-kernel32.dll!DisconnectNamedPipe
-kernel32.dll!DnsHostnameToComputerNameExW
-kernel32.dll!DnsHostnameToComputerNameW
-kernel32.dll!DosDateTimeToFileTime
-kernel32.dll!DosPathToSessionPathW
-kernel32.dll!DuplicateHandle
-kernel32.dll!EncodePointer
-kernel32.dll!EncodeSystemPointer
-kernel32.dll!EnterCriticalSection
-kernel32.dll!EnterSynchronizationBarrier
-kernel32.dll!EnumCalendarInfoA
-kernel32.dll!EnumCalendarInfoExA
-kernel32.dll!EnumCalendarInfoExEx
-kernel32.dll!EnumCalendarInfoExW
-kernel32.dll!EnumCalendarInfoW
-kernel32.dll!EnumDateFormatsA
-kernel32.dll!EnumDateFormatsExA
-kernel32.dll!EnumDateFormatsExEx
-kernel32.dll!EnumDateFormatsExW
-kernel32.dll!EnumDateFormatsW
-kernel32.dll!EnumerateLocalComputerNamesW
-kernel32.dll!EnumLanguageGroupLocalesA
-kernel32.dll!EnumLanguageGroupLocalesW
-kernel32.dll!EnumResourceLanguagesExA
-kernel32.dll!EnumResourceLanguagesExW
-kernel32.dll!EnumResourceNamesExA
-kernel32.dll!EnumResourceNamesExW
-kernel32.dll!EnumResourceTypesExA
-kernel32.dll!EnumResourceTypesExW
-kernel32.dll!EnumSystemCodePagesA
-kernel32.dll!EnumSystemCodePagesW
-kernel32.dll!EnumSystemFirmwareTables
-kernel32.dll!EnumSystemGeoID
-kernel32.dll!EnumSystemLanguageGroupsA
-kernel32.dll!EnumSystemLanguageGroupsW
-kernel32.dll!EnumSystemLocalesA
-kernel32.dll!EnumSystemLocalesEx
-kernel32.dll!EnumSystemLocalesW
-kernel32.dll!EnumTimeFormatsA
-kernel32.dll!EnumTimeFormatsEx
-kernel32.dll!EnumTimeFormatsW
-kernel32.dll!EnumUILanguagesA
-kernel32.dll!EnumUILanguagesW
-kernel32.dll!EscapeCommFunction
-kernel32.dll!ExitProcess
-kernel32.dll!ExitThread
-kernel32.dll!ExpandEnvironmentStringsA
-kernel32.dll!ExpandEnvironmentStringsW
-kernel32.dll!FatalAppExitA
-kernel32.dll!FatalAppExitW
-kernel32.dll!FileTimeToDosDateTime
-kernel32.dll!FileTimeToLocalFileTime
-kernel32.dll!FileTimeToSystemTime
-kernel32.dll!FillConsoleOutputAttribute
-kernel32.dll!FillConsoleOutputCharacterA
-kernel32.dll!FillConsoleOutputCharacterW
-kernel32.dll!FindActCtxSectionGuid
-kernel32.dll!FindActCtxSectionStringA
-kernel32.dll!FindActCtxSectionStringW
-kernel32.dll!FindAtomA
-kernel32.dll!FindAtomW
-kernel32.dll!FindClose
-kernel32.dll!FindCloseChangeNotification
-kernel32.dll!FindFirstChangeNotificationA
-kernel32.dll!FindFirstChangeNotificationW
-kernel32.dll!FindFirstFileA
-kernel32.dll!FindFirstFileExA
-kernel32.dll!FindFirstFileExW
-kernel32.dll!FindFirstFileNameW
-kernel32.dll!FindFirstFileW
-kernel32.dll!FindFirstStreamW
-kernel32.dll!FindFirstVolumeA
-kernel32.dll!FindFirstVolumeMountPointA
-kernel32.dll!FindFirstVolumeMountPointW
-kernel32.dll!FindFirstVolumeW
-kernel32.dll!FindNextChangeNotification
-kernel32.dll!FindNextFileA
-kernel32.dll!FindNextFileNameW
-kernel32.dll!FindNextFileW
-kernel32.dll!FindNextStreamW
-kernel32.dll!FindNextVolumeA
-kernel32.dll!FindNextVolumeMountPointA
-kernel32.dll!FindNextVolumeMountPointW
-kernel32.dll!FindNextVolumeW
-kernel32.dll!FindNLSString
-kernel32.dll!FindNLSStringEx
-kernel32.dll!FindResourceA
-kernel32.dll!FindResourceExA
-kernel32.dll!FindResourceExW
-kernel32.dll!FindResourceW
-kernel32.dll!FindStringOrdinal
-kernel32.dll!FindVolumeClose
-kernel32.dll!FindVolumeMountPointClose
-kernel32.dll!FlsAlloc
-kernel32.dll!FlsFree
-kernel32.dll!FlsGetValue
-kernel32.dll!FlsSetValue
-kernel32.dll!FlushConsoleInputBuffer
-kernel32.dll!FlushFileBuffers
-kernel32.dll!FlushInstructionCache
-kernel32.dll!FlushProcessWriteBuffers
-kernel32.dll!FlushViewOfFile
-kernel32.dll!FoldStringA
-kernel32.dll!FoldStringW
-kernel32.dll!FormatMessageA
-kernel32.dll!FormatMessageW
-kernel32.dll!FreeConsole
-kernel32.dll!FreeEnvironmentStringsA
-kernel32.dll!FreeEnvironmentStringsW
-kernel32.dll!FreeLibrary
-kernel32.dll!FreeLibraryAndExitThread
-kernel32.dll!FreeLibraryWhenCallbackReturns
-kernel32.dll!FreeResource
-kernel32.dll!FreeUserPhysicalPages
-kernel32.dll!GenerateConsoleCtrlEvent
-kernel32.dll!GetACP
-kernel32.dll!GetActiveProcessorCount
-kernel32.dll!GetAppContainerAce
-kernel32.dll!GetAppContainerNamedObjectPath
-kernel32.dll!GetApplicationRecoveryCallback
-kernel32.dll!GetApplicationRestartSettings
-kernel32.dll!GetAtomNameA
-kernel32.dll!GetAtomNameW
-kernel32.dll!GetBinaryTypeA
-kernel32.dll!GetBinaryTypeW
-kernel32.dll!GetCachedSigningLevel
-kernel32.dll!GetCalendarInfoA
-kernel32.dll!GetCalendarInfoEx
-kernel32.dll!GetCalendarInfoW
-kernel32.dll!GetCommandLineA
-kernel32.dll!GetCommandLineW
-kernel32.dll!GetCommConfig
-kernel32.dll!GetCommMask
-kernel32.dll!GetCommModemStatus
-kernel32.dll!GetCommProperties
-kernel32.dll!GetCommState
-kernel32.dll!GetCommTimeouts
-kernel32.dll!GetCompressedFileSizeA
-kernel32.dll!GetCompressedFileSizeW
-kernel32.dll!GetComputerNameA
-kernel32.dll!GetComputerNameExA
-kernel32.dll!GetComputerNameExW
-kernel32.dll!GetComputerNameW
-kernel32.dll!GetConsoleCP
-kernel32.dll!GetConsoleCursorInfo
-kernel32.dll!GetConsoleMode
-kernel32.dll!GetConsoleOutputCP
-kernel32.dll!GetConsoleScreenBufferInfo
-kernel32.dll!GetConsoleScreenBufferInfoEx
-kernel32.dll!GetConsoleTitleA
-kernel32.dll!GetConsoleTitleW
-kernel32.dll!GetConsoleWindow
-kernel32.dll!GetCPInfo
-kernel32.dll!GetCPInfoExA
-kernel32.dll!GetCPInfoExW
-kernel32.dll!GetCurrencyFormatA
-kernel32.dll!GetCurrencyFormatEx
-kernel32.dll!GetCurrencyFormatW
-kernel32.dll!GetCurrentActCtx
-kernel32.dll!GetCurrentDirectoryA
-kernel32.dll!GetCurrentDirectoryW
-kernel32.dll!GetCurrentProcess
-kernel32.dll!GetCurrentProcessId
-kernel32.dll!GetCurrentProcessorNumber
-kernel32.dll!GetCurrentProcessorNumberEx
-kernel32.dll!GetCurrentThread
-kernel32.dll!GetCurrentThreadId
-kernel32.dll!GetCurrentThreadStackLimits
-kernel32.dll!GetDateFormatA
-kernel32.dll!GetDateFormatEx
-kernel32.dll!GetDateFormatW
-kernel32.dll!GetDiskFreeSpaceA
-kernel32.dll!GetDiskFreeSpaceExA
-kernel32.dll!GetDiskFreeSpaceExW
-kernel32.dll!GetDiskFreeSpaceW
-kernel32.dll!GetDriveTypeA
-kernel32.dll!GetDriveTypeW
-kernel32.dll!GetDurationFormatEx
-kernel32.dll!GetDynamicTimeZoneInformation
-kernel32.dll!GetEnabledXStateFeatures
-kernel32.dll!GetEnvironmentStrings
-kernel32.dll!GetEnvironmentStringsW
-kernel32.dll!GetEnvironmentVariableA
-kernel32.dll!GetEnvironmentVariableW
-kernel32.dll!GetErrorMode
-kernel32.dll!GetExitCodeProcess
-kernel32.dll!GetExitCodeThread
-kernel32.dll!GetFileAttributesA
-kernel32.dll!GetFileAttributesExA
-kernel32.dll!GetFileAttributesExW
-kernel32.dll!GetFileAttributesTransactedA
-kernel32.dll!GetFileAttributesTransactedW
-kernel32.dll!GetFileAttributesW
-kernel32.dll!GetFileInformationByHandle
-kernel32.dll!GetFileInformationByHandleEx
-kernel32.dll!GetFileMUIInfo
-kernel32.dll!GetFileMUIPath
-kernel32.dll!GetFileSize
-kernel32.dll!GetFileSizeEx
-kernel32.dll!GetFileTime
-kernel32.dll!GetFileType
-kernel32.dll!GetFinalPathNameByHandleA
-kernel32.dll!GetFinalPathNameByHandleW
-kernel32.dll!GetFirmwareEnvironmentVariableExW
-kernel32.dll!GetFirmwareEnvironmentVariableW
-kernel32.dll!GetFirmwareType
-kernel32.dll!GetFullPathNameA
-kernel32.dll!GetFullPathNameW
-kernel32.dll!GetGeoInfoA
-kernel32.dll!GetGeoInfoW
-kernel32.dll!GetHandleInformation
-kernel32.dll!GetLargePageMinimum
-kernel32.dll!GetLargestConsoleWindowSize
-kernel32.dll!GetLastError
-kernel32.dll!GetLocaleInfoA
-kernel32.dll!GetLocaleInfoEx
-kernel32.dll!GetLocaleInfoW
-kernel32.dll!GetLocalTime
-kernel32.dll!GetLogicalDrives
-kernel32.dll!GetLogicalDriveStringsA
-kernel32.dll!GetLogicalDriveStringsW
-kernel32.dll!GetLogicalProcessorInformation
-kernel32.dll!GetLogicalProcessorInformationEx
-kernel32.dll!GetLongPathNameA
-kernel32.dll!GetLongPathNameW
-kernel32.dll!GetMaximumProcessorGroupCount
-kernel32.dll!GetMemoryErrorHandlingCapabilities
-kernel32.dll!GetModuleFileNameA
-kernel32.dll!GetModuleFileNameW
-kernel32.dll!GetModuleHandleA
-kernel32.dll!GetModuleHandleExA
-kernel32.dll!GetModuleHandleExW
-kernel32.dll!GetModuleHandleW
-kernel32.dll!GetNamedPipeClientComputerNameA
-kernel32.dll!GetNamedPipeClientComputerNameW
-kernel32.dll!GetNamedPipeClientProcessId
-kernel32.dll!GetNamedPipeHandleStateA
-kernel32.dll!GetNamedPipeHandleStateW
-kernel32.dll!GetNamedPipeInfo
-kernel32.dll!GetNamedPipeServerProcessId
-kernel32.dll!GetNativeSystemInfo
-kernel32.dll!GetNLSVersion
-kernel32.dll!GetNLSVersionEx
-kernel32.dll!GetNumaAvailableMemoryNodeEx
-kernel32.dll!GetNumaHighestNodeNumber
-kernel32.dll!GetNumaNodeProcessorMask
-kernel32.dll!GetNumaNodeProcessorMaskEx
-kernel32.dll!GetNumaProcessorNodeEx
-kernel32.dll!GetNumberFormatA
-kernel32.dll!GetNumberFormatEx
-kernel32.dll!GetNumberFormatW
-kernel32.dll!GetNumberOfConsoleInputEvents
-kernel32.dll!GetOEMCP
-kernel32.dll!GetOverlappedResult
-kernel32.dll!GetOverlappedResultEx
-kernel32.dll!GetPhysicallyInstalledSystemMemory
-kernel32.dll!GetPriorityClass
-kernel32.dll!GetPrivateProfileIntA
-kernel32.dll!GetPrivateProfileIntW
-kernel32.dll!GetPrivateProfileSectionA
-kernel32.dll!GetPrivateProfileSectionW
-kernel32.dll!GetPrivateProfileStringA
-kernel32.dll!GetPrivateProfileStringW
-kernel32.dll!GetProcAddress
-kernel32.dll!GetProcessAffinityMask
-kernel32.dll!GetProcessGroupAffinity
-kernel32.dll!GetProcessHandleCount
-kernel32.dll!GetProcessHeap
-kernel32.dll!GetProcessHeaps
-kernel32.dll!GetProcessId
-kernel32.dll!GetProcessIdOfThread
-kernel32.dll!GetProcessInformation
-kernel32.dll!GetProcessIoCounters
-kernel32.dll!GetProcessMitigationPolicy
-kernel32.dll!GetProcessorSystemCycleTime
-kernel32.dll!GetProcessPreferredUILanguages
-kernel32.dll!GetProcessPriorityBoost
-kernel32.dll!GetProcessShutdownParameters
-kernel32.dll!GetProcessTimes
-kernel32.dll!GetProcessVersion
-kernel32.dll!GetProcessWorkingSetSizeEx
-kernel32.dll!GetProductInfo
-kernel32.dll!GetProfileIntA
-kernel32.dll!GetProfileIntW
-kernel32.dll!GetProfileSectionA
-kernel32.dll!GetProfileSectionW
-kernel32.dll!GetProfileStringA
-kernel32.dll!GetProfileStringW
-kernel32.dll!GetQueuedCompletionStatus
-kernel32.dll!GetQueuedCompletionStatusEx
-kernel32.dll!GetShortPathNameA
-kernel32.dll!GetShortPathNameW
-kernel32.dll!GetStartupInfoA
-kernel32.dll!GetStartupInfoW
-kernel32.dll!GetStdHandle
-kernel32.dll!GetStringScripts
-kernel32.dll!GetStringTypeA
-kernel32.dll!GetStringTypeExA
-kernel32.dll!GetStringTypeExW
-kernel32.dll!GetStringTypeW
-kernel32.dll!GetSystemDefaultLangID
-kernel32.dll!GetSystemDefaultLCID
-kernel32.dll!GetSystemDefaultLocaleName
-kernel32.dll!GetSystemDefaultUILanguage
-kernel32.dll!GetSystemDirectoryA
-kernel32.dll!GetSystemDirectoryW
-kernel32.dll!GetSystemFileCacheSize
-kernel32.dll!GetSystemFirmwareTable
-kernel32.dll!GetSystemInfo
-kernel32.dll!GetSystemPowerStatus
-kernel32.dll!GetSystemPreferredUILanguages
-kernel32.dll!GetSystemTime
-kernel32.dll!GetSystemTimeAdjustment
-kernel32.dll!GetSystemTimeAsFileTime
-kernel32.dll!GetSystemTimePreciseAsFileTime
-kernel32.dll!GetSystemTimes
-kernel32.dll!GetSystemWindowsDirectoryA
-kernel32.dll!GetSystemWindowsDirectoryW
-kernel32.dll!GetSystemWow64DirectoryA
-kernel32.dll!GetSystemWow64DirectoryW
-kernel32.dll!GetTapeParameters
-kernel32.dll!GetTempFileNameA
-kernel32.dll!GetTempFileNameW
-kernel32.dll!GetTempPathA
-kernel32.dll!GetTempPathW
-kernel32.dll!GetThreadContext
-kernel32.dll!GetThreadErrorMode
-kernel32.dll!GetThreadGroupAffinity
-kernel32.dll!GetThreadId
-kernel32.dll!GetThreadIdealProcessorEx
-kernel32.dll!GetThreadInformation
-kernel32.dll!GetThreadIOPendingFlag
-kernel32.dll!GetThreadLocale
-kernel32.dll!GetThreadPreferredUILanguages
-kernel32.dll!GetThreadPriority
-kernel32.dll!GetThreadPriorityBoost
-kernel32.dll!GetThreadSelectorEntry
-kernel32.dll!GetThreadTimes
-kernel32.dll!GetThreadUILanguage
-kernel32.dll!GetTickCount
-kernel32.dll!GetTickCount64
-kernel32.dll!GetTimeFormatA
-kernel32.dll!GetTimeFormatEx
-kernel32.dll!GetTimeFormatW
-kernel32.dll!GetTimeZoneInformation
-kernel32.dll!GetTimeZoneInformationForYear
-kernel32.dll!GetUILanguageInfo
-kernel32.dll!GetUserDefaultLangID
-kernel32.dll!GetUserDefaultLCID
-kernel32.dll!GetUserDefaultLocaleName
-kernel32.dll!GetUserDefaultUILanguage
-kernel32.dll!GetUserGeoID
-kernel32.dll!GetUserPreferredUILanguages
-kernel32.dll!GetVersion
-kernel32.dll!GetVersionExA
-kernel32.dll!GetVersionExW
-kernel32.dll!GetVolumeInformationA
-kernel32.dll!GetVolumeInformationByHandleW
-kernel32.dll!GetVolumeInformationW
-kernel32.dll!GetVolumeNameForVolumeMountPointA
-kernel32.dll!GetVolumeNameForVolumeMountPointW
-kernel32.dll!GetVolumePathNameA
-kernel32.dll!GetVolumePathNamesForVolumeNameA
-kernel32.dll!GetVolumePathNamesForVolumeNameW
-kernel32.dll!GetVolumePathNameW
-kernel32.dll!GetWindowsDirectoryA
-kernel32.dll!GetWindowsDirectoryW
-kernel32.dll!GetWriteWatch
-kernel32.dll!GetXStateFeaturesMask
-kernel32.dll!GlobalAddAtomA
-kernel32.dll!GlobalAddAtomExA
-kernel32.dll!GlobalAddAtomExW
-kernel32.dll!GlobalAddAtomW
-kernel32.dll!GlobalAlloc
-kernel32.dll!GlobalDeleteAtom
-kernel32.dll!GlobalFindAtomA
-kernel32.dll!GlobalFindAtomW
-kernel32.dll!GlobalFlags
-kernel32.dll!GlobalFree
-kernel32.dll!GlobalGetAtomNameA
-kernel32.dll!GlobalGetAtomNameW
-kernel32.dll!GlobalHandle
-kernel32.dll!GlobalLock
-kernel32.dll!GlobalMemoryStatus
-kernel32.dll!GlobalMemoryStatusEx
-kernel32.dll!GlobalReAlloc
-kernel32.dll!GlobalSize
-kernel32.dll!GlobalUnlock
-kernel32.dll!HeapAlloc
-kernel32.dll!HeapCompact
-kernel32.dll!HeapCreate
-kernel32.dll!HeapDestroy
-kernel32.dll!HeapFree
-kernel32.dll!HeapLock
-kernel32.dll!HeapQueryInformation
-kernel32.dll!HeapReAlloc
-kernel32.dll!HeapSetInformation
-kernel32.dll!HeapSize
-kernel32.dll!HeapUnlock
-kernel32.dll!HeapValidate
-kernel32.dll!HeapWalk
-kernel32.dll!InitAtomTable
-kernel32.dll!InitializeConditionVariable
-kernel32.dll!InitializeContext
-kernel32.dll!InitializeCriticalSection
-kernel32.dll!InitializeCriticalSectionAndSpinCount
-kernel32.dll!InitializeCriticalSectionEx
-kernel32.dll!InitializeProcThreadAttributeList
-kernel32.dll!InitializeSListHead
-kernel32.dll!InitializeSRWLock
-kernel32.dll!InitializeSynchronizationBarrier
-kernel32.dll!InitOnceBeginInitialize
-kernel32.dll!InitOnceComplete
-kernel32.dll!InitOnceExecuteOnce
-kernel32.dll!InitOnceInitialize
-kernel32.dll!InstallELAMCertificateInfo
-kernel32.dll!InterlockedFlushSList
-kernel32.dll!InterlockedPopEntrySList
-kernel32.dll!InterlockedPushEntrySList
-kernel32.dll!InterlockedPushListSListEx
-kernel32.dll!IsDBCSLeadByte
-kernel32.dll!IsDBCSLeadByteEx
-kernel32.dll!IsDebuggerPresent
-kernel32.dll!IsNLSDefinedString
-kernel32.dll!IsNormalizedString
-kernel32.dll!IsProcessCritical
-kernel32.dll!IsProcessInJob
-kernel32.dll!IsProcessorFeaturePresent
-kernel32.dll!IsThreadAFiber
-kernel32.dll!IsThreadpoolTimerSet
-kernel32.dll!IsValidCodePage
-kernel32.dll!IsValidLanguageGroup
-kernel32.dll!IsValidLocale
-kernel32.dll!IsValidLocaleName
-kernel32.dll!IsValidNLSVersion
-kernel32.dll!IsWow64Process
-kernel32.dll!K32EmptyWorkingSet
-kernel32.dll!K32EnumDeviceDrivers
-kernel32.dll!K32EnumPageFilesA
-kernel32.dll!K32EnumPageFilesW
-kernel32.dll!K32EnumProcesses
-kernel32.dll!K32EnumProcessModules
-kernel32.dll!K32EnumProcessModulesEx
-kernel32.dll!K32GetDeviceDriverBaseNameA
-kernel32.dll!K32GetDeviceDriverBaseNameW
-kernel32.dll!K32GetDeviceDriverFileNameA
-kernel32.dll!K32GetDeviceDriverFileNameW
-kernel32.dll!K32GetMappedFileNameA
-kernel32.dll!K32GetMappedFileNameW
-kernel32.dll!K32GetModuleBaseNameA
-kernel32.dll!K32GetModuleBaseNameW
-kernel32.dll!K32GetModuleFileNameExA
-kernel32.dll!K32GetModuleFileNameExW
-kernel32.dll!K32GetModuleInformation
-kernel32.dll!K32GetPerformanceInfo
-kernel32.dll!K32GetProcessImageFileNameA
-kernel32.dll!K32GetProcessImageFileNameW
-kernel32.dll!K32GetProcessMemoryInfo
-kernel32.dll!K32GetWsChanges
-kernel32.dll!K32GetWsChangesEx
-kernel32.dll!K32InitializeProcessForWsWatch
-kernel32.dll!K32QueryWorkingSet
-kernel32.dll!K32QueryWorkingSetEx
-kernel32.dll!LCIDToLocaleName
-kernel32.dll!LCMapStringA
-kernel32.dll!LCMapStringEx
-kernel32.dll!LCMapStringW
-kernel32.dll!LeaveCriticalSection
-kernel32.dll!LeaveCriticalSectionWhenCallbackReturns
-kernel32.dll!LoadAppInitDlls
-kernel32.dll!LoadLibraryA
-kernel32.dll!LoadLibraryExA
-kernel32.dll!LoadLibraryExW
-kernel32.dll!LoadLibraryW
-kernel32.dll!LoadPackagedLibrary
-kernel32.dll!LoadResource
-kernel32.dll!LocalAlloc
-kernel32.dll!LocaleNameToLCID
-kernel32.dll!LocalFileTimeToFileTime
-kernel32.dll!LocalFlags
-kernel32.dll!LocalFree
-kernel32.dll!LocalLock
-kernel32.dll!LocalReAlloc
-kernel32.dll!LocalSize
-kernel32.dll!LocalUnlock
-kernel32.dll!LocateXStateFeature
-kernel32.dll!LockFile
-kernel32.dll!LockFileEx
-kernel32.dll!LockResource
-kernel32.dll!lstrcatA
-kernel32.dll!lstrcatW
-kernel32.dll!lstrcmpA
-kernel32.dll!lstrcmpiA
-kernel32.dll!lstrcmpiW
-kernel32.dll!lstrcmpW
-kernel32.dll!lstrcpyA
-kernel32.dll!lstrcpynA
-kernel32.dll!lstrcpynW
-kernel32.dll!lstrcpyW
-kernel32.dll!lstrlenA
-kernel32.dll!lstrlenW
-kernel32.dll!MapUserPhysicalPages
-kernel32.dll!MapViewOfFile
-kernel32.dll!MapViewOfFileEx
-kernel32.dll!MapViewOfFileFromApp
-kernel32.dll!Module32First
-kernel32.dll!Module32FirstW
-kernel32.dll!Module32Next
-kernel32.dll!Module32NextW
-kernel32.dll!MoveFileA
-kernel32.dll!MoveFileExA
-kernel32.dll!MoveFileExW
-kernel32.dll!MoveFileW
-kernel32.dll!MoveFileWithProgressA
-kernel32.dll!MoveFileWithProgressW
-kernel32.dll!MulDiv
-kernel32.dll!MultiByteToWideChar
-kernel32.dll!NeedCurrentDirectoryForExePathA
-kernel32.dll!NeedCurrentDirectoryForExePathW
-kernel32.dll!NormalizeString
-kernel32.dll!OfferVirtualMemory
-kernel32.dll!OpenEventA
-kernel32.dll!OpenEventW
-kernel32.dll!OpenFile
-kernel32.dll!OpenFileById
-kernel32.dll!OpenFileMappingA
-kernel32.dll!OpenFileMappingW
-kernel32.dll!OpenJobObjectA
-kernel32.dll!OpenJobObjectW
-kernel32.dll!OpenMutexA
-kernel32.dll!OpenMutexW
-kernel32.dll!OpenPrivateNamespaceA
-kernel32.dll!OpenPrivateNamespaceW
-kernel32.dll!OpenProcess
-kernel32.dll!OpenSemaphoreA
-kernel32.dll!OpenSemaphoreW
-kernel32.dll!OpenThread
-kernel32.dll!OpenWaitableTimerA
-kernel32.dll!OpenWaitableTimerW
-kernel32.dll!OutputDebugStringA
-kernel32.dll!OutputDebugStringW
-kernel32.dll!PeekConsoleInputA
-kernel32.dll!PeekConsoleInputW
-kernel32.dll!PeekNamedPipe
-kernel32.dll!PostQueuedCompletionStatus
-kernel32.dll!PowerClearRequest
-kernel32.dll!PowerCreateRequest
-kernel32.dll!PowerSetRequest
-kernel32.dll!PrefetchVirtualMemory
-kernel32.dll!Process32First
-kernel32.dll!Process32FirstW
-kernel32.dll!Process32Next
-kernel32.dll!Process32NextW
-kernel32.dll!ProcessIdToSessionId
-kernel32.dll!PssCaptureSnapshot
-kernel32.dll!PssDuplicateSnapshot
-kernel32.dll!PssFreeSnapshot
-kernel32.dll!PssQuerySnapshot
-kernel32.dll!PssWalkMarkerCreate
-kernel32.dll!PssWalkMarkerFree
-kernel32.dll!PssWalkMarkerGetPosition
-kernel32.dll!PssWalkMarkerSeekToBeginning
-kernel32.dll!PssWalkMarkerSetPosition
-kernel32.dll!PssWalkSnapshot
-kernel32.dll!PulseEvent
-kernel32.dll!PurgeComm
-kernel32.dll!QueryActCtxSettingsW
-kernel32.dll!QueryActCtxW
-kernel32.dll!QueryDepthSList
-kernel32.dll!QueryDosDeviceA
-kernel32.dll!QueryDosDeviceW
-kernel32.dll!QueryFullProcessImageNameA
-kernel32.dll!QueryFullProcessImageNameW
-kernel32.dll!QueryIdleProcessorCycleTime
-kernel32.dll!QueryIdleProcessorCycleTimeEx
-kernel32.dll!QueryInformationJobObject
-kernel32.dll!QueryMemoryResourceNotification
-kernel32.dll!QueryPerformanceCounter
-kernel32.dll!QueryPerformanceFrequency
-kernel32.dll!QueryProcessAffinityUpdateMode
-kernel32.dll!QueryProcessCycleTime
-kernel32.dll!QueryProtectedPolicy
-kernel32.dll!QueryThreadCycleTime
-kernel32.dll!QueryThreadpoolStackInformation
-kernel32.dll!QueryUnbiasedInterruptTime
-kernel32.dll!QueueUserAPC
-kernel32.dll!QueueUserWorkItem
-kernel32.dll!RaiseException
-kernel32.dll!RaiseFailFastException
-kernel32.dll!ReadConsoleA
-kernel32.dll!ReadConsoleInputA
-kernel32.dll!ReadConsoleInputW
-kernel32.dll!ReadConsoleOutputA
-kernel32.dll!ReadConsoleOutputAttribute
-kernel32.dll!ReadConsoleOutputCharacterA
-kernel32.dll!ReadConsoleOutputCharacterW
-kernel32.dll!ReadConsoleOutputW
-kernel32.dll!ReadConsoleW
-kernel32.dll!ReadDirectoryChangesW
-kernel32.dll!ReadFile
-kernel32.dll!ReadFileEx
-kernel32.dll!ReadFileScatter
-kernel32.dll!ReadProcessMemory
-kernel32.dll!ReclaimVirtualMemory
-kernel32.dll!RegisterBadMemoryNotification
-kernel32.dll!RegisterWaitForInputIdle
-kernel32.dll!RegisterWaitForSingleObject
-kernel32.dll!RegisterWaitForSingleObjectEx
-kernel32.dll!ReleaseActCtx
-kernel32.dll!ReleaseMutex
-kernel32.dll!ReleaseMutexWhenCallbackReturns
-kernel32.dll!ReleaseSemaphore
-kernel32.dll!ReleaseSemaphoreWhenCallbackReturns
-kernel32.dll!ReleaseSRWLockExclusive
-kernel32.dll!ReleaseSRWLockShared
-kernel32.dll!RemoveDirectoryA
-kernel32.dll!RemoveDirectoryW
-kernel32.dll!RemoveDllDirectory
-kernel32.dll!RemoveLocalAlternateComputerNameW
-kernel32.dll!RemoveVectoredContinueHandler
-kernel32.dll!RemoveVectoredExceptionHandler
-kernel32.dll!ReOpenFile
-kernel32.dll!ReplaceFileA
-kernel32.dll!ReplaceFileW
-kernel32.dll!ResetEvent
-kernel32.dll!ResetWriteWatch
-kernel32.dll!ResolveDelayLoadedAPI
-kernel32.dll!ResolveDelayLoadsFromDll
-kernel32.dll!ResolveLocaleName
-kernel32.dll!RestoreLastError
-kernel32.dll!ResumeThread
-kernel32.dll!RtlCaptureContext
-kernel32.dll!RtlCaptureStackBackTrace
-kernel32.dll!RtlCompareMemory
-kernel32.dll!RtlPcToFileHeader
-kernel32.dll!RtlRaiseException
-kernel32.dll!RtlUnwind
-kernel32.dll!ScrollConsoleScreenBufferA
-kernel32.dll!ScrollConsoleScreenBufferW
-kernel32.dll!SearchPathA
-kernel32.dll!SearchPathW
-kernel32.dll!SetCachedSigningLevel
-kernel32.dll!SetCalendarInfoA
-kernel32.dll!SetCalendarInfoW
-kernel32.dll!SetCommBreak
-kernel32.dll!SetCommConfig
-kernel32.dll!SetCommMask
-kernel32.dll!SetCommState
-kernel32.dll!SetCommTimeouts
-kernel32.dll!SetComputerNameA
-kernel32.dll!SetComputerNameEx2W
-kernel32.dll!SetComputerNameExA
-kernel32.dll!SetComputerNameExW
-kernel32.dll!SetComputerNameW
-kernel32.dll!SetConsoleActiveScreenBuffer
-kernel32.dll!SetConsoleCP
-kernel32.dll!SetConsoleCtrlHandler
-kernel32.dll!SetConsoleCursorInfo
-kernel32.dll!SetConsoleCursorPosition
-kernel32.dll!SetConsoleMode
-kernel32.dll!SetConsoleOutputCP
-kernel32.dll!SetConsoleScreenBufferInfoEx
-kernel32.dll!SetConsoleScreenBufferSize
-kernel32.dll!SetConsoleTextAttribute
-kernel32.dll!SetConsoleTitleA
-kernel32.dll!SetConsoleTitleW
-kernel32.dll!SetConsoleWindowInfo
-kernel32.dll!SetCriticalSectionSpinCount
-kernel32.dll!SetCurrentDirectoryA
-kernel32.dll!SetCurrentDirectoryW
-kernel32.dll!SetDefaultDllDirectories
-kernel32.dll!SetDllDirectoryA
-kernel32.dll!SetDllDirectoryW
-kernel32.dll!SetDynamicTimeZoneInformation
-kernel32.dll!SetEndOfFile
-kernel32.dll!SetEnvironmentStringsA
-kernel32.dll!SetEnvironmentStringsW
-kernel32.dll!SetEnvironmentVariableA
-kernel32.dll!SetEnvironmentVariableW
-kernel32.dll!SetErrorMode
-kernel32.dll!SetEvent
-kernel32.dll!SetEventWhenCallbackReturns
-kernel32.dll!SetFileApisToANSI
-kernel32.dll!SetFileApisToOEM
-kernel32.dll!SetFileAttributesA
-kernel32.dll!SetFileAttributesW
-kernel32.dll!SetFileCompletionNotificationModes
-kernel32.dll!SetFileInformationByHandle
-kernel32.dll!SetFileIoOverlappedRange
-kernel32.dll!SetFilePointer
-kernel32.dll!SetFilePointerEx
-kernel32.dll!SetFileTime
-kernel32.dll!SetFileValidData
-kernel32.dll!SetFirmwareEnvironmentVariableExW
-kernel32.dll!SetFirmwareEnvironmentVariableW
-kernel32.dll!SetHandleCount
-kernel32.dll!SetHandleInformation
-kernel32.dll!SetInformationJobObject
-kernel32.dll!SetLastError
-kernel32.dll!SetLocaleInfoA
-kernel32.dll!SetLocaleInfoW
-kernel32.dll!SetLocalPrimaryComputerNameW
-kernel32.dll!SetLocalTime
-kernel32.dll!SetMailslotInfo
-kernel32.dll!SetNamedPipeHandleState
-kernel32.dll!SetPriorityClass
-kernel32.dll!SetProcessAffinityMask
-kernel32.dll!SetProcessAffinityUpdateMode
-kernel32.dll!SetProcessInformation
-kernel32.dll!SetProcessMitigationPolicy
-kernel32.dll!SetProcessPreferredUILanguages
-kernel32.dll!SetProcessPriorityBoost
-kernel32.dll!SetProcessShutdownParameters
-kernel32.dll!SetProcessWorkingSetSizeEx
-kernel32.dll!SetProtectedPolicy
-kernel32.dll!SetStdHandle
-kernel32.dll!SetStdHandleEx
-kernel32.dll!SetSystemFileCacheSize
-kernel32.dll!SetSystemTime
-kernel32.dll!SetSystemTimeAdjustment
-kernel32.dll!SetThreadAffinityMask
-kernel32.dll!SetThreadContext
-kernel32.dll!SetThreadErrorMode
-kernel32.dll!SetThreadGroupAffinity
-kernel32.dll!SetThreadIdealProcessor
-kernel32.dll!SetThreadIdealProcessorEx
-kernel32.dll!SetThreadInformation
-kernel32.dll!SetThreadLocale
-kernel32.dll!SetThreadpoolStackInformation
-kernel32.dll!SetThreadpoolThreadMaximum
-kernel32.dll!SetThreadpoolThreadMinimum
-kernel32.dll!SetThreadpoolTimer
-kernel32.dll!SetThreadpoolTimerEx
-kernel32.dll!SetThreadpoolWait
-kernel32.dll!SetThreadpoolWaitEx
-kernel32.dll!SetThreadPreferredUILanguages
-kernel32.dll!SetThreadPriority
-kernel32.dll!SetThreadPriorityBoost
-kernel32.dll!SetThreadStackGuarantee
-kernel32.dll!SetThreadUILanguage
-kernel32.dll!SetTimeZoneInformation
-kernel32.dll!SetUnhandledExceptionFilter
-kernel32.dll!SetupComm
-kernel32.dll!SetUserGeoID
-kernel32.dll!SetVolumeLabelA
-kernel32.dll!SetVolumeLabelW
-kernel32.dll!SetVolumeMountPointA
-kernel32.dll!SetVolumeMountPointW
-kernel32.dll!SetWaitableTimer
-kernel32.dll!SetWaitableTimerEx
-kernel32.dll!SetXStateFeaturesMask
-kernel32.dll!SignalObjectAndWait
-kernel32.dll!SizeofResource
-kernel32.dll!Sleep
-kernel32.dll!SleepConditionVariableCS
-kernel32.dll!SleepConditionVariableSRW
-kernel32.dll!SleepEx
-kernel32.dll!StartThreadpoolIo
-kernel32.dll!SubmitThreadpoolWork
-kernel32.dll!SuspendThread
-kernel32.dll!SwitchToFiber
-kernel32.dll!SwitchToThread
-kernel32.dll!SystemTimeToFileTime
-kernel32.dll!SystemTimeToTzSpecificLocalTime
-kernel32.dll!SystemTimeToTzSpecificLocalTimeEx
-kernel32.dll!TerminateJobObject
-kernel32.dll!TerminateProcess
-kernel32.dll!TerminateThread
-kernel32.dll!Thread32First
-kernel32.dll!Thread32Next
-kernel32.dll!TlsAlloc
-kernel32.dll!TlsFree
-kernel32.dll!TlsGetValue
-kernel32.dll!TlsSetValue
-kernel32.dll!TransactNamedPipe
-kernel32.dll!TransmitCommChar
-kernel32.dll!TryAcquireSRWLockExclusive
-kernel32.dll!TryAcquireSRWLockShared
-kernel32.dll!TryEnterCriticalSection
-kernel32.dll!TrySubmitThreadpoolCallback
-kernel32.dll!TzSpecificLocalTimeToSystemTime
-kernel32.dll!TzSpecificLocalTimeToSystemTimeEx
-kernel32.dll!UnhandledExceptionFilter
-kernel32.dll!UnlockFile
-kernel32.dll!UnlockFileEx
-kernel32.dll!UnmapViewOfFile
-kernel32.dll!UnmapViewOfFileEx
-kernel32.dll!UnregisterBadMemoryNotification
-kernel32.dll!UnregisterWait
-kernel32.dll!UnregisterWaitEx
-kernel32.dll!UpdateProcThreadAttribute
-kernel32.dll!VerifyScripts
-kernel32.dll!VerifyVersionInfoA
-kernel32.dll!VerifyVersionInfoW
-kernel32.dll!VerLanguageNameA
-kernel32.dll!VerLanguageNameW
-kernel32.dll!VerSetConditionMask
-kernel32.dll!VirtualAlloc
-kernel32.dll!VirtualAllocEx
-kernel32.dll!VirtualAllocExNuma
-kernel32.dll!VirtualFree
-kernel32.dll!VirtualFreeEx
-kernel32.dll!VirtualLock
-kernel32.dll!VirtualProtect
-kernel32.dll!VirtualProtectEx
-kernel32.dll!VirtualQuery
-kernel32.dll!VirtualQueryEx
-kernel32.dll!VirtualUnlock
-kernel32.dll!WaitCommEvent
-kernel32.dll!WaitForDebugEvent
-kernel32.dll!WaitForDebugEventEx
-kernel32.dll!WaitForMultipleObjects
-kernel32.dll!WaitForMultipleObjectsEx
-kernel32.dll!WaitForSingleObject
-kernel32.dll!WaitForSingleObjectEx
-kernel32.dll!WaitForThreadpoolIoCallbacks
-kernel32.dll!WaitForThreadpoolTimerCallbacks
-kernel32.dll!WaitForThreadpoolWaitCallbacks
-kernel32.dll!WaitForThreadpoolWorkCallbacks
-kernel32.dll!WaitNamedPipeA
-kernel32.dll!WaitNamedPipeW
-kernel32.dll!WakeAllConditionVariable
-kernel32.dll!WakeConditionVariable
-kernel32.dll!WerGetFlags
-kernel32.dll!WerRegisterFile
-kernel32.dll!WerRegisterMemoryBlock
-kernel32.dll!WerRegisterRuntimeExceptionModule
-kernel32.dll!WerSetFlags
-kernel32.dll!WerUnregisterFile
-kernel32.dll!WerUnregisterMemoryBlock
-kernel32.dll!WerUnregisterRuntimeExceptionModule
-kernel32.dll!WideCharToMultiByte
-kernel32.dll!Wow64DisableWow64FsRedirection
-kernel32.dll!Wow64EnableWow64FsRedirection
-kernel32.dll!Wow64RevertWow64FsRedirection
-kernel32.dll!WriteConsoleA
-kernel32.dll!WriteConsoleInputA
-kernel32.dll!WriteConsoleInputW
-kernel32.dll!WriteConsoleOutputA
-kernel32.dll!WriteConsoleOutputAttribute
-kernel32.dll!WriteConsoleOutputCharacterA
-kernel32.dll!WriteConsoleOutputCharacterW
-kernel32.dll!WriteConsoleOutputW
-kernel32.dll!WriteConsoleW
-kernel32.dll!WriteFile
-kernel32.dll!WriteFileEx
-kernel32.dll!WriteFileGather
-kernel32.dll!WritePrivateProfileSectionA
-kernel32.dll!WritePrivateProfileSectionW
-kernel32.dll!WritePrivateProfileStringA
-kernel32.dll!WritePrivateProfileStringW
-kernel32.dll!WriteProcessMemory
-kernel32.dll!WTSGetActiveConsoleSessionId
-kernel32.dll!ZombifyActCtx
-normaliz.dll!IdnToAscii
-normaliz.dll!IdnToNameprepUnicode
-normaliz.dll!IdnToUnicode
-ole32.dll!CLIPFORMAT_UserFree
-ole32.dll!CLIPFORMAT_UserMarshal
-ole32.dll!CLIPFORMAT_UserSize
-ole32.dll!CLIPFORMAT_UserUnmarshal
-ole32.dll!CLSIDFromProgID
-ole32.dll!CLSIDFromString
-ole32.dll!CoAddRefServerProcess
-ole32.dll!CoAllowUnmarshalerCLSID
-ole32.dll!CoCancelCall
-ole32.dll!CoCopyProxy
-ole32.dll!CoCreateFreeThreadedMarshaler
-ole32.dll!CoCreateGuid
-ole32.dll!CoCreateInstance
-ole32.dll!CoCreateInstanceEx
-ole32.dll!CoCreateInstanceFromApp
-ole32.dll!CoCreateObjectInContext
-ole32.dll!CoDeactivateObject
-ole32.dll!CoDecodeProxy
-ole32.dll!CoDecrementMTAUsage
-ole32.dll!CoDisableCallCancellation
-ole32.dll!CoDisconnectContext
-ole32.dll!CoDisconnectObject
-ole32.dll!CoEnableCallCancellation
-ole32.dll!CoFreeUnusedLibraries
-ole32.dll!CoFreeUnusedLibrariesEx
-ole32.dll!CoGetApartmentID
-ole32.dll!CoGetApartmentType
-ole32.dll!CoGetCallContext
-ole32.dll!CoGetCallerTID
-ole32.dll!CoGetCancelObject
-ole32.dll!CoGetClassObject
-ole32.dll!CoGetClassVersion
-ole32.dll!CoGetContextToken
-ole32.dll!CoGetCurrentLogicalThreadId
-ole32.dll!CoGetCurrentProcess
-ole32.dll!CoGetDefaultContext
-ole32.dll!CoGetInstanceFromFile
-ole32.dll!CoGetInstanceFromIStorage
-ole32.dll!CoGetInterfaceAndReleaseStream
-ole32.dll!CoGetMalloc
-ole32.dll!CoGetMarshalSizeMax
-ole32.dll!CoGetObjectContext
-ole32.dll!CoGetProcessIdentifier
-ole32.dll!CoGetPSClsid
-ole32.dll!CoGetStandardMarshal
-ole32.dll!CoGetStdMarshalEx
-ole32.dll!CoGetSystemSecurityPermissions
-ole32.dll!CoGetTreatAsClass
-ole32.dll!CoImpersonateClient
-ole32.dll!CoIncrementMTAUsage
-ole32.dll!CoInitializeEx
-ole32.dll!CoInitializeSecurity
-ole32.dll!CoInitializeWOW
-ole32.dll!CoInvalidateRemoteMachineBindings
-ole32.dll!CoIsHandlerConnected
-ole32.dll!CoLockObjectExternal
-ole32.dll!CoMarshalHresult
-ole32.dll!CoMarshalInterface
-ole32.dll!CoMarshalInterThreadInterfaceInStream
-ole32.dll!CoQueryAuthenticationServices
-ole32.dll!CoQueryClientBlanket
-ole32.dll!CoQueryProxyBlanket
-ole32.dll!CoReactivateObject
-ole32.dll!CoRegisterActivationFilter
-ole32.dll!CoRegisterClassObject
-ole32.dll!CoRegisterInitializeSpy
-ole32.dll!CoRegisterMallocSpy
-ole32.dll!CoRegisterMessageFilter
-ole32.dll!CoRegisterPSClsid
-ole32.dll!CoRegisterSurrogate
-ole32.dll!CoRegisterSurrogateEx
-ole32.dll!CoReleaseMarshalData
-ole32.dll!CoReleaseServerProcess
-ole32.dll!CoResumeClassObjects
-ole32.dll!CoRetireServer
-ole32.dll!CoRevertToSelf
-ole32.dll!CoRevokeClassObject
-ole32.dll!CoRevokeInitializeSpy
-ole32.dll!CoRevokeMallocSpy
-ole32.dll!CoSetCancelObject
-ole32.dll!CoSetProxyBlanket
-ole32.dll!CoSuspendClassObjects
-ole32.dll!CoSwitchCallContext
-ole32.dll!CoTaskMemAlloc
-ole32.dll!CoTaskMemFree
-ole32.dll!CoTaskMemRealloc
-ole32.dll!CoTestCancel
-ole32.dll!CoUninitialize
-ole32.dll!CoUnloadingWOW
-ole32.dll!CoUnmarshalHresult
-ole32.dll!CoUnmarshalInterface
-ole32.dll!CoWaitForMultipleHandles
-ole32.dll!CoWaitForMultipleObjects
-ole32.dll!CreateStreamOnHGlobal
-ole32.dll!CStdAsyncStubBuffer_AddRef
-ole32.dll!CStdAsyncStubBuffer_Connect
-ole32.dll!CStdAsyncStubBuffer_Disconnect
-ole32.dll!CStdAsyncStubBuffer_Invoke
-ole32.dll!CStdAsyncStubBuffer_QueryInterface
-ole32.dll!CStdAsyncStubBuffer_Release
-ole32.dll!CStdAsyncStubBuffer2_Connect
-ole32.dll!CStdAsyncStubBuffer2_Disconnect
-ole32.dll!CStdAsyncStubBuffer2_Release
-ole32.dll!CStdStubBuffer2_Connect
-ole32.dll!CStdStubBuffer2_CountRefs
-ole32.dll!CStdStubBuffer2_Disconnect
-ole32.dll!CStdStubBuffer2_QueryInterface
-ole32.dll!DllDebugObjectRPCHook
-ole32.dll!EnableHookObject
-ole32.dll!FreePropVariantArray
-ole32.dll!GetHGlobalFromStream
-ole32.dll!GetHookInterface
-ole32.dll!HACCEL_UserFree
-ole32.dll!HACCEL_UserMarshal
-ole32.dll!HACCEL_UserSize
-ole32.dll!HACCEL_UserUnmarshal
-ole32.dll!HBITMAP_UserFree
-ole32.dll!HBITMAP_UserMarshal
-ole32.dll!HBITMAP_UserSize
-ole32.dll!HBITMAP_UserUnmarshal
-ole32.dll!HBRUSH_UserFree
-ole32.dll!HBRUSH_UserMarshal
-ole32.dll!HBRUSH_UserSize
-ole32.dll!HBRUSH_UserUnmarshal
-ole32.dll!HDC_UserFree
-ole32.dll!HDC_UserMarshal
-ole32.dll!HDC_UserSize
-ole32.dll!HDC_UserUnmarshal
-ole32.dll!HGLOBAL_UserFree
-ole32.dll!HGLOBAL_UserMarshal
-ole32.dll!HGLOBAL_UserSize
-ole32.dll!HGLOBAL_UserUnmarshal
-ole32.dll!HICON_UserFree
-ole32.dll!HICON_UserMarshal
-ole32.dll!HICON_UserSize
-ole32.dll!HICON_UserUnmarshal
-ole32.dll!HkOleRegisterObject
-ole32.dll!HMENU_UserFree
-ole32.dll!HMENU_UserMarshal
-ole32.dll!HMENU_UserSize
-ole32.dll!HMENU_UserUnmarshal
-ole32.dll!HMONITOR_UserFree
-ole32.dll!HMONITOR_UserMarshal
-ole32.dll!HMONITOR_UserSize
-ole32.dll!HMONITOR_UserUnmarshal
-ole32.dll!HPALETTE_UserFree
-ole32.dll!HPALETTE_UserMarshal
-ole32.dll!HPALETTE_UserSize
-ole32.dll!HPALETTE_UserUnmarshal
-ole32.dll!HWND_UserFree
-ole32.dll!HWND_UserMarshal
-ole32.dll!HWND_UserSize
-ole32.dll!HWND_UserUnmarshal
-ole32.dll!IIDFromString
-ole32.dll!NdrProxyForwardingFunction10
-ole32.dll!NdrProxyForwardingFunction11
-ole32.dll!NdrProxyForwardingFunction12
-ole32.dll!NdrProxyForwardingFunction13
-ole32.dll!NdrProxyForwardingFunction14
-ole32.dll!NdrProxyForwardingFunction15
-ole32.dll!NdrProxyForwardingFunction16
-ole32.dll!NdrProxyForwardingFunction17
-ole32.dll!NdrProxyForwardingFunction18
-ole32.dll!NdrProxyForwardingFunction19
-ole32.dll!NdrProxyForwardingFunction20
-ole32.dll!NdrProxyForwardingFunction21
-ole32.dll!NdrProxyForwardingFunction22
-ole32.dll!NdrProxyForwardingFunction23
-ole32.dll!NdrProxyForwardingFunction24
-ole32.dll!NdrProxyForwardingFunction25
-ole32.dll!NdrProxyForwardingFunction26
-ole32.dll!NdrProxyForwardingFunction27
-ole32.dll!NdrProxyForwardingFunction28
-ole32.dll!NdrProxyForwardingFunction29
-ole32.dll!NdrProxyForwardingFunction3
-ole32.dll!NdrProxyForwardingFunction30
-ole32.dll!NdrProxyForwardingFunction31
-ole32.dll!NdrProxyForwardingFunction32
-ole32.dll!NdrProxyForwardingFunction4
-ole32.dll!NdrProxyForwardingFunction5
-ole32.dll!NdrProxyForwardingFunction6
-ole32.dll!NdrProxyForwardingFunction7
-ole32.dll!NdrProxyForwardingFunction8
-ole32.dll!NdrProxyForwardingFunction9
-ole32.dll!ObjectStublessClient10
-ole32.dll!ObjectStublessClient11
-ole32.dll!ObjectStublessClient12
-ole32.dll!ObjectStublessClient13
-ole32.dll!ObjectStublessClient14
-ole32.dll!ObjectStublessClient15
-ole32.dll!ObjectStublessClient16
-ole32.dll!ObjectStublessClient17
-ole32.dll!ObjectStublessClient18
-ole32.dll!ObjectStublessClient19
-ole32.dll!ObjectStublessClient20
-ole32.dll!ObjectStublessClient21
-ole32.dll!ObjectStublessClient22
-ole32.dll!ObjectStublessClient23
-ole32.dll!ObjectStublessClient24
-ole32.dll!ObjectStublessClient25
-ole32.dll!ObjectStublessClient26
-ole32.dll!ObjectStublessClient27
-ole32.dll!ObjectStublessClient28
-ole32.dll!ObjectStublessClient29
-ole32.dll!ObjectStublessClient3
-ole32.dll!ObjectStublessClient30
-ole32.dll!ObjectStublessClient31
-ole32.dll!ObjectStublessClient32
-ole32.dll!ObjectStublessClient4
-ole32.dll!ObjectStublessClient5
-ole32.dll!ObjectStublessClient6
-ole32.dll!ObjectStublessClient7
-ole32.dll!ObjectStublessClient8
-ole32.dll!ObjectStublessClient9
-ole32.dll!ProgIDFromCLSID
-ole32.dll!PropVariantClear
-ole32.dll!PropVariantCopy
-ole32.dll!RoGetAgileReference
-ole32.dll!StringFromCLSID
-ole32.dll!StringFromGUID2
-ole32.dll!StringFromIID
-ole32.dll!UpdateDCOMSettings
-shell32.dll!CommandLineToArgvW
-shell32.dll!GetCurrentProcessExplicitAppUserModelID
-shell32.dll!PathCleanupSpec
-shell32.dll!PathIsExe
-shell32.dll!SetCurrentProcessExplicitAppUserModelID
-shell32.dll!SHCoCreateInstance
-shell32.dll!SHCreateDirectory
-shell32.dll!SHCreateDirectoryExA
-shell32.dll!SHCreateDirectoryExW
-shell32.dll!SHGetDesktopFolder
-shell32.dll!SHGetFileInfoW
-shell32.dll!SHGetFolderLocation
-shell32.dll!SHGetFolderPathA
-shell32.dll!SHGetFolderPathAndSubDirW
-shell32.dll!SHGetFolderPathW
-shell32.dll!SHGetInstanceExplorer
-shell32.dll!SHGetKnownFolderPath
-shell32.dll!SHGetSpecialFolderPathA
-shell32.dll!SHGetSpecialFolderPathW
-shell32.dll!SHSetKnownFolderPath
-shlwapi.dll!GetAcceptLanguagesA
-shlwapi.dll!GetAcceptLanguagesW
-shlwapi.dll!HashData
-shlwapi.dll!IsCharSpaceA
-shlwapi.dll!IsCharSpaceW
-shlwapi.dll!IsInternetESCEnabled
-shlwapi.dll!IsOS
-shlwapi.dll!IStream_Copy
-shlwapi.dll!IStream_Read
-shlwapi.dll!IStream_ReadStr
-shlwapi.dll!IStream_Reset
-shlwapi.dll!IStream_Size
-shlwapi.dll!IStream_Write
-shlwapi.dll!IStream_WriteStr
-shlwapi.dll!IUnknown_AtomicRelease
-shlwapi.dll!IUnknown_GetSite
-shlwapi.dll!IUnknown_QueryService
-shlwapi.dll!IUnknown_Set
-shlwapi.dll!IUnknown_SetSite
-shlwapi.dll!ParseURLA
-shlwapi.dll!ParseURLW
-shlwapi.dll!PathAddBackslashA
-shlwapi.dll!PathAddBackslashW
-shlwapi.dll!PathAddExtensionA
-shlwapi.dll!PathAddExtensionW
-shlwapi.dll!PathAppendA
-shlwapi.dll!PathAppendW
-shlwapi.dll!PathCanonicalizeA
-shlwapi.dll!PathCanonicalizeW
-shlwapi.dll!PathCombineA
-shlwapi.dll!PathCombineW
-shlwapi.dll!PathCommonPrefixA
-shlwapi.dll!PathCommonPrefixW
-shlwapi.dll!PathCreateFromUrlA
-shlwapi.dll!PathCreateFromUrlAlloc
-shlwapi.dll!PathCreateFromUrlW
-shlwapi.dll!PathFileExistsA
-shlwapi.dll!PathFileExistsW
-shlwapi.dll!PathFindExtensionA
-shlwapi.dll!PathFindExtensionW
-shlwapi.dll!PathFindFileNameA
-shlwapi.dll!PathFindFileNameW
-shlwapi.dll!PathFindNextComponentA
-shlwapi.dll!PathFindNextComponentW
-shlwapi.dll!PathGetArgsA
-shlwapi.dll!PathGetArgsW
-shlwapi.dll!PathGetCharTypeA
-shlwapi.dll!PathGetCharTypeW
-shlwapi.dll!PathGetDriveNumberA
-shlwapi.dll!PathGetDriveNumberW
-shlwapi.dll!PathIsFileSpecA
-shlwapi.dll!PathIsFileSpecW
-shlwapi.dll!PathIsLFNFileSpecA
-shlwapi.dll!PathIsLFNFileSpecW
-shlwapi.dll!PathIsPrefixA
-shlwapi.dll!PathIsPrefixW
-shlwapi.dll!PathIsRelativeA
-shlwapi.dll!PathIsRelativeW
-shlwapi.dll!PathIsRootA
-shlwapi.dll!PathIsRootW
-shlwapi.dll!PathIsSameRootA
-shlwapi.dll!PathIsSameRootW
-shlwapi.dll!PathIsUNCA
-shlwapi.dll!PathIsUNCServerA
-shlwapi.dll!PathIsUNCServerShareA
-shlwapi.dll!PathIsUNCServerShareW
-shlwapi.dll!PathIsUNCServerW
-shlwapi.dll!PathIsUNCW
-shlwapi.dll!PathIsURLA
-shlwapi.dll!PathIsURLW
-shlwapi.dll!PathMatchSpecA
-shlwapi.dll!PathMatchSpecExA
-shlwapi.dll!PathMatchSpecExW
-shlwapi.dll!PathMatchSpecW
-shlwapi.dll!PathParseIconLocationA
-shlwapi.dll!PathParseIconLocationW
-shlwapi.dll!PathQuoteSpacesA
-shlwapi.dll!PathQuoteSpacesW
-shlwapi.dll!PathRelativePathToA
-shlwapi.dll!PathRelativePathToW
-shlwapi.dll!PathRemoveBackslashA
-shlwapi.dll!PathRemoveBackslashW
-shlwapi.dll!PathRemoveBlanksA
-shlwapi.dll!PathRemoveBlanksW
-shlwapi.dll!PathRemoveExtensionA
-shlwapi.dll!PathRemoveExtensionW
-shlwapi.dll!PathRemoveFileSpecA
-shlwapi.dll!PathRemoveFileSpecW
-shlwapi.dll!PathRenameExtensionA
-shlwapi.dll!PathRenameExtensionW
-shlwapi.dll!PathSearchAndQualifyA
-shlwapi.dll!PathSearchAndQualifyW
-shlwapi.dll!PathSkipRootA
-shlwapi.dll!PathSkipRootW
-shlwapi.dll!PathStripPathA
-shlwapi.dll!PathStripPathW
-shlwapi.dll!PathStripToRootA
-shlwapi.dll!PathStripToRootW
-shlwapi.dll!PathUnExpandEnvStringsA
-shlwapi.dll!PathUnExpandEnvStringsW
-shlwapi.dll!PathUnquoteSpacesA
-shlwapi.dll!PathUnquoteSpacesW
-shlwapi.dll!QISearch
-shlwapi.dll!SHAnsiToAnsi
-shlwapi.dll!SHAnsiToUnicode
-shlwapi.dll!SHCopyKeyA
-shlwapi.dll!SHCopyKeyW
-shlwapi.dll!SHCreateMemStream
-shlwapi.dll!SHCreateStreamOnFileA
-shlwapi.dll!SHCreateStreamOnFileEx
-shlwapi.dll!SHCreateStreamOnFileW
-shlwapi.dll!SHCreateThread
-shlwapi.dll!SHCreateThreadRef
-shlwapi.dll!SHCreateThreadWithHandle
-shlwapi.dll!SHDeleteEmptyKeyA
-shlwapi.dll!SHDeleteEmptyKeyW
-shlwapi.dll!SHDeleteKeyA
-shlwapi.dll!SHDeleteKeyW
-shlwapi.dll!SHDeleteValueA
-shlwapi.dll!SHDeleteValueW
-shlwapi.dll!SHEnumKeyExA
-shlwapi.dll!SHEnumKeyExW
-shlwapi.dll!SHEnumValueA
-shlwapi.dll!SHEnumValueW
-shlwapi.dll!SHGetThreadRef
-shlwapi.dll!SHGetValueA
-shlwapi.dll!SHGetValueW
-shlwapi.dll!SHLoadIndirectString
-shlwapi.dll!SHOpenRegStream2A
-shlwapi.dll!SHOpenRegStream2W
-shlwapi.dll!SHOpenRegStreamA
-shlwapi.dll!SHOpenRegStreamW
-shlwapi.dll!SHQueryInfoKeyA
-shlwapi.dll!SHQueryInfoKeyW
-shlwapi.dll!SHQueryValueExA
-shlwapi.dll!SHQueryValueExW
-shlwapi.dll!SHRegCloseUSKey
-shlwapi.dll!SHRegCreateUSKeyA
-shlwapi.dll!SHRegCreateUSKeyW
-shlwapi.dll!SHRegDeleteEmptyUSKeyA
-shlwapi.dll!SHRegDeleteEmptyUSKeyW
-shlwapi.dll!SHRegDeleteUSValueA
-shlwapi.dll!SHRegDeleteUSValueW
-shlwapi.dll!SHRegDuplicateHKey
-shlwapi.dll!SHRegEnumUSKeyA
-shlwapi.dll!SHRegEnumUSKeyW
-shlwapi.dll!SHRegEnumUSValueA
-shlwapi.dll!SHRegEnumUSValueW
-shlwapi.dll!SHRegGetBoolUSValueA
-shlwapi.dll!SHRegGetBoolUSValueW
-shlwapi.dll!SHRegGetIntW
-shlwapi.dll!SHRegGetPathA
-shlwapi.dll!SHRegGetPathW
-shlwapi.dll!SHRegGetUSValueA
-shlwapi.dll!SHRegGetUSValueW
-shlwapi.dll!SHRegGetValueA
-shlwapi.dll!SHRegGetValueW
-shlwapi.dll!SHRegOpenUSKeyA
-shlwapi.dll!SHRegOpenUSKeyW
-shlwapi.dll!SHRegQueryInfoUSKeyA
-shlwapi.dll!SHRegQueryInfoUSKeyW
-shlwapi.dll!SHRegQueryUSValueA
-shlwapi.dll!SHRegQueryUSValueW
-shlwapi.dll!SHRegSetPathA
-shlwapi.dll!SHRegSetPathW
-shlwapi.dll!SHRegSetUSValueA
-shlwapi.dll!SHRegSetUSValueW
-shlwapi.dll!SHRegWriteUSValueA
-shlwapi.dll!SHRegWriteUSValueW
-shlwapi.dll!SHReleaseThreadRef
-shlwapi.dll!SHSetThreadRef
-shlwapi.dll!SHSetValueA
-shlwapi.dll!SHSetValueW
-shlwapi.dll!SHStrDupA
-shlwapi.dll!SHStrDupW
-shlwapi.dll!SHUnicodeToAnsi
-shlwapi.dll!SHUnicodeToUnicode
-shlwapi.dll!StrCatBuffA
-shlwapi.dll!StrCatBuffW
-shlwapi.dll!StrCatChainW
-shlwapi.dll!StrChrA
-shlwapi.dll!StrChrIA
-shlwapi.dll!StrChrIW
-shlwapi.dll!StrChrNIW
-shlwapi.dll!StrChrNW
-shlwapi.dll!StrChrW
-shlwapi.dll!StrCmpCA
-shlwapi.dll!StrCmpCW
-shlwapi.dll!StrCmpICA
-shlwapi.dll!StrCmpICW
-shlwapi.dll!StrCmpIW
-shlwapi.dll!StrCmpLogicalW
-shlwapi.dll!StrCmpNA
-shlwapi.dll!StrCmpNCA
-shlwapi.dll!StrCmpNCW
-shlwapi.dll!StrCmpNIA
-shlwapi.dll!StrCmpNICA
-shlwapi.dll!StrCmpNICW
-shlwapi.dll!StrCmpNIW
-shlwapi.dll!StrCmpNW
-shlwapi.dll!StrCmpW
-shlwapi.dll!StrCpyNW
-shlwapi.dll!StrCSpnA
-shlwapi.dll!StrCSpnIA
-shlwapi.dll!StrCSpnIW
-shlwapi.dll!StrCSpnW
-shlwapi.dll!StrDupA
-shlwapi.dll!StrDupW
-shlwapi.dll!StrIsIntlEqualA
-shlwapi.dll!StrIsIntlEqualW
-shlwapi.dll!StrPBrkA
-shlwapi.dll!StrPBrkW
-shlwapi.dll!StrRChrA
-shlwapi.dll!StrRChrIA
-shlwapi.dll!StrRChrIW
-shlwapi.dll!StrRChrW
-shlwapi.dll!StrRStrIA
-shlwapi.dll!StrRStrIW
-shlwapi.dll!StrSpnA
-shlwapi.dll!StrSpnW
-shlwapi.dll!StrStrA
-shlwapi.dll!StrStrIA
-shlwapi.dll!StrStrIW
-shlwapi.dll!StrStrNIW
-shlwapi.dll!StrStrNW
-shlwapi.dll!StrStrW
-shlwapi.dll!StrToInt64ExA
-shlwapi.dll!StrToInt64ExW
-shlwapi.dll!StrToIntA
-shlwapi.dll!StrToIntExA
-shlwapi.dll!StrToIntExW
-shlwapi.dll!StrToIntW
-shlwapi.dll!StrTrimA
-shlwapi.dll!StrTrimW
-shlwapi.dll!UrlApplySchemeA
-shlwapi.dll!UrlApplySchemeW
-shlwapi.dll!UrlCanonicalizeA
-shlwapi.dll!UrlCanonicalizeW
-shlwapi.dll!UrlCombineA
-shlwapi.dll!UrlCombineW
-shlwapi.dll!UrlCompareA
-shlwapi.dll!UrlCompareW
-shlwapi.dll!UrlCreateFromPathA
-shlwapi.dll!UrlCreateFromPathW
-shlwapi.dll!UrlEscapeA
-shlwapi.dll!UrlEscapeW
-shlwapi.dll!UrlFixupW
-shlwapi.dll!UrlGetLocationA
-shlwapi.dll!UrlGetLocationW
-shlwapi.dll!UrlGetPartA
-shlwapi.dll!UrlGetPartW
-shlwapi.dll!UrlHashA
-shlwapi.dll!UrlHashW
-shlwapi.dll!UrlIsA
-shlwapi.dll!UrlIsNoHistoryA
-shlwapi.dll!UrlIsNoHistoryW
-shlwapi.dll!UrlIsOpaqueA
-shlwapi.dll!UrlIsOpaqueW
-shlwapi.dll!UrlIsW
-shlwapi.dll!UrlUnescapeA
-shlwapi.dll!UrlUnescapeW
-version.dll!GetFileVersionInfoA
-version.dll!GetFileVersionInfoExW
-version.dll!GetFileVersionInfoSizeA
-version.dll!GetFileVersionInfoSizeExW
-version.dll!GetFileVersionInfoSizeW
-version.dll!GetFileVersionInfoW
-version.dll!VerFindFileA
-version.dll!VerFindFileW
-version.dll!VerQueryValueA
-version.dll!VerQueryValueW
-api-ms-win-core-memory-l1-1-3.dll!OpenFileMappingFromApp
-api-ms-win-core-memory-l1-1-3.dll!SetProcessValidCallTargets
-api-ms-win-core-memory-l1-1-3.dll!VirtualAllocFromApp
-api-ms-win-core-memory-l1-1-3.dll!VirtualProtectFromApp
-api-ms-win-core-winrt-error-l1-1-0.dll!GetRestrictedErrorInfo
-api-ms-win-core-winrt-error-l1-1-0.dll!RoCaptureErrorContext
-api-ms-win-core-winrt-error-l1-1-0.dll!RoFailFastWithErrorContext
-api-ms-win-core-winrt-error-l1-1-0.dll!RoGetErrorReportingFlags
-api-ms-win-core-winrt-error-l1-1-0.dll!RoOriginateError
-api-ms-win-core-winrt-error-l1-1-0.dll!RoOriginateErrorW
-api-ms-win-core-winrt-error-l1-1-0.dll!RoResolveRestrictedErrorInfoReference
-api-ms-win-core-winrt-error-l1-1-0.dll!RoSetErrorReportingFlags
-api-ms-win-core-winrt-error-l1-1-0.dll!RoTransformError
-api-ms-win-core-winrt-error-l1-1-0.dll!RoTransformErrorW
-api-ms-win-core-winrt-error-l1-1-0.dll!SetRestrictedErrorInfo
-api-ms-win-core-winrt-robuffer-l1-1-0.dll!RoGetBufferMarshaler
diff --git a/PinvokeAnalyzer_UWPApis.txt b/PinvokeAnalyzer_UWPApis.txt
deleted file mode 100644
index 951c2ff4bd..0000000000
--- a/PinvokeAnalyzer_UWPApis.txt
+++ /dev/null
@@ -1,2298 +0,0 @@
-bcrypt.dll!BCryptCloseAlgorithmProvider
-bcrypt.dll!BCryptCreateHash
-bcrypt.dll!BCryptDecrypt
-bcrypt.dll!BCryptDeriveKey
-bcrypt.dll!BCryptDeriveKeyCapi
-bcrypt.dll!BCryptDeriveKeyPBKDF2
-bcrypt.dll!BCryptDestroyHash
-bcrypt.dll!BCryptDestroyKey
-bcrypt.dll!BCryptDestroySecret
-bcrypt.dll!BCryptDuplicateHash
-bcrypt.dll!BCryptDuplicateKey
-bcrypt.dll!BCryptEncrypt
-bcrypt.dll!BCryptEnumAlgorithms
-bcrypt.dll!BCryptEnumProviders
-bcrypt.dll!BCryptExportKey
-bcrypt.dll!BCryptFinalizeKeyPair
-bcrypt.dll!BCryptFinishHash
-bcrypt.dll!BCryptFreeBuffer
-bcrypt.dll!BCryptGenerateKeyPair
-bcrypt.dll!BCryptGenerateSymmetricKey
-bcrypt.dll!BCryptGenRandom
-bcrypt.dll!BCryptGetProperty
-bcrypt.dll!BCryptHash
-bcrypt.dll!BCryptHashData
-bcrypt.dll!BCryptImportKey
-bcrypt.dll!BCryptImportKeyPair
-bcrypt.dll!BCryptKeyDerivation
-bcrypt.dll!BCryptOpenAlgorithmProvider
-bcrypt.dll!BCryptSecretAgreement
-bcrypt.dll!BCryptSetProperty
-bcrypt.dll!BCryptSignHash
-bcrypt.dll!BCryptVerifySignature
-Cabinet.dll!CloseCompressor
-Cabinet.dll!CloseDecompressor
-Cabinet.dll!Compress
-Cabinet.dll!CreateCompressor
-Cabinet.dll!CreateDecompressor
-Cabinet.dll!Decompress
-Cabinet.dll!FDICopy
-Cabinet.dll!FDICreate
-Cabinet.dll!FDIDestroy
-Cabinet.dll!FDIIsCabinet
-Cabinet.dll!QueryCompressorInformation
-Cabinet.dll!QueryDecompressorInformation
-Cabinet.dll!ResetCompressor
-Cabinet.dll!ResetDecompressor
-Cabinet.dll!SetCompressorInformation
-Cabinet.dll!SetDecompressorInformation
-chakra.dll!JsAddRef
-chakra.dll!JsBooleanToBool
-chakra.dll!JsBoolToBoolean
-chakra.dll!JsCallFunction
-chakra.dll!JsCollectGarbage
-chakra.dll!JsConstructObject
-chakra.dll!JsConvertValueToBoolean
-chakra.dll!JsConvertValueToNumber
-chakra.dll!JsConvertValueToObject
-chakra.dll!JsConvertValueToString
-chakra.dll!JsCreateArray
-chakra.dll!JsCreateArrayBuffer
-chakra.dll!JsCreateContext
-chakra.dll!JsCreateDataView
-chakra.dll!JsCreateError
-chakra.dll!JsCreateExternalObject
-chakra.dll!JsCreateFunction
-chakra.dll!JsCreateNamedFunction
-chakra.dll!JsCreateObject
-chakra.dll!JsCreateRangeError
-chakra.dll!JsCreateReferenceError
-chakra.dll!JsCreateRuntime
-chakra.dll!JsCreateSymbol
-chakra.dll!JsCreateSyntaxError
-chakra.dll!JsCreateTypedArray
-chakra.dll!JsCreateTypeError
-chakra.dll!JsCreateURIError
-chakra.dll!JsDefineProperty
-chakra.dll!JsDeleteIndexedProperty
-chakra.dll!JsDeleteProperty
-chakra.dll!JsDisableRuntimeExecution
-chakra.dll!JsDisposeRuntime
-chakra.dll!JsDoubleToNumber
-chakra.dll!JsEnableRuntimeExecution
-chakra.dll!JsEquals
-chakra.dll!JsGetAndClearException
-chakra.dll!JsGetArrayBufferStorage
-chakra.dll!JsGetCurrentContext
-chakra.dll!JsGetDataViewStorage
-chakra.dll!JsGetExtensionAllowed
-chakra.dll!JsGetExternalData
-chakra.dll!JsGetFalseValue
-chakra.dll!JsGetGlobalObject
-chakra.dll!JsGetIndexedPropertiesExternalData
-chakra.dll!JsGetIndexedProperty
-chakra.dll!JsGetNullValue
-chakra.dll!JsGetOwnPropertyDescriptor
-chakra.dll!JsGetOwnPropertyNames
-chakra.dll!JsGetOwnPropertySymbols
-chakra.dll!JsGetProperty
-chakra.dll!JsGetPropertyIdFromName
-chakra.dll!JsGetPropertyIdFromSymbol
-chakra.dll!JsGetPropertyIdType
-chakra.dll!JsGetPropertyNameFromId
-chakra.dll!JsGetPrototype
-chakra.dll!JsGetRuntime
-chakra.dll!JsGetRuntimeMemoryLimit
-chakra.dll!JsGetRuntimeMemoryUsage
-chakra.dll!JsGetStringLength
-chakra.dll!JsGetSymbolFromPropertyId
-chakra.dll!JsGetTrueValue
-chakra.dll!JsGetTypedArrayStorage
-chakra.dll!JsGetUndefinedValue
-chakra.dll!JsGetValueType
-chakra.dll!JsHasException
-chakra.dll!JsHasExternalData
-chakra.dll!JsHasIndexedPropertiesExternalData
-chakra.dll!JsHasIndexedProperty
-chakra.dll!JsHasProperty
-chakra.dll!JsIdle
-chakra.dll!JsInspectableToObject
-chakra.dll!JsIntToNumber
-chakra.dll!JsIsRuntimeExecutionDisabled
-chakra.dll!JsNumberToDouble
-chakra.dll!JsNumberToInt
-chakra.dll!JsObjectToInspectable
-chakra.dll!JsParseScript
-chakra.dll!JsParseSerializedScript
-chakra.dll!JsPointerToString
-chakra.dll!JsPreventExtension
-chakra.dll!JsProjectWinRTNamespace
-chakra.dll!JsRelease
-chakra.dll!JsRunScript
-chakra.dll!JsRunSerializedScript
-chakra.dll!JsSerializeScript
-chakra.dll!JsSetCurrentContext
-chakra.dll!JsSetException
-chakra.dll!JsSetExternalData
-chakra.dll!JsSetIndexedPropertiesToExternalData
-chakra.dll!JsSetIndexedProperty
-chakra.dll!JsSetObjectBeforeCollectCallback
-chakra.dll!JsSetProjectionEnqueueCallback
-chakra.dll!JsSetPromiseContinuationCallback
-chakra.dll!JsSetProperty
-chakra.dll!JsSetPrototype
-chakra.dll!JsSetRuntimeBeforeCollectCallback
-chakra.dll!JsSetRuntimeMemoryAllocationCallback
-chakra.dll!JsSetRuntimeMemoryLimit
-chakra.dll!JsStartDebugging
-chakra.dll!JsStrictEquals
-chakra.dll!JsStringToPointer
-chakra.dll!JsValueToVariant
-chakra.dll!JsVariantToValue
-CRYPT32.dll!CertAddCertificateContextToStore
-CRYPT32.dll!CertAddCertificateLinkToStore
-CRYPT32.dll!CertAddCRLContextToStore
-CRYPT32.dll!CertAddCRLLinkToStore
-CRYPT32.dll!CertAddCTLContextToStore
-CRYPT32.dll!CertAddCTLLinkToStore
-CRYPT32.dll!CertAddEncodedCertificateToStore
-CRYPT32.dll!CertAddEncodedCRLToStore
-CRYPT32.dll!CertAddEncodedCTLToStore
-CRYPT32.dll!CertAddSerializedElementToStore
-CRYPT32.dll!CertAddStoreToCollection
-CRYPT32.dll!CertCloseStore
-CRYPT32.dll!CertCompareCertificate
-CRYPT32.dll!CertCompareCertificateName
-CRYPT32.dll!CertCompareIntegerBlob
-CRYPT32.dll!CertControlStore
-CRYPT32.dll!CertCreateCertificateChainEngine
-CRYPT32.dll!CertCreateCertificateContext
-CRYPT32.dll!CertCreateContext
-CRYPT32.dll!CertCreateCRLContext
-CRYPT32.dll!CertCreateCTLContext
-CRYPT32.dll!CertCreateSelfSignCertificate
-CRYPT32.dll!CertDeleteCertificateFromStore
-CRYPT32.dll!CertDeleteCRLFromStore
-CRYPT32.dll!CertDeleteCTLFromStore
-CRYPT32.dll!CertDuplicateCertificateChain
-CRYPT32.dll!CertDuplicateCertificateContext
-CRYPT32.dll!CertDuplicateCRLContext
-CRYPT32.dll!CertDuplicateCTLContext
-CRYPT32.dll!CertDuplicateStore
-CRYPT32.dll!CertEnumCertificateContextProperties
-CRYPT32.dll!CertEnumCertificatesInStore
-CRYPT32.dll!CertEnumCRLContextProperties
-CRYPT32.dll!CertEnumCRLsInStore
-CRYPT32.dll!CertEnumCTLContextProperties
-CRYPT32.dll!CertEnumCTLsInStore
-CRYPT32.dll!CertEnumPhysicalStore
-CRYPT32.dll!CertEnumSystemStore
-CRYPT32.dll!CertEnumSystemStoreLocation
-CRYPT32.dll!CertFindAttribute
-CRYPT32.dll!CertFindCertificateInCRL
-CRYPT32.dll!CertFindCertificateInStore
-CRYPT32.dll!CertFindCRLInStore
-CRYPT32.dll!CertFindCTLInStore
-CRYPT32.dll!CertFindExtension
-CRYPT32.dll!CertFindRDNAttr
-CRYPT32.dll!CertFindSubjectInCTL
-CRYPT32.dll!CertFreeCertificateChain
-CRYPT32.dll!CertFreeCertificateChainEngine
-CRYPT32.dll!CertFreeCertificateChainList
-CRYPT32.dll!CertFreeCertificateContext
-CRYPT32.dll!CertFreeCRLContext
-CRYPT32.dll!CertFreeCTLContext
-CRYPT32.dll!CertGetCertificateChain
-CRYPT32.dll!CertGetCertificateContextProperty
-CRYPT32.dll!CertGetCRLContextProperty
-CRYPT32.dll!CertGetCRLFromStore
-CRYPT32.dll!CertGetCTLContextProperty
-CRYPT32.dll!CertGetEnhancedKeyUsage
-CRYPT32.dll!CertGetIntendedKeyUsage
-CRYPT32.dll!CertGetIssuerCertificateFromStore
-CRYPT32.dll!CertGetNameStringA
-CRYPT32.dll!CertGetNameStringW
-CRYPT32.dll!CertGetPublicKeyLength
-CRYPT32.dll!CertGetStoreProperty
-CRYPT32.dll!CertGetSubjectCertificateFromStore
-CRYPT32.dll!CertGetValidUsages
-CRYPT32.dll!CertIsValidCRLForCertificate
-CRYPT32.dll!CertNameToStrA
-CRYPT32.dll!CertNameToStrW
-CRYPT32.dll!CertOpenStore
-CRYPT32.dll!CertRDNValueToStrA
-CRYPT32.dll!CertRDNValueToStrW
-CRYPT32.dll!CertRemoveStoreFromCollection
-CRYPT32.dll!CertResyncCertificateChainEngine
-CRYPT32.dll!CertSaveStore
-CRYPT32.dll!CertSelectCertificateChains
-CRYPT32.dll!CertSerializeCertificateStoreElement
-CRYPT32.dll!CertSerializeCRLStoreElement
-CRYPT32.dll!CertSerializeCTLStoreElement
-CRYPT32.dll!CertSetCertificateContextProperty
-CRYPT32.dll!CertSetCRLContextProperty
-CRYPT32.dll!CertSetCTLContextProperty
-CRYPT32.dll!CertSetStoreProperty
-CRYPT32.dll!CertStrToNameA
-CRYPT32.dll!CertStrToNameW
-CRYPT32.dll!CertVerifyCertificateChainPolicy
-CRYPT32.dll!CertVerifySubjectCertificateContext
-CRYPT32.dll!CertVerifyTimeValidity
-CRYPT32.dll!CryptAcquireCertificatePrivateKey
-CRYPT32.dll!CryptDecodeObject
-CRYPT32.dll!CryptDecodeObjectEx
-CRYPT32.dll!CryptEncodeObject
-CRYPT32.dll!CryptEncodeObjectEx
-CRYPT32.dll!CryptEnumOIDFunction
-CRYPT32.dll!CryptEnumOIDInfo
-CRYPT32.dll!CryptFindLocalizedName
-CRYPT32.dll!CryptFindOIDInfo
-CRYPT32.dll!CryptFormatObject
-CRYPT32.dll!CryptFreeOIDFunctionAddress
-CRYPT32.dll!CryptGetDefaultOIDDllList
-CRYPT32.dll!CryptGetDefaultOIDFunctionAddress
-CRYPT32.dll!CryptGetOIDFunctionAddress
-CRYPT32.dll!CryptGetOIDFunctionValue
-CRYPT32.dll!CryptHashPublicKeyInfo
-CRYPT32.dll!CryptInitOIDFunctionSet
-CRYPT32.dll!CryptInstallOIDFunctionAddress
-CRYPT32.dll!CryptMsgCalculateEncodedLength
-CRYPT32.dll!CryptMsgClose
-CRYPT32.dll!CryptMsgControl
-CRYPT32.dll!CryptMsgCountersign
-CRYPT32.dll!CryptMsgCountersignEncoded
-CRYPT32.dll!CryptMsgDuplicate
-CRYPT32.dll!CryptMsgGetAndVerifySigner
-CRYPT32.dll!CryptMsgGetParam
-CRYPT32.dll!CryptMsgOpenToDecode
-CRYPT32.dll!CryptMsgOpenToEncode
-CRYPT32.dll!CryptMsgUpdate
-CRYPT32.dll!CryptMsgVerifyCountersignatureEncoded
-CRYPT32.dll!CryptMsgVerifyCountersignatureEncodedEx
-CRYPT32.dll!CryptProtectData
-CRYPT32.dll!CryptQueryObject
-CRYPT32.dll!CryptRetrieveTimeStamp
-CRYPT32.dll!CryptUnprotectData
-CRYPT32.dll!CryptVerifyTimeStampSignature
-CRYPT32.dll!PFXExportCertStore
-CRYPT32.dll!PFXExportCertStoreEx
-CRYPT32.dll!PFXImportCertStore
-CRYPT32.dll!PFXIsPFXBlob
-CRYPT32.dll!PFXVerifyPassword
-d2d1.dll!D2D1ComputeMaximumScaleFactor
-d2d1.dll!D2D1ConvertColorSpace
-d2d1.dll!D2D1CreateDevice
-d2d1.dll!D2D1CreateDeviceContext
-d2d1.dll!D2D1CreateFactory
-d2d1.dll!D2D1GetGradientMeshInteriorPointsFromCoonsPatch
-d2d1.dll!D2D1InvertMatrix
-d2d1.dll!D2D1IsMatrixInvertible
-d2d1.dll!D2D1MakeRotateMatrix
-d2d1.dll!D2D1MakeSkewMatrix
-d2d1.dll!D2D1SinCos
-d2d1.dll!D2D1Tan
-d2d1.dll!D2D1Vec3Length
-d3d11.dll!CreateDirect3D11DeviceFromDXGIDevice
-d3d11.dll!CreateDirect3D11SurfaceFromDXGISurface
-d3d11.dll!D3D11CreateDevice
-d3d11.dll!D3D11On12CreateDevice
-d3d12.dll!D3D12CreateDevice
-d3d12.dll!D3D12CreateRootSignatureDeserializer
-d3d12.dll!D3D12SerializeRootSignature
-D3DCOMPILER_47.dll!D3DCompile
-D3DCOMPILER_47.dll!D3DCompile2
-D3DCOMPILER_47.dll!D3DCompileFromFile
-D3DCOMPILER_47.dll!D3DCompressShaders
-D3DCOMPILER_47.dll!D3DCreateBlob
-D3DCOMPILER_47.dll!D3DCreateFunctionLinkingGraph
-D3DCOMPILER_47.dll!D3DCreateLinker
-D3DCOMPILER_47.dll!D3DDecompressShaders
-D3DCOMPILER_47.dll!D3DDisassemble
-D3DCOMPILER_47.dll!D3DDisassemble11Trace
-D3DCOMPILER_47.dll!D3DDisassembleRegion
-D3DCOMPILER_47.dll!D3DGetBlobPart
-D3DCOMPILER_47.dll!D3DGetDebugInfo
-D3DCOMPILER_47.dll!D3DGetInputAndOutputSignatureBlob
-D3DCOMPILER_47.dll!D3DGetInputSignatureBlob
-D3DCOMPILER_47.dll!D3DGetOutputSignatureBlob
-D3DCOMPILER_47.dll!D3DGetTraceInstructionOffsets
-D3DCOMPILER_47.dll!D3DLoadModule
-D3DCOMPILER_47.dll!D3DPreprocess
-D3DCOMPILER_47.dll!D3DReadFileToBlob
-D3DCOMPILER_47.dll!D3DReflect
-D3DCOMPILER_47.dll!D3DReflectLibrary
-D3DCOMPILER_47.dll!D3DSetBlobPart
-D3DCOMPILER_47.dll!D3DStripShader
-D3DCOMPILER_47.dll!D3DWriteBlobToFile
-deviceaccess.dll!CreateDeviceAccessInstance
-dhcpcsvc.DLL!DhcpCApiCleanup
-dhcpcsvc.DLL!DhcpCApiInitialize
-dhcpcsvc.DLL!DhcpRequestParams
-dhcpcsvc6.DLL!Dhcpv6CApiCleanup
-dhcpcsvc6.DLL!Dhcpv6CApiInitialize
-dhcpcsvc6.DLL!Dhcpv6RequestParams
-DWrite.dll!DWriteCreateFactory
-dxgi.dll!CreateDXGIFactory1
-dxgi.dll!CreateDXGIFactory2
-ESENT.dll!JetAddColumnW
-ESENT.dll!JetAttachDatabase2W
-ESENT.dll!JetBackupInstanceW
-ESENT.dll!JetBeginSessionW
-ESENT.dll!JetBeginTransaction3
-ESENT.dll!JetCloseDatabase
-ESENT.dll!JetCloseTable
-ESENT.dll!JetCommitTransaction
-ESENT.dll!JetCommitTransaction2
-ESENT.dll!JetCreateDatabase2W
-ESENT.dll!JetCreateIndex4W
-ESENT.dll!JetCreateInstance2W
-ESENT.dll!JetCreateTableColumnIndex4W
-ESENT.dll!JetDefragment2W
-ESENT.dll!JetDelete
-ESENT.dll!JetDeleteColumn2W
-ESENT.dll!JetDeleteIndexW
-ESENT.dll!JetDeleteTableW
-ESENT.dll!JetDetachDatabase2W
-ESENT.dll!JetEndSession
-ESENT.dll!JetEnumerateColumns
-ESENT.dll!JetEscrowUpdate
-ESENT.dll!JetGetBookmark
-ESENT.dll!JetGetColumnInfoW
-ESENT.dll!JetGetCurrentIndexW
-ESENT.dll!JetGetDatabaseFileInfoW
-ESENT.dll!JetGetDatabaseInfoW
-ESENT.dll!JetGetErrorInfoW
-ESENT.dll!JetGetIndexInfoW
-ESENT.dll!JetGetObjectInfoW
-ESENT.dll!JetGetRecordPosition
-ESENT.dll!JetGetSecondaryIndexBookmark
-ESENT.dll!JetGetSessionParameter
-ESENT.dll!JetGetSystemParameterW
-ESENT.dll!JetGetTableColumnInfoW
-ESENT.dll!JetGetTableIndexInfoW
-ESENT.dll!JetGetTableInfoW
-ESENT.dll!JetGetThreadStats
-ESENT.dll!JetGotoBookmark
-ESENT.dll!JetGotoPosition
-ESENT.dll!JetGotoSecondaryIndexBookmark
-ESENT.dll!JetIndexRecordCount
-ESENT.dll!JetInit3W
-ESENT.dll!JetIntersectIndexes
-ESENT.dll!JetMakeKey
-ESENT.dll!JetMove
-ESENT.dll!JetOpenDatabaseW
-ESENT.dll!JetOpenTableW
-ESENT.dll!JetOpenTemporaryTable2
-ESENT.dll!JetOpenTempTable3
-ESENT.dll!JetPrepareUpdate
-ESENT.dll!JetPrereadIndexRanges
-ESENT.dll!JetPrereadKeys
-ESENT.dll!JetRegisterCallback
-ESENT.dll!JetRenameColumnW
-ESENT.dll!JetRenameTableW
-ESENT.dll!JetResetSessionContext
-ESENT.dll!JetResetTableSequential
-ESENT.dll!JetResizeDatabase
-ESENT.dll!JetRestoreInstanceW
-ESENT.dll!JetRetrieveColumn
-ESENT.dll!JetRetrieveColumns
-ESENT.dll!JetRetrieveKey
-ESENT.dll!JetRollback
-ESENT.dll!JetSeek
-ESENT.dll!JetSetColumn
-ESENT.dll!JetSetColumns
-ESENT.dll!JetSetCurrentIndex4W
-ESENT.dll!JetSetCursorFilter
-ESENT.dll!JetSetIndexRange
-ESENT.dll!JetSetSessionContext
-ESENT.dll!JetSetSessionParameter
-ESENT.dll!JetSetSystemParameterW
-ESENT.dll!JetSetTableSequential
-ESENT.dll!JetStopBackupInstance
-ESENT.dll!JetStopServiceInstance2
-ESENT.dll!JetTerm2
-ESENT.dll!JetUnregisterCallback
-ESENT.dll!JetUpdate2
-HrtfApo.dll!CreateHrtfApo
-MF.dll!MFCreateAggregateSource
-MF.dll!MFCreateProtectedEnvironmentAccess
-MF.dll!MFGetLocalId
-MF.dll!MFGetService
-MF.dll!MFGetSystemId
-MF.dll!MFLoadSignedLibrary
-MFPlat.DLL!MFAllocateSerialWorkQueue
-MFPlat.DLL!MFCancelWorkItem
-MFPlat.DLL!MFCopyImage
-MFPlat.DLL!MFCreate2DMediaBuffer
-MFPlat.DLL!MFCreateAlignedMemoryBuffer
-MFPlat.DLL!MFCreateAsyncResult
-MFPlat.DLL!MFCreateAttributes
-MFPlat.DLL!MFCreateCollection
-MFPlat.DLL!MFCreateContentDecryptorContext
-MFPlat.DLL!MFCreateContentProtectionDevice
-MFPlat.DLL!MFCreateDXGIDeviceManager
-MFPlat.DLL!MFCreateDXGISurfaceBuffer
-MFPlat.DLL!MFCreateEventQueue
-MFPlat.DLL!MFCreateMediaBufferFromMediaType
-MFPlat.DLL!MFCreateMediaBufferWrapper
-MFPlat.DLL!MFCreateMediaEvent
-MFPlat.DLL!MFCreateMediaExtensionActivate
-MFPlat.DLL!MFCreateMediaType
-MFPlat.DLL!MFCreateMediaTypeFromProperties
-MFPlat.DLL!MFCreateMemoryBuffer
-MFPlat.DLL!MFCreateMFByteStreamOnStreamEx
-MFPlat.DLL!MFCreatePresentationDescriptor
-MFPlat.DLL!MFCreatePropertiesFromMediaType
-MFPlat.DLL!MFCreateSample
-MFPlat.DLL!MFCreateSourceResolver
-MFPlat.DLL!MFCreateStreamDescriptor
-MFPlat.DLL!MFCreateStreamOnMFByteStreamEx
-MFPlat.DLL!MFCreateTrackedSample
-MFPlat.DLL!MFCreateVideoSampleAllocatorEx
-MFPlat.DLL!MFCreateWaveFormatExFromMFMediaType
-MFPlat.DLL!MFDeserializeAttributesFromStream
-MFPlat.DLL!MFGetAttributesAsBlob
-MFPlat.DLL!MFGetAttributesAsBlobSize
-MFPlat.DLL!MFGetSystemTime
-MFPlat.DLL!MFInitAttributesFromBlob
-MFPlat.DLL!MFInitMediaTypeFromWaveFormatEx
-MFPlat.DLL!MFInvokeCallback
-MFPlat.DLL!MFIsContentProtectionDeviceSupported
-MFPlat.DLL!MFllMulDiv
-MFPlat.DLL!MFLockDXGIDeviceManager
-MFPlat.DLL!MFLockPlatform
-MFPlat.DLL!MFLockSharedWorkQueue
-MFPlat.DLL!MFLockWorkQueue
-MFPlat.DLL!MFPutWaitingWorkItem
-MFPlat.DLL!MFPutWorkItem2
-MFPlat.DLL!MFPutWorkItemEx2
-MFPlat.DLL!MFSerializeAttributesToStream
-MFPlat.DLL!MFShutdown
-MFPlat.DLL!MFStartup
-MFPlat.DLL!MFUnlockDXGIDeviceManager
-MFPlat.DLL!MFUnlockPlatform
-MFPlat.DLL!MFUnlockWorkQueue
-MFPlat.DLL!MFUnwrapMediaType
-MFPlat.DLL!MFWrapMediaType
-MFReadWrite.dll!MFCreateSinkWriterFromMediaSink
-MFReadWrite.dll!MFCreateSinkWriterFromURL
-MFReadWrite.dll!MFCreateSourceReaderFromByteStream
-MFReadWrite.dll!MFCreateSourceReaderFromMediaSource
-MFReadWrite.dll!MFCreateSourceReaderFromURL
-MMDevAPI.DLL!ActivateAudioInterfaceAsync
-MSAJApi.dll!alljoyn_aboutdata_create
-MSAJApi.dll!alljoyn_aboutdata_create_empty
-MSAJApi.dll!alljoyn_aboutdata_create_full
-MSAJApi.dll!alljoyn_aboutdata_createfrommsgarg
-MSAJApi.dll!alljoyn_aboutdata_destroy
-MSAJApi.dll!alljoyn_aboutdata_getaboutdata
-MSAJApi.dll!alljoyn_aboutdata_getajsoftwareversion
-MSAJApi.dll!alljoyn_aboutdata_getannouncedaboutdata
-MSAJApi.dll!alljoyn_aboutdata_getappid
-MSAJApi.dll!alljoyn_aboutdata_getappname
-MSAJApi.dll!alljoyn_aboutdata_getdateofmanufacture
-MSAJApi.dll!alljoyn_aboutdata_getdefaultlanguage
-MSAJApi.dll!alljoyn_aboutdata_getdescription
-MSAJApi.dll!alljoyn_aboutdata_getdeviceid
-MSAJApi.dll!alljoyn_aboutdata_getdevicename
-MSAJApi.dll!alljoyn_aboutdata_getfield
-MSAJApi.dll!alljoyn_aboutdata_getfields
-MSAJApi.dll!alljoyn_aboutdata_getfieldsignature
-MSAJApi.dll!alljoyn_aboutdata_gethardwareversion
-MSAJApi.dll!alljoyn_aboutdata_getmanufacturer
-MSAJApi.dll!alljoyn_aboutdata_getmodelnumber
-MSAJApi.dll!alljoyn_aboutdata_getsoftwareversion
-MSAJApi.dll!alljoyn_aboutdata_getsupportedlanguages
-MSAJApi.dll!alljoyn_aboutdata_getsupporturl
-MSAJApi.dll!alljoyn_aboutdata_isfieldannounced
-MSAJApi.dll!alljoyn_aboutdata_isfieldlocalized
-MSAJApi.dll!alljoyn_aboutdata_isfieldrequired
-MSAJApi.dll!alljoyn_aboutdata_isvalid
-MSAJApi.dll!alljoyn_aboutdata_setappid
-MSAJApi.dll!alljoyn_aboutdata_setappid_fromstring
-MSAJApi.dll!alljoyn_aboutdata_setappname
-MSAJApi.dll!alljoyn_aboutdata_setdateofmanufacture
-MSAJApi.dll!alljoyn_aboutdata_setdefaultlanguage
-MSAJApi.dll!alljoyn_aboutdata_setdescription
-MSAJApi.dll!alljoyn_aboutdata_setdeviceid
-MSAJApi.dll!alljoyn_aboutdata_setdevicename
-MSAJApi.dll!alljoyn_aboutdata_setfield
-MSAJApi.dll!alljoyn_aboutdata_sethardwareversion
-MSAJApi.dll!alljoyn_aboutdata_setmanufacturer
-MSAJApi.dll!alljoyn_aboutdata_setmodelnumber
-MSAJApi.dll!alljoyn_aboutdata_setsoftwareversion
-MSAJApi.dll!alljoyn_aboutdata_setsupportedlanguage
-MSAJApi.dll!alljoyn_aboutdata_setsupporturl
-MSAJApi.dll!alljoyn_aboutdatalistener_create
-MSAJApi.dll!alljoyn_aboutdatalistener_destroy
-MSAJApi.dll!alljoyn_abouticon_clear
-MSAJApi.dll!alljoyn_abouticon_create
-MSAJApi.dll!alljoyn_abouticon_destroy
-MSAJApi.dll!alljoyn_abouticon_setcontent
-MSAJApi.dll!alljoyn_abouticon_setcontent_frommsgarg
-MSAJApi.dll!alljoyn_abouticon_seturl
-MSAJApi.dll!alljoyn_abouticonobj_create
-MSAJApi.dll!alljoyn_abouticonobj_destroy
-MSAJApi.dll!alljoyn_abouticonproxy_create
-MSAJApi.dll!alljoyn_abouticonproxy_destroy
-MSAJApi.dll!alljoyn_abouticonproxy_geticon
-MSAJApi.dll!alljoyn_abouticonproxy_getversion
-MSAJApi.dll!alljoyn_aboutlistener_create
-MSAJApi.dll!alljoyn_aboutlistener_destroy
-MSAJApi.dll!alljoyn_aboutobj_announce
-MSAJApi.dll!alljoyn_aboutobj_announce_using_datalistener
-MSAJApi.dll!alljoyn_aboutobj_create
-MSAJApi.dll!alljoyn_aboutobj_destroy
-MSAJApi.dll!alljoyn_aboutobj_unannounce
-MSAJApi.dll!alljoyn_aboutobjectdescription_clear
-MSAJApi.dll!alljoyn_aboutobjectdescription_create
-MSAJApi.dll!alljoyn_aboutobjectdescription_create_full
-MSAJApi.dll!alljoyn_aboutobjectdescription_createfrommsgarg
-MSAJApi.dll!alljoyn_aboutobjectdescription_destroy
-MSAJApi.dll!alljoyn_aboutobjectdescription_getinterfacepaths
-MSAJApi.dll!alljoyn_aboutobjectdescription_getinterfaces
-MSAJApi.dll!alljoyn_aboutobjectdescription_getmsgarg
-MSAJApi.dll!alljoyn_aboutobjectdescription_getpaths
-MSAJApi.dll!alljoyn_aboutobjectdescription_hasinterface
-MSAJApi.dll!alljoyn_aboutobjectdescription_hasinterfaceatpath
-MSAJApi.dll!alljoyn_aboutobjectdescription_haspath
-MSAJApi.dll!alljoyn_aboutproxy_create
-MSAJApi.dll!alljoyn_aboutproxy_destroy
-MSAJApi.dll!alljoyn_aboutproxy_getaboutdata
-MSAJApi.dll!alljoyn_aboutproxy_getobjectdescription
-MSAJApi.dll!alljoyn_aboutproxy_getversion
-MSAJApi.dll!alljoyn_authlistener_create
-MSAJApi.dll!alljoyn_authlistener_destroy
-MSAJApi.dll!alljoyn_authlistener_requestcredentialsresponse
-MSAJApi.dll!alljoyn_authlistener_verifycredentialsresponse
-MSAJApi.dll!alljoyn_authlistenerasync_create
-MSAJApi.dll!alljoyn_authlistenerasync_destroy
-MSAJApi.dll!alljoyn_busattachment_addlogonentry
-MSAJApi.dll!alljoyn_busattachment_addmatch
-MSAJApi.dll!alljoyn_busattachment_advertisename
-MSAJApi.dll!alljoyn_busattachment_bindsessionport
-MSAJApi.dll!alljoyn_busattachment_canceladvertisename
-MSAJApi.dll!alljoyn_busattachment_cancelfindadvertisedname
-MSAJApi.dll!alljoyn_busattachment_cancelfindadvertisednamebytransport
-MSAJApi.dll!alljoyn_busattachment_cancelwhoimplements_interface
-MSAJApi.dll!alljoyn_busattachment_cancelwhoimplements_interfaces
-MSAJApi.dll!alljoyn_busattachment_clearkeys
-MSAJApi.dll!alljoyn_busattachment_clearkeystore
-MSAJApi.dll!alljoyn_busattachment_connect
-MSAJApi.dll!alljoyn_busattachment_create
-MSAJApi.dll!alljoyn_busattachment_create_concurrency
-MSAJApi.dll!alljoyn_busattachment_createinterface
-MSAJApi.dll!alljoyn_busattachment_createinterface_secure
-MSAJApi.dll!alljoyn_busattachment_createinterfacesfromxml
-MSAJApi.dll!alljoyn_busattachment_deleteinterface
-MSAJApi.dll!alljoyn_busattachment_destroy
-MSAJApi.dll!alljoyn_busattachment_disconnect
-MSAJApi.dll!alljoyn_busattachment_enableconcurrentcallbacks
-MSAJApi.dll!alljoyn_busattachment_enablepeersecurity
-MSAJApi.dll!alljoyn_busattachment_findadvertisedname
-MSAJApi.dll!alljoyn_busattachment_findadvertisednamebytransport
-MSAJApi.dll!alljoyn_busattachment_getalljoyndebugobj
-MSAJApi.dll!alljoyn_busattachment_getalljoynproxyobj
-MSAJApi.dll!alljoyn_busattachment_getconcurrency
-MSAJApi.dll!alljoyn_busattachment_getconnectspec
-MSAJApi.dll!alljoyn_busattachment_getdbusproxyobj
-MSAJApi.dll!alljoyn_busattachment_getglobalguidstring
-MSAJApi.dll!alljoyn_busattachment_getinterface
-MSAJApi.dll!alljoyn_busattachment_getinterfaces
-MSAJApi.dll!alljoyn_busattachment_getkeyexpiration
-MSAJApi.dll!alljoyn_busattachment_getpeerguid
-MSAJApi.dll!alljoyn_busattachment_gettimestamp
-MSAJApi.dll!alljoyn_busattachment_getuniquename
-MSAJApi.dll!alljoyn_busattachment_isconnected
-MSAJApi.dll!alljoyn_busattachment_ispeersecurityenabled
-MSAJApi.dll!alljoyn_busattachment_isstarted
-MSAJApi.dll!alljoyn_busattachment_isstopping
-MSAJApi.dll!alljoyn_busattachment_join
-MSAJApi.dll!alljoyn_busattachment_joinsession
-MSAJApi.dll!alljoyn_busattachment_joinsessionasync
-MSAJApi.dll!alljoyn_busattachment_leavesession
-MSAJApi.dll!alljoyn_busattachment_namehasowner
-MSAJApi.dll!alljoyn_busattachment_ping
-MSAJApi.dll!alljoyn_busattachment_registeraboutlistener
-MSAJApi.dll!alljoyn_busattachment_registerbuslistener
-MSAJApi.dll!alljoyn_busattachment_registerbusobject
-MSAJApi.dll!alljoyn_busattachment_registerbusobject_secure
-MSAJApi.dll!alljoyn_busattachment_registerkeystorelistener
-MSAJApi.dll!alljoyn_busattachment_registersignalhandler
-MSAJApi.dll!alljoyn_busattachment_registersignalhandlerwithrule
-MSAJApi.dll!alljoyn_busattachment_releasename
-MSAJApi.dll!alljoyn_busattachment_reloadkeystore
-MSAJApi.dll!alljoyn_busattachment_removematch
-MSAJApi.dll!alljoyn_busattachment_removesessionmember
-MSAJApi.dll!alljoyn_busattachment_requestname
-MSAJApi.dll!alljoyn_busattachment_setdaemondebug
-MSAJApi.dll!alljoyn_busattachment_setkeyexpiration
-MSAJApi.dll!alljoyn_busattachment_setlinktimeout
-MSAJApi.dll!alljoyn_busattachment_setlinktimeoutasync
-MSAJApi.dll!alljoyn_busattachment_setsessionlistener
-MSAJApi.dll!alljoyn_busattachment_start
-MSAJApi.dll!alljoyn_busattachment_stop
-MSAJApi.dll!alljoyn_busattachment_unbindsessionport
-MSAJApi.dll!alljoyn_busattachment_unregisteraboutlistener
-MSAJApi.dll!alljoyn_busattachment_unregisterallaboutlisteners
-MSAJApi.dll!alljoyn_busattachment_unregisterallhandlers
-MSAJApi.dll!alljoyn_busattachment_unregisterbuslistener
-MSAJApi.dll!alljoyn_busattachment_unregisterbusobject
-MSAJApi.dll!alljoyn_busattachment_unregistersignalhandler
-MSAJApi.dll!alljoyn_busattachment_unregistersignalhandlerwithrule
-MSAJApi.dll!alljoyn_busattachment_whoimplements_interface
-MSAJApi.dll!alljoyn_busattachment_whoimplements_interfaces
-MSAJApi.dll!alljoyn_buslistener_create
-MSAJApi.dll!alljoyn_buslistener_destroy
-MSAJApi.dll!alljoyn_busobject_addinterface
-MSAJApi.dll!alljoyn_busobject_addinterface_announced
-MSAJApi.dll!alljoyn_busobject_addmethodhandler
-MSAJApi.dll!alljoyn_busobject_addmethodhandlers
-MSAJApi.dll!alljoyn_busobject_cancelsessionlessmessage
-MSAJApi.dll!alljoyn_busobject_cancelsessionlessmessage_serial
-MSAJApi.dll!alljoyn_busobject_create
-MSAJApi.dll!alljoyn_busobject_destroy
-MSAJApi.dll!alljoyn_busobject_emitpropertieschanged
-MSAJApi.dll!alljoyn_busobject_emitpropertychanged
-MSAJApi.dll!alljoyn_busobject_getannouncedinterfacenames
-MSAJApi.dll!alljoyn_busobject_getbusattachment
-MSAJApi.dll!alljoyn_busobject_getname
-MSAJApi.dll!alljoyn_busobject_getpath
-MSAJApi.dll!alljoyn_busobject_issecure
-MSAJApi.dll!alljoyn_busobject_methodreply_args
-MSAJApi.dll!alljoyn_busobject_methodreply_err
-MSAJApi.dll!alljoyn_busobject_methodreply_status
-MSAJApi.dll!alljoyn_busobject_setannounceflag
-MSAJApi.dll!alljoyn_busobject_signal
-MSAJApi.dll!alljoyn_credentials_clear
-MSAJApi.dll!alljoyn_credentials_create
-MSAJApi.dll!alljoyn_credentials_destroy
-MSAJApi.dll!alljoyn_credentials_getcertchain
-MSAJApi.dll!alljoyn_credentials_getexpiration
-MSAJApi.dll!alljoyn_credentials_getlogonentry
-MSAJApi.dll!alljoyn_credentials_getpassword
-MSAJApi.dll!alljoyn_credentials_getprivateKey
-MSAJApi.dll!alljoyn_credentials_getusername
-MSAJApi.dll!alljoyn_credentials_isset
-MSAJApi.dll!alljoyn_credentials_setcertchain
-MSAJApi.dll!alljoyn_credentials_setexpiration
-MSAJApi.dll!alljoyn_credentials_setlogonentry
-MSAJApi.dll!alljoyn_credentials_setpassword
-MSAJApi.dll!alljoyn_credentials_setprivatekey
-MSAJApi.dll!alljoyn_credentials_setusername
-MSAJApi.dll!alljoyn_getbuildinfo
-MSAJApi.dll!alljoyn_getnumericversion
-MSAJApi.dll!alljoyn_getversion
-MSAJApi.dll!alljoyn_init
-MSAJApi.dll!alljoyn_interfacedescription_activate
-MSAJApi.dll!alljoyn_interfacedescription_addannotation
-MSAJApi.dll!alljoyn_interfacedescription_addmember
-MSAJApi.dll!alljoyn_interfacedescription_addmemberannotation
-MSAJApi.dll!alljoyn_interfacedescription_addmethod
-MSAJApi.dll!alljoyn_interfacedescription_addproperty
-MSAJApi.dll!alljoyn_interfacedescription_addpropertyannotation
-MSAJApi.dll!alljoyn_interfacedescription_addsignal
-MSAJApi.dll!alljoyn_interfacedescription_eql
-MSAJApi.dll!alljoyn_interfacedescription_getannotation
-MSAJApi.dll!alljoyn_interfacedescription_getannotationatindex
-MSAJApi.dll!alljoyn_interfacedescription_getannotationscount
-MSAJApi.dll!alljoyn_interfacedescription_getmember
-MSAJApi.dll!alljoyn_interfacedescription_getmemberannotation
-MSAJApi.dll!alljoyn_interfacedescription_getmembers
-MSAJApi.dll!alljoyn_interfacedescription_getmethod
-MSAJApi.dll!alljoyn_interfacedescription_getname
-MSAJApi.dll!alljoyn_interfacedescription_getproperties
-MSAJApi.dll!alljoyn_interfacedescription_getproperty
-MSAJApi.dll!alljoyn_interfacedescription_getpropertyannotation
-MSAJApi.dll!alljoyn_interfacedescription_getsecuritypolicy
-MSAJApi.dll!alljoyn_interfacedescription_getsignal
-MSAJApi.dll!alljoyn_interfacedescription_hasmember
-MSAJApi.dll!alljoyn_interfacedescription_hasproperties
-MSAJApi.dll!alljoyn_interfacedescription_hasproperty
-MSAJApi.dll!alljoyn_interfacedescription_introspect
-MSAJApi.dll!alljoyn_interfacedescription_issecure
-MSAJApi.dll!alljoyn_interfacedescription_member_eql
-MSAJApi.dll!alljoyn_interfacedescription_member_getannotation
-MSAJApi.dll!alljoyn_interfacedescription_member_getannotationatindex
-MSAJApi.dll!alljoyn_interfacedescription_member_getannotationscount
-MSAJApi.dll!alljoyn_interfacedescription_property_eql
-MSAJApi.dll!alljoyn_interfacedescription_property_getannotation
-MSAJApi.dll!alljoyn_interfacedescription_property_getannotationatindex
-MSAJApi.dll!alljoyn_interfacedescription_property_getannotationscount
-MSAJApi.dll!alljoyn_keystorelistener_create
-MSAJApi.dll!alljoyn_keystorelistener_destroy
-MSAJApi.dll!alljoyn_keystorelistener_getkeys
-MSAJApi.dll!alljoyn_keystorelistener_putkeys
-MSAJApi.dll!alljoyn_message_create
-MSAJApi.dll!alljoyn_message_description
-MSAJApi.dll!alljoyn_message_destroy
-MSAJApi.dll!alljoyn_message_eql
-MSAJApi.dll!alljoyn_message_getarg
-MSAJApi.dll!alljoyn_message_getargs
-MSAJApi.dll!alljoyn_message_getauthmechanism
-MSAJApi.dll!alljoyn_message_getcallserial
-MSAJApi.dll!alljoyn_message_getcompressiontoken
-MSAJApi.dll!alljoyn_message_getdestination
-MSAJApi.dll!alljoyn_message_geterrorname
-MSAJApi.dll!alljoyn_message_getflags
-MSAJApi.dll!alljoyn_message_getinterface
-MSAJApi.dll!alljoyn_message_getmembername
-MSAJApi.dll!alljoyn_message_getobjectpath
-MSAJApi.dll!alljoyn_message_getreceiveendpointname
-MSAJApi.dll!alljoyn_message_getreplyserial
-MSAJApi.dll!alljoyn_message_getsender
-MSAJApi.dll!alljoyn_message_getsessionid
-MSAJApi.dll!alljoyn_message_getsignature
-MSAJApi.dll!alljoyn_message_gettimestamp
-MSAJApi.dll!alljoyn_message_gettype
-MSAJApi.dll!alljoyn_message_isbroadcastsignal
-MSAJApi.dll!alljoyn_message_isencrypted
-MSAJApi.dll!alljoyn_message_isexpired
-MSAJApi.dll!alljoyn_message_isglobalbroadcast
-MSAJApi.dll!alljoyn_message_issessionless
-MSAJApi.dll!alljoyn_message_isunreliable
-MSAJApi.dll!alljoyn_message_parseargs
-MSAJApi.dll!alljoyn_message_setendianess
-MSAJApi.dll!alljoyn_message_tostring
-MSAJApi.dll!alljoyn_msgarg_array_create
-MSAJApi.dll!alljoyn_msgarg_array_element
-MSAJApi.dll!alljoyn_msgarg_array_get
-MSAJApi.dll!alljoyn_msgarg_array_set
-MSAJApi.dll!alljoyn_msgarg_array_set_offset
-MSAJApi.dll!alljoyn_msgarg_array_signature
-MSAJApi.dll!alljoyn_msgarg_array_tostring
-MSAJApi.dll!alljoyn_msgarg_clear
-MSAJApi.dll!alljoyn_msgarg_clone
-MSAJApi.dll!alljoyn_msgarg_copy
-MSAJApi.dll!alljoyn_msgarg_create
-MSAJApi.dll!alljoyn_msgarg_create_and_set
-MSAJApi.dll!alljoyn_msgarg_destroy
-MSAJApi.dll!alljoyn_msgarg_equal
-MSAJApi.dll!alljoyn_msgarg_get
-MSAJApi.dll!alljoyn_msgarg_get_array_element
-MSAJApi.dll!alljoyn_msgarg_get_array_elementsignature
-MSAJApi.dll!alljoyn_msgarg_get_array_numberofelements
-MSAJApi.dll!alljoyn_msgarg_get_bool
-MSAJApi.dll!alljoyn_msgarg_get_bool_array
-MSAJApi.dll!alljoyn_msgarg_get_double
-MSAJApi.dll!alljoyn_msgarg_get_double_array
-MSAJApi.dll!alljoyn_msgarg_get_int16
-MSAJApi.dll!alljoyn_msgarg_get_int16_array
-MSAJApi.dll!alljoyn_msgarg_get_int32
-MSAJApi.dll!alljoyn_msgarg_get_int32_array
-MSAJApi.dll!alljoyn_msgarg_get_int64
-MSAJApi.dll!alljoyn_msgarg_get_int64_array
-MSAJApi.dll!alljoyn_msgarg_get_objectpath
-MSAJApi.dll!alljoyn_msgarg_get_signature
-MSAJApi.dll!alljoyn_msgarg_get_string
-MSAJApi.dll!alljoyn_msgarg_get_uint16
-MSAJApi.dll!alljoyn_msgarg_get_uint16_array
-MSAJApi.dll!alljoyn_msgarg_get_uint32
-MSAJApi.dll!alljoyn_msgarg_get_uint32_array
-MSAJApi.dll!alljoyn_msgarg_get_uint64
-MSAJApi.dll!alljoyn_msgarg_get_uint64_array
-MSAJApi.dll!alljoyn_msgarg_get_uint8
-MSAJApi.dll!alljoyn_msgarg_get_uint8_array
-MSAJApi.dll!alljoyn_msgarg_get_variant
-MSAJApi.dll!alljoyn_msgarg_get_variant_array
-MSAJApi.dll!alljoyn_msgarg_getdictelement
-MSAJApi.dll!alljoyn_msgarg_getkey
-MSAJApi.dll!alljoyn_msgarg_getmember
-MSAJApi.dll!alljoyn_msgarg_getnummembers
-MSAJApi.dll!alljoyn_msgarg_gettype
-MSAJApi.dll!alljoyn_msgarg_getvalue
-MSAJApi.dll!alljoyn_msgarg_hassignature
-MSAJApi.dll!alljoyn_msgarg_set
-MSAJApi.dll!alljoyn_msgarg_set_and_stabilize
-MSAJApi.dll!alljoyn_msgarg_set_bool
-MSAJApi.dll!alljoyn_msgarg_set_bool_array
-MSAJApi.dll!alljoyn_msgarg_set_double
-MSAJApi.dll!alljoyn_msgarg_set_double_array
-MSAJApi.dll!alljoyn_msgarg_set_int16
-MSAJApi.dll!alljoyn_msgarg_set_int16_array
-MSAJApi.dll!alljoyn_msgarg_set_int32
-MSAJApi.dll!alljoyn_msgarg_set_int32_array
-MSAJApi.dll!alljoyn_msgarg_set_int64
-MSAJApi.dll!alljoyn_msgarg_set_int64_array
-MSAJApi.dll!alljoyn_msgarg_set_objectpath
-MSAJApi.dll!alljoyn_msgarg_set_objectpath_array
-MSAJApi.dll!alljoyn_msgarg_set_signature
-MSAJApi.dll!alljoyn_msgarg_set_signature_array
-MSAJApi.dll!alljoyn_msgarg_set_string
-MSAJApi.dll!alljoyn_msgarg_set_string_array
-MSAJApi.dll!alljoyn_msgarg_set_uint16
-MSAJApi.dll!alljoyn_msgarg_set_uint16_array
-MSAJApi.dll!alljoyn_msgarg_set_uint32
-MSAJApi.dll!alljoyn_msgarg_set_uint32_array
-MSAJApi.dll!alljoyn_msgarg_set_uint64
-MSAJApi.dll!alljoyn_msgarg_set_uint64_array
-MSAJApi.dll!alljoyn_msgarg_set_uint8
-MSAJApi.dll!alljoyn_msgarg_set_uint8_array
-MSAJApi.dll!alljoyn_msgarg_setdictentry
-MSAJApi.dll!alljoyn_msgarg_setstruct
-MSAJApi.dll!alljoyn_msgarg_signature
-MSAJApi.dll!alljoyn_msgarg_stabilize
-MSAJApi.dll!alljoyn_msgarg_tostring
-MSAJApi.dll!alljoyn_observer_create
-MSAJApi.dll!alljoyn_observer_destroy
-MSAJApi.dll!alljoyn_observer_get
-MSAJApi.dll!alljoyn_observer_getfirst
-MSAJApi.dll!alljoyn_observer_getnext
-MSAJApi.dll!alljoyn_observer_registerlistener
-MSAJApi.dll!alljoyn_observer_unregisteralllisteners
-MSAJApi.dll!alljoyn_observer_unregisterlistener
-MSAJApi.dll!alljoyn_observerlistener_create
-MSAJApi.dll!alljoyn_observerlistener_destroy
-MSAJApi.dll!alljoyn_passwordmanager_setcredentials
-MSAJApi.dll!alljoyn_proxybusobject_addchild
-MSAJApi.dll!alljoyn_proxybusobject_addinterface
-MSAJApi.dll!alljoyn_proxybusobject_addinterface_by_name
-MSAJApi.dll!alljoyn_proxybusobject_copy
-MSAJApi.dll!alljoyn_proxybusobject_create
-MSAJApi.dll!alljoyn_proxybusobject_create_secure
-MSAJApi.dll!alljoyn_proxybusobject_destroy
-MSAJApi.dll!alljoyn_proxybusobject_enablepropertycaching
-MSAJApi.dll!alljoyn_proxybusobject_getallproperties
-MSAJApi.dll!alljoyn_proxybusobject_getallpropertiesasync
-MSAJApi.dll!alljoyn_proxybusobject_getchild
-MSAJApi.dll!alljoyn_proxybusobject_getchildren
-MSAJApi.dll!alljoyn_proxybusobject_getinterface
-MSAJApi.dll!alljoyn_proxybusobject_getinterfaces
-MSAJApi.dll!alljoyn_proxybusobject_getpath
-MSAJApi.dll!alljoyn_proxybusobject_getproperty
-MSAJApi.dll!alljoyn_proxybusobject_getpropertyasync
-MSAJApi.dll!alljoyn_proxybusobject_getservicename
-MSAJApi.dll!alljoyn_proxybusobject_getsessionid
-MSAJApi.dll!alljoyn_proxybusobject_getuniquename
-MSAJApi.dll!alljoyn_proxybusobject_implementsinterface
-MSAJApi.dll!alljoyn_proxybusobject_introspectremoteobject
-MSAJApi.dll!alljoyn_proxybusobject_introspectremoteobjectasync
-MSAJApi.dll!alljoyn_proxybusobject_issecure
-MSAJApi.dll!alljoyn_proxybusobject_isvalid
-MSAJApi.dll!alljoyn_proxybusobject_methodcall
-MSAJApi.dll!alljoyn_proxybusobject_methodcall_member
-MSAJApi.dll!alljoyn_proxybusobject_methodcall_member_noreply
-MSAJApi.dll!alljoyn_proxybusobject_methodcall_noreply
-MSAJApi.dll!alljoyn_proxybusobject_methodcallasync
-MSAJApi.dll!alljoyn_proxybusobject_methodcallasync_member
-MSAJApi.dll!alljoyn_proxybusobject_parsexml
-MSAJApi.dll!alljoyn_proxybusobject_ref_create
-MSAJApi.dll!alljoyn_proxybusobject_ref_decref
-MSAJApi.dll!alljoyn_proxybusobject_ref_get
-MSAJApi.dll!alljoyn_proxybusobject_ref_incref
-MSAJApi.dll!alljoyn_proxybusobject_registerpropertieschangedlistener
-MSAJApi.dll!alljoyn_proxybusobject_removechild
-MSAJApi.dll!alljoyn_proxybusobject_secureconnection
-MSAJApi.dll!alljoyn_proxybusobject_secureconnectionasync
-MSAJApi.dll!alljoyn_proxybusobject_setproperty
-MSAJApi.dll!alljoyn_proxybusobject_setpropertyasync
-MSAJApi.dll!alljoyn_proxybusobject_unregisterpropertieschangedlistener
-MSAJApi.dll!alljoyn_sessionlistener_create
-MSAJApi.dll!alljoyn_sessionlistener_destroy
-MSAJApi.dll!alljoyn_sessionopts_cmp
-MSAJApi.dll!alljoyn_sessionopts_create
-MSAJApi.dll!alljoyn_sessionopts_destroy
-MSAJApi.dll!alljoyn_sessionopts_get_multipoint
-MSAJApi.dll!alljoyn_sessionopts_get_proximity
-MSAJApi.dll!alljoyn_sessionopts_get_traffic
-MSAJApi.dll!alljoyn_sessionopts_get_transports
-MSAJApi.dll!alljoyn_sessionopts_iscompatible
-MSAJApi.dll!alljoyn_sessionopts_set_multipoint
-MSAJApi.dll!alljoyn_sessionopts_set_proximity
-MSAJApi.dll!alljoyn_sessionopts_set_traffic
-MSAJApi.dll!alljoyn_sessionopts_set_transports
-MSAJApi.dll!alljoyn_sessionportlistener_create
-MSAJApi.dll!alljoyn_sessionportlistener_destroy
-MSAJApi.dll!alljoyn_shutdown
-MSAJApi.dll!alljoyn_unity_deferred_callbacks_process
-MSAJApi.dll!alljoyn_unity_set_deferred_callback_mainthread_only
-MSAJApi.dll!AllJoynCloseBusHandle
-MSAJApi.dll!AllJoynConnectToBus
-MSAJApi.dll!AllJoynEnumEvents
-MSAJApi.dll!AllJoynEventSelect
-MSAJApi.dll!AllJoynReceiveFromBus
-MSAJApi.dll!AllJoynSendToBus
-MSAJApi.dll!QCC_StatusText
-mscoree.dll!_CorDllMain
-mscoree.dll!_CorExeMain
-mscoree.dll!MetaDataGetDispenser
-MSWSOCK.dll!AcceptEx
-MSWSOCK.dll!GetAcceptExSockaddrs
-MSWSOCK.dll!TransmitFile
-ncrypt.dll!NCryptCreateClaim
-ncrypt.dll!NCryptCreatePersistedKey
-ncrypt.dll!NCryptDecrypt
-ncrypt.dll!NCryptDeleteKey
-ncrypt.dll!NCryptDeriveKey
-ncrypt.dll!NCryptEncrypt
-ncrypt.dll!NCryptEnumAlgorithms
-ncrypt.dll!NCryptEnumKeys
-ncrypt.dll!NCryptExportKey
-ncrypt.dll!NCryptFinalizeKey
-ncrypt.dll!NCryptFreeBuffer
-ncrypt.dll!NCryptFreeObject
-ncrypt.dll!NCryptGetProperty
-ncrypt.dll!NCryptImportKey
-ncrypt.dll!NCryptIsAlgSupported
-ncrypt.dll!NCryptKeyDerivation
-ncrypt.dll!NCryptOpenKey
-ncrypt.dll!NCryptOpenStorageProvider
-ncrypt.dll!NCryptSecretAgreement
-ncrypt.dll!NCryptSetProperty
-ncrypt.dll!NCryptSignHash
-ncrypt.dll!NCryptVerifyClaim
-ncrypt.dll!NCryptVerifySignature
-ntdll.dll!RtlEthernetAddressToStringA
-ntdll.dll!RtlEthernetAddressToStringW
-ntdll.dll!RtlEthernetStringToAddressA
-ntdll.dll!RtlEthernetStringToAddressW
-ntdll.dll!RtlIpv4AddressToStringA
-ntdll.dll!RtlIpv4AddressToStringExA
-ntdll.dll!RtlIpv4AddressToStringExW
-ntdll.dll!RtlIpv4AddressToStringW
-ntdll.dll!RtlIpv4StringToAddressA
-ntdll.dll!RtlIpv4StringToAddressExA
-ntdll.dll!RtlIpv4StringToAddressExW
-ntdll.dll!RtlIpv4StringToAddressW
-ntdll.dll!RtlIpv6AddressToStringA
-ntdll.dll!RtlIpv6AddressToStringExA
-ntdll.dll!RtlIpv6AddressToStringExW
-ntdll.dll!RtlIpv6AddressToStringW
-ntdll.dll!RtlIpv6StringToAddressA
-ntdll.dll!RtlIpv6StringToAddressExA
-ntdll.dll!RtlIpv6StringToAddressExW
-ntdll.dll!RtlIpv6StringToAddressW
-OLEAUT32.dll!BSTR_UserFree
-OLEAUT32.dll!BSTR_UserMarshal
-OLEAUT32.dll!BSTR_UserSize
-OLEAUT32.dll!BSTR_UserUnmarshal
-OLEAUT32.dll!DispInvoke
-OLEAUT32.dll!LPSAFEARRAY_Marshal
-OLEAUT32.dll!LPSAFEARRAY_Size
-OLEAUT32.dll!LPSAFEARRAY_Unmarshal
-OLEAUT32.dll!LPSAFEARRAY_UserFree
-OLEAUT32.dll!LPSAFEARRAY_UserMarshal
-OLEAUT32.dll!LPSAFEARRAY_UserSize
-OLEAUT32.dll!LPSAFEARRAY_UserUnmarshal
-OLEAUT32.dll!SafeArrayAccessData
-OLEAUT32.dll!SafeArrayAllocData
-OLEAUT32.dll!SafeArrayAllocDescriptor
-OLEAUT32.dll!SafeArrayAllocDescriptorEx
-OLEAUT32.dll!SafeArrayCopy
-OLEAUT32.dll!SafeArrayCopyData
-OLEAUT32.dll!SafeArrayCreate
-OLEAUT32.dll!SafeArrayCreateEx
-OLEAUT32.dll!SafeArrayCreateVector
-OLEAUT32.dll!SafeArrayCreateVectorEx
-OLEAUT32.dll!SafeArrayDestroy
-OLEAUT32.dll!SafeArrayDestroyData
-OLEAUT32.dll!SafeArrayDestroyDescriptor
-OLEAUT32.dll!SafeArrayGetDim
-OLEAUT32.dll!SafeArrayGetElement
-OLEAUT32.dll!SafeArrayGetElemsize
-OLEAUT32.dll!SafeArrayGetIID
-OLEAUT32.dll!SafeArrayGetLBound
-OLEAUT32.dll!SafeArrayGetRecordInfo
-OLEAUT32.dll!SafeArrayGetUBound
-OLEAUT32.dll!SafeArrayGetVartype
-OLEAUT32.dll!SafeArrayLock
-OLEAUT32.dll!SafeArrayPtrOfIndex
-OLEAUT32.dll!SafeArrayPutElement
-OLEAUT32.dll!SafeArrayRedim
-OLEAUT32.dll!SafeArraySetIID
-OLEAUT32.dll!SafeArraySetRecordInfo
-OLEAUT32.dll!SafeArrayUnaccessData
-OLEAUT32.dll!SafeArrayUnlock
-OLEAUT32.dll!SysAllocString
-OLEAUT32.dll!SysAllocStringByteLen
-OLEAUT32.dll!SysAllocStringLen
-OLEAUT32.dll!SysFreeString
-OLEAUT32.dll!SysReAllocString
-OLEAUT32.dll!SysReAllocStringLen
-OLEAUT32.dll!SysStringByteLen
-OLEAUT32.dll!SysStringLen
-OLEAUT32.dll!SystemTimeToVariantTime
-OLEAUT32.dll!VarAbs
-OLEAUT32.dll!VarAdd
-OLEAUT32.dll!VarAnd
-OLEAUT32.dll!VarBoolFromCy
-OLEAUT32.dll!VarBoolFromDate
-OLEAUT32.dll!VarBoolFromDec
-OLEAUT32.dll!VarBoolFromDisp
-OLEAUT32.dll!VarBoolFromI1
-OLEAUT32.dll!VarBoolFromI2
-OLEAUT32.dll!VarBoolFromI4
-OLEAUT32.dll!VarBoolFromI8
-OLEAUT32.dll!VarBoolFromR4
-OLEAUT32.dll!VarBoolFromR8
-OLEAUT32.dll!VarBoolFromStr
-OLEAUT32.dll!VarBoolFromUI1
-OLEAUT32.dll!VarBoolFromUI2
-OLEAUT32.dll!VarBoolFromUI4
-OLEAUT32.dll!VarBoolFromUI8
-OLEAUT32.dll!VarBstrCat
-OLEAUT32.dll!VarBstrCmp
-OLEAUT32.dll!VarBstrFromBool
-OLEAUT32.dll!VarBstrFromCy
-OLEAUT32.dll!VarBstrFromDate
-OLEAUT32.dll!VarBstrFromDec
-OLEAUT32.dll!VarBstrFromDisp
-OLEAUT32.dll!VarBstrFromI1
-OLEAUT32.dll!VarBstrFromI2
-OLEAUT32.dll!VarBstrFromI4
-OLEAUT32.dll!VarBstrFromI8
-OLEAUT32.dll!VarBstrFromR4
-OLEAUT32.dll!VarBstrFromR8
-OLEAUT32.dll!VarBstrFromUI1
-OLEAUT32.dll!VarBstrFromUI2
-OLEAUT32.dll!VarBstrFromUI4
-OLEAUT32.dll!VarBstrFromUI8
-OLEAUT32.dll!VarCat
-OLEAUT32.dll!VarCmp
-OLEAUT32.dll!VarCyAbs
-OLEAUT32.dll!VarCyAdd
-OLEAUT32.dll!VarCyCmp
-OLEAUT32.dll!VarCyCmpR8
-OLEAUT32.dll!VarCyFix
-OLEAUT32.dll!VarCyFromBool
-OLEAUT32.dll!VarCyFromDate
-OLEAUT32.dll!VarCyFromDec
-OLEAUT32.dll!VarCyFromDisp
-OLEAUT32.dll!VarCyFromI1
-OLEAUT32.dll!VarCyFromI2
-OLEAUT32.dll!VarCyFromI4
-OLEAUT32.dll!VarCyFromI8
-OLEAUT32.dll!VarCyFromR4
-OLEAUT32.dll!VarCyFromR8
-OLEAUT32.dll!VarCyFromStr
-OLEAUT32.dll!VarCyFromUI1
-OLEAUT32.dll!VarCyFromUI2
-OLEAUT32.dll!VarCyFromUI4
-OLEAUT32.dll!VarCyFromUI8
-OLEAUT32.dll!VarCyInt
-OLEAUT32.dll!VarCyMul
-OLEAUT32.dll!VarCyMulI4
-OLEAUT32.dll!VarCyMulI8
-OLEAUT32.dll!VarCyNeg
-OLEAUT32.dll!VarCyRound
-OLEAUT32.dll!VarCySub
-OLEAUT32.dll!VarDateFromBool
-OLEAUT32.dll!VarDateFromCy
-OLEAUT32.dll!VarDateFromDec
-OLEAUT32.dll!VarDateFromDisp
-OLEAUT32.dll!VarDateFromI1
-OLEAUT32.dll!VarDateFromI2
-OLEAUT32.dll!VarDateFromI4
-OLEAUT32.dll!VarDateFromI8
-OLEAUT32.dll!VarDateFromR4
-OLEAUT32.dll!VarDateFromR8
-OLEAUT32.dll!VarDateFromStr
-OLEAUT32.dll!VarDateFromUdate
-OLEAUT32.dll!VarDateFromUdateEx
-OLEAUT32.dll!VarDateFromUI1
-OLEAUT32.dll!VarDateFromUI2
-OLEAUT32.dll!VarDateFromUI4
-OLEAUT32.dll!VarDateFromUI8
-OLEAUT32.dll!VarDecAbs
-OLEAUT32.dll!VarDecAdd
-OLEAUT32.dll!VarDecCmp
-OLEAUT32.dll!VarDecCmpR8
-OLEAUT32.dll!VarDecDiv
-OLEAUT32.dll!VarDecFix
-OLEAUT32.dll!VarDecFromBool
-OLEAUT32.dll!VarDecFromCy
-OLEAUT32.dll!VarDecFromDate
-OLEAUT32.dll!VarDecFromDisp
-OLEAUT32.dll!VarDecFromI1
-OLEAUT32.dll!VarDecFromI2
-OLEAUT32.dll!VarDecFromI4
-OLEAUT32.dll!VarDecFromI8
-OLEAUT32.dll!VarDecFromR4
-OLEAUT32.dll!VarDecFromR8
-OLEAUT32.dll!VarDecFromStr
-OLEAUT32.dll!VarDecFromUI1
-OLEAUT32.dll!VarDecFromUI2
-OLEAUT32.dll!VarDecFromUI4
-OLEAUT32.dll!VarDecFromUI8
-OLEAUT32.dll!VarDecInt
-OLEAUT32.dll!VarDecMul
-OLEAUT32.dll!VarDecNeg
-OLEAUT32.dll!VarDecRound
-OLEAUT32.dll!VarDecSub
-OLEAUT32.dll!VarDiv
-OLEAUT32.dll!VarEqv
-OLEAUT32.dll!VarFix
-OLEAUT32.dll!VarFormat
-OLEAUT32.dll!VarFormatCurrency
-OLEAUT32.dll!VarFormatDateTime
-OLEAUT32.dll!VarFormatFromTokens
-OLEAUT32.dll!VarFormatNumber
-OLEAUT32.dll!VarFormatPercent
-OLEAUT32.dll!VarI1FromBool
-OLEAUT32.dll!VarI1FromCy
-OLEAUT32.dll!VarI1FromDate
-OLEAUT32.dll!VarI1FromDec
-OLEAUT32.dll!VarI1FromDisp
-OLEAUT32.dll!VarI1FromI2
-OLEAUT32.dll!VarI1FromI4
-OLEAUT32.dll!VarI1FromI8
-OLEAUT32.dll!VarI1FromR4
-OLEAUT32.dll!VarI1FromR8
-OLEAUT32.dll!VarI1FromStr
-OLEAUT32.dll!VarI1FromUI1
-OLEAUT32.dll!VarI1FromUI2
-OLEAUT32.dll!VarI1FromUI4
-OLEAUT32.dll!VarI1FromUI8
-OLEAUT32.dll!VarI2FromBool
-OLEAUT32.dll!VarI2FromCy
-OLEAUT32.dll!VarI2FromDate
-OLEAUT32.dll!VarI2FromDec
-OLEAUT32.dll!VarI2FromDisp
-OLEAUT32.dll!VarI2FromI1
-OLEAUT32.dll!VarI2FromI4
-OLEAUT32.dll!VarI2FromI8
-OLEAUT32.dll!VarI2FromR4
-OLEAUT32.dll!VarI2FromR8
-OLEAUT32.dll!VarI2FromStr
-OLEAUT32.dll!VarI2FromUI1
-OLEAUT32.dll!VarI2FromUI2
-OLEAUT32.dll!VarI2FromUI4
-OLEAUT32.dll!VarI2FromUI8
-OLEAUT32.dll!VarI4FromBool
-OLEAUT32.dll!VarI4FromCy
-OLEAUT32.dll!VarI4FromDate
-OLEAUT32.dll!VarI4FromDec
-OLEAUT32.dll!VarI4FromDisp
-OLEAUT32.dll!VarI4FromI1
-OLEAUT32.dll!VarI4FromI2
-OLEAUT32.dll!VarI4FromI8
-OLEAUT32.dll!VarI4FromR4
-OLEAUT32.dll!VarI4FromR8
-OLEAUT32.dll!VarI4FromStr
-OLEAUT32.dll!VarI4FromUI1
-OLEAUT32.dll!VarI4FromUI2
-OLEAUT32.dll!VarI4FromUI4
-OLEAUT32.dll!VarI4FromUI8
-OLEAUT32.dll!VarI8FromBool
-OLEAUT32.dll!VarI8FromCy
-OLEAUT32.dll!VarI8FromDate
-OLEAUT32.dll!VarI8FromDec
-OLEAUT32.dll!VarI8FromDisp
-OLEAUT32.dll!VarI8FromI1
-OLEAUT32.dll!VarI8FromI2
-OLEAUT32.dll!VarI8FromR4
-OLEAUT32.dll!VarI8FromR8
-OLEAUT32.dll!VarI8FromStr
-OLEAUT32.dll!VarI8FromUI1
-OLEAUT32.dll!VarI8FromUI2
-OLEAUT32.dll!VarI8FromUI4
-OLEAUT32.dll!VarI8FromUI8
-OLEAUT32.dll!VARIANT_UserFree
-OLEAUT32.dll!VARIANT_UserMarshal
-OLEAUT32.dll!VARIANT_UserSize
-OLEAUT32.dll!VARIANT_UserUnmarshal
-OLEAUT32.dll!VariantChangeType
-OLEAUT32.dll!VariantChangeTypeEx
-OLEAUT32.dll!VariantClear
-OLEAUT32.dll!VariantCopy
-OLEAUT32.dll!VariantCopyInd
-OLEAUT32.dll!VariantInit
-OLEAUT32.dll!VariantTimeToSystemTime
-OLEAUT32.dll!VarIdiv
-OLEAUT32.dll!VarImp
-OLEAUT32.dll!VarInt
-OLEAUT32.dll!VarMod
-OLEAUT32.dll!VarMonthName
-OLEAUT32.dll!VarMul
-OLEAUT32.dll!VarNeg
-OLEAUT32.dll!VarNot
-OLEAUT32.dll!VarNumFromParseNum
-OLEAUT32.dll!VarOr
-OLEAUT32.dll!VarParseNumFromStr
-OLEAUT32.dll!VarPow
-OLEAUT32.dll!VarR4CmpR8
-OLEAUT32.dll!VarR4FromBool
-OLEAUT32.dll!VarR4FromCy
-OLEAUT32.dll!VarR4FromDate
-OLEAUT32.dll!VarR4FromDec
-OLEAUT32.dll!VarR4FromDisp
-OLEAUT32.dll!VarR4FromI1
-OLEAUT32.dll!VarR4FromI2
-OLEAUT32.dll!VarR4FromI4
-OLEAUT32.dll!VarR4FromI8
-OLEAUT32.dll!VarR4FromR8
-OLEAUT32.dll!VarR4FromStr
-OLEAUT32.dll!VarR4FromUI1
-OLEAUT32.dll!VarR4FromUI2
-OLEAUT32.dll!VarR4FromUI4
-OLEAUT32.dll!VarR4FromUI8
-OLEAUT32.dll!VarR8FromBool
-OLEAUT32.dll!VarR8FromCy
-OLEAUT32.dll!VarR8FromDate
-OLEAUT32.dll!VarR8FromDec
-OLEAUT32.dll!VarR8FromDisp
-OLEAUT32.dll!VarR8FromI1
-OLEAUT32.dll!VarR8FromI2
-OLEAUT32.dll!VarR8FromI4
-OLEAUT32.dll!VarR8FromI8
-OLEAUT32.dll!VarR8FromR4
-OLEAUT32.dll!VarR8FromStr
-OLEAUT32.dll!VarR8FromUI1
-OLEAUT32.dll!VarR8FromUI2
-OLEAUT32.dll!VarR8FromUI4
-OLEAUT32.dll!VarR8FromUI8
-OLEAUT32.dll!VarR8Pow
-OLEAUT32.dll!VarR8Round
-OLEAUT32.dll!VarRound
-OLEAUT32.dll!VarSub
-OLEAUT32.dll!VarTokenizeFormatString
-OLEAUT32.dll!VarUdateFromDate
-OLEAUT32.dll!VarUI1FromBool
-OLEAUT32.dll!VarUI1FromCy
-OLEAUT32.dll!VarUI1FromDate
-OLEAUT32.dll!VarUI1FromDec
-OLEAUT32.dll!VarUI1FromDisp
-OLEAUT32.dll!VarUI1FromI1
-OLEAUT32.dll!VarUI1FromI2
-OLEAUT32.dll!VarUI1FromI4
-OLEAUT32.dll!VarUI1FromI8
-OLEAUT32.dll!VarUI1FromR4
-OLEAUT32.dll!VarUI1FromR8
-OLEAUT32.dll!VarUI1FromStr
-OLEAUT32.dll!VarUI1FromUI2
-OLEAUT32.dll!VarUI1FromUI4
-OLEAUT32.dll!VarUI1FromUI8
-OLEAUT32.dll!VarUI2FromBool
-OLEAUT32.dll!VarUI2FromCy
-OLEAUT32.dll!VarUI2FromDate
-OLEAUT32.dll!VarUI2FromDec
-OLEAUT32.dll!VarUI2FromDisp
-OLEAUT32.dll!VarUI2FromI1
-OLEAUT32.dll!VarUI2FromI2
-OLEAUT32.dll!VarUI2FromI4
-OLEAUT32.dll!VarUI2FromI8
-OLEAUT32.dll!VarUI2FromR4
-OLEAUT32.dll!VarUI2FromR8
-OLEAUT32.dll!VarUI2FromStr
-OLEAUT32.dll!VarUI2FromUI1
-OLEAUT32.dll!VarUI2FromUI4
-OLEAUT32.dll!VarUI2FromUI8
-OLEAUT32.dll!VarUI4FromBool
-OLEAUT32.dll!VarUI4FromCy
-OLEAUT32.dll!VarUI4FromDate
-OLEAUT32.dll!VarUI4FromDec
-OLEAUT32.dll!VarUI4FromDisp
-OLEAUT32.dll!VarUI4FromI1
-OLEAUT32.dll!VarUI4FromI2
-OLEAUT32.dll!VarUI4FromI4
-OLEAUT32.dll!VarUI4FromI8
-OLEAUT32.dll!VarUI4FromR4
-OLEAUT32.dll!VarUI4FromR8
-OLEAUT32.dll!VarUI4FromStr
-OLEAUT32.dll!VarUI4FromUI1
-OLEAUT32.dll!VarUI4FromUI2
-OLEAUT32.dll!VarUI4FromUI8
-OLEAUT32.dll!VarUI8FromBool
-OLEAUT32.dll!VarUI8FromCy
-OLEAUT32.dll!VarUI8FromDate
-OLEAUT32.dll!VarUI8FromDec
-OLEAUT32.dll!VarUI8FromDisp
-OLEAUT32.dll!VarUI8FromI1
-OLEAUT32.dll!VarUI8FromI2
-OLEAUT32.dll!VarUI8FromI8
-OLEAUT32.dll!VarUI8FromR4
-OLEAUT32.dll!VarUI8FromR8
-OLEAUT32.dll!VarUI8FromStr
-OLEAUT32.dll!VarUI8FromUI1
-OLEAUT32.dll!VarUI8FromUI2
-OLEAUT32.dll!VarUI8FromUI4
-OLEAUT32.dll!VarWeekdayName
-OLEAUT32.dll!VarXor
-PROPSYS.dll!PropVariantCompareEx
-PROPSYS.dll!PropVariantToWinRTPropertyValue
-PROPSYS.dll!WinRTPropertyValueToPropVariant
-RPCRT4.dll!CreateProxyFromTypeInfo
-RPCRT4.dll!CreateStubFromTypeInfo
-RPCRT4.dll!CStdStubBuffer_AddRef
-RPCRT4.dll!CStdStubBuffer_Connect
-RPCRT4.dll!CStdStubBuffer_CountRefs
-RPCRT4.dll!CStdStubBuffer_DebugServerQueryInterface
-RPCRT4.dll!CStdStubBuffer_DebugServerRelease
-RPCRT4.dll!CStdStubBuffer_Disconnect
-RPCRT4.dll!CStdStubBuffer_Invoke
-RPCRT4.dll!CStdStubBuffer_IsIIDSupported
-RPCRT4.dll!CStdStubBuffer_QueryInterface
-RPCRT4.dll!IUnknown_AddRef_Proxy
-RPCRT4.dll!IUnknown_QueryInterface_Proxy
-RPCRT4.dll!IUnknown_Release_Proxy
-RPCRT4.dll!NdrAllocate
-RPCRT4.dll!NdrAsyncClientCall
-RPCRT4.dll!NdrAsyncClientCall2
-RPCRT4.dll!NdrAsyncServerCall
-RPCRT4.dll!NdrByteCountPointerBufferSize
-RPCRT4.dll!NdrByteCountPointerFree
-RPCRT4.dll!NdrByteCountPointerMarshall
-RPCRT4.dll!NdrByteCountPointerUnmarshall
-RPCRT4.dll!NDRCContextBinding
-RPCRT4.dll!NDRCContextMarshall
-RPCRT4.dll!NDRCContextUnmarshall
-RPCRT4.dll!NdrClearOutParameters
-RPCRT4.dll!NdrClientCall2
-RPCRT4.dll!NdrClientCall4
-RPCRT4.dll!NdrClientContextMarshall
-RPCRT4.dll!NdrClientContextUnmarshall
-RPCRT4.dll!NdrClientInitialize
-RPCRT4.dll!NdrClientInitializeNew
-RPCRT4.dll!NdrComplexArrayBufferSize
-RPCRT4.dll!NdrComplexArrayFree
-RPCRT4.dll!NdrComplexArrayMarshall
-RPCRT4.dll!NdrComplexArrayMemorySize
-RPCRT4.dll!NdrComplexArrayUnmarshall
-RPCRT4.dll!NdrComplexStructBufferSize
-RPCRT4.dll!NdrComplexStructFree
-RPCRT4.dll!NdrComplexStructMarshall
-RPCRT4.dll!NdrComplexStructMemorySize
-RPCRT4.dll!NdrComplexStructUnmarshall
-RPCRT4.dll!NdrConformantArrayBufferSize
-RPCRT4.dll!NdrConformantArrayFree
-RPCRT4.dll!NdrConformantArrayMarshall
-RPCRT4.dll!NdrConformantArrayMemorySize
-RPCRT4.dll!NdrConformantArrayUnmarshall
-RPCRT4.dll!NdrConformantStringBufferSize
-RPCRT4.dll!NdrConformantStringMarshall
-RPCRT4.dll!NdrConformantStringMemorySize
-RPCRT4.dll!NdrConformantStringUnmarshall
-RPCRT4.dll!NdrConformantStructBufferSize
-RPCRT4.dll!NdrConformantStructFree
-RPCRT4.dll!NdrConformantStructMarshall
-RPCRT4.dll!NdrConformantStructMemorySize
-RPCRT4.dll!NdrConformantStructUnmarshall
-RPCRT4.dll!NdrConformantVaryingArrayBufferSize
-RPCRT4.dll!NdrConformantVaryingArrayFree
-RPCRT4.dll!NdrConformantVaryingArrayMarshall
-RPCRT4.dll!NdrConformantVaryingArrayMemorySize
-RPCRT4.dll!NdrConformantVaryingArrayUnmarshall
-RPCRT4.dll!NdrConformantVaryingStructBufferSize
-RPCRT4.dll!NdrConformantVaryingStructFree
-RPCRT4.dll!NdrConformantVaryingStructMarshall
-RPCRT4.dll!NdrConformantVaryingStructMemorySize
-RPCRT4.dll!NdrConformantVaryingStructUnmarshall
-RPCRT4.dll!NdrContextHandleInitialize
-RPCRT4.dll!NdrContextHandleSize
-RPCRT4.dll!NdrConvert
-RPCRT4.dll!NdrConvert2
-RPCRT4.dll!NdrCorrelationFree
-RPCRT4.dll!NdrCorrelationInitialize
-RPCRT4.dll!NdrCorrelationPass
-RPCRT4.dll!NdrCreateServerInterfaceFromStub
-RPCRT4.dll!NdrCStdStubBuffer_Release
-RPCRT4.dll!NdrCStdStubBuffer2_Release
-RPCRT4.dll!NdrDllCanUnloadNow
-RPCRT4.dll!NdrDllGetClassObject
-RPCRT4.dll!NdrDllRegisterProxy
-RPCRT4.dll!NdrDllUnregisterProxy
-RPCRT4.dll!NdrEncapsulatedUnionBufferSize
-RPCRT4.dll!NdrEncapsulatedUnionFree
-RPCRT4.dll!NdrEncapsulatedUnionMarshall
-RPCRT4.dll!NdrEncapsulatedUnionMemorySize
-RPCRT4.dll!NdrEncapsulatedUnionUnmarshall
-RPCRT4.dll!NdrFixedArrayBufferSize
-RPCRT4.dll!NdrFixedArrayFree
-RPCRT4.dll!NdrFixedArrayMarshall
-RPCRT4.dll!NdrFixedArrayMemorySize
-RPCRT4.dll!NdrFixedArrayUnmarshall
-RPCRT4.dll!NdrFreeBuffer
-RPCRT4.dll!NdrFullPointerXlatFree
-RPCRT4.dll!NdrFullPointerXlatInit
-RPCRT4.dll!NdrGetBuffer
-RPCRT4.dll!NdrGetDcomProtocolVersion
-RPCRT4.dll!NdrGetUserMarshalInfo
-RPCRT4.dll!NdrInterfacePointerBufferSize
-RPCRT4.dll!NdrInterfacePointerFree
-RPCRT4.dll!NdrInterfacePointerMarshall
-RPCRT4.dll!NdrInterfacePointerMemorySize
-RPCRT4.dll!NdrInterfacePointerUnmarshall
-RPCRT4.dll!NdrMapCommAndFaultStatus
-RPCRT4.dll!NdrNonConformantStringBufferSize
-RPCRT4.dll!NdrNonConformantStringMarshall
-RPCRT4.dll!NdrNonConformantStringMemorySize
-RPCRT4.dll!NdrNonConformantStringUnmarshall
-RPCRT4.dll!NdrNonEncapsulatedUnionBufferSize
-RPCRT4.dll!NdrNonEncapsulatedUnionFree
-RPCRT4.dll!NdrNonEncapsulatedUnionMarshall
-RPCRT4.dll!NdrNonEncapsulatedUnionMemorySize
-RPCRT4.dll!NdrNonEncapsulatedUnionUnmarshall
-RPCRT4.dll!NdrNsGetBuffer
-RPCRT4.dll!NdrNsSendReceive
-RPCRT4.dll!NdrOleAllocate
-RPCRT4.dll!NdrOleFree
-RPCRT4.dll!NdrPartialIgnoreClientBufferSize
-RPCRT4.dll!NdrPartialIgnoreClientMarshall
-RPCRT4.dll!NdrPartialIgnoreServerInitialize
-RPCRT4.dll!NdrPartialIgnoreServerUnmarshall
-RPCRT4.dll!NdrPointerBufferSize
-RPCRT4.dll!NdrPointerFree
-RPCRT4.dll!NdrPointerMarshall
-RPCRT4.dll!NdrPointerMemorySize
-RPCRT4.dll!NdrPointerUnmarshall
-RPCRT4.dll!NdrProxyErrorHandler
-RPCRT4.dll!NdrRangeUnmarshall
-RPCRT4.dll!NdrRpcSmClientAllocate
-RPCRT4.dll!NdrRpcSmClientFree
-RPCRT4.dll!NdrRpcSmSetClientToOsf
-RPCRT4.dll!NdrRpcSsDefaultAllocate
-RPCRT4.dll!NdrRpcSsDefaultFree
-RPCRT4.dll!NdrRpcSsDisableAllocate
-RPCRT4.dll!NdrRpcSsEnableAllocate
-RPCRT4.dll!NDRSContextMarshall
-RPCRT4.dll!NDRSContextMarshall2
-RPCRT4.dll!NDRSContextMarshallEx
-RPCRT4.dll!NDRSContextUnmarshall
-RPCRT4.dll!NDRSContextUnmarshall2
-RPCRT4.dll!NDRSContextUnmarshallEx
-RPCRT4.dll!NdrSendReceive
-RPCRT4.dll!NdrServerCall2
-RPCRT4.dll!NdrServerContextMarshall
-RPCRT4.dll!NdrServerContextNewMarshall
-RPCRT4.dll!NdrServerContextNewUnmarshall
-RPCRT4.dll!NdrServerContextUnmarshall
-RPCRT4.dll!NdrServerInitialize
-RPCRT4.dll!NdrServerInitializeMarshall
-RPCRT4.dll!NdrServerInitializeNew
-RPCRT4.dll!NdrServerInitializePartial
-RPCRT4.dll!NdrServerInitializeUnmarshall
-RPCRT4.dll!NdrSimpleStructBufferSize
-RPCRT4.dll!NdrSimpleStructFree
-RPCRT4.dll!NdrSimpleStructMarshall
-RPCRT4.dll!NdrSimpleStructMemorySize
-RPCRT4.dll!NdrSimpleStructUnmarshall
-RPCRT4.dll!NdrSimpleTypeMarshall
-RPCRT4.dll!NdrSimpleTypeUnmarshall
-RPCRT4.dll!NdrStubCall2
-RPCRT4.dll!NdrStubForwardingFunction
-RPCRT4.dll!NdrUserMarshalBufferSize
-RPCRT4.dll!NdrUserMarshalFree
-RPCRT4.dll!NdrUserMarshalMarshall
-RPCRT4.dll!NdrUserMarshalMemorySize
-RPCRT4.dll!NdrUserMarshalSimpleTypeConvert
-RPCRT4.dll!NdrUserMarshalUnmarshall
-RPCRT4.dll!NdrVaryingArrayBufferSize
-RPCRT4.dll!NdrVaryingArrayFree
-RPCRT4.dll!NdrVaryingArrayMarshall
-RPCRT4.dll!NdrVaryingArrayMemorySize
-RPCRT4.dll!NdrVaryingArrayUnmarshall
-RPCRT4.dll!NdrXmitOrRepAsBufferSize
-RPCRT4.dll!NdrXmitOrRepAsFree
-RPCRT4.dll!NdrXmitOrRepAsMarshall
-RPCRT4.dll!NdrXmitOrRepAsMemorySize
-RPCRT4.dll!NdrXmitOrRepAsUnmarshall
-RPCRT4.dll!RpcSmAllocate
-RPCRT4.dll!RpcSmClientFree
-RPCRT4.dll!RpcSmDestroyClientContext
-RPCRT4.dll!RpcSmDisableAllocate
-RPCRT4.dll!RpcSmEnableAllocate
-RPCRT4.dll!RpcSmFree
-RPCRT4.dll!RpcSmGetThreadHandle
-RPCRT4.dll!RpcSmSetClientAllocFree
-RPCRT4.dll!RpcSmSetThreadHandle
-RPCRT4.dll!RpcSmSwapClientAllocFree
-RPCRT4.dll!RpcSsAllocate
-RPCRT4.dll!RpcSsDestroyClientContext
-RPCRT4.dll!RpcSsDisableAllocate
-RPCRT4.dll!RpcSsEnableAllocate
-RPCRT4.dll!RpcSsFree
-RPCRT4.dll!RpcSsGetThreadHandle
-RPCRT4.dll!RpcSsSetClientAllocFree
-RPCRT4.dll!RpcSsSetThreadHandle
-RPCRT4.dll!RpcSsSwapClientAllocFree
-RPCRT4.dll!RpcUserFree
-UIAutomationCore.DLL!UiaClientsAreListening
-UIAutomationCore.DLL!UiaDisconnectAllProviders
-UIAutomationCore.DLL!UiaDisconnectProvider
-UIAutomationCore.DLL!UiaGetReservedMixedAttributeValue
-UIAutomationCore.DLL!UiaGetReservedNotSupportedValue
-UIAutomationCore.DLL!UiaHostProviderFromHwnd
-UIAutomationCore.DLL!UiaProviderForNonClient
-UIAutomationCore.DLL!UiaProviderFromIAccessible
-UIAutomationCore.DLL!UiaRaiseAsyncContentLoadedEvent
-UIAutomationCore.DLL!UiaRaiseAutomationEvent
-UIAutomationCore.DLL!UiaRaiseAutomationPropertyChangedEvent
-UIAutomationCore.DLL!UiaRaiseStructureChangedEvent
-UIAutomationCore.DLL!UiaRaiseTextEditTextChangedEvent
-UIAutomationCore.DLL!UiaReturnRawElementProvider
-urlmon.dll!CreateUri
-urlmon.dll!CreateUriWithFragment
-webservices.dll!WsAbandonCall
-webservices.dll!WsAbandonMessage
-webservices.dll!WsAbortChannel
-webservices.dll!WsAbortServiceProxy
-webservices.dll!WsAddCustomHeader
-webservices.dll!WsAddErrorString
-webservices.dll!WsAddMappedHeader
-webservices.dll!WsAddressMessage
-webservices.dll!WsAlloc
-webservices.dll!WsAsyncExecute
-webservices.dll!WsCall
-webservices.dll!WsCheckMustUnderstandHeaders
-webservices.dll!WsCloseChannel
-webservices.dll!WsCloseServiceProxy
-webservices.dll!WsCombineUrl
-webservices.dll!WsCopyError
-webservices.dll!WsCopyNode
-webservices.dll!WsCreateChannel
-webservices.dll!WsCreateError
-webservices.dll!WsCreateFaultFromError
-webservices.dll!WsCreateHeap
-webservices.dll!WsCreateMessage
-webservices.dll!WsCreateMessageForChannel
-webservices.dll!WsCreateMetadata
-webservices.dll!WsCreateReader
-webservices.dll!WsCreateServiceProxy
-webservices.dll!WsCreateServiceProxyFromTemplate
-webservices.dll!WsCreateWriter
-webservices.dll!WsCreateXmlBuffer
-webservices.dll!WsCreateXmlSecurityToken
-webservices.dll!WsDateTimeToFileTime
-webservices.dll!WsDecodeUrl
-webservices.dll!WsEncodeUrl
-webservices.dll!WsEndReaderCanonicalization
-webservices.dll!WsEndWriterCanonicalization
-webservices.dll!WsFileTimeToDateTime
-webservices.dll!WsFillBody
-webservices.dll!WsFillReader
-webservices.dll!WsFindAttribute
-webservices.dll!WsFlushBody
-webservices.dll!WsFlushWriter
-webservices.dll!WsFreeChannel
-webservices.dll!WsFreeError
-webservices.dll!WsFreeHeap
-webservices.dll!WsFreeMessage
-webservices.dll!WsFreeMetadata
-webservices.dll!WsFreeReader
-webservices.dll!WsFreeSecurityToken
-webservices.dll!WsFreeServiceProxy
-webservices.dll!WsFreeWriter
-webservices.dll!WsGetChannelProperty
-webservices.dll!WsGetCustomHeader
-webservices.dll!WsGetDictionary
-webservices.dll!WsGetErrorProperty
-webservices.dll!WsGetErrorString
-webservices.dll!WsGetFaultErrorDetail
-webservices.dll!WsGetFaultErrorProperty
-webservices.dll!WsGetHeader
-webservices.dll!WsGetHeaderAttributes
-webservices.dll!WsGetHeapProperty
-webservices.dll!WsGetMappedHeader
-webservices.dll!WsGetMessageProperty
-webservices.dll!WsGetMetadataEndpoints
-webservices.dll!WsGetMetadataProperty
-webservices.dll!WsGetMissingMetadataDocumentAddress
-webservices.dll!WsGetNamespaceFromPrefix
-webservices.dll!WsGetPolicyAlternativeCount
-webservices.dll!WsGetPolicyProperty
-webservices.dll!WsGetPrefixFromNamespace
-webservices.dll!WsGetReaderNode
-webservices.dll!WsGetReaderPosition
-webservices.dll!WsGetReaderProperty
-webservices.dll!WsGetSecurityContextProperty
-webservices.dll!WsGetSecurityTokenProperty
-webservices.dll!WsGetServiceProxyProperty
-webservices.dll!WsGetWriterPosition
-webservices.dll!WsGetWriterProperty
-webservices.dll!WsGetXmlAttribute
-webservices.dll!WsInitializeMessage
-webservices.dll!WsMarkHeaderAsUnderstood
-webservices.dll!WsMatchPolicyAlternative
-webservices.dll!WsMoveReader
-webservices.dll!WsMoveWriter
-webservices.dll!WsOpenChannel
-webservices.dll!WsOpenServiceProxy
-webservices.dll!WsPullBytes
-webservices.dll!WsPushBytes
-webservices.dll!WsReadArray
-webservices.dll!WsReadAttribute
-webservices.dll!WsReadBody
-webservices.dll!WsReadBytes
-webservices.dll!WsReadChars
-webservices.dll!WsReadCharsUtf8
-webservices.dll!WsReadElement
-webservices.dll!WsReadEndAttribute
-webservices.dll!WsReadEndElement
-webservices.dll!WsReadEndpointAddressExtension
-webservices.dll!WsReadEnvelopeEnd
-webservices.dll!WsReadEnvelopeStart
-webservices.dll!WsReadMessageEnd
-webservices.dll!WsReadMessageStart
-webservices.dll!WsReadMetadata
-webservices.dll!WsReadNode
-webservices.dll!WsReadQualifiedName
-webservices.dll!WsReadStartAttribute
-webservices.dll!WsReadStartElement
-webservices.dll!WsReadToStartElement
-webservices.dll!WsReadType
-webservices.dll!WsReadValue
-webservices.dll!WsReadXmlBuffer
-webservices.dll!WsReadXmlBufferFromBytes
-webservices.dll!WsReceiveMessage
-webservices.dll!WsRemoveCustomHeader
-webservices.dll!WsRemoveHeader
-webservices.dll!WsRemoveMappedHeader
-webservices.dll!WsRemoveNode
-webservices.dll!WsRequestReply
-webservices.dll!WsRequestSecurityToken
-webservices.dll!WsResetChannel
-webservices.dll!WsResetError
-webservices.dll!WsResetHeap
-webservices.dll!WsResetMessage
-webservices.dll!WsResetMetadata
-webservices.dll!WsResetServiceProxy
-webservices.dll!WsRevokeSecurityContext
-webservices.dll!WsSendFaultMessageForError
-webservices.dll!WsSendMessage
-webservices.dll!WsSendReplyMessage
-webservices.dll!WsSetChannelProperty
-webservices.dll!WsSetErrorProperty
-webservices.dll!WsSetFaultErrorDetail
-webservices.dll!WsSetFaultErrorProperty
-webservices.dll!WsSetHeader
-webservices.dll!WsSetInput
-webservices.dll!WsSetInputToBuffer
-webservices.dll!WsSetMessageProperty
-webservices.dll!WsSetOutput
-webservices.dll!WsSetOutputToBuffer
-webservices.dll!WsSetReaderPosition
-webservices.dll!WsSetWriterPosition
-webservices.dll!WsShutdownSessionChannel
-webservices.dll!WsSkipNode
-webservices.dll!WsStartReaderCanonicalization
-webservices.dll!WsStartWriterCanonicalization
-webservices.dll!WsTrimXmlWhitespace
-webservices.dll!WsVerifyXmlNCName
-webservices.dll!WsWriteArray
-webservices.dll!WsWriteAttribute
-webservices.dll!WsWriteBody
-webservices.dll!WsWriteBytes
-webservices.dll!WsWriteChars
-webservices.dll!WsWriteCharsUtf8
-webservices.dll!WsWriteElement
-webservices.dll!WsWriteEndAttribute
-webservices.dll!WsWriteEndCData
-webservices.dll!WsWriteEndElement
-webservices.dll!WsWriteEndStartElement
-webservices.dll!WsWriteEnvelopeEnd
-webservices.dll!WsWriteEnvelopeStart
-webservices.dll!WsWriteMessageEnd
-webservices.dll!WsWriteMessageStart
-webservices.dll!WsWriteNode
-webservices.dll!WsWriteQualifiedName
-webservices.dll!WsWriteStartAttribute
-webservices.dll!WsWriteStartCData
-webservices.dll!WsWriteStartElement
-webservices.dll!WsWriteText
-webservices.dll!WsWriteType
-webservices.dll!WsWriteValue
-webservices.dll!WsWriteXmlBuffer
-webservices.dll!WsWriteXmlBufferToBytes
-webservices.dll!WsWriteXmlnsAttribute
-webservices.dll!WsXmlStringEquals
-Windows.Data.Pdf.dll!PdfCreateRenderer
-Windows.Networking.dll!SetSocketMediaStreamingMode
-WindowsCodecs.dll!WICConvertBitmapSource
-WindowsCodecs.dll!WICCreateBitmapFromSection
-WindowsCodecs.dll!WICCreateBitmapFromSectionEx
-WindowsCodecs.dll!WICGetMetadataContentSize
-WindowsCodecs.dll!WICMapGuidToShortName
-WindowsCodecs.dll!WICMapSchemaToName
-WindowsCodecs.dll!WICMapShortNameToGuid
-WindowsCodecs.dll!WICMatchMetadataContent
-WindowsCodecs.dll!WICSerializeMetadataContent
-WS2_32.dll!__WSAFDIsSet
-WS2_32.dll!accept
-WS2_32.dll!bind
-WS2_32.dll!closesocket
-WS2_32.dll!connect
-WS2_32.dll!freeaddrinfo
-WS2_32.dll!FreeAddrInfoExW
-WS2_32.dll!FreeAddrInfoW
-WS2_32.dll!getaddrinfo
-WS2_32.dll!GetAddrInfoExCancel
-WS2_32.dll!GetAddrInfoExOverlappedResult
-WS2_32.dll!GetAddrInfoExW
-WS2_32.dll!GetAddrInfoW
-WS2_32.dll!gethostbyaddr
-WS2_32.dll!gethostbyname
-WS2_32.dll!gethostname
-WS2_32.dll!GetHostNameW
-WS2_32.dll!getnameinfo
-WS2_32.dll!GetNameInfoW
-WS2_32.dll!getpeername
-WS2_32.dll!getprotobyname
-WS2_32.dll!getprotobynumber
-WS2_32.dll!getservbyname
-WS2_32.dll!getservbyport
-WS2_32.dll!getsockname
-WS2_32.dll!getsockopt
-WS2_32.dll!htonl
-WS2_32.dll!htons
-WS2_32.dll!inet_addr
-WS2_32.dll!inet_ntoa
-WS2_32.dll!inet_ntop
-WS2_32.dll!inet_pton
-WS2_32.dll!InetNtopW
-WS2_32.dll!InetPtonW
-WS2_32.dll!ioctlsocket
-WS2_32.dll!listen
-WS2_32.dll!ntohl
-WS2_32.dll!ntohs
-WS2_32.dll!recv
-WS2_32.dll!recvfrom
-WS2_32.dll!select
-WS2_32.dll!send
-WS2_32.dll!sendto
-WS2_32.dll!SetAddrInfoExW
-WS2_32.dll!setsockopt
-WS2_32.dll!shutdown
-WS2_32.dll!socket
-WS2_32.dll!WSAAccept
-WS2_32.dll!WSAAddressToStringA
-WS2_32.dll!WSAAddressToStringW
-WS2_32.dll!WSACleanup
-WS2_32.dll!WSACloseEvent
-WS2_32.dll!WSAConnect
-WS2_32.dll!WSAConnectByList
-WS2_32.dll!WSAConnectByNameA
-WS2_32.dll!WSAConnectByNameW
-WS2_32.dll!WSACreateEvent
-WS2_32.dll!WSADuplicateSocketA
-WS2_32.dll!WSADuplicateSocketW
-WS2_32.dll!WSAEnumNameSpaceProvidersA
-WS2_32.dll!WSAEnumNameSpaceProvidersExA
-WS2_32.dll!WSAEnumNameSpaceProvidersExW
-WS2_32.dll!WSAEnumNameSpaceProvidersW
-WS2_32.dll!WSAEnumNetworkEvents
-WS2_32.dll!WSAEnumProtocolsA
-WS2_32.dll!WSAEnumProtocolsW
-WS2_32.dll!WSAEventSelect
-WS2_32.dll!WSAGetLastError
-WS2_32.dll!WSAGetOverlappedResult
-WS2_32.dll!WSAGetServiceClassInfoW
-WS2_32.dll!WSAGetServiceClassNameByClassIdW
-WS2_32.dll!WSAHtonl
-WS2_32.dll!WSAHtons
-WS2_32.dll!WSAIoctl
-WS2_32.dll!WSAJoinLeaf
-WS2_32.dll!WSALookupServiceBeginA
-WS2_32.dll!WSALookupServiceBeginW
-WS2_32.dll!WSALookupServiceEnd
-WS2_32.dll!WSALookupServiceNextA
-WS2_32.dll!WSALookupServiceNextW
-WS2_32.dll!WSANSPIoctl
-WS2_32.dll!WSANtohl
-WS2_32.dll!WSANtohs
-WS2_32.dll!WSAPoll
-WS2_32.dll!WSAProviderConfigChange
-WS2_32.dll!WSARecv
-WS2_32.dll!WSARecvFrom
-WS2_32.dll!WSAResetEvent
-WS2_32.dll!WSASend
-WS2_32.dll!WSASendMsg
-WS2_32.dll!WSASendTo
-WS2_32.dll!WSASetEvent
-WS2_32.dll!WSASetLastError
-WS2_32.dll!WSASetServiceA
-WS2_32.dll!WSASetServiceW
-WS2_32.dll!WSASocketA
-WS2_32.dll!WSASocketW
-WS2_32.dll!WSAStartup
-WS2_32.dll!WSAStringToAddressA
-WS2_32.dll!WSAStringToAddressW
-WS2_32.dll!WSAWaitForMultipleEvents
-XAudio2_9.dll!CreateAudioReverb
-XAudio2_9.dll!CreateAudioVolumeMeter
-XAudio2_9.dll!CreateFX
-XAudio2_9.dll!X3DAudioCalculate
-XAudio2_9.dll!X3DAudioInitialize
-XAudio2_9.dll!XAudio2Create
-XINPUTUAP.dll!XInputEnable
-XINPUTUAP.dll!XInputGetAudioDeviceIds
-XINPUTUAP.dll!XInputGetBatteryInformation
-XINPUTUAP.dll!XInputGetCapabilities
-XINPUTUAP.dll!XInputGetKeystroke
-XINPUTUAP.dll!XInputGetState
-XINPUTUAP.dll!XInputSetState
-XmlLite.dll!CreateXmlReader
-XmlLite.dll!CreateXmlReaderInputWithEncodingCodePage
-XmlLite.dll!CreateXmlReaderInputWithEncodingName
-XmlLite.dll!CreateXmlWriter
-XmlLite.dll!CreateXmlWriterOutputWithEncodingCodePage
-XmlLite.dll!CreateXmlWriterOutputWithEncodingName
-advapi32.dll!CloseTrace
-advapi32.dll!ControlTraceW
-advapi32.dll!CryptReleaseContext
-advapi32.dll!EnableTrace
-advapi32.dll!EnableTraceEx
-advapi32.dll!EnableTraceEx2
-advapi32.dll!EnumDynamicTimeZoneInformation
-advapi32.dll!EventActivityIdControl
-advapi32.dll!EventRegister
-advapi32.dll!EventSetInformation
-advapi32.dll!EventUnregister
-advapi32.dll!EventWrite
-advapi32.dll!EventWriteEx
-advapi32.dll!EventWriteString
-advapi32.dll!EventWriteTransfer
-advapi32.dll!FlushTraceW
-advapi32.dll!GetDynamicTimeZoneInformationEffectiveYears
-advapi32.dll!GetTraceEnableFlags
-advapi32.dll!GetTraceEnableLevel
-advapi32.dll!GetTraceLoggerHandle
-advapi32.dll!OpenTraceW
-advapi32.dll!ProcessTrace
-advapi32.dll!QueryTraceW
-advapi32.dll!RegisterTraceGuidsW
-advapi32.dll!StartTraceW
-advapi32.dll!StopTraceW
-advapi32.dll!TraceMessage
-advapi32.dll!UnregisterTraceGuids
-kernel32.dll!AcquireSRWLockExclusive
-kernel32.dll!AcquireSRWLockShared
-kernel32.dll!CallbackMayRunLong
-kernel32.dll!CancelIoEx
-kernel32.dll!CancelThreadpoolIo
-kernel32.dll!CeipIsOptedIn
-kernel32.dll!CloseHandle
-kernel32.dll!CloseThreadpool
-kernel32.dll!CloseThreadpoolCleanupGroup
-kernel32.dll!CloseThreadpoolCleanupGroupMembers
-kernel32.dll!CloseThreadpoolIo
-kernel32.dll!CloseThreadpoolTimer
-kernel32.dll!CloseThreadpoolWait
-kernel32.dll!CloseThreadpoolWork
-kernel32.dll!CompareStringEx
-kernel32.dll!CompareStringOrdinal
-kernel32.dll!ConvertFiberToThread
-kernel32.dll!ConvertThreadToFiberEx
-kernel32.dll!CopyFile2
-kernel32.dll!CreateDirectoryA
-kernel32.dll!CreateDirectoryW
-kernel32.dll!CreateEventA
-kernel32.dll!CreateEventExA
-kernel32.dll!CreateEventExW
-kernel32.dll!CreateEventW
-kernel32.dll!CreateFiberEx
-kernel32.dll!CreateFile2
-kernel32.dll!CreateFileMappingFromApp
-kernel32.dll!CreateMutexA
-kernel32.dll!CreateMutexExA
-kernel32.dll!CreateMutexExW
-kernel32.dll!CreateMutexW
-kernel32.dll!CreateSemaphoreA
-kernel32.dll!CreateSemaphoreExA
-kernel32.dll!CreateSemaphoreExW
-kernel32.dll!CreateSemaphoreW
-kernel32.dll!CreateThread
-kernel32.dll!CreateThreadpool
-kernel32.dll!CreateThreadpoolCleanupGroup
-kernel32.dll!CreateThreadpoolIo
-kernel32.dll!CreateThreadpoolTimer
-kernel32.dll!CreateThreadpoolWait
-kernel32.dll!CreateThreadpoolWork
-kernel32.dll!DecodePointer
-kernel32.dll!DelayLoadFailureHook
-kernel32.dll!DeleteCriticalSection
-kernel32.dll!DeleteFiber
-kernel32.dll!DeleteFileA
-kernel32.dll!DeleteFileW
-kernel32.dll!DisableThreadLibraryCalls
-kernel32.dll!DisassociateCurrentThreadFromCallback
-kernel32.dll!DiscardVirtualMemory
-kernel32.dll!DuplicateHandle
-kernel32.dll!EncodePointer
-kernel32.dll!EnterCriticalSection
-kernel32.dll!EnumCalendarInfoExEx
-kernel32.dll!EnumDateFormatsExEx
-kernel32.dll!EnumSystemCodePagesW
-kernel32.dll!EnumSystemGeoID
-kernel32.dll!EnumSystemLocalesEx
-kernel32.dll!EnumTimeFormatsEx
-kernel32.dll!ExitThread
-kernel32.dll!FileTimeToSystemTime
-kernel32.dll!FindClose
-kernel32.dll!FindFirstFileExA
-kernel32.dll!FindFirstFileExW
-kernel32.dll!FindNextFileA
-kernel32.dll!FindNextFileW
-kernel32.dll!FindNLSStringEx
-kernel32.dll!FindStringOrdinal
-kernel32.dll!FlsAlloc
-kernel32.dll!FlsFree
-kernel32.dll!FlsGetValue
-kernel32.dll!FlsSetValue
-kernel32.dll!FlushFileBuffers
-kernel32.dll!FlushProcessWriteBuffers
-kernel32.dll!FlushViewOfFile
-kernel32.dll!FormatMessageA
-kernel32.dll!FormatMessageW
-kernel32.dll!FreeLibrary
-kernel32.dll!FreeLibraryWhenCallbackReturns
-kernel32.dll!GetCalendarInfoEx
-kernel32.dll!GetCommandLineA
-kernel32.dll!GetCommandLineW
-kernel32.dll!GetCPInfo
-kernel32.dll!GetCPInfoExW
-kernel32.dll!GetCurrencyFormatEx
-kernel32.dll!GetCurrentDirectoryW
-kernel32.dll!GetCurrentProcess
-kernel32.dll!GetCurrentProcessId
-kernel32.dll!GetCurrentThread
-kernel32.dll!GetCurrentThreadId
-kernel32.dll!GetDateFormatEx
-kernel32.dll!GetDiskFreeSpaceExA
-kernel32.dll!GetDiskFreeSpaceExW
-kernel32.dll!GetDurationFormatEx
-kernel32.dll!GetDynamicTimeZoneInformation
-kernel32.dll!GetEnabledXStateFeatures
-kernel32.dll!GetExitCodeThread
-kernel32.dll!GetFileAttributesExA
-kernel32.dll!GetFileAttributesExW
-kernel32.dll!GetFileInformationByHandleEx
-kernel32.dll!GetFileSizeEx
-kernel32.dll!GetFileTime
-kernel32.dll!GetFileType
-kernel32.dll!GetFullPathNameW
-kernel32.dll!GetGeoInfoW
-kernel32.dll!GetLastError
-kernel32.dll!GetLocaleInfoEx
-kernel32.dll!GetLocalTime
-kernel32.dll!GetLongPathNameW
-kernel32.dll!GetModuleFileNameA
-kernel32.dll!GetModuleFileNameW
-kernel32.dll!GetNativeSystemInfo
-kernel32.dll!GetNLSVersionEx
-kernel32.dll!GetNumberFormatEx
-kernel32.dll!GetOverlappedResultEx
-kernel32.dll!GetProcAddress
-kernel32.dll!GetProcessDefaultCpuSets
-kernel32.dll!GetProcessHeap
-kernel32.dll!GetProcessInformation
-kernel32.dll!GetStringScripts
-kernel32.dll!GetStringTypeExA
-kernel32.dll!GetStringTypeExW
-kernel32.dll!GetStringTypeW
-kernel32.dll!GetSystemCpuSetInformation
-kernel32.dll!GetSystemDefaultLocaleName
-kernel32.dll!GetSystemInfo
-kernel32.dll!GetSystemTime
-kernel32.dll!GetSystemTimeAsFileTime
-kernel32.dll!GetSystemTimePreciseAsFileTime
-kernel32.dll!GetTempFileNameW
-kernel32.dll!GetTempPathW
-kernel32.dll!GetThreadContext
-kernel32.dll!GetThreadId
-kernel32.dll!GetThreadPriority
-kernel32.dll!GetThreadSelectedCpuSets
-kernel32.dll!GetTickCount64
-kernel32.dll!GetTimeFormatEx
-kernel32.dll!GetTimeZoneInformation
-kernel32.dll!GetTimeZoneInformationForYear
-kernel32.dll!GetUserDefaultLocaleName
-kernel32.dll!GetUserGeoID
-kernel32.dll!GetWriteWatch
-kernel32.dll!GetXStateFeaturesMask
-kernel32.dll!HeapAlloc
-kernel32.dll!HeapCompact
-kernel32.dll!HeapCreate
-kernel32.dll!HeapDestroy
-kernel32.dll!HeapFree
-kernel32.dll!HeapReAlloc
-kernel32.dll!HeapSetInformation
-kernel32.dll!HeapSize
-kernel32.dll!InitializeConditionVariable
-kernel32.dll!InitializeContext
-kernel32.dll!InitializeCriticalSection
-kernel32.dll!InitializeCriticalSectionAndSpinCount
-kernel32.dll!InitializeCriticalSectionEx
-kernel32.dll!InitializeSListHead
-kernel32.dll!InitializeSRWLock
-kernel32.dll!InitOnceBeginInitialize
-kernel32.dll!InitOnceComplete
-kernel32.dll!InitOnceExecuteOnce
-kernel32.dll!InitOnceInitialize
-kernel32.dll!InterlockedFlushSList
-kernel32.dll!InterlockedPopEntrySList
-kernel32.dll!InterlockedPushEntrySList
-kernel32.dll!InterlockedPushListSListEx
-kernel32.dll!IsDebuggerPresent
-kernel32.dll!IsNormalizedString
-kernel32.dll!IsProcessorFeaturePresent
-kernel32.dll!IsThreadAFiber
-kernel32.dll!IsThreadpoolTimerSet
-kernel32.dll!IsValidCodePage
-kernel32.dll!IsValidLocaleName
-kernel32.dll!IsValidNLSVersion
-kernel32.dll!LCIDToLocaleName
-kernel32.dll!LCMapStringEx
-kernel32.dll!LeaveCriticalSection
-kernel32.dll!LeaveCriticalSectionWhenCallbackReturns
-kernel32.dll!LoadPackagedLibrary
-kernel32.dll!LocaleNameToLCID
-kernel32.dll!LocateXStateFeature
-kernel32.dll!LockFileEx
-kernel32.dll!MapViewOfFileFromApp
-kernel32.dll!MoveFileExA
-kernel32.dll!MoveFileExW
-kernel32.dll!MulDiv
-kernel32.dll!MultiByteToWideChar
-kernel32.dll!NormalizeString
-kernel32.dll!OfferVirtualMemory
-kernel32.dll!OpenEventA
-kernel32.dll!OpenEventW
-kernel32.dll!OpenMutexA
-kernel32.dll!OpenMutexW
-kernel32.dll!OpenProcess
-kernel32.dll!OpenSemaphoreW
-kernel32.dll!OutputDebugStringA
-kernel32.dll!OutputDebugStringW
-kernel32.dll!QueryDepthSList
-kernel32.dll!QueryPerformanceCounter
-kernel32.dll!QueryPerformanceFrequency
-kernel32.dll!QueryThreadpoolStackInformation
-kernel32.dll!QueryUnbiasedInterruptTime
-kernel32.dll!QueueUserAPC
-kernel32.dll!RaiseException
-kernel32.dll!RaiseFailFastException
-kernel32.dll!ReadFile
-kernel32.dll!ReclaimVirtualMemory
-kernel32.dll!ReleaseMutex
-kernel32.dll!ReleaseMutexWhenCallbackReturns
-kernel32.dll!ReleaseSemaphore
-kernel32.dll!ReleaseSemaphoreWhenCallbackReturns
-kernel32.dll!ReleaseSRWLockExclusive
-kernel32.dll!ReleaseSRWLockShared
-kernel32.dll!RemoveDirectoryA
-kernel32.dll!RemoveDirectoryW
-kernel32.dll!ReplaceFileA
-kernel32.dll!ReplaceFileW
-kernel32.dll!ResetEvent
-kernel32.dll!ResetWriteWatch
-kernel32.dll!ResolveDelayLoadedAPI
-kernel32.dll!ResolveDelayLoadsFromDll
-kernel32.dll!ResolveLocaleName
-kernel32.dll!ResumeThread
-kernel32.dll!RtlCaptureStackBackTrace
-kernel32.dll!RtlPcToFileHeader
-kernel32.dll!RtlUnwind
-kernel32.dll!SetCriticalSectionSpinCount
-kernel32.dll!SetCurrentDirectoryW
-kernel32.dll!SetEndOfFile
-kernel32.dll!SetEvent
-kernel32.dll!SetEventWhenCallbackReturns
-kernel32.dll!SetFileAttributesA
-kernel32.dll!SetFileAttributesW
-kernel32.dll!SetFileInformationByHandle
-kernel32.dll!SetFilePointerEx
-kernel32.dll!SetFileTime
-kernel32.dll!SetLastError
-kernel32.dll!SetProcessDefaultCpuSets
-kernel32.dll!SetProcessInformation
-kernel32.dll!SetThreadIdealProcessor
-kernel32.dll!SetThreadIdealProcessorEx
-kernel32.dll!SetThreadpoolStackInformation
-kernel32.dll!SetThreadpoolThreadMaximum
-kernel32.dll!SetThreadpoolThreadMinimum
-kernel32.dll!SetThreadpoolTimer
-kernel32.dll!SetThreadpoolTimerEx
-kernel32.dll!SetThreadpoolWait
-kernel32.dll!SetThreadpoolWaitEx
-kernel32.dll!SetThreadPriority
-kernel32.dll!SetThreadSelectedCpuSets
-kernel32.dll!Sleep
-kernel32.dll!SleepConditionVariableCS
-kernel32.dll!SleepConditionVariableSRW
-kernel32.dll!SleepEx
-kernel32.dll!StartThreadpoolIo
-kernel32.dll!SubmitThreadpoolWork
-kernel32.dll!SuspendThread
-kernel32.dll!SwitchToFiber
-kernel32.dll!SwitchToThread
-kernel32.dll!SystemTimeToFileTime
-kernel32.dll!SystemTimeToTzSpecificLocalTime
-kernel32.dll!SystemTimeToTzSpecificLocalTimeEx
-kernel32.dll!TerminateProcess
-kernel32.dll!TryAcquireSRWLockExclusive
-kernel32.dll!TryAcquireSRWLockShared
-kernel32.dll!TryEnterCriticalSection
-kernel32.dll!TrySubmitThreadpoolCallback
-kernel32.dll!TzSpecificLocalTimeToSystemTime
-kernel32.dll!TzSpecificLocalTimeToSystemTimeEx
-kernel32.dll!UnlockFileEx
-kernel32.dll!UnmapViewOfFile
-kernel32.dll!VerifyScripts
-kernel32.dll!VirtualFree
-kernel32.dll!VirtualQuery
-kernel32.dll!WaitForMultipleObjects
-kernel32.dll!WaitForMultipleObjectsEx
-kernel32.dll!WaitForSingleObject
-kernel32.dll!WaitForSingleObjectEx
-kernel32.dll!WaitForThreadpoolIoCallbacks
-kernel32.dll!WaitForThreadpoolTimerCallbacks
-kernel32.dll!WaitForThreadpoolWaitCallbacks
-kernel32.dll!WaitForThreadpoolWorkCallbacks
-kernel32.dll!WakeAllConditionVariable
-kernel32.dll!WakeConditionVariable
-kernel32.dll!WerRegisterFile
-kernel32.dll!WerRegisterMemoryBlock
-kernel32.dll!WerUnregisterFile
-kernel32.dll!WerUnregisterMemoryBlock
-kernel32.dll!WideCharToMultiByte
-kernel32.dll!WriteFile
-normaliz.dll!IdnToAscii
-normaliz.dll!IdnToNameprepUnicode
-normaliz.dll!IdnToUnicode
-ole32.dll!CLSIDFromString
-ole32.dll!CoCreateFreeThreadedMarshaler
-ole32.dll!CoCreateGuid
-ole32.dll!CoCreateInstanceFromApp
-ole32.dll!CoDisconnectObject
-ole32.dll!CoFreeUnusedLibraries
-ole32.dll!CoFreeUnusedLibrariesEx
-ole32.dll!CoGetApartmentType
-ole32.dll!CoGetContextToken
-ole32.dll!CoGetCurrentLogicalThreadId
-ole32.dll!CoGetInterfaceAndReleaseStream
-ole32.dll!CoGetMarshalSizeMax
-ole32.dll!CoGetObjectContext
-ole32.dll!CoGetStandardMarshal
-ole32.dll!CoInitializeEx
-ole32.dll!CoInitializeSecurity
-ole32.dll!CoMarshalInterface
-ole32.dll!CoMarshalInterThreadInterfaceInStream
-ole32.dll!CoRegisterClassObject
-ole32.dll!CoReleaseMarshalData
-ole32.dll!CoResumeClassObjects
-ole32.dll!CoRevokeClassObject
-ole32.dll!CoSuspendClassObjects
-ole32.dll!CoSwitchCallContext
-ole32.dll!CoTaskMemAlloc
-ole32.dll!CoTaskMemFree
-ole32.dll!CoTaskMemRealloc
-ole32.dll!CoUninitialize
-ole32.dll!CoUnmarshalInterface
-ole32.dll!CreateILockBytesOnHGlobal
-ole32.dll!CreateStreamOnHGlobal
-ole32.dll!CStdAsyncStubBuffer_AddRef
-ole32.dll!CStdAsyncStubBuffer_Connect
-ole32.dll!CStdAsyncStubBuffer_Disconnect
-ole32.dll!CStdAsyncStubBuffer_Invoke
-ole32.dll!CStdAsyncStubBuffer_QueryInterface
-ole32.dll!CStdAsyncStubBuffer_Release
-ole32.dll!CStdAsyncStubBuffer2_Connect
-ole32.dll!CStdAsyncStubBuffer2_Disconnect
-ole32.dll!CStdAsyncStubBuffer2_Release
-ole32.dll!CStdStubBuffer2_Connect
-ole32.dll!CStdStubBuffer2_CountRefs
-ole32.dll!CStdStubBuffer2_Disconnect
-ole32.dll!CStdStubBuffer2_QueryInterface
-ole32.dll!FmtIdToPropStgName
-ole32.dll!FreePropVariantArray
-ole32.dll!GetConvertStg
-ole32.dll!GetHGlobalFromILockBytes
-ole32.dll!GetHGlobalFromStream
-ole32.dll!IIDFromString
-ole32.dll!NdrProxyForwardingFunction10
-ole32.dll!NdrProxyForwardingFunction11
-ole32.dll!NdrProxyForwardingFunction12
-ole32.dll!NdrProxyForwardingFunction13
-ole32.dll!NdrProxyForwardingFunction14
-ole32.dll!NdrProxyForwardingFunction15
-ole32.dll!NdrProxyForwardingFunction16
-ole32.dll!NdrProxyForwardingFunction17
-ole32.dll!NdrProxyForwardingFunction18
-ole32.dll!NdrProxyForwardingFunction19
-ole32.dll!NdrProxyForwardingFunction20
-ole32.dll!NdrProxyForwardingFunction21
-ole32.dll!NdrProxyForwardingFunction22
-ole32.dll!NdrProxyForwardingFunction23
-ole32.dll!NdrProxyForwardingFunction24
-ole32.dll!NdrProxyForwardingFunction25
-ole32.dll!NdrProxyForwardingFunction26
-ole32.dll!NdrProxyForwardingFunction27
-ole32.dll!NdrProxyForwardingFunction28
-ole32.dll!NdrProxyForwardingFunction29
-ole32.dll!NdrProxyForwardingFunction3
-ole32.dll!NdrProxyForwardingFunction30
-ole32.dll!NdrProxyForwardingFunction31
-ole32.dll!NdrProxyForwardingFunction32
-ole32.dll!NdrProxyForwardingFunction4
-ole32.dll!NdrProxyForwardingFunction5
-ole32.dll!NdrProxyForwardingFunction6
-ole32.dll!NdrProxyForwardingFunction7
-ole32.dll!NdrProxyForwardingFunction8
-ole32.dll!NdrProxyForwardingFunction9
-ole32.dll!ObjectStublessClient10
-ole32.dll!ObjectStublessClient11
-ole32.dll!ObjectStublessClient12
-ole32.dll!ObjectStublessClient13
-ole32.dll!ObjectStublessClient14
-ole32.dll!ObjectStublessClient15
-ole32.dll!ObjectStublessClient16
-ole32.dll!ObjectStublessClient17
-ole32.dll!ObjectStublessClient18
-ole32.dll!ObjectStublessClient19
-ole32.dll!ObjectStublessClient20
-ole32.dll!ObjectStublessClient21
-ole32.dll!ObjectStublessClient22
-ole32.dll!ObjectStublessClient23
-ole32.dll!ObjectStublessClient24
-ole32.dll!ObjectStublessClient25
-ole32.dll!ObjectStublessClient26
-ole32.dll!ObjectStublessClient27
-ole32.dll!ObjectStublessClient28
-ole32.dll!ObjectStublessClient29
-ole32.dll!ObjectStublessClient3
-ole32.dll!ObjectStublessClient30
-ole32.dll!ObjectStublessClient31
-ole32.dll!ObjectStublessClient32
-ole32.dll!ObjectStublessClient4
-ole32.dll!ObjectStublessClient5
-ole32.dll!ObjectStublessClient6
-ole32.dll!ObjectStublessClient7
-ole32.dll!ObjectStublessClient8
-ole32.dll!ObjectStublessClient9
-ole32.dll!PropStgNameToFmtId
-ole32.dll!PropVariantClear
-ole32.dll!PropVariantCopy
-ole32.dll!ReadClassStg
-ole32.dll!ReadClassStm
-ole32.dll!RoGetAgileReference
-ole32.dll!StgCreateDocfile
-ole32.dll!StgCreateDocfileOnILockBytes
-ole32.dll!StgCreatePropSetStg
-ole32.dll!StgCreatePropStg
-ole32.dll!StgCreateStorageEx
-ole32.dll!StgIsStorageFile
-ole32.dll!StgIsStorageILockBytes
-ole32.dll!StgOpenPropStg
-ole32.dll!StgOpenStorage
-ole32.dll!StgOpenStorageEx
-ole32.dll!StgOpenStorageOnILockBytes
-ole32.dll!StgSetTimes
-ole32.dll!StringFromCLSID
-ole32.dll!StringFromGUID2
-ole32.dll!StringFromIID
-ole32.dll!WriteClassStg
-ole32.dll!WriteClassStm
-api-ms-win-core-memory-l1-1-3.dll!OpenFileMappingFromApp
-api-ms-win-core-memory-l1-1-3.dll!VirtualAllocFromApp
-api-ms-win-core-memory-l1-1-3.dll!VirtualProtectFromApp
-api-ms-win-core-winrt-error-l1-1-0.dll!GetRestrictedErrorInfo
-api-ms-win-core-winrt-error-l1-1-0.dll!RoCaptureErrorContext
-api-ms-win-core-winrt-error-l1-1-0.dll!RoFailFastWithErrorContext
-api-ms-win-core-winrt-error-l1-1-0.dll!RoGetErrorReportingFlags
-api-ms-win-core-winrt-error-l1-1-0.dll!RoOriginateError
-api-ms-win-core-winrt-error-l1-1-0.dll!RoOriginateErrorW
-api-ms-win-core-winrt-error-l1-1-0.dll!RoSetErrorReportingFlags
-api-ms-win-core-winrt-error-l1-1-0.dll!RoTransformError
-api-ms-win-core-winrt-error-l1-1-0.dll!RoTransformErrorW
-api-ms-win-core-winrt-error-l1-1-0.dll!SetRestrictedErrorInfo
-api-ms-win-core-winrt-robuffer-l1-1-0.dll!RoGetBufferMarshaler
diff --git a/build.cmd b/build.cmd
index 5f22be79c1..d51e834b2d 100644
--- a/build.cmd
+++ b/build.cmd
@@ -6,7 +6,9 @@ if /I [%1] == [-?] goto Usage
:Build
call %~dp0build-native.cmd %*
if NOT [%ERRORLEVEL%]==[0] exit /b 1
-call %~dp0build-managed.cmd %*
+call %~dp0build-managed.cmd -FilterToOSGroup=Windows_NT %*
+if NOT [%ERRORLEVEL%]==[0] exit /b 1
+call %~dp0build-tests.cmd %*
exit /b %ERRORLEVEL%
:Usage
diff --git a/build.proj b/build.proj
index 41a17b6750..39ac5727a2 100644
--- a/build.proj
+++ b/build.proj
@@ -39,6 +39,12 @@
</Project>
-->
</ItemGroup>
+
+ <ItemGroup Condition="$(BuildTests)=='true'">
+ <Project Include="src\tests.builds">
+ <InputOSGroup>$(InputOSGroup)</InputOSGroup>
+ </Project>
+ </ItemGroup>
<Import Project="dir.targets" />
@@ -87,14 +93,9 @@
<TestDependencyListFile Include="$(BinDir)/TestDependencies/*.dependencylist.txt" />
</ItemGroup>
- <PropertyGroup>
- <TestArchiveDir>$(TestWorkingDir)$(OSPlatformConfig)/archive/tests/</TestArchiveDir>
- <TestArchiveDir Condition="'$(TestTFM)' != ''">$(TestArchiveDir)$(TestTFM)/</TestArchiveDir>
- </PropertyGroup>
-
<ZipFileCreateFromDependencyLists
DependencyListFiles="@(TestDependencyListFile)"
- DestinationArchive="$(TestArchiveDir)\Packages.zip"
+ DestinationArchive="$(TestWorkingDir)$(OSPlatformConfig)/archive/Packages.zip"
RelativePathBaseDirectory="$(PackagesDir)"
OverwriteDestination="true" />
</Target>
@@ -102,6 +103,8 @@
<!-- Override CleanAllProjects from dir.traversal.targets and just remove the full BinDir -->
<Target Name="CleanAllProjects">
<RemoveDir Directories="$(BinDir)" />
+ <!-- Temporarily outside BinDir -->
+ <RemoveDir Directories="$(PackageInstallPath)" />
</Target>
<!-- Hook that can be used to insert custom build tasks to the build process such as setup and/or cleanup tasks -->
diff --git a/build.sh b/build.sh
index d8a0d6c18b..0dd3ed5a28 100755
--- a/build.sh
+++ b/build.sh
@@ -23,11 +23,57 @@ fi
__scriptpath=$(cd "$(dirname "$0")"; pwd -P)
-"$__scriptpath/build-native.sh" $*
+__ServerGC=0
+__IsCentos=0
+__IsOSX=0
+
+while :; do
+ if [ $# -le 0 ]; then
+ break
+ fi
+
+ if [[ $1 == *"centos.7"* ]] ; then
+ __IsCentos=1
+ fi
+
+ if [[ $1 == *"osx.10"* ]] ; then
+ __IsOSX=1
+ fi
+
+ lowerI="$(echo $1 | awk '{print tolower($0)}')"
+ case $lowerI in
+ useservergc)
+ __ServerGC=1
+ ;;
+ *)
+ __UnprocessedBuildArgs="$__UnprocessedBuildArgs $1"
+ esac
+
+ shift
+done
+
+export CORECLR_SERVER_GC="$__ServerGC"
+
+"$__scriptpath/build-native.sh" $__UnprocessedBuildArgs
if [ $? -ne 0 ];then
exit 1
fi
-"$__scriptpath/build-managed.sh" $*
-exit $?
+if [ $__IsCentos -eq 1 ] ; then
+ "$__scriptpath/build-packages.sh" -DisableManagedPackage -FilterToOSGroup=rhel.7 $__UnprocessedBuildArgs
+elif [ $__IsOSX -eq 1 ] ; then
+ "$__scriptpath/build-packages.sh" -DisableManagedPackage -FilterToOSGroup=osx.10 $__UnprocessedBuildArgs
+else
+ "$__scriptpath/build-packages.sh" -DisableManagedPackage $__UnprocessedBuildArgs
+fi
+if [ $? -ne 0 ];then
+ exit 1
+fi
+"$__scriptpath/build-managed.sh" $__UnprocessedBuildArgs
+if [ $? -ne 0 ];then
+ exit 1
+fi
+
+"$__scriptpath/build-tests.sh" $__UnprocessedBuildArgs
+exit $?
diff --git a/buildpipeline/DotNet-Trusted-Publish.json b/buildpipeline/DotNet-Trusted-Publish.json
index 0787a968f4..eac1628e72 100644
--- a/buildpipeline/DotNet-Trusted-Publish.json
+++ b/buildpipeline/DotNet-Trusted-Publish.json
@@ -286,7 +286,7 @@
"scriptType": "inlineScript",
"scriptName": "",
"arguments": "-gitHubAuthToken $(UpdatePublishedVersions.AuthToken) -root $(Pipeline.SourcesDirectory)",
- "inlineScript": "param($gitHubAuthToken, $root)\nif ($env:ConfigurationGroup -ne \"Release\") { exit }\ncd $root\n. $root\\UpdatePublishedVersions.ps1 `\n -gitHubUser dotnet-helix-bot -gitHubEmail dotnet-helix-bot@microsoft.com `\n -gitHubAuthToken $gitHubAuthToken `\n -versionsRepoOwner $env:VersionsRepoOwner -versionsRepo versions `\n -versionsRepoPath build-info/dotnet/$env:GitHubRepositoryName/$env:SourceBranch `\n -nupkgPath $root\\packages\\AzureTransfer\\$env:ConfigurationGroup\\$env:AzureContainerPackageGlob",
+ "inlineScript": "param($gitHubAuthToken, $root)\nif ($env:ConfigurationGroup -ne \"Release\") { exit }\ncd $root\n. $root\\UpdatePublishedVersions.ps1 `\n -gitHubUser dotnet-build-bot -gitHubEmail dotnet-build-bot@microsoft.com `\n -gitHubAuthToken $gitHubAuthToken `\n -versionsRepoOwner $env:VersionsRepoOwner -versionsRepo versions `\n -versionsRepoPath build-info/dotnet/$env:GitHubRepositoryName/$env:SourceBranch `\n -nupkgPath $root\\packages\\AzureTransfer\\$env:ConfigurationGroup\\$env:AzureContainerPackageGlob",
"workingFolder": "",
"failOnStandardError": "true"
}
@@ -315,7 +315,7 @@
"enabled": true,
"continueOnError": true,
"alwaysRun": false,
- "displayName": "Publish to Artifact Services Drop",
+ "displayName": "Publish to Artifact Services Drop (BuildNumber)",
"timeoutInMinutes": 0,
"task": {
"id": "f9d96d25-0c81-4e77-8282-1ad1f785cbb4",
@@ -333,6 +333,27 @@
}
},
{
+ "enabled": true,
+ "continueOnError": true,
+ "alwaysRun": false,
+ "displayName": "Publish to Artifact Services Drop (OfficialBuildId)",
+ "timeoutInMinutes": 0,
+ "task": {
+ "id": "f9d96d25-0c81-4e77-8282-1ad1f785cbb4",
+ "versionSpec": "*",
+ "definitionType": "task"
+ },
+ "inputs": {
+ "dropServiceURI": "https://devdiv.artifacts.visualstudio.com/DefaultCollection",
+ "buildNumber": "dotnet/$(GitHubRepositoryName)/$(SourceBranch)/$(OfficialBuildId)/packages/$(ConfigurationGroup)",
+ "sourcePath": "$(Pipeline.SourcesDirectory)\\packages\\AzureTransfer\\$(ConfigurationGroup)",
+ "dropExePath": "",
+ "toLowerCase": "true",
+ "detailedLog": "false",
+ "usePat": "false"
+ }
+ },
+ {
"enabled": false,
"continueOnError": false,
"alwaysRun": false,
@@ -560,9 +581,6 @@
"UseLegacyBuildScripts": {
"value": "false",
"allowOverride": true
- },
- "ToolPackageSource": {
- "value": "https://www.myget.org/F/dagood-test-buildtools/api/v3/index.json"
}
},
"retentionRules": [
diff --git a/config.json b/config.json
index e494932ef6..484b77ad3d 100644
--- a/config.json
+++ b/config.json
@@ -159,7 +159,7 @@
"BuildArchitecture": {
"description": "Sets the value of the build architecture.",
"valueType": "passThrough",
- "values": ["x86", "arm", "arm-softfp", "x64", "arm64"],
+ "values": ["x86", "arm", "armel", "x64", "arm64"],
"defaultValue": "${CPUArch}"
},
"CmakeBuildType": {
@@ -180,6 +180,12 @@
"values": ["Numeric values"],
"defaultValue": "--numproc ${ProcessorCount}"
},
+ "AdditionalArgs": {
+ "description": "Pass additional arguments to the native_build script",
+ "valueType": "passThrough",
+ "values": [],
+ "defaultValue": ""
+ },
"Project": {
"description": "Project where the commands are going to be applied.",
"valueType": "passThrough",
@@ -198,6 +204,12 @@
"values": [],
"defaultValue": ""
},
+ "RestoreForTestsAgainstPackagesOnly": {
+ "description": "MsBuild target that restores the packages.",
+ "valueType": "property",
+ "values": ["true", "false"],
+ "defaultValue": "true"
+ },
"GenerateVersionHeader": {
"description": "MsBuild target that generates the version header.",
"valueType": "target",
@@ -227,7 +239,7 @@
"valueType": "target",
"values": [],
"defaultValue": ""
- }
+ }
},
"commands": {
"build-managed": {
@@ -248,6 +260,12 @@
"MsBuildLogging":"/flp:v=normal;LogFile=build-packages.log"
}
},
+ "portableLinux":{
+ "description": "Make the build-native script generate binaries that are portable over glibc based Linux distros.",
+ "settings": {
+ "FilterToOSGroup":"linux"
+ }
+ },
"tests": {
"description": "Builds the tests that are in the repository, doesn't restore packages.",
"settings": {
@@ -316,6 +334,7 @@
"toolName": "msbuild",
"settings": {
"TargetOS": "default",
+ "BuildTests": false,
"ConfigurationGroup": "default",
"MsBuildLogging":"default",
"MsBuildWarning":"default",
@@ -348,6 +367,12 @@
"settings": {
"HostOs": "default"
}
+ },
+ "portableLinux":{
+ "description": "Make the build-native script generate binaries that are portable over glibc based Linux distros.",
+ "settings": {
+ "AdditionalArgs": "portableLinux"
+ }
}
},
"defaultValues": {
@@ -357,7 +382,8 @@
"BuildArchitecture": "default",
"CmakeBuildType": "default",
"HostOs": "default",
- "ProcessorCount": "default",
+ "ProcessorCount": "default",
+ "AdditionalArgs": "default",
"ToolSetDir": "default"
}
}
@@ -384,7 +410,6 @@
}
},
"defaultValues": {
- "defaultAlias": "b",
"toolName": "msbuild",
"settings": {
"MsBuildLogging":"/flp:v=normal;LogFile=clean.log"
@@ -496,7 +521,7 @@
}
},
"defaultValues": {
- "defaultAlias": "p",
+ "defaultAlias": "p",
"toolName": "msbuild",
"settings": {
"MsBuildLogging":"/flp:v=normal;LogFile=sync.log"
diff --git a/cross/arm-softfp/sources.list.jessie b/cross/arm-softfp/sources.list.jessie
deleted file mode 100644
index 5b8510e5e7..0000000000
--- a/cross/arm-softfp/sources.list.jessie
+++ /dev/null
@@ -1,6 +0,0 @@
-deb http://ftp.debian.org/debian/ jessie main contrib non-free
-deb-src http://ftp.debian.org/debian/ jessie main contrib non-free
-
-# lldb-3.6-dev is unavailable in jessie
-deb http://ftp.debian.org/debian/ stretch main contrib non-free
-deb-src http://ftp.debian.org/debian/ stretch main contrib non-free
diff --git a/cross/arm/sources.list.xenial b/cross/arm/sources.list.xenial
new file mode 100644
index 0000000000..eacd86b7df
--- /dev/null
+++ b/cross/arm/sources.list.xenial
@@ -0,0 +1,11 @@
+deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
+
+deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse \ No newline at end of file
diff --git a/cross/arm64/sources.list.xenial b/cross/arm64/sources.list.xenial
new file mode 100644
index 0000000000..eacd86b7df
--- /dev/null
+++ b/cross/arm64/sources.list.xenial
@@ -0,0 +1,11 @@
+deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
+
+deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
+deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse \ No newline at end of file
diff --git a/cross/armel/sources.list.jessie b/cross/armel/sources.list.jessie
new file mode 100644
index 0000000000..d63875ae2a
--- /dev/null
+++ b/cross/armel/sources.list.jessie
@@ -0,0 +1,7 @@
+deb http://ftp.debian.org/debian/ jessie main contrib non-free
+deb-src http://ftp.debian.org/debian/ jessie main contrib non-free
+
+# Stable repo is the only repo that has llvm for armel
+deb http://ftp.debian.org/debian/ stable main contrib non-free
+deb-src http://ftp.debian.org/debian/ stable main contrib non-free
+
diff --git a/cross/arm-softfp/toolchain.cmake b/cross/armel/toolchain.cmake
index 2985ce5442..2985ce5442 100644
--- a/cross/arm-softfp/toolchain.cmake
+++ b/cross/armel/toolchain.cmake
diff --git a/cross/arm-softfp/tryrun.cmake b/cross/armel/tryrun.cmake
index f6d9159caa..f6d9159caa 100644
--- a/cross/arm-softfp/tryrun.cmake
+++ b/cross/armel/tryrun.cmake
diff --git a/cross/build-rootfs.sh b/cross/build-rootfs.sh
index 52378d6eaa..ae19804701 100755
--- a/cross/build-rootfs.sh
+++ b/cross/build-rootfs.sh
@@ -3,9 +3,8 @@
usage()
{
echo "Usage: $0 [BuildArch] [UbuntuCodeName]"
- echo "BuildArch can be: arm, arm-softfp, arm64"
- echo "UbuntuCodeName - optional, Code name for Ubuntu, can be: trusty(default), vivid, wily. If BuildArch is arm-softfp, UbuntuCodeName is ignored."
-
+ echo "BuildArch can be: arm, armel, arm64, x86"
+ echo "UbuntuCodeName - optional, Code name for Ubuntu, can be: trusty(default), vivid, wily, xenial. If BuildArch is armel, UbuntuCodeName is ignored."
exit 1
}
@@ -31,6 +30,8 @@ __UbuntuPackages+=" zlib1g-dev"
if [ -z "$LLVM_ARM_HOME" ]; then
__LLDB_Package="lldb-3.6-dev"
fi
+
+
__BuildArch=arm
__UbuntuArch=armhf
@@ -56,11 +57,15 @@ for i in "$@" ; do
__UbuntuArch=arm64
__MachineTriple=aarch64-linux-gnu
;;
- arm-softfp)
- __BuildArch=arm-softfp
+ x86)
+ __BuildArch=x86
+ __UbuntuArch=i386
+ __UbuntuRepo="http://archive.ubuntu.com/ubuntu"
+ ;;
+ armel)
+ __BuildArch=armel
__UbuntuArch=armel
__UbuntuRepo="http://ftp.debian.org/debian/"
- __UbuntuPackages+=" ${__LLDB_Package:-}"
__MachineTriple=arm-linux-gnueabi
__UbuntuCodeName=jessie
;;
@@ -74,6 +79,11 @@ for i in "$@" ; do
__UbuntuCodeName=wily
fi
;;
+ xenial)
+ if [ "$__UbuntuCodeName" != "jessie" ]; then
+ __UbuntuCodeName=xenial
+ fi
+ ;;
*)
__UnprocessedBuildArgs="$__UnprocessedBuildArgs $i"
;;
@@ -84,6 +94,11 @@ if [[ "$__BuildArch" == "arm" ]]; then
__UbuntuPackages+=" ${__LLDB_Package:-}"
fi
+if [ "$__BuildArch" == "armel" ]; then
+ __LLDB_Package="lldb-3.5-dev"
+ __UbuntuPackages+=" ${__LLDB_Package:-}"
+fi
+
__RootfsDir="$__CrossDir/rootfs/$__BuildArch"
if [[ -n "$ROOTFS_DIR" ]]; then
@@ -95,6 +110,7 @@ rm -rf $__RootfsDir
qemu-debootstrap --arch $__UbuntuArch $__UbuntuCodeName $__RootfsDir $__UbuntuRepo
cp $__CrossDir/$__BuildArch/sources.list.$__UbuntuCodeName $__RootfsDir/etc/apt/sources.list
chroot $__RootfsDir apt-get update
+chroot $__RootfsDir apt-get -f -y install
chroot $__RootfsDir apt-get -y install $__UbuntuPackages
chroot $__RootfsDir symlinks -cr /usr
umount $__RootfsDir/*
diff --git a/cross/x86/sources.list.trusty b/cross/x86/sources.list.trusty
new file mode 100644
index 0000000000..9b3085436e
--- /dev/null
+++ b/cross/x86/sources.list.trusty
@@ -0,0 +1,11 @@
+deb http://archive.ubuntu.com/ubuntu/ trusty main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ trusty main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ trusty-updates main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ trusty-updates main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ trusty-backports main restricted
+deb-src http://archive.ubuntu.com/ubuntu/ trusty-backports main restricted
+
+deb http://archive.ubuntu.com/ubuntu/ trusty-security main restricted universe multiverse
+deb-src http://archive.ubuntu.com/ubuntu/ trusty-security main restricted universe multiverse
diff --git a/cross/x86/sources.list.vivid b/cross/x86/sources.list.vivid
new file mode 100644
index 0000000000..26d37b20fc
--- /dev/null
+++ b/cross/x86/sources.list.vivid
@@ -0,0 +1,11 @@
+deb http://archive.ubuntu.com/ubuntu/ vivid main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ vivid main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ vivid-updates main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ vivid-updates main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ vivid-backports main restricted
+deb-src http://archive.ubuntu.com/ubuntu/ vivid-backports main restricted
+
+deb http://archive.ubuntu.com/ubuntu/ vivid-security main restricted universe multiverse
+deb-src http://archive.ubuntu.com/ubuntu/ vivid-security main restricted universe multiverse
diff --git a/cross/x86/sources.list.wily b/cross/x86/sources.list.wily
new file mode 100644
index 0000000000..c4b0b442ab
--- /dev/null
+++ b/cross/x86/sources.list.wily
@@ -0,0 +1,11 @@
+deb http://archive.ubuntu.com/ubuntu/ wily main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ wily main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ wily-updates main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ wily-updates main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ wily-backports main restricted
+deb-src http://archive.ubuntu.com/ubuntu/ wily-backports main restricted
+
+deb http://archive.ubuntu.com/ubuntu/ wily-security main restricted universe multiverse
+deb-src http://archive.ubuntu.com/ubuntu/ wily-security main restricted universe multiverse
diff --git a/cross/x86/sources.list.xenial b/cross/x86/sources.list.xenial
new file mode 100644
index 0000000000..ad9c5a0144
--- /dev/null
+++ b/cross/x86/sources.list.xenial
@@ -0,0 +1,11 @@
+deb http://archive.ubuntu.com/ubuntu/ xenial main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe
+deb-src http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe
+
+deb http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted
+deb-src http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted
+
+deb http://archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse
+deb-src http://archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse
diff --git a/cross/x86/toolchain.cmake b/cross/x86/toolchain.cmake
new file mode 100644
index 0000000000..1d68ec5e9b
--- /dev/null
+++ b/cross/x86/toolchain.cmake
@@ -0,0 +1,23 @@
+set(CROSS_ROOTFS $ENV{ROOTFS_DIR})
+
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_VERSION 1)
+set(CMAKE_SYSTEM_PROCESSOR x86)
+
+add_compile_options("-m32")
+add_compile_options("--sysroot=${CROSS_ROOTFS}")
+
+set(CROSS_LINK_FLAGS "${CROSS_LINK_FLAGS} --sysroot=${CROSS_ROOTFS}")
+set(CROSS_LINK_FLAGS "${CROSS_LINK_FLAGS} -B ${CROSS_ROOTFS}/usr/lib/gcc/i686-linux-gnu")
+set(CROSS_LINK_FLAGS "${CROSS_LINK_FLAGS} -L${CROSS_ROOTFS}/lib/i386-linux-gnu")
+set(CROSS_LINK_FLAGS "${CROSS_LINK_FLAGS} -m32")
+
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CROSS_LINK_FLAGS}" CACHE STRING "" FORCE)
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${CROSS_LINK_FLAGS}" CACHE STRING "" FORCE)
+set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${CROSS_LINK_FLAGS}" CACHE STRING "" FORCE)
+
+set(CMAKE_FIND_ROOT_PATH "${CROSS_ROOTFS}")
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
diff --git a/cross/x86/tryrun.cmake b/cross/x86/tryrun.cmake
new file mode 100644
index 0000000000..1ae9e2c3b5
--- /dev/null
+++ b/cross/x86/tryrun.cmake
@@ -0,0 +1,7 @@
+SET( HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP_EXITCODE
+ 0
+ CACHE STRING "Result from TRY_RUN" FORCE)
+SET( HAVE_CLOCK_MONOTONIC_EXITCODE
+ 0
+ CACHE STRING "Result from TRY_RUN" FORCE)
+
diff --git a/dependencies.props b/dependencies.props
index 286d68fd43..d7eb85680b 100644
--- a/dependencies.props
+++ b/dependencies.props
@@ -17,18 +17,18 @@
These ref versions are pulled from https://github.com/dotnet/versions.
-->
<PropertyGroup>
- <CoreFxCurrentRef>10ae672d2e13fb79101a4991f2643cca01208075</CoreFxCurrentRef>
+ <CoreFxCurrentRef>3c36f9bf01e35591e1bf30fdac512f863643f54f</CoreFxCurrentRef>
<CoreClrCurrentRef>71ca1111dc90eb30ceaafbdb1144dd411d712385</CoreClrCurrentRef>
<ExternalCurrentRef>4e2952b5114bfa90cc45eef908204006a771a62b</ExternalCurrentRef>
- <ProjectNTfsCurrentRef>efe21f521cf97ceb681deeeab390261eb9506552</ProjectNTfsCurrentRef>
+ <ProjectNTfsCurrentRef>3c36f9bf01e35591e1bf30fdac512f863643f54f</ProjectNTfsCurrentRef>
</PropertyGroup>
<!-- Auto-upgraded properties for each build info dependency. -->
<PropertyGroup>
- <CoreFxExpectedPrerelease>beta-24721-02</CoreFxExpectedPrerelease>
+ <CoreFxExpectedPrerelease>beta-24904-01</CoreFxExpectedPrerelease>
<CoreClrExpectedPrerelease>beta-24904-03</CoreClrExpectedPrerelease>
<ExternalExpectedPrerelease>beta-24727-00</ExternalExpectedPrerelease>
- <ProjectNTfsExpectedPrerelease>beta-24728-00</ProjectNTfsExpectedPrerelease>
+ <ProjectNTfsExpectedPrerelease>beta-24904-00</ProjectNTfsExpectedPrerelease>
</PropertyGroup>
<!-- Full package version strings that are used in other parts of the build. -->
diff --git a/dir.props b/dir.props
index 9ff9e7c0ae..228c12e42c 100644
--- a/dir.props
+++ b/dir.props
@@ -32,7 +32,7 @@
<PropertyGroup>
<BuildToolsTargets45 Condition="'$(OsEnvironment)'=='Windows_NT'">true</BuildToolsTargets45>
</PropertyGroup>
-
+
<!-- Common repo directories -->
<PropertyGroup>
<ProjectDir>$(MSBuildThisFileDirectory)</ProjectDir>
@@ -49,6 +49,10 @@
<!-- Input Directories -->
<PackagesDir Condition="'$(PackagesDir)'==''">$(ProjectDir)packages/</PackagesDir>
+
+ <!-- Temporarily outside BinDir -->
+ <PackageInstallPath>$(ProjectDir)bin.localpkg/</PackageInstallPath>
+
<ToolsDir Condition="'$(UseToolRuntimeForToolsDir)'=='true'">$(ToolRuntimePath)</ToolsDir>
<ToolsDir Condition="'$(ToolsDir)'==''">$(ProjectDir)Tools/</ToolsDir>
<ToolRuntimePath Condition="'$(ToolRuntimePath)'==''">$(ToolsDir)</ToolRuntimePath>
@@ -100,7 +104,6 @@
/t:BatchRestorePackages /p:OverridePackageSource=C:\coreclr\bin\Product\Windows_NT.x64.Debug\.nuget\pkg
-->
<DnuSourceList Include="$(OverridePackageSource)" />
- <!-- PackagesDrops is passed in via the commandline "/p:PackagesDrops=[drop location]" -->
<DnuSourceList Condition="'$(BuildTestsAgainstPackages)' == 'true'" Include="$(PackagesDrops)" />
<!-- Need to escape double forward slash (%2F) or MSBuild will normalize to one slash on Unix. -->
<!-- Including buildtools to pull in TestSuite packages and repackaged xunit dependencies-->
@@ -108,19 +111,30 @@
<DnuSourceList Include="https:%2F%2Fdotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<DnuSourceList Include="https:%2F%2Fwww.nuget.org/api/v2/" />
</ItemGroup>
-
+
+ <ItemGroup>
+ <DnuSourceList Condition="'$(BuildTestsAgainstPackages)' == 'true' and '$(RestoreForTestsAgainstPackagesOnly)' == 'true'" Include="$(PackageInstallPath)" />
+ </ItemGroup>
+
<!-- This is the directory where we dynamically generate project.json's for our test build package dependencies -->
<PropertyGroup Condition="'$(BuildTestsAgainstPackages)' == 'true'">
<BuildTestsAgainstPackagesIdentityRegex>$(CoreFxVersionsIdentityRegex)</BuildTestsAgainstPackagesIdentityRegex>
<SkipVerifyPackageVersions>true</SkipVerifyPackageVersions>
</PropertyGroup>
+
+ <!-- When restoring test projects with generated project.json's (during build.cmd), only restore using local packages -->
+ <PropertyGroup Condition="'$(RestoreForTestsAgainstPackagesOnly)' == 'true'">
+ <ExcludeInternetFeeds Condition="'$(ExcludeInternetFeeds)' == ''">true</ExcludeInternetFeeds>
+ <ExcludeNonTestRestores Condition="'$(ExcludeNonTestRestores)' == ''">true</ExcludeNonTestRestores>
+ </PropertyGroup>
+
<!-- list of directories to perform batch restore -->
<ItemGroup>
- <DnuRestoreDir Include="$(MSBuildThisFileDirectory)src" />
- <DnuRestoreDir Include="$(MSBuildThisFileDirectory)pkg" />
- <DnuRestoreDir Include="$(MSBuildThisFileDirectory)layout" />
- <DnuRestoreDir Condition="'$(BuildTestsAgainstPackages)' == 'true'" Include="$(GeneratedProjectJsonDir)" />
+ <DnuRestoreDir Include="$(MSBuildThisFileDirectory)src/" />
+ <DnuRestoreDir Condition="'$(ExcludeNonTestRestores)' != 'true'" Include="$(MSBuildThisFileDirectory)pkg/" />
+ <DnuRestoreDir Condition="'$(ExcludeNonTestRestores)' != 'true'" Include="$(MSBuildThisFileDirectory)layout" />
+ <DnuRestoreDir Condition="'$(BuildTestsAgainstPackages)' == 'true'" Include="$(GeneratedProjectJsonDir)/" />
</ItemGroup>
<PropertyGroup>
@@ -135,11 +149,16 @@
<DnuRestoreCommand>"$(DnuToolPath)"</DnuRestoreCommand>
<DnuRestoreCommand>$(DnuRestoreCommand) restore</DnuRestoreCommand>
+
+ <DnuRestoreCommandForBuildTestsAgainstPackages Condition="'$(BuildTestsAgainstPackages)' == 'true' and '$(RestoreForTestsAgainstPackagesOnly)' == 'true'">$(DnuRestoreCommand) --packages "$(PackageInstallPath)" --source $(PackagesDir)</DnuRestoreCommandForBuildTestsAgainstPackages>
+
<DnuRestoreCommand Condition="'$(ParallelRestore)'=='true'">$(DnuRestoreCommand) --parallel</DnuRestoreCommand>
<DnuRestoreCommand Condition="'$(UseNuGetHttpCache)'!='true'">$(DnuRestoreCommand) --no-cache</DnuRestoreCommand>
<DnuRestoreCommand>$(DnuRestoreCommand) --packages "$(PackagesDir.TrimEnd('/\'.ToCharArray()))" $(DnuRestoreSource)</DnuRestoreCommand>
<DnuRestoreCommand Condition="'$(LockDependencies)' == 'true'">$(DnuRestoreCommand) --lock</DnuRestoreCommand>
<DnuRestoreCommand Condition="'$(NuGetConfigPath)'!=''">$(DnuRestoreCommand) --configfile $(NuGetConfigPath)</DnuRestoreCommand>
+
+ <DnuRestoreCommand Condition="'$(BuildTestsAgainstPackages)' == 'true' and '$(RestoreForTestsAgainstPackagesOnly)' == 'true'">$(DnuRestoreCommandForBuildTestsAgainstPackages)</DnuRestoreCommand>
</PropertyGroup>
<PropertyGroup>
@@ -196,6 +215,8 @@
<TestTFM Condition="'$(TestTFM)'==''">$(DefaultTestTFM)</TestTFM>
<!-- we default FilterToTestTFM to DefaultTestTFM if it is not explicity defined -->
<FilterToTestTFM Condition="'$(FilterToTestTFM)'==''">$(DefaultTestTFM)</FilterToTestTFM>
+ <!-- FilterTestNugetTargetMoniker needs to stay in the long form to be used for Framework and Runtime filtering purposes -->
+ <FilterTestNugetTargetMoniker Condition="'$(FilterTestNugetTargetMoniker)'==''">.NETCoreApp,Version=v1.1</FilterTestNugetTargetMoniker>
</PropertyGroup>
<PropertyGroup>
@@ -261,6 +282,11 @@
<PackagesBasePath Condition="'$(PackagesBasePath)'==''">$(BinDir)$(OSPlatformConfig)</PackagesBasePath>
<PackageOutputPath Condition="'$(PackageOutputPath)'==''">$(PackageOutputRoot)$(ConfigurationGroup)/</PackageOutputPath>
<SymbolPackageOutputPath Condition="'$(SymbolPackageOutputPath)'==''">$(PackageOutputPath)symbols/</SymbolPackageOutputPath>
+
+ <!-- When testing against packages, we want to run against just the localpackages cache -->
+ <PackagesDir Condition="'$(BuildTestsAgainstPackages)'=='true'">$(PackageInstallPath)</PackagesDir>
+ <!-- PackageDrops is set to the bin folder where packages are built to generate the new test project.json for these -->
+ <PackagesDrops Condition="'$(PackagesDrops)'==''">$(PackageOutputPath)</PackagesDrops>
</PropertyGroup>
<PropertyGroup>
diff --git a/dir.targets b/dir.targets
index ec87e07704..eb49097f02 100644
--- a/dir.targets
+++ b/dir.targets
@@ -55,13 +55,7 @@
<SuppressPackageTargetFrameworkCompatibility Include="uap10.1" />
</ItemGroup>
- <PropertyGroup Condition="'$(OSGroup)'=='Windows_NT' and '$(EnableDotnetAnalyzers)' == 'true'">
- <!-- Override pinvoke files from codeAnalysis.targets, to use Win32 API instead of API set -->
- <ValidPinvokeMappings>$(MSBuildThisFileDirectory)PinvokeAnalyzer_OneCoreApis.txt</ValidPinvokeMappings>
- <ValidPinvokeMappings Condition="'$(TargetGroup)'=='netcore50' or '$(TargetGroup)'=='netcore50aot' or '$(SupportsUWP)'=='true'">$(MSBuildThisFileDirectory)PinvokeAnalyzer_UWPApis.txt</ValidPinvokeMappings>
- </PropertyGroup>
-
- <Target Name="ProducesPackageId"
+ <Target Name="ProducesPackageId"
Returns="@(PackageIds)">
<ItemGroup>
<PackageIds Include="$(Id)" />
diff --git a/layout/ApiCompatBaseline.netfx461.txt b/layout/ApiCompatBaseline.netfx461.txt
index 24379dbfd3..fea38c6fb6 100644
--- a/layout/ApiCompatBaseline.netfx461.txt
+++ b/layout/ApiCompatBaseline.netfx461.txt
@@ -172,9 +172,6 @@ CannotRemoveBaseTypeOrInterface : Type 'System.ThreadStaticAttribute' does not i
CannotRemoveBaseTypeOrInterface : Type 'System.TimeoutException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.TimeZoneNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Type' does not implement interface 'System.Runtime.InteropServices._Type' in the implementation but it does in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Type.IsEnum' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Type.Equals(System.Type)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Type.IsEnum.get()' is non-virtual in the implementation but is virtual in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.TypeAccessException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
TypesMustExist : Type 'System.TypedReference' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.TypeInitializationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
@@ -240,17 +237,12 @@ MembersMustExist : Member 'System.IO.FileInfo.GetAccessControl(System.Security.A
MembersMustExist : Member 'System.IO.FileInfo.SetAccessControl(System.Security.AccessControl.FileSecurity)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.IO.FileLoadException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.IO.FileNotFoundException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.IO.FileStream..ctor(System.IntPtr, System.IO.FileAccess)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.IO.FileStream..ctor(System.IntPtr, System.IO.FileAccess, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.IO.FileStream..ctor(System.IntPtr, System.IO.FileAccess, System.Boolean, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.IO.FileStream..ctor(System.IntPtr, System.IO.FileAccess, System.Boolean, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.Security.AccessControl.FileSystemRights, System.IO.FileShare, System.Int32, System.IO.FileOptions)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.Security.AccessControl.FileSystemRights, System.IO.FileShare, System.Int32, System.IO.FileOptions, System.Security.AccessControl.FileSecurity)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.IO.FileStream.GetAccessControl()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.IO.FileStream.SetAccessControl(System.Security.AccessControl.FileSecurity)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.IO.IOException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.IO.PathTooLongException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-CannotMakeMemberAbstract : Member 'System.IO.TextWriter.Write(System.Char)' is abstract in the implementation but is not abstract in the contract.
MembersMustExist : Member 'System.IO.IsolatedStorage.IsolatedStorage.GetPermission(System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.IO.IsolatedStorage.IsolatedStorageException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
MembersMustExist : Member 'System.IO.IsolatedStorage.IsolatedStorageFile.GetPermission(System.Security.PermissionSet)' does not exist in the implementation but it does exist in the contract.
@@ -259,11 +251,7 @@ TypesMustExist : Type 'System.IO.IsolatedStorage.IsolatedStorageSecurityOptions'
TypesMustExist : Type 'System.IO.IsolatedStorage.IsolatedStorageSecurityState' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AmbiguousMatchException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Assembly' does not implement interface 'System.Runtime.InteropServices._Assembly' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.EscapedCodeBase.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.Evidence.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.GetFile(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.GetFiles()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.GetFiles(System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.Load(System.Byte[], System.Byte[], System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.Load(System.Byte[], System.Byte[], System.Security.SecurityContextSource)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.Load(System.Reflection.AssemblyName, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract.
@@ -271,7 +259,6 @@ MembersMustExist : Member 'System.Reflection.Assembly.Load(System.String, System
MembersMustExist : Member 'System.Reflection.Assembly.LoadFile(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.LoadFrom(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.LoadFrom(System.String, System.Security.Policy.Evidence, System.Byte[], System.Configuration.Assemblies.AssemblyHashAlgorithm)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Reflection.Assembly.LoadModule(System.String, System.Byte[], System.Byte[])' is non-virtual in the implementation but is virtual in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.LoadWithPartialName(System.String, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.PermissionSet.get()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyAlgorithmIdAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
@@ -289,7 +276,6 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyKeyFileAttribu
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyKeyNameAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyMetadataAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyName' does not implement interface 'System.Runtime.InteropServices._AssemblyName' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Reflection.AssemblyName.EscapedCodeBase.get()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyProductAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblySignatureKeyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AssemblyTitleAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
@@ -305,7 +291,6 @@ MembersMustExist : Member 'System.Reflection.FieldInfo.SetValueDirect(System.Typ
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.InvalidFilterCriteriaException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.MemberInfo' does not implement interface 'System.Runtime.InteropServices._MemberInfo' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.MethodBase' does not implement interface 'System.Runtime.InteropServices._MethodBase' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Reflection.MethodBase.IsSecuritySafeCritical.get()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.MethodInfo' does not implement interface 'System.Runtime.InteropServices._MethodInfo' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Module' does not implement interface 'System.Runtime.InteropServices._Module' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Reflection.Module.GetSignerCertificate()' does not exist in the implementation but it does exist in the contract.
@@ -314,7 +299,6 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ObfuscationAttribute'
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ParameterInfo' does not implement interface 'System.Runtime.InteropServices._ParameterInfo' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.PropertyInfo' does not implement interface 'System.Runtime.InteropServices._PropertyInfo' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ReflectionTypeLoadException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Reflection.StrongNameKeyPair..ctor(System.IO.FileStream)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TargetException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TargetInvocationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TargetParameterCountException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
@@ -333,8 +317,6 @@ MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineUnmanage
MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineVersionInfoResource()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.DefineVersionInfoResource(System.String, System.String, System.String, System.String, System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.Evidence.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.GetFile(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.GetFiles(System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.PermissionSet.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.Save(System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.AssemblyBuilder.Save(System.String, System.Reflection.PortableExecutableKinds, System.Reflection.ImageFileMachine)' does not exist in the implementation but it does exist in the contract.
@@ -356,7 +338,6 @@ TypesMustExist : Type 'System.Reflection.Emit.DynamicILInfo' does not exist in t
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.DynamicMethod' does not implement interface 'System.Runtime.InteropServices._MethodInfo' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Reflection.Emit.DynamicMethod.DefineParameter(System.Int32, System.Reflection.ParameterAttributes, System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.DynamicMethod.GetDynamicILInfo()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Emit.DynamicMethod.IsSecuritySafeCritical.get()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.Emit.EnumBuilder' does not implement interface 'System.Runtime.InteropServices._EnumBuilder' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Reflection.Emit.EnumBuilder.CreateType()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.EnumBuilder.TypeToken.get()' does not exist in the implementation but it does exist in the contract.
@@ -380,7 +361,6 @@ MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.AddDeclarativeSe
MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.CreateMethodBody(System.Byte[], System.Int32)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.GetModule()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.GetToken()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.IsSecuritySafeCritical.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.SetMarshal(System.Reflection.Emit.UnmanagedMarshal)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.SetMethodBody(System.Byte[], System.Int32, System.Byte[], System.Collections.Generic.IEnumerable<System.Reflection.Emit.ExceptionHandler>, System.Collections.Generic.IEnumerable<System.Int32>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Emit.MethodBuilder.SetSymCustomAttribute(System.String, System.Byte[])' does not exist in the implementation but it does exist in the contract.
@@ -522,7 +502,7 @@ TypesMustExist : Type 'System.Runtime.InteropServices._Type' does not exist in t
TypesMustExist : Type 'System.Runtime.InteropServices._TypeBuilder' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Runtime.InteropServices.AssemblyRegistrationFlags' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Runtime.InteropServices.AutomationProxyAttribute' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.AutomationProxyAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.BestFitMappingAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Runtime.InteropServices.BIND_OPTS' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.InteropServices.BINDPTR' does not exist in the implementation but it does exist in the contract.
@@ -541,7 +521,6 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComSource
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComUnregisterFunctionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComVisibleAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Runtime.InteropServices.CONNECTDATA' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.CriticalHandle.Close()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.DefaultCharSetAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Runtime.InteropServices.DESCKIND' does not exist in the implementation but it does exist in the contract.
@@ -578,27 +557,18 @@ TypesMustExist : Type 'System.Runtime.InteropServices.ITypeLibExporterNotifySink
TypesMustExist : Type 'System.Runtime.InteropServices.ITypeLibImporterNotifySink' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.LCIDConversionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Runtime.InteropServices.LIBFLAGS' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Runtime.InteropServices.ManagedToNativeComInteropStubAttribute' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.BindToMoniker(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.ChangeWrapperHandleStrength(System.Object, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.CleanupUnusedObjectsInCurrentContext()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GenerateGuidForType(System.Type)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GenerateProgIdForType(System.Type)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ManagedToNativeComInteropStubAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetActiveObject(System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetComInterfaceForObjectInContext(System.Object, System.Type)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetComObjectData(System.Object, System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetComSlotForMethodInfo(System.Reflection.MemberInfo)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetEndComSlot(System.Type)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetExceptionPointers()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Module)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetIDispatchForObject(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetIDispatchForObjectInContext(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetITypeInfoForType(System.Type)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetIUnknownForObjectInContext(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetManagedThunkForUnmanagedMethodPtr(System.IntPtr, System.IntPtr, System.Int32)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetMethodInfoForComSlot(System.Type, System.Int32, System.Runtime.InteropServices.ComMemberType)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetThreadFromFiberCookie(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(System.IntPtr, System.Type)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeForITypeInfo(System.IntPtr)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeInfoName(System.Runtime.InteropServices.UCOMITypeInfo)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibGuid(System.Runtime.InteropServices.ComTypes.ITypeLib)' does not exist in the implementation but it does exist in the contract.
@@ -612,10 +582,7 @@ MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetTypeLibVers
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.GetUnmanagedThunkForManagedMethodPtr(System.IntPtr, System.IntPtr, System.Int32)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.IsTypeVisibleFromCom(System.Type)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.NumParamBytes(System.Reflection.MethodInfo)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.PtrToStringAuto(System.IntPtr)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.PtrToStringAuto(System.IntPtr, System.Int32)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.ReleaseThreadCache()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.SetComObjectData(System.Object, System.Object, System.Object)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.MarshalAsAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.MarshalDirectiveException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Runtime.InteropServices.ObjectCreationDelegate' does not exist in the implementation but it does exist in the contract.
@@ -891,16 +858,7 @@ TypesMustExist : Type 'System.Security.AccessControl.CryptoKeyAuditRule' does no
TypesMustExist : Type 'System.Security.AccessControl.CryptoKeyRights' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.AccessControl.CryptoKeySecurity' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Security.AccessControl.PrivilegeNotHeldException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.Aes.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.Clear()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.FromXmlString(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.ToXmlString(System.Boolean)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.CryptoAPITransform' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.CryptoConfig' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Security.Cryptography.CryptographicException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Security.Cryptography.CryptographicUnexpectedOperationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Security.Cryptography.CspKeyContainerInfo.CryptoKeySecurity.get()' does not exist in the implementation but it does exist in the contract.
@@ -908,79 +866,27 @@ MembersMustExist : Member 'System.Security.Cryptography.CspParameters..ctor(Syst
MembersMustExist : Member 'System.Security.Cryptography.CspParameters..ctor(System.Int32, System.String, System.String, System.Security.AccessControl.CryptoKeySecurity, System.Security.SecureString)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.CspParameters.CryptoKeySecurity.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.CspParameters.CryptoKeySecurity.set(System.Security.AccessControl.CryptoKeySecurity)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.CspParameters.KeyPassword.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.CspParameters.KeyPassword.set(System.Security.SecureString)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DES.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSA.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSA.FromXmlString(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSA.ToXmlString(System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSACryptoServiceProvider.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSACryptoServiceProvider.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Int32 System.Security.Cryptography.HashAlgorithm.HashSizeValue' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HashAlgorithm.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HashAlgorithm.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HMAC.BlockSizeValue.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HMAC.BlockSizeValue.set(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HMAC.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HMAC.Create(System.String)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.HMACRIPEMD160' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.KeyedHashAlgorithm.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.KeyedHashAlgorithm.Create(System.String)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.MACTripleDES' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.MaskGenerationMethod' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.MD5.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.PaddingMode System.Security.Cryptography.PaddingMode.ANSIX923' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.PaddingMode System.Security.Cryptography.PaddingMode.ISO10126' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.PasswordDeriveBytes' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.PKCS1MaskGenerationMethod' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RandomNumberGenerator.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RC2.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.Rfc2898DeriveBytes.CryptDeriveKey(System.String, System.String, System.Int32, System.Byte[])' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.Rijndael.Create(System.String)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.RijndaelManagedTransform' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.RIPEMD160' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.RIPEMD160Managed' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.Decrypt(System.Byte[], System.Security.Cryptography.RSAEncryptionPadding)' is abstract in the implementation but is not abstract in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.Encrypt(System.Byte[], System.Security.Cryptography.RSAEncryptionPadding)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.FromXmlString(System.String)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.HashData(System.Byte[], System.Int32, System.Int32, System.Security.Cryptography.HashAlgorithmName)' is abstract in the implementation but is not abstract in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.HashData(System.IO.Stream, System.Security.Cryptography.HashAlgorithmName)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.SignHash(System.Byte[], System.Security.Cryptography.HashAlgorithmName, System.Security.Cryptography.RSASignaturePadding)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.ToXmlString(System.Boolean)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.VerifyHash(System.Byte[], System.Byte[], System.Security.Cryptography.HashAlgorithmName, System.Security.Cryptography.RSASignaturePadding)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSACryptoServiceProvider.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSACryptoServiceProvider.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SHA1.Create(System.String)' does not exist in the implementation but it does exist in the contract.
CannotSealType : Type 'System.Security.Cryptography.SHA1Managed' is sealed in the implementation but not sealed in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA1Managed.HashCore(System.Byte[], System.Int32, System.Int32)' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA1Managed.HashFinal()' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA1Managed.Initialize()' is non-virtual in the implementation but is virtual in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SHA256.Create(System.String)' does not exist in the implementation but it does exist in the contract.
CannotSealType : Type 'System.Security.Cryptography.SHA256Managed' is sealed in the implementation but not sealed in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA256Managed.HashCore(System.Byte[], System.Int32, System.Int32)' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA256Managed.HashFinal()' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA256Managed.Initialize()' is non-virtual in the implementation but is virtual in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SHA384.Create(System.String)' does not exist in the implementation but it does exist in the contract.
CannotSealType : Type 'System.Security.Cryptography.SHA384Managed' is sealed in the implementation but not sealed in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA384Managed.HashCore(System.Byte[], System.Int32, System.Int32)' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA384Managed.HashFinal()' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA384Managed.Initialize()' is non-virtual in the implementation but is virtual in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SHA512.Create(System.String)' does not exist in the implementation but it does exist in the contract.
CannotSealType : Type 'System.Security.Cryptography.SHA512Managed' is sealed in the implementation but not sealed in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA512Managed.HashCore(System.Byte[], System.Int32, System.Int32)' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA512Managed.HashFinal()' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Security.Cryptography.SHA512Managed.Initialize()' is non-virtual in the implementation but is virtual in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.SignatureDescription' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Int32 System.Security.Cryptography.SymmetricAlgorithm.FeedbackSizeValue' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.FeedbackSize.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.FeedbackSize.set(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.ValidKeySize(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.TripleDES.Create(System.String)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.CodeAccessSecurityAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.EnvironmentPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Security.Permissions.FileDialogPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
@@ -1048,22 +954,11 @@ MembersMustExist : Member 'System.Security.Principal.WindowsPrincipal.UserClaims
CannotRemoveBaseTypeOrInterface : Type 'System.Text.DecoderFallbackException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Text.EncoderFallbackException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.AbandonedMutexException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-TypesMustExist : Type 'System.Threading.AsyncFlowControl' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Threading.CompressedStack' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.EventWaitHandle..ctor(System.Boolean, System.Threading.EventResetMode, System.String, System.Boolean, System.Security.AccessControl.EventWaitHandleSecurity)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.EventWaitHandle.GetAccessControl()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.EventWaitHandle.OpenExisting(System.String, System.Security.AccessControl.EventWaitHandleRights)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.EventWaitHandle.SetAccessControl(System.Security.AccessControl.EventWaitHandleSecurity)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.EventWaitHandle.TryOpenExisting(System.String, System.Security.AccessControl.EventWaitHandleRights, System.Threading.EventWaitHandle)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ExecutionContext' does not implement interface 'System.IDisposable' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.CreateCopy()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.Dispose()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.IsFlowSuppressed()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.RestoreFlow()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.SuppressFlow()' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Threading.HostExecutionContext' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Threading.HostExecutionContextManager' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.LockRecursionException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Threading.Mutex..ctor(System.Boolean, System.String, System.Boolean, System.Security.AccessControl.MutexSecurity)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.Mutex.GetAccessControl()' does not exist in the implementation but it does exist in the contract.
@@ -1071,28 +966,11 @@ MembersMustExist : Member 'System.Threading.Mutex.OpenExisting(System.String, Sy
MembersMustExist : Member 'System.Threading.Mutex.SetAccessControl(System.Security.AccessControl.MutexSecurity)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.Mutex.TryOpenExisting(System.String, System.Security.AccessControl.MutexRights, System.Threading.Mutex)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.SemaphoreFullException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Threading.SynchronizationContext.IsWaitNotificationRequired()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.SynchronizationContext.SetWaitNotificationRequired()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.SynchronizationContext.Wait(System.IntPtr[], System.Boolean, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.SynchronizationContext.WaitHelper(System.IntPtr[], System.Boolean, System.Int32)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.SynchronizationLockException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Thread' does not implement interface 'System.Runtime.InteropServices._Thread' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Threading.Thread.CurrentContext.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.Thread.DisableComObjectEagerCleanup()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.Thread.GetCompressedStack()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.Thread.SetCompressedStack(System.Threading.CompressedStack)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ThreadAbortException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ThreadInterruptedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.GetAvailableThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.GetMaxThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.GetMinThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.SetMaxThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.SetMinThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeQueueUserWorkItem(System.Threading.WaitCallback, System.Object)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle, System.Threading.WaitOrTimerCallback, System.Object, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle, System.Threading.WaitOrTimerCallback, System.Object, System.Int64, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle, System.Threading.WaitOrTimerCallback, System.Object, System.TimeSpan, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle, System.Threading.WaitOrTimerCallback, System.Object, System.UInt32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ThreadStartException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ThreadStateException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.WaitHandleCannotBeOpenedException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
@@ -1281,12 +1159,11 @@ TypesMustExist : Type 'System.Diagnostics.PerformanceCounterPermissionAttribute'
TypesMustExist : Type 'System.Diagnostics.PerformanceCounterPermissionEntry' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Diagnostics.PerformanceCounterPermissionEntryCollection' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Diagnostics.PerformanceCounterType' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Diagnostics.Process.Start(System.String, System.String, System.Security.SecureString, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Diagnostics.Process.Start(System.String, System.String, System.String, System.Security.SecureString, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Diagnostics.ProcessStartInfo.Password.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Diagnostics.ProcessStartInfo.Password.set(System.Security.SecureString)' does not exist in the implementation but it does exist in the contract.
+CannotMakeMoreVisible : Visibility of member 'System.Diagnostics.Switch.GetSupportedAttributes()' is 'Family' in the implementation but 'FamilyOrAssembly' in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.SwitchAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.SwitchLevelAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
+CannotMakeMoreVisible : Visibility of member 'System.Diagnostics.TraceListener.GetSupportedAttributes()' is 'Family' in the implementation but 'FamilyOrAssembly' in the contract.
+CannotMakeMoreVisible : Visibility of member 'System.Diagnostics.TraceSource.GetSupportedAttributes()' is 'Family' in the implementation but 'FamilyOrAssembly' in the contract.
TypesMustExist : Type 'System.Diagnostics.XmlWriterTraceListener' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.IO.InternalBufferOverflowException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
@@ -1312,75 +1189,13 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Net.CookieException' does not imp
TypesMustExist : Type 'System.Net.DnsPermission' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.DnsPermissionAttribute' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.EndpointPermission' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.DefaultServiceNames.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.ExtendedProtectionPolicy.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.ExtendedProtectionPolicy.set(System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.ExtendedProtectionSelectorDelegate.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.ExtendedProtectionSelectorDelegate.set(System.Net.HttpListener.ExtendedProtectionSelector)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.TimeoutManager.get()' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Net.HttpListener.ExtendedProtectionSelector' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListenerContext.AcceptWebSocketAsync(System.String, System.TimeSpan)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Net.HttpListenerException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Net.HttpListenerException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Net.HttpListenerTimeoutManager' does not exist in the implementation but it does exist in the contract.
CannotMakeTypeAbstract : Type 'System.Net.HttpVersion' is abstract in the implementation but is not abstract in the contract.
CannotSealType : Type 'System.Net.HttpVersion' is sealed in the implementation but not sealed in the contract.
MembersMustExist : Member 'System.Net.HttpVersion..ctor()' does not exist in the implementation but it does exist in the contract.
-CannotSealType : Type 'System.Net.HttpWebRequest' is sealed in the implementation but not sealed in the contract.
MembersMustExist : Member 'System.Net.HttpWebRequest..ctor()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpWebRequest..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowAutoRedirect' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowReadStreamBuffering' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowWriteStreamBuffering' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ConnectionGroupName' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ContentType' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.CookieContainer' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Credentials' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.HaveResponse' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Headers' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Method' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.RequestUri' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.SupportsCookieContainer' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.UseDefaultCredentials' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Abort()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowAutoRedirect.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowAutoRedirect.set(System.Boolean)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowReadStreamBuffering.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowReadStreamBuffering.set(System.Boolean)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowWriteStreamBuffering.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowWriteStreamBuffering.set(System.Boolean)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.BeginGetRequestStream(System.AsyncCallback, System.Object)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.BeginGetResponse(System.AsyncCallback, System.Object)' is non-virtual in the implementation but is virtual in the contract.
-MembersMustExist : Member 'System.Net.HttpWebRequest.Connection.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpWebRequest.Connection.set(System.String)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ConnectionGroupName.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ConnectionGroupName.set(System.String)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ContentType.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ContentType.set(System.String)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.CookieContainer.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.CookieContainer.set(System.Net.CookieContainer)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Credentials.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Credentials.set(System.Net.ICredentials)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.EndGetRequestStream(System.IAsyncResult)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.EndGetResponse(System.IAsyncResult)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.GetRequestStream()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.GetResponse()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.HaveResponse.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Headers.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Headers.set(System.Net.WebHeaderCollection)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Method.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Method.set(System.String)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.RequestUri.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.SupportsCookieContainer.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.UseDefaultCredentials.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.UseDefaultCredentials.set(System.Boolean)' is non-virtual in the implementation but is virtual in the contract.
-MembersMustExist : Member 'System.Net.HttpWebResponse..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.ICertificatePolicy' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.NetworkAccess' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.NetworkCredential..ctor(System.String, System.Security.SecureString)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.NetworkCredential..ctor(System.String, System.Security.SecureString, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.NetworkCredential.SecurePassword.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.NetworkCredential.SecurePassword.set(System.Security.SecureString)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Net.ProtocolViolationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Net.ServicePointManager.CertificatePolicy.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Net.ServicePointManager.CertificatePolicy.set(System.Net.ICertificatePolicy)' does not exist in the implementation but it does exist in the contract.
@@ -1389,14 +1204,10 @@ TypesMustExist : Type 'System.Net.SocketPermissionAttribute' does not exist in t
MembersMustExist : Member 'System.Net.TransportContext.GetTlsTokenBindings()' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.TransportType' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Net.WebException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Net.WebHeaderCollection.Set(System.Net.HttpRequestHeader, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.WebHeaderCollection.Set(System.Net.HttpResponseHeader, System.String)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.WebPermission' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.WebPermissionAttribute' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Net.WebRequest.CreatorInstance.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Net.WebRequest.RegisterPortableWebRequestCreator(System.Net.IWebRequestCreate)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.WebUtility.HtmlDecode(System.String, System.IO.TextWriter)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.WebUtility.HtmlEncode(System.String, System.IO.TextWriter)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.Configuration.AuthenticationModuleElement' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.Configuration.AuthenticationModuleElementCollection' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.Configuration.AuthenticationModulesSection' does not exist in the implementation but it does exist in the contract.
@@ -1439,16 +1250,6 @@ TypesMustExist : Type 'System.Net.Mail.SmtpPermissionAttribute' does not exist i
CannotRemoveBaseTypeOrInterface : Type 'System.Net.NetworkInformation.NetworkInformationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Net.NetworkInformation.NetworkInformationPermissionAttribute' does not implement interface 'System.Runtime.InteropServices._Attribute' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Net.NetworkInformation.PingException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Net.Sockets.AddressFamily System.Net.Sockets.AddressFamily.Max' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.BeginSendFile(System.String, System.AsyncCallback, System.Object)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.BeginSendFile(System.String, System.Byte[], System.Byte[], System.Net.Sockets.TransmitFileOptions, System.AsyncCallback, System.Object)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.EndAccept(System.Byte[], System.IAsyncResult)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.EndAccept(System.Byte[], System.Int32, System.IAsyncResult)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.EndSendFile(System.IAsyncResult)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.SendFile(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.SendFile(System.String, System.Byte[], System.Byte[], System.Net.Sockets.TransmitFileOptions)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.SendPacketsFlags.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.SendPacketsFlags.set(System.Net.Sockets.TransmitFileOptions)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.SocketClientAccessPolicyProtocol.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.SocketClientAccessPolicyProtocol.set(System.Net.Sockets.SocketClientAccessPolicyProtocol)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Net.Sockets.SocketClientAccessPolicyProtocol' does not exist in the implementation but it does exist in the contract.
@@ -1460,17 +1261,12 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.DefaultPa
TypesMustExist : Type 'System.Runtime.InteropServices.StandardOleMarshalObject' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Security.Authentication.AuthenticationException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Security.Authentication.InvalidCredentialException' does not implement interface 'System.Runtime.InteropServices._Exception' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Security.Authentication.SslProtocols System.Security.Authentication.SslProtocols.Default' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicyTypeConverter' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.TokenBinding' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.TokenBindingType' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.Configuration.ServiceNameElement' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.Configuration.ServiceNameElementCollection' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Claims.DynamicRoleClaimProvider' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Security.Cryptography.X509Certificates.X509Certificate2Collection' does not inherit from base type 'System.Collections.CollectionBase' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Security.Cryptography.X509Certificates.X509CertificateCollection' does not inherit from base type 'System.Collections.CollectionBase' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.X509Certificates.X509Chain.Create()' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Permissions.ResourcePermissionBase' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Permissions.ResourcePermissionBaseEntry' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Permissions.StorePermission' does not exist in the implementation but it does exist in the contract.
@@ -1586,26 +1382,16 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.Extensio
TypesMustExist : Type 'System.Runtime.CompilerServices.RuntimeOps' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.ComAwareEventInfo' does not implement interface 'System.Runtime.InteropServices._EventInfo' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Security.ManifestKinds' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.Aes.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AesManaged.FeedbackSize.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AesManaged.FeedbackSize.set(System.Int32)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.ECDiffieHellman' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.ECDiffieHellmanCng' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.ECDiffieHellmanCngPublicKey' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.Cryptography.ECDiffieHellmanKeyDerivationFunction' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.ECDsa.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.ECDsa.HashData(System.Byte[], System.Int32, System.Int32, System.Security.Cryptography.HashAlgorithmName)' is abstract in the implementation but is not abstract in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.ECDsa.HashData(System.IO.Stream, System.Security.Cryptography.HashAlgorithmName)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.ECDsa.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.ECDsa.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.FromXmlString(System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.FromXmlString(System.String, System.Security.Cryptography.ECKeyXmlFormat)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.HashAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.HashAlgorithm.set(System.Security.Cryptography.CngAlgorithm)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.SignData(System.Byte[])' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.SignData(System.Byte[], System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.SignData(System.IO.Stream)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.ToXmlString(System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.ToXmlString(System.Security.Cryptography.ECKeyXmlFormat)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.VerifyData(System.Byte[], System.Byte[])' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.Cryptography.ECDsaCng.VerifyData(System.Byte[], System.Int32, System.Int32, System.Byte[])' does not exist in the implementation but it does exist in the contract.
@@ -1736,4 +1522,4 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Xml.Xsl.XsltException' does not i
MembersMustExist : Member 'System.Xml.Xsl.XslTransform.Load(System.Xml.XmlReader, System.Xml.XmlResolver, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Xml.Xsl.XslTransform.Load(System.Xml.XPath.IXPathNavigable, System.Xml.XmlResolver, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Xml.Xsl.XslTransform.Load(System.Xml.XPath.XPathNavigator, System.Xml.XmlResolver, System.Security.Policy.Evidence)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 1731
+Total Issues: 1517
diff --git a/layout/ApiCompatBaseline.netstandard20.txt b/layout/ApiCompatBaseline.netstandard20.txt
index 8bcc95a6c1..fcc74cf864 100644
--- a/layout/ApiCompatBaseline.netstandard20.txt
+++ b/layout/ApiCompatBaseline.netstandard20.txt
@@ -1,208 +1 @@
-Compat issues with assembly netstandard:
-CannotMakeMemberNonVirtual : Member 'System.Type.IsEnum' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Type.Equals(System.Type)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Type.IsEnum.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMoreVisible : Visibility of member 'System.Diagnostics.DelimitedListTraceListener.GetSupportedAttributes()' is 'Family' in the implementation but 'FamilyOrAssembly' in the contract.
-MembersMustExist : Member 'System.Diagnostics.Process.Start(System.String, System.String, System.Security.SecureString, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Diagnostics.Process.Start(System.String, System.String, System.String, System.Security.SecureString, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Diagnostics.ProcessStartInfo.Password.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Diagnostics.ProcessStartInfo.Password.set(System.Security.SecureString)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.IO.FileStream..ctor(System.IntPtr, System.IO.FileAccess)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.IO.FileStream..ctor(System.IntPtr, System.IO.FileAccess, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.IO.FileStream..ctor(System.IntPtr, System.IO.FileAccess, System.Boolean, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.IO.FileStream..ctor(System.IntPtr, System.IO.FileAccess, System.Boolean, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.IO.TextWriter.Write(System.Char)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.DefaultServiceNames.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.ExtendedProtectionPolicy.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.ExtendedProtectionPolicy.set(System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.ExtendedProtectionSelectorDelegate.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.ExtendedProtectionSelectorDelegate.set(System.Net.HttpListener.ExtendedProtectionSelector)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListener.TimeoutManager.get()' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Net.HttpListener.ExtendedProtectionSelector' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListenerContext.AcceptWebSocketAsync(System.String, System.TimeSpan)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpListenerException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Net.HttpListenerTimeoutManager' does not exist in the implementation but it does exist in the contract.
-CannotSealType : Type 'System.Net.HttpWebRequest' is sealed in the implementation but not sealed in the contract.
-MembersMustExist : Member 'System.Net.HttpWebRequest..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowAutoRedirect' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowReadStreamBuffering' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowWriteStreamBuffering' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ConnectionGroupName' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ContentType' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.CookieContainer' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Credentials' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.HaveResponse' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Headers' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Method' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.RequestUri' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.SupportsCookieContainer' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.UseDefaultCredentials' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Abort()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowAutoRedirect.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowAutoRedirect.set(System.Boolean)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowReadStreamBuffering.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowReadStreamBuffering.set(System.Boolean)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowWriteStreamBuffering.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.AllowWriteStreamBuffering.set(System.Boolean)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.BeginGetRequestStream(System.AsyncCallback, System.Object)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.BeginGetResponse(System.AsyncCallback, System.Object)' is non-virtual in the implementation but is virtual in the contract.
-MembersMustExist : Member 'System.Net.HttpWebRequest.Connection.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.HttpWebRequest.Connection.set(System.String)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ConnectionGroupName.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ConnectionGroupName.set(System.String)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ContentType.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.ContentType.set(System.String)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.CookieContainer.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.CookieContainer.set(System.Net.CookieContainer)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Credentials.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Credentials.set(System.Net.ICredentials)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.EndGetRequestStream(System.IAsyncResult)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.EndGetResponse(System.IAsyncResult)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.GetRequestStream()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.GetResponse()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.HaveResponse.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Headers.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Headers.set(System.Net.WebHeaderCollection)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Method.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.Method.set(System.String)' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.RequestUri.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.SupportsCookieContainer.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.UseDefaultCredentials.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Net.HttpWebRequest.UseDefaultCredentials.set(System.Boolean)' is non-virtual in the implementation but is virtual in the contract.
-MembersMustExist : Member 'System.Net.HttpWebResponse..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.NetworkCredential..ctor(System.String, System.Security.SecureString)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.NetworkCredential..ctor(System.String, System.Security.SecureString, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.NetworkCredential.SecurePassword.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.NetworkCredential.SecurePassword.set(System.Security.SecureString)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Net.TransportType' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.WebHeaderCollection.Set(System.Net.HttpRequestHeader, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.WebHeaderCollection.Set(System.Net.HttpResponseHeader, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.WebUtility.HtmlDecode(System.String, System.IO.TextWriter)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.WebUtility.HtmlEncode(System.String, System.IO.TextWriter)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.AddressFamily System.Net.Sockets.AddressFamily.Max' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.BeginSendFile(System.String, System.AsyncCallback, System.Object)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.BeginSendFile(System.String, System.Byte[], System.Byte[], System.Net.Sockets.TransmitFileOptions, System.AsyncCallback, System.Object)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.EndAccept(System.Byte[], System.IAsyncResult)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.EndAccept(System.Byte[], System.Int32, System.IAsyncResult)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.EndSendFile(System.IAsyncResult)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.SendFile(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.Socket.SendFile(System.String, System.Byte[], System.Byte[], System.Net.Sockets.TransmitFileOptions)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.SendPacketsFlags.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Net.Sockets.SocketAsyncEventArgs.SendPacketsFlags.set(System.Net.Sockets.TransmitFileOptions)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.EscapedCodeBase.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.GetFile(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.GetFiles()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.GetFiles(System.Boolean)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberNonVirtual : Member 'System.Reflection.Assembly.LoadModule(System.String, System.Byte[], System.Byte[])' is non-virtual in the implementation but is virtual in the contract.
-MembersMustExist : Member 'System.Reflection.AssemblyName.EscapedCodeBase.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.MethodBase.IsSecuritySafeCritical.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Module.GetSignerCertificate()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.StrongNameKeyPair..ctor(System.IO.FileStream)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.CriticalHandle.Close()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.BindToMoniker(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.ChangeWrapperHandleStrength(System.Object, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.PtrToStringAuto(System.IntPtr)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.PtrToStringAuto(System.IntPtr, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Authentication.SslProtocols System.Security.Authentication.SslProtocols.Default' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicyTypeConverter' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.Aes.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AesManaged.FeedbackSize.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AesManaged.FeedbackSize.set(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.Clear()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.FromXmlString(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.AsymmetricAlgorithm.ToXmlString(System.Boolean)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.CryptoConfig' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.CspParameters.KeyPassword.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.CspParameters.KeyPassword.set(System.Security.SecureString)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DES.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSA.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSA.FromXmlString(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSA.ToXmlString(System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSACryptoServiceProvider.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.DSACryptoServiceProvider.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.ECDsa.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.ECDsa.HashData(System.Byte[], System.Int32, System.Int32, System.Security.Cryptography.HashAlgorithmName)' is abstract in the implementation but is not abstract in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.ECDsa.HashData(System.IO.Stream, System.Security.Cryptography.HashAlgorithmName)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.ECDsa.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.ECDsa.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Int32 System.Security.Cryptography.HashAlgorithm.HashSizeValue' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HashAlgorithm.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HashAlgorithm.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HMAC.BlockSizeValue.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HMAC.BlockSizeValue.set(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HMAC.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.HMAC.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.IncrementalHash..ctor()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.KeyedHashAlgorithm.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.KeyedHashAlgorithm.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.MaskGenerationMethod' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.MD5.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.PaddingMode System.Security.Cryptography.PaddingMode.ANSIX923' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.PaddingMode System.Security.Cryptography.PaddingMode.ISO10126' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.PasswordDeriveBytes' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.PKCS1MaskGenerationMethod' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RandomNumberGenerator.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RC2.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.Rfc2898DeriveBytes.CryptDeriveKey(System.String, System.String, System.Int32, System.Byte[])' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.Rijndael.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.Decrypt(System.Byte[], System.Security.Cryptography.RSAEncryptionPadding)' is abstract in the implementation but is not abstract in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.Encrypt(System.Byte[], System.Security.Cryptography.RSAEncryptionPadding)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.FromXmlString(System.String)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.HashData(System.Byte[], System.Int32, System.Int32, System.Security.Cryptography.HashAlgorithmName)' is abstract in the implementation but is not abstract in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.HashData(System.IO.Stream, System.Security.Cryptography.HashAlgorithmName)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.SignHash(System.Byte[], System.Security.Cryptography.HashAlgorithmName, System.Security.Cryptography.RSASignaturePadding)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSA.ToXmlString(System.Boolean)' does not exist in the implementation but it does exist in the contract.
-CannotMakeMemberAbstract : Member 'System.Security.Cryptography.RSA.VerifyHash(System.Byte[], System.Byte[], System.Security.Cryptography.HashAlgorithmName, System.Security.Cryptography.RSASignaturePadding)' is abstract in the implementation but is not abstract in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSACryptoServiceProvider.KeyExchangeAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.RSACryptoServiceProvider.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SHA1.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SHA256.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SHA384.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SHA512.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.SignatureDescription' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Int32 System.Security.Cryptography.SymmetricAlgorithm.FeedbackSizeValue' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.Create()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.FeedbackSize.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.FeedbackSize.set(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.SymmetricAlgorithm.ValidKeySize(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.TripleDES.Create(System.String)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Security.Cryptography.X509Certificates.X509Certificate2Collection' does not inherit from base type 'System.Collections.CollectionBase' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Security.Cryptography.X509Certificates.X509CertificateCollection' does not inherit from base type 'System.Collections.CollectionBase' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Security.Cryptography.X509Certificates.X509Chain.Create()' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Threading.AsyncFlowControl' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Threading.CompressedStack' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Threading.ExecutionContext' does not implement interface 'System.IDisposable' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.CreateCopy()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.Dispose()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.IsFlowSuppressed()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.RestoreFlow()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ExecutionContext.SuppressFlow()' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Threading.HostExecutionContext' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Threading.HostExecutionContextManager' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.SynchronizationContext.IsWaitNotificationRequired()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.SynchronizationContext.SetWaitNotificationRequired()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.SynchronizationContext.Wait(System.IntPtr[], System.Boolean, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.SynchronizationContext.WaitHelper(System.IntPtr[], System.Boolean, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.Thread.DisableComObjectEagerCleanup()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.Thread.GetCompressedStack()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.Thread.SetCompressedStack(System.Threading.CompressedStack)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.GetAvailableThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.GetMaxThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.GetMinThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.SetMaxThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.SetMinThreads(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeQueueUserWorkItem(System.Threading.WaitCallback, System.Object)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle, System.Threading.WaitOrTimerCallback, System.Object, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle, System.Threading.WaitOrTimerCallback, System.Object, System.Int64, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle, System.Threading.WaitOrTimerCallback, System.Object, System.TimeSpan, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Threading.ThreadPool.UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle, System.Threading.WaitOrTimerCallback, System.Object, System.UInt32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 206
+Total Issues: 0
diff --git a/netci.groovy b/netci.groovy
index 2e680f3c22..7221be2f41 100644
--- a/netci.groovy
+++ b/netci.groovy
@@ -233,7 +233,7 @@ def testNugetRuntimeIdConfiguration = ['Debug': 'win7-x86',
batchFile("call \"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat\" x86 && build.cmd -${configurationGroup} -outerloop -- /p:WithoutCategories=IgnoreForCI")
}
else if (osName == 'OSX') {
- shell("HOME=\$WORKSPACE/tempHome ./build.sh -${configurationGroup.toLowerCase()} -outerloop -- /p:TestWithLocalNativeLibraries=true /p:WithoutCategories=IgnoreForCI")
+ shell("HOME=\$WORKSPACE/tempHome ./build.sh -${configurationGroup.toLowerCase()} -outerloop -- /p:TestWithLocalNativeLibraries=true /p:TestNugetRuntimeId=${targetNugetRuntimeMap[osName]} /p:WithoutCategories=IgnoreForCI")
}
else {
shell("sudo HOME=\$WORKSPACE/tempHome ./build.sh -${configurationGroup.toLowerCase()} -outerloop -- /p:TestWithLocalNativeLibraries=true /p:TestNugetRuntimeId=${targetNugetRuntimeMap[osName]} /p:WithoutCategories=IgnoreForCI")
diff --git a/pkg/Microsoft.NETCore.Platforms/runtime.json b/pkg/Microsoft.NETCore.Platforms/runtime.json
index a00defb02c..5c7da9c0c8 100644
--- a/pkg/Microsoft.NETCore.Platforms/runtime.json
+++ b/pkg/Microsoft.NETCore.Platforms/runtime.json
@@ -141,6 +141,9 @@
"unix-x64": {
"#import": [ "unix" ]
},
+ "unix-x86": {
+ "#import": [ "unix" ]
+ },
"unix-arm": {
"#import": [ "unix" ]
},
@@ -175,13 +178,16 @@
"osx.10.12-x64": {
"#import": [ "osx.10.12", "osx.10.11-x64" ]
},
-
+
"linux": {
"#import": [ "unix" ]
},
"linux-x64": {
"#import": [ "linux", "unix-x64" ]
},
+ "linux-x86": {
+ "#import": [ "linux", "unix-x86" ]
+ },
"linux-arm": {
"#import": [ "linux", "unix-arm" ]
},
@@ -279,6 +285,9 @@
"debian-x64": {
"#import": [ "debian", "linux-x64" ]
},
+ "debian-x86": {
+ "#import": [ "debian", "linux-x86" ]
+ },
"debian-arm": {
"#import": [ "debian", "linux-arm" ]
},
@@ -292,6 +301,9 @@
"debian.8-x64": {
"#import": [ "debian.8", "debian-x64" ]
},
+ "debian.8-x86": {
+ "#import": [ "debian.8", "debian-x86" ]
+ },
"debian.8-arm": {
"#import": [ "debian.8", "debian-arm" ]
},
@@ -307,12 +319,26 @@
"#import": [ "ubuntu", "debian-x64" ]
},
+ "ubuntu-x86": {
+ "#import": [ "ubuntu", "debian-x86" ]
+ },
+
+ "ubuntu-arm": {
+ "#import": [ "ubuntu", "debian-arm" ]
+ },
+
"ubuntu.14.04": {
"#import": [ "ubuntu" ]
},
"ubuntu.14.04-x64": {
"#import": [ "ubuntu.14.04", "ubuntu-x64" ]
},
+ "ubuntu.14.04-x86": {
+ "#import": [ "ubuntu.14.04", "ubuntu-x86" ]
+ },
+ "ubuntu.14.04-arm": {
+ "#import": [ "ubuntu.14.04", "ubuntu-arm" ]
+ },
"ubuntu.14.10": {
"#import": [ "ubuntu" ]
@@ -320,6 +346,12 @@
"ubuntu.14.10-x64": {
"#import": [ "ubuntu.14.10", "ubuntu-x64" ]
},
+ "ubuntu.14.10-x86": {
+ "#import": [ "ubuntu.14.10", "ubuntu-x86" ]
+ },
+ "ubuntu.14.10-arm": {
+ "#import": [ "ubuntu.14.10", "ubuntu-arm" ]
+ },
"ubuntu.15.04": {
"#import": [ "ubuntu" ]
@@ -327,6 +359,12 @@
"ubuntu.15.04-x64": {
"#import": [ "ubuntu.15.04", "ubuntu-x64" ]
},
+ "ubuntu.15.04-x86": {
+ "#import": [ "ubuntu.15.04", "ubuntu-x86" ]
+ },
+ "ubuntu.15.04-arm": {
+ "#import": [ "ubuntu.15.04", "ubuntu-arm" ]
+ },
"ubuntu.15.10": {
"#import": [ "ubuntu" ]
@@ -334,6 +372,12 @@
"ubuntu.15.10-x64": {
"#import": [ "ubuntu.15.10", "ubuntu-x64" ]
},
+ "ubuntu.15.10-x86": {
+ "#import": [ "ubuntu.15.10", "ubuntu-x86" ]
+ },
+ "ubuntu.15.10-arm": {
+ "#import": [ "ubuntu.15.10", "ubuntu-arm" ]
+ },
"ubuntu.16.04": {
"#import": [ "ubuntu" ]
@@ -341,6 +385,12 @@
"ubuntu.16.04-x64": {
"#import": [ "ubuntu.16.04", "ubuntu-x64" ]
},
+ "ubuntu.16.04-x86": {
+ "#import": [ "ubuntu.16.04", "ubuntu-x86" ]
+ },
+ "ubuntu.16.04-arm": {
+ "#import": [ "ubuntu.16.04", "ubuntu-arm" ]
+ },
"ubuntu.16.10": {
"#import": [ "ubuntu" ]
@@ -348,6 +398,12 @@
"ubuntu.16.10-x64": {
"#import": [ "ubuntu.16.10", "ubuntu-x64" ]
},
+ "ubuntu.16.10-x86": {
+ "#import": [ "ubuntu.16.10", "ubuntu-x86" ]
+ },
+ "ubuntu.16.10-arm": {
+ "#import": [ "ubuntu.16.10", "ubuntu-arm" ]
+ },
"linuxmint.17": {
"#import": [ "ubuntu.14.04" ]
@@ -355,21 +411,21 @@
"linuxmint.17-x64": {
"#import": [ "linuxmint.17", "ubuntu.14.04-x64" ]
},
-
+
"linuxmint.17.1": {
"#import": [ "linuxmint.17" ]
},
"linuxmint.17.1-x64": {
"#import": [ "linuxmint.17.1", "linuxmint.17-x64" ]
},
-
+
"linuxmint.17.2": {
"#import": [ "linuxmint.17.1" ]
},
"linuxmint.17.2-x64": {
"#import": [ "linuxmint.17.2", "linuxmint.17.1-x64" ]
},
-
+
"linuxmint.17.3": {
"#import": [ "linuxmint.17.2" ]
},
@@ -446,6 +502,378 @@
"alpine.3.4.3-x64": {
"#import": [ "alpine.3.4.3", "alpine.3-x64" ]
},
+
+ "corert": {
+ "#import": [ "any" ]
+ },
+
+ "win-corert": {
+ "#import": [ "corert", "win" ]
+ },
+ "win-x86-corert": {
+ "#import": [ "win-corert", "win-x86" ]
+ },
+ "win-x64-corert": {
+ "#import": [ "win-corert", "win-x64" ]
+ },
+
+ "win7-corert": {
+ "#import": [ "win-corert", "win7" ]
+ },
+ "win7-x86-corert": {
+ "#import": [ "win7-corert", "win7-x86" ]
+ },
+ "win7-x64-corert": {
+ "#import": [ "win7-corert", "win7-x64" ]
+ },
+
+ "win8-corert": {
+ "#import": [ "win7-corert", "win8" ]
+ },
+ "win8-x86-corert": {
+ "#import": [ "win8-corert", "win7-x86-corert", "win8-x86"]
+ },
+ "win8-x64-corert": {
+ "#import": [ "win8-corert", "win7-x64-corert", "win8-x64" ]
+ },
+ "win8-arm-corert": {
+ "#import": [ "win8-corert", "win8-arm" ]
+ },
+
+ "win81-corert": {
+ "#import": [ "win8-corert", "win81" ]
+ },
+ "win81-x86-corert": {
+ "#import": [ "win81-corert", "win8-x86-corert", "win81-x86" ]
+ },
+ "win81-x64-corert": {
+ "#import": [ "win81-corert", "win8-x64-corert", "win81-x64" ]
+ },
+ "win81-arm-corert": {
+ "#import": [ "win81-corert", "win8-arm-corert", "win81-arm" ]
+ },
+
+ "win10-corert": {
+ "#import": [ "win81-corert", "win10" ]
+ },
+ "win10-x86-corert": {
+ "#import": [ "win10-corert", "win81-x86-corert", "win10-x86" ]
+ },
+ "win10-x64-corert": {
+ "#import": [ "win10-corert", "win81-x64-corert", "win10-x64" ]
+ },
+ "win10-arm-corert": {
+ "#import": [ "win10-corert", "win81-arm-corert", "win10-arm" ]
+ },
+ "win10-arm64-corert": {
+ "#import": [ "win10-corert", "win10-arm64" ]
+ },
+
+ "unix-corert": {
+ "#import": [ "corert", "unix" ]
+ },
+ "unix-x64-corert": {
+ "#import": [ "unix-corert", "unix-x64" ]
+ },
+ "unix-arm-corert": {
+ "#import": [ "unix-corert", "unix-arm" ]
+ },
+ "unix-arm64-corert": {
+ "#import": [ "unix-corert", "unix-arm64" ]
+ },
+
+ "osx-corert": {
+ "#import": [ "unix-corert", "osx" ]
+ },
+ "osx-x64-corert": {
+ "#import": [ "osx-corert", "unix-x64-corert", "osx-x64" ]
+ },
+
+ "osx.10.10-corert": {
+ "#import": [ "osx-corert", "osx.10.10" ]
+ },
+ "osx.10.10-x64-corert": {
+ "#import": [ "osx.10.10-corert", "osx-x64-corert", "osx.10.10-x64" ]
+ },
+
+ "osx.10.11-corert": {
+ "#import": [ "osx.10.10-corert", "osx.10.11" ]
+ },
+ "osx.10.11-x64-corert": {
+ "#import": [ "osx.10.11-corert", "osx.10.10-x64-corert", "osx.10.11-x64" ]
+ },
+
+ "osx.10.12-corert": {
+ "#import": [ "osx.10.11-corert", "osx.10.12" ]
+ },
+ "osx.10.12-x64-corert": {
+ "#import": [ "osx.10.12-corert", "osx.10.11-x64-corert", "osx.10.12-x64" ]
+ },
+
+ "linux-corert": {
+ "#import": [ "corert", "linux", "unix-corert" ]
+ },
+ "linux-x64-corert": {
+ "#import": [ "linux-corert", "linux-x64" ]
+ },
+ "linux-arm-corert": {
+ "#import": [ "linux-corert", "linux-arm" ]
+ },
+ "linux-arm64-corert": {
+ "#import": [ "linux-corert", "linux-arm64" ]
+ },
+
+ "rhel-corert": {
+ "#import": [ "corert", "rhel" ]
+ },
+ "rhel-x64-corert": {
+ "#import": [ "rhel-corert", "linux-x64-corert", "rhel-x64" ]
+ },
+
+ "rhel.7-corert": {
+ "#import": [ "rhel-corert", "rhel.7" ]
+ },
+ "rhel.7-x64-corert": {
+ "#import": [ "rhel.7-corert", "rhel-x64-corert", "rhel.7-x64" ]
+ },
+
+ "rhel.7.0-corert": {
+ "#import": [ "rhel.7-corert", "rhel.7.0" ]
+ },
+ "rhel.7.0-x64-corert": {
+ "#import": [ "rhel.7.0-corert", "rhel.7-x64-corert", "rhel.7.0-x64" ]
+ },
+
+ "rhel.7.1-corert": {
+ "#import": [ "rhel.7.0-corert", "rhel.7.1" ]
+ },
+ "rhel.7.1-x64-corert": {
+ "#import": [ "rhel.7.1-corert", "rhel.7.0-x64-corert", "rhel.7.1-x64" ]
+ },
+
+ "rhel.7.2-corert": {
+ "#import": [ "rhel.7.1-corert", "rhel.7.2" ]
+ },
+ "rhel.7.2-x64-corert": {
+ "#import": [ "rhel.7.2-corert", "rhel.7.1-x64-corert", "rhel.7.2-x64" ]
+ },
+
+ "ol-corert": {
+ "#import": [ "rhel-corert", "ol" ]
+ },
+ "ol-x64-corert": {
+ "#import": [ "ol-corert", "rhel-x64-corert", "ol-x64" ]
+ },
+
+ "ol.7-corert": {
+ "#import": [ "ol-corert", "ol.7" ]
+ },
+ "ol.7-x64-corert": {
+ "#import": [ "ol.7-corert", "rhel.7-x64-corert", "ol.7-x64" ]
+ },
+
+ "ol.7.0-corert": {
+ "#import": [ "ol.7-corert", "ol.7.0" ]
+ },
+ "ol.7.0-x64-corert": {
+ "#import": [ "ol.7.0-corert", "rhel.7.0-corert", "ol.7.0-x64" ]
+ },
+
+ "ol.7.1-corert": {
+ "#import": [ "ol.7.0-corert", "ol.7.1" ]
+ },
+ "ol.7.1-x64-corert": {
+ "#import": [ "ol.7.1-corert", "rhel.7.1-x64-corert", "ol.7.1-x64" ]
+ },
+
+ "centos-corert": {
+ "#import": [ "rel-corert", "centos" ]
+ },
+ "centos-x64-corert": {
+ "#import": [ "centos-corert", "rhel-x64-corert", "centos-x64" ]
+ },
+
+ "centos.7-corert": {
+ "#import": [ "centos-corert", "centos.7" ]
+ },
+ "centos.7-x64-corert": {
+ "#import": [ "centos.7-corert", "centos-x64-corert", "centos.7-x64" ]
+ },
+
+ "debian-corert": {
+ "#import": [ "linux-corert", "debian" ]
+ },
+ "debian-x64-corert": {
+ "#import": [ "debian-corert", "linux-x64-corert", "debian-x64" ]
+ },
+ "debian-arm-corert": {
+ "#import": [ "debian-corert", "debian-arm" ]
+ },
+ "debian-arm64-corert": {
+ "#import": [ "debian-corert", "debian-arm64" ]
+ },
+
+ "debian.8-corert": {
+ "#import": [ "debian-corert", "debian.8" ]
+ },
+ "debian.8-x64-corert": {
+ "#import": [ "debian.8-corert", "debian-x64-corert", "debian.8-x64" ]
+ },
+ "debian.8-arm-corert": {
+ "#import": [ "debian.8-corert", "debian-arm-corert", "debian.8-arm" ]
+ },
+ "debian.8-arm64-corert": {
+ "#import": [ "debian.8-corert", "debian-arm64-corert", "debian.8-arm64" ]
+ },
+
+ "ubuntu-corert": {
+ "#import": [ "debian-corert", "ubuntu" ]
+ },
+
+ "ubuntu-x64-corert": {
+ "#import": [ "ubuntu-corert", "debian-x64-corert", "ubuntu-x64" ]
+ },
+
+ "ubuntu.14.04-corert": {
+ "#import": [ "ubuntu-corert", "ubuntu.14.06" ]
+ },
+ "ubuntu.14.04-x64-corert": {
+ "#import": [ "ubuntu.14.04-corert", "ubuntu-x64-corert", "ubuntu-14.04-x64" ]
+ },
+
+ "ubuntu.14.10-corert": {
+ "#import": [ "ubuntu.14.04-corert", "ubuntu-14.10" ]
+ },
+ "ubuntu.14.10-x64-corert": {
+ "#import": [ "ubuntu.14.10-corert", "ubuntu.14.04-x64-corert", "ubuntu.14.10-x64" ]
+ },
+
+ "ubuntu.15.04-corert": {
+ "#import": [ "ubuntu.14.10-corert", "ubuntu-15.04" ]
+ },
+ "ubuntu.15.04-x64-corert": {
+ "#import": [ "ubuntu.15.04-corert", "ubuntu.14.10-x64-corert", "ubuntu.15.04-x64" ]
+ },
+
+ "ubuntu.15.10-corert": {
+ "#import": [ "ubuntu.15.04-corert", "ubuntu-15.10" ]
+ },
+ "ubuntu.15.10-x64-corert": {
+ "#import": [ "ubuntu.15.10-corert", "ubuntu.15.04-x64-corert", "ubuntu.15.10-x64" ]
+ },
+
+ "ubuntu.16.04-corert": {
+ "#import": [ "ubuntu.15.10-corert", "ubuntu-16.04" ]
+ },
+ "ubuntu.16.04-x64-corert": {
+ "#import": [ "ubuntu.16.04-corert", "ubuntu.15.10-x64-corert", "ubuntu.16.04-x64" ]
+ },
+
+ "ubuntu.16.10-corert": {
+ "#import": [ "ubuntu.16.04-corert", "ubuntu.16.10" ]
+ },
+ "ubuntu.16.10-x64-corert": {
+ "#import": [ "ubuntu.16.10-corert", "ubuntu.16.04-x64-corert", "ubuntu.16.10-x64" ]
+ },
+
+ "linuxmint.17-corert": {
+ "#import": [ "ubuntu.14.04-corert", "linuxmint.17" ]
+ },
+ "linuxmint.17-x64-corert": {
+ "#import": [ "linuxmint.17-corert", "ubuntu.14.04-x64-corert", "linuxmint.17-x64" ]
+ },
+
+ "linuxmint.17.1-corert": {
+ "#import": [ "linuxmint.17-corert", "linuxmint.17.1" ]
+ },
+ "linuxmint.17.1-x64-corert": {
+ "#import": [ "linuxmint.17.1-corert", "linuxmint.17-x64-corert", "linuxmint.17.1-x64" ]
+ },
+
+ "linuxmint.17.2-corert": {
+ "#import": [ "linuxmint.17.1-corert", "linuxmint.17.2" ]
+ },
+ "linuxmint.17.2-x64-corert": {
+ "#import": [ "linuxmint.17.2-corert", "linuxmint.17.1-x64-corert", "linuxmint.17.2-x64" ]
+ },
+
+ "linuxmint.17.3-corert": {
+ "#import": [ "linuxmint.17.2-corert", "linuxmint.17.3" ]
+ },
+ "linuxmint.17.3-x64-corert": {
+ "#import": [ "linuxmint.17.3-corert", "linuxmint.17.2-x64-corert", "linuxmint.17.3-x64" ]
+ },
+
+ "linuxmint.18-corert": {
+ "#import": [ "ubuntu.16.04-corert", "linuxmint.18" ]
+ },
+ "linuxmint.18-x64-corert": {
+ "#import": [ "linuxmint.18-corert", "ubuntu.16.04-x64-corert", "linuxmint.18-x64" ]
+ },
+
+ "fedora-corert": {
+ "#import": [ "linux-corert", "fedora" ]
+ },
+ "fedora-x64-corert": {
+ "#import": [ "fedora-corert", "linux-x64-corert", "fedora-x64" ]
+ },
+
+ "fedora.23-corert": {
+ "#import": [ "fedora-corert", "fedora.23" ]
+ },
+ "fedora.23-x64-corert": {
+ "#import": [ "fedora.23-corert", "fedora-x64-corert", "fedora.23-x64" ]
+ },
+
+ "fedora.24-corert": {
+ "#import": [ "fedora.23-corert", "fedora.24" ]
+ },
+ "fedora.24-x64-corert": {
+ "#import": [ "fedora.24-corert", "fedora.23-x64-corert", "fedora.24-x64" ]
+ },
+
+ "opensuse-corert": {
+ "#import": [ "linux-corert", "opensuse" ]
+ },
+ "opensuse-x64-corert": {
+ "#import": [ "opensuse-corert", "linux-x64-corert", "opensuste-x64" ]
+ },
+
+ "opensuse.13.2-corert": {
+ "#import": [ "opensuse-corert", "opensuse.13.2" ]
+ },
+ "opensuse.13.2-x64-corert": {
+ "#import": [ "opensuse.13.2-corert", "opensuse-x64-corert", "opensuse.13.2-x64" ]
+ },
+
+ "opensuse.42.1-corert": {
+ "#import": [ "opensuse.13.2-corert", "opensuse.42.1" ]
+ },
+ "opensuse.42.1-x64-corert": {
+ "#import": [ "opensuse.42.1-corert", "opensuse.13.2-x64-corert", "opensuse.42.1-x64" ]
+ },
+
+ "alpine-corert": {
+ "#import": [ "linux-corert", "alpine" ]
+ },
+ "alpine-x64-corert": {
+ "#import": [ "alpine-corert", "linux-x64-corert", "alpine-x64" ]
+ },
+
+ "alpine.3-corert": {
+ "#import": [ "alpine-corert", "alpine.3" ]
+ },
+ "alpine.3-x64-corert": {
+ "#import": [ "alpine.3-corert", "alpine-x64-corert", "alpine.3-x64" ]
+ },
+
+ "alpine.3.4.3-corert": {
+ "#import": [ "alpine.3-corert", "alpine.3.4.3" ]
+ },
+ "alpine.3.4.3-x64-corert": {
+ "#import": [ "alpine.3.4.3-corert", "alpine.3-x64-corert", "alpine.3.4.3-x64" ]
+ }
+
}
- }
+}
diff --git a/pkg/Microsoft.Private.PackageBaseline/packageIndex.json b/pkg/Microsoft.Private.PackageBaseline/packageIndex.json
index 91d2209df2..e7c33ef85e 100644
--- a/pkg/Microsoft.Private.PackageBaseline/packageIndex.json
+++ b/pkg/Microsoft.Private.PackageBaseline/packageIndex.json
@@ -735,6 +735,21 @@
],
"BaselineVersion": "4.4.0"
},
+ "runtime.ubuntu.14.04-arm.runtime.native.System": {
+ "BaselineVersion": "4.4.0"
+ },
+ "runtime.ubuntu.14.04-arm.runtime.native.System.IO.Compression": {
+ "BaselineVersion": "4.4.0"
+ },
+ "runtime.ubuntu.14.04-arm.runtime.native.System.Net.Http": {
+ "BaselineVersion": "4.4.0"
+ },
+ "runtime.ubuntu.14.04-arm.runtime.native.System.Net.Security": {
+ "BaselineVersion": "4.4.0"
+ },
+ "runtime.ubuntu.14.04-arm.runtime.native.System.Security.Cryptography": {
+ "BaselineVersion": "4.4.0"
+ },
"runtime.ubuntu.16.04-x64.runtime.native.System": {
"StableVersions": [
"1.0.1",
@@ -770,6 +785,21 @@
],
"BaselineVersion": "4.4.0"
},
+ "runtime.ubuntu.16.04-arm.runtime.native.System": {
+ "BaselineVersion": "4.4.0"
+ },
+ "runtime.ubuntu.16.04-arm.runtime.native.System.IO.Compression": {
+ "BaselineVersion": "4.4.0"
+ },
+ "runtime.ubuntu.16.04-arm.runtime.native.System.Net.Http": {
+ "BaselineVersion": "4.4.0"
+ },
+ "runtime.ubuntu.16.04-arm.runtime.native.System.Net.Security": {
+ "BaselineVersion": "4.4.0"
+ },
+ "runtime.ubuntu.16.04-arm.runtime.native.System.Security.Cryptography": {
+ "BaselineVersion": "4.4.0"
+ },
"runtime.unix.Microsoft.Win32.Primitives": {
"StableVersions": [
"4.0.1",
@@ -3069,12 +3099,18 @@
],
"BaselineVersion": "4.4.0"
},
+ "runtime.ubuntu.14.04-arm.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "BaselineVersion": "4.4.0"
+ },
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"StableVersions": [
"4.3.0"
],
"BaselineVersion": "4.4.0"
},
+ "runtime.ubuntu.16.04-arm.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "BaselineVersion": "4.4.0"
+ },
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": {
"StableVersions": [
"4.3.0"
@@ -3157,6 +3193,11 @@
"AssemblyVersionInPackageVersion": {
"4.0.0.0": "4.4.0"
}
+ },
+ "System.Configuration": {
+ "AssemblyVersionInPackageVersion": {
+ "4.0.0.0": "4.4.0"
+ }
}
},
"ModulesToPackages": {
@@ -3170,4 +3211,4 @@
"System.Security.Cryptography.Native.Apple": "runtime.native.System.Security.Cryptography.Apple",
"System.Security.Cryptography.Native.OpenSsl": "runtime.native.System.Security.Cryptography.OpenSsl"
}
-} \ No newline at end of file
+}
diff --git a/pkg/baseline/packageBaseline.1.1.json b/pkg/baseline/packageBaseline.1.1.json
new file mode 100644
index 0000000000..deadd99eaa
--- /dev/null
+++ b/pkg/baseline/packageBaseline.1.1.json
@@ -0,0 +1,449 @@
+{
+ "Packages": {
+ "Microsoft.CSharp": {
+ "BaselineVersion": "4.3.0"
+ },
+ "Microsoft.NETCore.Platforms": {
+ "BaselineVersion": "1.1.0"
+ },
+ "Microsoft.NETCore.Targets": {
+ "BaselineVersion": "1.1.0"
+ },
+ "Microsoft.VisualBasic": {
+ "BaselineVersion": "10.1.0"
+ },
+ "Microsoft.Win32.Primitives": {
+ "BaselineVersion": "4.3.0"
+ },
+ "Microsoft.Win32.Registry": {
+ "BaselineVersion": "4.3.0"
+ },
+ "Microsoft.Win32.Registry.AccessControl": {
+ "BaselineVersion": "4.3.0"
+ },
+ "NETStandard.Library": {
+ "BaselineVersion": "1.6.1"
+ },
+ "System.AppContext": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Buffers": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Collections": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Collections.Concurrent": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Collections.Immutable": {
+ "BaselineVersion": "1.3.0"
+ },
+ "System.Collections.NonGeneric": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Collections.Specialized": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.ComponentModel": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.ComponentModel.Annotations": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.ComponentModel.EventBasedAsync": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.ComponentModel.Primitives": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.ComponentModel.TypeConverter": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Console": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Data.Common": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Data.SqlClient": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.Contracts": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.Debug": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.DiagnosticSource": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.FileVersionInfo": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.Process": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.StackTrace": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.TextWriterTraceListener": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.Tools": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.TraceSource": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Diagnostics.Tracing": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Drawing.Primitives": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Dynamic.Runtime": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Globalization": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Globalization.Calendars": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Globalization.Extensions": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.Compression": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.Compression.ZipFile": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.FileSystem": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.FileSystem.AccessControl": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.FileSystem.DriveInfo": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.FileSystem.Primitives": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.FileSystem.Watcher": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.IsolatedStorage": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.MemoryMappedFiles": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.Packaging": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.Pipes": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.IO.UnmanagedMemoryStream": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Linq": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Linq.Expressions": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Linq.Parallel": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Linq.Queryable": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.Http": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.Http.Rtc": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.Http.WinHttpHandler": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.NameResolution": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.NetworkInformation": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.Ping": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.Primitives": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.Requests": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.Security": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.Sockets": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.WebHeaderCollection": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.WebSockets": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Net.WebSockets.Client": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Numerics.Vectors": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Numerics.Vectors.WindowsRuntime": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.ObjectModel": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Private.DataContractSerialization": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Private.Uri": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Reflection": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Reflection.Context": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Reflection.DispatchProxy": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Reflection.Emit": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Reflection.Emit.ILGeneration": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Reflection.Emit.Lightweight": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Reflection.Extensions": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Reflection.Metadata": {
+ "BaselineVersion": "1.4.1"
+ },
+ "System.Reflection.Primitives": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Reflection.TypeExtensions": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Resources.Reader": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Resources.ResourceManager": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Resources.Writer": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.CompilerServices.VisualC": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.Extensions": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.Handles": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.InteropServices": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.InteropServices.RuntimeInformation": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.InteropServices.WindowsRuntime": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.Loader": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.Numerics": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.Serialization.Json": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.Serialization.Primitives": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.Serialization.Xml": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.WindowsRuntime": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.WindowsRuntime.UI.Xaml": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.AccessControl": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Claims": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Cryptography.Algorithms": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Cryptography.Cng": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Cryptography.Csp": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Cryptography.Encoding": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Cryptography.OpenSsl": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Cryptography.Primitives": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Cryptography.ProtectedData": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Cryptography.X509Certificates": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Principal": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.Principal.Windows": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Security.SecureString": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.ServiceProcess.ServiceController": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Text.Encoding": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Text.Encoding.CodePages": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Text.Encoding.Extensions": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Text.Encodings.Web": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Text.RegularExpressions": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Threading": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Threading.AccessControl": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Threading.Overlapped": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Threading.Tasks": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Threading.Tasks.Dataflow": {
+ "BaselineVersion": "4.7.0"
+ },
+ "System.Threading.Tasks.Extensions": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Threading.Tasks.Parallel": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Threading.Thread": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Threading.ThreadPool": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Threading.Timer": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Xml.ReaderWriter": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Xml.XDocument": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Xml.XmlDocument": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Xml.XmlSerializer": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Xml.XPath": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Xml.XPath.XDocument": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Xml.XPath.XmlDocument": {
+ "BaselineVersion": "4.3.0"
+ },
+ "Microsoft.Private.PackageBaseline": {
+ "BaselineVersion": "1.0.1"
+ },
+ "System.Composition.AttributedModel": {
+ "BaselineVersion": "1.0.31"
+ },
+ "System.Composition.Convention": {
+ "BaselineVersion": "1.0.31"
+ },
+ "System.Composition.Hosting": {
+ "BaselineVersion": "1.0.31"
+ },
+ "System.Composition.Runtime": {
+ "BaselineVersion": "1.0.31"
+ },
+ "System.Composition.TypedParts": {
+ "BaselineVersion": "1.0.31"
+ },
+ "System.Composition": {
+ "BaselineVersion": "1.0.31"
+ },
+ "System.IO.Pipes.AccessControl": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.Runtime.Serialization.Formatters": {
+ "BaselineVersion": "4.3.0"
+ },
+ "System.ValueTuple": {
+ "BaselineVersion": "4.3.0"
+ }
+ },
+ "ModulesToPackages": {}
+} \ No newline at end of file
diff --git a/pkg/descriptions.json b/pkg/descriptions.json
index 922d5ed7ff..e94f0b2c09 100644
--- a/pkg/descriptions.json
+++ b/pkg/descriptions.json
@@ -400,6 +400,14 @@
]
},
{
+ "Name": "System.Configuration",
+ "Description": "Provides types that support using configuration files.",
+ "CommonTypes": [
+ "System.Configuration.Configuration",
+ "System.Configuration.ConfigurationManager"
+ ]
+ },
+ {
"Name": "System.Console",
"Description": "Provides the System.Console class, which represents the standard input, output and error streams for console applications.",
"CommonTypes": [
diff --git a/pkg/useSharedDesignerContext.txt b/pkg/useSharedDesignerContext.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/pkg/useSharedDesignerContext.txt
diff --git a/run-test.sh b/run-test.sh
index 798548d114..0da216ae0a 100755
--- a/run-test.sh
+++ b/run-test.sh
@@ -221,6 +221,12 @@ run_test()
fi
dirName="$1/$TestRelPath"
+
+ if [ ! -d "$dirName" ]; then
+ echo "Nothing to test in $testProject"
+ exit 0
+ fi
+
copy_test_overlay $dirName
pushd $dirName > /dev/null
diff --git a/src/Common/src/Interop/OSX/Interop.CommonCrypto.cs b/src/Common/src/Interop/OSX/Interop.CommonCrypto.cs
index 74f6cc5628..7f4111d613 100644
--- a/src/Common/src/Interop/OSX/Interop.CommonCrypto.cs
+++ b/src/Common/src/Interop/OSX/Interop.CommonCrypto.cs
@@ -13,6 +13,6 @@ internal static partial class Interop
internal static partial class CommonCrypto
{
[DllImport(Libraries.LibSystemCommonCrypto)]
- internal static unsafe extern int CCRandomGenerateBytes(byte* bytes, int byteCount);
+ internal static extern unsafe int CCRandomGenerateBytes(byte* bytes, int byteCount);
}
} \ No newline at end of file
diff --git a/src/Common/src/Interop/OSX/Interop.SystemConfiguration.cs b/src/Common/src/Interop/OSX/Interop.SystemConfiguration.cs
index a25caa0f68..7fc727c441 100644
--- a/src/Common/src/Interop/OSX/Interop.SystemConfiguration.cs
+++ b/src/Common/src/Interop/OSX/Interop.SystemConfiguration.cs
@@ -41,7 +41,7 @@ internal static partial class Interop
/// <param name="context">The context associated with the callout.</param>
/// <returns>A reference to the new dynamic store session.</returns>
[DllImport(Libraries.SystemConfigurationLibrary)]
- private static unsafe extern SafeCreateHandle SCDynamicStoreCreate(
+ private static extern unsafe SafeCreateHandle SCDynamicStoreCreate(
IntPtr allocator,
CFStringRef name,
SCDynamicStoreCallBack callout,
diff --git a/src/Common/src/Interop/OSX/Interop.libproc.cs b/src/Common/src/Interop/OSX/Interop.libproc.cs
index c3af54e07f..eefed75860 100644
--- a/src/Common/src/Interop/OSX/Interop.libproc.cs
+++ b/src/Common/src/Interop/OSX/Interop.libproc.cs
@@ -171,7 +171,7 @@ internal static partial class Interop
/// <param name="buffersize">The length of the block of memory allocated for the PID array</param>
/// <returns>Returns the number of elements (PIDs) in the buffer</returns>
[DllImport(Interop.Libraries.libproc, SetLastError = true)]
- private static unsafe extern int proc_listallpids(
+ private static extern unsafe int proc_listallpids(
int* pBuffer,
int buffersize);
@@ -230,7 +230,7 @@ internal static partial class Interop
/// to not having enough permissions to query for the data of that specific process
/// </returns>
[DllImport(Interop.Libraries.libproc, SetLastError = true)]
- private static unsafe extern int proc_pidinfo(
+ private static extern unsafe int proc_pidinfo(
int pid,
int flavor,
ulong arg,
@@ -251,7 +251,7 @@ internal static partial class Interop
/// to not having enough permissions to query for the data of that specific process
/// </returns>
[DllImport(Interop.Libraries.libproc, SetLastError = true)]
- private static unsafe extern int proc_pidinfo(
+ private static extern unsafe int proc_pidinfo(
int pid,
int flavor,
ulong arg,
@@ -272,7 +272,7 @@ internal static partial class Interop
/// to not having enough permissions to query for the data of that specific process
/// </returns>
[DllImport(Interop.Libraries.libproc, SetLastError = true)]
- private static unsafe extern int proc_pidinfo(
+ private static extern unsafe int proc_pidinfo(
int pid,
int flavor,
ulong arg,
@@ -293,7 +293,7 @@ internal static partial class Interop
/// to not having enough permissions to query for the data of that specific process
/// </returns>
[DllImport(Interop.Libraries.libproc, SetLastError = true)]
- private static unsafe extern int proc_pidinfo(
+ private static extern unsafe int proc_pidinfo(
int pid,
int flavor,
ulong arg,
@@ -414,7 +414,7 @@ internal static partial class Interop
/// <param name="bufferSize">The size of the buffer, should be PROC_PIDPATHINFO_MAXSIZE</param>
/// <returns>Returns the length of the path returned on success</returns>
[DllImport(Interop.Libraries.libproc, SetLastError = true)]
- private static unsafe extern int proc_pidpath(
+ private static extern unsafe int proc_pidpath(
int pid,
byte* buffer,
uint bufferSize);
@@ -457,7 +457,7 @@ internal static partial class Interop
/// void* and not a strong type even though it returns a rusage_info struct
/// </remarks>
[DllImport(Interop.Libraries.libproc, SetLastError = true)]
- private static unsafe extern int proc_pid_rusage(
+ private static extern unsafe int proc_pid_rusage(
int pid,
int flavor,
rusage_info_v3* rusage_info_t);
diff --git a/src/Common/src/Interop/OSX/System.Native/Interop.ProtocolStatistics.cs b/src/Common/src/Interop/OSX/System.Native/Interop.ProtocolStatistics.cs
index a1a9f6e03c..b1b9b6d873 100644
--- a/src/Common/src/Interop/OSX/System.Native/Interop.ProtocolStatistics.cs
+++ b/src/Common/src/Interop/OSX/System.Native/Interop.ProtocolStatistics.cs
@@ -24,7 +24,7 @@ internal static partial class Interop
}
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetTcpGlobalStatistics")]
- public static unsafe extern int GetTcpGlobalStatistics(out TcpGlobalStatistics statistics);
+ public static extern unsafe int GetTcpGlobalStatistics(out TcpGlobalStatistics statistics);
[StructLayoutAttribute(LayoutKind.Sequential)]
public unsafe struct IPv4GlobalStatistics
@@ -46,7 +46,7 @@ internal static partial class Interop
}
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIPv4GlobalStatistics")]
- public static unsafe extern int GetIPv4GlobalStatistics(out IPv4GlobalStatistics statistics);
+ public static extern unsafe int GetIPv4GlobalStatistics(out IPv4GlobalStatistics statistics);
[StructLayoutAttribute(LayoutKind.Sequential)]
public unsafe struct UdpGlobalStatistics
@@ -59,7 +59,7 @@ internal static partial class Interop
}
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetUdpGlobalStatistics")]
- public static unsafe extern int GetUdpGlobalStatistics(out UdpGlobalStatistics statistics);
+ public static extern unsafe int GetUdpGlobalStatistics(out UdpGlobalStatistics statistics);
[StructLayoutAttribute(LayoutKind.Sequential)]
public unsafe struct Icmpv4GlobalStatistics
@@ -89,7 +89,7 @@ internal static partial class Interop
}
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIcmpv4GlobalStatistics")]
- public static unsafe extern int GetIcmpv4GlobalStatistics(out Icmpv4GlobalStatistics statistics);
+ public static extern unsafe int GetIcmpv4GlobalStatistics(out Icmpv4GlobalStatistics statistics);
[StructLayoutAttribute(LayoutKind.Sequential)]
public unsafe struct Icmpv6GlobalStatistics
@@ -125,7 +125,7 @@ internal static partial class Interop
}
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIcmpv6GlobalStatistics")]
- public static unsafe extern int GetIcmpv6GlobalStatistics(out Icmpv6GlobalStatistics statistics);
+ public static extern unsafe int GetIcmpv6GlobalStatistics(out Icmpv6GlobalStatistics statistics);
public struct NativeIPInterfaceStatistics
{
@@ -145,7 +145,7 @@ internal static partial class Interop
}
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNativeIPInterfaceStatistics")]
- public static unsafe extern int GetNativeIPInterfaceStatistics(string name, out NativeIPInterfaceStatistics stats);
+ public static extern unsafe int GetNativeIPInterfaceStatistics(string name, out NativeIPInterfaceStatistics stats);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNumRoutes")]
public static extern int GetNumRoutes();
diff --git a/src/Common/src/Interop/OSX/System.Native/Interop.TcpConnectionInfo.cs b/src/Common/src/Interop/OSX/System.Native/Interop.TcpConnectionInfo.cs
index 6738f694cf..5312c6a98f 100644
--- a/src/Common/src/Interop/OSX/System.Native/Interop.TcpConnectionInfo.cs
+++ b/src/Common/src/Interop/OSX/System.Native/Interop.TcpConnectionInfo.cs
@@ -27,15 +27,15 @@ internal static partial class Interop
}
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetEstimatedTcpConnectionCount")]
- public unsafe static extern int GetEstimatedTcpConnectionCount();
+ public static extern unsafe int GetEstimatedTcpConnectionCount();
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetActiveTcpConnectionInfos")]
- public unsafe static extern int GetActiveTcpConnectionInfos(NativeTcpConnectionInformation* infos, int* infoCount);
+ public static extern unsafe int GetActiveTcpConnectionInfos(NativeTcpConnectionInformation* infos, int* infoCount);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetEstimatedUdpListenerCount")]
- public unsafe static extern int GetEstimatedUdpListenerCount();
+ public static extern unsafe int GetEstimatedUdpListenerCount();
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetActiveUdpListeners")]
- public unsafe static extern int GetActiveUdpListeners(IPEndPointInfo* infos, int* infoCount);
+ public static extern unsafe int GetActiveUdpListeners(IPEndPointInfo* infos, int* infoCount);
}
}
diff --git a/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Random.cs b/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Random.cs
index 3a2ae9136e..68b9501fcc 100644
--- a/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Random.cs
+++ b/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Random.cs
@@ -30,6 +30,6 @@ internal static partial class Interop
}
[DllImport(Libraries.AppleCryptoNative)]
- private static unsafe extern int AppleCryptoNative_GetRandomBytes(byte* buf, int num, out int errorCode);
+ private static extern unsafe int AppleCryptoNative_GetRandomBytes(byte* buf, int num, out int errorCode);
}
}
diff --git a/src/Common/src/Interop/Unix/Interop.Errors.cs b/src/Common/src/Interop/Unix/Interop.Errors.cs
index 4248434db3..e8aef9903f 100644
--- a/src/Common/src/Interop/Unix/Interop.Errors.cs
+++ b/src/Common/src/Interop/Unix/Interop.Errors.cs
@@ -186,7 +186,7 @@ internal static partial class Interop
internal static extern int ConvertErrorPalToPlatform(Error error);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_StrErrorR")]
- private static unsafe extern byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize);
+ private static extern unsafe byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Globalization.Native/Interop.Idna.cs b/src/Common/src/Interop/Unix/System.Globalization.Native/Interop.Idna.cs
index 02f64aa0f8..0331c2a9f1 100644
--- a/src/Common/src/Interop/Unix/System.Globalization.Native/Interop.Idna.cs
+++ b/src/Common/src/Interop/Unix/System.Globalization.Native/Interop.Idna.cs
@@ -13,9 +13,9 @@ internal static partial class Interop
internal const int UseStd3AsciiRules = 0x2;
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ToAscii")]
- internal static unsafe extern int ToAscii(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);
+ internal static extern unsafe int ToAscii(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ToUnicode")]
- internal static unsafe extern int ToUnicode(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);
+ internal static extern unsafe int ToUnicode(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.GetCwd.cs b/src/Common/src/Interop/Unix/System.Native/Interop.GetCwd.cs
index 724e342342..b4ee81fe09 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.GetCwd.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.GetCwd.cs
@@ -10,7 +10,7 @@ internal static partial class Interop
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetCwd", SetLastError = true)]
- private static unsafe extern byte* GetCwd(byte* buffer, int bufferLength);
+ private static extern unsafe byte* GetCwd(byte* buffer, int bufferLength);
internal static unsafe string GetCwd()
{
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.GetEnviron.cs b/src/Common/src/Interop/Unix/System.Native/Interop.GetEnviron.cs
index 25faaa38b8..65737caa3f 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.GetEnviron.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.GetEnviron.cs
@@ -11,6 +11,6 @@ internal static partial class Interop
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetEnviron", SetLastError = true)]
- internal static unsafe extern byte** GetEnviron();
+ internal static extern unsafe byte** GetEnviron();
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs b/src/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs
index fd610141d2..3858b495a1 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs
@@ -11,7 +11,7 @@ internal static partial class Interop
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostName", SetLastError = true)]
- private unsafe static extern int GetHostName(byte* name, int nameLength);
+ private static extern unsafe int GetHostName(byte* name, int nameLength);
internal static unsafe string GetHostName()
{
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.GetNameInfo.cs b/src/Common/src/Interop/Unix/System.Native/Interop.GetNameInfo.cs
index 275abffa3a..a3b672c44f 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.GetNameInfo.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.GetNameInfo.cs
@@ -17,7 +17,7 @@ internal static partial class Interop
}
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNameInfo")]
- internal static unsafe extern int GetNameInfo(
+ internal static extern unsafe int GetNameInfo(
byte* address,
uint addressLength,
bool isIpv6,
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.GetPeerID.cs b/src/Common/src/Interop/Unix/System.Native/Interop.GetPeerID.cs
index cdefe3c490..9ebb48ec39 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.GetPeerID.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.GetPeerID.cs
@@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPeerID", SetLastError = true)]
- internal unsafe static extern int GetPeerID(SafeHandle socket, out uint euid);
+ internal static extern unsafe int GetPeerID(SafeHandle socket, out uint euid);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.GetPeerUserName.cs b/src/Common/src/Interop/Unix/System.Native/Interop.GetPeerUserName.cs
index 450b1e11b4..8effc8883e 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.GetPeerUserName.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.GetPeerUserName.cs
@@ -11,6 +11,6 @@ internal static partial class Interop
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPeerUserName", SetLastError = true)]
- internal unsafe static extern string GetPeerUserName(SafeHandle socket);
+ internal static extern unsafe string GetPeerUserName(SafeHandle socket);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs b/src/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs
index 2660d8b090..31875417b9 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs
@@ -82,9 +82,9 @@ internal static partial class Interop
internal static extern int IPv4StringToAddress(string address, byte[] buffer, int bufferLength, out ushort port);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_IPAddressToString")]
- internal unsafe static extern int IPAddressToString(byte* address, int addressLength, bool isIPv6, byte* str, int stringLength, uint scope = 0);
+ internal static extern unsafe int IPAddressToString(byte* address, int addressLength, bool isIPv6, byte* str, int stringLength, uint scope = 0);
- internal unsafe static uint IPAddressToString(byte[] address, bool isIPv6, StringBuilder addressString, uint scope = 0)
+ internal static unsafe uint IPAddressToString(byte[] address, bool isIPv6, StringBuilder addressString, uint scope = 0)
{
Debug.Assert(address != null, "address was null");
Debug.Assert((address.Length == IPv4AddressBytes) || (address.Length == IPv6AddressBytes), $"Unexpected address length: {address.Length}");
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs b/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs
index 3a0a829a89..f2da069017 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs
@@ -80,7 +80,7 @@ internal static partial class Interop
internal static extern int GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPStr)]string name, out MountPointInformation mpi);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFormatInfoForMountPoint", SetLastError = true)]
- private unsafe static extern int GetFormatInfoForMountPoint(
+ private static extern unsafe int GetFormatInfoForMountPoint(
[MarshalAs(UnmanagedType.LPStr)]string name,
byte* formatNameBuffer,
int bufferLength,
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.Poll.cs b/src/Common/src/Interop/Unix/System.Native/Interop.Poll.cs
index ee926b83be..255cd55291 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.Poll.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.Poll.cs
@@ -38,7 +38,7 @@ internal static partial class Interop
/// <param name="triggered">The number of events triggered (i.e. the number of entries in pollEvents with a non-zero TriggeredEvents). May be zero in the event of a timeout.</param>
/// <returns>An error or Error.SUCCESS.</returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Poll")]
- internal static unsafe extern Error Poll(PollEvent* pollEvents, uint eventCount, int timeout, uint* triggered);
+ internal static extern unsafe Error Poll(PollEvent* pollEvents, uint eventCount, int timeout, uint* triggered);
/// <summary>
/// Polls a File Descriptor for the passed in flags.
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.Read.Pipe.cs b/src/Common/src/Interop/Unix/System.Native/Interop.Read.Pipe.cs
index f1c6616f37..f41f6eefab 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.Read.Pipe.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.Read.Pipe.cs
@@ -20,6 +20,6 @@ internal static partial class Interop
/// Note - on fail. the position of the stream may change depending on the platform; consult man 2 read for more info
/// </returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Read", SetLastError = true)]
- internal static unsafe extern int Read(SafePipeHandle fd, byte* buffer, int count);
+ internal static extern unsafe int Read(SafePipeHandle fd, byte* buffer, int count);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.Read.cs b/src/Common/src/Interop/Unix/System.Native/Interop.Read.cs
index 812ae348dc..1be5e789c2 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.Read.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.Read.cs
@@ -20,6 +20,6 @@ internal static partial class Interop
/// Note - on fail. the position of the stream may change depending on the platform; consult man 2 read for more info
/// </returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Read", SetLastError = true)]
- internal static unsafe extern int Read(SafeFileHandle fd, byte* buffer, int count);
+ internal static extern unsafe int Read(SafeFileHandle fd, byte* buffer, int count);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs b/src/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs
index d43b6b76bd..bcd29bc2da 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs
@@ -46,7 +46,7 @@ internal static partial class Interop
internal static extern int GetDirentSize();
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadDirR", SetLastError = false)]
- private static unsafe extern int ReadDirR(SafeDirectoryHandle dir, byte* buffer, int bufferSize, out InternalDirectoryEntry outputEntry);
+ private static extern unsafe int ReadDirR(SafeDirectoryHandle dir, byte* buffer, int bufferSize, out InternalDirectoryEntry outputEntry);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CloseDir", SetLastError = true)]
internal static extern int CloseDir(IntPtr dir);
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.ReadLink.cs b/src/Common/src/Interop/Unix/System.Native/Interop.ReadLink.cs
index 31547269ae..a39650fd83 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.ReadLink.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.ReadLink.cs
@@ -19,6 +19,6 @@ internal static partial class Interop
/// Returns the number of bytes placed into the buffer on success; otherwise, -1 is returned
/// </returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadLink", SetLastError = true)]
- internal static unsafe extern int ReadLink(string path, byte[] buffer, int bufferSize);
+ internal static extern unsafe int ReadLink(string path, byte[] buffer, int bufferSize);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.ReadStdinUnbuffered.cs b/src/Common/src/Interop/Unix/System.Native/Interop.ReadStdinUnbuffered.cs
index 5aefc4fd52..1b3b0ac7ea 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.ReadStdinUnbuffered.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.ReadStdinUnbuffered.cs
@@ -10,12 +10,12 @@ internal static partial class Interop
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadStdin", SetLastError = true)]
- internal unsafe static extern int ReadStdin(byte* buffer, int bufferSize);
+ internal static extern unsafe int ReadStdin(byte* buffer, int bufferSize);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_InitializeConsoleBeforeRead")]
- internal unsafe static extern void InitializeConsoleBeforeRead(byte minChars = 1, byte decisecondsTimeout = 0);
+ internal static extern unsafe void InitializeConsoleBeforeRead(byte minChars = 1, byte decisecondsTimeout = 0);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_UninitializeConsoleAfterRead")]
- internal unsafe static extern void UninitializeConsoleAfterRead();
+ internal static extern unsafe void UninitializeConsoleAfterRead();
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.SNPrintF.cs b/src/Common/src/Interop/Unix/System.Native/Interop.SNPrintF.cs
index bc265ebf8b..61fa8d60a0 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.SNPrintF.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.SNPrintF.cs
@@ -28,7 +28,7 @@ internal static partial class Interop
/// On failure, returns a negative value.
/// </returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SNPrintF", SetLastError = true)]
- internal static unsafe extern int SNPrintF(byte* str, int size, string format, string arg1);
+ internal static extern unsafe int SNPrintF(byte* str, int size, string format, string arg1);
/// <summary>
/// Takes a string and applies a formatting to it to transform
@@ -49,6 +49,6 @@ internal static partial class Interop
/// On failure, returns a negative value.
/// </returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SNPrintF", SetLastError = true)]
- internal static unsafe extern int SNPrintF(byte* str, int size, string format, int arg1);
+ internal static extern unsafe int SNPrintF(byte* str, int size, string format, int arg1);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.SendFile.cs b/src/Common/src/Interop/Unix/System.Native/Interop.SendFile.cs
new file mode 100644
index 0000000000..b253a59b0d
--- /dev/null
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.SendFile.cs
@@ -0,0 +1,14 @@
+// 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
+{
+ internal static partial class Sys
+ {
+ [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SendFile", SetLastError = true)]
+ internal static extern unsafe Error SendFile(SafeHandle out_fd, SafeHandle in_fd, long offset, long count, out long sent);
+ }
+}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.StdinReady.cs b/src/Common/src/Interop/Unix/System.Native/Interop.StdinReady.cs
index fa4cf8627d..7a19512c66 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.StdinReady.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.StdinReady.cs
@@ -9,6 +9,6 @@ internal static partial class Interop
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_StdinReady")]
- internal unsafe static extern bool StdinReady();
+ internal static extern unsafe bool StdinReady();
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.Write.Pipe.cs b/src/Common/src/Interop/Unix/System.Native/Interop.Write.Pipe.cs
index 675fcd47fc..89bf8c3383 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.Write.Pipe.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.Write.Pipe.cs
@@ -19,6 +19,6 @@ internal static partial class Interop
/// Returns the number of bytes written on success; otherwise, returns -1 and sets errno
/// </returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)]
- internal static unsafe extern int Write(SafePipeHandle fd, byte* buffer, int bufferSize);
+ internal static extern unsafe int Write(SafePipeHandle fd, byte* buffer, int bufferSize);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.Write.cs b/src/Common/src/Interop/Unix/System.Native/Interop.Write.cs
index c14fc26263..0636615a8b 100644
--- a/src/Common/src/Interop/Unix/System.Native/Interop.Write.cs
+++ b/src/Common/src/Interop/Unix/System.Native/Interop.Write.cs
@@ -19,9 +19,9 @@ internal static partial class Interop
/// Returns the number of bytes written on success; otherwise, returns -1 and sets errno
/// </returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)]
- internal static unsafe extern int Write(SafeFileHandle fd, byte* buffer, int bufferSize);
+ internal static extern unsafe int Write(SafeFileHandle fd, byte* buffer, int bufferSize);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)]
- internal static unsafe extern int Write(int fd, byte* buffer, int bufferSize);
+ internal static extern unsafe int Write(int fd, byte* buffer, int bufferSize);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs
index b2d04383e2..fab6ea2a81 100644
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs
@@ -17,7 +17,7 @@ internal static partial class Interop
internal static extern SafeAsn1ObjectHandle ObjTxt2Obj(string s);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ObjObj2Txt")]
- private static unsafe extern int ObjObj2Txt(byte* buf, int buf_len, IntPtr a);
+ private static extern unsafe int ObjObj2Txt(byte* buf, int buf_len, IntPtr a);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetObjectDefinitionByName", CharSet = CharSet.Ansi)]
internal static extern IntPtr GetObjectDefinitionByName(string friendlyName);
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs
index d381b6181b..9e8c6d8457 100644
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs
@@ -25,7 +25,7 @@ internal static partial class Interop
internal static extern IntPtr ErrReasonErrorString(ulong error);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrErrorStringN")]
- private static unsafe extern void ErrErrorStringN(ulong e, byte* buf, int len);
+ private static extern unsafe void ErrErrorStringN(ulong e, byte* buf, int len);
private static unsafe string ErrErrorStringN(ulong error)
{
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs
index 5172edab93..44cbc146b1 100644
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs
@@ -32,7 +32,7 @@ internal static partial class Interop
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherUpdate")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal static unsafe extern bool EvpCipherUpdate(
+ internal static extern unsafe bool EvpCipherUpdate(
SafeEvpCipherCtxHandle ctx,
byte* @out,
out int outl,
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Pkcs12.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Pkcs12.cs
index 0ea5c8fb9e..1be561006f 100644
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Pkcs12.cs
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Pkcs12.cs
@@ -12,7 +12,7 @@ internal static partial class Interop
internal static partial class Crypto
{
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodePkcs12")]
- internal static unsafe extern SafePkcs12Handle DecodePkcs12(byte[] buf, int len);
+ internal static extern unsafe SafePkcs12Handle DecodePkcs12(byte[] buf, int len);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodePkcs12FromBio")]
internal static extern SafePkcs12Handle DecodePkcs12FromBio(SafeBioHandle bio);
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.RAND.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.RAND.cs
index 3fcd2334c6..d179fd7373 100644
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.RAND.cs
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.RAND.cs
@@ -19,6 +19,6 @@ internal static partial class Interop
[DllImport(Libraries.CryptoNative)]
[return: MarshalAs(UnmanagedType.Bool)]
- private static unsafe extern bool CryptoNative_GetRandomBytes(byte* buf, int num);
+ private static extern unsafe bool CryptoNative_GetRandomBytes(byte* buf, int num);
}
}
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs
index e3611685bf..19ab1ddc4a 100644
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs
@@ -73,7 +73,7 @@ internal static partial class Interop
out int hashKeySize);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslWrite")]
- internal static unsafe extern int SslWrite(SafeSslHandle ssl, byte* buf, int num);
+ internal static extern unsafe int SslWrite(SafeSslHandle ssl, byte* buf, int num);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslRead")]
internal static extern int SslRead(SafeSslHandle ssl, byte[] buf, int num);
@@ -97,7 +97,7 @@ internal static partial class Interop
// NOTE: this is just an (unsafe) overload to the BioWrite method from Interop.Bio.cs.
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioWrite")]
- internal static unsafe extern int BioWrite(SafeBioHandle b, byte* data, int len);
+ internal static extern unsafe int BioWrite(SafeBioHandle b, byte* data, int len);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetPeerCertificate")]
internal static extern SafeX509Handle SslGetPeerCertificate(SafeSslHandle ssl);
diff --git a/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs b/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs
index d2ce4131b0..2431265e41 100644
--- a/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs
+++ b/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs
@@ -21,6 +21,6 @@ internal partial class Interop
private const int BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002;
[DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)]
- private static unsafe extern NTSTATUS BCryptGenRandom(IntPtr hAlgorithm, byte* pbBuffer, int cbBuffer, int dwFlags);
+ private static extern unsafe NTSTATUS BCryptGenRandom(IntPtr hAlgorithm, byte* pbBuffer, int cbBuffer, int dwFlags);
}
}
diff --git a/src/Common/src/Interop/Windows/BCrypt/Interop.Blobs.cs b/src/Common/src/Interop/Windows/BCrypt/Interop.Blobs.cs
index 5ab59edce9..b81a6527f1 100644
--- a/src/Common/src/Interop/Windows/BCrypt/Interop.Blobs.cs
+++ b/src/Common/src/Interop/Windows/BCrypt/Interop.Blobs.cs
@@ -142,7 +142,7 @@ internal partial class Interop
/// The BCRYPT_DSA_KEY_BLOB structure is used as a v1 header for a DSA public key or private key BLOB in memory.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
- unsafe internal struct BCRYPT_DSA_KEY_BLOB
+ internal unsafe struct BCRYPT_DSA_KEY_BLOB
{
internal KeyBlobMagicNumber Magic;
internal int cbKey;
@@ -155,7 +155,7 @@ internal partial class Interop
/// The BCRYPT_DSA_KEY_BLOB structure is used as a v2 header for a DSA public key or private key BLOB in memory.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
- unsafe internal struct BCRYPT_DSA_KEY_BLOB_V2
+ internal unsafe struct BCRYPT_DSA_KEY_BLOB_V2
{
internal KeyBlobMagicNumber Magic;
internal int cbKey;
diff --git a/src/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs b/src/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs
index 806dc2b547..797de1cc84 100644
--- a/src/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs
+++ b/src/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs
@@ -22,7 +22,7 @@ internal static partial class Interop
internal const int IPv4AddressSize = 16;
internal const int IPv6AddressSize = 28;
- private unsafe static bool InitHttpApi(HTTPAPI_VERSION version)
+ private static unsafe bool InitHttpApi(HTTPAPI_VERSION version)
{
uint statusCode = HttpInitialize(version, (uint)HTTP_FLAGS.HTTP_INITIALIZE_SERVER, null);
return statusCode == ERROR_SUCCESS;
@@ -517,16 +517,16 @@ internal static partial class Interop
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpInitialize(HTTPAPI_VERSION version, uint flags, void* pReserved);
+ internal static extern unsafe uint HttpInitialize(HTTPAPI_VERSION version, uint flags, void* pReserved);
[DllImport(Libraries.HttpApi, SetLastError = true)]
internal static extern uint HttpSetUrlGroupProperty(ulong urlGroupId, HTTP_SERVER_PROPERTY serverProperty, IntPtr pPropertyInfo, uint propertyInfoLength);
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpCreateServerSession(HTTPAPI_VERSION version, ulong* serverSessionId, uint reserved);
+ internal static extern unsafe uint HttpCreateServerSession(HTTPAPI_VERSION version, ulong* serverSessionId, uint reserved);
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpCreateUrlGroup(ulong serverSessionId, ulong* urlGroupId, uint reserved);
+ internal static extern unsafe uint HttpCreateUrlGroup(ulong serverSessionId, ulong* urlGroupId, uint reserved);
[DllImport(Libraries.HttpApi, SetLastError = true)]
internal static extern uint HttpCloseUrlGroup(ulong urlGroupId);
@@ -542,19 +542,19 @@ internal static partial class Interop
internal static extern uint HttpRemoveUrlFromUrlGroup(ulong urlGroupId, string pFullyQualifiedUrl, uint flags);
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, NativeOverlapped* pOverlapped);
+ internal static extern unsafe uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, NativeOverlapped* pOverlapped);
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpSendHttpResponse(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_RESPONSE* pHttpResponse, void* pCachePolicy, uint* pBytesSent, SafeLocalAllocHandle pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData);
+ internal static extern unsafe uint HttpSendHttpResponse(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_RESPONSE* pHttpResponse, void* pCachePolicy, uint* pBytesSent, SafeLocalAllocHandle pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData);
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpWaitForDisconnect(SafeHandle requestQueueHandle, ulong connectionId, NativeOverlapped* pOverlapped);
+ internal static extern unsafe uint HttpWaitForDisconnect(SafeHandle requestQueueHandle, ulong connectionId, NativeOverlapped* pOverlapped);
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpReceiveRequestEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, void* pEntityBuffer, uint entityBufferLength, out uint bytesReturned, NativeOverlapped* pOverlapped);
+ internal static extern unsafe uint HttpReceiveRequestEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, void* pEntityBuffer, uint entityBufferLength, out uint bytesReturned, NativeOverlapped* pOverlapped);
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpSendResponseEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, HTTP_DATA_CHUNK* pEntityChunks, uint* pBytesSent, SafeLocalAllocHandle pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData);
+ internal static extern unsafe uint HttpSendResponseEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, HTTP_DATA_CHUNK* pEntityChunks, uint* pBytesSent, SafeLocalAllocHandle pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData);
[DllImport(Libraries.HttpApi, SetLastError = true)]
internal static extern unsafe uint HttpCloseRequestQueue(IntPtr pReqQueueHandle);
@@ -600,10 +600,10 @@ internal static partial class Interop
internal static extern SafeLocalFreeChannelBinding LocalAlloc(int uFlags, UIntPtr sizetdwBytes);
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, HTTP_SSL_CLIENT_CERT_INFO* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped);
+ internal static extern unsafe uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, HTTP_SSL_CLIENT_CERT_INFO* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped);
[DllImport(Libraries.HttpApi, SetLastError = true)]
- internal unsafe static extern uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, byte* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped);
+ internal static extern unsafe uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, byte* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped);
[Flags]
internal enum FileCompletionNotificationModes : byte
@@ -614,7 +614,7 @@ internal static partial class Interop
}
[DllImport(Libraries.Kernel32, SetLastError = true)]
- internal static unsafe extern bool SetFileCompletionNotificationModes(SafeHandle handle, FileCompletionNotificationModes modes);
+ internal static extern unsafe bool SetFileCompletionNotificationModes(SafeHandle handle, FileCompletionNotificationModes modes);
internal static readonly string[] HttpVerbs = new string[]
{
@@ -722,7 +722,7 @@ internal static partial class Interop
"WWW-Authenticate",
};
- private readonly static Dictionary<string, int> s_hashtable = CreateTable();
+ private static readonly Dictionary<string, int> s_hashtable = CreateTable();
private static Dictionary<string, int> CreateTable()
{
@@ -746,7 +746,7 @@ internal static partial class Interop
}
}
- private unsafe static string GetKnownHeader(HTTP_REQUEST* request, long fixup, int headerIndex)
+ private static unsafe string GetKnownHeader(HTTP_REQUEST* request, long fixup, int headerIndex)
{
if (NetEventSource.IsEnabled) { NetEventSource.Enter(null); }
@@ -771,12 +771,12 @@ internal static partial class Interop
return header;
}
- internal unsafe static string GetKnownHeader(HTTP_REQUEST* request, int headerIndex)
+ internal static unsafe string GetKnownHeader(HTTP_REQUEST* request, int headerIndex)
{
return GetKnownHeader(request, 0, headerIndex);
}
- internal unsafe static string GetKnownHeader(byte[] memoryBlob, IntPtr originalAddress, int headerIndex)
+ internal static unsafe string GetKnownHeader(byte[] memoryBlob, IntPtr originalAddress, int headerIndex)
{
fixed (byte* pMemoryBlob = memoryBlob)
{
@@ -784,7 +784,7 @@ internal static partial class Interop
}
}
- private unsafe static string GetVerb(HTTP_REQUEST* request, long fixup)
+ private static unsafe string GetVerb(HTTP_REQUEST* request, long fixup)
{
string verb = null;
@@ -800,12 +800,12 @@ internal static partial class Interop
return verb;
}
- internal unsafe static string GetVerb(HTTP_REQUEST* request)
+ internal static unsafe string GetVerb(HTTP_REQUEST* request)
{
return GetVerb(request, 0);
}
- internal unsafe static string GetVerb(byte[] memoryBlob, IntPtr originalAddress)
+ internal static unsafe string GetVerb(byte[] memoryBlob, IntPtr originalAddress)
{
fixed (byte* pMemoryBlob = memoryBlob)
{
@@ -815,7 +815,7 @@ internal static partial class Interop
// Server API
- internal unsafe static WebHeaderCollection GetHeaders(byte[] memoryBlob, IntPtr originalAddress)
+ internal static unsafe WebHeaderCollection GetHeaders(byte[] memoryBlob, IntPtr originalAddress)
{
NetEventSource.Enter(null);
@@ -873,7 +873,7 @@ internal static partial class Interop
}
- internal unsafe static uint GetChunks(byte[] memoryBlob, IntPtr originalAddress, ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size)
+ internal static unsafe uint GetChunks(byte[] memoryBlob, IntPtr originalAddress, ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size)
{
if (NetEventSource.IsEnabled)
{
@@ -936,7 +936,7 @@ internal static partial class Interop
return dataRead;
}
- internal unsafe static HTTP_VERB GetKnownVerb(byte[] memoryBlob, IntPtr originalAddress)
+ internal static unsafe HTTP_VERB GetKnownVerb(byte[] memoryBlob, IntPtr originalAddress)
{
NetEventSource.Enter(null);
@@ -955,7 +955,7 @@ internal static partial class Interop
return verb;
}
- internal unsafe static IPEndPoint GetRemoteEndPoint(byte[] memoryBlob, IntPtr originalAddress)
+ internal static unsafe IPEndPoint GetRemoteEndPoint(byte[] memoryBlob, IntPtr originalAddress)
{
if (NetEventSource.IsEnabled) NetEventSource.Enter(null);
@@ -983,7 +983,7 @@ internal static partial class Interop
return endpoint;
}
- internal unsafe static IPEndPoint GetLocalEndPoint(byte[] memoryBlob, IntPtr originalAddress)
+ internal static unsafe IPEndPoint GetLocalEndPoint(byte[] memoryBlob, IntPtr originalAddress)
{
if (NetEventSource.IsEnabled) NetEventSource.Enter(null);
@@ -1011,7 +1011,7 @@ internal static partial class Interop
return endpoint;
}
- private unsafe static void CopyOutAddress(IntPtr address, ref SocketAddress v4address, ref SocketAddress v6address)
+ private static unsafe void CopyOutAddress(IntPtr address, ref SocketAddress v4address, ref SocketAddress v6address)
{
if (address != IntPtr.Zero)
{
diff --git a/src/Common/src/Interop/Windows/Interop.Libraries.cs b/src/Common/src/Interop/Windows/Interop.Libraries.cs
index 77c1ab6d8b..c523734535 100644
--- a/src/Common/src/Interop/Windows/Interop.Libraries.cs
+++ b/src/Common/src/Interop/Windows/Interop.Libraries.cs
@@ -14,8 +14,8 @@ internal static partial class Interop
internal const string IpHlpApi = "iphlpapi.dll";
internal const string Kernel32 = "kernel32.dll";
internal const string Memory_L1_3 = "api-ms-win-core-memory-l1-1-3.dll";
+ internal const string Mswsock = "mswsock.dll";
internal const string NCrypt = "ncrypt.dll";
- internal const string Normaliz = "normaliz.dll";
internal const string NtDll = "ntdll.dll";
internal const string OleAut32 = "oleaut32.dll";
internal const string RoBuffer = "api-ms-win-core-winrt-robuffer-l1-1-0.dll";
diff --git a/src/Common/src/Interop/Windows/NCrypt/Interop.EncryptDecrypt.cs b/src/Common/src/Interop/Windows/NCrypt/Interop.EncryptDecrypt.cs
index cbe54828f0..673b392af4 100644
--- a/src/Common/src/Interop/Windows/NCrypt/Interop.EncryptDecrypt.cs
+++ b/src/Common/src/Interop/Windows/NCrypt/Interop.EncryptDecrypt.cs
@@ -11,15 +11,15 @@ internal static partial class Interop
{
[DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)]
- internal static unsafe extern ErrorCode NCryptEncrypt(SafeNCryptKeyHandle hKey, [In] byte[] pbInput, int cbInput, void* pPaddingInfo, [Out] byte[] pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags);
+ internal static extern unsafe ErrorCode NCryptEncrypt(SafeNCryptKeyHandle hKey, [In] byte[] pbInput, int cbInput, void* pPaddingInfo, [Out] byte[] pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags);
[DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)]
- internal static unsafe extern ErrorCode NCryptEncrypt(SafeNCryptKeyHandle hKey, byte* pbInput, int cbInput, void* pPaddingInfo, byte* pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags);
+ internal static extern unsafe ErrorCode NCryptEncrypt(SafeNCryptKeyHandle hKey, byte* pbInput, int cbInput, void* pPaddingInfo, byte* pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags);
[DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)]
- internal static unsafe extern ErrorCode NCryptDecrypt(SafeNCryptKeyHandle hKey, [In] byte[] pbInput, int cbInput, void* pPaddingInfo, [Out] byte[] pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags);
+ internal static extern unsafe ErrorCode NCryptDecrypt(SafeNCryptKeyHandle hKey, [In] byte[] pbInput, int cbInput, void* pPaddingInfo, [Out] byte[] pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags);
[DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)]
- internal static unsafe extern ErrorCode NCryptDecrypt(SafeNCryptKeyHandle hKey, byte* pbInput, int cbInput, void* pPaddingInfo, byte* pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags);
+ internal static extern unsafe ErrorCode NCryptDecrypt(SafeNCryptKeyHandle hKey, byte* pbInput, int cbInput, void* pPaddingInfo, byte* pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags);
}
}
diff --git a/src/Common/src/Interop/Windows/NCrypt/Interop.SignVerify.cs b/src/Common/src/Interop/Windows/NCrypt/Interop.SignVerify.cs
index 266fceb7f2..8a56d24995 100644
--- a/src/Common/src/Interop/Windows/NCrypt/Interop.SignVerify.cs
+++ b/src/Common/src/Interop/Windows/NCrypt/Interop.SignVerify.cs
@@ -10,9 +10,9 @@ internal static partial class Interop
internal static partial class NCrypt
{
[DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)]
- internal static unsafe extern ErrorCode NCryptSignHash(SafeNCryptKeyHandle hKey, void* pPaddingInfo, [In] byte[] pbHashValue, int cbHashValue, [Out] byte[] pbSignature, int cbSignature, out int pcbResult, AsymmetricPaddingMode dwFlags);
+ internal static extern unsafe ErrorCode NCryptSignHash(SafeNCryptKeyHandle hKey, void* pPaddingInfo, [In] byte[] pbHashValue, int cbHashValue, [Out] byte[] pbSignature, int cbSignature, out int pcbResult, AsymmetricPaddingMode dwFlags);
[DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)]
- internal static unsafe extern ErrorCode NCryptVerifySignature(SafeNCryptKeyHandle hKey, void *pPaddingInfo, [In] byte[] pbHashValue, int cbHashValue, [In] byte[] pbSignature, int cbSignature, AsymmetricPaddingMode dwFlags);
+ internal static extern unsafe ErrorCode NCryptVerifySignature(SafeNCryptKeyHandle hKey, void *pPaddingInfo, [In] byte[] pbHashValue, int cbHashValue, [In] byte[] pbSignature, int cbSignature, AsymmetricPaddingMode dwFlags);
}
}
diff --git a/src/Common/src/Interop/Windows/SChannel/UnmanagedCertificateContext.cs b/src/Common/src/Interop/Windows/SChannel/UnmanagedCertificateContext.cs
index a64928f333..66c4a60c5d 100644
--- a/src/Common/src/Interop/Windows/SChannel/UnmanagedCertificateContext.cs
+++ b/src/Common/src/Interop/Windows/SChannel/UnmanagedCertificateContext.cs
@@ -9,7 +9,7 @@ using System.Security.Cryptography.X509Certificates;
namespace System.Net
{
- internal unsafe static class UnmanagedCertificateContext
+ internal static unsafe class UnmanagedCertificateContext
{
internal static X509Certificate2Collection GetRemoteCertificatesFromStoreContext(SafeFreeCertContext certContext)
{
diff --git a/src/Common/src/Interop/Windows/Winsock/Interop.TransmitFile.cs b/src/Common/src/Interop/Windows/Winsock/Interop.TransmitFile.cs
new file mode 100644
index 0000000000..28cd01c50f
--- /dev/null
+++ b/src/Common/src/Interop/Windows/Winsock/Interop.TransmitFile.cs
@@ -0,0 +1,32 @@
+// 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.Net.Sockets;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Mswsock
+ {
+ [DllImport(Interop.Libraries.Mswsock, SetLastError = true)]
+ internal static extern unsafe bool TransmitFile(
+ SafeHandle socket,
+ SafeHandle fileHandle,
+ int numberOfBytesToWrite,
+ int numberOfBytesPerSend,
+ SafeHandle overlapped,
+ TransmitFileBuffers* buffers,
+ TransmitFileOptions flags);
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TransmitFileBuffers
+ {
+ internal IntPtr Head;
+ internal int HeadLength;
+ internal IntPtr Tail;
+ internal int TailLength;
+ }
+ }
+}
diff --git a/src/Common/src/Interop/Windows/Winsock/Interop.WSASocketW.SafeCloseSocket.cs b/src/Common/src/Interop/Windows/Winsock/Interop.WSASocketW.SafeCloseSocket.cs
index 32af456e70..e18aa106fd 100644
--- a/src/Common/src/Interop/Windows/Winsock/Interop.WSASocketW.SafeCloseSocket.cs
+++ b/src/Common/src/Interop/Windows/Winsock/Interop.WSASocketW.SafeCloseSocket.cs
@@ -31,7 +31,7 @@ internal static partial class Interop
[In] SocketConstructorFlags flags);
[DllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, SetLastError = true)]
- internal unsafe static extern SafeCloseSocket.InnerSafeCloseSocket WSASocketW(
+ internal static extern unsafe SafeCloseSocket.InnerSafeCloseSocket WSASocketW(
[In] AddressFamily addressFamily,
[In] SocketType socketType,
[In] ProtocolType protocolType,
diff --git a/src/Common/src/Interop/Windows/Winsock/Interop.recv.cs b/src/Common/src/Interop/Windows/Winsock/Interop.recv.cs
index ffcf16889c..7cb21edb4c 100644
--- a/src/Common/src/Interop/Windows/Winsock/Interop.recv.cs
+++ b/src/Common/src/Interop/Windows/Winsock/Interop.recv.cs
@@ -12,7 +12,7 @@ internal static partial class Interop
{
// This method is always blocking, so it uses an IntPtr.
[DllImport(Interop.Libraries.Ws2_32, SetLastError = true)]
- internal unsafe static extern int recv(
+ internal static extern unsafe int recv(
[In] IntPtr socketHandle,
[In] byte* pinnedBuffer,
[In] int len,
diff --git a/src/Common/src/Interop/Windows/Winsock/Interop.recvfrom.cs b/src/Common/src/Interop/Windows/Winsock/Interop.recvfrom.cs
index 2e02323340..ba8757f9ce 100644
--- a/src/Common/src/Interop/Windows/Winsock/Interop.recvfrom.cs
+++ b/src/Common/src/Interop/Windows/Winsock/Interop.recvfrom.cs
@@ -12,7 +12,7 @@ internal static partial class Interop
{
// This method is always blocking, so it uses an IntPtr.
[DllImport(Interop.Libraries.Ws2_32, SetLastError = true)]
- internal unsafe static extern int recvfrom(
+ internal static extern unsafe int recvfrom(
[In] IntPtr socketHandle,
[In] byte* pinnedBuffer,
[In] int len,
diff --git a/src/Common/src/Interop/Windows/Winsock/Interop.send.cs b/src/Common/src/Interop/Windows/Winsock/Interop.send.cs
index aa101a04a9..473c6d1eca 100644
--- a/src/Common/src/Interop/Windows/Winsock/Interop.send.cs
+++ b/src/Common/src/Interop/Windows/Winsock/Interop.send.cs
@@ -12,7 +12,7 @@ internal static partial class Interop
{
// This method is always blocking, so it uses an IntPtr.
[DllImport(Interop.Libraries.Ws2_32, SetLastError = true)]
- internal unsafe static extern int send(
+ internal static extern unsafe int send(
[In] IntPtr socketHandle,
[In] byte* pinnedBuffer,
[In] int len,
diff --git a/src/Common/src/Interop/Windows/Winsock/Interop.sendto.cs b/src/Common/src/Interop/Windows/Winsock/Interop.sendto.cs
index c0691880c4..dd0ea1ba8c 100644
--- a/src/Common/src/Interop/Windows/Winsock/Interop.sendto.cs
+++ b/src/Common/src/Interop/Windows/Winsock/Interop.sendto.cs
@@ -12,7 +12,7 @@ internal static partial class Interop
{
// This method is always blocking, so it uses an IntPtr.
[DllImport(Interop.Libraries.Ws2_32, SetLastError = true)]
- internal unsafe static extern int sendto(
+ internal static extern unsafe int sendto(
[In] IntPtr socketHandle,
[In] byte* pinnedBuffer,
[In] int len,
diff --git a/src/Common/src/Interop/Windows/advapi32/Interop.ControlService.cs b/src/Common/src/Interop/Windows/advapi32/Interop.ControlService.cs
index 1d276f6131..94cda1257b 100644
--- a/src/Common/src/Interop/Windows/advapi32/Interop.ControlService.cs
+++ b/src/Common/src/Interop/Windows/advapi32/Interop.ControlService.cs
@@ -10,7 +10,7 @@ internal partial class Interop
internal partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
- internal unsafe extern static bool ControlService(IntPtr serviceHandle, int control, SERVICE_STATUS* pStatus);
+ internal extern unsafe static bool ControlService(IntPtr serviceHandle, int control, SERVICE_STATUS* pStatus);
}
}
diff --git a/src/Common/src/Interop/Windows/advapi32/Interop.EventWriteTransfer.cs b/src/Common/src/Interop/Windows/advapi32/Interop.EventWriteTransfer.cs
index b6f0591cc7..42b5ee6361 100644
--- a/src/Common/src/Interop/Windows/advapi32/Interop.EventWriteTransfer.cs
+++ b/src/Common/src/Interop/Windows/advapi32/Interop.EventWriteTransfer.cs
@@ -10,7 +10,7 @@ internal static partial class Interop
internal static partial class Advapi32
{
[DllImport(Interop.Libraries.Advapi32)]
- internal unsafe static extern int EventWriteTransfer(
+ internal static extern unsafe int EventWriteTransfer(
ulong registrationHandle,
void* eventDescriptor,
Guid* activityId,
diff --git a/src/Common/src/Interop/Windows/advapi32/Interop.RegEnumKeyEx.cs b/src/Common/src/Interop/Windows/advapi32/Interop.RegEnumKeyEx.cs
index 79fbf9f806..8469e3242a 100644
--- a/src/Common/src/Interop/Windows/advapi32/Interop.RegEnumKeyEx.cs
+++ b/src/Common/src/Interop/Windows/advapi32/Interop.RegEnumKeyEx.cs
@@ -12,7 +12,7 @@ internal partial class Interop
internal partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumKeyExW")]
- internal unsafe static extern int RegEnumKeyEx(
+ internal static extern unsafe int RegEnumKeyEx(
SafeRegistryHandle hKey,
int dwIndex,
char* lpName,
diff --git a/src/Common/src/Interop/Windows/advapi32/Interop.RegEnumValue.cs b/src/Common/src/Interop/Windows/advapi32/Interop.RegEnumValue.cs
index 83cb8251b1..696723bafe 100644
--- a/src/Common/src/Interop/Windows/advapi32/Interop.RegEnumValue.cs
+++ b/src/Common/src/Interop/Windows/advapi32/Interop.RegEnumValue.cs
@@ -11,7 +11,7 @@ internal partial class Interop
internal partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumValueW")]
- internal unsafe static extern int RegEnumValue(
+ internal static extern unsafe int RegEnumValue(
SafeRegistryHandle hKey,
int dwIndex,
char* lpValueName,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.CancelIoEx.cs b/src/Common/src/Interop/Windows/kernel32/Interop.CancelIoEx.cs
index ae253fe1c3..fc99e3052f 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.CancelIoEx.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.CancelIoEx.cs
@@ -11,6 +11,6 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- internal static unsafe extern bool CancelIoEx(SafeHandle handle, NativeOverlapped* lpOverlapped);
+ internal static extern unsafe bool CancelIoEx(SafeHandle handle, NativeOverlapped* lpOverlapped);
}
}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.ConnectNamedPipe.cs b/src/Common/src/Interop/Windows/kernel32/Interop.ConnectNamedPipe.cs
index dde659c14c..0a0b7d0df3 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.ConnectNamedPipe.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.ConnectNamedPipe.cs
@@ -13,7 +13,7 @@ internal partial class Interop
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
- unsafe internal static extern bool ConnectNamedPipe(SafePipeHandle handle, NativeOverlapped* overlapped);
+ internal static extern unsafe bool ConnectNamedPipe(SafePipeHandle handle, NativeOverlapped* overlapped);
[DllImport(Libraries.Kernel32, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.Encoding.Constants.cs b/src/Common/src/Interop/Windows/kernel32/Interop.Encoding.Constants.cs
new file mode 100644
index 0000000000..43bcf4e2ac
--- /dev/null
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.Encoding.Constants.cs
@@ -0,0 +1,12 @@
+// 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.
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ internal const uint CP_ACP = 0;
+ internal const uint WC_NO_BEST_FIT_CHARS = 0x00000400;
+ }
+}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.GetCPInfoEx.cs b/src/Common/src/Interop/Windows/kernel32/Interop.GetCPInfoEx.cs
index 1497a02482..b9218bfae3 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.GetCPInfoEx.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.GetCPInfoEx.cs
@@ -8,10 +8,8 @@ internal partial class Interop
{
internal partial class Kernel32
{
- private const uint CP_ACP = 0x0u;
-
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "GetCPInfoExW")]
- private extern unsafe static int GetCPInfoExW(uint CodePage, uint dwFlags, CPINFOEXW* lpCPInfoEx);
+ private extern static unsafe int GetCPInfoExW(uint CodePage, uint dwFlags, CPINFOEXW* lpCPInfoEx);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private unsafe struct CPINFOEXW
@@ -24,23 +22,38 @@ internal partial class Interop
internal fixed byte CodePageName[260];
}
- internal static bool TryGetACPCodePage(out int codePage)
+ internal static unsafe int GetLeadByteRanges(int codePage, byte[] leadByteRanges)
{
- codePage = 0;
- // Note: GetACP is not available in the Windows Store Profile, but calling
- // GetCPInfoEx with the value CP_ACP (0) yields the same result.
- CPINFOEXW _cpInfo;
- unsafe
+ int count = 0;
+ CPINFOEXW cpInfo;
+ if (GetCPInfoExW((uint) codePage, 0, &cpInfo) != 0)
{
- CPINFOEXW* _lpCPInfoExPtr = &(_cpInfo);
- if (GetCPInfoExW(CP_ACP, 0, _lpCPInfoExPtr) != 0)
+ // we don't care about the last 2 bytes as those are nulls
+ for (int i=0; i<10 && leadByteRanges[i] != 0; i+=2)
{
- codePage = (int)_cpInfo.CodePage;
- return true;
+ leadByteRanges[i] = cpInfo.LeadByte[i];
+ leadByteRanges[i+1] = cpInfo.LeadByte[i+1];
+ count++;
}
}
+ return count;
+ }
- return false;
+ internal static unsafe bool TryGetACPCodePage(out int codePage)
+ {
+ // Note: GetACP is not available in the Windows Store Profile, but calling
+ // GetCPInfoEx with the value CP_ACP (0) yields the same result.
+ CPINFOEXW cpInfo;
+ if (GetCPInfoExW(CP_ACP, 0, &cpInfo) != 0)
+ {
+ codePage = (int)cpInfo.CodePage;
+ return true;
+ }
+ else
+ {
+ codePage = 0;
+ return false;
+ }
}
}
}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.GetFullPathNameW.cs b/src/Common/src/Interop/Windows/kernel32/Interop.GetFullPathNameW.cs
index 9dc5e6695c..d7b164923e 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.GetFullPathNameW.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.GetFullPathNameW.cs
@@ -13,6 +13,6 @@ internal partial class Interop
/// WARNING: This method does not implicitly handle long paths. Use GetFullPathName or PathHelper.
/// </summary>
[DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
- unsafe internal static extern uint GetFullPathNameW(char* path, uint numBufferChars, SafeHandle buffer, IntPtr mustBeZero);
+ internal static extern unsafe uint GetFullPathNameW(char* path, uint numBufferChars, SafeHandle buffer, IntPtr mustBeZero);
}
}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.GetLastError.cs b/src/Common/src/Interop/Windows/kernel32/Interop.MultiByteToWideChar.cs
index 9193ce1630..428d77c904 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.GetLastError.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.MultiByteToWideChar.cs
@@ -2,6 +2,7 @@
// 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;
internal partial class Interop
@@ -9,6 +10,9 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32)]
- internal extern static int GetLastError();
+ internal static extern unsafe int MultiByteToWideChar(
+ uint CodePage, uint dwFlags,
+ byte* lpMultiByteStr, int cbMultiByte,
+ char* lpWideCharStr, int cchWideChar);
}
}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.Normalization.cs b/src/Common/src/Interop/Windows/kernel32/Interop.Normalization.cs
deleted file mode 100644
index bfdea57b17..0000000000
--- a/src/Common/src/Interop/Windows/kernel32/Interop.Normalization.cs
+++ /dev/null
@@ -1,40 +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;
-using System.Runtime.InteropServices;
-
-internal partial class Interop
-{
- // These are error codes we get back from the Normalization DLL
- internal const int ERROR_SUCCESS = 0;
- internal const int ERROR_NOT_ENOUGH_MEMORY = 8;
- internal const int ERROR_INVALID_PARAMETER = 87;
- internal const int ERROR_INSUFFICIENT_BUFFER = 122;
- internal const int ERROR_INVALID_NAME = 123;
- internal const int ERROR_NO_UNICODE_TRANSLATION = 1113;
-
- // The VM can override the last error code with this value in debug builds
- // so this value for us is equivalent to ERROR_SUCCESS
- internal const int LAST_ERROR_TRASH_VALUE = 42424;
-
- internal partial class Kernel32
- {
- //
- // Normalization APIs
- //
-
- [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)]
- internal static extern bool IsNormalizedString(int normForm, string source, int length);
-
- [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)]
- internal static extern int NormalizeString(
- int normForm,
- string source,
- int sourceLength,
- [System.Runtime.InteropServices.OutAttribute()]
- char[] destination,
- int destinationLength);
- }
-}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.ReadConsole.cs b/src/Common/src/Interop/Windows/kernel32/Interop.ReadConsole.cs
index 21a1424e5b..4c5f2719c7 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.ReadConsole.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.ReadConsole.cs
@@ -10,7 +10,7 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "ReadConsoleW")]
- internal static unsafe extern bool ReadConsole(
+ internal static extern unsafe bool ReadConsole(
IntPtr hConsoleInput,
Byte* lpBuffer,
Int32 nNumberOfCharsToRead,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.ReadConsoleOutput.cs b/src/Common/src/Interop/Windows/kernel32/Interop.ReadConsoleOutput.cs
index c944de5abd..31acf26fae 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.ReadConsoleOutput.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.ReadConsoleOutput.cs
@@ -17,6 +17,6 @@ internal partial class Interop
}
[DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ReadConsoleOutputW")]
- internal static unsafe extern bool ReadConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* pBuffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT readRegion);
+ internal static extern unsafe bool ReadConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* pBuffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT readRegion);
}
}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.ReadDirectoryChangesW.cs b/src/Common/src/Interop/Windows/kernel32/Interop.ReadDirectoryChangesW.cs
index a355554817..84cd715e57 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.ReadDirectoryChangesW.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.ReadDirectoryChangesW.cs
@@ -12,7 +12,7 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, EntryPoint = "ReadDirectoryChangesW", CharSet = CharSet.Unicode, SetLastError = true)]
- internal unsafe static extern bool ReadDirectoryChangesW(
+ internal static extern unsafe bool ReadDirectoryChangesW(
SafeFileHandle hDirectory,
byte[] lpBuffer,
int nBufferLength,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_IntPtr.cs b/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_IntPtr.cs
index 971c72f759..a018551262 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_IntPtr.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_IntPtr.cs
@@ -10,7 +10,7 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- unsafe internal static extern int ReadFile(
+ internal static extern unsafe int ReadFile(
IntPtr handle,
byte* bytes,
int numBytesToRead,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs b/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs
index 08b6bde1d3..076f7f136f 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs
@@ -11,7 +11,7 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- unsafe internal static extern int ReadFile(
+ internal static extern unsafe int ReadFile(
SafeHandle handle,
byte* bytes,
int numBytesToRead,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs b/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs
index 8f34d2bf7b..3ae65a8806 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs
@@ -12,7 +12,7 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- unsafe internal static extern int ReadFile(
+ internal static extern unsafe int ReadFile(
SafeHandle handle,
byte* bytes,
int numBytesToRead,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.SetConsoleWindowInfo.cs b/src/Common/src/Interop/Windows/kernel32/Interop.SetConsoleWindowInfo.cs
index 22129427af..17bb3008bf 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.SetConsoleWindowInfo.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.SetConsoleWindowInfo.cs
@@ -10,6 +10,6 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- internal static unsafe extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool absolute, SMALL_RECT* consoleWindow);
+ internal static extern unsafe bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool absolute, SMALL_RECT* consoleWindow);
}
}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.SetFileInformationByHandle.cs b/src/Common/src/Interop/Windows/kernel32/Interop.SetFileInformationByHandle.cs
index 5ad8308131..e7e0ef0d9b 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.SetFileInformationByHandle.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.SetFileInformationByHandle.cs
@@ -14,7 +14,7 @@ internal partial class Interop
internal static extern bool SetFileInformationByHandle(SafeFileHandle hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, ref FILE_BASIC_INFO lpFileInformation, uint dwBufferSize);
// Default values indicate "no change". Use defaults so that we don't force callsites to be aware of the default values
- internal unsafe static bool SetFileTime(
+ internal static unsafe bool SetFileTime(
SafeFileHandle hFile,
long creationTime = -1,
long lastAccessTime = -1,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.SetNamedPipeHandleState.cs b/src/Common/src/Interop/Windows/kernel32/Interop.SetNamedPipeHandleState.cs
index 641d79c2ff..6a35f5930e 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.SetNamedPipeHandleState.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.SetNamedPipeHandleState.cs
@@ -12,7 +12,7 @@ internal partial class Interop
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
- internal static unsafe extern bool SetNamedPipeHandleState(
+ internal static extern unsafe bool SetNamedPipeHandleState(
SafePipeHandle hNamedPipe,
int* lpMode,
IntPtr lpMaxCollectionCount,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.ThreadPoolIO.cs b/src/Common/src/Interop/Windows/kernel32/Interop.ThreadPoolIO.cs
index 99db906e93..bc79d31bb4 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.ThreadPoolIO.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.ThreadPoolIO.cs
@@ -11,16 +11,16 @@ internal static partial class Interop
internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- internal static unsafe extern SafeThreadPoolIOHandle CreateThreadpoolIo(SafeHandle fl, [MarshalAs(UnmanagedType.FunctionPtr)] NativeIoCompletionCallback pfnio, IntPtr context, IntPtr pcbe);
+ internal static extern unsafe SafeThreadPoolIOHandle CreateThreadpoolIo(SafeHandle fl, [MarshalAs(UnmanagedType.FunctionPtr)] NativeIoCompletionCallback pfnio, IntPtr context, IntPtr pcbe);
[DllImport(Libraries.Kernel32)]
- internal static unsafe extern void CloseThreadpoolIo(IntPtr pio);
+ internal static extern unsafe void CloseThreadpoolIo(IntPtr pio);
[DllImport(Libraries.Kernel32)]
- internal static unsafe extern void StartThreadpoolIo(SafeThreadPoolIOHandle pio);
+ internal static extern unsafe void StartThreadpoolIo(SafeThreadPoolIOHandle pio);
[DllImport(Libraries.Kernel32)]
- internal static unsafe extern void CancelThreadpoolIo(SafeThreadPoolIOHandle pio);
+ internal static extern unsafe void CancelThreadpoolIo(SafeThreadPoolIOHandle pio);
}
internal delegate void NativeIoCompletionCallback(IntPtr instance, IntPtr context, IntPtr overlapped, uint ioResult, UIntPtr numberOfBytesTransferred, IntPtr io);
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.WideCharToMultiByte.cs b/src/Common/src/Interop/Windows/kernel32/Interop.WideCharToMultiByte.cs
index 07271cae33..8fa8ff8112 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.WideCharToMultiByte.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.WideCharToMultiByte.cs
@@ -16,7 +16,5 @@ internal partial class Interop
byte* lpMultiByteStr, int cbMultiByte,
IntPtr lpDefaultChar, IntPtr lpUsedDefaultChar);
- internal const uint CP_ACP = 0;
- internal const uint WC_NO_BEST_FIT_CHARS = 0x00000400;
}
}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.WriteConsole.cs b/src/Common/src/Interop/Windows/kernel32/Interop.WriteConsole.cs
index b5fc70d4d4..629d92f21d 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.WriteConsole.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.WriteConsole.cs
@@ -10,7 +10,7 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "WriteConsoleW")]
- internal static unsafe extern bool WriteConsole(
+ internal static extern unsafe bool WriteConsole(
IntPtr hConsoleOutput,
Byte* lpBuffer,
Int32 nNumberOfCharsToWrite,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.WriteConsoleOutput.cs b/src/Common/src/Interop/Windows/kernel32/Interop.WriteConsoleOutput.cs
index 834e22c573..5e777bb52c 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.WriteConsoleOutput.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.WriteConsoleOutput.cs
@@ -10,6 +10,6 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WriteConsoleOutputW")]
- internal static unsafe extern bool WriteConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* buffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT writeRegion);
+ internal static extern unsafe bool WriteConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* buffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT writeRegion);
}
}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_IntPtr.cs b/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_IntPtr.cs
index 331a618f3f..2e18dc3ba2 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_IntPtr.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_IntPtr.cs
@@ -9,7 +9,7 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- internal static unsafe extern int WriteFile(
+ internal static extern unsafe int WriteFile(
IntPtr handle,
byte* bytes,
int numBytesToWrite,
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs b/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs
index 4c74c57def..e7e868e142 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs
@@ -18,7 +18,7 @@ internal partial class Interop
// and pass in an address for the numBytesRead parameter.
[DllImport(Libraries.Kernel32, SetLastError = true)]
- internal static unsafe extern int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);
+ internal static extern unsafe int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);
}
}
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs b/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs
index 86adae10a8..dc1e97555b 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs
+++ b/src/Common/src/Interop/Windows/kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs
@@ -17,6 +17,6 @@ internal partial class Interop
// struct in a callback (or an EndWrite method called by that callback),
// and pass in an address for the numBytesRead parameter.
[DllImport(Libraries.Kernel32, SetLastError = true)]
- internal static unsafe extern int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, IntPtr numBytesWritten_mustBeZero, NativeOverlapped* lpOverlapped);
+ internal static extern unsafe int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, IntPtr numBytesWritten_mustBeZero, NativeOverlapped* lpOverlapped);
}
}
diff --git a/src/Common/src/Interop/Windows/normaliz/Interop.Idna.cs b/src/Common/src/Interop/Windows/normaliz/Interop.Idna.cs
deleted file mode 100644
index d50822a50c..0000000000
--- a/src/Common/src/Interop/Windows/normaliz/Interop.Idna.cs
+++ /dev/null
@@ -1,37 +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;
-using System.Runtime.InteropServices;
-
-internal partial class Interop
-{
- internal partial class Normaliz
- {
- //
- // Idn APIs
- //
-
- [DllImport(Libraries.Normaliz, CharSet = CharSet.Unicode, SetLastError = true)]
- internal static extern int IdnToAscii(
- uint dwFlags,
- IntPtr lpUnicodeCharStr,
- int cchUnicodeChar,
- [System.Runtime.InteropServices.OutAttribute()]
- IntPtr lpASCIICharStr,
- int cchASCIIChar);
-
- [DllImport(Libraries.Normaliz, CharSet = CharSet.Unicode, SetLastError = true)]
- internal static extern int IdnToUnicode(
- uint dwFlags,
- IntPtr lpASCIICharStr,
- int cchASCIIChar,
- [System.Runtime.InteropServices.OutAttribute()]
- IntPtr lpUnicodeCharStr,
- int cchUnicodeChar);
-
- internal const int IDN_ALLOW_UNASSIGNED = 0x1;
- internal const int IDN_USE_STD3_ASCII_RULES = 0x2;
- }
-}
diff --git a/src/Common/src/Interop/Windows/shell32/Interop.SHGetKnownFolderPath.cs b/src/Common/src/Interop/Windows/shell32/Interop.SHGetKnownFolderPath.cs
index 1843afe9b9..f61435ca23 100644
--- a/src/Common/src/Interop/Windows/shell32/Interop.SHGetKnownFolderPath.cs
+++ b/src/Common/src/Interop/Windows/shell32/Interop.SHGetKnownFolderPath.cs
@@ -32,7 +32,7 @@ internal partial class Interop
#pragma warning restore BCL0015
internal static int SHGetKnownFolderPath(
- [MarshalAs(UnmanagedType.LPStruct)] Guid rfid,
+ Guid rfid,
uint dwFlags,
IntPtr hToken,
out string ppszPath)
diff --git a/src/Common/src/Interop/Windows/sspicli/Interop.SSPI.cs b/src/Common/src/Interop/Windows/sspicli/Interop.SSPI.cs
index 37313998c0..a08b49dba7 100644
--- a/src/Common/src/Interop/Windows/sspicli/Interop.SSPI.cs
+++ b/src/Common/src/Interop/Windows/sspicli/Interop.SSPI.cs
@@ -263,7 +263,7 @@ internal static partial class Interop
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)]
- internal static unsafe extern int DecryptMessage(
+ internal static extern unsafe int DecryptMessage(
[In] ref CredHandle contextHandle,
[In, Out] ref SecBufferDesc inputOutput,
[In] uint sequenceNumber,
@@ -290,7 +290,7 @@ internal static partial class Interop
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)]
- internal unsafe static extern int AcceptSecurityContext(
+ internal static extern unsafe int AcceptSecurityContext(
ref CredHandle credentialHandle,
[In] void* inContextPtr,
[In] SecBufferDesc* inputBuffer,
@@ -303,13 +303,13 @@ internal static partial class Interop
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)]
- internal unsafe static extern int QueryContextAttributesW(
+ internal static extern unsafe int QueryContextAttributesW(
ref CredHandle contextHandle,
[In] ContextAttribute attribute,
[In] void* buffer);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)]
- internal unsafe static extern int SetContextAttributesW(
+ internal static extern unsafe int SetContextAttributesW(
ref CredHandle contextHandle,
[In] ContextAttribute attribute,
[In] byte[] buffer,
@@ -321,7 +321,7 @@ internal static partial class Interop
[Out] out SafeFreeContextBuffer_SECURITY handle);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
- internal unsafe static extern int AcquireCredentialsHandleW(
+ internal static extern unsafe int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
@@ -334,7 +334,7 @@ internal static partial class Interop
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
- internal unsafe static extern int AcquireCredentialsHandleW(
+ internal static extern unsafe int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
@@ -347,7 +347,7 @@ internal static partial class Interop
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
- internal unsafe static extern int AcquireCredentialsHandleW(
+ internal static extern unsafe int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
@@ -360,7 +360,7 @@ internal static partial class Interop
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
- internal unsafe static extern int AcquireCredentialsHandleW(
+ internal static extern unsafe int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
@@ -373,7 +373,7 @@ internal static partial class Interop
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)]
- internal unsafe static extern int InitializeSecurityContextW(
+ internal static extern unsafe int InitializeSecurityContextW(
ref CredHandle credentialHandle,
[In] void* inContextPtr,
[In] byte* targetName,
@@ -389,23 +389,23 @@ internal static partial class Interop
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)]
- internal unsafe static extern int CompleteAuthToken(
+ internal static extern unsafe int CompleteAuthToken(
[In] void* inContextPtr,
[In, Out] ref SecBufferDesc inputBuffers
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)]
- internal unsafe static extern int ApplyControlToken(
+ internal static extern unsafe int ApplyControlToken(
[In] void* inContextPtr,
[In, Out] ref SecBufferDesc inputBuffers
);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)]
- internal unsafe static extern SECURITY_STATUS SspiFreeAuthIdentity(
+ internal static extern unsafe SECURITY_STATUS SspiFreeAuthIdentity(
[In] IntPtr authData);
[DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
- internal unsafe static extern SECURITY_STATUS SspiEncodeStringsAsAuthIdentity(
+ internal static extern unsafe SECURITY_STATUS SspiEncodeStringsAsAuthIdentity(
[In] string userName,
[In] string domainName,
[In] string password,
diff --git a/src/Common/src/Interop/Windows/sspicli/SSPIWrapper.cs b/src/Common/src/Interop/Windows/sspicli/SSPIWrapper.cs
index bc39991e0d..7adaee70cc 100644
--- a/src/Common/src/Interop/Windows/sspicli/SSPIWrapper.cs
+++ b/src/Common/src/Interop/Windows/sspicli/SSPIWrapper.cs
@@ -178,7 +178,7 @@ namespace System.Net
int errorCode = secModule.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, datarep, inputBuffer, outputBuffer, ref outFlags);
if (NetEventSource.IsEnabled) NetEventSource.Log.SecurityContextInputBuffer(nameof(InitializeSecurityContext), inputBuffer?.size ?? 0, outputBuffer.size, (Interop.SECURITY_STATUS)errorCode);
-
+
return errorCode;
}
@@ -266,7 +266,7 @@ namespace System.Net
VerifySignature
}
- private unsafe static int EncryptDecryptHelper(OP op, SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber)
+ private static unsafe int EncryptDecryptHelper(OP op, SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber)
{
Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(input.Length);
var unmanagedBuffer = new Interop.SspiCli.SecBuffer[input.Length];
@@ -378,7 +378,7 @@ namespace System.Net
}
if (NetEventSource.IsEnabled && errorCode != 0)
- {
+ {
if (errorCode == Interop.SspiCli.SEC_I_RENEGOTIATE)
{
NetEventSource.Error(null, SR.Format(SR.event_OperationReturnedSomething, op, "SEC_I_RENEGOTIATE"));
diff --git a/src/Common/src/Interop/Windows/sspicli/SecuritySafeHandles.cs b/src/Common/src/Interop/Windows/sspicli/SecuritySafeHandles.cs
index 6d02e0a003..417024ef40 100644
--- a/src/Common/src/Interop/Windows/sspicli/SecuritySafeHandles.cs
+++ b/src/Common/src/Interop/Windows/sspicli/SecuritySafeHandles.cs
@@ -75,12 +75,12 @@ namespace System.Net.Security
// This method switches between three non-interruptible helper methods. (This method can't be both non-interruptible and
// reference imports from all three DLLs - doing so would cause all three DLLs to try to be bound to.)
//
- public unsafe static int QueryContextAttributes(SafeDeleteContext phContext, Interop.SspiCli.ContextAttribute contextAttribute, byte* buffer, SafeHandle refHandle)
+ public static unsafe int QueryContextAttributes(SafeDeleteContext phContext, Interop.SspiCli.ContextAttribute contextAttribute, byte* buffer, SafeHandle refHandle)
{
return QueryContextAttributes_SECURITY(phContext, contextAttribute, buffer, refHandle);
}
- private unsafe static int QueryContextAttributes_SECURITY(
+ private static unsafe int QueryContextAttributes_SECURITY(
SafeDeleteContext phContext,
Interop.SspiCli.ContextAttribute contextAttribute,
byte* buffer,
@@ -220,7 +220,7 @@ namespace System.Net.Security
}
#endif
- public unsafe static int AcquireCredentialsHandle(
+ public static unsafe int AcquireCredentialsHandle(
string package,
Interop.SspiCli.CredentialUse intent,
ref Interop.SspiCli.SEC_WINNT_AUTH_IDENTITY_W authdata,
@@ -255,7 +255,7 @@ namespace System.Net.Security
return errorCode;
}
- public unsafe static int AcquireDefaultCredential(
+ public static unsafe int AcquireDefaultCredential(
string package,
Interop.SspiCli.CredentialUse intent,
out SafeFreeCredentials outCredential)
@@ -290,7 +290,7 @@ namespace System.Net.Security
return errorCode;
}
- public unsafe static int AcquireCredentialsHandle(
+ public static unsafe int AcquireCredentialsHandle(
string package,
Interop.SspiCli.CredentialUse intent,
ref SafeSspiAuthDataHandle authdata,
@@ -319,7 +319,7 @@ namespace System.Net.Security
return errorCode;
}
- public unsafe static int AcquireCredentialsHandle(
+ public static unsafe int AcquireCredentialsHandle(
string package,
Interop.SspiCli.CredentialUse intent,
ref Interop.SspiCli.SCHANNEL_CRED authdata,
@@ -448,7 +448,7 @@ namespace System.Net.Security
protected SafeFreeCredentials _EffectiveCredential;
//-------------------------------------------------------------------
- internal unsafe static int InitializeSecurityContext(
+ internal static unsafe int InitializeSecurityContext(
ref SafeFreeCredentials inCredentials,
ref SafeDeleteContext refContext,
string targetName,
@@ -740,7 +740,7 @@ namespace System.Net.Security
}
//-------------------------------------------------------------------
- internal unsafe static int AcceptSecurityContext(
+ internal static unsafe int AcceptSecurityContext(
ref SafeFreeCredentials inCredentials,
ref SafeDeleteContext refContext,
Interop.SspiCli.ContextFlags inFlags,
@@ -1021,7 +1021,7 @@ namespace System.Net.Security
return errorCode;
}
- internal unsafe static int CompleteAuthToken(
+ internal static unsafe int CompleteAuthToken(
ref SafeDeleteContext refContext,
SecurityBuffer[] inSecBuffers)
{
@@ -1120,7 +1120,7 @@ namespace System.Net.Security
return errorCode;
}
- internal unsafe static int ApplyControlToken(
+ internal static unsafe int ApplyControlToken(
ref SafeDeleteContext refContext,
SecurityBuffer[] inSecBuffers)
{
@@ -1264,12 +1264,12 @@ namespace System.Net.Security
return new SafeFreeContextBufferChannelBinding_SECURITY();
}
- public unsafe static int QueryContextChannelBinding(SafeDeleteContext phContext, Interop.SspiCli.ContextAttribute contextAttribute, SecPkgContext_Bindings* buffer, SafeFreeContextBufferChannelBinding refHandle)
+ public static unsafe int QueryContextChannelBinding(SafeDeleteContext phContext, Interop.SspiCli.ContextAttribute contextAttribute, SecPkgContext_Bindings* buffer, SafeFreeContextBufferChannelBinding refHandle)
{
return QueryContextChannelBinding_SECURITY(phContext, contextAttribute, buffer, refHandle);
}
- private unsafe static int QueryContextChannelBinding_SECURITY(SafeDeleteContext phContext, Interop.SspiCli.ContextAttribute contextAttribute, SecPkgContext_Bindings* buffer, SafeFreeContextBufferChannelBinding refHandle)
+ private static unsafe int QueryContextChannelBinding_SECURITY(SafeDeleteContext phContext, Interop.SspiCli.ContextAttribute contextAttribute, SecPkgContext_Bindings* buffer, SafeFreeContextBufferChannelBinding refHandle)
{
int status = (int)Interop.SECURITY_STATUS.InvalidHandle;
diff --git a/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs b/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs
index 030624be25..502e6db07d 100644
--- a/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs
+++ b/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs
@@ -15,6 +15,7 @@ namespace System.Collections.Generic
private const int StartingCapacity = 4;
private const int ResizeLimit = 32;
+ private readonly int _maxCapacity; // The maximum capacity this builder can have.
private T[] _first; // The first buffer we store items in. Resized until ResizeLimit.
private ArrayBuilder<T[]> _buffers; // After ResizeLimit * 2, we store previous buffers we've filled out here.
private T[] _current; // Current buffer we're reading into. If _count <= ResizeLimit, this is _first.
@@ -26,15 +27,29 @@ namespace System.Collections.Generic
/// </summary>
/// <param name="initialize">Pass <c>true</c>.</param>
public LargeArrayBuilder(bool initialize)
+ : this(maxCapacity: int.MaxValue)
{
// This is a workaround for C# not having parameterless struct constructors yet.
// Once it gets them, replace this with a parameterless constructor.
Debug.Assert(initialize);
+ }
+
+ /// <summary>
+ /// Constructs a new builder with the specified maximum capacity.
+ /// </summary>
+ /// <param name="maxCapacity">The maximum capacity this builder can have.</param>
+ /// <remarks>
+ /// Do not add more than <paramref name="maxCapacity"/> items to this builder.
+ /// </remarks>
+ public LargeArrayBuilder(int maxCapacity)
+ {
+ Debug.Assert(maxCapacity >= 0);
_first = _current = Array.Empty<T>();
_buffers = default(ArrayBuilder<T[]>);
_index = 0;
_count = 0;
+ _maxCapacity = maxCapacity;
}
/// <summary>
@@ -53,6 +68,8 @@ namespace System.Collections.Generic
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(T item)
{
+ Debug.Assert(_maxCapacity > _count);
+
if (_index == _current.Length)
{
AllocateBuffer();
@@ -66,6 +83,10 @@ namespace System.Collections.Generic
/// Adds a range of items to this builder.
/// </summary>
/// <param name="items">The sequence to add.</param>
+ /// <remarks>
+ /// It is the caller's responsibility to ensure that adding <paramref name="items"/>
+ /// does not cause the builder to exceed its maximum capacity.
+ /// </remarks>
public void AddRange(IEnumerable<T> items)
{
Debug.Assert(items != null);
@@ -107,10 +128,9 @@ namespace System.Collections.Generic
/// <param name="count">The number of items to copy.</param>
public void CopyTo(T[] array, int arrayIndex, int count)
{
- Debug.Assert(array != null);
Debug.Assert(arrayIndex >= 0);
Debug.Assert(count >= 0 && count <= Count);
- Debug.Assert(array.Length - arrayIndex >= count);
+ Debug.Assert(array?.Length - arrayIndex >= count);
for (int i = -1; count > 0; i++)
{
@@ -161,7 +181,9 @@ namespace System.Collections.Generic
// and start reading into _current. Set _index to 0.
// - When _current runs out of space, add it to _buffers and repeat the
// above step, except with _current.Length * 2.
+ // - Make sure we never pass _maxCapacity in all of the above steps.
+ Debug.Assert((uint)_maxCapacity > (uint)_count);
Debug.Assert(_index == _current.Length, $"{nameof(AllocateBuffer)} was called, but there's more space.");
// If _count is int.MinValue, we want to go down the other path which will raise an exception.
@@ -170,7 +192,7 @@ namespace System.Collections.Generic
// We haven't passed ResizeLimit. Resize _first, copying over the previous items.
Debug.Assert(_current == _first && _count == _first.Length);
- int nextCapacity = _count == 0 ? StartingCapacity : _count * 2;
+ int nextCapacity = Math.Min(_count == 0 ? StartingCapacity : _count * 2, _maxCapacity);
_current = new T[nextCapacity];
Array.Copy(_first, 0, _current, 0, _count);
@@ -178,6 +200,7 @@ namespace System.Collections.Generic
}
else
{
+ Debug.Assert(_maxCapacity > ResizeLimit);
Debug.Assert(_count == ResizeLimit ^ _current != _first);
int nextCapacity;
@@ -187,8 +210,18 @@ namespace System.Collections.Generic
}
else
{
+ // Example scenario: Let's say _count == 256.
+ // Then our buffers look like this: | 32 | 32 | 64 | 128 |
+ // As you can see, our count will be just double the last buffer.
+ // Now, say _maxCapacity is 500. We will find the right amount to allocate by
+ // doing min(256, 500 - 256). The lhs represents double the last buffer,
+ // the rhs the limit minus the amount we've already allocated.
+
+ Debug.Assert(_count >= ResizeLimit * 2);
+ Debug.Assert(_count == _current.Length * 2);
+
_buffers.Add(_current);
- nextCapacity = _current.Length * 2;
+ nextCapacity = Math.Min(_count, _maxCapacity - _count);
}
_current = new T[nextCapacity];
diff --git a/src/Common/src/System/Dynamic/Utils/CacheDict.cs b/src/Common/src/System/Dynamic/Utils/CacheDict.cs
index 7dca7c1c4b..a891109915 100644
--- a/src/Common/src/System/Dynamic/Utils/CacheDict.cs
+++ b/src/Common/src/System/Dynamic/Utils/CacheDict.cs
@@ -16,21 +16,21 @@ namespace System.Dynamic.Utils
// cache size is always ^2.
// items are placed at [hash ^ mask]
// new item will displace previous one at the same location.
- private readonly int mask;
- private readonly Entry[] entries;
+ private readonly int _mask;
+ private readonly Entry[] _entries;
// class, to ensure atomic updates.
private sealed class Entry
{
- internal readonly int hash;
- internal readonly TKey key;
- internal readonly TValue value;
+ internal readonly int _hash;
+ internal readonly TKey _key;
+ internal readonly TValue _value;
internal Entry(int hash, TKey key, TValue value)
{
- this.hash = hash;
- this.key = key;
- this.value = value;
+ _hash = hash;
+ _key = key;
+ _value = value;
}
}
@@ -41,8 +41,8 @@ namespace System.Dynamic.Utils
internal CacheDict(int size)
{
int alignedSize = AlignSize(size);
- this.mask = alignedSize - 1;
- this.entries = new Entry[alignedSize];
+ _mask = alignedSize - 1;
+ _entries = new Entry[alignedSize];
}
private static int AlignSize(int size)
@@ -68,12 +68,12 @@ namespace System.Dynamic.Utils
internal bool TryGetValue(TKey key, out TValue value)
{
int hash = key.GetHashCode();
- int idx = hash & mask;
+ int idx = hash & _mask;
- Entry entry = Volatile.Read(ref this.entries[idx]);
- if (entry != null && entry.hash == hash && entry.key.Equals(key))
+ Entry entry = Volatile.Read(ref _entries[idx]);
+ if (entry != null && entry._hash == hash && entry._key.Equals(key))
{
- value = entry.value;
+ value = entry._value;
return true;
}
@@ -88,12 +88,12 @@ namespace System.Dynamic.Utils
internal void Add(TKey key, TValue value)
{
int hash = key.GetHashCode();
- int idx = hash & mask;
+ int idx = hash & _mask;
- Entry entry = Volatile.Read(ref this.entries[idx]);
- if (entry == null || entry.hash != hash || !entry.key.Equals(key))
+ Entry entry = Volatile.Read(ref _entries[idx]);
+ if (entry == null || entry._hash != hash || !entry._key.Equals(key))
{
- Volatile.Write(ref entries[idx], new Entry(hash, key, value));
+ Volatile.Write(ref _entries[idx], new Entry(hash, key, value));
}
}
diff --git a/src/Common/src/System/Dynamic/Utils/CollectionExtensions.AddFirst.cs b/src/Common/src/System/Dynamic/Utils/CollectionExtensions.AddFirst.cs
deleted file mode 100644
index 14f72f7f30..0000000000
--- a/src/Common/src/System/Dynamic/Utils/CollectionExtensions.AddFirst.cs
+++ /dev/null
@@ -1,19 +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.Collections.Generic;
-
-namespace System.Dynamic.Utils
-{
- internal static partial class CollectionExtensions
- {
- public static T[] AddFirst<T>(this IList<T> list, T item)
- {
- T[] res = new T[list.Count + 1];
- res[0] = item;
- list.CopyTo(res, 1);
- return res;
- }
- }
-}
diff --git a/src/Common/src/System/Dynamic/Utils/CollectionExtensions.Map.cs b/src/Common/src/System/Dynamic/Utils/CollectionExtensions.Map.cs
deleted file mode 100644
index 1b035c40b8..0000000000
--- a/src/Common/src/System/Dynamic/Utils/CollectionExtensions.Map.cs
+++ /dev/null
@@ -1,24 +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.
-
-namespace System.Dynamic.Utils
-{
- internal static partial class CollectionExtensions
- {
- // Name needs to be different so it doesn't conflict with Enumerable.Select
- public static U[] Map<T, U>(this T[] array, Func<T, U> select)
- {
- int count = array.Length;
-
- U[] result = new U[count];
-
- for (int i = 0; i < count; i++)
- {
- result[i] = select(array[i]);
- }
-
- return result;
- }
- }
-}
diff --git a/src/Common/src/System/Dynamic/Utils/CollectionExtensions.cs b/src/Common/src/System/Dynamic/Utils/CollectionExtensions.cs
deleted file mode 100644
index 284c880dbb..0000000000
--- a/src/Common/src/System/Dynamic/Utils/CollectionExtensions.cs
+++ /dev/null
@@ -1,100 +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.Diagnostics.Contracts;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Runtime.CompilerServices;
-
-namespace System.Dynamic.Utils
-{
- internal static partial class CollectionExtensions
- {
- /// <summary>
- /// Wraps the provided enumerable into a ReadOnlyCollection{T}
- ///
- /// Copies all of the data into a new array, so the data can't be
- /// changed after creation. The exception is if the enumerable is
- /// already a ReadOnlyCollection{T}, in which case we just return it.
- /// </summary>
- [Pure]
- public static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> enumerable)
- {
- if (enumerable == null)
- {
- return EmptyReadOnlyCollection<T>.Instance;
- }
-
- var troc = enumerable as TrueReadOnlyCollection<T>;
- if (troc != null)
- {
- return troc;
- }
-
- var builder = enumerable as ReadOnlyCollectionBuilder<T>;
- if (builder != null)
- {
- return builder.ToReadOnlyCollection();
- }
-
- T[] array = EnumerableHelpers.ToArray(enumerable);
- return array.Length == 0 ?
- EmptyReadOnlyCollection<T>.Instance :
- new TrueReadOnlyCollection<T>(array);
- }
-
- // We could probably improve the hashing here
- public static int ListHashCode<T>(this ReadOnlyCollection<T> list)
- {
- EqualityComparer<T> cmp = EqualityComparer<T>.Default;
- int h = 6551;
- foreach (T t in list)
- {
- h ^= (h << 5) ^ cmp.GetHashCode(t);
- }
- return h;
- }
-
- [Pure]
- public static bool ListEquals<T>(this ReadOnlyCollection<T> first, ReadOnlyCollection<T> second)
- {
- if (first == second)
- {
- return true;
- }
-
- int count = first.Count;
-
- if (count != second.Count)
- {
- return false;
- }
-
- EqualityComparer<T> cmp = EqualityComparer<T>.Default;
- for(int i = 0; i != count; ++i)
- {
- if (!cmp.Equals(first[i], second[i]))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static T[] RemoveFirst<T>(this T[] array)
- {
- T[] result = new T[array.Length - 1];
- Array.Copy(array, 1, result, 0, result.Length);
- return result;
- }
-
- public static T[] RemoveLast<T>(this T[] array)
- {
- T[] result = new T[array.Length - 1];
- Array.Copy(array, 0, result, 0, result.Length);
- return result;
- }
- }
-}
diff --git a/src/Common/src/System/Dynamic/Utils/ContractUtils.cs b/src/Common/src/System/Dynamic/Utils/ContractUtils.cs
index 1474e3921b..a8b1affeea 100644
--- a/src/Common/src/System/Dynamic/Utils/ContractUtils.cs
+++ b/src/Common/src/System/Dynamic/Utils/ContractUtils.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Threading;
namespace System.Dynamic.Utils
{
@@ -140,6 +141,12 @@ namespace System.Dynamic.Utils
}
}
+ [Conditional("DEBUG")]
+ public static void AssertLockHeld(object lockObject)
+ {
+ Debug.Assert(Monitor.IsEntered(lockObject), "Expected lock is not held.");
+ }
+
private static string GetParamName(string paramName, int index)
{
if (index >= 0)
diff --git a/src/Common/src/System/Dynamic/Utils/DelegateHelpers.cs b/src/Common/src/System/Dynamic/Utils/DelegateHelpers.cs
index 2797ff40f7..bbca8d01c2 100644
--- a/src/Common/src/System/Dynamic/Utils/DelegateHelpers.cs
+++ b/src/Common/src/System/Dynamic/Utils/DelegateHelpers.cs
@@ -12,7 +12,7 @@ namespace System.Dynamic.Utils
{
internal static partial class DelegateHelpers
{
- internal static Delegate CreateObjectArrayDelegate(Type delegateType, System.Func<object[], object> handler)
+ internal static Delegate CreateObjectArrayDelegate(Type delegateType, Func<object[], object> handler)
{
#if !FEATURE_DYNAMIC_DELEGATE
return CreateObjectArrayDelegateRefEmit(delegateType, handler);
@@ -24,6 +24,9 @@ namespace System.Dynamic.Utils
#if !FEATURE_DYNAMIC_DELEGATE
+ private static readonly MethodInfo s_FuncInvoke = typeof(Func<object[], object>).GetMethod("Invoke");
+ private static readonly MethodInfo s_ArrayEmpty = typeof(Array).GetMethod(nameof(Array.Empty)).MakeGenericMethod(typeof(object));
+
// We will generate the following code:
//
// object ret;
@@ -37,14 +40,14 @@ namespace System.Dynamic.Utils
// param0 = (T0)args[0]; // only generated for each byref argument
// }
// return (TRet)ret;
- private static Delegate CreateObjectArrayDelegateRefEmit(Type delegateType, System.Func<object[], object> handler)
+ private static Delegate CreateObjectArrayDelegateRefEmit(Type delegateType, Func<object[], object> handler)
{
MethodInfo delegateInvokeMethod = delegateType.GetMethod("Invoke");
Type returnType = delegateInvokeMethod.ReturnType;
bool hasReturnValue = returnType != typeof(void);
- ParameterInfo[] parameters = delegateInvokeMethod.GetParameters();
+ ParameterInfo[] parameters = delegateInvokeMethod.GetParametersCached();
Type[] paramTypes = new Type[parameters.Length + 1];
paramTypes[0] = typeof(Func<object[], object>);
for (int i = 0; i < parameters.Length; i++)
@@ -59,8 +62,15 @@ namespace System.Dynamic.Utils
LocalBuilder retValue = ilgen.DeclareLocal(typeof(object));
// create the argument array
- ilgen.Emit(OpCodes.Ldc_I4, parameters.Length);
- ilgen.Emit(OpCodes.Newarr, typeof(object));
+ if (parameters.Length == 0)
+ {
+ ilgen.Emit(OpCodes.Call, s_ArrayEmpty);
+ }
+ else
+ {
+ ilgen.Emit(OpCodes.Ldc_I4, parameters.Length);
+ ilgen.Emit(OpCodes.Newarr, typeof(object));
+ }
ilgen.Emit(OpCodes.Stloc, argArray);
// populate object array
@@ -99,8 +109,7 @@ namespace System.Dynamic.Utils
ilgen.Emit(OpCodes.Ldloc, argArray);
// invoke Invoke
- MethodInfo invoke = typeof(Func<object[], object>).GetMethod("Invoke");
- ilgen.Emit(OpCodes.Callvirt, invoke);
+ ilgen.Emit(OpCodes.Callvirt, s_FuncInvoke);
ilgen.Emit(OpCodes.Stloc, retValue);
if (hasRefArgs)
diff --git a/src/Common/src/System/Dynamic/Utils/ExpressionVisitorUtils.cs b/src/Common/src/System/Dynamic/Utils/ExpressionVisitorUtils.cs
deleted file mode 100644
index 1e14a048a8..0000000000
--- a/src/Common/src/System/Dynamic/Utils/ExpressionVisitorUtils.cs
+++ /dev/null
@@ -1,36 +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.Linq.Expressions;
-
-namespace System.Dynamic.Utils
-{
- internal static partial class ExpressionVisitorUtils
- {
- public static Expression[] VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
- {
- Expression[] newNodes = null;
- for (int i = 0, n = nodes.ArgumentCount; i < n; i++)
- {
- Expression curNode = nodes.GetArgument(i);
- Expression node = visitor.Visit(curNode);
-
- if (newNodes != null)
- {
- newNodes[i] = node;
- }
- else if (!object.ReferenceEquals(node, curNode))
- {
- newNodes = new Expression[n];
- for (int j = 0; j < i; j++)
- {
- newNodes[j] = nodes.GetArgument(j);
- }
- newNodes[i] = node;
- }
- }
- return newNodes;
- }
- }
-}
diff --git a/src/Common/src/System/Globalization/FormatProvider.Number.cs b/src/Common/src/System/Globalization/FormatProvider.Number.cs
index e4fc5ea6f7..969d4793ab 100644
--- a/src/Common/src/System/Globalization/FormatProvider.Number.cs
+++ b/src/Common/src/System/Globalization/FormatProvider.Number.cs
@@ -296,7 +296,7 @@ namespace System.Globalization
return (((ch) == 0x20) || ((ch) >= 0x09 && (ch) <= 0x0D));
}
- private unsafe static char* MatchChars(char* p, string str)
+ private static unsafe char* MatchChars(char* p, string str)
{
fixed (char* stringPointer = str)
{
@@ -304,7 +304,7 @@ namespace System.Globalization
}
}
- private unsafe static char* MatchChars(char* p, char* str)
+ private static unsafe char* MatchChars(char* p, char* str)
{
Debug.Assert(p != null && str != null);
@@ -325,7 +325,7 @@ namespace System.Globalization
return null;
}
- private unsafe static bool ParseNumber(ref char* str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, bool parseDecimal)
+ private static unsafe bool ParseNumber(ref char* str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, bool parseDecimal)
{
const int StateSign = 0x0001;
const int StateParens = 0x0002;
@@ -555,7 +555,7 @@ namespace System.Globalization
return true;
}
- internal unsafe static bool TryStringToNumber(string str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, bool parseDecimal)
+ internal static unsafe bool TryStringToNumber(string str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, bool parseDecimal)
{
if (str == null)
{
@@ -622,7 +622,7 @@ namespace System.Globalization
private static string s_posNumberFormat = "#";
- internal unsafe static void Int32ToDecChars(char* buffer, ref int index, uint value, int digits)
+ internal static unsafe void Int32ToDecChars(char* buffer, ref int index, uint value, int digits)
{
while (--digits >= 0 || value != 0)
{
diff --git a/src/Common/src/System/Globalization/IdnMapping.Windows.cs b/src/Common/src/System/Globalization/IdnMapping.Windows.cs
deleted file mode 100644
index 185d1f5356..0000000000
--- a/src/Common/src/System/Globalization/IdnMapping.Windows.cs
+++ /dev/null
@@ -1,113 +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.Diagnostics;
-using System.Runtime.InteropServices;
-
-namespace System.Globalization
-{
- sealed partial class IdnMapping
- {
- private unsafe string GetAsciiCore(char* unicode, int count)
- {
- uint flags = Flags;
-
- // Determine the required length
- int length = Interop.Normaliz.IdnToAscii(flags, new IntPtr(unicode), count, IntPtr.Zero, 0);
- if (length == 0)
- {
- ThrowForZeroLength(nameof(unicode), SR.Argument_IdnIllegalName, SR.Argument_InvalidCharSequenceNoIndex);
- }
-
- // Do the conversion
- const int StackAllocThreshold = 512; // arbitrary limit to switch from stack to heap allocation
- if (length < StackAllocThreshold)
- {
- char* output = stackalloc char[length];
- return GetAsciiCore(unicode, count, flags, output, length);
- }
- else
- {
- char[] output = new char[length];
- fixed (char* pOutput = output)
- {
- return GetAsciiCore(unicode, count, flags, pOutput, length);
- }
- }
- }
-
- private unsafe string GetAsciiCore(char* unicode, int count, uint flags, char* output, int outputLength)
- {
- int length = Interop.Normaliz.IdnToAscii(flags, new IntPtr(unicode), count, new IntPtr(output), outputLength);
- if (length == 0)
- {
- ThrowForZeroLength(nameof(unicode), SR.Argument_IdnIllegalName, SR.Argument_InvalidCharSequenceNoIndex);
- }
- Debug.Assert(length == outputLength);
- return new string(output, 0, length);
- }
-
- private unsafe string GetUnicodeCore(char* ascii, int count)
- {
- uint flags = Flags;
-
- // Determine the required length
- int length = Interop.Normaliz.IdnToUnicode(flags, new IntPtr(ascii), count, IntPtr.Zero, 0);
- if (length == 0)
- {
- ThrowForZeroLength(nameof(ascii), SR.Argument_IdnIllegalName, SR.Argument_IdnBadPunycode);
- }
-
- // Do the conversion
- const int StackAllocThreshold = 512; // arbitrary limit to switch from stack to heap allocation
- if (length < StackAllocThreshold)
- {
- char* output = stackalloc char[length];
- return GetUnicodeCore(ascii, count, flags, output, length);
- }
- else
- {
- char[] output = new char[length];
- fixed (char* pOutput = output)
- {
- return GetUnicodeCore(ascii, count, flags, pOutput, length);
- }
- }
- }
-
- private unsafe string GetUnicodeCore(char* ascii, int count, uint flags, char* output, int outputLength)
- {
- int length = Interop.Normaliz.IdnToUnicode(flags, new IntPtr(ascii), count, new IntPtr(output), outputLength);
- if (length == 0)
- {
- ThrowForZeroLength(nameof(ascii), SR.Argument_IdnIllegalName, SR.Argument_IdnBadPunycode);
- }
- Debug.Assert(length == outputLength);
- return new string(output, 0, length);
- }
-
- // -----------------------------
- // ---- PAL layer ends here ----
- // -----------------------------
-
- private uint Flags
- {
- get
- {
- int flags =
- (AllowUnassigned ? Interop.Normaliz.IDN_ALLOW_UNASSIGNED : 0) |
- (UseStd3AsciiRules ? Interop.Normaliz.IDN_USE_STD3_ASCII_RULES : 0);
- return (uint)flags;
- }
- }
-
- private static void ThrowForZeroLength(string paramName, string invalidNameString, string otherString)
- {
- throw new ArgumentException(
- Marshal.GetLastWin32Error() == Interop.ERROR_INVALID_NAME ? invalidNameString : otherString,
- paramName);
- }
- }
-}
-
diff --git a/src/Common/src/System/Globalization/IdnMapping.cs b/src/Common/src/System/Globalization/IdnMapping.cs
deleted file mode 100644
index 04a978dfc1..0000000000
--- a/src/Common/src/System/Globalization/IdnMapping.cs
+++ /dev/null
@@ -1,157 +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.
-
-// This file contains the IDN functions and implementation.
-//
-// This allows encoding of non-ASCII domain names in a "punycode" form,
-// for example:
-//
-// \u5B89\u5BA4\u5948\u7F8E\u6075-with-SUPER-MONKEYS
-//
-// is encoded as:
-//
-// xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n
-//
-// Additional options are provided to allow unassigned IDN characters and
-// to validate according to the Std3ASCII Rules (like DNS names).
-//
-// There are also rules regarding bidirectionality of text and the length
-// of segments.
-//
-// For additional rules see also:
-// RFC 3490 - Internationalizing Domain Names in Applications (IDNA)
-// RFC 3491 - Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN)
-// RFC 3492 - Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)
-
-using System.Diagnostics.Contracts;
-
-namespace System.Globalization
-{
- // IdnMapping class used to map names to Punycode
-#if INTERNAL_GLOBALIZATION_EXTENSIONS
- internal
-#else
- public
-#endif
- sealed partial class IdnMapping
- {
- private bool _allowUnassigned;
- private bool _useStd3AsciiRules;
-
- public IdnMapping()
- {
- }
-
- public bool AllowUnassigned
- {
- get { return _allowUnassigned; }
- set { _allowUnassigned = value; }
- }
-
- public bool UseStd3AsciiRules
- {
- get { return _useStd3AsciiRules; }
- set { _useStd3AsciiRules = value; }
- }
-
- // Gets ASCII (Punycode) version of the string
- public string GetAscii(string unicode)
- {
- return GetAscii(unicode, 0);
- }
-
- public string GetAscii(string unicode, int index)
- {
- if (unicode == null)
- throw new ArgumentNullException(nameof(unicode));
- Contract.EndContractBlock();
- return GetAscii(unicode, index, unicode.Length - index);
- }
-
- public string GetAscii(string unicode, int index, int count)
- {
- if (unicode == null)
- throw new ArgumentNullException(nameof(unicode));
- if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
- if (index > unicode.Length)
- throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
- if (index > unicode.Length - count)
- throw new ArgumentOutOfRangeException(nameof(unicode), SR.ArgumentOutOfRange_IndexCountBuffer);
- Contract.EndContractBlock();
-
- if (count == 0)
- {
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode));
- }
- if (unicode[index + count - 1] == 0)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequence, index + count - 1), nameof(unicode));
- }
-
- unsafe
- {
- fixed (char* pUnicode = unicode)
- {
- return GetAsciiCore(pUnicode + index, count);
- }
- }
- }
-
- // Gets Unicode version of the string. Normalized and limited to IDNA characters.
- public string GetUnicode(string ascii)
- {
- return GetUnicode(ascii, 0);
- }
-
- public string GetUnicode(string ascii, int index)
- {
- if (ascii == null)
- throw new ArgumentNullException(nameof(ascii));
- Contract.EndContractBlock();
- return GetUnicode(ascii, index, ascii.Length - index);
- }
-
- public string GetUnicode(string ascii, int index, int count)
- {
- if (ascii == null)
- throw new ArgumentNullException(nameof(ascii));
- if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
- if (index > ascii.Length)
- throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
- if (index > ascii.Length - count)
- throw new ArgumentOutOfRangeException(nameof(ascii), SR.ArgumentOutOfRange_IndexCountBuffer);
-
- // This is a case (i.e. explicitly null-terminated input) where behavior in .NET and Win32 intentionally differ.
- // The .NET APIs should (and did in v4.0 and earlier) throw an ArgumentException on input that includes a terminating null.
- // The Win32 APIs fail on an embedded null, but not on a terminating null.
- if (count > 0 && ascii[index + count - 1] == (char)0)
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
- Contract.EndContractBlock();
-
- unsafe
- {
- fixed (char* pAscii = ascii)
- {
- return GetUnicodeCore(pAscii + index, count);
- }
- }
- }
-
- public override bool Equals(object obj)
- {
- IdnMapping that = obj as IdnMapping;
- return
- that != null &&
- _allowUnassigned == that._allowUnassigned &&
- _useStd3AsciiRules == that._useStd3AsciiRules;
- }
-
- public override int GetHashCode()
- {
- return (_allowUnassigned ? 100 : 200) + (_useStd3AsciiRules ? 1000 : 2000);
- }
- }
-}
diff --git a/src/Common/src/System/IO/PathInternal.Windows.StringBuffer.cs b/src/Common/src/System/IO/PathInternal.Windows.StringBuffer.cs
index fec2218844..2d7a0c1ec5 100644
--- a/src/Common/src/System/IO/PathInternal.Windows.StringBuffer.cs
+++ b/src/Common/src/System/IO/PathInternal.Windows.StringBuffer.cs
@@ -27,7 +27,7 @@ namespace System.IO
/// <summary>
/// Gets the length of the root of the path (drive, share, etc.).
/// </summary>
- internal unsafe static uint GetRootLength(StringBuffer path)
+ internal static unsafe uint GetRootLength(StringBuffer path)
{
if (path.Length == 0) return 0;
return GetRootLength(path.CharPointer, path.Length);
diff --git a/src/Common/src/System/IO/PathInternal.Windows.cs b/src/Common/src/System/IO/PathInternal.Windows.cs
index e14b0526b0..f98062bb45 100644
--- a/src/Common/src/System/IO/PathInternal.Windows.cs
+++ b/src/Common/src/System/IO/PathInternal.Windows.cs
@@ -207,7 +207,7 @@ namespace System.IO
/// Check for known wildcard characters. '*' and '?' are the most common ones.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal unsafe static bool HasWildCardCharacters(string path)
+ internal static unsafe bool HasWildCardCharacters(string path)
{
// Question mark is part of dos device syntax so we have to skip if we are
int startIndex = PathInternal.IsDevice(path) ? ExtendedPathPrefix.Length : 0;
@@ -218,7 +218,7 @@ namespace System.IO
/// <summary>
/// Gets the length of the root of the path (drive, share, etc.).
/// </summary>
- internal unsafe static int GetRootLength(string path)
+ internal static unsafe int GetRootLength(string path)
{
fixed(char* value = path)
{
@@ -226,7 +226,7 @@ namespace System.IO
}
}
- private unsafe static uint GetRootLength(char* path, uint pathLength)
+ private static unsafe uint GetRootLength(char* path, uint pathLength)
{
uint i = 0;
uint volumeSeparatorLength = 2; // Length to the colon "C:"
@@ -273,7 +273,7 @@ namespace System.IO
return i;
}
- private unsafe static bool StartsWithOrdinal(char* source, uint sourceLength, string value)
+ private static unsafe bool StartsWithOrdinal(char* source, uint sourceLength, string value)
{
if (sourceLength < (uint)value.Length) return false;
for (int i = 0; i < value.Length; i++)
diff --git a/src/Common/src/System/IO/PathInternal.cs b/src/Common/src/System/IO/PathInternal.cs
index ee68750224..59e8aeb7b1 100644
--- a/src/Common/src/System/IO/PathInternal.cs
+++ b/src/Common/src/System/IO/PathInternal.cs
@@ -145,7 +145,7 @@ namespace System.IO
/// <summary>
/// Gets the count of common characters from the left optionally ignoring case
/// </summary>
- unsafe internal static int EqualStartingCharacterCount(string first, string second, bool ignoreCase)
+ internal static unsafe int EqualStartingCharacterCount(string first, string second, bool ignoreCase)
{
if (string.IsNullOrEmpty(first) || string.IsNullOrEmpty(second)) return 0;
diff --git a/src/Common/src/System/IO/StreamHelpers.CopyValidation.cs b/src/Common/src/System/IO/StreamHelpers.CopyValidation.cs
index 40be3c6e10..45bbd816df 100644
--- a/src/Common/src/System/IO/StreamHelpers.CopyValidation.cs
+++ b/src/Common/src/System/IO/StreamHelpers.CopyValidation.cs
@@ -27,7 +27,7 @@ namespace System.IO
}
bool destinationCanWrite = destination.CanWrite;
- if (!destination.CanRead && !destinationCanWrite)
+ if (!destinationCanWrite && !destination.CanRead)
{
throw new ObjectDisposedException(nameof(destination), SR.ObjectDisposed_StreamClosed);
}
diff --git a/src/Common/src/System/LocalAppContext.cs b/src/Common/src/System/LocalAppContext.cs
index 95eaf2447e..95a8666d2b 100644
--- a/src/Common/src/System/LocalAppContext.cs
+++ b/src/Common/src/System/LocalAppContext.cs
@@ -8,14 +8,9 @@ namespace System
{
internal partial class LocalAppContext
{
- static LocalAppContext()
- {
- bool isEnabled;
- if (AppContext.TryGetSwitch(@"TestSwitch.LocalAppContext.DisableCaching", out isEnabled))
- {
- DisableCaching = isEnabled;
- }
- }
+ private static bool s_isDisableCachingInitialized;
+ private static bool s_disableCaching;
+ private static readonly object s_syncObject = new object();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool GetCachedSwitchValue(string switchName, ref int switchValue)
@@ -40,6 +35,29 @@ namespace System
return isSwitchEnabled;
}
- private static bool DisableCaching { get; set; }
+ private static bool DisableCaching
+ {
+ get
+ {
+ if (!s_isDisableCachingInitialized)
+ {
+ lock (s_syncObject)
+ {
+ if (!s_isDisableCachingInitialized)
+ {
+ bool isEnabled;
+ if (AppContext.TryGetSwitch(@"TestSwitch.LocalAppContext.DisableCaching", out isEnabled))
+ {
+ s_disableCaching = isEnabled;
+ }
+
+ s_isDisableCachingInitialized = true;
+ }
+ }
+ }
+
+ return s_disableCaching;
+ }
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/Common/src/System/Net/ContextFlagsAdapterPal.Windows.cs b/src/Common/src/System/Net/ContextFlagsAdapterPal.Windows.cs
index c560b2d15e..c1c037a30a 100644
--- a/src/Common/src/System/Net/ContextFlagsAdapterPal.Windows.cs
+++ b/src/Common/src/System/Net/ContextFlagsAdapterPal.Windows.cs
@@ -51,7 +51,7 @@ namespace System.Net
ContextFlagsPal flags = ContextFlagsPal.None;
foreach (ContextFlagMapping mapping in s_contextFlagMapping)
{
- if ((win32Flags & mapping.Win32Flag) == mapping.Win32Flag)
+ if ((win32Flags & mapping.Win32Flag) == mapping.Win32Flag)
{
flags |= mapping.ContextFlag;
}
@@ -65,7 +65,7 @@ namespace System.Net
Interop.SspiCli.ContextFlags win32Flags = Interop.SspiCli.ContextFlags.Zero;
foreach (ContextFlagMapping mapping in s_contextFlagMapping)
{
- if ((flags & mapping.ContextFlag) == mapping.ContextFlag)
+ if ((flags & mapping.ContextFlag) == mapping.ContextFlag)
{
win32Flags |= mapping.Win32Flag;
}
diff --git a/src/Common/src/System/Net/HttpKnownHeaderNames.TryGetHeaderName.cs b/src/Common/src/System/Net/HttpKnownHeaderNames.TryGetHeaderName.cs
index adfc3dddf4..2b50a69d5e 100644
--- a/src/Common/src/System/Net/HttpKnownHeaderNames.TryGetHeaderName.cs
+++ b/src/Common/src/System/Net/HttpKnownHeaderNames.TryGetHeaderName.cs
@@ -27,7 +27,7 @@ namespace System.Net
/// Gets a known header name string from a matching IntPtr buffer, using a case-sensitive
/// ordinal comparison. Used to avoid allocating new strings for known header names.
/// </summary>
- public unsafe static bool TryGetHeaderName(IntPtr buffer, int length, out string name)
+ public static unsafe bool TryGetHeaderName(IntPtr buffer, int length, out string name)
{
Debug.Assert(length >= 0);
@@ -328,7 +328,7 @@ namespace System.Net
return false;
}
- private unsafe static bool EqualsOrdinal(string left, IntPtr right, int rightLength)
+ private static unsafe bool EqualsOrdinal(string left, IntPtr right, int rightLength)
{
Debug.Assert(left != null);
Debug.Assert(right != IntPtr.Zero);
diff --git a/src/Common/src/System/Net/IPEndPointStatics.cs b/src/Common/src/System/Net/IPEndPointStatics.cs
index 8c95603cf3..e8aa2bae74 100644
--- a/src/Common/src/System/Net/IPEndPointStatics.cs
+++ b/src/Common/src/System/Net/IPEndPointStatics.cs
@@ -7,7 +7,7 @@ namespace System.Net
internal static class IPEndPointStatics
{
internal const int AnyPort = IPEndPoint.MinPort;
- internal readonly static IPEndPoint Any = new IPEndPoint(IPAddress.Any, AnyPort);
- internal readonly static IPEndPoint IPv6Any = new IPEndPoint(IPAddress.IPv6Any, AnyPort);
+ internal static readonly IPEndPoint Any = new IPEndPoint(IPAddress.Any, AnyPort);
+ internal static readonly IPEndPoint IPv6Any = new IPEndPoint(IPAddress.IPv6Any, AnyPort);
}
}
diff --git a/src/Common/src/System/Net/NTAuthentication.cs b/src/Common/src/System/Net/NTAuthentication.Common.cs
index 4120ce0756..7ba6afb4b3 100644
--- a/src/Common/src/System/Net/NTAuthentication.cs
+++ b/src/Common/src/System/Net/NTAuthentication.Common.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.ComponentModel;
using System.Diagnostics;
using System.Net.Security;
using System.Security.Authentication.ExtendedProtection;
@@ -24,23 +25,68 @@ namespace System.Net
private bool _isCompleted;
private string _package;
+ private string _lastProtocolName;
+ private string _protocolName;
+ private string _clientSpecifiedSpn;
private ChannelBinding _channelBinding;
// If set, no more calls should be made.
- internal bool IsCompleted
+ internal bool IsCompleted => _isCompleted;
+ internal bool IsValidContext => !(_securityContext == null || _securityContext.IsInvalid);
+ internal string Package => _package;
+
+ // True indicates this instance is for Server and will use AcceptSecurityContext SSPI API.
+ internal bool IsServer => _isServer;
+
+ internal string ClientSpecifiedSpn
{
get
{
- return _isCompleted;
+ if (_clientSpecifiedSpn == null)
+ {
+ _clientSpecifiedSpn = GetClientSpecifiedSpn();
+ }
+
+ return _clientSpecifiedSpn;
}
}
- internal bool IsValidContext
+ internal string ProtocolName
{
get
{
- return !(_securityContext == null || _securityContext.IsInvalid);
+ // Note: May return string.Empty if the auth is not done yet or failed.
+ if (_protocolName == null)
+ {
+ string negotiationAuthenticationPackage = null;
+
+ if (IsValidContext)
+ {
+ negotiationAuthenticationPackage = NegotiateStreamPal.QueryContextAuthenticationPackage(_securityContext);
+ if (IsCompleted)
+ {
+ _protocolName = negotiationAuthenticationPackage;
+ }
+ }
+
+ return negotiationAuthenticationPackage ?? string.Empty;
+ }
+
+ return _protocolName;
+ }
+ }
+
+ internal bool IsKerberos
+ {
+ get
+ {
+ if (_lastProtocolName == null)
+ {
+ _lastProtocolName = ProtocolName;
+ }
+
+ return (object)_lastProtocolName == (object)NegotiationInfoClass.Kerberos;
}
}
@@ -82,6 +128,28 @@ namespace System.Net
}
}
+ internal SafeDeleteContext GetContext(out SecurityStatusPal status)
+ {
+ status = new SecurityStatusPal(SecurityStatusPalErrorCode.OK);
+ if (!(IsCompleted && IsValidContext))
+ {
+ NetEventSource.Fail(this, "Should be called only when completed with success, currently is not!");
+ }
+
+ if (!IsServer)
+ {
+ NetEventSource.Fail(this, "The method must not be called by the client side!");
+ }
+
+ if (!IsValidContext)
+ {
+ status = new SecurityStatusPal(SecurityStatusPalErrorCode.InvalidHandle);
+ return null;
+ }
+
+ return _securityContext;
+ }
+
internal void CloseContext()
{
if (_securityContext != null && !_securityContext.IsClosed)
@@ -263,5 +331,19 @@ namespace System.Net
return outSecurityBuffer.token;
}
+
+ private string GetClientSpecifiedSpn()
+ {
+ if (!(IsValidContext && IsCompleted))
+ {
+ NetEventSource.Fail(this, "Trying to get the client SPN before handshaking is done!");
+ }
+
+ string spn = NegotiateStreamPal.QueryContextClientSpecifiedSpn(_securityContext);
+
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"The client specified SPN is [{spn}]");
+
+ return spn;
+ }
}
}
diff --git a/src/Common/src/System/Net/NegotiationInfoClass.cs b/src/Common/src/System/Net/NegotiationInfoClass.cs
index 3f2e34d35e..560098ef4c 100644
--- a/src/Common/src/System/Net/NegotiationInfoClass.cs
+++ b/src/Common/src/System/Net/NegotiationInfoClass.cs
@@ -11,5 +11,6 @@ namespace System.Net
internal const string NTLM = "NTLM";
internal const string Kerberos = "Kerberos";
internal const string Negotiate = "Negotiate";
- }
+ internal const string Basic = "Basic";
+ }
}
diff --git a/src/Common/src/System/Net/SafeCloseSocket.Unix.cs b/src/Common/src/System/Net/SafeCloseSocket.Unix.cs
index 2722d03c42..5c1fa75890 100644
--- a/src/Common/src/System/Net/SafeCloseSocket.Unix.cs
+++ b/src/Common/src/System/Net/SafeCloseSocket.Unix.cs
@@ -85,19 +85,19 @@ namespace System.Net.Sockets
}
}
- public unsafe static SafeCloseSocket CreateSocket(IntPtr fileDescriptor)
+ public static unsafe SafeCloseSocket CreateSocket(IntPtr fileDescriptor)
{
return CreateSocket(InnerSafeCloseSocket.CreateSocket(fileDescriptor));
}
- public unsafe static SocketError CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, out SafeCloseSocket socket)
+ public static unsafe SocketError CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, out SafeCloseSocket socket)
{
SocketError errorCode;
socket = CreateSocket(InnerSafeCloseSocket.CreateSocket(addressFamily, socketType, protocolType, out errorCode));
return errorCode;
}
- public unsafe static SocketError Accept(SafeCloseSocket socketHandle, byte[] socketAddress, ref int socketAddressSize, out SafeCloseSocket socket)
+ public static unsafe SocketError Accept(SafeCloseSocket socketHandle, byte[] socketAddress, ref int socketAddressSize, out SafeCloseSocket socket)
{
SocketError errorCode;
socket = CreateSocket(InnerSafeCloseSocket.Accept(socketHandle, socketAddress, ref socketAddressSize, out errorCode));
diff --git a/src/Common/src/System/Net/SafeCloseSocket.Windows.cs b/src/Common/src/System/Net/SafeCloseSocket.Windows.cs
index 85565268d4..f90789fc19 100644
--- a/src/Common/src/System/Net/SafeCloseSocket.Windows.cs
+++ b/src/Common/src/System/Net/SafeCloseSocket.Windows.cs
@@ -69,7 +69,7 @@ namespace System.Net.Sockets
return _iocpBoundHandle;
}
- internal unsafe static SafeCloseSocket CreateWSASocket(byte* pinnedBuffer)
+ internal static unsafe SafeCloseSocket CreateWSASocket(byte* pinnedBuffer)
{
return CreateSocket(InnerSafeCloseSocket.CreateWSASocket(pinnedBuffer));
}
@@ -208,7 +208,7 @@ namespace System.Net.Sockets
return errorCode;
}
- internal unsafe static InnerSafeCloseSocket CreateWSASocket(byte* pinnedBuffer)
+ internal static unsafe InnerSafeCloseSocket CreateWSASocket(byte* pinnedBuffer)
{
// NOTE: -1 is the value for FROM_PROTOCOL_INFO.
InnerSafeCloseSocket result = Interop.Winsock.WSASocketW((AddressFamily)(-1), (SocketType)(-1), (ProtocolType)(-1), pinnedBuffer, 0, Interop.Winsock.SocketConstructorFlags.WSA_FLAG_OVERLAPPED);
diff --git a/src/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs b/src/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs
index 7e48b90d52..74ed1b5d61 100644
--- a/src/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs
+++ b/src/Common/src/System/Net/Security/NegotiateStreamPal.Unix.cs
@@ -26,6 +26,17 @@ namespace System.Net.Security
// defined in winerror.h
private const int NTE_FAIL = unchecked((int)0x80090020);
+ internal static string QueryContextClientSpecifiedSpn(SafeDeleteContext securityContext)
+ {
+ throw new PlatformNotSupportedException(SR.net_nego_server_not_supported);
+ }
+
+ internal static string QueryContextAuthenticationPackage(SafeDeleteContext securityContext)
+ {
+ SafeDeleteNegoContext negoContext = (SafeDeleteNegoContext)securityContext;
+ return negoContext.IsNtlmUsed ? NegotiationInfoClass.NTLM : NegotiationInfoClass.Kerberos;
+ }
+
static byte[] GssWrap(
SafeGssContextHandle context,
bool encrypt,
diff --git a/src/Common/src/System/Net/Security/NegotiateStreamPal.Windows.cs b/src/Common/src/System/Net/Security/NegotiateStreamPal.Windows.cs
index 380fed81b7..e48978f6c2 100644
--- a/src/Common/src/System/Net/Security/NegotiateStreamPal.Windows.cs
+++ b/src/Common/src/System/Net/Security/NegotiateStreamPal.Windows.cs
@@ -28,7 +28,7 @@ namespace System.Net.Security
(isServer ? Interop.SspiCli.CredentialUse.SECPKG_CRED_INBOUND : Interop.SspiCli.CredentialUse.SECPKG_CRED_OUTBOUND));
}
- internal unsafe static SafeFreeCredentials AcquireCredentialsHandle(string package, bool isServer, NetworkCredential credential)
+ internal static unsafe SafeFreeCredentials AcquireCredentialsHandle(string package, bool isServer, NetworkCredential credential)
{
SafeSspiAuthDataHandle authData = null;
try
@@ -55,6 +55,17 @@ namespace System.Net.Security
}
}
+ internal static string QueryContextClientSpecifiedSpn(SafeDeleteContext securityContext)
+ {
+ return SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CLIENT_SPECIFIED_TARGET) as string;
+ }
+
+ internal static string QueryContextAuthenticationPackage(SafeDeleteContext securityContext)
+ {
+ var negotiationInfoClass = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NEGOTIATION_INFO) as NegotiationInfoClass;
+ return negotiationInfoClass?.AuthenticationPackage;
+ }
+
internal static SecurityStatusPal InitializeSecurityContext(
SafeFreeCredentials credentialsHandle,
ref SafeDeleteContext securityContext,
diff --git a/src/System.Net.Mail/src/System/Net/Security/NetEventSource.Security.Windows.cs b/src/Common/src/System/Net/Security/NetEventSource.Security.Windows.cs
index a7dcea6f61..a7dcea6f61 100644
--- a/src/System.Net.Mail/src/System/Net/Security/NetEventSource.Security.Windows.cs
+++ b/src/Common/src/System/Net/Security/NetEventSource.Security.Windows.cs
diff --git a/src/System.Net.Mail/src/System/Net/Security/NetEventSource.Security.cs b/src/Common/src/System/Net/Security/NetEventSource.Security.cs
index f7dc49a27d..f7dc49a27d 100644
--- a/src/System.Net.Mail/src/System/Net/Security/NetEventSource.Security.cs
+++ b/src/Common/src/System/Net/Security/NetEventSource.Security.cs
diff --git a/src/Common/src/System/Net/Security/SecurityBufferType.cs b/src/Common/src/System/Net/Security/SecurityBufferType.cs
index a587cabbd7..51174938a1 100644
--- a/src/Common/src/System/Net/Security/SecurityBufferType.cs
+++ b/src/Common/src/System/Net/Security/SecurityBufferType.cs
@@ -21,7 +21,7 @@ namespace System.Net.Security
SECBUFFER_TARGET_HOST = 16,
SECBUFFER_ALERT = 17,
SECBUFFER_APPLICATION_PROTOCOLS = 18,
-
+
SECBUFFER_READONLY = unchecked((int)0x80000000),
SECBUFFER_READONLY_WITH_CHECKSUM = 0x10000000
}
diff --git a/src/Common/src/System/Net/SecurityStatusAdapterPal.Windows.cs b/src/Common/src/System/Net/SecurityStatusAdapterPal.Windows.cs
index a02338bd59..a107c04deb 100644
--- a/src/Common/src/System/Net/SecurityStatusAdapterPal.Windows.cs
+++ b/src/Common/src/System/Net/SecurityStatusAdapterPal.Windows.cs
@@ -1,6 +1,7 @@
// 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.Generic;
using System.ComponentModel;
using System.Diagnostics;
@@ -63,7 +64,7 @@ namespace System.Net
internal static SecurityStatusPal GetSecurityStatusPalFromNativeInt(int win32SecurityStatus)
{
- return GetSecurityStatusPalFromInterop((Interop.SECURITY_STATUS) win32SecurityStatus);
+ return GetSecurityStatusPalFromInterop((Interop.SECURITY_STATUS)win32SecurityStatus);
}
internal static SecurityStatusPal GetSecurityStatusPalFromInterop(Interop.SECURITY_STATUS win32SecurityStatus, bool attachException = false)
diff --git a/src/Common/src/System/Net/SocketAddress.cs b/src/Common/src/System/Net/SocketAddress.cs
index c628b73123..e3097699a2 100644
--- a/src/Common/src/System/Net/SocketAddress.cs
+++ b/src/Common/src/System/Net/SocketAddress.cs
@@ -22,8 +22,8 @@ namespace System.Net.Internals
#endif
class SocketAddress
{
- internal readonly static int IPv6AddressSize = SocketAddressPal.IPv6AddressSize;
- internal readonly static int IPv4AddressSize = SocketAddressPal.IPv4AddressSize;
+ internal static readonly int IPv6AddressSize = SocketAddressPal.IPv6AddressSize;
+ internal static readonly int IPv4AddressSize = SocketAddressPal.IPv4AddressSize;
internal int InternalSize;
internal byte[] Buffer;
diff --git a/src/Common/src/System/Net/SocketAddressPal.Unix.cs b/src/Common/src/System/Net/SocketAddressPal.Unix.cs
index 75b1e0bceb..718672d38d 100644
--- a/src/Common/src/System/Net/SocketAddressPal.Unix.cs
+++ b/src/Common/src/System/Net/SocketAddressPal.Unix.cs
@@ -13,8 +13,8 @@ namespace System.Net
{
public const int DataOffset = 0;
- public readonly static int IPv6AddressSize = GetIPv6AddressSize();
- public readonly static int IPv4AddressSize = GetIPv4AddressSize();
+ public static readonly int IPv6AddressSize = GetIPv6AddressSize();
+ public static readonly int IPv4AddressSize = GetIPv4AddressSize();
private static unsafe int GetIPv6AddressSize()
{
diff --git a/src/Common/src/System/Net/WebHeaderEncoding.cs b/src/Common/src/System/Net/WebHeaderEncoding.cs
index 433931d0b6..b00a7ca09b 100644
--- a/src/Common/src/System/Net/WebHeaderEncoding.cs
+++ b/src/Common/src/System/Net/WebHeaderEncoding.cs
@@ -59,7 +59,7 @@ namespace System.Net
{
return myString.Length;
}
- internal unsafe static void GetBytes(string myString, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ internal static unsafe void GetBytes(string myString, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
if (myString.Length == 0)
{
@@ -75,7 +75,7 @@ namespace System.Net
}
}
}
- internal unsafe static byte[] GetBytes(string myString)
+ internal static unsafe byte[] GetBytes(string myString)
{
byte[] bytes = new byte[myString.Length];
if (myString.Length != 0)
diff --git a/src/Common/src/System/Numerics/Hashing/HashHelpers.cs b/src/Common/src/System/Numerics/Hashing/HashHelpers.cs
index 72d3c39728..166c49fe02 100644
--- a/src/Common/src/System/Numerics/Hashing/HashHelpers.cs
+++ b/src/Common/src/System/Numerics/Hashing/HashHelpers.cs
@@ -6,12 +6,14 @@ namespace System.Numerics.Hashing
{
internal static class HashHelpers
{
+ public static readonly int RandomSeed = Guid.NewGuid().GetHashCode();
+
public static int Combine(int h1, int h2)
{
- // The jit optimizes this to use the ROL instruction on x86
+ // RyuJIT optimizes this to use the ROL instruction
// Related GitHub pull request: dotnet/coreclr#1830
- uint shift5 = ((uint)h1 << 5) | ((uint)h1 >> 27);
- return ((int)shift5 + h1) ^ h2;
+ uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27);
+ return ((int)rol5 + h1) ^ h2;
}
}
}
diff --git a/src/Common/src/System/Runtime/InteropServices/Marshal.Unix.cs b/src/Common/src/System/Runtime/InteropServices/Marshal.Unix.cs
index 4f6c19b54e..0ed38ff1de 100644
--- a/src/Common/src/System/Runtime/InteropServices/Marshal.Unix.cs
+++ b/src/Common/src/System/Runtime/InteropServices/Marshal.Unix.cs
@@ -14,7 +14,7 @@ namespace System.Runtime.InteropServices
return 0;
}
- unsafe public static String PtrToStringAnsi(IntPtr ptr)
+ public static unsafe String PtrToStringAnsi(IntPtr ptr)
{
if (IntPtr.Zero == ptr)
{
diff --git a/src/Common/src/System/Runtime/InteropServices/Marshal.Win32.cs b/src/Common/src/System/Runtime/InteropServices/Marshal.Win32.cs
deleted file mode 100644
index 0e5bc38d14..0000000000
--- a/src/Common/src/System/Runtime/InteropServices/Marshal.Win32.cs
+++ /dev/null
@@ -1,15 +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.
-
-namespace System.Runtime.InteropServices
-{
- // Stand-in type for low-level assemblies to obtain Win32 errors
- internal static class Marshal
- {
- public static int GetLastWin32Error()
- {
- return Interop.Kernel32.GetLastError();
- }
- }
-}
diff --git a/src/Common/src/System/Runtime/InteropServices/NativeBuffer.cs b/src/Common/src/System/Runtime/InteropServices/NativeBuffer.cs
index 875009aee2..4cea7c6ad4 100644
--- a/src/Common/src/System/Runtime/InteropServices/NativeBuffer.cs
+++ b/src/Common/src/System/Runtime/InteropServices/NativeBuffer.cs
@@ -23,8 +23,8 @@ namespace System.Runtime.InteropServices
/// </remarks>
internal class NativeBuffer : IDisposable
{
- private readonly static SafeHeapHandleCache s_handleCache = new SafeHeapHandleCache();
- private readonly static SafeHandle s_emptyHandle = new EmptySafeHandle();
+ private static readonly SafeHeapHandleCache s_handleCache = new SafeHeapHandleCache();
+ private static readonly SafeHandle s_emptyHandle = new EmptySafeHandle();
private SafeHeapHandle _handle;
private ulong _capacity;
diff --git a/src/Common/src/System/SR.cs b/src/Common/src/System/SR.cs
index 06b630db04..46162b8619 100644
--- a/src/Common/src/System/SR.cs
+++ b/src/Common/src/System/SR.cs
@@ -91,4 +91,4 @@ namespace System
return string.Format(resourceFormat, p1, p2, p3);
}
}
-}
+} \ No newline at end of file
diff --git a/src/Common/src/System/Security/IdentityHelper.cs b/src/Common/src/System/Security/IdentityHelper.cs
new file mode 100644
index 0000000000..a801af2e26
--- /dev/null
+++ b/src/Common/src/System/Security/IdentityHelper.cs
@@ -0,0 +1,141 @@
+// 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.IO;
+using System.Reflection;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace System.Security
+{
+ /// <summary>
+ /// Helper class for getting identity hashes for types that used
+ /// to live in Assembly Evidence.
+ /// </summary>
+ internal static class IdentityHelper
+ {
+ private static readonly char[] s_base32Char =
+ {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z', '0', '1', '2', '3', '4', '5'
+ };
+
+ /// <summary>
+ /// Gives a hash equivalent to what Url.Normalize() gives.
+ /// </summary>
+ internal static string GetNormalizedUriHash(Uri uri)
+ {
+ // On desktop System.Security.Url is used as evidence, it has an internal Normalize() method.
+ // Uri.ToString() appears to be functionally equivalent.
+ return GetStrongHashSuitableForObjectName(uri.ToString());
+ }
+
+ /// <summary>
+ /// Uses the AssemblyName's public key to generate a hash equivalent to what
+ /// StrongName.Normalize() gives.
+ /// </summary>
+ internal static string GetNormalizedStrongNameHash(AssemblyName name)
+ {
+ byte[] publicKey = name.GetPublicKey();
+
+ // If we don't have a key, we're not strong named
+ if (publicKey == null || publicKey.Length == 0)
+ return null;
+
+ // Emulate what we get from StrongName.Normalize().
+ using (MemoryStream ms = new MemoryStream())
+ using (BinaryWriter bw = new BinaryWriter(ms))
+ {
+ bw.Write(publicKey);
+ bw.Write(name.Version.Major);
+ bw.Write(name.Name);
+
+ ms.Position = 0;
+ return GetStrongHashSuitableForObjectName(ms);
+ }
+ }
+
+ internal static string GetStrongHashSuitableForObjectName(string name)
+ {
+ using (MemoryStream ms = new MemoryStream())
+ using (BinaryWriter b = new BinaryWriter(ms))
+ {
+ b.Write(name.ToUpperInvariant());
+
+ ms.Position = 0;
+ return GetStrongHashSuitableForObjectName(ms);
+ }
+ }
+
+ [Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "Compat: Used to generate an 8.3 filename.")]
+ internal static string GetStrongHashSuitableForObjectName(Stream stream)
+ {
+ using (SHA1 sha1 = SHA1.Create())
+ {
+ return ToBase32StringSuitableForDirName(sha1.ComputeHash(stream));
+ }
+ }
+
+ // This is from the NetFX Path class. The implementation in CoreFx was optimized for internal Path usage so
+ // we can't share the implementation.
+ internal static string ToBase32StringSuitableForDirName(byte[] buff)
+ {
+ // This routine is optimised to be used with buffs of length 20
+ Debug.Assert(((buff.Length % 5) == 0), "Unexpected hash length");
+
+ StringBuilder sb = new StringBuilder();
+ int l, i;
+
+ l = buff.Length;
+ i = 0;
+
+ // Create l chars using the last 5 bits of each byte.
+ // Consume 3 MSB bits 5 bytes at a time.
+
+ do
+ {
+ byte b0 = (i < l) ? buff[i++] : (byte)0;
+ byte b1 = (i < l) ? buff[i++] : (byte)0;
+ byte b2 = (i < l) ? buff[i++] : (byte)0;
+ byte b3 = (i < l) ? buff[i++] : (byte)0;
+ byte b4 = (i < l) ? buff[i++] : (byte)0;
+
+ // Consume the 5 Least significant bits of each byte
+ sb.Append(s_base32Char[b0 & 0x1F]);
+ sb.Append(s_base32Char[b1 & 0x1F]);
+ sb.Append(s_base32Char[b2 & 0x1F]);
+ sb.Append(s_base32Char[b3 & 0x1F]);
+ sb.Append(s_base32Char[b4 & 0x1F]);
+
+ // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4
+ sb.Append(s_base32Char[(
+ ((b0 & 0xE0) >> 5) |
+ ((b3 & 0x60) >> 2))]);
+
+ sb.Append(s_base32Char[(
+ ((b1 & 0xE0) >> 5) |
+ ((b4 & 0x60) >> 2))]);
+
+ // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4
+
+ b2 >>= 5;
+
+ Debug.Assert(((b2 & 0xF8) == 0), "Unexpected set bits");
+
+ if ((b3 & 0x80) != 0)
+ b2 |= 0x08;
+ if ((b4 & 0x80) != 0)
+ b2 |= 0x10;
+
+ sb.Append(s_base32Char[b2]);
+
+ } while (i < l);
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/src/Common/src/System/StringNormalizationExtensions.Windows.cs b/src/Common/src/System/StringNormalizationExtensions.Windows.cs
deleted file mode 100644
index 8e4bfca14a..0000000000
--- a/src/Common/src/System/StringNormalizationExtensions.Windows.cs
+++ /dev/null
@@ -1,133 +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.Diagnostics;
-using System.Diagnostics.Contracts;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Text;
-
-namespace System
-{
- static partial class StringNormalizationExtensions
- {
- [SecurityCritical]
- public static bool IsNormalized(this string strInput, NormalizationForm normalizationForm)
- {
- if (strInput == null)
- {
- throw new ArgumentNullException(nameof(strInput));
- }
- Contract.EndContractBlock();
-
- // The only way to know if IsNormalizedString failed is through checking the Win32 last error
- Interop.Kernel32.SetLastError(Interop.ERROR_SUCCESS);
- bool result = Interop.Kernel32.IsNormalizedString((int)normalizationForm, strInput, strInput.Length);
-
- int lastError = Marshal.GetLastWin32Error();
- switch (lastError)
- {
- case Interop.ERROR_SUCCESS:
- case Interop.LAST_ERROR_TRASH_VALUE:
- break;
-
- case Interop.ERROR_INVALID_PARAMETER:
- case Interop.ERROR_NO_UNICODE_TRANSLATION:
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
-
- case Interop.ERROR_NOT_ENOUGH_MEMORY:
- throw new OutOfMemoryException(SR.Arg_OutOfMemoryException);
-
- default:
- throw new InvalidOperationException(SR.Format(SR.UnknownError_Num, lastError));
- }
-
- return result;
- }
-
- [SecurityCritical]
- public static string Normalize(this string strInput, NormalizationForm normalizationForm)
- {
- if (strInput == null)
- {
- throw new ArgumentNullException(nameof(strInput));
- }
- Contract.EndContractBlock();
-
- // we depend on Win32 last error when calling NormalizeString
- Interop.Kernel32.SetLastError(Interop.ERROR_SUCCESS);
-
- // Guess our buffer size first
- int iLength = Interop.Kernel32.NormalizeString((int)normalizationForm, strInput, strInput.Length, null, 0);
-
- int lastError = Marshal.GetLastWin32Error();
- // Could have an error (actually it'd be quite hard to have an error here)
- if ((lastError != Interop.ERROR_SUCCESS && lastError != Interop.LAST_ERROR_TRASH_VALUE) ||
- iLength < 0)
- {
- if (lastError == Interop.ERROR_INVALID_PARAMETER)
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
-
- // We shouldn't really be able to get here..., guessing length is
- // a trivial math function...
- // Can't really be Out of Memory, but just in case:
- if (lastError == Interop.ERROR_NOT_ENOUGH_MEMORY)
- throw new OutOfMemoryException(SR.Arg_OutOfMemoryException);
-
- // Who knows what happened? Not us!
- throw new InvalidOperationException(SR.Format(SR.UnknownError_Num, lastError));
- }
-
- // Don't break for empty strings (only possible for D & KD and not really possible at that)
- if (iLength == 0) return string.Empty;
-
- // Someplace to stick our buffer
- char[] cBuffer = null;
-
- for (;;)
- {
- // (re)allocation buffer and normalize string
- cBuffer = new char[iLength];
-
- // Reset last error
- Interop.Kernel32.SetLastError(Interop.ERROR_SUCCESS);
- iLength = Interop.Kernel32.NormalizeString((int)normalizationForm, strInput, strInput.Length, cBuffer, cBuffer.Length);
- lastError = Marshal.GetLastWin32Error();
-
- if (lastError == Interop.ERROR_SUCCESS || lastError == Interop.LAST_ERROR_TRASH_VALUE)
- break;
-
- // Could have an error (actually it'd be quite hard to have an error here)
- switch (lastError)
- {
- // Do appropriate stuff for the individual errors:
- case Interop.ERROR_INSUFFICIENT_BUFFER:
- iLength = Math.Abs(iLength);
- Debug.Assert(iLength > cBuffer.Length, "Buffer overflow should have iLength > cBuffer.Length");
- continue;
-
- case Interop.ERROR_INVALID_PARAMETER:
- case Interop.ERROR_NO_UNICODE_TRANSLATION:
- // Illegal code point or order found. Ie: FFFE or D800 D800, etc.
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
-
- case Interop.ERROR_NOT_ENOUGH_MEMORY:
- throw new OutOfMemoryException(SR.Arg_OutOfMemoryException);
-
- default:
- // We shouldn't get here...
- throw new InvalidOperationException(SR.Format(SR.UnknownError_Num, lastError));
- }
- }
-
- // Copy our buffer into our new string, which will be the appropriate size
- return new string(cBuffer, 0, iLength);
- }
-
- // -----------------------------
- // ---- PAL layer ends here ----
- // -----------------------------
- }
-}
-
diff --git a/src/Common/src/System/StringNormalizationExtensions.cs b/src/Common/src/System/StringNormalizationExtensions.cs
deleted file mode 100644
index 1de632ebaf..0000000000
--- a/src/Common/src/System/StringNormalizationExtensions.cs
+++ /dev/null
@@ -1,27 +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.Text;
-
-namespace System
-{
-#if INTERNAL_GLOBALIZATION_EXTENSIONS
- internal
-#else
- public
-#endif
- static partial class StringNormalizationExtensions
- {
- public static bool IsNormalized(this string strInput)
- {
- return IsNormalized(strInput, NormalizationForm.FormC);
- }
-
- public static string Normalize(this string strInput)
- {
- // Default to Form C
- return Normalize(strInput, NormalizationForm.FormC);
- }
- }
-}
diff --git a/src/Common/src/System/SystemException.cs b/src/Common/src/System/SystemException.cs
deleted file mode 100644
index c06cc94ea1..0000000000
--- a/src/Common/src/System/SystemException.cs
+++ /dev/null
@@ -1,30 +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;
-using System.Runtime.Serialization;
-
-// TODO: remove this stub once System.SystemException is added to UWP
-namespace System {
-
- [Serializable]
- [System.Runtime.InteropServices.ComVisible(true)]
- public class SystemException : Exception
- {
- public SystemException()
- : base("System error.") {
- }
-
- public SystemException(String message)
- : base(message) {
- }
-
- public SystemException(String message, Exception innerException)
- : base(message, innerException) {
- }
-
- protected SystemException(SerializationInfo info, StreamingContext context) : base(info, context) {
- }
- }
-} \ No newline at end of file
diff --git a/src/Common/src/System/Text/DBCSDecoder.cs b/src/Common/src/System/Text/DBCSDecoder.cs
new file mode 100644
index 0000000000..630a301cb6
--- /dev/null
+++ b/src/Common/src/System/Text/DBCSDecoder.cs
@@ -0,0 +1,294 @@
+// 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.Text;
+using System.Diagnostics;
+
+namespace System.Text
+{
+ [Serializable]
+ internal sealed class DecoderDBCS : Decoder
+ {
+ private readonly Encoding _encoding;
+ private readonly byte[] _leadByteRanges = new byte[10]; // Max 5 ranges
+ private int _rangesCount;
+ private byte _leftOverLeadByte;
+
+ internal DecoderDBCS(Encoding encoding)
+ {
+ _encoding = encoding;
+ _rangesCount = Interop.Kernel32.GetLeadByteRanges(_encoding.CodePage, _leadByteRanges);
+ Reset();
+ }
+
+ private bool IsLeadByte(byte b)
+ {
+ if (b < _leadByteRanges[0])
+ return false;
+ int i = 0;
+ while (i < _rangesCount)
+ {
+ if (b >= _leadByteRanges[i] && b <= _leadByteRanges[i + 1])
+ return true;
+ i += 2;
+ }
+ return false;
+ }
+
+ public override void Reset()
+ {
+ _leftOverLeadByte = 0;
+ }
+
+ public override unsafe int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return GetCharCount(bytes, index, count, false);
+ }
+
+ public override unsafe int GetCharCount(byte[] bytes, int index, int count, bool flush)
+ {
+ if (bytes == null)
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
+
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException(index < 0 ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (bytes.Length - index < count)
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (count == 0 && (_leftOverLeadByte == 0 || !flush))
+ return 0;
+
+ fixed (byte* pBytes = bytes)
+ {
+ byte dummyByte;
+ byte* pBuffer = pBytes == null ? &dummyByte : pBytes + index;
+
+ return GetCharCount(pBuffer, count, flush);
+ }
+ }
+
+ private unsafe int ConvertWithLeftOverByte(byte* bytes, int count, char* chars, int charCount)
+ {
+ Debug.Assert(_leftOverLeadByte != 0);
+ byte* pTempBuffer = stackalloc byte[2];
+ pTempBuffer[0] = _leftOverLeadByte;
+
+ int index = 0;
+
+ if (count > 0)
+ {
+ pTempBuffer[1] = bytes[0];
+ index++;
+ }
+
+ int result = OSEncoding.MultiByteToWideChar(_encoding.CodePage, pTempBuffer, index+1, chars, charCount);
+
+ if (count - index > 0)
+ result += OSEncoding.MultiByteToWideChar(
+ _encoding.CodePage, bytes + index,
+ count - index,
+ chars == null ? null : chars + result,
+ chars == null ? 0 : charCount - result);
+
+ return result;
+ }
+
+ public unsafe override int GetCharCount(byte* bytes, int count, bool flush)
+ {
+ if (bytes == null)
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ bool excludeLastByte = count > 0 && !flush && IsLastByteALeadByte(bytes, count);
+
+ if (excludeLastByte)
+ count--;
+
+ if (_leftOverLeadByte == 0)
+ {
+ if (count <= 0)
+ return 0;
+
+ return OSEncoding.MultiByteToWideChar(_encoding.CodePage, bytes, count, null, 0);
+ }
+
+ if (count == 0 && !excludeLastByte && !flush)
+ return 0;
+
+ return ConvertWithLeftOverByte(bytes, count, null, 0);
+ }
+
+ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex)
+ {
+ return GetChars(bytes, byteIndex, byteCount, chars, charIndex, false);
+ }
+
+ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex, bool flush)
+ {
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
+
+ if (byteIndex < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException(byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (bytes.Length - byteIndex < byteCount)
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (charIndex < 0 || charIndex > chars.Length)
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
+
+ if (chars.Length == 0)
+ return 0;
+
+ if (byteCount == 0 && (_leftOverLeadByte == 0 || !flush))
+ return 0;
+
+ fixed (char* pChars = chars)
+ fixed (byte* pBytes = bytes)
+ {
+ byte dummyByte;
+ byte* pBuffer = pBytes == null ? &dummyByte : pBytes + byteIndex;
+
+ return GetChars(pBuffer, byteCount, pChars + charIndex, chars.Length - charIndex, flush);
+ }
+ }
+
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount, bool flush)
+ {
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), SR.ArgumentNull_Array);
+
+ if (byteCount < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException(byteCount < 0 ? nameof(byteCount) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (charCount == 0)
+ return 0;
+
+ byte lastByte = byteCount > 0 && !flush && IsLastByteALeadByte(bytes, byteCount) ? bytes[byteCount - 1] : (byte) 0;
+
+ if (lastByte != 0)
+ byteCount--;
+
+ if (_leftOverLeadByte == 0)
+ {
+ if (byteCount <= 0)
+ {
+ _leftOverLeadByte = lastByte;
+ return 0;
+ }
+
+ int result = OSEncoding.MultiByteToWideChar(_encoding.CodePage, bytes, byteCount, chars, charCount);
+ _leftOverLeadByte = lastByte;
+ return result;
+ }
+
+ // we have left over lead byte
+ if (byteCount == 0 && lastByte == 0 && !flush)
+ return 0;
+
+ int res = ConvertWithLeftOverByte(bytes, byteCount, chars, charCount);
+ _leftOverLeadByte = lastByte;
+ return res;
+ }
+
+ public override unsafe void Convert(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex, int charCount, bool flush,
+ out int bytesUsed, out int charsUsed, out bool completed)
+ {
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
+
+ if (byteIndex < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException(byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (bytes.Length - byteIndex < byteCount)
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (chars.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (charCount == 0 || (bytes.Length == 0 && (_leftOverLeadByte == 0 || !flush)))
+ {
+ bytesUsed = 0;
+ charsUsed = 0;
+ completed = false;
+ return;
+ }
+
+ fixed (char* pChars = chars)
+ fixed (byte* pBytes = bytes)
+ {
+ byte dummyByte;
+ byte* pBuffer = pBytes == null ? &dummyByte : pBytes + byteIndex;
+
+ Convert(pBuffer, byteCount, pChars + charIndex, charCount, flush, out bytesUsed, out charsUsed, out completed);
+ }
+ }
+
+ public unsafe override void Convert(byte* bytes, int byteCount,
+ char* chars, int charCount, bool flush,
+ out int bytesUsed, out int charsUsed, out bool completed)
+ {
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), SR.ArgumentNull_Array);
+ if (byteCount < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException(byteCount < 0 ? nameof(byteCount) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ int count = byteCount;
+ while (count > 0)
+ {
+ int returnedCharCount = GetCharCount(bytes, count, flush);
+ if (returnedCharCount <= charCount)
+ break;
+
+ count /= 2;
+ }
+
+ if (count > 0)
+ {
+ // note GetChars can change the _leftOverLeadByte state
+ charsUsed = GetChars(bytes, count, chars, charCount, flush);
+ bytesUsed = count;
+ completed = _leftOverLeadByte == 0 && byteCount == count;
+ return;
+ }
+
+ bytesUsed = 0;
+ charsUsed = 0;
+ completed = false;
+ }
+
+ // not IsLastByteALeadByte depends on the _leftOverLeadByte state
+ private unsafe bool IsLastByteALeadByte(byte* bytes, int count)
+ {
+ if (!IsLeadByte(bytes[count - 1]))
+ return false; // no need to process the buffer
+
+ int index = 0;
+ if (_leftOverLeadByte != 0)
+ index++; // trail byte
+
+ while (index < count)
+ {
+ if (IsLeadByte(bytes[index]))
+ {
+ index++;
+ if (index >= count)
+ return true;
+ }
+ index++;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/Common/src/System/Text/EncodingHelper.cs b/src/Common/src/System/Text/EncodingHelper.Windows.cs
index a93615c252..e286b35a2b 100644
--- a/src/Common/src/System/Text/EncodingHelper.cs
+++ b/src/Common/src/System/Text/EncodingHelper.Windows.cs
@@ -12,7 +12,7 @@ namespace System.Text
{
// Since only a minimum set of encodings are available by default,
// Console encoding might not be available and require provider registering.
- // To avoid encoding exception in Console APIs we default to UTF8 in such scenarios.
+ // To avoid encoding exception in Console APIs we fallback to OSEncoding.
//
//
// The guaranteed way to identify the above is to use a try/catch pattern, however to avoid 1st chance exceptions
@@ -30,14 +30,14 @@ namespace System.Text
if ((defaultEncCodePage == codepage) || defaultEncCodePage != Encoding.UTF8.CodePage)
{
- try
- {
- return Encoding.GetEncoding(codepage);
- }
- catch (NotSupportedException)
- {
- }
+ return Encoding.GetEncoding(codepage);
}
+
+ if (codepage != Encoding.UTF8.CodePage)
+ {
+ return new OSEncoding(codepage);
+ }
+
return new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
}
}
diff --git a/src/Common/src/System/Text/NormalizationForm.cs b/src/Common/src/System/Text/NormalizationForm.cs
deleted file mode 100644
index d593974252..0000000000
--- a/src/Common/src/System/Text/NormalizationForm.cs
+++ /dev/null
@@ -1,20 +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.
-
-namespace System.Text
-{
- // This is the enumeration for Normalization Forms
-#if INTERNAL_GLOBALIZATION_EXTENSIONS
- internal
-#else
- public
-#endif
- enum NormalizationForm
- {
- FormC = 1,
- FormD = 2,
- FormKC = 5,
- FormKD = 6
- }
-}
diff --git a/src/Common/src/System/Text/OSEncoder.cs b/src/Common/src/System/Text/OSEncoder.cs
new file mode 100644
index 0000000000..70fb658172
--- /dev/null
+++ b/src/Common/src/System/Text/OSEncoder.cs
@@ -0,0 +1,253 @@
+// 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.Text;
+using System.Diagnostics;
+
+namespace System.Text
+{
+ [Serializable]
+ internal sealed class OSEncoder : Encoder
+ {
+ private char _charLeftOver;
+ private readonly Encoding _encoding;
+
+ private const char NULL_CHAR = (char)0;
+
+ internal OSEncoder(Encoding encoding)
+ {
+ _encoding = encoding;
+ Reset();
+ }
+
+ public override void Reset()
+ {
+ _charLeftOver = NULL_CHAR;
+ }
+
+ public override unsafe int GetByteCount(char[] chars, int index, int count, bool flush)
+ {
+ if (chars == null)
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
+
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException(index < 0 ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (chars.Length - index < count)
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (chars.Length == 0 && (_charLeftOver == NULL_CHAR || !flush))
+ return 0;
+
+ fixed (char* pChar = chars)
+ {
+ char dummyChar;
+ char* pBuffer = pChar == null ? &dummyChar : pChar + index;
+ return GetByteCount(pBuffer, count, flush);
+ }
+ }
+
+ private unsafe int ConvertWithLeftOverChar(char* chars, int count, byte* bytes, int byteCount)
+ {
+ Debug.Assert(_charLeftOver != NULL_CHAR);
+ char* pTempBuffer = stackalloc char[2];
+ pTempBuffer[0] = _charLeftOver;
+
+ int index = 0;
+
+ if (count > 0 && Char.IsLowSurrogate(chars[0]))
+ {
+ pTempBuffer[1] = chars[0];
+ index++;
+ }
+
+ int result = OSEncoding.WideCharToMultiByte(_encoding.CodePage, pTempBuffer, index+1, bytes, byteCount);
+
+ if (count - index > 0)
+ result += OSEncoding.WideCharToMultiByte(
+ _encoding.CodePage, chars + index,
+ count - index,
+ bytes == null ? null : bytes + result,
+ bytes == null ? 0 : byteCount - result);
+
+ return result;
+ }
+
+ public unsafe override int GetByteCount(char* chars, int count, bool flush)
+ {
+ if (chars == null)
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ bool excludeLastChar = count > 0 && !flush && Char.IsHighSurrogate(chars[count - 1]);
+
+ if (excludeLastChar)
+ count--;
+
+ if (_charLeftOver == NULL_CHAR)
+ {
+ if (count <= 0)
+ return 0;
+
+ return OSEncoding.WideCharToMultiByte(_encoding.CodePage, chars, count, null, 0);
+ }
+
+ // we have left over character
+ if (count == 0 && !excludeLastChar && !flush)
+ return 0;
+
+ return ConvertWithLeftOverChar(chars, count, null, 0);
+ }
+
+ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex, bool flush)
+ {
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), SR.ArgumentNull_Array);
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (chars.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (byteIndex < 0 || byteIndex > bytes.Length)
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
+
+ if (bytes.Length == 0)
+ return 0;
+
+ if (charCount == 0 && (_charLeftOver == NULL_CHAR || !flush))
+ return 0;
+
+ fixed (char* pChars = chars)
+ fixed (byte* pBytes = bytes)
+ {
+ char dummyChar;
+ char* pBuffer = pChars == null ? &dummyChar : pChars + charIndex;
+
+ return GetBytes(pBuffer, charCount, pBytes + byteIndex, bytes.Length - byteIndex, flush);
+ }
+ }
+
+ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, bool flush)
+ {
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), SR.ArgumentNull_Array);
+
+ if (byteCount < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException(byteCount < 0 ? nameof(byteCount) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (byteCount == 0)
+ return 0;
+
+ char lastChar = charCount > 0 && !flush && Char.IsHighSurrogate(chars[charCount - 1]) ? chars[charCount - 1] : NULL_CHAR;
+
+ if (lastChar != NULL_CHAR)
+ charCount--;
+
+ if (_charLeftOver == NULL_CHAR)
+ {
+ if (charCount <= 0)
+ {
+ _charLeftOver = lastChar;
+ return 0;
+ }
+
+ int result = OSEncoding.WideCharToMultiByte(_encoding.CodePage, chars, charCount, bytes, byteCount);
+ _charLeftOver = lastChar;
+ return result;
+ }
+
+ // we have left over character
+ if (charCount == 0 && lastChar == NULL_CHAR && !flush)
+ return 0;
+
+ int res = ConvertWithLeftOverChar(chars, charCount, bytes, byteCount);
+ _charLeftOver = lastChar;
+ return res;
+ }
+
+ public override unsafe void Convert(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex, int byteCount, bool flush,
+ out int charsUsed, out int bytesUsed, out bool completed)
+ {
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), SR.ArgumentNull_Array);
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (byteIndex < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException(byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (chars.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (bytes.Length - byteIndex < byteCount)
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (bytes.Length == 0 || (chars.Length == 0 && (_charLeftOver == NULL_CHAR || !flush)))
+ {
+ bytesUsed = 0;
+ charsUsed = 0;
+ completed = false;
+ return;
+ }
+
+ fixed (char* pChars = chars)
+ fixed (byte* pBytes = bytes)
+ {
+ char dummyChar;
+ char* pBuffer = pChars == null ? &dummyChar : pChars + charIndex;
+
+ Convert(pBuffer, charCount, pBytes + byteIndex, byteCount, flush, out charsUsed, out bytesUsed, out completed);
+ }
+ }
+
+ public override unsafe void Convert(char* chars, int charCount,
+ byte* bytes, int byteCount, bool flush,
+ out int charsUsed, out int bytesUsed, out bool completed)
+ {
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
+ if (charCount < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException(charCount < 0 ? nameof(charCount) : nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ int count = charCount;
+ while (count > 0)
+ {
+ int returnedByteCount = GetByteCount(chars, count, flush);
+ if (returnedByteCount <= byteCount)
+ break;
+
+ count /= 2;
+ }
+
+ if (count > 0)
+ {
+ // note GetBytes can change the _charLeftOver state
+ bytesUsed = GetBytes(chars, count, bytes, byteCount, flush);
+ charsUsed = count;
+ completed = _charLeftOver == NULL_CHAR && charCount == count;
+ return;
+ }
+
+ bytesUsed = 0;
+ charsUsed = 0;
+ completed = false;
+ }
+
+ public Encoding Encoding
+ {
+ get
+ {
+ return _encoding;
+ }
+ }
+ }
+}
diff --git a/src/Common/src/System/Text/OSEncoding.Windows.cs b/src/Common/src/System/Text/OSEncoding.Windows.cs
new file mode 100644
index 0000000000..5aa021abdb
--- /dev/null
+++ b/src/Common/src/System/Text/OSEncoding.Windows.cs
@@ -0,0 +1,259 @@
+// 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.Text;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+namespace System.Text
+{
+ [Serializable]
+ internal sealed class OSEncoding : Encoding
+ {
+ private readonly int _codePage;
+ private string _encodingName;
+
+ internal OSEncoding(int codePage) : base(codePage)
+ {
+ _codePage = codePage;
+ }
+
+ public override unsafe int GetByteCount(char[] chars, int index, int count)
+ {
+ if (chars == null)
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
+
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException(index < 0 ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (chars.Length - index < count)
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (count == 0)
+ return 0;
+
+ fixed (char* pChar = chars)
+ {
+ return WideCharToMultiByte(_codePage, pChar+index, count, null, 0);
+ }
+ }
+
+ public override unsafe int GetByteCount(String s)
+ {
+ // Validate input
+ if (s == null)
+ throw new ArgumentNullException(nameof(s));
+
+ if (s.Length == 0)
+ return 0;
+
+ fixed (char* pChars = s)
+ {
+ return WideCharToMultiByte(_codePage, pChars, s.Length, null, 0);
+ }
+ }
+
+ public override unsafe int GetBytes(String s, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ {
+ if (s == null || bytes == null)
+ throw new ArgumentNullException(s == null ? nameof(s) : nameof(bytes), SR.ArgumentNull_Array);
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (s.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
+
+ if (byteIndex < 0 || byteIndex > bytes.Length)
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
+
+ if (charCount == 0)
+ return 0;
+
+ if (bytes.Length == 0)
+ {
+ throw new ArgumentOutOfRangeException(SR.Argument_EncodingConversionOverflowBytes);
+ }
+
+ fixed (char* pChars = s)
+ fixed (byte *pBytes = bytes)
+ {
+ return WideCharToMultiByte(_codePage, pChars+charIndex, charCount, pBytes+byteIndex, bytes.Length - byteIndex);
+ }
+ }
+
+ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ {
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), SR.ArgumentNull_Array);
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (chars.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (byteIndex < 0 || byteIndex > bytes.Length)
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
+
+ if (charCount == 0)
+ return 0;
+
+ if (bytes.Length == 0)
+ {
+ throw new ArgumentOutOfRangeException(SR.Argument_EncodingConversionOverflowBytes);
+ }
+
+ fixed (char* pChars = chars)
+ fixed (byte *pBytes = bytes)
+ {
+ return WideCharToMultiByte(_codePage, pChars+charIndex, charCount, pBytes+byteIndex, bytes.Length - byteIndex);
+ }
+ }
+
+ public override unsafe int GetCharCount(byte[] bytes, int index, int count)
+ {
+ if (bytes == null)
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
+
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException(index < 0 ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (bytes.Length - index < count)
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (count == 0)
+ return 0;
+
+ fixed (byte* pBytes = bytes)
+ {
+ return MultiByteToWideChar(_codePage, pBytes+index, count, null, 0);
+ }
+ }
+
+ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
+ {
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
+
+ if (byteIndex < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException(byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (bytes.Length - byteIndex < byteCount)
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
+
+ if (charIndex < 0 || charIndex > chars.Length)
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
+
+ if (byteCount == 0)
+ return 0;
+
+ if (chars.Length == 0)
+ throw new ArgumentOutOfRangeException(SR.Argument_EncodingConversionOverflowChars);
+
+ fixed (byte* pBytes = bytes)
+ fixed (char* pChars = chars)
+ {
+ return MultiByteToWideChar(_codePage, pBytes+byteIndex, byteCount, pChars+charIndex, chars.Length - charIndex);
+ }
+ }
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException(nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ long byteCount = (long)charCount * 14; // Max possible value for all encodings
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException(nameof(charCount), SR.ArgumentOutOfRange_GetByteCountOverflow);
+
+ return (int)byteCount;
+ }
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException(nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ long charCount = byteCount * 4; // Max possible value for all encodings
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException(nameof(byteCount), SR.ArgumentOutOfRange_GetCharCountOverflow);
+
+ return (int)charCount;
+ }
+
+ public override String EncodingName
+ {
+ get
+ {
+ if (_encodingName == null)
+ {
+ _encodingName = "Codepage - " + _codePage.ToString();
+ }
+ return _encodingName;
+ }
+ }
+
+ public override String WebName
+ {
+ get
+ {
+ return EncodingName;
+ }
+ }
+
+ public override Encoder GetEncoder()
+ {
+ return new OSEncoder(this);
+ }
+
+ public override Decoder GetDecoder()
+ {
+ switch (CodePage)
+ {
+ case 932: // Japanese (Shift-JIS)
+ case 936: // Chinese Simplified (GB2312)
+ case 949: // Korean
+ case 950: // Chinese Traditional (Big5)
+ case 1361: // Korean (Johab)
+ case 10001: // Japanese (Mac)
+ case 10002: // Chinese Traditional (Mac)
+ case 10003: // Korean (Mac)
+ case 10008: // Chinese Simplified (Mac)
+ case 20000: // Chinese Traditional (CNS)
+ case 20001: // TCA Taiwan
+ case 20002: // Chinese Traditional (Eten)
+ case 20003: // IBM5550 Taiwan
+ case 20004: // TeleText Taiwan
+ case 20005: // Wang Taiwan
+ case 20261: // T.61
+ case 20932: // Japanese (JIS 0208-1990 and 0212-1990)
+ case 20936: // Chinese Simplified (GB2312-80)
+ case 51949: // Korean (EUC)
+ return new DecoderDBCS(this);
+
+ default:
+ return base.GetDecoder();
+ }
+ }
+
+ internal static unsafe int WideCharToMultiByte(int codePage, char* pChars, int count, byte* pBytes, int byteCount)
+ {
+ int result = Interop.Kernel32.WideCharToMultiByte((uint)codePage, 0, pChars, count, pBytes, byteCount, IntPtr.Zero, IntPtr.Zero);
+ if (result <= 0)
+ throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex);
+ return result;
+ }
+
+ internal static unsafe int MultiByteToWideChar(int codePage, byte* pBytes, int byteCount, char* pChars, int count)
+ {
+ int result = Interop.Kernel32.MultiByteToWideChar((uint)codePage, 0, pBytes, byteCount, pChars, count);
+ if (result <= 0)
+ throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex);
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Common/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs b/src/Common/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
index 4eae6d65a4..ee54cd4c6a 100644
--- a/src/Common/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
+++ b/src/Common/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
@@ -9,7 +9,7 @@ namespace System.Threading.Tasks
/// <summary>Enables awaiting a Begin/End method pair.</summary>
internal sealed class BeginEndAwaitableAdapter : RendezvousAwaitable<IAsyncResult>
{
- public readonly static AsyncCallback Callback = asyncResult =>
+ public static readonly AsyncCallback Callback = asyncResult =>
{
Debug.Assert(asyncResult != null);
Debug.Assert(asyncResult.IsCompleted);
diff --git a/src/Common/src/System/Xml/XmlCharType.cs b/src/Common/src/System/Xml/XmlCharType.cs
index 11ce7b498e..95a5f3b8c4 100644
--- a/src/Common/src/System/Xml/XmlCharType.cs
+++ b/src/Common/src/System/Xml/XmlCharType.cs
@@ -26,7 +26,7 @@ namespace System.Xml
/// </devdoc>
#if XMLCHARTYPE_USE_RESOURCE
- unsafe internal struct XmlCharType {
+ internal unsafe struct XmlCharType {
#else
internal struct XmlCharType
{
@@ -681,7 +681,7 @@ namespace System.Xml
return -1;
}
- static internal bool IsOnlyDigits(string str, int startPos, int len)
+ internal static bool IsOnlyDigits(string str, int startPos, int len)
{
Debug.Assert(str != null);
Debug.Assert(startPos + len <= str.Length);
diff --git a/src/Common/tests/Common.Tests.csproj b/src/Common/tests/Common.Tests.csproj
index 25c44c6e9e..7dc8f7c032 100644
--- a/src/Common/tests/Common.Tests.csproj
+++ b/src/Common/tests/Common.Tests.csproj
@@ -19,51 +19,55 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
- <Compile Include="..\src\Interop\Linux\procfs\Interop.ProcFsStat.cs">
+ <Compile Include="$(CommonPath)\Interop\Linux\procfs\Interop.ProcFsStat.cs">
<Link>Common\Interop\Linux\procfs\Interop.ProcFsStat.cs</Link>
</Compile>
- <Compile Include="..\src\System\CharArrayHelpers.cs">
+ <Compile Include="$(CommonPath)\System\CharArrayHelpers.cs">
<Link>Common\System\CharArrayHelpers.cs</Link>
</Compile>
- <Compile Include="..\src\System\StringExtensions.cs">
+ <Compile Include="$(CommonPath)\System\StringExtensions.cs">
<Link>Common\System\StringExtensions.cs</Link>
</Compile>
- <Compile Include="..\src\System\Collections\Generic\ArrayBuilder.cs">
+ <Compile Include="$(CommonPath)\System\Collections\Generic\ArrayBuilder.cs">
<Link>Common\System\Collections\Generic\ArrayBuilder.cs</Link>
</Compile>
- <Compile Include="..\src\System\Collections\Generic\LargeArrayBuilder.cs">
+ <Compile Include="$(CommonPath)\System\Collections\Generic\LargeArrayBuilder.cs">
<Link>Common\System\Collections\Generic\LargeArrayBuilder.cs</Link>
</Compile>
- <Compile Include="..\src\System\IO\PathInternal.cs">
+ <Compile Include="$(CommonPath)\System\IO\PathInternal.cs">
<Link>Common\System\IO\PathInternal.cs</Link>
</Compile>
- <Compile Include="..\src\System\IO\PathInternal.CaseSensitivity.cs">
+ <Compile Include="$(CommonPath)\System\IO\PathInternal.CaseSensitivity.cs">
<Link>Common\System\IO\PathInternal.CaseSensitivity.cs</Link>
</Compile>
- <Compile Include="..\src\System\IO\RowConfigReader.cs">
+ <Compile Include="$(CommonPath)\System\IO\RowConfigReader.cs">
<Link>Common\System\IO\RowConfigReader.cs</Link>
</Compile>
- <Compile Include="..\src\System\IO\StringBuilderCache.cs">
+ <Compile Include="$(CommonPath)\System\IO\StringBuilderCache.cs">
<Link>Common\System\IO\StringBuilderCache.cs</Link>
</Compile>
- <Compile Include="..\src\System\IO\StringParser.cs">
+ <Compile Include="$(CommonPath)\System\IO\StringParser.cs">
<Link>Common\System\IO\StringParser.cs</Link>
</Compile>
- <Compile Include="..\src\System\Net\HttpKnownHeaderNames.cs">
+ <Compile Include="$(CommonPath)\System\Net\HttpKnownHeaderNames.cs">
<Link>Common\System\Net\HttpKnownHeaderNames.cs</Link>
</Compile>
- <Compile Include="..\src\System\Net\HttpKnownHeaderNames.TryGetHeaderName.cs">
+ <Compile Include="$(CommonPath)\System\Net\HttpKnownHeaderNames.TryGetHeaderName.cs">
<Link>Common\System\Net\HttpKnownHeaderNames.TryGetHeaderName.cs</Link>
</Compile>
- <Compile Include="..\src\System\Text\ReusableTextReader.cs">
+ <Compile Include="$(CommonPath)\System\Text\ReusableTextReader.cs">
<Link>Common\System\Text\ReusableTextReader.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\AssertExtensions.cs">
<Link>CommonTest\System\AssertExtensions.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\System\Security\IdentityHelper.cs">
+ <Link>Common\System\Security\IdentityHelper.cs</Link>
+ </Compile>
<Compile Include="Tests\Interop\procfsTests.cs" />
<Compile Include="Tests\System\CharArrayHelpersTests.cs" />
<Compile Include="Tests\System\IO\StringParserTests.cs" />
+ <Compile Include="Tests\System\Security\IdentityHelperTests.cs" />
<Compile Include="Tests\System\StringExtensions.Tests.cs" />
<Compile Include="Tests\System\Collections\Generic\ArrayBuilderTests.cs" />
<Compile Include="Tests\System\Collections\Generic\LargeArrayBuilderTests.cs" />
@@ -135,6 +139,7 @@
</Compile>
</ItemGroup>
<ItemGroup>
+ <Folder Include="CommonTest\System\" />
<Folder Include="System\Net\Sockets\" />
<Folder Include="System\Net\VirtualNetwork\" />
</ItemGroup>
diff --git a/src/Common/tests/System/Collections/ICollection.Generic.Tests.cs b/src/Common/tests/System/Collections/ICollection.Generic.Tests.cs
index ed2efea8b9..3d2e37508c 100644
--- a/src/Common/tests/System/Collections/ICollection.Generic.Tests.cs
+++ b/src/Common/tests/System/Collections/ICollection.Generic.Tests.cs
@@ -37,6 +37,8 @@ namespace System.Collections.Tests
protected virtual bool DuplicateValuesAllowed => true;
protected virtual bool DefaultValueWhenNotAllowed_Throws => true;
protected virtual bool IsReadOnly => false;
+ protected virtual bool IsReadOnly_ValidityValue => IsReadOnly;
+ protected virtual bool AddRemoveClear_ThrowsNotSupported => false;
protected virtual bool DefaultValueAllowed => true;
protected virtual IEnumerable<T> InvalidValues => Array.Empty<T>();
@@ -71,32 +73,41 @@ namespace System.Collections.Tests
{
get
{
- yield return (IEnumerable<T> enumerable) =>
+ if (!AddRemoveClear_ThrowsNotSupported)
{
- var casted = (ICollection<T>)enumerable;
- casted.Add(CreateT(2344));
- return true;
- };
- yield return (IEnumerable<T> enumerable) =>
- {
- var casted = (ICollection<T>)enumerable;
- if (casted.Count() > 0)
+ yield return (IEnumerable<T> enumerable) =>
{
- casted.Remove(casted.ElementAt(0));
+ var casted = (ICollection<T>)enumerable;
+ casted.Add(CreateT(2344));
return true;
- }
- return false;
- };
- yield return (IEnumerable<T> enumerable) =>
+ };
+ }
+ if (!AddRemoveClear_ThrowsNotSupported)
{
- var casted = (ICollection<T>)enumerable;
- if (casted.Count() > 0)
+ yield return (IEnumerable<T> enumerable) =>
{
- casted.Clear();
- return true;
- }
- return false;
- };
+ var casted = (ICollection<T>)enumerable;
+ if (casted.Count() > 0)
+ {
+ casted.Remove(casted.ElementAt(0));
+ return true;
+ }
+ return false;
+ };
+ }
+ if (!AddRemoveClear_ThrowsNotSupported)
+ {
+ yield return (IEnumerable<T> enumerable) =>
+ {
+ var casted = (ICollection<T>)enumerable;
+ if (casted.Count() > 0)
+ {
+ casted.Clear();
+ return true;
+ }
+ return false;
+ };
+ }
}
}
@@ -109,7 +120,7 @@ namespace System.Collections.Tests
public void ICollection_Generic_IsReadOnly_Validity(int count)
{
ICollection<T> collection = GenericICollectionFactory(count);
- Assert.Equal(IsReadOnly, collection.IsReadOnly);
+ Assert.Equal(IsReadOnly_ValidityValue , collection.IsReadOnly);
}
#endregion
@@ -132,7 +143,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_DefaultValue(int count)
{
- if (DefaultValueAllowed && !IsReadOnly)
+ if (DefaultValueAllowed && !IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
ICollection<T> collection = GenericICollectionFactory(count);
collection.Add(default(T));
@@ -144,7 +155,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_InvalidValueToMiddleOfCollection(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
Assert.All(InvalidValues, invalidValue =>
{
@@ -161,7 +172,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_InvalidValueToBeginningOfCollection(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
Assert.All(InvalidValues, invalidValue =>
{
@@ -178,7 +189,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_InvalidValueToEndOfCollection(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
Assert.All(InvalidValues, invalidValue =>
{
@@ -193,7 +204,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_DuplicateValue(int count)
{
- if (!IsReadOnly && DuplicateValuesAllowed)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported && DuplicateValuesAllowed)
{
ICollection<T> collection = GenericICollectionFactory(count);
T duplicateValue = CreateT(700);
@@ -207,7 +218,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_AfterCallingClear(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
ICollection<T> collection = GenericICollectionFactory(count);
collection.Clear();
@@ -220,7 +231,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_AfterRemovingAnyValue(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
int seed = 840;
ICollection<T> collection = GenericICollectionFactory(count);
@@ -245,7 +256,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_AfterRemovingAllItems(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
ICollection<T> collection = GenericICollectionFactory(count);
List<T> itemsToRemove = collection.ToList();
@@ -253,14 +264,14 @@ namespace System.Collections.Tests
collection.Remove(collection.ElementAt(0));
collection.Add(CreateT(254));
Assert.Equal(1, collection.Count);
- }
+ }
}
[Theory]
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_ToReadOnlyCollection(int count)
{
- if (IsReadOnly)
+ if (IsReadOnly || AddRemoveClear_ThrowsNotSupported)
{
ICollection<T> collection = GenericICollectionFactory(count);
Assert.Throws<NotSupportedException>(() => collection.Add(CreateT(0)));
@@ -272,7 +283,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Add_AfterRemoving(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
int seed = 840;
ICollection<T> collection = GenericICollectionFactory(count);
@@ -294,7 +305,7 @@ namespace System.Collections.Tests
public void ICollection_Generic_Clear(int count)
{
ICollection<T> collection = GenericICollectionFactory(count);
- if (IsReadOnly)
+ if (IsReadOnly || AddRemoveClear_ThrowsNotSupported)
{
Assert.Throws<NotSupportedException>(() => collection.Clear());
Assert.Equal(count, collection.Count);
@@ -311,7 +322,7 @@ namespace System.Collections.Tests
public void ICollection_Generic_Clear_Repeatedly(int count)
{
ICollection<T> collection = GenericICollectionFactory(count);
- if (IsReadOnly)
+ if (IsReadOnly || AddRemoveClear_ThrowsNotSupported)
{
Assert.Throws<NotSupportedException>(() => collection.Clear());
Assert.Throws<NotSupportedException>(() => collection.Clear());
@@ -365,9 +376,9 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Contains_DefaultValueOnCollectionContainingDefaultValue(int count)
{
- ICollection<T> collection = GenericICollectionFactory(count);
- if (DefaultValueAllowed && !IsReadOnly)
+ if (DefaultValueAllowed && !IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
+ ICollection<T> collection = GenericICollectionFactory(count);
collection.Add(default(T));
Assert.True(collection.Contains(default(T)));
}
@@ -377,7 +388,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Contains_ValidValueThatExistsTwiceInTheCollection(int count)
{
- if (DuplicateValuesAllowed && !IsReadOnly)
+ if (DuplicateValuesAllowed && !IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
ICollection<T> collection = GenericICollectionFactory(count);
T item = CreateT(12);
@@ -401,9 +412,9 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public virtual void ICollection_Generic_Contains_DefaultValueWhenNotAllowed(int count)
{
- ICollection<T> collection = GenericICollectionFactory(count);
if (!DefaultValueAllowed && !IsReadOnly)
{
+ ICollection<T> collection = GenericICollectionFactory(count);
if (DefaultValueWhenNotAllowed_Throws)
Assert.Throws<ArgumentNullException>("item", () => collection.Contains(default(T)));
else
@@ -494,7 +505,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Remove_OnReadOnlyCollection_ThrowsNotSupportedException(int count)
{
- if (IsReadOnly)
+ if (IsReadOnly || AddRemoveClear_ThrowsNotSupported)
{
ICollection<T> collection = GenericICollectionFactory(count);
Assert.Throws<NotSupportedException>(() => collection.Remove(CreateT(34543)));
@@ -505,7 +516,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Remove_DefaultValueNotContainedInCollection(int count)
{
- if (!IsReadOnly && DefaultValueAllowed && !Enumerable.Contains(InvalidValues, default(T)))
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported && DefaultValueAllowed && !Enumerable.Contains(InvalidValues, default(T)))
{
int seed = count * 21;
ICollection<T> collection = GenericICollectionFactory(count);
@@ -524,7 +535,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Remove_NonDefaultValueNotContainedInCollection(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
int seed = count * 251;
ICollection<T> collection = GenericICollectionFactory(count);
@@ -540,7 +551,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Remove_DefaultValueContainedInCollection(int count)
{
- if (!IsReadOnly && DefaultValueAllowed && !Enumerable.Contains(InvalidValues, default(T)))
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported && DefaultValueAllowed && !Enumerable.Contains(InvalidValues, default(T)))
{
int seed = count * 21;
ICollection<T> collection = GenericICollectionFactory(count);
@@ -559,7 +570,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Remove_NonDefaultValueContainedInCollection(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
int seed = count * 251;
ICollection<T> collection = GenericICollectionFactory(count);
@@ -578,7 +589,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Remove_ValueThatExistsTwiceInCollection(int count)
{
- if (!IsReadOnly && DuplicateValuesAllowed)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported && DuplicateValuesAllowed)
{
int seed = count * 90;
ICollection<T> collection = GenericICollectionFactory(count);
@@ -596,7 +607,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Remove_EveryValue(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
ICollection<T> collection = GenericICollectionFactory(count);
Assert.All(collection.ToList(), value =>
@@ -623,9 +634,9 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void ICollection_Generic_Remove_DefaultValueWhenNotAllowed(int count)
{
- ICollection<T> collection = GenericICollectionFactory(count);
- if (!DefaultValueAllowed && !IsReadOnly)
+ if (!DefaultValueAllowed && !IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
+ ICollection<T> collection = GenericICollectionFactory(count);
if (DefaultValueWhenNotAllowed_Throws)
Assert.Throws<ArgumentNullException>(() => collection.Remove(default(T)));
else
diff --git a/src/Common/tests/System/Collections/IEnumerable.Generic.Tests.cs b/src/Common/tests/System/Collections/IEnumerable.Generic.Tests.cs
index d850ef85e0..c773cc3acc 100644
--- a/src/Common/tests/System/Collections/IEnumerable.Generic.Tests.cs
+++ b/src/Common/tests/System/Collections/IEnumerable.Generic.Tests.cs
@@ -60,16 +60,15 @@ namespace System.Collections.Tests
protected virtual bool Enumerator_Current_UndefinedOperation_Throws => false;
/// <summary>
- /// The behavior of MoveNext at the end of the enumerable after modification is undefined for the generic
- /// IEnumerable. It may either throw an InvalidOperationException or do nothing.
- /// </summary>
- protected bool MoveNextAtEndThrowsOnModifiedCollection => true;
-
- /// <summary>
- /// Used in IEnumerable_Generic_Enumerator_Current.
- /// Some enumerators do not throw accessing Current if enumeration has not yet started (e.g. ConcurrentDictionary)
+ /// When calling MoveNext or Reset after modification of the enumeration, the resulting behavior is
+ /// undefined. Tests are included to cover two behavioral scenarios:
+ /// - Throwing an InvalidOperationException
+ /// - Execute MoveNext or Reset.
+ ///
+ /// If this property is set to true, the tests ensure that the exception is thrown. The default value is
+ /// true.
/// </summary>
- protected virtual bool IEnumerable_Generic_Enumerator_Current_EnumerationNotStarted_ThrowsInvalidOperationException => true;
+ protected virtual bool Enumerator_ModifiedDuringEnumeration_ThrowsInvalidOperationException => true;
/// <summary>
/// Specifies whether this IEnumerable follows some sort of ordering pattern.
@@ -90,12 +89,12 @@ namespace System.Collections.Tests
#region Validation
private void RepeatTest(
- Action<IEnumerator, T[], int> testCode,
+ Action<IEnumerator<T>, T[], int> testCode,
int iters = 3)
{
IEnumerable<T> enumerable = GenericIEnumerableFactory(32);
T[] items = enumerable.ToArray();
- IEnumerator enumerator = enumerable.GetEnumerator();
+ IEnumerator<T> enumerator = enumerable.GetEnumerator();
for (var i = 0; i < iters; i++)
{
testCode(enumerator, items, i);
@@ -111,14 +110,14 @@ namespace System.Collections.Tests
}
private void RepeatTest(
- Action<IEnumerator, T[]> testCode,
+ Action<IEnumerator<T>, T[]> testCode,
int iters = 3)
{
RepeatTest((e, i, it) => testCode(e, i), iters);
}
private void VerifyModifiedEnumerator(
- IEnumerator enumerator,
+ IEnumerator<T> enumerator,
object expectedCurrent,
bool expectCurrentThrow,
bool atEnd)
@@ -138,15 +137,8 @@ namespace System.Collections.Tests
}
}
- if (!atEnd || MoveNextAtEndThrowsOnModifiedCollection)
- {
- Assert.Throws<InvalidOperationException>(
- () => enumerator.MoveNext());
- }
- else
- {
- Assert.False(enumerator.MoveNext());
- }
+ Assert.Throws<InvalidOperationException>(
+ () => enumerator.MoveNext());
if (!!ResetImplemented)
{
@@ -156,7 +148,7 @@ namespace System.Collections.Tests
}
private void VerifyEnumerator(
- IEnumerator enumerator,
+ IEnumerator<T> enumerator,
T[] expectedItems)
{
VerifyEnumerator(
@@ -169,20 +161,19 @@ namespace System.Collections.Tests
}
private void VerifyEnumerator(
- IEnumerator enumerator,
+ IEnumerator<T> enumerator,
T[] expectedItems,
int startIndex,
int count,
bool validateStart,
bool validateEnd)
{
- bool needToMatchAllExpectedItems = count - startIndex
- == expectedItems.Length;
+ bool needToMatchAllExpectedItems = count - startIndex == expectedItems.Length;
if (validateStart)
{
for (var i = 0; i < 3; i++)
{
- if (IEnumerable_Generic_Enumerator_Current_EnumerationNotStarted_ThrowsInvalidOperationException)
+ if (Enumerator_Current_UndefinedOperation_Throws)
{
Assert.Throws<InvalidOperationException>(() => enumerator.Current);
}
@@ -278,21 +269,17 @@ namespace System.Collections.Tests
{
for (var i = 0; i < 3; i++)
{
- Assert.False(
- enumerator.MoveNext(),
- "enumerator.MoveNext() returned true past the expected end.");
- }
+ Assert.False(enumerator.MoveNext(), "enumerator.MoveNext() returned true past the expected end.");
- if (!Enumerator_Current_UndefinedOperation_Throws)
- {
- return;
- }
- // apparently it is okay if enumerator.Current doesn't throw when the collection is generic.
- for (var i = 0; i < 3; i++)
- {
+ if (Enumerator_Current_UndefinedOperation_Throws)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current);
+ }
+ else
+ {
+ var cur = enumerator.Current;
+ }
}
- Assert.Throws<InvalidOperationException>(
- () => enumerator.Current);
}
}
@@ -378,7 +365,16 @@ namespace System.Collections.Tests
using (IEnumerator<T> enumerator = enumerable.GetEnumerator())
{
if (ModifyEnumerable(enumerable))
- Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ {
+ if (Enumerator_ModifiedDuringEnumeration_ThrowsInvalidOperationException)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ }
+ else
+ {
+ enumerator.MoveNext();
+ }
+ }
}
});
}
@@ -395,7 +391,16 @@ namespace System.Collections.Tests
for (int i = 0; i < count / 2; i++)
enumerator.MoveNext();
if (ModifyEnumerable(enumerable))
- Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ {
+ if (Enumerator_ModifiedDuringEnumeration_ThrowsInvalidOperationException)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ }
+ else
+ {
+ enumerator.MoveNext();
+ }
+ }
}
});
}
@@ -411,7 +416,16 @@ namespace System.Collections.Tests
{
while (enumerator.MoveNext()) ;
if (ModifyEnumerable(enumerable))
- Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ {
+ if (Enumerator_ModifiedDuringEnumeration_ThrowsInvalidOperationException)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ }
+ else
+ {
+ enumerator.MoveNext();
+ }
+ }
}
});
}
@@ -450,23 +464,6 @@ namespace System.Collections.Tests
#region Enumerator.Current
[Fact]
- public void IEnumerable_Generic_Enumerator_CurrentThrowsAfterEndOfCollection()
- {
- if (Enumerator_Current_UndefinedOperation_Throws)
- {
- RepeatTest(
- (enumerator, items) =>
- {
- while (enumerator.MoveNext())
- {
- }
- Assert.Throws<InvalidOperationException>(
- () => enumerator.Current);
- });
- }
- }
-
- [Fact]
public void IEnumerable_Generic_Enumerator_Current()
{
// Verify that current returns proper result.
@@ -603,7 +600,16 @@ namespace System.Collections.Tests
using (IEnumerator<T> enumerator = enumerable.GetEnumerator())
{
if (ModifyEnumerable(enumerable))
- Assert.Throws<InvalidOperationException>(() => enumerator.Reset());
+ {
+ if (Enumerator_ModifiedDuringEnumeration_ThrowsInvalidOperationException)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Reset());
+ }
+ else
+ {
+ enumerator.Reset();
+ }
+ }
}
});
}
@@ -620,7 +626,16 @@ namespace System.Collections.Tests
for (int i = 0; i < count / 2; i++)
enumerator.MoveNext();
if (ModifyEnumerable(enumerable))
- Assert.Throws<InvalidOperationException>(() => enumerator.Reset());
+ {
+ if (Enumerator_ModifiedDuringEnumeration_ThrowsInvalidOperationException)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Reset());
+ }
+ else
+ {
+ enumerator.Reset();
+ }
+ }
}
});
}
@@ -636,7 +651,16 @@ namespace System.Collections.Tests
{
while (enumerator.MoveNext()) ;
if (ModifyEnumerable(enumerable))
- Assert.Throws<InvalidOperationException>(() => enumerator.Reset());
+ {
+ if (Enumerator_ModifiedDuringEnumeration_ThrowsInvalidOperationException)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Reset());
+ }
+ else
+ {
+ enumerator.Reset();
+ }
+ }
}
});
}
diff --git a/src/Common/tests/System/Collections/IList.Generic.Tests.cs b/src/Common/tests/System/Collections/IList.Generic.Tests.cs
index f277842440..6d9680c4a0 100644
--- a/src/Common/tests/System/Collections/IList.Generic.Tests.cs
+++ b/src/Common/tests/System/Collections/IList.Generic.Tests.cs
@@ -41,22 +41,23 @@ namespace System.Collections.Tests
{
get
{
- yield return (IEnumerable<T> enumerable) =>
- {
- IList<T> casted = ((IList<T>)enumerable);
- casted.Add(CreateT(2344));
- return true;
- };
- yield return (IEnumerable<T> enumerable) =>
+ foreach (var item in base.ModifyEnumerables)
+ yield return item;
+
+ if (!AddRemoveClear_ThrowsNotSupported)
{
- IList<T> casted = ((IList<T>)enumerable);
- if (casted.Count > 0)
+ yield return (IEnumerable<T> enumerable) =>
{
- casted.Insert(0, CreateT(12));
- return true;
- }
- return false;
- };
+ IList<T> casted = ((IList<T>)enumerable);
+ if (casted.Count > 0)
+ {
+ casted.Insert(0, CreateT(12));
+ return true;
+ }
+ return false;
+ };
+ }
+
yield return (IEnumerable<T> enumerable) =>
{
IList<T> casted = ((IList<T>)enumerable);
@@ -68,35 +69,19 @@ namespace System.Collections.Tests
return false;
};
- yield return (IEnumerable<T> enumerable) =>
- {
- IList<T> casted = ((IList<T>)enumerable);
- if (casted.Count > 0)
- {
- return casted.Remove(casted[0]);
- }
- return false;
- };
- yield return (IEnumerable<T> enumerable) =>
- {
- IList<T> casted = ((IList<T>)enumerable);
- if (casted.Count > 0)
- {
- casted.RemoveAt(0);
- return true;
- }
- return false;
- };
- yield return (IEnumerable<T> enumerable) =>
+ if (!AddRemoveClear_ThrowsNotSupported)
{
- IList<T> casted = ((IList<T>)enumerable);
- if (casted.Count > 0)
+ yield return (IEnumerable<T> enumerable) =>
{
- casted.Clear();
- return true;
- }
- return false;
- };
+ IList<T> casted = ((IList<T>)enumerable);
+ if (casted.Count > 0)
+ {
+ casted.RemoveAt(0);
+ return true;
+ }
+ return false;
+ };
+ }
}
}
@@ -275,7 +260,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_ItemSet_InvalidValue(int count)
{
- if (!IsReadOnly)
+ if (count > 0&& !IsReadOnly)
{
Assert.All(InvalidValues, value =>
{
@@ -387,7 +372,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_IndexOf_ReturnsFirstMatchingValue(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
foreach (T duplicate in list.ToList()) // hard copies list to circumvent enumeration error
@@ -408,7 +393,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_Insert_NegativeIndex_ThrowsArgumentOutOfRangeException(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
T validAdd = CreateT(0);
@@ -422,7 +407,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_Insert_IndexGreaterThanListCount_Appends(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
T validAdd = CreateT(12350);
@@ -436,7 +421,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_Insert_ToReadOnlyList(int count)
{
- if (IsReadOnly)
+ if (IsReadOnly || AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
Assert.Throws<NotSupportedException>(() => list.Insert(count / 2, CreateT(321432)));
@@ -448,7 +433,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_Insert_FirstItemToNonDefaultValue(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
T value = CreateT(123452);
@@ -462,7 +447,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_Insert_FirstItemToDefaultValue(int count)
{
- if (!IsReadOnly && DefaultValueAllowed)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported && DefaultValueAllowed)
{
IList<T> list = GenericIListFactory(count);
T value = default(T);
@@ -476,7 +461,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_Insert_LastItemToNonDefaultValue(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
T value = CreateT(123452);
@@ -491,7 +476,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_Insert_LastItemToDefaultValue(int count)
{
- if (!IsReadOnly && DefaultValueAllowed)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported && DefaultValueAllowed)
{
IList<T> list = GenericIListFactory(count);
T value = default(T);
@@ -506,15 +491,22 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_Insert_DuplicateValues(int count)
{
- if (!IsReadOnly && DuplicateValuesAllowed)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported && DuplicateValuesAllowed)
{
IList<T> list = GenericIListFactory(count);
T value = CreateT(123452);
- list.Insert(0, value);
- list.Insert(1, value);
- Assert.Equal(value, list[0]);
- Assert.Equal(value, list[1]);
- Assert.Equal(count + 2, list.Count);
+ if (AddRemoveClear_ThrowsNotSupported)
+ {
+ Assert.Throws<NotSupportedException>(() => list.Insert(0, value));
+ }
+ else
+ {
+ list.Insert(0, value);
+ list.Insert(1, value);
+ Assert.Equal(value, list[0]);
+ Assert.Equal(value, list[1]);
+ Assert.Equal(count + 2, list.Count);
+ }
}
}
@@ -522,7 +514,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_Insert_InvalidValue(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
Assert.All(InvalidValues, value =>
{
@@ -540,7 +532,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_RemoveAt_NegativeIndex_ThrowsArgumentOutOfRangeException(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
T validAdd = CreateT(0);
@@ -554,7 +546,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_RemoveAt_IndexGreaterThanListCount_ThrowsArgumentOutOfRangeException(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
T validAdd = CreateT(0);
@@ -568,7 +560,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_RemoveAt_OnReadOnlyList(int count)
{
- if (IsReadOnly)
+ if (IsReadOnly || AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
Assert.Throws<NotSupportedException>(() => list.RemoveAt(count / 2));
@@ -580,7 +572,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_RemoveAt_AllValidIndices(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
Assert.Equal(count, list.Count);
@@ -596,7 +588,7 @@ namespace System.Collections.Tests
[MemberData(nameof(ValidCollectionSizes))]
public void IList_Generic_RemoveAt_ZeroMultipleTimes(int count)
{
- if (!IsReadOnly)
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
{
IList<T> list = GenericIListFactory(count);
Assert.All(Enumerable.Range(0, count), index =>
@@ -608,5 +600,53 @@ namespace System.Collections.Tests
}
#endregion
+
+ #region Enumerator.Current
+
+ // Test Enumerator.Current at end after new elements was added
+ [Theory]
+ [MemberData(nameof(ValidCollectionSizes))]
+ public void IList_Generic_CurrentAtEnd_AfterAdd(int count)
+ {
+ if (!IsReadOnly && !AddRemoveClear_ThrowsNotSupported)
+ {
+ IList<T> collection = GenericIListFactory(count);
+
+ using (IEnumerator<T> enumerator = collection.GetEnumerator())
+ {
+ while (enumerator.MoveNext()) ; // Go to end of enumerator
+
+ T current = default(T);
+ if (Enumerator_Current_UndefinedOperation_Throws)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current); // enumerator.Current should fail
+ }
+ else
+ {
+ current = enumerator.Current;
+ Assert.Equal(default(T), current);
+ }
+
+ // Test after add
+ int seed = 3538963;
+ for (int i = 0; i < 3; i++)
+ {
+ collection.Add(CreateT(seed++));
+
+ if (Enumerator_Current_UndefinedOperation_Throws)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current); // enumerator.Current should fail
+ }
+ else
+ {
+ current = enumerator.Current;
+ Assert.Equal(default(T), current);
+ }
+ }
+ }
+ }
+ }
+
+ #endregion
}
}
diff --git a/src/Common/tests/System/Collections/IList.NonGeneric.Tests.cs b/src/Common/tests/System/Collections/IList.NonGeneric.Tests.cs
index b4f76dad22..7b1194c2c2 100644
--- a/src/Common/tests/System/Collections/IList.NonGeneric.Tests.cs
+++ b/src/Common/tests/System/Collections/IList.NonGeneric.Tests.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
+using System.Reflection;
using Xunit;
namespace System.Collections.Tests
@@ -73,6 +74,17 @@ namespace System.Collections.Tests
protected virtual bool IList_NonGeneric_RemoveNonExistent_Throws => false;
+ /// <summary>
+ /// When calling Current of the enumerator after the end of the list and list is extended by new items.
+ /// Tests are included to cover two behavioral scenarios:
+ /// - Throwing an InvalidOperationException
+ /// - Returning an undefined value.
+ ///
+ /// If this property is set to true, the tests ensure that the exception is thrown. The default value is
+ /// the same as Enumerator_Current_UndefinedOperation_Throws.
+ /// </summary>
+ protected virtual bool IList_CurrentAfterAdd_Throws => Enumerator_Current_UndefinedOperation_Throws;
+
#endregion
#region ICollection Helper Methods
@@ -1049,5 +1061,47 @@ namespace System.Collections.Tests
}
#endregion
+
+ #region Enumerator.Current
+
+ // Test Enumerator.Current at end after new elements was added
+ [Theory]
+ [MemberData(nameof(ValidCollectionSizes))]
+ public void IList_NonGeneric_CurrentAtEnd_AfterAdd(int count)
+ {
+ if (!IsReadOnly && !ExpectedFixedSize)
+ {
+ IList collection = NonGenericIListFactory(count);
+ IEnumerator enumerator = collection.GetEnumerator();
+ while (enumerator.MoveNext()) ; // Go to end of enumerator
+
+ if (Enumerator_Current_UndefinedOperation_Throws)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current); // Enumerator.Current should fail
+ }
+ else
+ {
+ var current = enumerator.Current; // Enumerator.Current should not fail
+ }
+
+ // Test after add
+ int seed = 523561;
+ for (int i = 0; i < 3; i++)
+ {
+ collection.Add(CreateT(seed++));
+
+ if (IList_CurrentAfterAdd_Throws)
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current); // Enumerator.Current should fail
+ }
+ else
+ {
+ var current = enumerator.Current; // Enumerator.Current should not fail
+ }
+ }
+ }
+ }
+
+ #endregion
}
}
diff --git a/src/Common/tests/System/Net/Configuration.Http.cs b/src/Common/tests/System/Net/Configuration.Http.cs
index e76d5c6e56..d340ec09dc 100644
--- a/src/Common/tests/System/Net/Configuration.Http.cs
+++ b/src/Common/tests/System/Net/Configuration.Http.cs
@@ -8,7 +8,7 @@ namespace System.Net.Test.Common
{
public static partial class Http
{
- private readonly static string DefaultAzureServer = "corefx-net.cloudapp.net";
+ private static readonly string DefaultAzureServer = "corefx-net.cloudapp.net";
public static string Host => GetValue("COREFX_HTTPHOST", DefaultAzureServer);
@@ -50,21 +50,21 @@ namespace System.Net.Test.Common
private const string DeflateHandler = "Deflate.ashx";
private const string GZipHandler = "GZip.ashx";
- public readonly static Uri RemoteEchoServer = new Uri("http://" + Host + "/" + EchoHandler);
- public readonly static Uri SecureRemoteEchoServer = new Uri("https://" + SecureHost + "/" + EchoHandler);
+ public static readonly Uri RemoteEchoServer = new Uri("http://" + Host + "/" + EchoHandler);
+ public static readonly Uri SecureRemoteEchoServer = new Uri("https://" + SecureHost + "/" + EchoHandler);
- public readonly static Uri RemoteVerifyUploadServer = new Uri("http://" + Host + "/" + VerifyUploadHandler);
- public readonly static Uri SecureRemoteVerifyUploadServer = new Uri("https://" + SecureHost + "/" + VerifyUploadHandler);
+ public static readonly Uri RemoteVerifyUploadServer = new Uri("http://" + Host + "/" + VerifyUploadHandler);
+ public static readonly Uri SecureRemoteVerifyUploadServer = new Uri("https://" + SecureHost + "/" + VerifyUploadHandler);
- public readonly static Uri RemoteEmptyContentServer = new Uri("http://" + Host + "/" + EmptyContentHandler);
- public readonly static Uri RemoteDeflateServer = new Uri("http://" + Host + "/" + DeflateHandler);
- public readonly static Uri RemoteGZipServer = new Uri("http://" + Host + "/" + GZipHandler);
+ public static readonly Uri RemoteEmptyContentServer = new Uri("http://" + Host + "/" + EmptyContentHandler);
+ public static readonly Uri RemoteDeflateServer = new Uri("http://" + Host + "/" + DeflateHandler);
+ public static readonly Uri RemoteGZipServer = new Uri("http://" + Host + "/" + GZipHandler);
- public readonly static object[][] EchoServers = { new object[] { RemoteEchoServer }, new object[] { SecureRemoteEchoServer } };
- public readonly static object[][] VerifyUploadServers = { new object[] { RemoteVerifyUploadServer }, new object[] { SecureRemoteVerifyUploadServer } };
- public readonly static object[][] CompressedServers = { new object[] { RemoteDeflateServer }, new object[] { RemoteGZipServer } };
- public readonly static object[][] Http2Servers = { new object[] { new Uri("https://" + Http2Host) } };
- public readonly static object[][] Http2NoPushServers = { new object[] { new Uri("https://" + Http2NoPushHost) } };
+ public static readonly object[][] EchoServers = { new object[] { RemoteEchoServer }, new object[] { SecureRemoteEchoServer } };
+ public static readonly object[][] VerifyUploadServers = { new object[] { RemoteVerifyUploadServer }, new object[] { SecureRemoteVerifyUploadServer } };
+ public static readonly object[][] CompressedServers = { new object[] { RemoteDeflateServer }, new object[] { RemoteGZipServer } };
+ public static readonly object[][] Http2Servers = { new object[] { new Uri("https://" + Http2Host) } };
+ public static readonly object[][] Http2NoPushServers = { new object[] { new Uri("https://" + Http2NoPushHost) } };
public static Uri NegotiateAuthUriForDefaultCreds(bool secure)
{
diff --git a/src/Common/tests/System/Net/Configuration.Security.cs b/src/Common/tests/System/Net/Configuration.Security.cs
index 006ac43a49..da270ce005 100644
--- a/src/Common/tests/System/Net/Configuration.Security.cs
+++ b/src/Common/tests/System/Net/Configuration.Security.cs
@@ -8,7 +8,7 @@ namespace System.Net.Test.Common
{
public static partial class Security
{
- private readonly static string DefaultAzureServer = "corefx-net.cloudapp.net";
+ private static readonly string DefaultAzureServer = "corefx-net.cloudapp.net";
public static string ActiveDirectoryName => GetValue("COREFX_NET_AD_DOMAINNAME");
diff --git a/src/Common/tests/System/Net/Configuration.WebSockets.cs b/src/Common/tests/System/Net/Configuration.WebSockets.cs
index 1c1db58334..a6752c9417 100644
--- a/src/Common/tests/System/Net/Configuration.WebSockets.cs
+++ b/src/Common/tests/System/Net/Configuration.WebSockets.cs
@@ -15,14 +15,14 @@ namespace System.Net.Test.Common
private const string EchoHandler = "WebSocket/EchoWebSocket.ashx";
private const string EchoHeadersHandler = "WebSocket/EchoWebSocketHeaders.ashx";
- public readonly static Uri RemoteEchoServer = new Uri("ws://" + Host + "/" + EchoHandler);
- public readonly static Uri SecureRemoteEchoServer = new Uri("wss://" + SecureHost + "/" + EchoHandler);
+ public static readonly Uri RemoteEchoServer = new Uri("ws://" + Host + "/" + EchoHandler);
+ public static readonly Uri SecureRemoteEchoServer = new Uri("wss://" + SecureHost + "/" + EchoHandler);
- public readonly static Uri RemoteEchoHeadersServer = new Uri("ws://" + Host + "/" + EchoHeadersHandler);
- public readonly static Uri SecureRemoteEchoHeadersServer = new Uri("wss://" + SecureHost + "/" + EchoHeadersHandler);
+ public static readonly Uri RemoteEchoHeadersServer = new Uri("ws://" + Host + "/" + EchoHeadersHandler);
+ public static readonly Uri SecureRemoteEchoHeadersServer = new Uri("wss://" + SecureHost + "/" + EchoHeadersHandler);
- public readonly static object[][] EchoServers = { new object[] { RemoteEchoServer }, new object[] { SecureRemoteEchoServer } };
- public readonly static object[][] EchoHeadersServers = { new object[] { RemoteEchoHeadersServer }, new object[] { SecureRemoteEchoHeadersServer } };
+ public static readonly object[][] EchoServers = { new object[] { RemoteEchoServer }, new object[] { SecureRemoteEchoServer } };
+ public static readonly object[][] EchoHeadersServers = { new object[] { RemoteEchoHeadersServer }, new object[] { SecureRemoteEchoHeadersServer } };
}
}
}
diff --git a/src/Common/tests/System/Net/Configuration.cs b/src/Common/tests/System/Net/Configuration.cs
index e6b87f2fa9..1aa664d2aa 100644
--- a/src/Common/tests/System/Net/Configuration.cs
+++ b/src/Common/tests/System/Net/Configuration.cs
@@ -7,7 +7,7 @@ namespace System.Net.Test.Common
public static partial class Configuration
{
#pragma warning disable 414
- private readonly static string DefaultAzureServer = "corefx-net.cloudapp.net";
+ private static readonly string DefaultAzureServer = "corefx-net.cloudapp.net";
#pragma warning restore 414
private static string GetValue(string envName, string defaultValue=null)
diff --git a/src/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/AssemblyInfo.cs b/src/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/AssemblyInfo.cs
index 7affb0bd76..cd7593312d 100644
--- a/src/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/AssemblyInfo.cs
+++ b/src/Common/tests/System/Net/Prerequisites/Servers/CoreFxNetCloudService/WebServer/Properties/AssemblyInfo.cs
@@ -18,14 +18,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("6acff710-5f63-4e46-b0da-0d1fe36ef4a7")]
-
// Version information for an assembly consists of the following four values:
//
// Major Version
diff --git a/src/Common/tests/System/Net/VirtualNetwork/VirtualNetworkStream.cs b/src/Common/tests/System/Net/VirtualNetwork/VirtualNetworkStream.cs
index 9886da3fd1..13efa3ae50 100644
--- a/src/Common/tests/System/Net/VirtualNetwork/VirtualNetworkStream.cs
+++ b/src/Common/tests/System/Net/VirtualNetwork/VirtualNetworkStream.cs
@@ -14,6 +14,8 @@ namespace System.Net.Test.Common
private MemoryStream _readStream;
private readonly bool _isServer;
private object _readStreamLock = new object();
+ private TaskCompletionSource<object> _flushTcs;
+ private bool _isFlushed;
public VirtualNetworkStream(VirtualNetwork network, bool isServer)
{
@@ -68,7 +70,31 @@ namespace System.Net.Test.Common
public override void Flush()
{
- // No-op.
+ _isFlushed = true;
+ }
+
+ public override Task FlushAsync(CancellationToken cancellationToken)
+ {
+ if (_flushTcs != null)
+ {
+ throw new InvalidOperationException();
+ }
+ _flushTcs = new TaskCompletionSource<object>();
+
+ return _flushTcs.Task;
+ }
+
+ public bool HasBeenSyncFlushed => _isFlushed;
+
+ public void CompleteAsyncFlush()
+ {
+ if (_flushTcs == null)
+ {
+ throw new InvalidOperationException();
+ }
+
+ _flushTcs.SetResult(null);
+ _flushTcs = null;
}
public override void SetLength(long value)
diff --git a/src/Common/tests/System/PlatformDetection.cs b/src/Common/tests/System/PlatformDetection.cs
index 6b11dc5398..6752ff999a 100644
--- a/src/Common/tests/System/PlatformDetection.cs
+++ b/src/Common/tests/System/PlatformDetection.cs
@@ -23,6 +23,12 @@ namespace System
File.Exists(Path.Combine(Environment.GetEnvironmentVariable("windir"), "regedit.exe")));
public static bool IsWindows10Version1607OrGreater { get; } = IsWindows &&
GetWindowsVersion() == 10 && GetWindowsMinorVersion() == 0 && GetWindowsBuildNumber() >= 14393;
+ // Windows OneCoreUAP SKU doesn't have httpapi.dll
+ public static bool HasHttpApi { get; } = (IsWindows &&
+ File.Exists(Path.Combine(Environment.GetEnvironmentVariable("windir"), "System32", "httpapi.dll")));
+
+ public static bool IsNotOneCoreUAP { get; } = (!IsWindows ||
+ File.Exists(Path.Combine(Environment.GetEnvironmentVariable("windir"), "System32", "httpapi.dll")));
public static int WindowsVersion { get; } = GetWindowsVersion();
diff --git a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs
index 2ca6346667..fc423e8f24 100644
--- a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs
+++ b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs
@@ -324,115 +324,5 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
}
}
}
-
-#if netstandard17
- [Fact]
- public static void PaddingMode_Validation()
- {
- byte[] key = "1ed2f625c187b993256a8b3ccf9dcbfa5b44b4795c731012f70e4e64732efd5d".HexToByteArray();
- byte[] iv = "47d1e060ba3c8643f9f8b65feeda4b30".HexToByteArray();
-
- byte[] plainText = "".HexToByteArray();
- ValidatePaddingMode(plainText, Array.Empty<byte>(), PaddingMode.Zeros, 0); // no block is added in this case!
- ValidatePaddingMode(plainText, "d5450767bcc31793fe5065251b96b715".HexToByteArray(), PaddingMode.PKCS7, 16);
- ValidatePaddingMode(plainText, "a3d32a3a9dca71b6f961f5a8ed7e414f".HexToByteArray(), PaddingMode.ANSIX923, 16);
- ValidatePaddingMode(plainText, Array.Empty<byte>(), PaddingMode.ISO10126, 16);
-
- plainText = "e505a2".HexToByteArray();
- ValidatePaddingMode(plainText, "0a2e62938b03e5822ee251117a4ce066".HexToByteArray(), PaddingMode.Zeros, 13);
- ValidatePaddingMode(plainText, "46785bde46622b92ff7c8ebb91508a4d".HexToByteArray(), PaddingMode.PKCS7, 13);
- ValidatePaddingMode(plainText, "43b27d41a9fde73ca5db22c0fda76cb1".HexToByteArray(), PaddingMode.ANSIX923, 13);
- ValidatePaddingMode(plainText, Array.Empty<byte>(), PaddingMode.ISO10126, 13);
-
- plainText = "46785bde46622b92ff7c8ebb91508a".HexToByteArray();
- ValidatePaddingMode(plainText, "1be8aa365a15d11fc7826b3a10602d09".HexToByteArray(), PaddingMode.Zeros, 1);
- ValidatePaddingMode(plainText, "db5b7829cce732bfe609140cf45a8843".HexToByteArray(), PaddingMode.PKCS7, 1);
- ValidatePaddingMode(plainText, "db5b7829cce732bfe609140cf45a8843".HexToByteArray(), PaddingMode.ANSIX923, 1);
- ValidatePaddingMode(plainText, Array.Empty<byte>(), PaddingMode.ISO10126, 1);
- }
-
- private static void ValidatePaddingMode(byte[] plainText, byte[] expectedCipher, PaddingMode paddingMode, int expectedPaddingSize)
- {
- byte[] key = "1ed2f625c187b993256a8b3ccf9dcbfa5b44b4795c731012f70e4e64732efd5d".HexToByteArray();
- byte[] iv = "47d1e060ba3c8643f9f8b65feeda4b30".HexToByteArray();
-
- using (Aes a = Aes.Create())
- {
- a.Key = key;
- a.IV = iv;
- a.Mode = CipherMode.CBC;
- a.Padding = paddingMode;
-
- byte[] cipher = a.Encrypt(plainText);
-
- // we cannot validate the cipher in this padding mode as it consists of random data
- if (paddingMode != PaddingMode.ISO10126)
- {
- Assert.Equal<byte>(expectedCipher, cipher);
- }
-
- // decrypt it with PaddingMode.None so that we can inspect the padding manually
- a.Padding = PaddingMode.None;
- byte[] decrypted = a.Decrypt(cipher);
- ValidatePadding(decrypted, paddingMode, expectedPaddingSize);
- }
- }
-
- private static void ValidatePadding(byte[] buffer, PaddingMode paddingMode, int expectedPaddingSize)
- {
- switch (paddingMode)
- {
- case PaddingMode.PKCS7:
- ValidatePKCS7Padding(buffer, expectedPaddingSize);
- break;
- case PaddingMode.ANSIX923:
- ValidateANSIX923Padding(buffer, expectedPaddingSize);
- break;
- case PaddingMode.ISO10126:
- ValidateISO10126Padding(buffer, expectedPaddingSize);
- break;
- case PaddingMode.Zeros:
- ValidateZerosPadding(buffer, expectedPaddingSize);
- break;
- case PaddingMode.None:
- break;
- default:
- break;
- }
- }
-
- private static void ValidateZerosPadding(byte[] buffer, int expectedPaddingSize)
- {
- for (int i = buffer.Length - 1; i > buffer.Length - 1 - expectedPaddingSize; i--)
- {
- Assert.Equal(0, buffer[i]);
- }
- }
-
- private static void ValidatePKCS7Padding(byte[] buffer, int expectedPaddingSize)
- {
- for (int i = buffer.Length - 1; i > buffer.Length - 1 - expectedPaddingSize; i--)
- {
- Assert.Equal(expectedPaddingSize, buffer[i]);
- }
- }
-
- private static void ValidateANSIX923Padding(byte[] buffer, int expectedPaddingSize)
- {
- Assert.Equal(buffer[buffer.Length - 1], expectedPaddingSize);
-
- for (int i = buffer.Length - expectedPaddingSize; i < buffer.Length - 1; i++)
- {
- Assert.Equal(0, buffer[i]);
- }
- }
-
- private static void ValidateISO10126Padding(byte[] buffer, int expectedPaddingSize)
- {
- // there is nothing else to validate as all the other padding bytes are random.
- Assert.Equal(buffer[buffer.Length - 1], expectedPaddingSize);
- }
-
-#endif
}
}
diff --git a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs
index a4ac86cc94..a0eadb5321 100644
--- a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs
+++ b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs
@@ -181,7 +181,7 @@ namespace System.Security.Cryptography.Dsa.Tests
}
}
- static internal bool SupportsFips186_3
+ internal static bool SupportsFips186_3
{
get
{
diff --git a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs
index 404d7bd129..dd59de1e91 100644
--- a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs
+++ b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs
@@ -232,7 +232,7 @@ namespace System.Security.Cryptography.EcDsa.Tests
// On CentOS, secp224r1 (also called nistP224) appears to be disabled. To prevent test failures on that platform,
// probe for this capability before depending on it.
- static internal bool ECDsa224Available
+ internal static bool ECDsa224Available
{
get
{
@@ -240,7 +240,7 @@ namespace System.Security.Cryptography.EcDsa.Tests
}
}
- static internal bool ECExplicitCurvesSupported
+ internal static bool ECExplicitCurvesSupported
{
get
{
diff --git a/src/Common/tests/System/Xml/BaseLibManaged/Globalization.cs b/src/Common/tests/System/Xml/BaseLibManaged/Globalization.cs
index 08f2843eee..db36b95f3e 100644
--- a/src/Common/tests/System/Xml/BaseLibManaged/Globalization.cs
+++ b/src/Common/tests/System/Xml/BaseLibManaged/Globalization.cs
@@ -21,11 +21,11 @@ namespace WebData.BaseLib
public int seed;
private string _fileLocation = string.Empty;
- static protected int[] cWhitespaceMap = {
+ protected static int[] cWhitespaceMap = {
0x20, 0x9, 0xD, 0xA
};
- static protected int[] cBaseCharMap = {
+ protected static int[] cBaseCharMap = {
//Base Chars::
0x0041, 0x005A, 0x0061, 0x007A, 0x00C0, 0x00D6, 0x00D8, 0x00F6, 0x00F8, 0x00FF,
0x0100, 0x0131, 0x0134, 0x013E, 0x0141, 0x0148, 0x014A, 0x017E, 0x0180, 0x01C3,
diff --git a/src/Common/tests/System/Xml/ModuleCore/ccommon.cs b/src/Common/tests/System/Xml/ModuleCore/ccommon.cs
index 05499907f3..516dc17a1c 100644
--- a/src/Common/tests/System/Xml/ModuleCore/ccommon.cs
+++ b/src/Common/tests/System/Xml/ModuleCore/ccommon.cs
@@ -15,35 +15,35 @@ namespace OLEDB.Test.ModuleCore
////////////////////////////////////////////////////////////////
internal class Common
{
- static public void Assert(bool condition)
+ public static void Assert(bool condition)
{
Assert(condition, "Assertion Failed!", null);
}
- static public void Assert(bool condition, string strCondition)
+ public static void Assert(bool condition, string strCondition)
{
Assert(condition, strCondition, null);
}
- static public void Assert(bool condition, string strCondition, string message)
+ public static void Assert(bool condition, string strCondition, string message)
{
Debug.Assert(condition, strCondition + message /*+ new StackTrace()*/);
}
- static public void Trace(string message)
+ public static void Trace(string message)
{
Console.WriteLine(message);
Debug.WriteLine(message);
}
- static public string ToString(object value)
+ public static string ToString(object value)
{
if (value == null)
return null;
return value.ToString();
}
- static public string Format(object value)
+ public static string Format(object value)
{
if (value == null)
return "(null)";
diff --git a/src/Common/tests/System/Xml/ModuleCore/cerror.cs b/src/Common/tests/System/Xml/ModuleCore/cerror.cs
index 0bcb73c4fe..6349299975 100644
--- a/src/Common/tests/System/Xml/ModuleCore/cerror.cs
+++ b/src/Common/tests/System/Xml/ModuleCore/cerror.cs
@@ -25,7 +25,7 @@ namespace OLEDB.Test.ModuleCore
{
}
- static public IError Error
+ public static IError Error
{
set
{
@@ -49,17 +49,17 @@ namespace OLEDB.Test.ModuleCore
get { return s_rIError; }
}
- static public TextWriter Out
+ public static TextWriter Out
{
get { return s_rLTMConsole; }
}
- static public ITestConsole TestConsole
+ public static ITestConsole TestConsole
{
get { return s_rITestConsole; }
}
- static internal void Dispose()
+ internal static void Dispose()
{
//Reset the info.
s_rIError = null;
@@ -69,17 +69,17 @@ namespace OLEDB.Test.ModuleCore
s_rLTMConsole = null;
}
- static internal void DisableAsserts()
+ internal static void DisableAsserts()
{
}
//Helpers
- static public void Increment()
+ public static void Increment()
{
Error.Increment();
}
- static public tagERRORLEVEL ErrorLevel
+ public static tagERRORLEVEL ErrorLevel
{
get
{
@@ -94,59 +94,59 @@ namespace OLEDB.Test.ModuleCore
}
}
- static public void Transmit(string text)
+ public static void Transmit(string text)
{
Write(text);
}
- static public string NewLine
+ public static string NewLine
{
get { return "\n"; }
}
- static public void Write(object value)
+ public static void Write(object value)
{
if (value != null)
Write(value.ToString());
}
- static public void WriteLine(object value)
+ public static void WriteLine(object value)
{
Write(value);
WriteLine();
}
- static public void Write(string text)
+ public static void Write(string text)
{
Write(tagCONSOLEFLAGS.CONSOLE_TEXT, text);
}
- static public void WriteLine(string text)
+ public static void WriteLine(string text)
{
Write(tagCONSOLEFLAGS.CONSOLE_TEXT, text);
WriteLine();
}
- static public void Write(string text, params object[] args)
+ public static void Write(string text, params object[] args)
{
//Delegate
Write(String.Format(text, args));
}
- static public void WriteLine(string text, params object[] args)
+ public static void WriteLine(string text, params object[] args)
{
//Delegate
WriteLine(String.Format(text, args));
}
- static public void Write(char[] value)
+ public static void Write(char[] value)
{
//Delegate
if (value != null)
Write(new string(value));
}
- static public void WriteLine(char[] value)
+ public static void WriteLine(char[] value)
{
//Delegate
if (value != null)
@@ -154,27 +154,27 @@ namespace OLEDB.Test.ModuleCore
WriteLine();
}
- static public void WriteXml(string text)
+ public static void WriteXml(string text)
{
Write(tagCONSOLEFLAGS.CONSOLE_XML, text);
}
- static public void WriteRaw(string text)
+ public static void WriteRaw(string text)
{
Write(tagCONSOLEFLAGS.CONSOLE_RAW, text);
}
- static public void WriteIgnore(string text)
+ public static void WriteIgnore(string text)
{
Write(tagCONSOLEFLAGS.CONSOLE_IGNORE, text);
}
- static public void WriteLineIgnore(string text)
+ public static void WriteLineIgnore(string text)
{
Write(tagCONSOLEFLAGS.CONSOLE_IGNORE, text + CError.NewLine);
}
- static public void Write(tagCONSOLEFLAGS flags, string text)
+ public static void Write(tagCONSOLEFLAGS flags, string text)
{
if (flags == tagCONSOLEFLAGS.CONSOLE_TEXT)
{
@@ -193,7 +193,7 @@ namespace OLEDB.Test.ModuleCore
}
}
- static public void WriteLine()
+ public static void WriteLine()
{
if (TestConsole != null)
TestConsole.WriteLine();
@@ -201,14 +201,14 @@ namespace OLEDB.Test.ModuleCore
Error.Transmit(CError.NewLine);
}
- static public bool Compare(bool equal, string message)
+ public static bool Compare(bool equal, string message)
{
if (equal)
return true;
return Compare(false, true, message);
}
- static public bool Compare(object actual, object expected, string message)
+ public static bool Compare(object actual, object expected, string message)
{
if (InternalEquals(actual, expected))
return true;
@@ -223,7 +223,7 @@ namespace OLEDB.Test.ModuleCore
throw new CTestFailedException(message, actual, expected, null);
}
- static public bool Compare(object actual, object expected1, object expected2, string message)
+ public static bool Compare(object actual, object expected1, object expected2, string message)
{
if (InternalEquals(actual, expected1) || InternalEquals(actual, expected2))
return true;
@@ -239,7 +239,7 @@ namespace OLEDB.Test.ModuleCore
//return false;
}
- static public bool Equals(object actual, object expected, string message)
+ public static bool Equals(object actual, object expected, string message)
{
try
{
@@ -255,7 +255,7 @@ namespace OLEDB.Test.ModuleCore
}
}
- static public bool Equals(bool equal, string message)
+ public static bool Equals(bool equal, string message)
{
try
{
@@ -271,17 +271,17 @@ namespace OLEDB.Test.ModuleCore
}
}
- static public bool Warning(bool equal, string message)
+ public static bool Warning(bool equal, string message)
{
return Warning(equal, true, message, null);
}
- static public bool Warning(object actual, object expected, string message)
+ public static bool Warning(object actual, object expected, string message)
{
return Warning(actual, expected, message, null);
}
- static public bool Warning(object actual, object expected, string message, Exception inner)
+ public static bool Warning(object actual, object expected, string message, Exception inner)
{
//See if these are equal
bool equal = InternalEquals(actual, expected);
@@ -301,20 +301,20 @@ namespace OLEDB.Test.ModuleCore
}
}
- static public bool Skip(string message)
+ public static bool Skip(string message)
{
//Delegate
return Skip(true, message);
}
- static public bool Skip(bool skip, string message)
+ public static bool Skip(bool skip, string message)
{
if (skip)
throw new CTestSkippedException(message);
return false;
}
- static internal bool InternalEquals(object actual, object expected)
+ internal static bool InternalEquals(object actual, object expected)
{
//Handle null comparison
if (actual == null && expected == null)
@@ -326,7 +326,7 @@ namespace OLEDB.Test.ModuleCore
return expected.Equals(actual);
}
- static public bool Log(object actual, object expected, string source, string message, string details, tagERRORLEVEL eErrorLevel)
+ public static bool Log(object actual, object expected, string source, string message, string details, tagERRORLEVEL eErrorLevel)
{
//Obtain the error level
tagERRORLEVEL rSavedLevel = ErrorLevel;
diff --git a/src/Common/tests/System/Xml/ModuleCore/cmodinfo.cs b/src/Common/tests/System/Xml/ModuleCore/cmodinfo.cs
index 5e05c3b4cd..bfe153c567 100644
--- a/src/Common/tests/System/Xml/ModuleCore/cmodinfo.cs
+++ b/src/Common/tests/System/Xml/ModuleCore/cmodinfo.cs
@@ -33,9 +33,9 @@ namespace OLEDB.Test.ModuleCore
public class CModInfo
{
//Data
- static private String s_strCommandLine;
- static private MyDict<string, string> s_hashOptions;
- static private object _includenotimplemented;
+ private static String s_strCommandLine;
+ private static MyDict<string, string> s_hashOptions;
+ private static object _includenotimplemented;
//Constructor
public CModInfo()
@@ -43,7 +43,7 @@ namespace OLEDB.Test.ModuleCore
}
//Helpers
- static internal void Dispose()
+ internal static void Dispose()
{
//Reset the info.
//Since this is a static class, (to make it simpler to access from anywhere in your code)
@@ -53,7 +53,7 @@ namespace OLEDB.Test.ModuleCore
s_strCommandLine = null;
s_hashOptions = null;
}
- static public string CommandLine
+ public static string CommandLine
{
// This Assert allows callers without the EnvironementPermission to use this property
get
@@ -67,7 +67,7 @@ namespace OLEDB.Test.ModuleCore
s_strCommandLine = value;
}
}
- static public MyDict<string, string> Options
+ public static MyDict<string, string> Options
{
get
{
@@ -83,19 +83,19 @@ namespace OLEDB.Test.ModuleCore
}
}
- static public string Filter
+ public static string Filter
{
//Typed options
get { return (string)CModInfo.Options["Filter"]; }
}
- static public string MaxPriority
+ public static string MaxPriority
{
//Typed options
get { return (string)CModInfo.Options["MaxPriority"]; }
}
- static public bool IncludeNotImplemented
+ public static bool IncludeNotImplemented
{
//Typed options
get
diff --git a/src/Common/tests/System/Xml/ModuleCore/cparser.cs b/src/Common/tests/System/Xml/ModuleCore/cparser.cs
index d2fbd6b368..2b3f5acda6 100644
--- a/src/Common/tests/System/Xml/ModuleCore/cparser.cs
+++ b/src/Common/tests/System/Xml/ModuleCore/cparser.cs
@@ -42,12 +42,12 @@ namespace OLEDB.Test.ModuleCore
//Methods
- static public MyDict<string, string> ParseKeywords(string str)
+ public static MyDict<string, string> ParseKeywords(string str)
{
return ParseKeywords(str, s_DefaultTokens);
}
- static public MyDict<string, string> ParseKeywords(string str, Tokens tokens)
+ public static MyDict<string, string> ParseKeywords(string str, Tokens tokens)
{
PARSE state = PARSE.Initial;
int index = 0;
diff --git a/src/Common/tests/System/Xml/XmlCoreTest/MiscUtil.cs b/src/Common/tests/System/Xml/XmlCoreTest/MiscUtil.cs
index 65b82a967c..01573d2604 100644
--- a/src/Common/tests/System/Xml/XmlCoreTest/MiscUtil.cs
+++ b/src/Common/tests/System/Xml/XmlCoreTest/MiscUtil.cs
@@ -10,7 +10,7 @@ namespace XmlCoreTest.Common
{
public static class MiscUtil
{
- static public bool IsCurrentCultureHasLimitedDateRange
+ public static bool IsCurrentCultureHasLimitedDateRange
{
get
{
diff --git a/src/Common/tests/Tests/System/Collections/Generic/LargeArrayBuilderTests.cs b/src/Common/tests/Tests/System/Collections/Generic/LargeArrayBuilderTests.cs
index e0cfa7d692..9eabb18253 100644
--- a/src/Common/tests/Tests/System/Collections/Generic/LargeArrayBuilderTests.cs
+++ b/src/Common/tests/Tests/System/Collections/Generic/LargeArrayBuilderTests.cs
@@ -23,10 +23,8 @@ namespace System.Collections.Generic.Tests
[Theory]
[MemberData(nameof(EnumerableData))]
- public void TypicalUsages(IEnumerable<T> seed)
+ public void AddCountAndToArray(IEnumerable<T> seed)
{
- // Verifies Count, Add, SlowAdd, and ToArray.
-
var builder1 = new LargeArrayBuilder<T>(initialize: true);
var builder2 = new LargeArrayBuilder<T>(initialize: true);
@@ -47,6 +45,22 @@ namespace System.Collections.Generic.Tests
}
[Theory]
+ [MemberData(nameof(MaxCapacityData))]
+ public void MaxCapacity(IEnumerable<T> seed, int maxCapacity)
+ {
+ var builder = new LargeArrayBuilder<T>(maxCapacity);
+
+ for (int i = 0; i < maxCapacity; i++)
+ {
+ builder.Add(seed.ElementAt(i));
+
+ int count = i + 1;
+ Assert.Equal(count, builder.Count);
+ Assert.Equal(seed.Take(count), builder.ToArray());
+ }
+ }
+
+ [Theory]
[MemberData(nameof(EnumerableData))]
public void AddRange(IEnumerable<T> seed)
{
@@ -98,11 +112,26 @@ namespace System.Collections.Generic.Tests
return data;
}
+ public static TheoryData<IEnumerable<T>, int> MaxCapacityData()
+ {
+ var data = new TheoryData<IEnumerable<T>, int>();
+
+ IEnumerable<IEnumerable<T>> enumerables = EnumerableData().Select(array => array[0]).Cast<IEnumerable<T>>();
+
+ foreach (IEnumerable<T> enumerable in enumerables)
+ {
+ int count = enumerable.Count();
+ data.Add(enumerable, count);
+ }
+
+ return data;
+ }
+
public static TheoryData<IEnumerable<T>, int, int> CopyToData()
{
var data = new TheoryData<IEnumerable<T>, int, int>();
- var enumerables = EnumerableData().Select(array => array[0]).Cast<IEnumerable<T>>();
+ IEnumerable<IEnumerable<T>> enumerables = EnumerableData().Select(array => array[0]).Cast<IEnumerable<T>>();
foreach (IEnumerable<T> enumerable in enumerables)
{
diff --git a/src/Common/tests/Tests/System/Security/IdentityHelperTests.cs b/src/Common/tests/Tests/System/Security/IdentityHelperTests.cs
new file mode 100644
index 0000000000..03aff2f7ae
--- /dev/null
+++ b/src/Common/tests/Tests/System/Security/IdentityHelperTests.cs
@@ -0,0 +1,71 @@
+// 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.Reflection;
+using System.Security;
+using Xunit;
+
+namespace Tests.System.Security
+{
+ public class IdentityHelperTests
+ {
+ [Theory
+ InlineData(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00 }, @"aaaaaaaa")
+ InlineData(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, @"55555555")
+ InlineData(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @"aaaaaaaaaaaaaaaa")
+ InlineData(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }, @"abcdeaaafghijaaa")
+ InlineData(
+ new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ ]
+ public void ToBase32StringSuitableForDirName(byte[] buff, string expected)
+ {
+ // Validating that the legacy Path.ToBase32StringSuitableForDirName results match
+ // our copy of the code. Results should NOT change as IsolatedStorage depends
+ // on this for creating a stable hash based directory name.
+ Assert.Equal(expected, IdentityHelper.ToBase32StringSuitableForDirName(buff));
+ }
+
+ [Fact]
+ public void GetNormalizedStrongNameHash()
+ {
+ // Validating that we match the exact hash the desktop IsolatedStorage implementation would create.
+ Assert.Equal(@"10nbq10da2m1qfsisndjihnhqmilalwl", IdentityHelper.GetNormalizedStrongNameHash(GetAssemblyNameWithFullKey()));
+ }
+
+ [Fact]
+ public void GetNormalizedUrlHash()
+ {
+ // Validating that we match the exact hash the desktop IsolatedStorage implementation would create.
+ Uri uri = new Uri(@"file://C:/Users/jerem/Documents/Visual Studio 2015/Projects/LongPath/LongPath/bin/Debug/TestAssembly.EXE");
+ Assert.Equal(@"qgeirsoc3cznuklvq5xlalurh1m0unxl", IdentityHelper.GetNormalizedUriHash(uri));
+ }
+
+ private static AssemblyName GetAssemblyNameWithFullKey()
+ {
+ byte[] publicKey = new byte[]
+ {
+ 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
+ 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x37, 0x52, 0x6e, 0xdf, 0xc0, 0x62, 0x17, 0x9f,
+ 0x9d, 0x24, 0xe5, 0x0d, 0x3f, 0x9b, 0xb1, 0x34, 0xe1, 0x7e, 0x14, 0x9e, 0xb5, 0x19, 0xcc, 0x2f, 0xd1, 0x9c, 0x39, 0x08,
+ 0x46, 0xf4, 0x18, 0xba, 0x6b, 0x2b, 0xe1, 0xc2, 0xb7, 0xe9, 0x06, 0x59, 0x57, 0xed, 0xe1, 0x83, 0x9c, 0xc8, 0x66, 0x4f,
+ 0xba, 0x3a, 0x05, 0x6b, 0x73, 0x98, 0x56, 0x0a, 0x34, 0x8e, 0x69, 0xf1, 0x4a, 0x69, 0x4f, 0x4f, 0xea, 0xc7, 0x3e, 0x27,
+ 0xf6, 0x6f, 0xd5, 0x4c, 0xcb, 0xeb, 0xe3, 0xa7, 0x5f, 0x3c, 0x11, 0xd3, 0x82, 0xc7, 0xee, 0x1a, 0x5c, 0xf6, 0x37, 0x8c,
+ 0xc9, 0x81, 0xbb, 0xb8, 0xa4, 0xab, 0xe6, 0x9d, 0x10, 0x96, 0x3a, 0xf8, 0xa0, 0xaa, 0x42, 0xb4, 0x45, 0xb1, 0x6c, 0xe3,
+ 0x9b, 0xc5, 0xb0, 0x84, 0x29, 0x32, 0x20, 0xc8, 0xb9, 0x5b, 0x1d, 0x40, 0xec, 0xbe, 0x23, 0x2e, 0x6b, 0xdd, 0x5d, 0xc4
+ };
+
+ AssemblyName name = new AssemblyName();
+ name.Name = "TestAssembly";
+ name.Version = new Version(1, 0);
+ name.SetPublicKey(publicKey);
+
+ return name;
+
+ // C:\Users\jerem\AppData\Local\IsolatedStorage\10v31ho4.bo2\eeolfu22.f2w\Url.qgeirsoc3cznuklvq5xlalurh1m0unxl\AssemFiles\
+ // C:\Users\jerem\AppData\Local\IsolatedStorage\10v31ho4.bo2\eeolfu22.f2w\StrongName.10nbq10da2m1qfsisndjihnhqmilalwl\AssemFiles\
+ }
+ }
+}
diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Binding/Better.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Binding/Better.cs
index a784cc0d17..7d3dbbfb57 100644
--- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Binding/Better.cs
+++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Binding/Better.cs
@@ -17,7 +17,7 @@ namespace Microsoft.CSharp.RuntimeBinder.Semantics
// Use all the simple types plus 1 more for Object
// See CLR section 7.4.1.3
- static private readonly byte[][] s_betterConversionTable =
+ private static readonly byte[][] s_betterConversionTable =
{
// BYTE SHORT INT LONG FLOAT DOUBLE DECIMAL CHAR BOOL SBYTE USHORT UINT ULONG IPTR UIPTR OBJECT
new byte[] /* BYTE*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/BindingContextBase.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/BindingContextBase.cs
index dea05906c1..d2c5bfa527 100644
--- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/BindingContextBase.cs
+++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/BindingContextBase.cs
@@ -29,7 +29,7 @@ namespace Microsoft.CSharp.RuntimeBinder.Semantics
internal class BindingContext
{
- static public BindingContext CreateInstance(
+ public static BindingContext CreateInstance(
CSemanticChecker pSemanticChecker,
ExprFactory exprFactory,
OutputContext outputContext,
diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs
index 821fb5953c..b2825c6591 100644
--- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs
+++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs
@@ -116,7 +116,7 @@ namespace Microsoft.CSharp.RuntimeBinder.Semantics
private const byte XUD = EXP | UDC;
private const byte IUD = IMP | UDC;
- static private readonly byte[][] s_simpleTypeConversions =
+ private static readonly byte[][] s_simpleTypeConversions =
{
// to: BYTE I2 I4 I8 FLT DBL DEC CHAR BOOL SBYTE U2 U4 U8
/* from */
@@ -196,7 +196,7 @@ namespace Microsoft.CSharp.RuntimeBinder.Semantics
private const byte neither = (byte)BetterType.Neither;
- static private readonly byte[][] s_simpleTypeBetter =
+ private static readonly byte[][] s_simpleTypeBetter =
{
// BYTE SHORT INT LONG FLOAT DOUBLE DECIMAL CHAR BOOL SBYTE USHORT UINT ULONG IPTR UIPTR OBJECT
new byte[] /* BYTE */{same ,left ,left ,left ,left ,left ,left ,neither,neither,right ,left ,left ,left ,neither,neither,left },
@@ -217,7 +217,7 @@ namespace Microsoft.CSharp.RuntimeBinder.Semantics
new byte[] /* OBJECT */{right ,right ,right ,right ,right ,right ,right ,right ,right ,right ,right ,right ,right ,right ,right ,same }
};
#if DEBUG
- static private volatile bool s_fCheckedBetter = false;
+ private static volatile bool s_fCheckedBetter = false;
private void CheckBetterTable()
{
if (s_fCheckedBetter)
diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs
index d971e21294..df102dd94b 100644
--- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs
+++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs
@@ -2455,7 +2455,7 @@ namespace Microsoft.CSharp.RuntimeBinder.Semantics
return false;
}
- readonly static private PredefinedName[] s_EK2NAME =
+ private static readonly PredefinedName[] s_EK2NAME =
{
PredefinedName.PN_OPEQUALS,
PredefinedName.PN_OPCOMPARE,
diff --git a/src/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
index 38ec306d90..0391e9c502 100644
--- a/src/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
+++ b/src/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
@@ -676,7 +676,7 @@ namespace Microsoft.Win32
}
}
- static private void ValidateKeyOptions(RegistryOptions options)
+ private static void ValidateKeyOptions(RegistryOptions options)
{
if (options < RegistryOptions.None || options > RegistryOptions.Volatile)
{
@@ -684,7 +684,7 @@ namespace Microsoft.Win32
}
}
- static private void ValidateKeyView(RegistryView view)
+ private static void ValidateKeyView(RegistryView view)
{
if (view != RegistryView.Default && view != RegistryView.Registry32 && view != RegistryView.Registry64)
{
diff --git a/src/Native/Unix/CMakeLists.txt b/src/Native/Unix/CMakeLists.txt
index 4b4ba0f365..c81729c242 100644
--- a/src/Native/Unix/CMakeLists.txt
+++ b/src/Native/Unix/CMakeLists.txt
@@ -28,9 +28,10 @@ endif ()
if (CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL amd64)
add_definitions(-DBIT64=1)
add_definitions(-D_AMD64_)
-elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL x86)
+elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL x86 OR CMAKE_SYSTEM_PROCESSOR STREQUAL i686)
add_definitions(-DBIT32=1)
add_definitions(-D_X86_)
+ add_definitions(-D_FILE_OFFSET_BITS=64)
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
add_definitions(-DBIT64=1)
add_definitions(-D_ARM64_)
@@ -146,15 +147,15 @@ if (NOT WIN32)
else (CMAKE_SYSTEM_NAME STREQUAL Darwin)
# Ensure that objcopy is present
if(DEFINED ENV{CROSSCOMPILE})
- if(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l OR CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
+ if(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l OR CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL x86)
find_program(OBJCOPY ${TOOLCHAIN}-objcopy)
else()
- message(FATAL_ERROR "Only AMD64, ARM64 and ARM are supported")
+ message(FATAL_ERROR "Only AMD64, X86, ARM64 and ARM are supported")
endif()
else()
find_program(OBJCOPY objcopy)
endif()
- if (OBJCOPY STREQUAL "OBJCOPY-NOTFOUND")
+ if (OBJCOPY STREQUAL "OBJCOPY-NOTFOUND" AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL x86)
message(FATAL_ERROR "objcopy not found")
endif()
endif (CMAKE_SYSTEM_NAME STREQUAL Darwin)
diff --git a/src/Native/Unix/Common/pal_config.h.in b/src/Native/Unix/Common/pal_config.h.in
index 7e0539bb79..bc0aa28a99 100644
--- a/src/Native/Unix/Common/pal_config.h.in
+++ b/src/Native/Unix/Common/pal_config.h.in
@@ -28,7 +28,8 @@
#cmakedefine01 HAVE_STATFS
#cmakedefine01 HAVE_EPOLL
#cmakedefine01 HAVE_KQUEUE
-#cmakedefine01 HAVE_SENDFILE
+#cmakedefine01 HAVE_SENDFILE_4
+#cmakedefine01 HAVE_SENDFILE_6
#cmakedefine01 HAVE_FCOPYFILE
#cmakedefine01 HAVE_GETHOSTBYNAME_R
#cmakedefine01 HAVE_GETHOSTBYADDR_R
diff --git a/src/Native/Unix/System.Native/pal_io.cpp b/src/Native/Unix/System.Native/pal_io.cpp
index a50aedbffb..094e345cd8 100644
--- a/src/Native/Unix/System.Native/pal_io.cpp
+++ b/src/Native/Unix/System.Native/pal_io.cpp
@@ -28,7 +28,7 @@
#include <limits.h>
#if HAVE_FCOPYFILE
#include <copyfile.h>
-#elif HAVE_SENDFILE
+#elif HAVE_SENDFILE_4
#include <sys/sendfile.h>
#endif
#if HAVE_INOTIFY
@@ -1024,7 +1024,7 @@ extern "C" int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destination
int ret;
struct stat_ sourceStat;
bool copied = false;
-#if HAVE_SENDFILE
+#if HAVE_SENDFILE_4
// If sendfile is available (Linux), try to use it, as the whole copy
// can be performed in the kernel, without lots of unnecessary copying.
while (CheckInterrupted(ret = fstat_(inFd, &sourceStat)));
@@ -1069,7 +1069,7 @@ extern "C" int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destination
// sendfile couldn't be used; fall back to a manual copy below. This could happen
// if we're on an old kernel, for example, where sendfile could only be used
// with sockets and not regular files.
-#endif // HAVE_SENDFILE
+#endif // HAVE_SENDFILE_4
// Manually read all data from the source and write it to the destination.
if (!copied && CopyFile_ReadWrite(inFd, outFd) != 0)
diff --git a/src/Native/Unix/System.Native/pal_networking.cpp b/src/Native/Unix/System.Native/pal_networking.cpp
index e5ebb72dd2..79f5118559 100644
--- a/src/Native/Unix/System.Native/pal_networking.cpp
+++ b/src/Native/Unix/System.Native/pal_networking.cpp
@@ -34,6 +34,11 @@
#include <unistd.h>
#include <vector>
#include <pwd.h>
+#if HAVE_SENDFILE_4
+#include <sys/sendfile.h>
+#elif HAVE_SENDFILE_6
+#include <sys/uio.h>
+#endif
#if HAVE_KQUEUE
#if KEVENT_HAS_VOID_UDATA
@@ -2753,3 +2758,54 @@ extern "C" void SystemNative_GetDomainSocketSizes(int32_t* pathOffset, int32_t*
*pathSize = sizeof(domainSocket.sun_path);
*addressSize = sizeof(domainSocket);
}
+
+extern "C" Error SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, int64_t count, int64_t* sent)
+{
+ assert(sent != nullptr);
+
+ int outfd = ToFileDescriptor(out_fd);
+ int infd = ToFileDescriptor(in_fd);
+
+#if HAVE_SENDFILE_4
+ off_t offtOffset = static_cast<off_t>(offset);
+
+ ssize_t res;
+ while (CheckInterrupted(res = sendfile(outfd, infd, &offtOffset, static_cast<size_t>(count))));
+ if (res != -1)
+ {
+ *sent = res;
+ return PAL_SUCCESS;
+ }
+
+ *sent = 0;
+ return SystemNative_ConvertErrorPlatformToPal(errno);
+#elif HAVE_SENDFILE_6
+ off_t len = count;
+ ssize_t res;
+ while (CheckInterrupted(res = sendfile(infd, outfd, static_cast<off_t>(offset), &len, nullptr, 0)));
+ if (res != -1)
+ {
+ if (len == 0)
+ {
+ // This indicates EOF
+ *sent = count;
+ }
+ else
+ {
+ *sent = len;
+ }
+ return PAL_SUCCESS;
+ }
+
+ *sent = 0;
+ return SystemNative_ConvertErrorPlatformToPal(errno);
+#else
+ (void)outfd;
+ (void)infd;
+ (void)offset;
+ (void)count;
+ *sent = 0;
+ errno = ENOTSUP;
+ return SystemNative_ConvertErrorPlatformToPal(errno);
+#endif
+}
diff --git a/src/Native/Unix/System.Native/pal_networking.h b/src/Native/Unix/System.Native/pal_networking.h
index 7f5456153f..b02988c1a1 100644
--- a/src/Native/Unix/System.Native/pal_networking.h
+++ b/src/Native/Unix/System.Native/pal_networking.h
@@ -417,3 +417,5 @@ extern "C" int32_t SystemNative_PlatformSupportsDualModeIPv4PacketInfo();
extern "C" char* SystemNative_GetPeerUserName(intptr_t socket);
extern "C" void SystemNative_GetDomainSocketSizes(int32_t* pathOffset, int32_t* pathSize, int32_t* addressSize);
+
+extern "C" Error SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, int64_t count, int64_t* sent);
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt b/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt
index 74c901bee5..28d64547a1 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt
+++ b/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt
@@ -43,6 +43,17 @@ set(NATIVECRYPTO_SOURCES
pal_x509ext.cpp
)
+if (FEATURE_DISTRO_AGNOSTIC_SSL)
+ if (NOT CMAKE_SYSTEM_NAME STREQUAL Linux)
+ message(FATAL_ERROR "FEATURE_DISTRO_AGNOSTIC_SSL can only be enabled for Linux")
+ endif()
+
+ list(APPEND NATIVECRYPTO_SOURCES
+ opensslshim.cpp
+ )
+ add_definitions(-DFEATURE_DISTRO_AGNOSTIC_SSL)
+endif()
+
add_library(objlib OBJECT ${NATIVECRYPTO_SOURCES} ${VERSION_FILE_PATH})
add_library(System.Security.Cryptography.Native
@@ -59,36 +70,55 @@ add_library(System.Security.Cryptography.Native.OpenSsl
set_target_properties(System.Security.Cryptography.Native PROPERTIES PREFIX "")
set_target_properties(System.Security.Cryptography.Native.OpenSsl PROPERTIES PREFIX "")
-target_link_libraries(System.Security.Cryptography.Native
- ${OPENSSL_CRYPTO_LIBRARY}
- ${OPENSSL_SSL_LIBRARY}
-)
-
-target_link_libraries(System.Security.Cryptography.Native.OpenSsl
- ${OPENSSL_CRYPTO_LIBRARY}
- ${OPENSSL_SSL_LIBRARY}
-)
-
-# On OS X every library emits the manner in which it should be referenced.
-# All of our libraries are referenced via @rpath, which is similar to how Linux and Windows
-# libraries are loaded. The homebrew installation of OpenSSL (libcrypto, libssl) uses the
-# full path to the library installation. This means that this library is not flexible to
-# users installing newer libcrypto in the working directory, or to systems which do not
-# install to the same path as homebrew does.
-#
-# So, after compiling, rewrite the references to libcrypto to be more flexible.
-if (APPLE)
- add_custom_command(TARGET System.Security.Cryptography.Native POST_BUILD
- COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib @rpath/libcrypto.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native>
- COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libssl.1.0.0.dylib @rpath/libssl.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native>
- COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath @loader_path $<TARGET_FILE:System.Security.Cryptography.Native>
- )
-
+if (FEATURE_DISTRO_AGNOSTIC_SSL)
add_custom_command(TARGET System.Security.Cryptography.Native.OpenSsl POST_BUILD
- COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib @rpath/libcrypto.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
- COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libssl.1.0.0.dylib @rpath/libssl.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
- COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath @loader_path $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
- )
+ COMMENT "Verifying System.Security.Cryptography.Native.OpenSsl.so dependencies"
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../verify-so.sh
+ $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
+ "Verification failed. System.Security.Cryptography.Native.OpenSsl.so has undefined dependencies. These are likely OpenSSL APIs that need to be added to opensslshim.h"
+ VERBATIM
+ )
+
+ # Link with libdl.so to get the dlopen / dlsym / dlclose
+ target_link_libraries(System.Security.Cryptography.Native
+ dl
+ )
+
+ target_link_libraries(System.Security.Cryptography.Native.OpenSsl
+ dl
+ )
+else()
+ target_link_libraries(System.Security.Cryptography.Native
+ ${OPENSSL_CRYPTO_LIBRARY}
+ ${OPENSSL_SSL_LIBRARY}
+ )
+
+ target_link_libraries(System.Security.Cryptography.Native.OpenSsl
+ ${OPENSSL_CRYPTO_LIBRARY}
+ ${OPENSSL_SSL_LIBRARY}
+ )
+
+ # On OS X every library emits the manner in which it should be referenced.
+ # All of our libraries are referenced via @rpath, which is similar to how Linux and Windows
+ # libraries are loaded. The homebrew installation of OpenSSL (libcrypto, libssl) uses the
+ # full path to the library installation. This means that this library is not flexible to
+ # users installing newer libcrypto in the working directory, or to systems which do not
+ # install to the same path as homebrew does.
+ #
+ # So, after compiling, rewrite the references to libcrypto to be more flexible.
+ if (APPLE)
+ add_custom_command(TARGET System.Security.Cryptography.Native POST_BUILD
+ COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib @rpath/libcrypto.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native>
+ COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libssl.1.0.0.dylib @rpath/libssl.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native>
+ COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath @loader_path $<TARGET_FILE:System.Security.Cryptography.Native>
+ )
+
+ add_custom_command(TARGET System.Security.Cryptography.Native.OpenSsl POST_BUILD
+ COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib @rpath/libcrypto.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
+ COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libssl.1.0.0.dylib @rpath/libssl.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
+ COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath @loader_path $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
+ )
+ endif()
endif()
include(configure.cmake)
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp b/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp
index 4c7c72249c..3b2d4fb1b7 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp
@@ -5,6 +5,7 @@
#include "pal_types.h"
#include "pal_utilities.h"
#include "pal_safecrt.h"
+#include "opensslshim.h"
#include <assert.h>
#include <limits.h>
@@ -13,13 +14,6 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
-#include <openssl/asn1.h>
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
#include <memory>
// See X509NameType.SimpleName
@@ -84,7 +78,11 @@ extern "C" int32_t CryptoNative_GetX509Thumbprint(X509* x509, uint8_t* pBuf, int
return -SHA_DIGEST_LENGTH;
}
- memcpy_s(pBuf, UnsignedCast(cBuf), x509->sha1_hash, SHA_DIGEST_LENGTH);
+ if (!X509_digest(x509, EVP_sha1(), pBuf, NULL))
+ {
+ return 0;
+ }
+
return 1;
}
@@ -718,11 +716,7 @@ static int CheckX509HostnameMatch(ASN1_STRING* candidate, const char* hostname,
// RFC2818 says to use RFC2595 matching rules, but then gives an example that f*.com would match foo.com
// RFC2595 says that '*' may be used as the left name component, in which case it is a wildcard that does
// not match a '.'.
- //
- // In the interest of time, and the idea that it's better to err on the side of more restrictive,
- // this implementation does not support mid-string wildcards.
- //
- // TODO (3444): Determine if we're too restrictive here.
+ // The recommendation from the Windows Crypto team was not to match f*.com with foo.com.
char* candidateStr;
int i;
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp
new file mode 100644
index 0000000000..604c59ad08
--- /dev/null
+++ b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp
@@ -0,0 +1,56 @@
+// 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.
+//
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+#include "opensslshim.h"
+
+// Define pointers to all the used ICU functions
+#define PER_FUNCTION_BLOCK(fn, isRequired) decltype(fn) fn##_ptr;
+FOR_ALL_OPENSSL_FUNCTIONS
+#undef PER_FUNCTION_BLOCK
+
+static void* libssl = nullptr;
+
+bool OpenLibrary()
+{
+ // First try the default versioned so naming as described in the OpenSSL doc
+ libssl = dlopen("libssl.so.1.0.0", RTLD_LAZY);
+ if (libssl == nullptr)
+ {
+ // Fedora derived distros use different naming for the version 1.0.0
+ libssl = dlopen("libssl.so.10", RTLD_LAZY);
+ }
+
+ return libssl != nullptr;
+}
+
+__attribute__((constructor))
+void InitializeOpenSSLShim()
+{
+ if (!OpenLibrary())
+ {
+ fprintf(stderr, "No usable version of the libssl was found\n");
+ abort();
+ }
+
+ // Get pointers to all the ICU functions that are needed
+#define PER_FUNCTION_BLOCK(fn, isRequired) \
+ fn##_ptr = reinterpret_cast<decltype(fn)>(dlsym(libssl, #fn)); \
+ if ((fn##_ptr) == NULL && isRequired) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); }
+
+ FOR_ALL_OPENSSL_FUNCTIONS
+#undef PER_FUNCTION_BLOCK
+}
+
+__attribute__((destructor))
+void ShutdownOpenSSLShim()
+{
+ if (libssl != nullptr)
+ {
+ dlclose(libssl);
+ }
+}
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h
new file mode 100644
index 0000000000..fc92139686
--- /dev/null
+++ b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h
@@ -0,0 +1,623 @@
+// 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.
+//
+
+// Enable calling OpenSSL functions through shims to enable support for
+// different versioned so files naming and different configuration options
+// on various Linux distributions.
+
+#pragma once
+
+// All the openssl includes need to be here to ensure that the APIs we use
+// are overriden to be called through our function pointers.
+#include <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
+#include <openssl/ecdsa.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/md5.h>
+#include <openssl/objects.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs12.h>
+#include <openssl/pkcs7.h>
+#include <openssl/rand.h>
+#include <openssl/rsa.h>
+#include <openssl/sha.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pal_crypto_config.h"
+
+#ifdef FEATURE_DISTRO_AGNOSTIC_SSL
+
+#define API_EXISTS(fn) (fn != nullptr)
+
+// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
+// Forgetting to add a function here results in build failure with message reporting the function
+// that needs to be added.
+#define FOR_ALL_UNCONDITIONAL_OPENSSL_FUNCTIONS \
+ PER_FUNCTION_BLOCK(ASN1_BIT_STRING_free, true) \
+ PER_FUNCTION_BLOCK(ASN1_INTEGER_get, true) \
+ PER_FUNCTION_BLOCK(ASN1_OBJECT_free, true) \
+ PER_FUNCTION_BLOCK(ASN1_OCTET_STRING_free, true) \
+ PER_FUNCTION_BLOCK(ASN1_OCTET_STRING_new, true) \
+ PER_FUNCTION_BLOCK(ASN1_OCTET_STRING_set, true) \
+ PER_FUNCTION_BLOCK(ASN1_STRING_free, true) \
+ PER_FUNCTION_BLOCK(ASN1_STRING_print_ex, true) \
+ PER_FUNCTION_BLOCK(BASIC_CONSTRAINTS_free, true) \
+ PER_FUNCTION_BLOCK(BIO_ctrl, true) \
+ PER_FUNCTION_BLOCK(BIO_ctrl_pending, true) \
+ PER_FUNCTION_BLOCK(BIO_free, true) \
+ PER_FUNCTION_BLOCK(BIO_gets, true) \
+ PER_FUNCTION_BLOCK(BIO_new, true) \
+ PER_FUNCTION_BLOCK(BIO_new_file, true) \
+ PER_FUNCTION_BLOCK(BIO_read, true) \
+ PER_FUNCTION_BLOCK(BIO_s_mem, true) \
+ PER_FUNCTION_BLOCK(BIO_write, true) \
+ PER_FUNCTION_BLOCK(BN_bin2bn, true) \
+ PER_FUNCTION_BLOCK(BN_bn2bin, true) \
+ PER_FUNCTION_BLOCK(BN_clear_free, true) \
+ PER_FUNCTION_BLOCK(BN_free, true) \
+ PER_FUNCTION_BLOCK(BN_new, true) \
+ PER_FUNCTION_BLOCK(BN_num_bits, true) \
+ PER_FUNCTION_BLOCK(CRYPTO_add_lock, true) \
+ PER_FUNCTION_BLOCK(CRYPTO_num_locks, true) \
+ PER_FUNCTION_BLOCK(CRYPTO_set_locking_callback, true) \
+ PER_FUNCTION_BLOCK(d2i_ASN1_BIT_STRING, true) \
+ PER_FUNCTION_BLOCK(d2i_ASN1_OCTET_STRING, true) \
+ PER_FUNCTION_BLOCK(d2i_ASN1_type_bytes, true) \
+ PER_FUNCTION_BLOCK(d2i_BASIC_CONSTRAINTS, true) \
+ PER_FUNCTION_BLOCK(d2i_EXTENDED_KEY_USAGE, true) \
+ PER_FUNCTION_BLOCK(d2i_PKCS12, true) \
+ PER_FUNCTION_BLOCK(d2i_PKCS12_bio, true) \
+ PER_FUNCTION_BLOCK(d2i_PKCS7, true) \
+ PER_FUNCTION_BLOCK(d2i_PKCS7_bio, true) \
+ PER_FUNCTION_BLOCK(d2i_RSAPublicKey, true) \
+ PER_FUNCTION_BLOCK(d2i_X509, true) \
+ PER_FUNCTION_BLOCK(d2i_X509_bio, true) \
+ PER_FUNCTION_BLOCK(d2i_X509_CRL, true) \
+ PER_FUNCTION_BLOCK(d2i_X509_NAME, true) \
+ PER_FUNCTION_BLOCK(DSA_free, true) \
+ PER_FUNCTION_BLOCK(DSA_generate_key, true) \
+ PER_FUNCTION_BLOCK(DSA_generate_parameters_ex, true) \
+ PER_FUNCTION_BLOCK(DSA_new, true) \
+ PER_FUNCTION_BLOCK(DSA_sign, true) \
+ PER_FUNCTION_BLOCK(DSA_size, true) \
+ PER_FUNCTION_BLOCK(DSA_up_ref, true) \
+ PER_FUNCTION_BLOCK(DSA_verify, true) \
+ PER_FUNCTION_BLOCK(ECDSA_sign, true) \
+ PER_FUNCTION_BLOCK(ECDSA_size, true) \
+ PER_FUNCTION_BLOCK(ECDSA_verify, true) \
+ PER_FUNCTION_BLOCK(EC_GFp_mont_method, true) \
+ PER_FUNCTION_BLOCK(EC_GFp_simple_method, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_check, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_free, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_get0_generator, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_get0_seed, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_get_cofactor, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_get_curve_GFp, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_get_curve_name, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_get_degree, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_get_order, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_get_seed_len, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_method_of, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_new, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_set_curve_GFp, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_set_generator, true) \
+ PER_FUNCTION_BLOCK(EC_GROUP_set_seed, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_check_key, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_free, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_generate_key, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_get0_group, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_get0_private_key, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_get0_public_key, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_new, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_new_by_curve_name, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_set_group, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_set_private_key, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_set_public_key_affine_coordinates, true) \
+ PER_FUNCTION_BLOCK(EC_KEY_up_ref, true) \
+ PER_FUNCTION_BLOCK(EC_METHOD_get_field_type, true) \
+ PER_FUNCTION_BLOCK(EC_POINT_free, true) \
+ PER_FUNCTION_BLOCK(EC_POINT_get_affine_coordinates_GFp, true) \
+ PER_FUNCTION_BLOCK(EC_POINT_new, true) \
+ PER_FUNCTION_BLOCK(EC_POINT_set_affine_coordinates_GFp, true) \
+ PER_FUNCTION_BLOCK(ERR_clear_error, true) \
+ PER_FUNCTION_BLOCK(ERR_error_string_n, true) \
+ PER_FUNCTION_BLOCK(ERR_get_error, true) \
+ PER_FUNCTION_BLOCK(ERR_load_crypto_strings, true) \
+ PER_FUNCTION_BLOCK(ERR_peek_error, true) \
+ PER_FUNCTION_BLOCK(ERR_peek_last_error, true) \
+ PER_FUNCTION_BLOCK(ERR_reason_error_string, true) \
+ PER_FUNCTION_BLOCK(EVP_aes_128_cbc, true) \
+ PER_FUNCTION_BLOCK(EVP_aes_128_ecb, true) \
+ PER_FUNCTION_BLOCK(EVP_aes_192_cbc, true) \
+ PER_FUNCTION_BLOCK(EVP_aes_192_ecb, true) \
+ PER_FUNCTION_BLOCK(EVP_aes_256_cbc, true) \
+ PER_FUNCTION_BLOCK(EVP_aes_256_ecb, true) \
+ PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_cleanup, true) \
+ PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_ctrl, true) \
+ PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_init, true) \
+ PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_set_key_length, true) \
+ PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_set_padding, true) \
+ PER_FUNCTION_BLOCK(EVP_CipherFinal_ex, true) \
+ PER_FUNCTION_BLOCK(EVP_CipherInit_ex, true) \
+ PER_FUNCTION_BLOCK(EVP_CipherUpdate, true) \
+ PER_FUNCTION_BLOCK(EVP_des_cbc, true) \
+ PER_FUNCTION_BLOCK(EVP_des_ecb, true) \
+ PER_FUNCTION_BLOCK(EVP_des_ede3, true) \
+ PER_FUNCTION_BLOCK(EVP_des_ede3_cbc, true) \
+ PER_FUNCTION_BLOCK(EVP_DigestFinal_ex, true) \
+ PER_FUNCTION_BLOCK(EVP_DigestInit_ex, true) \
+ PER_FUNCTION_BLOCK(EVP_DigestUpdate, true) \
+ PER_FUNCTION_BLOCK(EVP_md5, true) \
+ PER_FUNCTION_BLOCK(EVP_MD_CTX_create, true) \
+ PER_FUNCTION_BLOCK(EVP_MD_CTX_destroy, true) \
+ PER_FUNCTION_BLOCK(EVP_MD_size, true) \
+ PER_FUNCTION_BLOCK(EVP_PKEY_free, true) \
+ PER_FUNCTION_BLOCK(EVP_PKEY_get1_DSA, true) \
+ PER_FUNCTION_BLOCK(EVP_PKEY_get1_EC_KEY, true) \
+ PER_FUNCTION_BLOCK(EVP_PKEY_get1_RSA, true) \
+ PER_FUNCTION_BLOCK(EVP_PKEY_new, true) \
+ PER_FUNCTION_BLOCK(EVP_PKEY_set1_DSA, true) \
+ PER_FUNCTION_BLOCK(EVP_PKEY_set1_EC_KEY, true) \
+ PER_FUNCTION_BLOCK(EVP_PKEY_set1_RSA, true) \
+ PER_FUNCTION_BLOCK(EVP_rc2_cbc, true) \
+ PER_FUNCTION_BLOCK(EVP_rc2_ecb, true) \
+ PER_FUNCTION_BLOCK(EVP_sha1, true) \
+ PER_FUNCTION_BLOCK(EVP_sha256, true) \
+ PER_FUNCTION_BLOCK(EVP_sha384, true) \
+ PER_FUNCTION_BLOCK(EVP_sha512, true) \
+ PER_FUNCTION_BLOCK(EXTENDED_KEY_USAGE_free, true) \
+ PER_FUNCTION_BLOCK(GENERAL_NAMES_free, true) \
+ PER_FUNCTION_BLOCK(HMAC_CTX_cleanup, true) \
+ PER_FUNCTION_BLOCK(HMAC_CTX_init, true) \
+ PER_FUNCTION_BLOCK(HMAC_Final, true) \
+ PER_FUNCTION_BLOCK(HMAC_Init_ex, true) \
+ PER_FUNCTION_BLOCK(HMAC_Update, true) \
+ PER_FUNCTION_BLOCK(i2d_ASN1_INTEGER, true) \
+ PER_FUNCTION_BLOCK(i2d_ASN1_TYPE, true) \
+ PER_FUNCTION_BLOCK(i2d_PKCS12, true) \
+ PER_FUNCTION_BLOCK(i2d_PKCS7, true) \
+ PER_FUNCTION_BLOCK(i2d_X509, true) \
+ PER_FUNCTION_BLOCK(i2d_X509_PUBKEY, true) \
+ PER_FUNCTION_BLOCK(OBJ_ln2nid, true) \
+ PER_FUNCTION_BLOCK(OBJ_nid2ln, true) \
+ PER_FUNCTION_BLOCK(OBJ_nid2obj, true) \
+ PER_FUNCTION_BLOCK(OBJ_obj2nid, true) \
+ PER_FUNCTION_BLOCK(OBJ_obj2txt, true) \
+ PER_FUNCTION_BLOCK(OBJ_sn2nid, true) \
+ PER_FUNCTION_BLOCK(OBJ_txt2nid, true) \
+ PER_FUNCTION_BLOCK(OBJ_txt2obj, true) \
+ PER_FUNCTION_BLOCK(OPENSSL_add_all_algorithms_conf, true) \
+ PER_FUNCTION_BLOCK(PEM_read_bio_PKCS7, true) \
+ PER_FUNCTION_BLOCK(PEM_read_bio_X509_AUX, true) \
+ PER_FUNCTION_BLOCK(PEM_read_bio_X509_CRL, true) \
+ PER_FUNCTION_BLOCK(PEM_write_bio_X509_CRL, true) \
+ PER_FUNCTION_BLOCK(PKCS12_create, true) \
+ PER_FUNCTION_BLOCK(PKCS12_free, true) \
+ PER_FUNCTION_BLOCK(PKCS12_parse, true) \
+ PER_FUNCTION_BLOCK(PKCS7_add_certificate, true) \
+ PER_FUNCTION_BLOCK(PKCS7_content_new, true) \
+ PER_FUNCTION_BLOCK(PKCS7_free, true) \
+ PER_FUNCTION_BLOCK(PKCS7_new, true) \
+ PER_FUNCTION_BLOCK(PKCS7_set_type, true) \
+ PER_FUNCTION_BLOCK(RAND_bytes, true) \
+ PER_FUNCTION_BLOCK(RAND_poll, true) \
+ PER_FUNCTION_BLOCK(RSA_free, true) \
+ PER_FUNCTION_BLOCK(RSA_generate_key_ex, true) \
+ PER_FUNCTION_BLOCK(RSA_new, true) \
+ PER_FUNCTION_BLOCK(RSA_private_decrypt, true) \
+ PER_FUNCTION_BLOCK(RSA_public_encrypt, true) \
+ PER_FUNCTION_BLOCK(RSA_sign, true) \
+ PER_FUNCTION_BLOCK(RSA_size, true) \
+ PER_FUNCTION_BLOCK(RSA_up_ref, true) \
+ PER_FUNCTION_BLOCK(RSA_verify, true) \
+ PER_FUNCTION_BLOCK(sk_free, true) \
+ PER_FUNCTION_BLOCK(sk_new_null, true) \
+ PER_FUNCTION_BLOCK(sk_num, true) \
+ PER_FUNCTION_BLOCK(sk_pop_free, true) \
+ PER_FUNCTION_BLOCK(sk_push, true) \
+ PER_FUNCTION_BLOCK(sk_value, true) \
+ PER_FUNCTION_BLOCK(SSL_CIPHER_description, true) \
+ PER_FUNCTION_BLOCK(SSL_ctrl, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_check_private_key, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_ctrl, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_free, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_new, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_set_cert_verify_callback, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_set_cipher_list, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_set_client_CA_list, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_set_client_cert_cb, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_set_quiet_shutdown, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_set_verify, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_use_certificate, true) \
+ PER_FUNCTION_BLOCK(SSL_CTX_use_PrivateKey, true) \
+ PER_FUNCTION_BLOCK(SSL_do_handshake, true) \
+ PER_FUNCTION_BLOCK(SSL_free, true) \
+ PER_FUNCTION_BLOCK(SSL_get_client_CA_list, true) \
+ PER_FUNCTION_BLOCK(SSL_get_current_cipher, true) \
+ PER_FUNCTION_BLOCK(SSL_get_error, true) \
+ PER_FUNCTION_BLOCK(SSL_get_finished, true) \
+ PER_FUNCTION_BLOCK(SSL_get_peer_cert_chain, true) \
+ PER_FUNCTION_BLOCK(SSL_get_peer_certificate, true) \
+ PER_FUNCTION_BLOCK(SSL_get_peer_finished, true) \
+ PER_FUNCTION_BLOCK(SSL_get_SSL_CTX, true) \
+ PER_FUNCTION_BLOCK(SSL_get_version, true) \
+ PER_FUNCTION_BLOCK(SSL_library_init, true) \
+ PER_FUNCTION_BLOCK(SSL_load_error_strings, true) \
+ PER_FUNCTION_BLOCK(SSL_new, true) \
+ PER_FUNCTION_BLOCK(SSL_read, true) \
+ PER_FUNCTION_BLOCK(SSL_renegotiate_pending, true) \
+ PER_FUNCTION_BLOCK(SSL_set_accept_state, true) \
+ PER_FUNCTION_BLOCK(SSL_set_bio, true) \
+ PER_FUNCTION_BLOCK(SSL_set_connect_state, true) \
+ PER_FUNCTION_BLOCK(SSL_shutdown, true) \
+ PER_FUNCTION_BLOCK(SSL_state, true) \
+ PER_FUNCTION_BLOCK(SSLv23_method, true) \
+ PER_FUNCTION_BLOCK(SSLv3_method, true) \
+ PER_FUNCTION_BLOCK(SSL_write, true) \
+ PER_FUNCTION_BLOCK(TLSv1_1_method, true) \
+ PER_FUNCTION_BLOCK(TLSv1_2_method, true) \
+ PER_FUNCTION_BLOCK(TLSv1_method, true) \
+ PER_FUNCTION_BLOCK(X509_check_issued, true) \
+ PER_FUNCTION_BLOCK(X509_check_purpose, true) \
+ PER_FUNCTION_BLOCK(X509_CRL_free, true) \
+ PER_FUNCTION_BLOCK(X509_digest, true) \
+ PER_FUNCTION_BLOCK(X509_dup, true) \
+ PER_FUNCTION_BLOCK(X509_EXTENSION_create_by_OBJ, true) \
+ PER_FUNCTION_BLOCK(X509_EXTENSION_free, true) \
+ PER_FUNCTION_BLOCK(X509_EXTENSION_get_critical, true) \
+ PER_FUNCTION_BLOCK(X509_EXTENSION_get_data, true) \
+ PER_FUNCTION_BLOCK(X509_EXTENSION_get_object, true) \
+ PER_FUNCTION_BLOCK(X509_free, true) \
+ PER_FUNCTION_BLOCK(X509_get_default_cert_dir, true) \
+ PER_FUNCTION_BLOCK(X509_get_default_cert_dir_env, true) \
+ PER_FUNCTION_BLOCK(X509_get_default_cert_file, true) \
+ PER_FUNCTION_BLOCK(X509_get_default_cert_file_env, true) \
+ PER_FUNCTION_BLOCK(X509_get_ext, true) \
+ PER_FUNCTION_BLOCK(X509_get_ext_count, true) \
+ PER_FUNCTION_BLOCK(X509_get_ext_d2i, true) \
+ PER_FUNCTION_BLOCK(X509_get_issuer_name, true) \
+ PER_FUNCTION_BLOCK(X509_get_serialNumber, true) \
+ PER_FUNCTION_BLOCK(X509_get_subject_name, true) \
+ PER_FUNCTION_BLOCK(X509_issuer_name_hash, true) \
+ PER_FUNCTION_BLOCK(X509_NAME_dup, true) \
+ PER_FUNCTION_BLOCK(X509_NAME_entry_count, true) \
+ PER_FUNCTION_BLOCK(X509_NAME_ENTRY_get_data, true) \
+ PER_FUNCTION_BLOCK(X509_NAME_ENTRY_get_object, true) \
+ PER_FUNCTION_BLOCK(X509_NAME_free, true) \
+ PER_FUNCTION_BLOCK(X509_NAME_get_entry, true) \
+ PER_FUNCTION_BLOCK(X509_NAME_get_index_by_NID, true) \
+ PER_FUNCTION_BLOCK(X509_PUBKEY_get, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_add_cert, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_add_crl, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_CTX_free, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_CTX_get0_param, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_CTX_get1_chain, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_CTX_get_error, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_CTX_get_error_depth, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_CTX_init, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_CTX_new, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_CTX_set_verify_cb, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_free, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_new, true) \
+ PER_FUNCTION_BLOCK(X509_STORE_set_flags, true) \
+ PER_FUNCTION_BLOCK(X509V3_EXT_print, true) \
+ PER_FUNCTION_BLOCK(X509_verify_cert, true) \
+ PER_FUNCTION_BLOCK(X509_verify_cert_error_string, true) \
+ PER_FUNCTION_BLOCK(X509_VERIFY_PARAM_set_time, true) \
+
+#if HAVE_OPENSSL_EC2M
+#define FOR_ALL_OPENSSL_FUNCTIONS \
+ FOR_ALL_UNCONDITIONAL_OPENSSL_FUNCTIONS \
+ PER_FUNCTION_BLOCK(EC_GF2m_simple_method, false) \
+ PER_FUNCTION_BLOCK(EC_GROUP_get_curve_GF2m, false) \
+ PER_FUNCTION_BLOCK(EC_GROUP_set_curve_GF2m, false) \
+ PER_FUNCTION_BLOCK(EC_POINT_get_affine_coordinates_GF2m, false) \
+ PER_FUNCTION_BLOCK(EC_POINT_set_affine_coordinates_GF2m, false) \
+
+#else // HAVE_OPENSSL_EC2M
+#define FOR_ALL_OPENSSL_FUNCTIONS \
+ FOR_ALL_UNCONDITIONAL_OPENSSL_FUNCTIONS
+
+#endif // HAVE_OPENSSL_EC2M
+
+// Declare pointers to all the used OpenSSL functions
+#define PER_FUNCTION_BLOCK(fn, isRequired) extern decltype(fn)* fn##_ptr;
+FOR_ALL_OPENSSL_FUNCTIONS
+#undef PER_FUNCTION_BLOCK
+
+// Redefine all calls to OpenSSL functions as calls through pointers that are set
+// to the functions from the libssl.so selected by the shim.
+#define ASN1_BIT_STRING_free ASN1_BIT_STRING_free_ptr
+#define ASN1_INTEGER_get ASN1_INTEGER_get_ptr
+#define ASN1_OBJECT_free ASN1_OBJECT_free_ptr
+#define ASN1_OCTET_STRING_free ASN1_OCTET_STRING_free_ptr
+#define ASN1_OCTET_STRING_new ASN1_OCTET_STRING_new_ptr
+#define ASN1_OCTET_STRING_set ASN1_OCTET_STRING_set_ptr
+#define ASN1_STRING_free ASN1_STRING_free_ptr
+#define ASN1_STRING_print_ex ASN1_STRING_print_ex_ptr
+#define BASIC_CONSTRAINTS_free BASIC_CONSTRAINTS_free_ptr
+#define BIO_ctrl BIO_ctrl_ptr
+#define BIO_ctrl_pending BIO_ctrl_pending_ptr
+#define BIO_free BIO_free_ptr
+#define BIO_gets BIO_gets_ptr
+#define BIO_new BIO_new_ptr
+#define BIO_new_file BIO_new_file_ptr
+#define BIO_read BIO_read_ptr
+#define BIO_s_mem BIO_s_mem_ptr
+#define BIO_write BIO_write_ptr
+#define BN_bin2bn BN_bin2bn_ptr
+#define BN_bn2bin BN_bn2bin_ptr
+#define BN_clear_free BN_clear_free_ptr
+#define BN_free BN_free_ptr
+#define BN_new BN_new_ptr
+#define BN_num_bits BN_num_bits_ptr
+#define CRYPTO_add_lock CRYPTO_add_lock_ptr
+#define CRYPTO_num_locks CRYPTO_num_locks_ptr
+#define CRYPTO_set_locking_callback CRYPTO_set_locking_callback_ptr
+#define d2i_ASN1_BIT_STRING d2i_ASN1_BIT_STRING_ptr
+#define d2i_ASN1_OCTET_STRING d2i_ASN1_OCTET_STRING_ptr
+#define d2i_ASN1_type_bytes d2i_ASN1_type_bytes_ptr
+#define d2i_BASIC_CONSTRAINTS d2i_BASIC_CONSTRAINTS_ptr
+#define d2i_EXTENDED_KEY_USAGE d2i_EXTENDED_KEY_USAGE_ptr
+#define d2i_PKCS12 d2i_PKCS12_ptr
+#define d2i_PKCS12_bio d2i_PKCS12_bio_ptr
+#define d2i_PKCS7 d2i_PKCS7_ptr
+#define d2i_PKCS7_bio d2i_PKCS7_bio_ptr
+#define d2i_RSAPublicKey d2i_RSAPublicKey_ptr
+#define d2i_X509 d2i_X509_ptr
+#define d2i_X509_bio d2i_X509_bio_ptr
+#define d2i_X509_CRL d2i_X509_CRL_ptr
+#define d2i_X509_NAME d2i_X509_NAME_ptr
+#define DSA_free DSA_free_ptr
+#define DSA_generate_key DSA_generate_key_ptr
+#define DSA_generate_parameters_ex DSA_generate_parameters_ex_ptr
+#define DSA_new DSA_new_ptr
+#define DSA_sign DSA_sign_ptr
+#define DSA_size DSA_size_ptr
+#define DSA_up_ref DSA_up_ref_ptr
+#define DSA_verify DSA_verify_ptr
+#define ECDSA_sign ECDSA_sign_ptr
+#define ECDSA_size ECDSA_size_ptr
+#define ECDSA_verify ECDSA_verify_ptr
+#define EC_GFp_mont_method EC_GFp_mont_method_ptr
+#define EC_GFp_simple_method EC_GFp_simple_method_ptr
+#define EC_GROUP_check EC_GROUP_check_ptr
+#define EC_GROUP_free EC_GROUP_free_ptr
+#define EC_GROUP_get0_generator EC_GROUP_get0_generator_ptr
+#define EC_GROUP_get0_seed EC_GROUP_get0_seed_ptr
+#define EC_GROUP_get_cofactor EC_GROUP_get_cofactor_ptr
+#define EC_GROUP_get_curve_GFp EC_GROUP_get_curve_GFp_ptr
+#define EC_GROUP_get_curve_name EC_GROUP_get_curve_name_ptr
+#define EC_GROUP_get_degree EC_GROUP_get_degree_ptr
+#define EC_GROUP_get_order EC_GROUP_get_order_ptr
+#define EC_GROUP_get_seed_len EC_GROUP_get_seed_len_ptr
+#define EC_GROUP_method_of EC_GROUP_method_of_ptr
+#define EC_GROUP_new EC_GROUP_new_ptr
+#define EC_GROUP_set_curve_GFp EC_GROUP_set_curve_GFp_ptr
+#define EC_GROUP_set_generator EC_GROUP_set_generator_ptr
+#define EC_GROUP_set_seed EC_GROUP_set_seed_ptr
+#define EC_KEY_check_key EC_KEY_check_key_ptr
+#define EC_KEY_free EC_KEY_free_ptr
+#define EC_KEY_generate_key EC_KEY_generate_key_ptr
+#define EC_KEY_get0_group EC_KEY_get0_group_ptr
+#define EC_KEY_get0_private_key EC_KEY_get0_private_key_ptr
+#define EC_KEY_get0_public_key EC_KEY_get0_public_key_ptr
+#define EC_KEY_new EC_KEY_new_ptr
+#define EC_KEY_new_by_curve_name EC_KEY_new_by_curve_name_ptr
+#define EC_KEY_set_group EC_KEY_set_group_ptr
+#define EC_KEY_set_private_key EC_KEY_set_private_key_ptr
+#define EC_KEY_set_public_key_affine_coordinates EC_KEY_set_public_key_affine_coordinates_ptr
+#define EC_KEY_up_ref EC_KEY_up_ref_ptr
+#define EC_METHOD_get_field_type EC_METHOD_get_field_type_ptr
+#define EC_POINT_free EC_POINT_free_ptr
+#define EC_POINT_get_affine_coordinates_GFp EC_POINT_get_affine_coordinates_GFp_ptr
+#define EC_POINT_new EC_POINT_new_ptr
+#define EC_POINT_set_affine_coordinates_GFp EC_POINT_set_affine_coordinates_GFp_ptr
+#define ERR_clear_error ERR_clear_error_ptr
+#define ERR_error_string_n ERR_error_string_n_ptr
+#define ERR_get_error ERR_get_error_ptr
+#define ERR_load_crypto_strings ERR_load_crypto_strings_ptr
+#define ERR_peek_error ERR_peek_error_ptr
+#define ERR_peek_last_error ERR_peek_last_error_ptr
+#define ERR_reason_error_string ERR_reason_error_string_ptr
+#define EVP_aes_128_cbc EVP_aes_128_cbc_ptr
+#define EVP_aes_128_ecb EVP_aes_128_ecb_ptr
+#define EVP_aes_192_cbc EVP_aes_192_cbc_ptr
+#define EVP_aes_192_ecb EVP_aes_192_ecb_ptr
+#define EVP_aes_256_cbc EVP_aes_256_cbc_ptr
+#define EVP_aes_256_ecb EVP_aes_256_ecb_ptr
+#define EVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_cleanup_ptr
+#define EVP_CIPHER_CTX_ctrl EVP_CIPHER_CTX_ctrl_ptr
+#define EVP_CIPHER_CTX_init EVP_CIPHER_CTX_init_ptr
+#define EVP_CIPHER_CTX_set_key_length EVP_CIPHER_CTX_set_key_length_ptr
+#define EVP_CIPHER_CTX_set_padding EVP_CIPHER_CTX_set_padding_ptr
+#define EVP_CipherFinal_ex EVP_CipherFinal_ex_ptr
+#define EVP_CipherInit_ex EVP_CipherInit_ex_ptr
+#define EVP_CipherUpdate EVP_CipherUpdate_ptr
+#define EVP_des_cbc EVP_des_cbc_ptr
+#define EVP_des_ecb EVP_des_ecb_ptr
+#define EVP_des_ede3 EVP_des_ede3_ptr
+#define EVP_des_ede3_cbc EVP_des_ede3_cbc_ptr
+#define EVP_DigestFinal_ex EVP_DigestFinal_ex_ptr
+#define EVP_DigestInit_ex EVP_DigestInit_ex_ptr
+#define EVP_DigestUpdate EVP_DigestUpdate_ptr
+#define EVP_md5 EVP_md5_ptr
+#define EVP_MD_CTX_create EVP_MD_CTX_create_ptr
+#define EVP_MD_CTX_destroy EVP_MD_CTX_destroy_ptr
+#define EVP_MD_size EVP_MD_size_ptr
+#define EVP_PKEY_free EVP_PKEY_free_ptr
+#define EVP_PKEY_get1_DSA EVP_PKEY_get1_DSA_ptr
+#define EVP_PKEY_get1_EC_KEY EVP_PKEY_get1_EC_KEY_ptr
+#define EVP_PKEY_get1_RSA EVP_PKEY_get1_RSA_ptr
+#define EVP_PKEY_new EVP_PKEY_new_ptr
+#define EVP_PKEY_set1_DSA EVP_PKEY_set1_DSA_ptr
+#define EVP_PKEY_set1_EC_KEY EVP_PKEY_set1_EC_KEY_ptr
+#define EVP_PKEY_set1_RSA EVP_PKEY_set1_RSA_ptr
+#define EVP_rc2_cbc EVP_rc2_cbc_ptr
+#define EVP_rc2_ecb EVP_rc2_ecb_ptr
+#define EVP_sha1 EVP_sha1_ptr
+#define EVP_sha256 EVP_sha256_ptr
+#define EVP_sha384 EVP_sha384_ptr
+#define EVP_sha512 EVP_sha512_ptr
+#define EXTENDED_KEY_USAGE_free EXTENDED_KEY_USAGE_free_ptr
+#define GENERAL_NAMES_free GENERAL_NAMES_free_ptr
+#define HMAC_CTX_cleanup HMAC_CTX_cleanup_ptr
+#define HMAC_CTX_init HMAC_CTX_init_ptr
+#define HMAC_Final HMAC_Final_ptr
+#define HMAC_Init_ex HMAC_Init_ex_ptr
+#define HMAC_Update HMAC_Update_ptr
+#define i2d_ASN1_INTEGER i2d_ASN1_INTEGER_ptr
+#define i2d_ASN1_TYPE i2d_ASN1_TYPE_ptr
+#define i2d_PKCS12 i2d_PKCS12_ptr
+#define i2d_PKCS7 i2d_PKCS7_ptr
+#define i2d_X509 i2d_X509_ptr
+#define i2d_X509_PUBKEY i2d_X509_PUBKEY_ptr
+#define OBJ_ln2nid OBJ_ln2nid_ptr
+#define OBJ_nid2ln OBJ_nid2ln_ptr
+#define OBJ_nid2obj OBJ_nid2obj_ptr
+#define OBJ_obj2nid OBJ_obj2nid_ptr
+#define OBJ_obj2txt OBJ_obj2txt_ptr
+#define OBJ_sn2nid OBJ_sn2nid_ptr
+#define OBJ_txt2nid OBJ_txt2nid_ptr
+#define OBJ_txt2obj OBJ_txt2obj_ptr
+#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
+#define PEM_read_bio_PKCS7 PEM_read_bio_PKCS7_ptr
+#define PEM_read_bio_X509_AUX PEM_read_bio_X509_AUX_ptr
+#define PEM_read_bio_X509_CRL PEM_read_bio_X509_CRL_ptr
+#define PEM_write_bio_X509_CRL PEM_write_bio_X509_CRL_ptr
+#define PKCS12_create PKCS12_create_ptr
+#define PKCS12_free PKCS12_free_ptr
+#define PKCS12_parse PKCS12_parse_ptr
+#define PKCS7_add_certificate PKCS7_add_certificate_ptr
+#define PKCS7_content_new PKCS7_content_new_ptr
+#define PKCS7_free PKCS7_free_ptr
+#define PKCS7_new PKCS7_new_ptr
+#define PKCS7_set_type PKCS7_set_type_ptr
+#define RAND_bytes RAND_bytes_ptr
+#define RAND_poll RAND_poll_ptr
+#define RSA_free RSA_free_ptr
+#define RSA_generate_key_ex RSA_generate_key_ex_ptr
+#define RSA_new RSA_new_ptr
+#define RSA_private_decrypt RSA_private_decrypt_ptr
+#define RSA_public_encrypt RSA_public_encrypt_ptr
+#define RSA_sign RSA_sign_ptr
+#define RSA_size RSA_size_ptr
+#define RSA_up_ref RSA_up_ref_ptr
+#define RSA_verify RSA_verify_ptr
+#define sk_free sk_free_ptr
+#define sk_new_null sk_new_null_ptr
+#define sk_num sk_num_ptr
+#define sk_pop_free sk_pop_free_ptr
+#define sk_push sk_push_ptr
+#define sk_value sk_value_ptr
+#define SSL_CIPHER_description SSL_CIPHER_description_ptr
+#define SSL_ctrl SSL_ctrl_ptr
+#define SSL_CTX_check_private_key SSL_CTX_check_private_key_ptr
+#define SSL_CTX_ctrl SSL_CTX_ctrl_ptr
+#define SSL_CTX_free SSL_CTX_free_ptr
+#define SSL_CTX_new SSL_CTX_new_ptr
+#define SSL_CTX_set_cert_verify_callback SSL_CTX_set_cert_verify_callback_ptr
+#define SSL_CTX_set_cipher_list SSL_CTX_set_cipher_list_ptr
+#define SSL_CTX_set_client_CA_list SSL_CTX_set_client_CA_list_ptr
+#define SSL_CTX_set_client_cert_cb SSL_CTX_set_client_cert_cb_ptr
+#define SSL_CTX_set_quiet_shutdown SSL_CTX_set_quiet_shutdown_ptr
+#define SSL_CTX_set_verify SSL_CTX_set_verify_ptr
+#define SSL_CTX_use_certificate SSL_CTX_use_certificate_ptr
+#define SSL_CTX_use_PrivateKey SSL_CTX_use_PrivateKey_ptr
+#define SSL_do_handshake SSL_do_handshake_ptr
+#define SSL_free SSL_free_ptr
+#define SSL_get_client_CA_list SSL_get_client_CA_list_ptr
+#define SSL_get_current_cipher SSL_get_current_cipher_ptr
+#define SSL_get_error SSL_get_error_ptr
+#define SSL_get_finished SSL_get_finished_ptr
+#define SSL_get_peer_cert_chain SSL_get_peer_cert_chain_ptr
+#define SSL_get_peer_certificate SSL_get_peer_certificate_ptr
+#define SSL_get_peer_finished SSL_get_peer_finished_ptr
+#define SSL_get_SSL_CTX SSL_get_SSL_CTX_ptr
+#define SSL_get_version SSL_get_version_ptr
+#define SSL_library_init SSL_library_init_ptr
+#define SSL_load_error_strings SSL_load_error_strings_ptr
+#define SSL_new SSL_new_ptr
+#define SSL_read SSL_read_ptr
+#define SSL_renegotiate_pending SSL_renegotiate_pending_ptr
+#define SSL_set_accept_state SSL_set_accept_state_ptr
+#define SSL_set_bio SSL_set_bio_ptr
+#define SSL_set_connect_state SSL_set_connect_state_ptr
+#define SSL_shutdown SSL_shutdown_ptr
+#define SSL_state SSL_state_ptr
+#define SSLv23_method SSLv23_method_ptr
+#define SSLv3_method SSLv3_method_ptr
+#define SSL_write SSL_write_ptr
+#define TLSv1_1_method TLSv1_1_method_ptr
+#define TLSv1_2_method TLSv1_2_method_ptr
+#define TLSv1_method TLSv1_method_ptr
+#define X509_check_issued X509_check_issued_ptr
+#define X509_check_purpose X509_check_purpose_ptr
+#define X509_CRL_free X509_CRL_free_ptr
+#define X509_digest X509_digest_ptr
+#define X509_dup X509_dup_ptr
+#define X509_EXTENSION_create_by_OBJ X509_EXTENSION_create_by_OBJ_ptr
+#define X509_EXTENSION_free X509_EXTENSION_free_ptr
+#define X509_EXTENSION_get_critical X509_EXTENSION_get_critical_ptr
+#define X509_EXTENSION_get_data X509_EXTENSION_get_data_ptr
+#define X509_EXTENSION_get_object X509_EXTENSION_get_object_ptr
+#define X509_free X509_free_ptr
+#define X509_get_default_cert_dir X509_get_default_cert_dir_ptr
+#define X509_get_default_cert_dir_env X509_get_default_cert_dir_env_ptr
+#define X509_get_default_cert_file X509_get_default_cert_file_ptr
+#define X509_get_default_cert_file_env X509_get_default_cert_file_env_ptr
+#define X509_get_ext X509_get_ext_ptr
+#define X509_get_ext_count X509_get_ext_count_ptr
+#define X509_get_ext_d2i X509_get_ext_d2i_ptr
+#define X509_get_issuer_name X509_get_issuer_name_ptr
+#define X509_get_serialNumber X509_get_serialNumber_ptr
+#define X509_get_subject_name X509_get_subject_name_ptr
+#define X509_issuer_name_hash X509_issuer_name_hash_ptr
+#define X509_NAME_dup X509_NAME_dup_ptr
+#define X509_NAME_entry_count X509_NAME_entry_count_ptr
+#define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_get_data_ptr
+#define X509_NAME_ENTRY_get_object X509_NAME_ENTRY_get_object_ptr
+#define X509_NAME_free X509_NAME_free_ptr
+#define X509_NAME_get_entry X509_NAME_get_entry_ptr
+#define X509_NAME_get_index_by_NID X509_NAME_get_index_by_NID_ptr
+#define X509_PUBKEY_get X509_PUBKEY_get_ptr
+#define X509_STORE_add_cert X509_STORE_add_cert_ptr
+#define X509_STORE_add_crl X509_STORE_add_crl_ptr
+#define X509_STORE_CTX_free X509_STORE_CTX_free_ptr
+#define X509_STORE_CTX_get0_param X509_STORE_CTX_get0_param_ptr
+#define X509_STORE_CTX_get1_chain X509_STORE_CTX_get1_chain_ptr
+#define X509_STORE_CTX_get_error X509_STORE_CTX_get_error_ptr
+#define X509_STORE_CTX_get_error_depth X509_STORE_CTX_get_error_depth_ptr
+#define X509_STORE_CTX_init X509_STORE_CTX_init_ptr
+#define X509_STORE_CTX_new X509_STORE_CTX_new_ptr
+#define X509_STORE_CTX_set_verify_cb X509_STORE_CTX_set_verify_cb_ptr
+#define X509_STORE_free X509_STORE_free_ptr
+#define X509_STORE_new X509_STORE_new_ptr
+#define X509_STORE_set_flags X509_STORE_set_flags_ptr
+#define X509V3_EXT_print X509V3_EXT_print_ptr
+#define X509_verify_cert X509_verify_cert_ptr
+#define X509_verify_cert_error_string X509_verify_cert_error_string_ptr
+#define X509_VERIFY_PARAM_set_time X509_VERIFY_PARAM_set_time_ptr
+
+#if HAVE_OPENSSL_EC2M
+#define EC_GF2m_simple_method EC_GF2m_simple_method_ptr
+#define EC_GROUP_get_curve_GF2m EC_GROUP_get_curve_GF2m_ptr
+#define EC_GROUP_set_curve_GF2m EC_GROUP_set_curve_GF2m_ptr
+#define EC_POINT_get_affine_coordinates_GF2m EC_POINT_get_affine_coordinates_GF2m_ptr
+#define EC_POINT_set_affine_coordinates_GF2m EC_POINT_set_affine_coordinates_GF2m_ptr
+#endif // HAVE_OPENSSL_EC2M
+
+#else // FEATURE_DISTRO_AGNOSTIC_SSL
+
+#define API_EXISTS(fn) true
+
+#endif // FEATURE_DISTRO_AGNOSTIC_SSL
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp
index b5f238e395..5429592e57 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp
@@ -4,8 +4,6 @@
#include "pal_asn1.h"
-#include <openssl/objects.h>
-
static_assert(PAL_NID_undef == NID_undef, "");
static_assert(PAL_NID_X9_62_prime256v1 == NID_X9_62_prime256v1, "");
static_assert(PAL_NID_secp224r1 == NID_secp224r1, "");
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h
index 710282709c..6ec1795d25 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/asn1.h>
+#include "opensslshim.h"
/*
NID values that are used in managed code.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.h
index 570afb71b1..982506e420 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/asn1.h>
+#include "opensslshim.h"
/*
Flags for the 'type' parameter of CryptoNative_DecodeAsn1TypeBytes.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_bignum.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_bignum.h
index 615a550f16..19919c8141 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_bignum.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_bignum.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/bn.h>
+#include "opensslshim.h"
/*
Cleans up and deletes an BIGNUM instance.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_bio.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_bio.h
index f724b59322..6897dc1403 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_bio.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_bio.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/bio.h>
+#include "opensslshim.h"
/*
Creates a new memory-backed BIO instance.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_types.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_types.h
index d61542985f..fb4a0c8603 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_types.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_types.h
@@ -4,8 +4,7 @@
#pragma once
#include "pal_types.h"
-
-#include <openssl/x509.h>
+#include "opensslshim.h"
typedef STACK_OF(X509) X509Stack;
typedef STACK_OF(X509_NAME) X509NameStack;
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp
index 56f14ae246..d9fdedc97c 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp
@@ -4,7 +4,6 @@
#include "pal_dsa.h"
#include "pal_utilities.h"
-#include <openssl/err.h>
extern "C" int32_t CryptoNative_DsaUpRef(DSA* dsa)
{
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h
index 667cc29646..ede7065992 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/dsa.h>
+#include "opensslshim.h"
/*
Shims the DSA_new method.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.cpp
index 512b7b7243..6cc7021004 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.cpp
@@ -2,9 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#include <openssl/ec.h>
-#include <openssl/objects.h>
-#include "pal_crypto_config.h"
#include "pal_ecc_import_export.h"
#include "pal_utilities.h"
@@ -33,7 +30,7 @@ const EC_METHOD* CurveTypeToMethod(ECCurveType curveType)
return EC_GFp_mont_method();
#if HAVE_OPENSSL_EC2M
- if (curveType == ECCurveType::Characteristic2)
+ if (API_EXISTS(EC_GF2m_simple_method) && (curveType == ECCurveType::Characteristic2))
return EC_GF2m_simple_method();
#endif
@@ -93,7 +90,7 @@ extern "C" int32_t CryptoNative_GetECKeyParameters(
goto error;
#if HAVE_OPENSSL_EC2M
- if (curveType == ECCurveType::Characteristic2)
+ if (API_EXISTS(EC_POINT_get_affine_coordinates_GF2m) && (curveType == ECCurveType::Characteristic2))
{
if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, xBn, yBn, nullptr))
goto error;
@@ -221,7 +218,7 @@ extern "C" int32_t CryptoNative_GetECCurveParameters(
// Extract p, a, b
#if HAVE_OPENSSL_EC2M
- if (*curveType == ECCurveType::Characteristic2)
+ if (API_EXISTS(EC_GROUP_get_curve_GF2m) && (*curveType == ECCurveType::Characteristic2))
{
// pBn represents the binary polynomial
if (!EC_GROUP_get_curve_GF2m(group, pBn, aBn, bBn, nullptr))
@@ -238,7 +235,7 @@ extern "C" int32_t CryptoNative_GetECCurveParameters(
// Extract gx and gy
G = const_cast<EC_POINT*>(EC_GROUP_get0_generator(group));
#if HAVE_OPENSSL_EC2M
- if (*curveType == ECCurveType::Characteristic2)
+ if (API_EXISTS(EC_POINT_get_affine_coordinates_GF2m) && (*curveType == ECCurveType::Characteristic2))
{
if (!EC_POINT_get_affine_coordinates_GF2m(group, G, xBn, yBn, NULL))
goto error;
@@ -431,7 +428,7 @@ extern "C" EC_KEY* CryptoNative_EcKeyCreateByExplicitParameters(
bBn = BN_bin2bn(b, bLength, nullptr);
#if HAVE_OPENSSL_EC2M
- if (curveType == ECCurveType::Characteristic2)
+ if (API_EXISTS(EC_GROUP_set_curve_GF2m) && (curveType == ECCurveType::Characteristic2))
{
if (!EC_GROUP_set_curve_GF2m(group, pBn, aBn, bBn, nullptr))
goto error;
@@ -449,7 +446,7 @@ extern "C" EC_KEY* CryptoNative_EcKeyCreateByExplicitParameters(
gyBn = BN_bin2bn(gy, gyLength, nullptr);
#if HAVE_OPENSSL_EC2M
- if (curveType == ECCurveType::Characteristic2)
+ if (API_EXISTS(EC_POINT_set_affine_coordinates_GF2m) && (curveType == ECCurveType::Characteristic2))
{
EC_POINT_set_affine_coordinates_GF2m(group, G, gxBn, gyBn, nullptr);
}
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.h
index baa129e330..b138a080e6 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_ecc_import_export.h
@@ -3,9 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/ecdsa.h>
-#include <openssl/ec.h>
+#include "opensslshim.h"
typedef enum : int32_t {
Unspecified = 0,
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_ecdsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_ecdsa.h
index deb42753a3..13ed17bb29 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_ecdsa.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_ecdsa.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/ecdsa.h>
+#include "opensslshim.h"
/*
Shims the ECDSA_sign method.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.cpp
index 846051649f..9a5a2a3662 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.cpp
@@ -5,7 +5,6 @@
#include "pal_eckey.h"
#include <assert.h>
-#include <openssl/objects.h>
extern "C" void CryptoNative_EcKeyDestroy(EC_KEY* r)
{
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.h
index 8a6833379b..4f180c9007 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_eckey.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/ec.h>
+#include "opensslshim.h"
/*
Cleans up and deletes an EC_KEY instance.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_err.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_err.cpp
index e6e37aea93..8985bc9999 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_err.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_err.cpp
@@ -5,8 +5,6 @@
#include "pal_err.h"
#include "pal_utilities.h"
-#include <openssl/err.h>
-
extern "C" uint64_t CryptoNative_ErrGetError()
{
return ERR_get_error();
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_err.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_err.h
index bb4f25b4e6..7ef05fce5d 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_err.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_err.h
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
#include <stdint.h>
+#include "opensslshim.h"
/*
Shims the ERR_get_error method.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.h
index 4db89c0a40..1e0dc4a141 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.h
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
#include <stdint.h>
-#include <openssl/evp.h>
+#include "opensslshim.h"
/*
Creates and initializes an EVP_MD_CTX with the given args.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.h
index 9311fcad94..fb3a6c750e 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.h
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-#include <openssl/evp.h>
+#include "opensslshim.h"
/*
Creates and initializes an EVP_CIPHER_CTX with the given args.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.h
index fa456f2149..1449fda5b4 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/evp.h>
+#include "opensslshim.h"
/*
Shims the EVP_PKEY_new method.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_dsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_dsa.h
index 563ec2aa06..79835d27ec 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_dsa.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_dsa.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/evp.h>
+#include "opensslshim.h"
/*
Shims the EVP_PKEY_get1_DSA method.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_eckey.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_eckey.h
index 1f4708cb85..0b71546cf8 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_eckey.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_eckey.h
@@ -3,9 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/ec.h>
-#include <openssl/evp.h>
+#include "opensslshim.h"
/*
Shims the EVP_PKEY_get1_EC_KEY method.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h
index 147542e00e..3200a6180e 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/evp.h>
+#include "opensslshim.h"
/*
Shims the EVP_PKEY_get1_RSA method.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp
index cec33dac5a..10eef6809c 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp
@@ -8,7 +8,6 @@
#include <assert.h>
#include <memory>
-#include <openssl/hmac.h>
extern "C" HMAC_CTX* CryptoNative_HmacCreate(const uint8_t* key, int32_t keyLen, const EVP_MD* md)
{
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h
index 2acd7e22e8..131e148c00 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
+#include "opensslshim.h"
// The shim API here is slightly less than 1:1 with underlying API so that:
// * P/Invokes are less chatty
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.cpp
index 6b455f4daa..7e48813e03 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.cpp
@@ -4,8 +4,6 @@
#include "pal_pkcs12.h"
-#include <openssl/err.h>
-
extern "C" PKCS12* CryptoNative_DecodePkcs12(const uint8_t* buf, int32_t len)
{
if (!buf || !len)
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.h
index c582838740..9b9960a1a7 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs12.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_crypto_types.h"
-
-#include <openssl/pkcs12.h>
+#include "opensslshim.h"
/*
Shims the d2i_PKCS12 method and makes it easier to invoke from managed code.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.cpp
index 5ae9146564..718d6ccfb4 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.cpp
@@ -4,8 +4,6 @@
#include "pal_pkcs7.h"
-#include <openssl/pem.h>
-
extern "C" PKCS7* CryptoNative_PemReadBioPkcs7(BIO* bp)
{
return PEM_read_bio_PKCS7(bp, nullptr, nullptr, nullptr);
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.h
index 06f0b02769..e7921c1be4 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_pkcs7.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_crypto_types.h"
-
-#include <openssl/pkcs7.h>
+#include "opensslshim.h"
/*
Reads a PKCS7 instance in PEM format from a BIO.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h
index 2c2536934c..45a4ad6303 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/rsa.h>
+#include "opensslshim.h"
/*
Padding options for RsaPublicEncrypt and RsaPrivateDecrypt.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp
index 2757173042..e6ba23a8be 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp
@@ -3,11 +3,9 @@
// See the LICENSE file in the project root for more information.
#include "pal_ssl.h"
-#include "pal_crypto_config.h"
#include <assert.h>
#include <string.h>
-#include <openssl/err.h>
static_assert(PAL_SSL_ERROR_NONE == SSL_ERROR_NONE, "");
static_assert(PAL_SSL_ERROR_SSL == SSL_ERROR_SSL, "");
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.h
index a1c5352e9d..aaae3901c9 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.h
@@ -3,10 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_crypto_types.h"
-
-#include <openssl/ssl.h>
-#include <openssl/md5.h>
-#include <openssl/sha.h>
+#include "opensslshim.h"
/*
These values should be kept in sync with System.Security.Authentication.SslProtocols.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp
index 72ffb1c9d4..f4a8fd6bb0 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp
@@ -5,8 +5,6 @@
#include "pal_x509.h"
#include <assert.h>
-#include <openssl/pem.h>
-#include <openssl/x509v3.h>
static_assert(PAL_X509_V_OK == X509_V_OK, "");
static_assert(PAL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, "");
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.h
index e2be7a2469..1050cca7b9 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_crypto_types.h"
-
-#include <openssl/x509.h>
+#include "opensslshim.h"
/*
These values should be kept in sync with System.Security.Cryptography.X509Certificates.X509RevocationFlag.
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h
index a2d8f77c86..d542c4b356 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_crypto_types.h"
-
-#include <openssl/x509.h>
+#include "opensslshim.h"
/*
Function:
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp
index ec5da26b28..2132a81836 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp
@@ -5,8 +5,6 @@
#include "pal_x509_root.h"
#include <assert.h>
-#include <openssl/pem.h>
-#include <openssl/x509v3.h>
extern "C" const char* CryptoNative_GetX509RootStorePath()
{
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.h
index 3ab121db64..ef7ce5262b 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.h
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#include "opensslshim.h"
+
/*
Look up the directory in which all certificate files therein are considered
trusted (root or trusted intermediate).
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509ext.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509ext.h
index ee222aa16b..c68d96650c 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509ext.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509ext.h
@@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
#include "pal_types.h"
-
-#include <openssl/x509v3.h>
+#include "opensslshim.h"
/*
Creates an X509_EXTENSION with the given args.
diff --git a/src/Native/Unix/configure.cmake b/src/Native/Unix/configure.cmake
index 1f3d3bdb8f..7c3c0445d8 100644
--- a/src/Native/Unix/configure.cmake
+++ b/src/Native/Unix/configure.cmake
@@ -224,7 +224,17 @@ check_cxx_source_compiles(
#include <sys/sendfile.h>
int main() { int i = sendfile(0, 0, 0, 0); }
"
- HAVE_SENDFILE)
+ HAVE_SENDFILE_4)
+
+check_cxx_source_compiles(
+ "
+ #include <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/uio.h>
+ int main() { int i = sendfile(0, 0, 0, NULL, NULL, 0); }
+ "
+ HAVE_SENDFILE_6)
check_function_exists(
fcopyfile
diff --git a/src/Native/Unix/gen-buildsys-clang.sh b/src/Native/Unix/gen-buildsys-clang.sh
index de8127bae4..de220dc6d2 100755
--- a/src/Native/Unix/gen-buildsys-clang.sh
+++ b/src/Native/Unix/gen-buildsys-clang.sh
@@ -66,7 +66,7 @@ if [[ -n "$CROSSCOMPILE" ]]; then
cmake_extra_defines="$cmake_extra_defines -C $CONFIG_DIR/tryrun.cmake"
cmake_extra_defines="$cmake_extra_defines -DCMAKE_TOOLCHAIN_FILE=$CONFIG_DIR/toolchain.cmake"
fi
-if [ "$build_arch" == "arm-softfp" ]; then
+if [ "$build_arch" == "armel" ]; then
cmake_extra_defines="$cmake_extra_defines -DARM_SOFTFP=1"
fi
diff --git a/src/Native/Unix/verify-so.sh b/src/Native/Unix/verify-so.sh
new file mode 100755
index 0000000000..07a23d6cc4
--- /dev/null
+++ b/src/Native/Unix/verify-so.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+# $1 contains full path to the .so to verify
+# $2 contains message to print when the verification fails
+ldd -r $1 | awk 'BEGIN {count=0} /undefined symbol:/ { if (count==0) {print "Undefined symbol(s) found:"} print " " $3; count++ } END {if (count>0) exit(1)}'
+if [ $? != 0 ]; then
+ echo "$2"
+ exit 1
+fi
diff --git a/src/Native/Windows/FailedLoads/_tools_BinscopeFilter_packages_Newtonsoft.Json.9.0.1_lib_net45_Newtonsoft.Json.txt b/src/Native/Windows/FailedLoads/_tools_BinscopeFilter_packages_Newtonsoft.Json.9.0.1_lib_net45_Newtonsoft.Json.txt
new file mode 100644
index 0000000000..77577df2c7
--- /dev/null
+++ b/src/Native/Windows/FailedLoads/_tools_BinscopeFilter_packages_Newtonsoft.Json.9.0.1_lib_net45_Newtonsoft.Json.txt
Binary files differ
diff --git a/src/Native/Windows/gen-buildsys-win.bat b/src/Native/Windows/gen-buildsys-win.bat
index 91ec4bef04..3200919390 100644
--- a/src/Native/Windows/gen-buildsys-win.bat
+++ b/src/Native/Windows/gen-buildsys-win.bat
@@ -23,7 +23,7 @@ if defined CMakePath goto DoGen
:: Eval the output from probe-win1.ps1
pushd "%__sourceDir%"
-for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy RemoteSigned "& .\probe-win.ps1"') do %%a
+for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy ByPass "& .\probe-win.ps1"') do %%a
popd
:DoGen
diff --git a/src/Native/build-native.sh b/src/Native/build-native.sh
index e4ec1e53e9..4141f6bf3d 100755
--- a/src/Native/build-native.sh
+++ b/src/Native/build-native.sh
@@ -14,6 +14,7 @@ usage()
echo "cross - optional argument to signify cross compilation,"
echo " - will use ROOTFS_DIR environment variable if set."
echo "staticLibLink - Optional argument to statically link any native library."
+ echo "portableLinux - Optional argument to build native libraries portable over GLIBC based Linux distros."
echo "generateversion - Pass this in to get a version on the build output."
echo "cmakeargs - user-settable additional arguments passed to CMake."
exit 1
@@ -120,6 +121,18 @@ __ServerGC=0
__VerboseBuild=false
__ClangMajorVersion=3
__ClangMinorVersion=5
+__StaticLibLink=0
+__PortableLinux=0
+
+CPUName=$(uname -p)
+# Some Linux platforms report unknown for platform, but the arch for machine.
+if [ $CPUName == "unknown" ]; then
+ CPUName=$(uname -m)
+fi
+
+if [ $CPUName == "i686" ]; then
+ __BuildArch=x86
+fi
while :; do
if [ $# -le 0 ]; then
@@ -141,8 +154,8 @@ while :; do
arm)
__BuildArch=arm
;;
- arm-softfp)
- __BuildArch=arm-softfp
+ armel)
+ __BuildArch=armel
;;
arm64)
__BuildArch=arm64
@@ -178,7 +191,10 @@ while :; do
__VerboseBuild=1
;;
staticliblink)
- __CMakeExtraArgs="$__CMakeExtraArgs -DCMAKE_STATIC_LIB_LINK=1"
+ __StaticLibLink=1
+ ;;
+ portablelinux)
+ __PortableLinux=1
;;
generateversion)
__generateversionsource=true
@@ -234,12 +250,10 @@ while :; do
shift
done
+__CMakeExtraArgs="$__CMakeExtraArgs -DFEATURE_DISTRO_AGNOSTIC_SSL=$__PortableLinux"
+__CMakeExtraArgs="$__CMakeExtraArgs -DCMAKE_STATIC_LIB_LINK=$__StaticLibLink"
+
# Set cross build
-CPUName=$(uname -p)
-# Some Linux platforms report unknown for platform, but the arch for machine.
-if [ $CPUName == "unknown" ]; then
- CPUName=$(uname -m)
-fi
case $CPUName in
i686)
if [ $__BuildArch != x86 ]; then
diff --git a/src/Native/pkg/runtime.native.System.IO.Compression/linux/runtime.native.System.IO.Compression.pkgproj b/src/Native/pkg/runtime.native.System.IO.Compression/linux/runtime.native.System.IO.Compression.pkgproj
new file mode 100644
index 0000000000..e216eea606
--- /dev/null
+++ b/src/Native/pkg/runtime.native.System.IO.Compression/linux/runtime.native.System.IO.Compression.pkgproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
+ <!-- only build for x64 -->
+ <PackagePlatforms>x64;</PackagePlatforms>
+ </PropertyGroup>
+ <ItemGroup>
+ <NativeFile Include="$(LinuxNativePath)System.IO.Compression.Native.so">
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
+ </NativeFile>
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.builds b/src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.builds
index 9f944bffd5..9c8f6a1fbe 100644
--- a/src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.builds
+++ b/src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.builds
@@ -1,8 +1,12 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Project Include="runtime.native.System.IO.Compression.pkgproj"/>
+ <Project Include="linux\runtime.native.System.IO.Compression.pkgproj">
+ <OSGroup>linux</OSGroup>
+ <Platform>amd64</Platform>
+ </Project>
<Project Include="rhel\runtime.native.System.IO.Compression.pkgproj">
<OSGroup>rhel.7</OSGroup>
<Platform>amd64</Platform>
@@ -23,14 +27,26 @@
<OSGroup>ubuntu.14.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\14.04\runtime.native.System.IO.Compression.pkgproj">
+ <OSGroup>ubuntu.14.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.04\runtime.native.System.IO.Compression.pkgproj">
<OSGroup>ubuntu.16.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.04\runtime.native.System.IO.Compression.pkgproj">
+ <OSGroup>ubuntu.16.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.10\runtime.native.System.IO.Compression.pkgproj">
<OSGroup>ubuntu.16.10</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.10\runtime.native.System.IO.Compression.pkgproj">
+ <OSGroup>ubuntu.16.10</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="osx\runtime.native.System.IO.Compression.pkgproj">
<OSGroup>osx.10</OSGroup>
<Platform>amd64</Platform>
diff --git a/src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.pkgproj b/src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.pkgproj
index 6796b32de2..5ffbcefeb5 100644
--- a/src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.pkgproj
+++ b/src/Native/pkg/runtime.native.System.IO.Compression/runtime.native.System.IO.Compression.pkgproj
@@ -10,6 +10,9 @@
<File Include="$(PlaceHolderFile)">
<TargetPath>lib/netstandard1.0</TargetPath>
</File>
+ <ProjectReference Include="linux\runtime.native.System.IO.Compression.pkgproj">
+ <Platform>amd64</Platform>
+ </ProjectReference>
<ProjectReference Include="rhel\runtime.native.System.IO.Compression.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -34,9 +37,15 @@
<ProjectReference Include="ubuntu\14.04\runtime.native.System.IO.Compression.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\14.04\runtime.native.System.IO.Compression.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.04\runtime.native.System.IO.Compression.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\16.04\runtime.native.System.IO.Compression.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.10\runtime.native.System.IO.Compression.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -69,4 +78,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/14.04/runtime.native.System.IO.Compression.pkgproj b/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/14.04/runtime.native.System.IO.Compression.pkgproj
index 3e943b5277..459abc9fee 100644
--- a/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/14.04/runtime.native.System.IO.Compression.pkgproj
+++ b/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/14.04/runtime.native.System.IO.Compression.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1404NativePath)System.IO.Compression.Native.so">
diff --git a/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.04/runtime.native.System.IO.Compression.pkgproj b/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.04/runtime.native.System.IO.Compression.pkgproj
index 2cdfdc3614..19e9c8754f 100644
--- a/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.04/runtime.native.System.IO.Compression.pkgproj
+++ b/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.04/runtime.native.System.IO.Compression.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1604NativePath)System.IO.Compression.Native.so">
diff --git a/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.10/runtime.native.System.IO.Compression.pkgproj b/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.10/runtime.native.System.IO.Compression.pkgproj
index 99281da9bc..119c0725cf 100644
--- a/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.10/runtime.native.System.IO.Compression.pkgproj
+++ b/src/Native/pkg/runtime.native.System.IO.Compression/ubuntu/16.10/runtime.native.System.IO.Compression.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1610NativePath)System.IO.Compression.Native.so">
diff --git a/src/Native/pkg/runtime.native.System.Net.Http/linux/runtime.native.System.Net.Http.pkgproj b/src/Native/pkg/runtime.native.System.Net.Http/linux/runtime.native.System.Net.Http.pkgproj
new file mode 100644
index 0000000000..4ed58c1c8e
--- /dev/null
+++ b/src/Native/pkg/runtime.native.System.Net.Http/linux/runtime.native.System.Net.Http.pkgproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
+ <!-- only build for x64 -->
+ <PackagePlatforms>x64;</PackagePlatforms>
+ </PropertyGroup>
+ <ItemGroup>
+ <NativeFile Include="$(LinuxNativePath)System.Net.Http.Native.so">
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
+ </NativeFile>
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.builds b/src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.builds
index c532e811bb..2463e9415d 100644
--- a/src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.builds
+++ b/src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.builds
@@ -1,8 +1,12 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Project Include="runtime.native.System.Net.Http.pkgproj"/>
+ <Project Include="linux\runtime.native.System.Net.Http.pkgproj">
+ <OSGroup>linux</OSGroup>
+ <Platform>amd64</Platform>
+ </Project>
<Project Include="rhel\runtime.native.System.Net.Http.pkgproj">
<OSGroup>rhel.7</OSGroup>
<Platform>amd64</Platform>
@@ -23,14 +27,26 @@
<OSGroup>ubuntu.14.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\14.04\runtime.native.System.Net.Http.pkgproj">
+ <OSGroup>ubuntu.14.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.04\runtime.native.System.Net.Http.pkgproj">
<OSGroup>ubuntu.16.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.04\runtime.native.System.Net.Http.pkgproj">
+ <OSGroup>ubuntu.16.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.10\runtime.native.System.Net.Http.pkgproj">
<OSGroup>ubuntu.16.10</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.10\runtime.native.System.Net.Http.pkgproj">
+ <OSGroup>ubuntu.16.10</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="osx\runtime.native.System.Net.Http.pkgproj">
<OSGroup>osx.10</OSGroup>
<Platform>amd64</Platform>
diff --git a/src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.pkgproj b/src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.pkgproj
index e2fc9474fb..1f090c2a0d 100644
--- a/src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Net.Http/runtime.native.System.Net.Http.pkgproj
@@ -10,6 +10,9 @@
<File Include="$(PlaceHolderFile)">
<TargetPath>lib/netstandard1.0</TargetPath>
</File>
+ <ProjectReference Include="linux\runtime.native.System.Net.Http.pkgproj">
+ <Platform>amd64</Platform>
+ </ProjectReference>
<ProjectReference Include="rhel\runtime.native.System.Net.Http.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -34,9 +37,15 @@
<ProjectReference Include="ubuntu\14.04\runtime.native.System.Net.Http.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\14.04\runtime.native.System.Net.Http.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.04\runtime.native.System.Net.Http.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\16.04\runtime.native.System.Net.Http.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.10\runtime.native.System.Net.Http.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -45,4 +54,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/14.04/runtime.native.System.Net.Http.pkgproj b/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/14.04/runtime.native.System.Net.Http.pkgproj
index 7c2d686349..08322b11e5 100644
--- a/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/14.04/runtime.native.System.Net.Http.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/14.04/runtime.native.System.Net.Http.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1404NativePath)System.Net.Http.Native.so">
diff --git a/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.04/runtime.native.System.Net.Http.pkgproj b/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.04/runtime.native.System.Net.Http.pkgproj
index 7d5921d70a..ee8c01ee41 100644
--- a/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.04/runtime.native.System.Net.Http.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.04/runtime.native.System.Net.Http.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1604NativePath)System.Net.Http.Native.so">
diff --git a/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.10/runtime.native.System.Net.Http.pkgproj b/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.10/runtime.native.System.Net.Http.pkgproj
index 90e2ba2b31..4e95a3efde 100644
--- a/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.10/runtime.native.System.Net.Http.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Net.Http/ubuntu/16.10/runtime.native.System.Net.Http.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1610NativePath)System.Net.Http.Native.so">
diff --git a/src/Native/pkg/runtime.native.System.Net.Security/linux/runtime.native.System.Net.Security.pkgproj b/src/Native/pkg/runtime.native.System.Net.Security/linux/runtime.native.System.Net.Security.pkgproj
new file mode 100644
index 0000000000..2e87d907f8
--- /dev/null
+++ b/src/Native/pkg/runtime.native.System.Net.Security/linux/runtime.native.System.Net.Security.pkgproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
+ <!-- only build for x64 -->
+ <PackagePlatforms>x64;</PackagePlatforms>
+ </PropertyGroup>
+ <ItemGroup>
+ <NativeFile Include="$(LinuxNativePath)\System.Net.Security.Native.so">
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
+ </NativeFile>
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.builds b/src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.builds
index cfe30be802..f6d0d52ab5 100644
--- a/src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.builds
+++ b/src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.builds
@@ -3,6 +3,10 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Project Include="runtime.native.System.Net.Security.pkgproj"/>
+ <Project Include="linux\runtime.native.System.Net.Security.pkgproj">
+ <OSGroup>linux</OSGroup>
+ <Platform>amd64</Platform>
+ </Project>
<Project Include="rhel\runtime.native.System.Net.Security.pkgproj">
<OSGroup>rhel.7</OSGroup>
<Platform>amd64</Platform>
@@ -23,14 +27,26 @@
<OSGroup>ubuntu.14.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\14.04\runtime.native.System.Net.Security.pkgproj">
+ <OSGroup>ubuntu.14.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.04\runtime.native.System.Net.Security.pkgproj">
<OSGroup>ubuntu.16.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.04\runtime.native.System.Net.Security.pkgproj">
+ <OSGroup>ubuntu.16.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.10\runtime.native.System.Net.Security.pkgproj">
<OSGroup>ubuntu.16.10</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.10\runtime.native.System.Net.Security.pkgproj">
+ <OSGroup>ubuntu.16.10</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="osx\runtime.native.System.Net.Security.pkgproj">
<OSGroup>osx.10</OSGroup>
<Platform>amd64</Platform>
diff --git a/src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.pkgproj b/src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.pkgproj
index 28c1ca2070..856b78b74a 100644
--- a/src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Net.Security/runtime.native.System.Net.Security.pkgproj
@@ -10,6 +10,9 @@
<File Include="$(PlaceHolderFile)">
<TargetPath>lib/netstandard1.0</TargetPath>
</File>
+ <ProjectReference Include="linux\runtime.native.System.Net.Security.pkgproj">
+ <Platform>amd64</Platform>
+ </ProjectReference>
<ProjectReference Include="rhel\runtime.native.System.Net.Security.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -34,9 +37,15 @@
<ProjectReference Include="ubuntu\14.04\runtime.native.System.Net.Security.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\14.04\runtime.native.System.Net.Security.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.04\runtime.native.System.Net.Security.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\16.04\runtime.native.System.Net.Security.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.10\runtime.native.System.Net.Security.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -45,4 +54,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/14.04/runtime.native.System.Net.Security.pkgproj b/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/14.04/runtime.native.System.Net.Security.pkgproj
index 06492846d1..a682716ee1 100644
--- a/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/14.04/runtime.native.System.Net.Security.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/14.04/runtime.native.System.Net.Security.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1404NativePath)\System.Net.Security.Native.so">
diff --git a/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.04/runtime.native.System.Net.Security.pkgproj b/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.04/runtime.native.System.Net.Security.pkgproj
index 791bfc755b..ccd0e29b7c 100644
--- a/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.04/runtime.native.System.Net.Security.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.04/runtime.native.System.Net.Security.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1604NativePath)\System.Net.Security.Native.so">
diff --git a/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.10/runtime.native.System.Net.Security.pkgproj b/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.10/runtime.native.System.Net.Security.pkgproj
index 973bb623a6..8c10a1db8f 100644
--- a/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.10/runtime.native.System.Net.Security.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Net.Security/ubuntu/16.10/runtime.native.System.Net.Security.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1610NativePath)\System.Net.Security.Native.so">
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.Apple/osx/runtime.native.System.Security.Cryptography.Apple.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.Apple/osx/runtime.native.System.Security.Cryptography.Apple.pkgproj
index e7c774305b..b54a9fafd2 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.Apple/osx/runtime.native.System.Security.Cryptography.Apple.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.Apple/osx/runtime.native.System.Security.Cryptography.Apple.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>osx.10.10-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>osx.10.10-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(OSXNativePath)System.Security.Cryptography.Native.Apple.dylib">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/alpine/3.4.3/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/alpine/3.4.3/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index 67c95ec7ac..bd26f5300b 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/alpine/3.4.3/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/alpine/3.4.3/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>alpine.3.4.3-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>alpine.3.4.3-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Alpine343NativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/debian/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/debian/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index 591ec548df..93ac6630c7 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/debian/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/debian/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>debian.8-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>debian.8-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(DebianNativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/23/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/23/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index 870bc8bff1..bf4dc62bb5 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/23/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/23/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>fedora.23-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>fedora.23-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Fedora23NativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/24/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/24/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index f32ab7d47a..ff80db6a28 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/24/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/fedora/24/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>fedora.24-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>fedora.24-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Fedora24NativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/linux/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/linux/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
new file mode 100644
index 0000000000..95f30b84fb
--- /dev/null
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/linux/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
+ <!-- only build for x64 -->
+ <PackagePlatforms>x64;</PackagePlatforms>
+ </PropertyGroup>
+ <ItemGroup>
+ <NativeFile Include="$(LinuxNativePath)System.Security.Cryptography.Native.OpenSsl.so">
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
+ </NativeFile>
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/13.2/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/13.2/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index 614a8bd5a4..587070bc26 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/13.2/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/13.2/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>opensuse.13.2-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>opensuse.13.2-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(OpenSuse132NativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/42.1/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/42.1/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index f1658370bb..c46d097cc8 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/42.1/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/opensuse/42.1/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>opensuse.42.1-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>opensuse.42.1-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(OpenSuse421NativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/osx/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/osx/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index c0db73dc2f..319a9d2ea0 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/osx/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/osx/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>osx.10.10-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>osx.10.10-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(OSXNativePath)System.Security.Cryptography.Native.OpenSsl.dylib">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/rhel/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/rhel/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index c1e77c22ce..b31b04dc87 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/rhel/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/rhel/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>rhel.7-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>rhel.7-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(RHELNativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.builds b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.builds
index d5eebd866a..a0a8e719ad 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.builds
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.builds
@@ -1,8 +1,12 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Project Include="runtime.native.System.Security.Cryptography.OpenSsl.pkgproj"/>
+ <Project Include="linux\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
+ <OSGroup>linux</OSGroup>
+ <Platform>amd64</Platform>
+ </Project>
<Project Include="rhel\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
<OSGroup>rhel.7</OSGroup>
<Platform>amd64</Platform>
@@ -23,14 +27,26 @@
<OSGroup>ubuntu.14.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\14.04\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
+ <OSGroup>ubuntu.14.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.04\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
<OSGroup>ubuntu.16.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.04\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
+ <OSGroup>ubuntu.16.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.10\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
<OSGroup>ubuntu.16.10</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.10\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
+ <OSGroup>ubuntu.16.10</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="osx\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
<OSGroup>osx.10</OSGroup>
<Platform>amd64</Platform>
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index c31044ee75..3f57206206 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -10,6 +10,9 @@
<File Include="$(PlaceHolderFile)">
<TargetPath>lib/netstandard1.0</TargetPath>
</File>
+ <ProjectReference Include="linux\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
+ <Platform>amd64</Platform>
+ </ProjectReference>
<ProjectReference Include="rhel\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -34,9 +37,15 @@
<ProjectReference Include="ubuntu\14.04\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\14.04\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.04\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\16.04\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.10\runtime.native.System.Security.Cryptography.OpenSsl.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/14.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/14.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index 526d8ddbe3..546d5524b0 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/14.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/14.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>ubuntu.14.04-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1404NativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index 885b39a1ed..54be6d6209 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.04/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>ubuntu.16.04-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1604NativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.10/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.10/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
index 746095c347..7dcfaaad6f 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.10/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography.OpenSsl/ubuntu/16.10/runtime.native.System.Security.Cryptography.OpenSsl.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>ubuntu.16.10-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1610NativePath)System.Security.Cryptography.Native.OpenSsl.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/alpine/3.4.3/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/alpine/3.4.3/runtime.native.System.Security.Cryptography.pkgproj
index 8440d283a6..78f0003265 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/alpine/3.4.3/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/alpine/3.4.3/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>alpine.3.4.3-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>alpine.3.4.3-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Alpine343NativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/debian/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/debian/runtime.native.System.Security.Cryptography.pkgproj
index 279307e377..1af8550b98 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/debian/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/debian/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>debian.8-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>debian.8-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(DebianNativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/23/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/23/runtime.native.System.Security.Cryptography.pkgproj
index c9f91eb676..2f3f70d25e 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/23/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/23/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>fedora.23-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>fedora.23-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Fedora23NativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/24/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/24/runtime.native.System.Security.Cryptography.pkgproj
index 36d595d0ee..e0d1fec93a 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/24/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/fedora/24/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>fedora.24-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>fedora.24-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Fedora24NativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/linux/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/linux/runtime.native.System.Security.Cryptography.pkgproj
new file mode 100644
index 0000000000..4664913a63
--- /dev/null
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/linux/runtime.native.System.Security.Cryptography.pkgproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
+ <!-- only build for x64 -->
+ <PackagePlatforms>x64;</PackagePlatforms>
+ </PropertyGroup>
+ <ItemGroup>
+ <NativeFile Include="$(LinuxNativePath)System.Security.Cryptography.Native.so">
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
+ </NativeFile>
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/13.2/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/13.2/runtime.native.System.Security.Cryptography.pkgproj
index 40de31f530..daa7a1cfbf 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/13.2/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/13.2/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>opensuse.13.2-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>opensuse.13.2-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(OpenSuse132NativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/42.1/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/42.1/runtime.native.System.Security.Cryptography.pkgproj
index ac6f0f4516..7f9b7484e2 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/42.1/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/opensuse/42.1/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>opensuse.42.1-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>opensuse.42.1-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(OpenSuse421NativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/osx/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/osx/runtime.native.System.Security.Cryptography.pkgproj
index ccd280993c..b54bf01159 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/osx/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/osx/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>osx.10.10-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>osx.10.10-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(OSXNativePath)System.Security.Cryptography.Native.dylib">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/rhel/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/rhel/runtime.native.System.Security.Cryptography.pkgproj
index 5be77e534b..c12bce5030 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/rhel/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/rhel/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>rhel.7-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>rhel.7-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
<PackagePlatforms>x64;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(RHELNativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.builds b/src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.builds
index dcca35c0d8..ba8760aaea 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.builds
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.builds
@@ -1,8 +1,12 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Project Include="runtime.native.System.Security.Cryptography.pkgproj"/>
+ <Project Include="linux\runtime.native.System.Security.Cryptography.pkgproj">
+ <OSGroup>linux</OSGroup>
+ <Platform>amd64</Platform>
+ </Project>
<Project Include="rhel\runtime.native.System.Security.Cryptography.pkgproj">
<OSGroup>rhel.7</OSGroup>
<Platform>amd64</Platform>
@@ -23,14 +27,26 @@
<OSGroup>ubuntu.14.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\14.04\runtime.native.System.Security.Cryptography.pkgproj">
+ <OSGroup>ubuntu.14.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.04\runtime.native.System.Security.Cryptography.pkgproj">
<OSGroup>ubuntu.16.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.04\runtime.native.System.Security.Cryptography.pkgproj">
+ <OSGroup>ubuntu.16.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.10\runtime.native.System.Security.Cryptography.pkgproj">
<OSGroup>ubuntu.16.10</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.10\runtime.native.System.Security.Cryptography.pkgproj">
+ <OSGroup>ubuntu.16.10</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="osx\runtime.native.System.Security.Cryptography.pkgproj">
<OSGroup>osx.10</OSGroup>
<Platform>amd64</Platform>
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.pkgproj
index c5a3dd8a59..fb003be2e2 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/runtime.native.System.Security.Cryptography.pkgproj
@@ -10,6 +10,9 @@
<File Include="$(PlaceHolderFile)">
<TargetPath>lib/netstandard1.0</TargetPath>
</File>
+ <ProjectReference Include="linux\runtime.native.System.Security.Cryptography.pkgproj">
+ <Platform>amd64</Platform>
+ </ProjectReference>
<ProjectReference Include="rhel\runtime.native.System.Security.Cryptography.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -34,9 +37,15 @@
<ProjectReference Include="ubuntu\14.04\runtime.native.System.Security.Cryptography.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\14.04\runtime.native.System.Security.Cryptography.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.04\runtime.native.System.Security.Cryptography.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\16.04\runtime.native.System.Security.Cryptography.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.10\runtime.native.System.Security.Cryptography.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -45,4 +54,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/14.04/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/14.04/runtime.native.System.Security.Cryptography.pkgproj
index 720c0e7103..04585edc99 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/14.04/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/14.04/runtime.native.System.Security.Cryptography.pkgproj
@@ -1,16 +1,15 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>ubuntu.14.04-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1404NativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.04/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.04/runtime.native.System.Security.Cryptography.pkgproj
index a2ff301e43..700e91d59a 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.04/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.04/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>ubuntu.16.04-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1604NativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.10/runtime.native.System.Security.Cryptography.pkgproj b/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.10/runtime.native.System.Security.Cryptography.pkgproj
index 51aabd61cb..91975f6362 100644
--- a/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.10/runtime.native.System.Security.Cryptography.pkgproj
+++ b/src/Native/pkg/runtime.native.System.Security.Cryptography/ubuntu/16.10/runtime.native.System.Security.Cryptography.pkgproj
@@ -2,14 +2,13 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <PackageRid>ubuntu.16.10-$(PackagePlatform)</PackageRid>
- <IdPrefix>runtime.$(PackageRid).</IdPrefix>
+ <PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1610NativePath)System.Security.Cryptography.Native.so">
- <TargetPath>runtimes/$(PackageRid)/native</TargetPath>
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
</NativeFile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/Native/pkg/runtime.native.System/linux/runtime.native.System.pkgproj b/src/Native/pkg/runtime.native.System/linux/runtime.native.System.pkgproj
new file mode 100644
index 0000000000..47bc5ec283
--- /dev/null
+++ b/src/Native/pkg/runtime.native.System/linux/runtime.native.System.pkgproj
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
+ <!-- only build for x64 -->
+ <PackagePlatforms>x64;</PackagePlatforms>
+ </PropertyGroup>
+ <ItemGroup>
+ <NativeFile Include="$(LinuxNativePath)System.Native.so">
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
+ </NativeFile>
+ <File Include="$(LinuxNativePath)System.Native.a">
+ <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
+ </File>
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/Native/pkg/runtime.native.System/runtime.native.System.builds b/src/Native/pkg/runtime.native.System/runtime.native.System.builds
index ddeedacd44..c1e25bc130 100644
--- a/src/Native/pkg/runtime.native.System/runtime.native.System.builds
+++ b/src/Native/pkg/runtime.native.System/runtime.native.System.builds
@@ -3,6 +3,10 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Project Include="runtime.native.System.pkgproj"/>
+ <Project Include="linux\runtime.native.System.pkgproj">
+ <OSGroup>linux</OSGroup>
+ <Platform>amd64</Platform>
+ </Project>
<Project Include="rhel\runtime.native.System.pkgproj">
<OSGroup>rhel.7</OSGroup>
<Platform>amd64</Platform>
@@ -23,14 +27,26 @@
<OSGroup>ubuntu.14.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\14.04\runtime.native.System.pkgproj">
+ <OSGroup>ubuntu.14.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.04\runtime.native.System.pkgproj">
<OSGroup>ubuntu.16.04</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.04\runtime.native.System.pkgproj">
+ <OSGroup>ubuntu.16.04</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="ubuntu\16.10\runtime.native.System.pkgproj">
<OSGroup>ubuntu.16.10</OSGroup>
<Platform>amd64</Platform>
</Project>
+ <Project Include="ubuntu\16.10\runtime.native.System.pkgproj">
+ <OSGroup>ubuntu.16.10</OSGroup>
+ <Platform>arm</Platform>
+ </Project>
<Project Include="osx\runtime.native.System.pkgproj">
<OSGroup>osx.10</OSGroup>
<Platform>amd64</Platform>
diff --git a/src/Native/pkg/runtime.native.System/runtime.native.System.pkgproj b/src/Native/pkg/runtime.native.System/runtime.native.System.pkgproj
index cf805c1cd8..c319829cac 100644
--- a/src/Native/pkg/runtime.native.System/runtime.native.System.pkgproj
+++ b/src/Native/pkg/runtime.native.System/runtime.native.System.pkgproj
@@ -10,6 +10,9 @@
<File Include="$(PlaceHolderFile)">
<TargetPath>lib/netstandard1.0</TargetPath>
</File>
+ <ProjectReference Include="linux\runtime.native.System.pkgproj">
+ <Platform>amd64</Platform>
+ </ProjectReference>
<ProjectReference Include="rhel\runtime.native.System.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -34,9 +37,15 @@
<ProjectReference Include="ubuntu\14.04\runtime.native.System.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\14.04\runtime.native.System.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.04\runtime.native.System.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
+ <ProjectReference Include="ubuntu\16.04\runtime.native.System.pkgproj">
+ <Platform>arm</Platform>
+ </ProjectReference>
<ProjectReference Include="ubuntu\16.10\runtime.native.System.pkgproj">
<Platform>amd64</Platform>
</ProjectReference>
@@ -45,4 +54,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/Native/pkg/runtime.native.System/ubuntu/14.04/runtime.native.System.pkgproj b/src/Native/pkg/runtime.native.System/ubuntu/14.04/runtime.native.System.pkgproj
index 59f55c16a4..3ed7b31e66 100644
--- a/src/Native/pkg/runtime.native.System/ubuntu/14.04/runtime.native.System.pkgproj
+++ b/src/Native/pkg/runtime.native.System/ubuntu/14.04/runtime.native.System.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1404NativePath)System.Native.so">
diff --git a/src/Native/pkg/runtime.native.System/ubuntu/16.04/runtime.native.System.pkgproj b/src/Native/pkg/runtime.native.System/ubuntu/16.04/runtime.native.System.pkgproj
index b65cd6fbaf..c2ea60698f 100644
--- a/src/Native/pkg/runtime.native.System/ubuntu/16.04/runtime.native.System.pkgproj
+++ b/src/Native/pkg/runtime.native.System/ubuntu/16.04/runtime.native.System.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1604NativePath)System.Native.so">
diff --git a/src/Native/pkg/runtime.native.System/ubuntu/16.10/runtime.native.System.pkgproj b/src/Native/pkg/runtime.native.System/ubuntu/16.10/runtime.native.System.pkgproj
index 7c84ddf443..e4190632ed 100644
--- a/src/Native/pkg/runtime.native.System/ubuntu/16.10/runtime.native.System.pkgproj
+++ b/src/Native/pkg/runtime.native.System/ubuntu/16.10/runtime.native.System.pkgproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
<!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
+ <PackagePlatforms>x64;arm;</PackagePlatforms>
</PropertyGroup>
<ItemGroup>
<NativeFile Include="$(Ubuntu1610NativePath)System.Native.so">
diff --git a/src/System.Buffers/src/System/Buffers/ArrayPoolEventSource.cs b/src/System.Buffers/src/System/Buffers/ArrayPoolEventSource.cs
index 9482744144..908229a832 100644
--- a/src/System.Buffers/src/System/Buffers/ArrayPoolEventSource.cs
+++ b/src/System.Buffers/src/System/Buffers/ArrayPoolEventSource.cs
@@ -9,7 +9,7 @@ namespace System.Buffers
[EventSource(Name = "System.Buffers.ArrayPoolEventSource")]
internal sealed class ArrayPoolEventSource : EventSource
{
- internal readonly static ArrayPoolEventSource Log = new ArrayPoolEventSource();
+ internal static readonly ArrayPoolEventSource Log = new ArrayPoolEventSource();
/// <summary>The reason for a BufferAllocated event.</summary>
internal enum BufferAllocatedReason : int
diff --git a/src/System.CodeDom/pkg/System.CodeDom.pkgproj b/src/System.CodeDom/pkg/System.CodeDom.pkgproj
index 1c2595f82a..97f66ff3b6 100644
--- a/src/System.CodeDom/pkg/System.CodeDom.pkgproj
+++ b/src/System.CodeDom/pkg/System.CodeDom.pkgproj
@@ -4,7 +4,7 @@
<ItemGroup>
<ProjectReference Include="..\ref\System.CodeDom.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.CodeDom.builds" />
</ItemGroup>
diff --git a/src/System.CodeDom/src/Configurations.props b/src/System.CodeDom/src/Configurations.props
index f20b2fb8af..32bba83db7 100644
--- a/src/System.CodeDom/src/Configurations.props
+++ b/src/System.CodeDom/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463;
+ net461;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.CodeDom/src/System.CodeDom.csproj b/src/System.CodeDom/src/System.CodeDom.csproj
index f1f3344b96..5067732408 100644
--- a/src/System.CodeDom/src/System.CodeDom.csproj
+++ b/src/System.CodeDom/src/System.CodeDom.csproj
@@ -4,13 +4,13 @@
<PropertyGroup>
<ProjectGuid>{53D09AF4-0C13-4197-B8AD-9746F0374E88}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net463'">true</IsPartialFacadeAssembly>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net461'">true</IsPartialFacadeAssembly>
</PropertyGroup>
<!-- Default configurations to help VS understand the options -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="Microsoft\CSharp\CSharpCodeGenerator.cs" />
<Compile Include="Microsoft\CSharp\CSharpCodeProvider.cs" />
@@ -129,7 +129,7 @@
<Compile Include="System\Collections\Specialized\FixedStringLookup.cs" />
<Compile Include="$(CommonPath)\System\CSharpHelpers.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="System" />
</ItemGroup>
<ItemGroup>
diff --git a/src/System.CodeDom/src/System/CodeDom/Compiler/CodeDomProvider.cs b/src/System.CodeDom/src/System/CodeDom/Compiler/CodeDomProvider.cs
index 27aa60ca3c..b1d14061cc 100644
--- a/src/System.CodeDom/src/System/CodeDom/Compiler/CodeDomProvider.cs
+++ b/src/System.CodeDom/src/System/CodeDom/Compiler/CodeDomProvider.cs
@@ -13,9 +13,9 @@ namespace System.CodeDom.Compiler
{
public abstract class CodeDomProvider // TODO: Inherit Component
{
- private readonly static Dictionary<string, CompilerInfo> s_compilerLanguages = new Dictionary<string, CompilerInfo>(StringComparer.OrdinalIgnoreCase);
- private readonly static Dictionary<string, CompilerInfo> s_compilerExtensions = new Dictionary<string, CompilerInfo>(StringComparer.OrdinalIgnoreCase);
- private readonly static List<CompilerInfo> s_allCompilerInfo = new List<CompilerInfo>();
+ private static readonly Dictionary<string, CompilerInfo> s_compilerLanguages = new Dictionary<string, CompilerInfo>(StringComparer.OrdinalIgnoreCase);
+ private static readonly Dictionary<string, CompilerInfo> s_compilerExtensions = new Dictionary<string, CompilerInfo>(StringComparer.OrdinalIgnoreCase);
+ private static readonly List<CompilerInfo> s_allCompilerInfo = new List<CompilerInfo>();
static CodeDomProvider()
{
diff --git a/src/System.CodeDom/tests/CodeCollections/CodeNamespaceImportCollectionTests.cs b/src/System.CodeDom/tests/CodeCollections/CodeNamespaceImportCollectionTests.cs
index f307dee73c..f4076f033e 100644
--- a/src/System.CodeDom/tests/CodeCollections/CodeNamespaceImportCollectionTests.cs
+++ b/src/System.CodeDom/tests/CodeCollections/CodeNamespaceImportCollectionTests.cs
@@ -17,6 +17,7 @@ namespace System.CodeDom.Tests
protected override bool NullAllowed => false;
protected override bool Enumerator_Current_UndefinedOperation_Throws => true;
+ protected override bool IList_CurrentAfterAdd_Throws => false;
protected override bool ICollection_NonGeneric_HasNullSyncRoot => true;
protected override Type ICollection_NonGeneric_CopyTo_NonZeroLowerBound_ThrowType => typeof(ArgumentOutOfRangeException);
diff --git a/src/System.Collections.Concurrent/pkg/System.Collections.Concurrent.pkgproj b/src/System.Collections.Concurrent/pkg/System.Collections.Concurrent.pkgproj
index f714f3e28d..26019957ce 100644
--- a/src/System.Collections.Concurrent/pkg/System.Collections.Concurrent.pkgproj
+++ b/src/System.Collections.Concurrent/pkg/System.Collections.Concurrent.pkgproj
@@ -2,8 +2,8 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
- <ProjectReference Include="..\ref\System.Collections.Concurrent.csproj">
- <SupportedFramework>net46;netcore50;netcoreapp1.0;$(AllXamarinFrameworks)</SupportedFramework>
+ <ProjectReference Include="..\ref\System.Collections.Concurrent.builds">
+ <SupportedFramework>netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Collections.Concurrent.builds" />
<InboxOnTargetFramework Include="MonoAndroid10" />
diff --git a/src/System.Collections.Concurrent/ref/Configurations.props b/src/System.Collections.Concurrent/ref/Configurations.props
new file mode 100644
index 0000000000..84eaf1100d
--- /dev/null
+++ b/src/System.Collections.Concurrent/ref/Configurations.props
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <BuildConfigurations>
+ netstandard;
+ netcoreapp;
+ </BuildConfigurations>
+ </PropertyGroup>
+</Project>
diff --git a/src/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs b/src/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs
index c95f11c95b..5ada3f8177 100644
--- a/src/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs
+++ b/src/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs
@@ -99,11 +99,17 @@ namespace System.Collections.Concurrent
public System.Collections.Generic.ICollection<TValue> Values { get { throw null; } }
public TValue AddOrUpdate(TKey key, TValue addValue, System.Func<TKey, TValue, TValue> updateValueFactory) { throw null; }
public TValue AddOrUpdate(TKey key, System.Func<TKey, TValue> addValueFactory, System.Func<TKey, TValue, TValue> updateValueFactory) { throw null; }
+#if netcoreapp11
+ public TValue AddOrUpdate<TArg>(TKey key, System.Func<TKey, TArg, TValue> addValueFactory, System.Func<TKey, TValue, TArg, TValue> updateValueFactory, TArg factoryArgument) { throw null; }
+#endif
public void Clear() { }
public bool ContainsKey(TKey key) { throw null; }
public System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<TKey, TValue>> GetEnumerator() { throw null; }
public TValue GetOrAdd(TKey key, TValue value) { throw null; }
public TValue GetOrAdd(TKey key, System.Func<TKey, TValue> valueFactory) { throw null; }
+#if netcoreapp11
+ public TValue GetOrAdd<TArg>(TKey key, System.Func<TKey, TArg, TValue> valueFactory, TArg factoryArgument) { throw null; }
+#endif
void System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey, TValue>>.Add(System.Collections.Generic.KeyValuePair<TKey, TValue> keyValuePair) { }
bool System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey, TValue>>.Contains(System.Collections.Generic.KeyValuePair<TKey, TValue> keyValuePair) { throw null; }
void System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey, TValue>>.CopyTo(System.Collections.Generic.KeyValuePair<TKey, TValue>[] array, int index) { }
diff --git a/src/System.Collections.Concurrent/ref/System.Collections.Concurrent.csproj b/src/System.Collections.Concurrent/ref/System.Collections.Concurrent.csproj
index b5beb722a9..0ac08d61ea 100644
--- a/src/System.Collections.Concurrent/ref/System.Collections.Concurrent.csproj
+++ b/src/System.Collections.Concurrent/ref/System.Collections.Concurrent.csproj
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <DefineConstants Condition="'$(TargetGroup)'==''">$(DefineConstants);netcoreapp11</DefineConstants>
+ </PropertyGroup>
<ItemGroup>
<Compile Include="System.Collections.Concurrent.cs" />
</ItemGroup>
diff --git a/src/System.Collections.Concurrent/src/Resources/Strings.resx b/src/System.Collections.Concurrent/src/Resources/Strings.resx
index 06b6918d55..34a9d3643b 100644
--- a/src/System.Collections.Concurrent/src/Resources/Strings.resx
+++ b/src/System.Collections.Concurrent/src/Resources/Strings.resx
@@ -144,7 +144,7 @@
<data name="BlockingCollection_CopyTo_NonNegative" xml:space="preserve">
<value>The index argument must be greater than or equal zero.</value>
</data>
- <data name="BlockingCollection_CopyTo_TooManyElems" xml:space="preserve">
+ <data name="Collection_CopyTo_TooManyElems" xml:space="preserve">
<value>The number of elements in the collection is greater than the available space from index to the end of the destination array.</value>
</data>
<data name="BlockingCollection_ctor_BoundedCapacityRange" xml:space="preserve">
@@ -183,7 +183,7 @@
<data name="ConcurrentBag_CopyTo_ArgumentNullException" xml:space="preserve">
<value>The array argument is null.</value>
</data>
- <data name="ConcurrentBag_CopyTo_ArgumentOutOfRangeException" xml:space="preserve">
+ <data name="Collection_CopyTo_ArgumentOutOfRangeException" xml:space="preserve">
<value>The index argument must be greater than or equal zero.</value>
</data>
<data name="ConcurrentCollection_SyncRoot_NotSupported" xml:space="preserve">
@@ -237,4 +237,7 @@
<data name="PartitionerStatic_CurrentCalledBeforeMoveNext" xml:space="preserve">
<value>MoveNext must be called at least once before calling Current.</value>
</data>
+ <data name="ConcurrentBag_Enumerator_EnumerationNotStartedOrAlreadyFinished" xml:space="preserve">
+ <value>Enumeration has either not started or has already finished.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/System.Collections.Concurrent/src/System.Collections.Concurrent.csproj b/src/System.Collections.Concurrent/src/System.Collections.Concurrent.csproj
index 01d6c9e637..200dc03479 100644
--- a/src/System.Collections.Concurrent/src/System.Collections.Concurrent.csproj
+++ b/src/System.Collections.Concurrent/src/System.Collections.Concurrent.csproj
@@ -5,7 +5,6 @@
<ProjectGuid>{96AA2060-C846-4E56-9509-E8CB9C114C8F}</ProjectGuid>
<AssemblyName>System.Collections.Concurrent</AssemblyName>
<RootNamespace>System.Collections.Concurrent</RootNamespace>
- <DefineConstants>FEATURE_TRACING</DefineConstants>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
diff --git a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs
index 0a1fc25920..abfbfb95cd 100644
--- a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs
+++ b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs
@@ -1617,7 +1617,7 @@ nameof(boundedCapacity), boundedCapacity,
}
catch (ArgumentException)
{
- throw new ArgumentException(SR.BlockingCollection_CopyTo_TooManyElems, nameof(index));
+ throw new ArgumentException(SR.Collection_CopyTo_TooManyElems, nameof(index));
}
catch (RankException)
{
diff --git a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs
index cc565678e8..a68317c7c7 100644
--- a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs
+++ b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs
@@ -14,10 +14,6 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-using System;
-using System.Collections.Generic;
-using System.Text;
-#if FEATURE_TRACING
using System.Diagnostics.Tracing;
namespace System.Collections.Concurrent
@@ -118,4 +114,3 @@ namespace System.Collections.Concurrent
}
}
}
-#endif // FEATURE_TRACING
diff --git a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentBag.cs b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentBag.cs
index 9091423334..0e77844b38 100644
--- a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentBag.cs
+++ b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentBag.cs
@@ -2,23 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-// ConcurrentBag.cs
-//
-// An unordered collection that allows duplicates and that provides add and get operations.
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
using System.Collections.Generic;
using System.Diagnostics;
-using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Threading;
namespace System.Collections.Concurrent
{
/// <summary>
- /// Represents an thread-safe, unordered collection of objects.
+ /// Represents a thread-safe, unordered collection of objects.
/// </summary>
/// <typeparam name="T">Specifies the type of elements in the bag.</typeparam>
/// <remarks>
@@ -41,29 +33,19 @@ namespace System.Collections.Concurrent
[Serializable]
public class ConcurrentBag<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>
{
- // ThreadLocalList object that contains the data per thread
- [NonSerialized]
- private ThreadLocal<ThreadLocalList> _locals;
-
- // This head and tail pointers points to the first and last local lists, to allow enumeration on the thread locals objects
+ /// <summary>The per-bag, per-thread work-stealing queues.</summary>
[NonSerialized]
- private volatile ThreadLocalList _headList, _tailList;
-
- // A flag used to tell the operations thread that it must synchronize the operation, this flag is set/unset within
- // GlobalListsLock lock
+ private ThreadLocal<WorkStealingQueue> _locals;
+ /// <summary>The head work stealing queue in a linked list of queues.</summary>
[NonSerialized]
- private bool _needSync;
-
- // Used for custom serialization.
+ private volatile WorkStealingQueue _workStealingQueues;
+ /// <summary>Temporary storage of the bag's contents used during serialization.</summary>
private T[] _serializationArray;
- /// <summary>
- /// Initializes a new instance of the <see cref="ConcurrentBag{T}"/>
- /// class.
- /// </summary>
+ /// <summary>Initializes a new instance of the <see cref="ConcurrentBag{T}"/> class.</summary>
public ConcurrentBag()
{
- Initialize(null);
+ _locals = new ThreadLocal<WorkStealingQueue>();
}
/// <summary>
@@ -80,26 +62,13 @@ namespace System.Collections.Concurrent
{
throw new ArgumentNullException(nameof(collection), SR.ConcurrentBag_Ctor_ArgumentNullException);
}
- Initialize(collection);
- }
+ _locals = new ThreadLocal<WorkStealingQueue>();
- /// <summary>
- /// Local helper function to initialize a new bag object
- /// </summary>
- /// <param name="collection">An enumeration containing items with which to initialize this bag.</param>
- private void Initialize(IEnumerable<T> collection)
- {
- _locals = new ThreadLocal<ThreadLocalList>();
-
- // Copy the collection to the bag
- if (collection != null)
+ WorkStealingQueue queue = GetCurrentThreadWorkStealingQueue(forceCreate: true);
+ foreach (T item in collection)
{
- ThreadLocalList list = GetThreadList(true);
- foreach (T item in collection)
- {
- list.Add(item, false);
- }
+ queue.LocalPush(item);
}
}
@@ -118,21 +87,21 @@ namespace System.Collections.Concurrent
_serializationArray = null;
}
- /// <summary>Construct the stack from a previously seiralized one.</summary>
+ /// <summary>Construct the stack from a previously serialized one.</summary>
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
- _locals = new ThreadLocal<ThreadLocalList>();
+ Debug.Assert(_locals == null);
+ _locals = new ThreadLocal<WorkStealingQueue>();
- ThreadLocalList list = GetThreadList(true);
+ WorkStealingQueue queue = GetCurrentThreadWorkStealingQueue(forceCreate: true);
foreach (T item in _serializationArray)
{
- list.Add(item, false);
+ queue.LocalPush(item);
}
- _headList = list;
- _tailList = list;
-
_serializationArray = null;
+
+ _workStealingQueues = queue;
}
/// <summary>
@@ -141,46 +110,7 @@ namespace System.Collections.Concurrent
/// <param name="item">The object to be added to the
/// <see cref="ConcurrentBag{T}"/>. The value can be a null reference
/// (Nothing in Visual Basic) for reference types.</param>
- public void Add(T item)
- {
- // Get the local list for that thread, create a new list if this thread doesn't exist
- //(first time to call add)
- ThreadLocalList list = GetThreadList(true);
- AddInternal(list, item);
- }
-
- /// <summary>
- /// </summary>
- /// <param name="list"></param>
- /// <param name="item"></param>
- private void AddInternal(ThreadLocalList list, T item)
- {
- bool lockTaken = false;
- try
- {
-#pragma warning disable 0420
- Interlocked.Exchange(ref list._currentOp, (int)ListOperation.Add);
-#pragma warning restore 0420
- //Synchronization cases:
- // if the list count is less than two to avoid conflict with any stealing thread
- // if _needSync is set, this means there is a thread that needs to freeze the bag
- if (list.Count < 2 || _needSync)
- {
- // reset it back to zero to avoid deadlock with stealing thread
- list._currentOp = (int)ListOperation.None;
- Monitor.Enter(list, ref lockTaken);
- }
- list.Add(item, lockTaken);
- }
- finally
- {
- list._currentOp = (int)ListOperation.None;
- if (lockTaken)
- {
- Monitor.Exit(list);
- }
- }
- }
+ public void Add(T item) => GetCurrentThreadWorkStealingQueue(forceCreate: true).LocalPush(item);
/// <summary>
/// Attempts to add an object to the <see cref="ConcurrentBag{T}"/>.
@@ -196,8 +126,7 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Attempts to remove and return an object from the <see
- /// cref="ConcurrentBag{T}"/>.
+ /// Attempts to remove and return an object from the <see cref="ConcurrentBag{T}"/>.
/// </summary>
/// <param name="result">When this method returns, <paramref name="result"/> contains the object
/// removed from the <see cref="ConcurrentBag{T}"/> or the default value
@@ -205,12 +134,12 @@ namespace System.Collections.Concurrent
/// <returns>true if an object was removed successfully; otherwise, false.</returns>
public bool TryTake(out T result)
{
- return TryTakeOrPeek(out result, true);
+ WorkStealingQueue queue = GetCurrentThreadWorkStealingQueue(forceCreate: false);
+ return (queue != null && queue.TryLocalPop(out result)) || TrySteal(out result, take: true);
}
/// <summary>
- /// Attempts to return an object from the <see cref="ConcurrentBag{T}"/>
- /// without removing it.
+ /// Attempts to return an object from the <see cref="ConcurrentBag{T}"/> without removing it.
/// </summary>
/// <param name="result">When this method returns, <paramref name="result"/> contains an object from
/// the <see cref="ConcurrentBag{T}"/> or the default value of
@@ -218,236 +147,106 @@ namespace System.Collections.Concurrent
/// <returns>true if and object was returned successfully; otherwise, false.</returns>
public bool TryPeek(out T result)
{
- return TryTakeOrPeek(out result, false);
+ WorkStealingQueue queue = GetCurrentThreadWorkStealingQueue(forceCreate: false);
+ return (queue != null && queue.TryLocalPeek(out result)) || TrySteal(out result, take: false);
}
- /// <summary>
- /// Local helper function to Take or Peek an item from the bag
- /// </summary>
- /// <param name="result">To receive the item retrieved from the bag</param>
- /// <param name="take">True means Take operation, false means Peek operation</param>
- /// <returns>True if succeeded, false otherwise</returns>
- private bool TryTakeOrPeek(out T result, bool take)
+ /// <summary>Gets the work-stealing queue data structure for the current thread.</summary>
+ /// <param name="forceCreate">Whether to create a new queue if this thread doesn't have one.</param>
+ /// <returns>The local queue object, or null if the thread doesn't have one.</returns>
+ private WorkStealingQueue GetCurrentThreadWorkStealingQueue(bool forceCreate) =>
+ _locals.Value ??
+ (forceCreate ? CreateWorkStealingQueueForCurrentThread() : null);
+
+ private WorkStealingQueue CreateWorkStealingQueueForCurrentThread()
{
- // Get the local list for that thread, return null if the thread doesn't exit
- //(this thread never add before)
- ThreadLocalList list = GetThreadList(false);
- if (list == null || list.Count == 0)
+ lock (GlobalQueuesLock) // necessary to update _workStealingQueues, so as to synchronize with freezing operations
{
- return Steal(out result, take);
- }
+ WorkStealingQueue head = _workStealingQueues;
- bool lockTaken = false;
- try
- {
- if (take) // Take operation
+ WorkStealingQueue queue = head != null ? GetUnownedWorkStealingQueue() : null;
+ if (queue == null)
{
-#pragma warning disable 0420
- Interlocked.Exchange(ref list._currentOp, (int)ListOperation.Take);
-#pragma warning restore 0420
- //Synchronization cases:
- // if the list count is less than or equal two to avoid conflict with any stealing thread
- // if _needSync is set, this means there is a thread that needs to freeze the bag
- if (list.Count <= 2 || _needSync)
- {
- // reset it back to zero to avoid deadlock with stealing thread
- list._currentOp = (int)ListOperation.None;
- Monitor.Enter(list, ref lockTaken);
-
- // Double check the count and steal if it became empty
- if (list.Count == 0)
- {
- // Release the lock before stealing
- if (lockTaken)
- {
- try { }
- finally
- {
- lockTaken = false; // reset lockTaken to avoid calling Monitor.Exit again in the finally block
- Monitor.Exit(list);
- }
- }
- return Steal(out result, true);
- }
- }
- list.Remove(out result);
+ _workStealingQueues = queue = new WorkStealingQueue(head);
}
- else
- {
- if (!list.Peek(out result))
- {
- return Steal(out result, false);
- }
- }
- }
- finally
- {
- list._currentOp = (int)ListOperation.None;
- if (lockTaken)
- {
- Monitor.Exit(list);
- }
- }
- return true;
- }
-
-
- /// <summary>
- /// Local helper function to retrieve a thread local list by a thread object
- /// </summary>
- /// <param name="forceCreate">Create a new list if the thread does not exist</param>
- /// <returns>The local list object</returns>
- private ThreadLocalList GetThreadList(bool forceCreate)
- {
- ThreadLocalList list = _locals.Value;
+ _locals.Value = queue;
- if (list != null)
- {
- return list;
- }
- else if (forceCreate)
- {
- // Acquire the lock to update the _tailList pointer
- lock (GlobalListsLock)
- {
- if (_headList == null)
- {
- list = new ThreadLocalList(Environment.CurrentManagedThreadId);
- _headList = list;
- _tailList = list;
- }
- else
- {
- list = GetUnownedList();
- if (list == null)
- {
- list = new ThreadLocalList(Environment.CurrentManagedThreadId);
- _tailList._nextList = list;
- _tailList = list;
- }
- }
- _locals.Value = list;
- }
- }
- else
- {
- return null;
+ return queue;
}
- Debug.Assert(list != null);
- return list;
}
/// <summary>
- /// Try to reuse an unowned list if exist
- /// unowned lists are the lists that their owner threads are aborted or terminated
- /// this is workaround to avoid memory leaks.
+ /// Try to reuse an unowned queue. If a thread interacts with the bag and then exits,
+ /// the bag purposefully retains its queue, as it contains data associated with the bag.
/// </summary>
- /// <returns>The list object, null if all lists are owned</returns>
- private ThreadLocalList GetUnownedList()
+ /// <returns>The queue object, or null if no unowned queue could be gathered.</returns>
+ private WorkStealingQueue GetUnownedWorkStealingQueue()
{
- //the global lock must be held at this point
- Debug.Assert(Monitor.IsEntered(GlobalListsLock));
+ Debug.Assert(Monitor.IsEntered(GlobalQueuesLock));
+ // Look for a thread that has the same ID as this one. It won't have come from the same thread,
+ // but if our thread ID is reused, we know that no other thread can have the same ID and thus
+ // no other thread can be using this queue.
int currentThreadId = Environment.CurrentManagedThreadId;
- ThreadLocalList currentList = _headList;
- while (currentList != null)
+ for (WorkStealingQueue queue = _workStealingQueues; queue != null; queue = queue._nextQueue)
{
- if (currentList._ownerThreadId == currentThreadId)
+ if (queue._ownerThreadId == currentThreadId)
{
- return currentList;
+ return queue;
}
- currentList = currentList._nextList;
}
+
return null;
}
-
- /// <summary>
- /// Local helper method to steal an item from any other non empty thread
- /// </summary>
+ /// <summary>Local helper method to steal an item from any other non empty thread.</summary>
/// <param name="result">To receive the item retrieved from the bag</param>
/// <param name="take">Whether to remove or peek.</param>
/// <returns>True if succeeded, false otherwise.</returns>
- private bool Steal(out T result, bool take)
+ private bool TrySteal(out T result, bool take)
{
-#if FEATURE_TRACING
if (take)
+ {
CDSCollectionETWBCLProvider.Log.ConcurrentBag_TryTakeSteals();
+ }
else
+ {
CDSCollectionETWBCLProvider.Log.ConcurrentBag_TryPeekSteals();
-#endif
+ }
- bool loop;
- List<int> versionsList = new List<int>(); // save the lists version
- do
+ // If there's no local queue for this thread, just start from the head queue
+ // and try to steal from each queue until we get a result.
+ WorkStealingQueue localQueue = GetCurrentThreadWorkStealingQueue(forceCreate: false);
+ if (localQueue == null)
{
- versionsList.Clear(); //clear the list from the previous iteration
- loop = false;
-
-
- ThreadLocalList currentList = _headList;
- while (currentList != null)
- {
- versionsList.Add(currentList._version);
- if (currentList._head != null && TrySteal(currentList, out result, take))
- {
- return true;
- }
- currentList = currentList._nextList;
- }
-
- // verify versioning, if other items are added to this list since we last visit it, we should retry
- currentList = _headList;
- foreach (int version in versionsList)
- {
- if (version != currentList._version) //oops state changed
- {
- loop = true;
- if (currentList._head != null && TrySteal(currentList, out result, take))
- return true;
- }
- currentList = currentList._nextList;
- }
- } while (loop);
+ return TryStealFromTo(_workStealingQueues, null, out result, take);
+ }
+ // If there is a local queue from this thread, then start from the next queue
+ // after it, and then iterate around back from the head to this queue, not including it.
+ return
+ TryStealFromTo(localQueue._nextQueue, null, out result, take) ||
+ TryStealFromTo(_workStealingQueues, localQueue, out result, take);
- result = default(T);
- return false;
+ // TODO: Investigate storing the queues in an array instead of a linked list, and then
+ // randomly choosing a starting location from which to start iterating.
}
/// <summary>
- /// local helper function tries to steal an item from given local list
+ /// Attempts to steal from each queue starting from <paramref name="startInclusive"/> to <paramref name="endExclusive"/>.
/// </summary>
- private bool TrySteal(ThreadLocalList list, out T result, bool take)
+ private bool TryStealFromTo(WorkStealingQueue startInclusive, WorkStealingQueue endExclusive, out T result, bool take)
{
- lock (list)
+ for (WorkStealingQueue queue = startInclusive; queue != endExclusive; queue = queue._nextQueue)
{
- if (CanSteal(list))
+ if (queue.TrySteal(out result, take))
{
- list.Steal(out result, take);
return true;
}
- result = default(T);
- return false;
- }
- }
- /// <summary>
- /// Local helper function to check the list if it became empty after acquiring the lock
- /// and wait if there is unsynchronized Add/Take operation in the list to be done
- /// </summary>
- /// <param name="list">The list to steal</param>
- /// <returns>True if can steal, false otherwise</returns>
- private static bool CanSteal(ThreadLocalList list)
- {
- if (list.Count <= 2 && list._currentOp != (int)ListOperation.None)
- {
- SpinWait spinner = new SpinWait();
- while (list._currentOp != (int)ListOperation.None)
- {
- spinner.SpinOnce();
- }
}
- return list.Count > 0;
+
+ result = default(T);
+ return false;
}
/// <summary>
@@ -478,19 +277,38 @@ namespace System.Collections.Concurrent
}
if (index < 0)
{
- throw new ArgumentOutOfRangeException
- (nameof(index), SR.ConcurrentBag_CopyTo_ArgumentOutOfRangeException);
+ throw new ArgumentOutOfRangeException(nameof(index), SR.Collection_CopyTo_ArgumentOutOfRangeException);
}
// Short path if the bag is empty
- if (_headList == null)
+ if (_workStealingQueues == null)
+ {
return;
+ }
bool lockTaken = false;
try
{
FreezeBag(ref lockTaken);
- ToList().CopyTo(array, index);
+
+ // Make sure we won't go out of bounds on the array
+ int count = DangerousCount;
+ if (index > array.Length - count)
+ {
+ throw new ArgumentException(SR.Collection_CopyTo_TooManyElems, nameof(index));
+ }
+
+ // Do the copy
+ try
+ {
+ int copied = CopyFromEachQueueToArray(array, index);
+ Debug.Assert(copied == count);
+ }
+ catch (ArrayTypeMismatchException e)
+ {
+ // Propagate same exception as in desktop
+ throw new InvalidCastException(e.Message, e);
+ }
}
finally
{
@@ -498,6 +316,19 @@ namespace System.Collections.Concurrent
}
}
+ /// <summary>Copies from each queue to the target array, starting at the specified index.</summary>
+ private int CopyFromEachQueueToArray(T[] array, int index)
+ {
+ Debug.Assert(Monitor.IsEntered(GlobalQueuesLock));
+
+ int i = index;
+ for (WorkStealingQueue queue = _workStealingQueues; queue != null; queue = queue._nextQueue)
+ {
+ i += queue.DangerousCopyTo(array, i);
+ }
+ return i - index;
+ }
+
/// <summary>
/// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see
/// cref="T:System.Array"/>, starting at a particular
@@ -525,24 +356,24 @@ namespace System.Collections.Concurrent
/// </exception>
void ICollection.CopyTo(Array array, int index)
{
- if (array == null)
+ // If the destination is actually a T[], use the strongly-typed
+ // overload that doesn't allocate/copy an extra array.
+ T[] szArray = array as T[];
+ if (szArray != null)
{
- throw new ArgumentNullException(nameof(array), SR.ConcurrentBag_CopyTo_ArgumentNullException);
+ CopyTo(szArray, index);
+ return;
}
- bool lockTaken = false;
- try
- {
- FreezeBag(ref lockTaken);
- ((ICollection)ToList()).CopyTo(array, index);
- }
- finally
+ // Otherwise, fall back to first storing the contents to an array,
+ // and then relying on its CopyTo to copy to the target Array.
+ if (array == null)
{
- UnfreezeBag(lockTaken);
+ throw new ArgumentNullException(nameof(array), SR.ConcurrentBag_CopyTo_ArgumentNullException);
}
+ ToArray().CopyTo(array, index);
}
-
/// <summary>
/// Copies the <see cref="ConcurrentBag{T}"/> elements to a new array.
/// </summary>
@@ -550,20 +381,30 @@ namespace System.Collections.Concurrent
/// cref="ConcurrentBag{T}"/>.</returns>
public T[] ToArray()
{
- // Short path if the bag is empty
- if (_headList == null)
- return Array.Empty<T>();
-
- bool lockTaken = false;
- try
+ if (_workStealingQueues != null)
{
- FreezeBag(ref lockTaken);
- return ToList().ToArray();
- }
- finally
- {
- UnfreezeBag(lockTaken);
+ bool lockTaken = false;
+ try
+ {
+ FreezeBag(ref lockTaken);
+
+ int count = DangerousCount;
+ if (count > 0)
+ {
+ var arr = new T[count];
+ int copied = CopyFromEachQueueToArray(arr, 0);
+ Debug.Assert(copied == count);
+ return arr;
+ }
+ }
+ finally
+ {
+ UnfreezeBag(lockTaken);
+ }
}
+
+ // Bag was empty
+ return Array.Empty<T>();
}
/// <summary>
@@ -578,23 +419,7 @@ namespace System.Collections.Concurrent
/// <see cref="GetEnumerator"/> was called. The enumerator is safe to use
/// concurrently with reads from and writes to the bag.
/// </remarks>
- public IEnumerator<T> GetEnumerator()
- {
- // Short path if the bag is empty
- if (_headList == null)
- return ((IEnumerable<T>)Array.Empty<T>()).GetEnumerator();
-
- bool lockTaken = false;
- try
- {
- FreezeBag(ref lockTaken);
- return ToList().GetEnumerator();
- }
- finally
- {
- UnfreezeBag(lockTaken);
- }
- }
+ public IEnumerator<T> GetEnumerator() => new Enumerator(ToArray());
/// <summary>
/// Returns an enumerator that iterates through the <see
@@ -607,10 +432,7 @@ namespace System.Collections.Concurrent
/// of the bag. It does not reflect any update to the collection after
/// <see cref="GetEnumerator"/> was called.
/// </remarks>
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((ConcurrentBag<T>)this).GetEnumerator();
- }
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <summary>
/// Gets the number of elements contained in the <see cref="ConcurrentBag{T}"/>.
@@ -626,14 +448,16 @@ namespace System.Collections.Concurrent
get
{
// Short path if the bag is empty
- if (_headList == null)
+ if (_workStealingQueues == null)
+ {
return 0;
+ }
bool lockTaken = false;
try
{
FreezeBag(ref lockTaken);
- return GetCountInternal();
+ return DangerousCount;
}
finally
{
@@ -642,6 +466,23 @@ namespace System.Collections.Concurrent
}
}
+ /// <summary>Gets the number of items stored in the bag.</summary>
+ /// <remarks>Only provides a stable result when the bag is frozen.</remarks>
+ private int DangerousCount
+ {
+ get
+ {
+ int count = 0;
+ for (WorkStealingQueue queue = _workStealingQueues; queue != null; queue = queue._nextQueue)
+ {
+ checked { count += queue.DangerousCount; }
+ }
+
+ Debug.Assert(count >= 0);
+ return count;
+ }
+ }
+
/// <summary>
/// Gets a value that indicates whether the <see cref="ConcurrentBag{T}"/> is empty.
/// </summary>
@@ -650,29 +491,50 @@ namespace System.Collections.Concurrent
{
get
{
- if (_headList == null)
- return true;
+ // Fast-path based on the current thread's local queue.
+ WorkStealingQueue local = GetCurrentThreadWorkStealingQueue(forceCreate: false);
+ if (local != null)
+ {
+ // We don't need the lock to check the local queue, as no other thread
+ // could be adding to it, and a concurrent steal that transitions from
+ // non-empty to empty doesn't matter because if we see this as non-empty,
+ // then that's a valid moment-in-time answer, and if we see this as empty,
+ // we check other things.
+ if (!local.IsEmpty)
+ {
+ return false;
+ }
+ // We know the local queue is empty (no one besides this thread could have
+ // added to it since we checked). If the local queue is the only one
+ // in the bag, then the bag is empty, too.
+ if (local._nextQueue == null && local == _workStealingQueues)
+ {
+ return true;
+ }
+ }
+
+ // Couldn't take a fast path. Freeze the bag, and enumerate the queues to see if
+ // any is non-empty.
bool lockTaken = false;
try
{
FreezeBag(ref lockTaken);
- ThreadLocalList currentList = _headList;
- while (currentList != null)
+ for (WorkStealingQueue queue = _workStealingQueues; queue != null; queue = queue._nextQueue)
{
- if (currentList._head != null)
- //at least this list is not empty, we return false
+ if (!queue.IsEmpty)
{
return false;
}
- currentList = currentList._nextList;
}
- return true;
}
finally
{
UnfreezeBag(lockTaken);
}
+
+ // All queues were empty, so the bag was empty.
+ return true;
}
}
@@ -683,10 +545,7 @@ namespace System.Collections.Concurrent
/// <value>true if access to the <see cref="T:System.Collections.ICollection"/> is synchronized
/// with the SyncRoot; otherwise, false. For <see cref="ConcurrentBag{T}"/>, this property always
/// returns false.</value>
- bool ICollection.IsSynchronized
- {
- get { return false; }
- }
+ bool ICollection.IsSynchronized => false;
/// <summary>
/// Gets an object that can be used to synchronize access to the <see
@@ -695,19 +554,11 @@ namespace System.Collections.Concurrent
/// <exception cref="T:System.NotSupportedException">The SyncRoot property is not supported.</exception>
object ICollection.SyncRoot
{
- get
- {
- throw new NotSupportedException(SR.ConcurrentCollection_SyncRoot_NotSupported);
- }
+ get { throw new NotSupportedException(SR.ConcurrentCollection_SyncRoot_NotSupported); }
}
-
- /// <summary>
- /// A global lock object, used in two cases:
- /// 1- To maintain the _tailList pointer for each new list addition process ( first time a thread called Add )
- /// 2- To freeze the bag in GetEnumerator, CopyTo, ToArray and Count members
- /// </summary>
- private object GlobalListsLock
+ /// <summary>Global lock used to synchronize the queues pointer and all bag-wide operations (e.g. ToArray, Count, etc.).</summary>
+ private object GlobalQueuesLock
{
get
{
@@ -716,338 +567,475 @@ namespace System.Collections.Concurrent
}
}
-
- #region Freeze bag helper methods
- /// <summary>
- /// Local helper method to freeze all bag operations, it
- /// 1- Acquire the global lock to prevent any other thread to freeze the bag, and also new thread can be added
- /// to the dictionary
- /// 2- Then Acquire all local lists locks to prevent steal and synchronized operations
- /// 3- Wait for all un-synchronized operations to be done
- /// </summary>
- /// <param name="lockTaken">Retrieve the lock taken result for the global lock, to be passed to Unfreeze method</param>
+ /// <summary>"Freezes" the bag, such that no concurrent operations will be mutating the bag when it returns.</summary>
+ /// <param name="lockTaken">true if the global lock was taken; otherwise, false.</param>
private void FreezeBag(ref bool lockTaken)
{
- Debug.Assert(!Monitor.IsEntered(GlobalListsLock));
-
- // global lock to be safe against multi threads calls count and corrupt _needSync
- Monitor.Enter(GlobalListsLock, ref lockTaken);
-
- // This will force any future add/take operation to be synchronized
- _needSync = true;
-
- //Acquire all local lists locks
- AcquireAllLocks();
-
- // Wait for all un-synchronized operation to be done
- WaitAllOperations();
- }
-
- /// <summary>
- /// Local helper method to unfreeze the bag from a frozen state
- /// </summary>
- /// <param name="lockTaken">The lock taken result from the Freeze method</param>
- private void UnfreezeBag(bool lockTaken)
- {
- ReleaseAllLocks();
- _needSync = false;
- if (lockTaken)
+ // Take the global lock to start freezing the bag. This helps, for example,
+ // to prevent other threads from joining the bag (adding their local queues)
+ // while a global operation is in progress.
+ Debug.Assert(!Monitor.IsEntered(GlobalQueuesLock));
+ Monitor.Enter(GlobalQueuesLock, ref lockTaken);
+ WorkStealingQueue head = _workStealingQueues; // stable at least until GlobalQueuesLock is released in UnfreezeBag
+
+ // Then acquire all local queue locks, noting on each that it's been taken.
+ for (WorkStealingQueue queue = head; queue != null; queue = queue._nextQueue)
{
- Monitor.Exit(GlobalListsLock);
+ Monitor.Enter(queue, ref queue._frozen);
}
- }
-
- /// <summary>
- /// local helper method to acquire all local lists locks
- /// </summary>
- private void AcquireAllLocks()
- {
- Debug.Assert(Monitor.IsEntered(GlobalListsLock));
+ Interlocked.MemoryBarrier(); // prevent reads of _currentOp from moving before writes to _frozen
- bool lockTaken = false;
- ThreadLocalList currentList = _headList;
- while (currentList != null)
- {
- // Try/Finally block to avoid thread abort between acquiring the lock and setting the taken flag
- try
- {
- Monitor.Enter(currentList, ref lockTaken);
- }
- finally
- {
- if (lockTaken)
- {
- currentList._lockTaken = true;
- lockTaken = false;
- }
- }
- currentList = currentList._nextList;
- }
- }
-
- /// <summary>
- /// Local helper method to release all local lists locks
- /// </summary>
- private void ReleaseAllLocks()
- {
- ThreadLocalList currentList = _headList;
- while (currentList != null)
+ // Finally, wait for all unsynchronized operations on each queue to be done.
+ for (WorkStealingQueue queue = head; queue != null; queue = queue._nextQueue)
{
- if (currentList._lockTaken)
+ if (queue._currentOp != (int)Operation.None)
{
- currentList._lockTaken = false;
- Monitor.Exit(currentList);
+ var spinner = new SpinWait();
+ do { spinner.SpinOnce(); }
+ while (queue._currentOp != (int)Operation.None);
}
- currentList = currentList._nextList;
}
}
- /// <summary>
- /// Local helper function to wait all unsynchronized operations
- /// </summary>
- private void WaitAllOperations()
+ /// <summary>"Unfreezes" a bag frozen with <see cref="FreezeBag(ref bool)"/>.</summary>
+ /// <param name="lockTaken">The result of the <see cref="FreezeBag(ref bool)"/> method.</param>
+ private void UnfreezeBag(bool lockTaken)
{
- Debug.Assert(Monitor.IsEntered(GlobalListsLock));
-
- ThreadLocalList currentList = _headList;
- while (currentList != null)
+ Debug.Assert(Monitor.IsEntered(GlobalQueuesLock) == lockTaken);
+ if (lockTaken)
{
- if (currentList._currentOp != (int)ListOperation.None)
+ // Release all of the individual queue locks.
+ for (WorkStealingQueue queue = _workStealingQueues; queue != null; queue = queue._nextQueue)
{
- SpinWait spinner = new SpinWait();
- while (currentList._currentOp != (int)ListOperation.None)
+ if (queue._frozen)
{
- spinner.SpinOnce();
+ queue._frozen = false;
+ Monitor.Exit(queue);
}
}
- currentList = currentList._nextList;
+
+ // Then release the global lock.
+ Monitor.Exit(GlobalQueuesLock);
}
}
- /// <summary>
- /// Local helper function to get the bag count, the caller should call it from Freeze/Unfreeze block
- /// </summary>
- /// <returns>The current bag count</returns>
- private int GetCountInternal()
+ /// <summary>Provides a work-stealing queue data structure stored per thread.</summary>
+ private sealed class WorkStealingQueue
{
- Debug.Assert(Monitor.IsEntered(GlobalListsLock));
-
- int count = 0;
- ThreadLocalList currentList = _headList;
- while (currentList != null)
+ /// <summary>Initial size of the queue's array.</summary>
+ private const int InitialSize = 32;
+ /// <summary>Starting index for the head and tail indices.</summary>
+ private const int StartIndex =
+#if DEBUG
+ int.MaxValue; // in debug builds, start at the end so we exercise the index reset logic
+#else
+ 0;
+#endif
+ /// <summary>Head index from which to steal. This and'd with the <see cref="_mask"/> is the index into <see cref="_array"/>.</summary>
+ private volatile int _headIndex = StartIndex;
+ /// <summary>Tail index at which local pushes/pops happen. This and'd with the <see cref="_mask"/> is the index into <see cref="_array"/>.</summary>
+ private volatile int _tailIndex = StartIndex;
+ /// <summary>The array storing the queue's data.</summary>
+ private volatile T[] _array = new T[InitialSize];
+ /// <summary>Mask and'd with <see cref="_headIndex"/> and <see cref="_tailIndex"/> to get an index into <see cref="_array"/>.</summary>
+ private volatile int _mask = InitialSize - 1;
+ /// <summary>Numbers of elements in the queue from the local perspective; needs to be combined with <see cref="_stealCount"/> to get an actual Count.</summary>
+ private int _addTakeCount;
+ /// <summary>Number of steals; needs to be combined with <see cref="_addTakeCount"/> to get an actual Count.</summary>
+ private int _stealCount;
+ /// <summary>The current queue operation. Used to quiesce before performing operations from one thread onto another.</summary>
+ internal volatile int _currentOp;
+ /// <summary>true if this queue's lock is held as part of a global freeze.</summary>
+ internal bool _frozen;
+ /// <summary>Next queue in the <see cref="ConcurrentBag{T}"/>'s set of thread-local queues.</summary>
+ internal readonly WorkStealingQueue _nextQueue;
+ /// <summary>Thread ID that owns this queue.</summary>
+ internal readonly int _ownerThreadId;
+
+ /// <summary>Initialize the WorkStealingQueue.</summary>
+ /// <param name="nextQueue">The next queue in the linked list of work-stealing queues.</param>
+ internal WorkStealingQueue(WorkStealingQueue nextQueue)
{
- checked
- {
- count += currentList.Count;
- }
- currentList = currentList._nextList;
+ _ownerThreadId = Environment.CurrentManagedThreadId;
+ _nextQueue = nextQueue;
}
- return count;
- }
- /// <summary>
- /// Local helper function to return the bag item in a list, this is mainly used by CopyTo and ToArray
- /// This is not thread safe, should be called in Freeze/UnFreeze bag block
- /// </summary>
- /// <returns>List the contains the bag items</returns>
- private List<T> ToList()
- {
- Debug.Assert(Monitor.IsEntered(GlobalListsLock));
-
- List<T> list = new List<T>();
- ThreadLocalList currentList = _headList;
- while (currentList != null)
+ /// <summary>Gets whether the queue is empty.</summary>
+ internal bool IsEmpty
{
- Node currentNode = currentList._head;
- while (currentNode != null)
+ get
{
- list.Add(currentNode._value);
- currentNode = currentNode._next;
+ /// _tailIndex can be decremented even while the bag is frozen, as the decrement in TryLocalPop happens prior
+ /// to the check for _frozen. But that's ok, as if _tailIndex is being decremented such that _headIndex becomes
+ /// >= _tailIndex, then the queue is about to be empty. This does mean, though, that while holding the lock,
+ /// it is possible to observe Count == 1 but IsEmpty == true. As such, we simply need to avoid doing any operation
+ /// while the bag is frozen that requires those values to be consistent.
+ return _headIndex >= _tailIndex;
}
- currentList = currentList._nextList;
}
- return list;
- }
-
- #endregion
-
-
- #region Inner Classes
-
- /// <summary>
- /// A class that represents a node in the lock thread list
- /// </summary>
- internal class Node
- {
- public Node(T value)
+ /// <summary>
+ /// Add new item to the tail of the queue.
+ /// </summary>
+ /// <param name="item">The item to add.</param>
+ internal void LocalPush(T item)
{
- _value = value;
- }
- public readonly T _value;
- public Node _next;
- public Node _prev;
- }
-
- /// <summary>
- /// A class that represents the lock thread list
- /// </summary>
- internal class ThreadLocalList
- {
- // Head node in the list, null means the list is empty
- internal volatile Node _head;
-
- // Tail node for the list
- private volatile Node _tail;
+ Debug.Assert(Environment.CurrentManagedThreadId == _ownerThreadId);
+ bool lockTaken = false;
+ try
+ {
+ // Full fence to ensure subsequent reads don't get reordered before this
+ Interlocked.Exchange(ref _currentOp, (int)Operation.Add);
+ int tail = _tailIndex;
- // The current list operation
- internal volatile int _currentOp;
+ // Rare corner case (at most once every 2 billion pushes on this thread):
+ // We're going to increment the tail; if we'll overflow, then we need to reset our counts
+ if (tail == int.MaxValue)
+ {
+ _currentOp = (int)Operation.None; // set back to None temporarily to avoid a deadlock
+ lock (this)
+ {
+ Debug.Assert(_tailIndex == int.MaxValue, "No other thread should be changing _tailIndex");
+
+ // Rather than resetting to zero, we'll just mask off the bits we don't care about.
+ // This way we don't need to rearrange the items already in the queue; they'll be found
+ // correctly exactly where they are. One subtlety here is that we need to make sure that
+ // if head is currently < tail, it remains that way. This happens to just fall out from
+ // the bit-masking, because we only do this if tail == int.MaxValue, meaning that all
+ // bits are set, so all of the bits we're keeping will also be set. Thus it's impossible
+ // for the head to end up > than the tail, since you can't set any more bits than all of them.
+ _headIndex = _headIndex & _mask;
+ _tailIndex = tail = _tailIndex & _mask;
+ Debug.Assert(_headIndex <= _tailIndex);
+
+ _currentOp = (int)Operation.Add;
+ }
+ }
- // The list count from the Add/Take perspective
- private int _count;
+ // We'd like to take the fast path that doesn't require locking, if possible. It's not possible if another
+ // thread is currently requesting that the whole bag synchronize, e.g. a ToArray operation. It's also
+ // not possible if there are fewer than two spaces available. One space is necessary for obvious reasons:
+ // to store the element we're trying to push. The other is necessary due to synchronization with steals.
+ // A stealing thread first increments _headIndex to reserve the slot at its old value, and then tries to
+ // read from that slot. We could potentially have a race condition whereby _headIndex is incremented just
+ // before this check, in which case we could overwrite the element being stolen as that slot would appear
+ // to be empty. Thus, we only allow the fast path if there are two empty slots.
+ if (!_frozen && tail < (_headIndex + _mask))
+ {
+ _array[tail & _mask] = item;
+ _tailIndex = tail + 1;
+ }
+ else
+ {
+ // We need to contend with foreign operations (e.g. steals, enumeration, etc.), so we lock.
+ _currentOp = (int)Operation.None; // set back to None to avoid a deadlock
+ Monitor.Enter(this, ref lockTaken);
- // The stealing count
- internal int _stealCount;
+ int head = _headIndex;
+ int count = _tailIndex - _headIndex;
- // Next list in the dictionary values
- internal volatile ThreadLocalList _nextList;
+ // If we're full, expand the array.
+ if (count >= _mask)
+ {
+ // Expand the queue by doubling its size.
+ var newArray = new T[_array.Length << 1];
+ int headIdx = head & _mask;
+ if (headIdx == 0)
+ {
+ Array.Copy(_array, 0, newArray, 0, _array.Length);
+ }
+ else
+ {
+ Array.Copy(_array, headIdx, newArray, 0, _array.Length - headIdx);
+ Array.Copy(_array, 0, newArray, _array.Length - headIdx, headIdx);
+ }
- // Set if the locl lock is taken
- internal bool _lockTaken;
+ // Reset the field values
+ _array = newArray;
+ _headIndex = 0;
+ _tailIndex = tail = count;
+ _mask = (_mask << 1) | 1;
+ }
- // The owner thread for this list
- internal int _ownerThreadId;
+ // Add the element
+ _array[tail & _mask] = item;
+ _tailIndex = tail + 1;
- // the version of the list, incremented only when the list changed from empty to non empty state
- internal volatile int _version;
+ // Update the count to avoid overflow. We can trust _stealCount here,
+ // as we're inside the lock and it's only manipulated there.
+ _addTakeCount -= _stealCount;
+ _stealCount = 0;
+ }
- /// <summary>
- /// ThreadLocalList constructor
- /// </summary>
- /// <param name="ownerThread">The owner thread for this list</param>
- internal ThreadLocalList(int ownerThreadId)
- {
- _ownerThreadId = ownerThreadId;
- }
- /// <summary>
- /// Add new item to head of the list
- /// </summary>
- /// <param name="item">The item to add.</param>
- /// <param name="updateCount">Whether to update the count.</param>
- internal void Add(T item, bool updateCount)
- {
- checked
- {
- _count++;
- }
- Node node = new Node(item);
- if (_head == null)
- {
- Debug.Assert(_tail == null);
- _head = node;
- _tail = node;
- _version++; // changing from empty state to non empty state
- }
- else
- {
- node._next = _head;
- _head._prev = node;
- _head = node;
+ // Increment the count from the add/take perspective
+ checked { _addTakeCount++; }
}
- if (updateCount) // update the count to avoid overflow if this add is synchronized
+ finally
{
- _count = _count - _stealCount;
- _stealCount = 0;
+ _currentOp = (int)Operation.None;
+ if (lockTaken)
+ {
+ Monitor.Exit(this);
+ }
}
}
- /// <summary>
- /// Remove an item from the head of the list
- /// </summary>
+ /// <summary>Remove an item from the tail of the queue.</summary>
/// <param name="result">The removed item</param>
- internal void Remove(out T result)
+ internal bool TryLocalPop(out T result)
{
- Debug.Assert(_head != null);
- Node head = _head;
- _head = _head._next;
- if (_head != null)
+ Debug.Assert(Environment.CurrentManagedThreadId == _ownerThreadId);
+
+ int tail = _tailIndex;
+ if (_headIndex >= tail)
{
- _head._prev = null;
+ result = default(T);
+ return false;
}
- else
+
+ bool lockTaken = false;
+ try
{
- _tail = null;
+ // Decrement the tail using a full fence to ensure subsequent reads don't reorder before this.
+ // If the read of _headIndex moved before this write to _tailIndex, we could erroneously end up
+ // popping an element that's concurrently being stolen, leading to the same element being
+ // dequeued from the bag twice.
+ _currentOp = (int)Operation.Take;
+ Interlocked.Exchange(ref _tailIndex, --tail);
+
+ // If there is no interaction with a steal, we can head down the fast path.
+ // Note that we use _headIndex < tail rather than _headIndex <= tail to account
+ // for stealing peeks, which don't increment _headIndex, and which could observe
+ // the written default(T) in a race condition to peek at the element.
+ if (!_frozen && _headIndex < tail)
+ {
+ int idx = tail & _mask;
+ result = _array[idx];
+ _array[idx] = default(T);
+ _addTakeCount--;
+ return true;
+ }
+ else
+ {
+ // Interaction with steals: 0 or 1 elements left.
+ _currentOp = (int)Operation.None; // set back to None to avoid a deadlock
+ Monitor.Enter(this, ref lockTaken);
+ if (_headIndex <= tail)
+ {
+ // Element still available. Take it.
+ int idx = tail & _mask;
+ result = _array[idx];
+ _array[idx] = default(T);
+ _addTakeCount--;
+ return true;
+ }
+ else
+ {
+ // We encountered a race condition and the element was stolen, restore the tail.
+ _tailIndex = tail + 1;
+ result = default(T);
+ return false;
+ }
+ }
+ }
+ finally
+ {
+ _currentOp = (int)Operation.None;
+ if (lockTaken)
+ {
+ Monitor.Exit(this);
+ }
}
- _count--;
- result = head._value;
}
- /// <summary>
- /// Peek an item from the head of the list
- /// </summary>
+ /// <summary>Peek an item from the tail of the queue.</summary>
/// <param name="result">the peeked item</param>
/// <returns>True if succeeded, false otherwise</returns>
- internal bool Peek(out T result)
+ internal bool TryLocalPeek(out T result)
{
- Node head = _head;
- if (head != null)
+ Debug.Assert(Environment.CurrentManagedThreadId == _ownerThreadId);
+
+ int tail = _tailIndex;
+ if (_headIndex < tail)
{
- result = head._value;
- return true;
+ // It is possible to enable lock-free peeks, following the same general approach
+ // that's used in TryLocalPop. However, peeks are more complicated as we can't
+ // do the same kind of index reservation that's done in TryLocalPop; doing so could
+ // end up making a steal think that no item is available, even when one is. To do
+ // it correctly, then, we'd need to add spinning to TrySteal in case of a concurrent
+ // peek happening. With a lock, the common case (no contention with steals) will
+ // effectively only incur two interlocked operations (entering/exiting the lock) instead
+ // of one (setting Peek as the _currentOp). Combined with Peeks on a bag being rare,
+ // for now we'll use the simpler/safer code.
+ lock (this)
+ {
+ if (_headIndex < tail)
+ {
+ result = _array[(tail - 1) & _mask];
+ return true;
+ }
+ }
}
+
result = default(T);
return false;
}
- /// <summary>
- /// Steal an item from the tail of the list
- /// </summary>
+ /// <summary>Steal an item from the head of the queue.</summary>
/// <param name="result">the removed item</param>
- /// <param name="remove">remove or peek flag</param>
- internal void Steal(out T result, bool remove)
+ /// <param name="take">true to take the item; false to simply peek at it</param>
+ internal bool TrySteal(out T result, bool take)
{
- Node tail = _tail;
- Debug.Assert(tail != null);
- if (remove) // Take operation
+ // Fast-path check to see if the queue is empty.
+ if (_headIndex < _tailIndex)
{
- _tail = _tail._prev;
- if (_tail != null)
- {
- _tail._next = null;
- }
- else
+ // Anything other than empty requires synchronization.
+ lock (this)
{
- _head = null;
+ int head = _headIndex;
+ if (take)
+ {
+ // Increment head to tentatively take an element: a full fence is used to ensure the read
+ // of _tailIndex doesn't move earlier, as otherwise we could potentially end up stealing
+ // the same element that's being popped locally.
+ Interlocked.Exchange(ref _headIndex, head + 1);
+
+ // If there's an element to steal, do it.
+ if (head < _tailIndex)
+ {
+ int idx = head & _mask;
+ result = _array[idx];
+ _array[idx] = default(T);
+ _stealCount++;
+ return true;
+ }
+ else
+ {
+ // We contended with the local thread and lost the race, so restore the head.
+ _headIndex = head;
+ }
+ }
+ else if (head < _tailIndex)
+ {
+ // Peek, if there's an element available
+ result = _array[head & _mask];
+ return true;
+ }
}
- // Increment the steal count
- _stealCount++;
}
- result = tail._value;
+
+ // The queue was empty.
+ result = default(T);
+ return false;
}
+ /// <summary>Copies the contents of this queue to the target array starting at the specified index.</summary>
+ internal int DangerousCopyTo(T[] array, int arrayIndex)
+ {
+ Debug.Assert(Monitor.IsEntered(this));
+ Debug.Assert(_frozen);
+ Debug.Assert(array != null);
+ Debug.Assert(arrayIndex >= 0 && arrayIndex <= array.Length);
+
+ int headIndex = _headIndex;
+ int count = DangerousCount;
+ Debug.Assert(
+ count == (_tailIndex - _headIndex) ||
+ count == (_tailIndex + 1 - _headIndex),
+ "Count should be the same as tail - head, but allowing for the possibilty that " +
+ "a peek decremented _tailIndex before seeing that a freeze was happening.");
+ Debug.Assert(arrayIndex <= array.Length - count);
+
+ // Copy from this queue's array to the destination array, but in reverse
+ // order to match the ordering of desktop.
+ for (int i = arrayIndex + count - 1; i >= arrayIndex; i--)
+ {
+ array[i] = _array[headIndex++ & _mask];
+ }
+
+ return count;
+ }
- /// <summary>
- /// Gets the total list count, it's not thread safe, may provide incorrect count if it is called concurrently
- /// </summary>
- internal int Count
+ /// <summary>Gets the total number of items in the queue.</summary>
+ /// <remarks>
+ /// This is not thread safe, only providing an accurate result either from the owning
+ /// thread while its lock is held or from any thread while the bag is frozen.
+ /// </remarks>
+ internal int DangerousCount
{
get
{
- return _count - _stealCount;
+ Debug.Assert(Monitor.IsEntered(this));
+ int count = _addTakeCount - _stealCount;
+ Debug.Assert(count >= 0);
+ return count;
}
}
}
- #endregion
- }
- /// <summary>
- /// List operations for ConcurrentBag
- /// </summary>
- internal enum ListOperation
- {
- None,
- Add,
- Take
- };
+ /// <summary>Lock-free operations performed on a queue.</summary>
+ internal enum Operation
+ {
+ None,
+ Add,
+ Take
+ };
+
+ /// <summary>Provides an enumerator for the bag.</summary>
+ /// <remarks>
+ /// The original implementation of ConcurrentBag used a <see cref="List{T}"/> as part of
+ /// the GetEnumerator implementation. That list was then changed to be an array, but array's
+ /// GetEnumerator has different behavior than does list's, in particular for the case where
+ /// Current is used after MoveNext returns false. To avoid any concerns around compatibility,
+ /// we use a custom enumerator rather than just returning array's. This enumerator provides
+ /// the essential elements of both list's and array's enumerators.
+ /// </remarks>
+ [Serializable]
+ private sealed class Enumerator : IEnumerator<T>
+ {
+ private readonly T[] _array;
+ private T _current;
+ private int _index;
+
+ public Enumerator(T[] array)
+ {
+ Debug.Assert(array != null);
+ _array = array;
+ }
+
+ public bool MoveNext()
+ {
+ if (_index < _array.Length)
+ {
+ _current = _array[_index++];
+ return true;
+ }
+
+ _index = _array.Length + 1;
+ return false;
+ }
+
+ public T Current => _current;
+ object IEnumerator.Current
+ {
+ get
+ {
+ if (_index == 0 || _index == _array.Length + 1)
+ {
+ throw new InvalidOperationException(SR.ConcurrentBag_Enumerator_EnumerationNotStartedOrAlreadyFinished);
+ }
+ return Current;
+ }
+ }
+
+ public void Reset()
+ {
+ _index = 0;
+ _current = default(T);
+ }
+
+ public void Dispose() { }
+ }
+ }
}
diff --git a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs
index c683dcc0a4..7cebb46e78 100644
--- a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs
+++ b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs
@@ -1047,6 +1047,37 @@ namespace System.Collections.Concurrent
/// if the key does not already exist.
/// </summary>
/// <param name="key">The key of the element to add.</param>
+ /// <param name="valueFactory">The function used to generate a value for the key</param>
+ /// <param name="factoryArgument">An argument value to pass into <paramref name="valueFactory"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="valueFactory"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.OverflowException">The dictionary contains too many
+ /// elements.</exception>
+ /// <returns>The value for the key. This will be either the existing value for the key if the
+ /// key is already in the dictionary, or the new value for the key as returned by valueFactory
+ /// if the key was not in the dictionary.</returns>
+ public TValue GetOrAdd<TArg>(TKey key, Func<TKey, TArg, TValue> valueFactory, TArg factoryArgument)
+ {
+ if (key == null) throw new ArgumentNullException(nameof(key));
+ if (valueFactory == null) throw new ArgumentNullException(nameof(valueFactory));
+
+ int hashcode = _comparer.GetHashCode(key);
+
+ TValue resultingValue;
+ if (!TryGetValueInternal(key, hashcode, out resultingValue))
+ {
+ TryAddInternal(key, hashcode, valueFactory(key, factoryArgument), false, true, out resultingValue);
+ }
+ return resultingValue;
+ }
+
+ /// <summary>
+ /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// if the key does not already exist.
+ /// </summary>
+ /// <param name="key">The key of the element to add.</param>
/// <param name="value">the value to be added, if the key does not already exist</param>
/// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
/// (Nothing in Visual Basic).</exception>
@@ -1077,6 +1108,59 @@ namespace System.Collections.Concurrent
/// <param name="addValueFactory">The function used to generate a value for an absent key</param>
/// <param name="updateValueFactory">The function used to generate a new value for an existing key
/// based on the key's existing value</param>
+ /// <param name="factoryArgument">An argument to pass into <paramref name="addValueFactory"/> and <paramref name="updateValueFactory"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="addValueFactory"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="updateValueFactory"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.OverflowException">The dictionary contains too many
+ /// elements.</exception>
+ /// <returns>The new value for the key. This will be either be the result of addValueFactory (if the key was
+ /// absent) or the result of updateValueFactory (if the key was present).</returns>
+ public TValue AddOrUpdate<TArg>(
+ TKey key, Func<TKey, TArg, TValue> addValueFactory, Func<TKey, TValue, TArg, TValue> updateValueFactory, TArg factoryArgument)
+ {
+ if (key == null) throw new ArgumentNullException(nameof(key));
+ if (addValueFactory == null) throw new ArgumentNullException(nameof(addValueFactory));
+ if (updateValueFactory == null) throw new ArgumentNullException(nameof(updateValueFactory));
+
+ int hashcode = _comparer.GetHashCode(key);
+
+ while (true)
+ {
+ TValue oldValue;
+ if (TryGetValueInternal(key, hashcode, out oldValue))
+ {
+ // key exists, try to update
+ TValue newValue = updateValueFactory(key, oldValue, factoryArgument);
+ if (TryUpdateInternal(key, hashcode, newValue, oldValue))
+ {
+ return newValue;
+ }
+ }
+ else
+ {
+ // key doesn't exist, try to add
+ TValue resultingValue;
+ if (TryAddInternal(key, hashcode, addValueFactory(key, factoryArgument), false, true, out resultingValue))
+ {
+ return resultingValue;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key does not already
+ /// exist, or updates a key/value pair in the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key
+ /// already exists.
+ /// </summary>
+ /// <param name="key">The key to be added or whose value should be updated</param>
+ /// <param name="addValueFactory">The function used to generate a value for an absent key</param>
+ /// <param name="updateValueFactory">The function used to generate a new value for an existing key
+ /// based on the key's existing value</param>
/// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
/// (Nothing in Visual Basic).</exception>
/// <exception cref="T:System.ArgumentNullException"><paramref name="addValueFactory"/> is a null reference
@@ -1099,16 +1183,17 @@ namespace System.Collections.Concurrent
{
TValue oldValue;
if (TryGetValueInternal(key, hashcode, out oldValue))
- //key exists, try to update
{
+ // key exists, try to update
TValue newValue = updateValueFactory(key, oldValue);
if (TryUpdateInternal(key, hashcode, newValue, oldValue))
{
return newValue;
}
}
- else //try add
+ else
{
+ // key doesn't exist, try to add
TValue resultingValue;
if (TryAddInternal(key, hashcode, addValueFactory(key), false, true, out resultingValue))
{
@@ -1146,16 +1231,17 @@ namespace System.Collections.Concurrent
{
TValue oldValue;
if (TryGetValueInternal(key, hashcode, out oldValue))
- //key exists, try to update
{
+ // key exists, try to update
TValue newValue = updateValueFactory(key, oldValue);
if (TryUpdateInternal(key, hashcode, newValue, oldValue))
{
return newValue;
}
}
- else //try add
+ else
{
+ // key doesn't exist, try to add
TValue resultingValue;
if (TryAddInternal(key, hashcode, addValue, false, true, out resultingValue))
{
@@ -1834,12 +1920,10 @@ namespace System.Collections.Concurrent
/// </summary>
private void AcquireAllLocks(ref int locksAcquired)
{
-#if FEATURE_TRACING
if (CDSCollectionETWBCLProvider.Log.IsEnabled())
{
CDSCollectionETWBCLProvider.Log.ConcurrentDictionary_AcquiringAllLocks(_tables._buckets.Length);
}
-#endif
// First, acquire lock 0
AcquireLocks(0, 1, ref locksAcquired);
diff --git a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentQueue.cs b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentQueue.cs
index fc61f16547..739542cc79 100644
--- a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentQueue.cs
+++ b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentQueue.cs
@@ -2,14 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-// ConcurrentQueue.cs
-//
-// A lock-free, concurrent queue primitive, and its associated debugger view type.
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
@@ -23,7 +15,7 @@ namespace System.Collections.Concurrent
/// </summary>
/// <typeparam name="T">Specifies the type of elements in the queue.</typeparam>
/// <remarks>
- /// All public and protected members of <see cref="ConcurrentQueue{T}"/> are thread-safe and may be used
+ /// All public and protected members of <see cref="ConcurrentQueue{T}"/> are thread-safe and may be used
/// concurrently from multiple threads.
/// </remarks>
[DebuggerDisplay("Count = {Count}")]
@@ -31,44 +23,72 @@ namespace System.Collections.Concurrent
[Serializable]
public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>
{
+ // This implementation provides an unbounded, multi-producer multi-consumer queue
+ // that supports the standard Enqueue/TryDequeue operations, as well as support for
+ // snapshot enumeration (GetEnumerator, ToArray, CopyTo), peeking, and Count/IsEmpty.
+ // It is composed of a linked list of bounded ring buffers, each of which has a head
+ // and a tail index, isolated from each other to minimize false sharing. As long as
+ // the number of elements in the queue remains less than the size of the current
+ // buffer (Segment), no additional allocations are required for enqueued items. When
+ // the number of items exceeds the size of the current segment, the current segment is
+ // "frozen" to prevent further enqueues, and a new segment is linked from it and set
+ // as the new tail segment for subsequent enqueues. As old segments are consumed by
+ // dequeues, the head reference is updated to point to the segment that dequeuers should
+ // try next. To support snapshot enumeration, segments also support the notion of
+ // preserving for observation, whereby they avoid overwriting state as part of dequeues.
+ // Any operation that requires a snapshot results in all current segments being
+ // both frozen for enqueues and preserved for observation: any new enqueues will go
+ // to new segments, and dequeuers will consume from the existing segments but without
+ // overwriting the existing data.
+
+ /// <summary>Initial length of the segments used in the queue.</summary>
+ private const int InitialSegmentLength = 32;
+ /// <summary>
+ /// Maximum length of the segments used in the queue. This is a somewhat arbitrary limit:
+ /// larger means that as long as we don't exceed the size, we avoid allocating more segments,
+ /// but if we do exceed it, then the segment becomes garbage.
+ /// </summary>
+ private const int MaxSegmentLength = 1024 * 1024;
+
+ /// <summary>
+ /// Lock used to protect cross-segment operations, including any updates to <see cref="_tail"/> or <see cref="_head"/>
+ /// and any operations that need to get a consistent view of them.
+ /// </summary>
[NonSerialized]
- private volatile Segment _head;
+ private object _crossSegmentLock;
+ /// <summary>The current tail segment.</summary>
[NonSerialized]
private volatile Segment _tail;
-
- private T[] _serializationArray; // Used for custom serialization.
-
- private const int SEGMENT_SIZE = 32;
-
- //number of snapshot takers, GetEnumerator(), ToList() and ToArray() operations take snapshot.
+ /// <summary>The current head segment.</summary>
[NonSerialized]
- internal volatile int _numSnapshotTakers = 0;
+ private volatile Segment _head;
+ /// <summary>Field used to temporarily store the contents of the queue for serialization.</summary>
+ private T[] _serializationArray;
/// <summary>
/// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class.
/// </summary>
public ConcurrentQueue()
{
- _head = _tail = new Segment(0, this);
+ _crossSegmentLock = new object();
+ _tail = _head = new Segment(InitialSegmentLength);
}
- /// <summary>Get the data array to be serialized.</summary>
+ /// <summary>Set the data array to be serialized.</summary>
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
- // save the data into the serialization array to be saved
_serializationArray = ToArray();
}
+ /// <summary>Clear the data array that was serialized.</summary>
[OnSerialized]
private void OnSerialized(StreamingContext context)
{
_serializationArray = null;
}
- /// <summary>
- /// Construct the queue from a previously seiralized one
- /// </summary>
+ /// <summary>Construct the queue from the deserialized <see cref="_serializationArray"/>.</summary>
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
@@ -83,34 +103,39 @@ namespace System.Collections.Concurrent
/// <param name="collection">A collection from which to copy elements.</param>
private void InitializeFromCollection(IEnumerable<T> collection)
{
- Segment localTail = new Segment(0, this);//use this local variable to avoid the extra volatile read/write. this is safe because it is only called from ctor
- _head = localTail;
-
- int index = 0;
- foreach (T element in collection)
+ _crossSegmentLock = new object();
+
+ // Determine the initial segment size. We'll use the default,
+ // unless the collection is known to be larger than than, in which
+ // case we round its length up to a power of 2, as all segments must
+ // be a power of 2 in length.
+ int length = InitialSegmentLength;
+ var c = collection as ICollection<T>;
+ if (c != null)
{
- Debug.Assert(index >= 0 && index < SEGMENT_SIZE);
- localTail.UnsafeAdd(element);
- index++;
-
- if (index >= SEGMENT_SIZE)
+ int count = c.Count;
+ if (count > length)
{
- localTail = localTail.UnsafeGrow();
- index = 0;
+ length = RoundUpToPowerOf2(count);
}
}
- _tail = localTail;
+ // Initialize the segment and add all of the data to it.
+ _tail = _head = new Segment(length);
+ foreach (T item in collection)
+ {
+ Enqueue(item);
+ }
}
/// <summary>
- /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/>
- /// class that contains elements copied from the specified collection
+ /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class that contains elements copied
+ /// from the specified collection.
/// </summary>
- /// <param name="collection">The collection whose elements are copied to the new <see
- /// cref="ConcurrentQueue{T}"/>.</param>
- /// <exception cref="T:System.ArgumentNullException">The <paramref name="collection"/> argument is
- /// null.</exception>
+ /// <param name="collection">
+ /// The collection whose elements are copied to the new <see cref="ConcurrentQueue{T}"/>.
+ /// </param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="collection"/> argument is null.</exception>
public ConcurrentQueue(IEnumerable<T> collection)
{
if (collection == null)
@@ -122,16 +147,15 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see
- /// cref="T:System.Array"/>, starting at a particular
- /// <see cref="T:System.Array"/> index.
+ /// Copies the elements of the <see cref="ICollection"/> to an <see
+ /// cref="Array"/>, starting at a particular <see cref="Array"/> index.
/// </summary>
- /// <param name="array">The one-dimensional <see cref="T:System.Array">Array</see> that is the
- /// destination of the elements copied from the
- /// <see cref="T:System.Collections.Concurrent.ConcurrentBag"/>. The <see
- /// cref="T:System.Array">Array</see> must have zero-based indexing.</param>
- /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
- /// begins.</param>
+ /// <param name="array">
+ /// The one-dimensional <see cref="Array">Array</see> that is the destination of the
+ /// elements copied from the <see cref="ConcurrentQueue{T}"/>. <paramref name="array"/> must have
+ /// zero-based indexing.
+ /// </param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param>
/// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
/// Visual Basic).</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
@@ -140,72 +164,58 @@ namespace System.Collections.Concurrent
/// <paramref name="array"/> is multidimensional. -or-
/// <paramref name="array"/> does not have zero-based indexing. -or-
/// <paramref name="index"/> is equal to or greater than the length of the <paramref name="array"/>
- /// -or- The number of elements in the source <see cref="T:System.Collections.ICollection"/> is
+ /// -or- The number of elements in the source <see cref="ICollection"/> is
/// greater than the available space from <paramref name="index"/> to the end of the destination
/// <paramref name="array"/>. -or- The type of the source <see
- /// cref="T:System.Collections.ICollection"/> cannot be cast automatically to the type of the
+ /// cref="ICollection"/> cannot be cast automatically to the type of the
/// destination <paramref name="array"/>.
/// </exception>
void ICollection.CopyTo(Array array, int index)
{
+ // Special-case when the Array is actually a T[], taking a faster path
+ T[] szArray = array as T[];
+ if (szArray != null)
+ {
+ CopyTo(szArray, index);
+ return;
+ }
+
// Validate arguments.
if (array == null)
{
throw new ArgumentNullException(nameof(array));
}
- // We must be careful not to corrupt the array, so we will first accumulate an
- // internal list of elements that we will then copy to the array. This requires
- // some extra allocation, but is necessary since we don't know up front whether
- // the array is sufficiently large to hold the stack's contents.
- ((ICollection)ToList()).CopyTo(array, index);
+ // Otherwise, fall back to the slower path that first copies the contents
+ // to an array, and then uses that array's non-generic CopyTo to do the copy.
+ ToArray().CopyTo(array, index);
}
/// <summary>
- /// Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"/> is
+ /// Gets a value indicating whether access to the <see cref="ICollection"/> is
/// synchronized with the SyncRoot.
/// </summary>
- /// <value>true if access to the <see cref="T:System.Collections.ICollection"/> is synchronized
+ /// <value>true if access to the <see cref="ICollection"/> is synchronized
/// with the SyncRoot; otherwise, false. For <see cref="ConcurrentQueue{T}"/>, this property always
/// returns false.</value>
- bool ICollection.IsSynchronized
- {
- // Gets a value indicating whether access to this collection is synchronized. Always returns
- // false. The reason is subtle. While access is in face thread safe, it's not the case that
- // locking on the SyncRoot would have prevented concurrent pushes and pops, as this property
- // would typically indicate; that's because we internally use CAS operations vs. true locks.
- get { return false; }
- }
-
+ bool ICollection.IsSynchronized => false; // always false, as true implies synchronization via SyncRoot
/// <summary>
/// Gets an object that can be used to synchronize access to the <see
- /// cref="T:System.Collections.ICollection"/>. This property is not supported.
+ /// cref="ICollection"/>. This property is not supported.
/// </summary>
- /// <exception cref="T:System.NotSupportedException">The SyncRoot property is not supported.</exception>
- object ICollection.SyncRoot
- {
- get
- {
- throw new NotSupportedException(SR.ConcurrentCollection_SyncRoot_NotSupported);
- }
- }
+ /// <exception cref="NotSupportedException">The SyncRoot property is not supported.</exception>
+ object ICollection.SyncRoot { get { throw new NotSupportedException(SR.ConcurrentCollection_SyncRoot_NotSupported); } }
- /// <summary>
- /// Returns an enumerator that iterates through a collection.
- /// </summary>
- /// <returns>An <see cref="T:System.Collections.IEnumerator"/> that can be used to iterate through the collection.</returns>
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable<T>)this).GetEnumerator();
- }
+ /// <summary>Returns an enumerator that iterates through a collection.</summary>
+ /// <returns>An <see cref="IEnumerator"/> that can be used to iterate through the collection.</returns>
+ IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<T>)this).GetEnumerator();
/// <summary>
- /// Attempts to add an object to the <see
- /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>.
+ /// Attempts to add an object to the <see cref="Concurrent.IProducerConsumerCollection{T}"/>.
/// </summary>
/// <param name="item">The object to add to the <see
- /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>. The value can be a null
+ /// cref="Concurrent.IProducerConsumerCollection{T}"/>. The value can be a null
/// reference (Nothing in Visual Basic) for reference types.
/// </param>
/// <returns>true if the object was added successfully; otherwise, false.</returns>
@@ -219,8 +229,7 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Attempts to remove and return an object from the <see
- /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>.
+ /// Attempts to remove and return an object from the <see cref="Concurrent.IProducerConsumerCollection{T}"/>.
/// </summary>
/// <param name="item">
/// When this method returns, if the operation was successful, <paramref name="item"/> contains the
@@ -230,10 +239,7 @@ namespace System.Collections.Concurrent
/// <remarks>For <see cref="ConcurrentQueue{T}"/>, this operation will attempt to remove the object
/// from the beginning of the <see cref="ConcurrentQueue{T}"/>.
/// </remarks>
- bool IProducerConsumerCollection<T>.TryTake(out T item)
- {
- return TryDequeue(out item);
- }
+ bool IProducerConsumerCollection<T>.TryTake(out T item) => TryDequeue(out item);
/// <summary>
/// Gets a value that indicates whether the <see cref="ConcurrentQueue{T}"/> is empty.
@@ -250,127 +256,43 @@ namespace System.Collections.Concurrent
{
get
{
- Segment head = _head;
- if (!head.IsEmpty)
- //fast route 1:
- //if current head is not empty, then queue is not empty
- return false;
- else if (head.Next == null)
- //fast route 2:
- //if current head is empty and it's the last segment
- //then queue is empty
- return true;
- else
- //slow route:
- //current head is empty and it is NOT the last segment,
- //it means another thread is growing new segment
- {
- SpinWait spin = new SpinWait();
- while (head.IsEmpty)
- {
- if (head.Next == null)
- return true;
-
- spin.SpinOnce();
- head = _head;
- }
- return false;
- }
+ // IsEmpty == !TryPeek. We use a "resultUsed:false" peek in order to avoid marking
+ // segments as preserved for observation, making IsEmpty a cheaper way than either
+ // TryPeek(out T) or Count == 0 to check whether any elements are in the queue.
+ T ignoredResult;
+ return !TryPeek(out ignoredResult, resultUsed: false);
}
}
- /// <summary>
- /// Copies the elements stored in the <see cref="ConcurrentQueue{T}"/> to a new array.
- /// </summary>
- /// <returns>A new array containing a snapshot of elements copied from the <see
- /// cref="ConcurrentQueue{T}"/>.</returns>
+ /// <summary>Copies the elements stored in the <see cref="ConcurrentQueue{T}"/> to a new array.</summary>
+ /// <returns>A new array containing a snapshot of elements copied from the <see cref="ConcurrentQueue{T}"/>.</returns>
public T[] ToArray()
{
- return ToList().ToArray();
- }
+ // Snap the current contents for enumeration.
+ Segment head, tail;
+ int headHead, tailTail;
+ SnapForObservation(out head, out headHead, out tail, out tailTail);
-#pragma warning disable 0420 // No warning for Interlocked.xxx if compiled with new managed compiler (Roslyn)
- /// <summary>
- /// Copies the <see cref="ConcurrentQueue{T}"/> elements to a new <see
- /// cref="T:System.Collections.Generic.List{T}"/>.
- /// </summary>
- /// <returns>A new <see cref="T:System.Collections.Generic.List{T}"/> containing a snapshot of
- /// elements copied from the <see cref="ConcurrentQueue{T}"/>.</returns>
- private List<T> ToList()
- {
- // Increments the number of active snapshot takers. This increment must happen before the snapshot is
- // taken. At the same time, Decrement must happen after list copying is over. Only in this way, can it
- // eliminate race condition when Segment.TryRemove() checks whether _numSnapshotTakers == 0.
- Interlocked.Increment(ref _numSnapshotTakers);
+ // Count the number of items in that snapped set, and use it to allocate an
+ // array of the right size.
+ long count = GetCount(head, headHead, tail, tailTail);
+ T[] arr = new T[count];
- List<T> list = new List<T>();
- try
+ // Now enumerate the contents, copying each element into the array.
+ using (IEnumerator<T> e = Enumerate(head, headHead, tail, tailTail))
{
- //store head and tail positions in buffer,
- Segment head, tail;
- int headLow, tailHigh;
- GetHeadTailPositions(out head, out tail, out headLow, out tailHigh);
-
- if (head == tail)
+ int i = 0;
+ while (e.MoveNext())
{
- head.AddToList(list, headLow, tailHigh);
- }
- else
- {
- head.AddToList(list, headLow, SEGMENT_SIZE - 1);
- Segment curr = head.Next;
- while (curr != tail)
- {
- curr.AddToList(list, 0, SEGMENT_SIZE - 1);
- curr = curr.Next;
- }
- //Add tail segment
- tail.AddToList(list, 0, tailHigh);
+ arr[i++] = e.Current;
}
+ Debug.Assert(count == i);
}
- finally
- {
- // This Decrement must happen after copying is over.
- Interlocked.Decrement(ref _numSnapshotTakers);
- }
- return list;
- }
- /// <summary>
- /// Store the position of the current head and tail positions.
- /// </summary>
- /// <param name="head">return the head segment</param>
- /// <param name="tail">return the tail segment</param>
- /// <param name="headLow">return the head offset, value range [0, SEGMENT_SIZE]</param>
- /// <param name="tailHigh">return the tail offset, value range [-1, SEGMENT_SIZE-1]</param>
- private void GetHeadTailPositions(out Segment head, out Segment tail,
- out int headLow, out int tailHigh)
- {
- head = _head;
- tail = _tail;
- headLow = head.Low;
- tailHigh = tail.High;
- SpinWait spin = new SpinWait();
-
- //we loop until the observed values are stable and sensible.
- //This ensures that any update order by other methods can be tolerated.
- while (
- //if head and tail changed, retry
- head != _head || tail != _tail
- //if low and high pointers, retry
- || headLow != head.Low || tailHigh != tail.High
- //if head jumps ahead of tail because of concurrent grow and dequeue, retry
- || head._index > tail._index)
- {
- spin.SpinOnce();
- head = _head;
- tail = _tail;
- headLow = head.Low;
- tailHigh = tail.High;
- }
+ // And return it.
+ return arr;
}
-
/// <summary>
/// Gets the number of elements contained in the <see cref="ConcurrentQueue{T}"/>.
/// </summary>
@@ -384,38 +306,140 @@ namespace System.Collections.Concurrent
{
get
{
- //store head and tail positions in buffer,
Segment head, tail;
- int headLow, tailHigh;
- GetHeadTailPositions(out head, out tail, out headLow, out tailHigh);
-
- if (head == tail)
+ int headHead, headTail, tailHead, tailTail;
+ var spinner = new SpinWait();
+ while (true)
{
- return tailHigh - headLow + 1;
+ // Capture the head and tail, as well as the head's head and tail.
+ head = _head;
+ tail = _tail;
+ headHead = Volatile.Read(ref head._headAndTail.Head);
+ headTail = Volatile.Read(ref head._headAndTail.Tail);
+
+ if (head == tail)
+ {
+ // There was a single segment in the queue. If the captured
+ // values still (or again) represent reality, return the segment's
+ // count. A single segment should be the most common case once the
+ // queue's size has stabilized after segments have grown to
+ // the point where growing is no longer needed.
+ if (head == _head &&
+ head == _tail &&
+ headHead == Volatile.Read(ref head._headAndTail.Head) &&
+ headTail == Volatile.Read(ref head._headAndTail.Tail))
+ {
+ return GetCount(head, headHead, headTail);
+ }
+ }
+ else if (head._nextSegment == tail)
+ {
+ // There were two segments in the queue. Get the positions
+ // from the tail, and if the captured values still (or again) match
+ // reality, return the sum of the counts from both segments.
+ tailHead = Volatile.Read(ref tail._headAndTail.Head);
+ tailTail = Volatile.Read(ref tail._headAndTail.Tail);
+ if (head == _head &&
+ tail == _tail &&
+ headHead == Volatile.Read(ref head._headAndTail.Head) &&
+ headTail == Volatile.Read(ref head._headAndTail.Tail) &&
+ tailHead == Volatile.Read(ref tail._headAndTail.Head) &&
+ tailTail == Volatile.Read(ref tail._headAndTail.Tail))
+ {
+ // We got stable values, so we can just compute the sizes based on those
+ // values and return the sum of the counts of the segments.
+ return GetCount(head, headHead, headTail) + GetCount(tail, tailHead, tailTail);
+ }
+ }
+ else
+ {
+ // There were more than two segments. Take the slower path, where we freeze the
+ // queue and then count the now stable segments.
+ SnapForObservation(out head, out headHead, out tail, out tailTail);
+ return unchecked((int)GetCount(head, headHead, tail, tailTail));
+ }
+
+ // We raced with enqueues/dequeues and captured an inconsistent picture of the queue.
+ // Spin and try again.
+ spinner.SpinOnce();
}
+ }
+ }
- //head segment
- int count = SEGMENT_SIZE - headLow;
+ /// <summary>Computes the number of items in a segment based on a fixed head and tail in that segment.</summary>
+ private static int GetCount(Segment s, int head, int tail)
+ {
+ if (head != tail && head != tail - s.FreezeOffset)
+ {
+ head &= s._slotsMask;
+ tail &= s._slotsMask;
+ return head < tail ? tail - head : s._slots.Length - head + tail;
+ }
+ return 0;
+ }
- //middle segment(s), if any, are full.
- //We don't deal with overflow to be consistent with the behavior of generic types in CLR.
- count += SEGMENT_SIZE * ((int)(tail._index - head._index - 1));
+ /// <summary>Gets the number of items in snapped region.</summary>
+ private static long GetCount(Segment head, int headHead, Segment tail, int tailTail)
+ {
+ // All of the segments should have been both frozen for enqueues and preserved for observation.
+ // Validate that here for head and tail; we'll validate it for intermediate segments later.
+ Debug.Assert(head._preservedForObservation);
+ Debug.Assert(head._frozenForEnqueues);
+ Debug.Assert(tail._preservedForObservation);
+ Debug.Assert(tail._frozenForEnqueues);
+
+ long count = 0;
+
+ // Head segment. We've already marked it as frozen for enqueues, so its tail position is fixed,
+ // and we've already marked it as preserved for observation (before we grabbed the head), so we
+ // can safely enumerate from its head to its tail and access its elements.
+ int headTail = (head == tail ? tailTail : Volatile.Read(ref head._headAndTail.Tail)) - head.FreezeOffset;
+ if (headHead < headTail)
+ {
+ // Mask the head and tail for the head segment
+ headHead &= head._slotsMask;
+ headTail &= head._slotsMask;
+
+ // Increase the count by either the one or two regions, based on whether tail
+ // has wrapped to be less than head.
+ count += headHead < headTail ?
+ headTail - headHead :
+ head._slots.Length - headHead + headTail;
+ }
- //tail segment
- count += tailHigh + 1;
+ // We've enumerated the head. If the tail is different from the head, we need to
+ // enumerate the remaining segments.
+ if (head != tail)
+ {
+ // Count the contents of each segment between head and tail, not including head and tail.
+ // Since there were segments before these, for our purposes we consider them to start at
+ // the 0th element, and since there is at least one segment after each, each was frozen
+ // by the time we snapped it, so we can iterate until each's frozen tail.
+ for (Segment s = head._nextSegment; s != tail; s = s._nextSegment)
+ {
+ Debug.Assert(s._preservedForObservation);
+ Debug.Assert(s._frozenForEnqueues);
+ count += s._headAndTail.Tail - s.FreezeOffset;
+ }
- return count;
+ // Finally, enumerate the tail. As with the intermediate segments, there were segments
+ // before this in the snapped region, so we can start counting from the beginning. Unlike
+ // the intermediate segments, we can't just go until the Tail, as that could still be changing;
+ // instead we need to go until the tail we snapped for observation.
+ count += tailTail - tail.FreezeOffset;
}
- }
+ // Return the computed count.
+ return count;
+ }
/// <summary>
/// Copies the <see cref="ConcurrentQueue{T}"/> elements to an existing one-dimensional <see
- /// cref="T:System.Array">Array</see>, starting at the specified array index.
+ /// cref="Array">Array</see>, starting at the specified array index.
/// </summary>
- /// <param name="array">The one-dimensional <see cref="T:System.Array">Array</see> that is the
+ /// <param name="array">The one-dimensional <see cref="Array">Array</see> that is the
/// destination of the elements copied from the
- /// <see cref="ConcurrentQueue{T}"/>. The <see cref="T:System.Array">Array</see> must have zero-based
+ /// <see cref="ConcurrentQueue{T}"/>. The <see cref="Array">Array</see> must have zero-based
/// indexing.</param>
/// <param name="index">The zero-based index in <paramref name="array"/> at which copying
/// begins.</param>
@@ -435,19 +459,36 @@ namespace System.Collections.Concurrent
{
throw new ArgumentNullException(nameof(array));
}
+ if (index < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(index), SR.Collection_CopyTo_ArgumentOutOfRangeException);
+ }
- // We must be careful not to corrupt the array, so we will first accumulate an
- // internal list of elements that we will then copy to the array. This requires
- // some extra allocation, but is necessary since we don't know up front whether
- // the array is sufficiently large to hold the stack's contents.
- ToList().CopyTo(array, index);
- }
+ // Snap for enumeration
+ Segment head, tail;
+ int headHead, tailTail;
+ SnapForObservation(out head, out headHead, out tail, out tailTail);
+
+ // Get the number of items to be enumerated
+ long count = GetCount(head, headHead, tail, tailTail);
+ if (index > array.Length - count)
+ {
+ throw new ArgumentException(); // TODO: finish this
+ }
+ // Copy the items to the target array
+ int i = index;
+ using (IEnumerator<T> e = Enumerate(head, headHead, tail, tailTail))
+ {
+ while (e.MoveNext())
+ {
+ array[i++] = e.Current;
+ }
+ }
+ Debug.Assert(count == i - index);
+ }
- /// <summary>
- /// Returns an enumerator that iterates through the <see
- /// cref="ConcurrentQueue{T}"/>.
- /// </summary>
+ /// <summary>Returns an enumerator that iterates through the <see cref="ConcurrentQueue{T}"/>.</summary>
/// <returns>An enumerator for the contents of the <see
/// cref="ConcurrentQueue{T}"/>.</returns>
/// <remarks>
@@ -458,124 +499,195 @@ namespace System.Collections.Concurrent
/// </remarks>
public IEnumerator<T> GetEnumerator()
{
- // Increments the number of active snapshot takers. This increment must happen before the snapshot is
- // taken. At the same time, Decrement must happen after the enumeration is over. Only in this way, can it
- // eliminate race condition when Segment.TryRemove() checks whether _numSnapshotTakers == 0.
- Interlocked.Increment(ref _numSnapshotTakers);
-
- // Takes a snapshot of the queue.
- // A design flaw here: if a Thread.Abort() happens, we cannot decrement _numSnapshotTakers. But we cannot
- // wrap the following with a try/finally block, otherwise the decrement will happen before the yield return
- // statements in the GetEnumerator (head, tail, headLow, tailHigh) method.
Segment head, tail;
- int headLow, tailHigh;
- GetHeadTailPositions(out head, out tail, out headLow, out tailHigh);
-
- //If we put yield-return here, the iterator will be lazily evaluated. As a result a snapshot of
- // the queue is not taken when GetEnumerator is initialized but when MoveNext() is first called.
- // This is inconsistent with existing generic collections. In order to prevent it, we capture the
- // value of _head in a buffer and call out to a helper method.
- //The old way of doing this was to return the ToList().GetEnumerator(), but ToList() was an
- // unnecessary performance hit.
- return GetEnumerator(head, tail, headLow, tailHigh);
+ int headHead, tailTail;
+ SnapForObservation(out head, out headHead, out tail, out tailTail);
+ return Enumerate(head, headHead, tail, tailTail);
}
/// <summary>
- /// Helper method of GetEnumerator to separate out yield return statement, and prevent lazy evaluation.
+ /// Gets the head and tail information of the current contents of the queue.
+ /// After this call returns, the specified region can be enumerated any number
+ /// of times and will not change.
/// </summary>
- private IEnumerator<T> GetEnumerator(Segment head, Segment tail, int headLow, int tailHigh)
+ private void SnapForObservation(out Segment head, out int headHead, out Segment tail, out int tailTail)
{
- try
+ lock (_crossSegmentLock) // _head and _tail may only change while the lock is held.
{
- SpinWait spin = new SpinWait();
+ // Snap the head and tail
+ head = _head;
+ tail = _tail;
+ Debug.Assert(head != null);
+ Debug.Assert(tail != null);
+ Debug.Assert(tail._nextSegment == null);
- if (head == tail)
+ // Mark them and all segments in between as preserving, and ensure no additional items
+ // can be added to the tail.
+ for (Segment s = head; ; s = s._nextSegment)
{
- for (int i = headLow; i <= tailHigh; i++)
- {
- // If the position is reserved by an Enqueue operation, but the value is not written into,
- // spin until the value is available.
- spin.Reset();
- while (!head._state[i]._value)
- {
- spin.SpinOnce();
- }
- yield return head._array[i];
- }
+ s._preservedForObservation = true;
+ if (s == tail) break;
+ Debug.Assert(s._frozenForEnqueues); // any non-tail should already be marked
+ }
+ tail.EnsureFrozenForEnqueues(); // we want to prevent the tailTail from moving
+
+ // At this point, any dequeues from any segment won't overwrite the value, and
+ // none of the existing segments can have new items enqueued.
+
+ headHead = Volatile.Read(ref head._headAndTail.Head);
+ tailTail = Volatile.Read(ref tail._headAndTail.Tail);
+ }
+ }
+
+ /// <summary>Gets the item stored in the <paramref name="i"/>th entry in <paramref name="segment"/>.</summary>
+ private T GetItemWhenAvailable(Segment segment, int i)
+ {
+ Debug.Assert(segment._preservedForObservation);
+
+ // Get the expected value for the sequence number
+ int expectedSequenceNumberAndMask = (i + 1) & segment._slotsMask;
+
+ // If the expected sequence number is not yet written, we're still waiting for
+ // an enqueuer to finish storing it. Spin until it's there.
+ if ((segment._slots[i].SequenceNumber & segment._slotsMask) != expectedSequenceNumberAndMask)
+ {
+ var spinner = new SpinWait();
+ while ((Volatile.Read(ref segment._slots[i].SequenceNumber) & segment._slotsMask) != expectedSequenceNumberAndMask)
+ {
+ spinner.SpinOnce();
+ }
+ }
+
+ // Return the value from the slot.
+ return segment._slots[i].Item;
+ }
+
+ private IEnumerator<T> Enumerate(Segment head, int headHead, Segment tail, int tailTail)
+ {
+ Debug.Assert(head._preservedForObservation);
+ Debug.Assert(head._frozenForEnqueues);
+ Debug.Assert(tail._preservedForObservation);
+ Debug.Assert(tail._frozenForEnqueues);
+
+ // Head segment. We've already marked it as not accepting any more enqueues,
+ // so its tail position is fixed, and we've already marked it as preserved for
+ // enumeration (before we grabbed its head), so we can safely enumerate from
+ // its head to its tail.
+ int headTail = (head == tail ? tailTail : Volatile.Read(ref head._headAndTail.Tail)) - head.FreezeOffset;
+ if (headHead < headTail)
+ {
+ headHead &= head._slotsMask;
+ headTail &= head._slotsMask;
+
+ if (headHead < headTail)
+ {
+ for (int i = headHead; i < headTail; i++) yield return GetItemWhenAvailable(head, i);
}
else
{
- //iterate on head segment
- for (int i = headLow; i < SEGMENT_SIZE; i++)
- {
- // If the position is reserved by an Enqueue operation, but the value is not written into,
- // spin until the value is available.
- spin.Reset();
- while (!head._state[i]._value)
- {
- spin.SpinOnce();
- }
- yield return head._array[i];
- }
- //iterate on middle segments
- Segment curr = head.Next;
- while (curr != tail)
- {
- for (int i = 0; i < SEGMENT_SIZE; i++)
- {
- // If the position is reserved by an Enqueue operation, but the value is not written into,
- // spin until the value is available.
- spin.Reset();
- while (!curr._state[i]._value)
- {
- spin.SpinOnce();
- }
- yield return curr._array[i];
- }
- curr = curr.Next;
- }
+ for (int i = headHead; i < head._slots.Length; i++) yield return GetItemWhenAvailable(head, i);
+ for (int i = 0; i < headTail; i++) yield return GetItemWhenAvailable(head, i);
+ }
+ }
- //iterate on tail segment
- for (int i = 0; i <= tailHigh; i++)
+ // We've enumerated the head. If the tail is the same, we're done.
+ if (head != tail)
+ {
+ // Each segment between head and tail, not including head and tail. Since there were
+ // segments before these, for our purposes we consider it to start at the 0th element.
+ for (Segment s = head._nextSegment; s != tail; s = s._nextSegment)
+ {
+ Debug.Assert(s._preservedForObservation, "Would have had to been preserved as a segment part of enumeration");
+ Debug.Assert(s._frozenForEnqueues, "Would have had to be frozen for enqueues as it's intermediate");
+
+ int sTail = s._headAndTail.Tail - s.FreezeOffset;
+ for (int i = 0; i < sTail; i++)
{
- // If the position is reserved by an Enqueue operation, but the value is not written into,
- // spin until the value is available.
- spin.Reset();
- while (!tail._state[i]._value)
- {
- spin.SpinOnce();
- }
- yield return tail._array[i];
+ yield return GetItemWhenAvailable(s, i);
}
}
- }
- finally
- {
- // This Decrement must happen after the enumeration is over.
- Interlocked.Decrement(ref _numSnapshotTakers);
+
+ // Enumerate the tail. Since there were segments before this, we can just start at
+ // its beginning, and iterate until the tail we already grabbed.
+ tailTail -= tail.FreezeOffset;
+ for (int i = 0; i < tailTail; i++)
+ {
+ yield return GetItemWhenAvailable(tail, i);
+ }
}
}
- /// <summary>
- /// Adds an object to the end of the <see cref="ConcurrentQueue{T}"/>.
- /// </summary>
- /// <param name="item">The object to add to the end of the <see
- /// cref="ConcurrentQueue{T}"/>. The value can be a null reference
- /// (Nothing in Visual Basic) for reference types.
+ /// <summary>Round the specified value up to the next power of 2, if it isn't one already.</summary>
+ private static int RoundUpToPowerOf2(int i)
+ {
+ --i;
+ i |= i >> 1;
+ i |= i >> 2;
+ i |= i >> 4;
+ i |= i >> 8;
+ i |= i >> 16;
+ return i + 1;
+ }
+
+ /// <summary>Adds an object to the end of the <see cref="ConcurrentQueue{T}"/>.</summary>
+ /// <param name="item">
+ /// The object to add to the end of the <see cref="ConcurrentQueue{T}"/>.
+ /// The value can be a null reference (Nothing in Visual Basic) for reference types.
/// </param>
public void Enqueue(T item)
{
- SpinWait spin = new SpinWait();
+ // Try to enqueue to the current tail.
+ if (!_tail.TryEnqueue(item))
+ {
+ // If we're unable to, we need to take a slow path that will
+ // try to add a new tail segment.
+ EnqueueSlow(item);
+ }
+ }
+
+ /// <summary>Adds to the end of the queue, adding a new segment if necessary.</summary>
+ private void EnqueueSlow(T item)
+ {
while (true)
{
Segment tail = _tail;
- if (tail.TryAppend(item))
+
+ // Try to append to the existing tail.
+ if (tail.TryEnqueue(item))
+ {
return;
- spin.SpinOnce();
+ }
+
+ // If we were unsuccessful, take the lock so that we can compare and manipulate
+ // the tail. Assuming another enqueuer hasn't already added a new segment,
+ // do so, then loop around to try enqueueing again.
+ lock (_crossSegmentLock)
+ {
+ if (tail == _tail)
+ {
+ // Make sure no one else can enqueue to this segment.
+ tail.EnsureFrozenForEnqueues();
+
+ // We determine the new segment's length based on the old length.
+ // In general, we double the size of the segment, to make it less likely
+ // that we'll need to grow again. However, if the tail segment is marked
+ // as preserved for observation, something caused us to avoid reusing this
+ // segment, and if that happens a lot and we grow, we'll end up allocating
+ // lots of wasted space. As such, in such situations we reset back to the
+ // initial segment length; if these observations are happening frequently,
+ // this will help to avoid wasted memory, and if they're not, we'll
+ // relatively quickly grow again to a larger size.
+ int nextSize = tail._preservedForObservation ? InitialSegmentLength : tail.Capacity * 2;
+ var newTail = new Segment(nextSize);
+
+ // Hook up the new tail.
+ tail._nextSegment = newTail;
+ _tail = newTail;
+ }
+ }
}
}
-
/// <summary>
/// Attempts to remove and return the object at the beginning of the <see
/// cref="ConcurrentQueue{T}"/>.
@@ -584,364 +696,433 @@ namespace System.Collections.Concurrent
/// When this method returns, if the operation was successful, <paramref name="result"/> contains the
/// object removed. If no object was available to be removed, the value is unspecified.
/// </param>
- /// <returns>true if an element was removed and returned from the beginning of the <see
- /// cref="ConcurrentQueue{T}"/>
- /// successfully; otherwise, false.</returns>
- public bool TryDequeue(out T result)
+ /// <returns>
+ /// true if an element was removed and returned from the beginning of the
+ /// <see cref="ConcurrentQueue{T}"/> successfully; otherwise, false.
+ /// </returns>
+ public bool TryDequeue(out T result) =>
+ _head.TryDequeue(out result) || // fast-path that operates just on the head segment
+ TryDequeueSlow(out result); // slow path that needs to fix up segments
+
+ /// <summary>Tries to dequeue an item, removing empty segments as needed.</summary>
+ private bool TryDequeueSlow(out T item)
{
- while (!IsEmpty)
+ while (true)
{
+ // Get the current head
Segment head = _head;
- if (head.TryRemove(out result))
+
+ // Try to take. If we're successful, we're done.
+ if (head.TryDequeue(out item))
+ {
+ return true;
+ }
+
+ // Check to see whether this segment is the last. If it is, we can consider
+ // this to be a moment-in-time empty condition (even though between the TryDequeue
+ // check and this check, another item could have arrived).
+ if (head._nextSegment == null)
+ {
+ item = default(T);
+ return false;
+ }
+
+ // At this point we know that head.Next != null, which means
+ // this segment has been frozen for additional enqueues. But between
+ // the time that we ran TryDequeue and checked for a next segment,
+ // another item could have been added. Try to dequeue one more time
+ // to confirm that the segment is indeed empty.
+ Debug.Assert(head._frozenForEnqueues);
+ if (head.TryDequeue(out item))
+ {
return true;
- //since method IsEmpty spins, we don't need to spin in the while loop
+ }
+
+ // This segment is frozen (nothing more can be added) and empty (nothing is in it).
+ // Update head to point to the next segment in the list, assuming no one's beat us to it.
+ lock (_crossSegmentLock)
+ {
+ if (head == _head)
+ {
+ _head = head._nextSegment;
+ }
+ }
}
- result = default(T);
- return false;
}
/// <summary>
/// Attempts to return an object from the beginning of the <see cref="ConcurrentQueue{T}"/>
/// without removing it.
/// </summary>
- /// <param name="result">When this method returns, <paramref name="result"/> contains an object from
- /// the beginning of the <see cref="T:System.Collections.Concurrent.ConcurrentQueue{T}"/> or an
- /// unspecified value if the operation failed.</param>
+ /// <param name="result">
+ /// When this method returns, <paramref name="result"/> contains an object from
+ /// the beginning of the <see cref="Concurrent.ConcurrentQueue{T}"/> or default(T)
+ /// if the operation failed.
+ /// </param>
/// <returns>true if and object was returned successfully; otherwise, false.</returns>
- public bool TryPeek(out T result)
- {
- Interlocked.Increment(ref _numSnapshotTakers);
+ /// <remarks>
+ /// For determining whether the collection contains any items, use of the <see cref="IsEmpty"/>
+ /// property is recommended rather than peeking.
+ /// </remarks>
+ public bool TryPeek(out T result) => TryPeek(out result, resultUsed: true);
- while (!IsEmpty)
+ /// <summary>Attempts to retrieve the value for the first element in the queue.</summary>
+ /// <param name="result">The value of the first element, if found.</param>
+ /// <param name="resultUsed">true if the result is neede; otherwise false if only the true/false outcome is needed.</param>
+ /// <returns>true if an element was found; otherwise, false.</returns>
+ private bool TryPeek(out T result, bool resultUsed)
+ {
+ // Starting with the head segment, look through all of the segments
+ // for the first one we can find that's not empty.
+ Segment s = _head;
+ while (true)
{
- Segment head = _head;
- if (head.TryPeek(out result))
+ // Grab the next segment from this one, before we peek.
+ // This is to be able to see whether the value has changed
+ // during the peek operation.
+ Segment next = Volatile.Read(ref s._nextSegment);
+
+ // Peek at the segment. If we find an element, we're done.
+ if (s.TryPeek(out result, resultUsed))
{
- Interlocked.Decrement(ref _numSnapshotTakers);
return true;
}
- //since method IsEmpty spins, we don't need to spin in the while loop
+
+ // The current segment was empty at the moment we checked.
+
+ if (next != null)
+ {
+ // If prior to the peek there was already a next segment, then
+ // during the peek no additional items could have been enqueued
+ // to it and we can just move on to check the next segment.
+ Debug.Assert(next == s._nextSegment);
+ s = next;
+ }
+ else if (Volatile.Read(ref s._nextSegment) == null)
+ {
+ // The next segment is null. Nothing more to peek at.
+ break;
+ }
+
+ // The next segment was null before we peeked but non-null after.
+ // That means either when we peeked the first segment had
+ // already been frozen but the new segment not yet added,
+ // or that the first segment was empty and between the time
+ // that we peeked and then checked _nextSegment, so many items
+ // were enqueued that we filled the first segment and went
+ // into the next. Since we need to peek in order, we simply
+ // loop around again to peek on the same segment. The next
+ // time around on this segment we'll then either successfully
+ // peek or we'll find that next was non-null before peeking,
+ // and we'll traverse to that segment.
}
+
result = default(T);
- Interlocked.Decrement(ref _numSnapshotTakers);
return false;
}
-
/// <summary>
- /// private class for ConcurrentQueue.
- /// a queue is a linked list of small arrays, each node is called a segment.
- /// A segment contains an array, a pointer to the next segment, and _low, _high indices recording
- /// the first and last valid elements of the array.
+ /// Provides a multi-producer, multi-consumer thread-safe bounded segment. When the queue is full,
+ /// enqueues fail and return false. When the queue is empty, dequeues fail and return null.
+ /// These segments are linked together to form the unbounded <see cref="ConcurrentQueue{T}"/>.
/// </summary>
- private class Segment
+ [DebuggerDisplay("Capacity = {Capacity}")]
+ private sealed class Segment
{
- //we define two volatile arrays: _array and _state. Note that the accesses to the array items
- //do not get volatile treatment. But we don't need to worry about loading adjacent elements or
- //store/load on adjacent elements would suffer reordering.
- // - Two stores: these are at risk, but CLRv2 memory model guarantees store-release hence we are safe.
- // - Two loads: because one item from two volatile arrays are accessed, the loads of the array references
- // are sufficient to prevent reordering of the loads of the elements.
- internal volatile T[] _array;
-
- // For each entry in _array, the corresponding entry in _state indicates whether this position contains
- // a valid value. _state is initially all false.
- internal volatile VolatileBool[] _state;
-
- //pointer to the next segment. null if the current segment is the last segment
- private volatile Segment _next;
-
- //We use this zero based index to track how many segments have been created for the queue, and
- //to compute how many active segments are there currently.
- // * The number of currently active segments is : _tail._index - _head._index + 1;
- // * _index is incremented with every Segment.Grow operation. We use Int64 type, and we can safely
- // assume that it never overflows. To overflow, we need to do 2^63 increments, even at a rate of 4
- // billion (2^32) increments per second, it takes 2^31 seconds, which is about 64 years.
- internal readonly long _index;
-
- //indices of where the first and last valid values
- // - _low points to the position of the next element to pop from this segment, range [0, infinity)
- // _low >= SEGMENT_SIZE implies the segment is disposable
- // - _high points to the position of the latest pushed element, range [-1, infinity)
- // _high == -1 implies the segment is new and empty
- // _high >= SEGMENT_SIZE-1 means this segment is ready to grow.
- // and the thread who sets _high to SEGMENT_SIZE-1 is responsible to grow the segment
- // - Math.Min(_low, SEGMENT_SIZE) > Math.Min(_high, SEGMENT_SIZE-1) implies segment is empty
- // - initially _low =0 and _high=-1;
- private volatile int _low;
- private volatile int _high;
-
- private volatile ConcurrentQueue<T> _source;
-
- /// <summary>
- /// Create and initialize a segment with the specified index.
- /// </summary>
- internal Segment(long index, ConcurrentQueue<T> source)
+ // Segment design is inspired by the algorithm outlined at:
+ // http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
+
+ /// <summary>The array of items in this queue. Each slot contains the item in that slot and its "sequence number".</summary>
+ internal readonly Slot[] _slots;
+ /// <summary>Mask for quickly accessing a position within the queue's array.</summary>
+ internal readonly int _slotsMask;
+ /// <summary>The head and tail positions, with padding to help avoid false sharing contention.</summary>
+ /// <remarks>Dequeueing happens from the head, enqueueing happens at the tail.</remarks>
+ internal PaddedHeadAndTail _headAndTail; // mutable struct: do not make this readonly
+
+ /// <summary>Indicates whether the segment has been marked such that dequeues don't overwrite the removed data.</summary>
+ internal bool _preservedForObservation;
+ /// <summary>Indicates whether the segment has been marked such that no additional items may be enqueued.</summary>
+ internal bool _frozenForEnqueues;
+ /// <summary>The segment following this one in the queue, or null if this segment is the last in the queue.</summary>
+ internal Segment _nextSegment;
+
+ /// <summary>Creates the segment.</summary>
+ /// <param name="boundedLength">
+ /// The maximum number of elements the segment can contain. Must be a power of 2.
+ /// </param>
+ public Segment(int boundedLength)
{
- _array = new T[SEGMENT_SIZE];
- _state = new VolatileBool[SEGMENT_SIZE]; //all initialized to false
- _high = -1;
- Debug.Assert(index >= 0);
- _index = index;
- _source = source;
- }
-
- /// <summary>
- /// return the next segment
- /// </summary>
- internal Segment Next
- {
- get { return _next; }
- }
-
-
- /// <summary>
- /// return true if the current segment is empty (doesn't have any element available to dequeue,
- /// false otherwise
- /// </summary>
- internal bool IsEmpty
- {
- get { return (Low > High); }
- }
-
- /// <summary>
- /// Add an element to the tail of the current segment
- /// exclusively called by ConcurrentQueue.InitializedFromCollection
- /// InitializeFromCollection is responsible to guarantee that there is no index overflow,
- /// and there is no contention
- /// </summary>
- /// <param name="value"></param>
- internal void UnsafeAdd(T value)
- {
- Debug.Assert(_high < SEGMENT_SIZE - 1);
- _high++;
- _array[_high] = value;
- _state[_high]._value = true;
- }
-
- /// <summary>
- /// Create a new segment and append to the current one
- /// Does not update the _tail pointer
- /// exclusively called by ConcurrentQueue.InitializedFromCollection
- /// InitializeFromCollection is responsible to guarantee that there is no index overflow,
- /// and there is no contention
- /// </summary>
- /// <returns>the reference to the new Segment</returns>
- internal Segment UnsafeGrow()
- {
- Debug.Assert(_high >= SEGMENT_SIZE - 1);
- Segment newSegment = new Segment(_index + 1, _source); //_index is Int64, we don't need to worry about overflow
- _next = newSegment;
- return newSegment;
+ // Validate the length
+ Debug.Assert(boundedLength >= 2, $"Must be >= 2, got {boundedLength}");
+ Debug.Assert((boundedLength & (boundedLength - 1)) == 0, $"Must be a power of 2, got {boundedLength}");
+
+ // Initialize the slots and the mask. The mask is used as a way of quickly doing "% _slots.Length",
+ // instead letting us do "& _slotsMask".
+ _slots = new Slot[boundedLength];
+ _slotsMask = boundedLength - 1;
+
+ // Initialize the sequence number for each slot. The sequence number provides a ticket that
+ // allows dequeuers to know whether they can dequeue and enqueuers to know whether they can
+ // enqueue. An enqueuer at position N can enqueue when the sequence number is N, and a dequeuer
+ // for position N can dequeue when the sequence number is N + 1. When an enqueuer is done writing
+ // at position N, it sets the sequence number to N so that a dequeuer will be able to dequeue,
+ // and when a dequeuer is done dequeueing at position N, it sets the sequence number to N + _slots.Length,
+ // so that when an enqueuer loops around the slots, it'll find that the sequence number at
+ // position N is N. This also means that when an enqueuer finds that at position N the sequence
+ // number is < N, there is still a value in that slot, i.e. the segment is full, and when a
+ // dequeuer finds that the value in a slot is < N + 1, there is nothing currently available to
+ // dequeue. (It is possible for multiple enqueuers to enqueue concurrently, writing into
+ // subsequent slots, and to have the first enqueuer take longer, so that the slots for 1, 2, 3, etc.
+ // may have values, but the 0th slot may still be being filled... in that case, TryDequeue will
+ // return false.)
+ for (int i = 0; i < _slots.Length; i++)
+ {
+ _slots[i].SequenceNumber = i;
+ }
}
- /// <summary>
- /// Create a new segment and append to the current one
- /// Update the _tail pointer
- /// This method is called when there is no contention
- /// </summary>
- internal void Grow()
- {
- //no CAS is needed, since there is no contention (other threads are blocked, busy waiting)
- Segment newSegment = new Segment(_index + 1, _source); //_index is Int64, we don't need to worry about overflow
- _next = newSegment;
- Debug.Assert(_source._tail == this);
- _source._tail = _next;
- }
+ /// <summary>Gets the number of elements this segment can store.</summary>
+ internal int Capacity => _slots.Length;
+ /// <summary>Gets the "freeze offset" for this segment.</summary>
+ internal int FreezeOffset => _slots.Length * 2;
/// <summary>
- /// Try to append an element at the end of this segment.
+ /// Ensures that the segment will not accept any subsequent enqueues that aren't already underway.
/// </summary>
- /// <param name="value">the element to append</param>
- /// <param name="tail">The tail.</param>
- /// <returns>true if the element is appended, false if the current segment is full</returns>
- /// <remarks>if appending the specified element succeeds, and after which the segment is full,
- /// then grow the segment</remarks>
- internal bool TryAppend(T value)
+ /// <remarks>
+ /// When we mark a segment as being frozen for additional enqueues,
+ /// we set the <see cref="_frozenForEnqueues"/> bool, but that's mostly
+ /// as a small helper to avoid marking it twice. The real marking comes
+ /// by modifying the Tail for the segment, increasing it by this
+ /// <see cref="FreezeOffset"/>. This effectively knocks it off the
+ /// sequence expected by future enqueuers, such that any additional enqueuer
+ /// will be unable to enqueue due to it not lining up with the expected
+ /// sequence numbers. This value is chosen specially so that Tail will grow
+ /// to a value that maps to the same slot but that won't be confused with
+ /// any other enqueue/dequeue sequence number.
+ /// </remarks>
+ internal void EnsureFrozenForEnqueues() // must only be called while queue's segment lock is held
{
- //quickly check if _high is already over the boundary, if so, bail out
- if (_high >= SEGMENT_SIZE - 1)
+ if (!_frozenForEnqueues) // flag used to ensure we don't increase the Tail more than once if frozen more than once
{
- return false;
- }
+ _frozenForEnqueues = true;
- //Now we will use a CAS to increment _high, and store the result in newhigh.
- //Depending on how many free spots left in this segment and how many threads are doing this Increment
- //at this time, the returning "newhigh" can be
- // 1) < SEGMENT_SIZE - 1 : we took a spot in this segment, and not the last one, just insert the value
- // 2) == SEGMENT_SIZE - 1 : we took the last spot, insert the value AND grow the segment
- // 3) > SEGMENT_SIZE - 1 : we failed to reserve a spot in this segment, we return false to
- // Queue.Enqueue method, telling it to try again in the next segment.
-
- int newhigh = SEGMENT_SIZE; //initial value set to be over the boundary
-
- //We need do Interlocked.Increment and value/state update in a finally block to ensure that they run
- //without interruption. This is to prevent anything from happening between them, and another dequeue
- //thread maybe spinning forever to wait for _state[] to be true;
- try
- { }
- finally
- {
- newhigh = Interlocked.Increment(ref _high);
- if (newhigh <= SEGMENT_SIZE - 1)
+ // Increase the tail by FreezeOffset, spinning until we're successful in doing so.
+ var spinner = new SpinWait();
+ while (true)
{
- _array[newhigh] = value;
- _state[newhigh]._value = true;
- }
-
- //if this thread takes up the last slot in the segment, then this thread is responsible
- //to grow a new segment. Calling Grow must be in the finally block too for reliability reason:
- //if thread abort during Grow, other threads will be left busy spinning forever.
- if (newhigh == SEGMENT_SIZE - 1)
- {
- Grow();
+ int tail = Volatile.Read(ref _headAndTail.Tail);
+ if (Interlocked.CompareExchange(ref _headAndTail.Tail, tail + FreezeOffset, tail) == tail)
+ {
+ break;
+ }
+ spinner.SpinOnce();
}
}
-
- //if newhigh <= SEGMENT_SIZE-1, it means the current thread successfully takes up a spot
- return newhigh <= SEGMENT_SIZE - 1;
}
-
- /// <summary>
- /// try to remove an element from the head of current segment
- /// </summary>
- /// <param name="result">The result.</param>
- /// <param name="head">The head.</param>
- /// <returns>return false only if the current segment is empty</returns>
- internal bool TryRemove(out T result)
+ /// <summary>Tries to dequeue an element from the queue.</summary>
+ public bool TryDequeue(out T item)
{
- SpinWait spin = new SpinWait();
- int lowLocal = Low, highLocal = High;
- while (lowLocal <= highLocal)
+ // Loop in case of contention...
+ var spinner = new SpinWait();
+ while (true)
{
- //try to update _low
- if (Interlocked.CompareExchange(ref _low, lowLocal + 1, lowLocal) == lowLocal)
- {
- //if the specified value is not available (this spot is taken by a push operation,
- // but the value is not written into yet), then spin
- SpinWait spinLocal = new SpinWait();
- while (!_state[lowLocal]._value)
- {
- spinLocal.SpinOnce();
- }
- result = _array[lowLocal];
+ // Get the head at which to try to dequeue.
+ int currentHead = Volatile.Read(ref _headAndTail.Head);
+ int slotsIndex = currentHead & _slotsMask;
- // If there is no other thread taking snapshot (GetEnumerator(), ToList(), etc), reset the deleted entry to null.
- // It is ok if after this conditional check _numSnapshotTakers becomes > 0, because new snapshots won't include
- // the deleted entry at _array[lowLocal].
- if (_source._numSnapshotTakers <= 0)
- {
- _array[lowLocal] = default(T); //release the reference to the object.
- }
+ // Read the sequence number for the head position.
+ int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
- //if the current thread sets _low to SEGMENT_SIZE, which means the current segment becomes
- //disposable, then this thread is responsible to dispose this segment, and reset _head
- if (lowLocal + 1 >= SEGMENT_SIZE)
+ // We can dequeue from this slot if it's been filled by an enqueuer, which
+ // would have left the sequence number at pos+1.
+ if (sequenceNumber == currentHead + 1)
+ {
+ // We may be racing with other dequeuers. Try to reserve the slot by incrementing
+ // the head. Once we've done that, no one else will be able to read from this slot,
+ // and no enqueuer will be able to read from this slot until we've written the new
+ // sequence number. WARNING: The next few lines are not reliable on a runtime that
+ // supports thread aborts. If a thread abort were to sneak in after the CompareExchange
+ // but before the Volatile.Write, enqueuers trying to enqueue into this slot would
+ // spin indefinitely. If this implementation is ever used on such a platform, this
+ // if block should be wrapped in a finally / prepared region.
+ if (Interlocked.CompareExchange(ref _headAndTail.Head, currentHead + 1, currentHead) == currentHead)
{
- // Invariant: we only dispose the current _head, not any other segment
- // In usual situation, disposing a segment is simply setting _head to _head._next
- // But there is one special case, where _head and _tail points to the same and ONLY
- //segment of the queue: Another thread A is doing Enqueue and finds that it needs to grow,
- //while the *current* thread is doing *this* Dequeue operation, and finds that it needs to
- //dispose the current (and ONLY) segment. Then we need to wait till thread A finishes its
- //Grow operation, this is the reason of having the following while loop
- spinLocal = new SpinWait();
- while (_next == null)
+ // Successfully reserved the slot. Note that after the above CompareExchange, other threads
+ // trying to dequeue from this slot will end up spinning until we do the subsequent Write.
+ item = _slots[slotsIndex].Item;
+ if (!Volatile.Read(ref _preservedForObservation))
{
- spinLocal.SpinOnce();
+ // If we're preserving, though, we don't zero out the slot, as we need it for
+ // enumerations, peeking, ToArray, etc. And we don't update the sequence number,
+ // so that an enqueuer will see it as full and be forced to move to a new segment.
+ _slots[slotsIndex].Item = default(T);
+ Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentHead + _slots.Length);
}
- Debug.Assert(_source._head == this);
- _source._head = _next;
+ return true;
}
- return true;
}
- else
+ else if (sequenceNumber < currentHead + 1)
{
- //CAS failed due to contention: spin briefly and retry
- spin.SpinOnce();
- lowLocal = Low; highLocal = High;
+ // The sequence number was less than what we needed, which means this slot doesn't
+ // yet contain a value we can dequeue, i.e. the segment is empty. Technically it's
+ // possible that multiple enqueuers could have written concurrently, with those
+ // getting later slots actually finishing first, so there could be elements after
+ // this one that are available, but we need to dequeue in order. So before declaring
+ // failure and that the segment is empty, we check the tail to see if we're actually
+ // empty or if we're just waiting for items in flight or after this one to become available.
+ bool frozen = _frozenForEnqueues;
+ int currentTail = Volatile.Read(ref _headAndTail.Tail);
+ if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
+ {
+ item = default(T);
+ return false;
+ }
+
+ // It's possible it could have become frozen after we checked _frozenForEnqueues
+ // and before reading the tail. That's ok: in that rare race condition, we just
+ // loop around again.
}
- }//end of while
- result = default(T);
- return false;
+
+ // Lost a race. Spin a bit, then try again.
+ spinner.SpinOnce();
+ }
}
-#pragma warning restore 0420
- /// <summary>
- /// try to peek the current segment
- /// </summary>
- /// <param name="result">holds the return value of the element at the head position,
- /// value set to default(T) if there is no such an element</param>
- /// <returns>true if there are elements in the current segment, false otherwise</returns>
- internal bool TryPeek(out T result)
+
+ /// <summary>Tries to peek at an element from the queue, without removing it.</summary>
+ public bool TryPeek(out T result, bool resultUsed)
{
- result = default(T);
- int lowLocal = Low;
- if (lowLocal > High)
- return false;
- SpinWait spin = new SpinWait();
- while (!_state[lowLocal]._value)
+ if (resultUsed)
{
- spin.SpinOnce();
+ // In order to ensure we don't get a torn read on the value, we mark the segment
+ // as preserving for observation. Additional items can still be enqueued to this
+ // segment, but no space will be freed during dequeues, such that the segment will
+ // no longer be reusable.
+ _preservedForObservation = true;
+ Interlocked.MemoryBarrier();
}
- result = _array[lowLocal];
- return true;
- }
- /// <summary>
- /// Adds part or all of the current segment into a List.
- /// </summary>
- /// <param name="list">the list to which to add</param>
- /// <param name="start">the start position</param>
- /// <param name="end">the end position</param>
- internal void AddToList(List<T> list, int start, int end)
- {
- for (int i = start; i <= end; i++)
+ // Loop in case of contention...
+ var spinner = new SpinWait();
+ while (true)
{
- SpinWait spin = new SpinWait();
- while (!_state[i]._value)
+ // Get the head at which to try to peek.
+ int currentHead = Volatile.Read(ref _headAndTail.Head);
+ int slotsIndex = currentHead & _slotsMask;
+
+ // Read the sequence number for the head position.
+ int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
+
+ // We can peek from this slot if it's been filled by an enqueuer, which
+ // would have left the sequence number at pos+1.
+ if (sequenceNumber == currentHead + 1)
{
- spin.SpinOnce();
+ result = resultUsed ? _slots[slotsIndex].Item : default(T);
+ return true;
}
- list.Add(_array[i]);
+ else if (sequenceNumber < currentHead + 1)
+ {
+ // The sequence number was less than what we needed, which means this slot doesn't
+ // yet contain a value we can peek, i.e. the segment is empty. Technically it's
+ // possible that multiple enqueuers could have written concurrently, with those
+ // getting later slots actually finishing first, so there could be elements after
+ // this one that are available, but we need to peek in order. So before declaring
+ // failure and that the segment is empty, we check the tail to see if we're actually
+ // empty or if we're just waiting for items in flight or after this one to become available.
+ bool frozen = _frozenForEnqueues;
+ int currentTail = Volatile.Read(ref _headAndTail.Tail);
+ if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
+ {
+ result = default(T);
+ return false;
+ }
+
+ // It's possible it could have become frozen after we checked _frozenForEnqueues
+ // and before reading the tail. That's ok: in that rare race condition, we just
+ // loop around again.
+ }
+
+ // Lost a race. Spin a bit, then try again.
+ spinner.SpinOnce();
}
}
/// <summary>
- /// return the position of the head of the current segment
- /// Value range [0, SEGMENT_SIZE], if it's SEGMENT_SIZE, it means this segment is exhausted and thus empty
+ /// Attempts to enqueue the item. If successful, the item will be stored
+ /// in the queue and true will be returned; otherwise, the item won't be stored, and false
+ /// will be returned.
/// </summary>
- internal int Low
+ public bool TryEnqueue(T item)
{
- get
+ // Loop in case of contention...
+ var spinner = new SpinWait();
+ while (true)
{
- return Math.Min(_low, SEGMENT_SIZE);
+ // Get the tail at which to try to return.
+ int currentTail = Volatile.Read(ref _headAndTail.Tail);
+ int slotsIndex = currentTail & _slotsMask;
+
+ // Read the sequence number for the tail position.
+ int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
+
+ // The slot is empty and ready for us to enqueue into it if its sequence
+ // number matches the slot.
+ if (sequenceNumber == currentTail)
+ {
+ // We may be racing with other enqueuers. Try to reserve the slot by incrementing
+ // the tail. Once we've done that, no one else will be able to write to this slot,
+ // and no dequeuer will be able to read from this slot until we've written the new
+ // sequence number. WARNING: The next few lines are not reliable on a runtime that
+ // supports thread aborts. If a thread abort were to sneak in after the CompareExchange
+ // but before the Volatile.Write, other threads will spin trying to access this slot.
+ // If this implementation is ever used on such a platform, this if block should be
+ // wrapped in a finally / prepared region.
+ if (Interlocked.CompareExchange(ref _headAndTail.Tail, currentTail + 1, currentTail) == currentTail)
+ {
+ // Successfully reserved the slot. Note that after the above CompareExchange, other threads
+ // trying to return will end up spinning until we do the subsequent Write.
+ _slots[slotsIndex].Item = item;
+ Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentTail + 1);
+ return true;
+ }
+ }
+ else if (sequenceNumber < currentTail)
+ {
+ // The sequence number was less than what we needed, which means this slot still
+ // contains a value, i.e. the segment is full. Technically it's possible that multiple
+ // dequeuers could have read concurrently, with those getting later slots actually
+ // finishing first, so there could be spaces after this one that are available, but
+ // we need to enqueue in order.
+ return false;
+ }
+
+ // Lost a race. Spin a bit, then try again.
+ spinner.SpinOnce();
}
}
- /// <summary>
- /// return the logical position of the tail of the current segment
- /// Value range [-1, SEGMENT_SIZE-1]. When it's -1, it means this is a new segment and has no element yet
- /// </summary>
- internal int High
+ /// <summary>Represents a slot in the queue.</summary>
+ [StructLayout(LayoutKind.Auto)]
+ [DebuggerDisplay("Item = {Item}, SequenceNumber = {SequenceNumber}")]
+ internal struct Slot
{
- get
- {
- //if _high > SEGMENT_SIZE, it means it's out of range, we should return
- //SEGMENT_SIZE-1 as the logical position
- return Math.Min(_high, SEGMENT_SIZE - 1);
- }
+ /// <summary>The item.</summary>
+ public T Item;
+ /// <summary>The sequence number for this slot, used to synchronize between enqueuers and dequeuers.</summary>
+ public int SequenceNumber;
}
}
- }//end of class Segment
+ }
- /// <summary>
- /// A wrapper struct for volatile bool, please note the copy of the struct it self will not be volatile
- /// for example this statement will not include in volatile operation volatileBool1 = volatileBool2 the jit will copy the struct and will ignore the volatile
- /// </summary>
- struct VolatileBool
+ /// <summary>Padded head and tail indices, to avoid false sharing between producers and consumers.</summary>
+ [DebuggerDisplay("Head = {Head}, Tail = {Tail}")]
+ [StructLayout(LayoutKind.Explicit, Size = 192)] // padding before/between/after fields based on typical cache line size of 64
+ internal struct PaddedHeadAndTail
{
- public volatile bool _value;
+ [FieldOffset(64)] public int Head;
+ [FieldOffset(128)] public int Tail;
}
}
diff --git a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentStack.cs b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentStack.cs
index fd272132c1..cf7af45e6a 100644
--- a/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentStack.cs
+++ b/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentStack.cs
@@ -437,12 +437,10 @@ namespace System.Collections.Concurrent
while (Interlocked.CompareExchange(
ref _head, head, tail._next) != tail._next);
-#if FEATURE_TRACING
if (CDSCollectionETWBCLProvider.Log.IsEnabled())
{
CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPushFailed(spin.Count);
}
-#endif
}
/// <summary>
@@ -662,12 +660,11 @@ namespace System.Collections.Concurrent
// Is the stack empty?
if (head == null)
{
-#if FEATURE_TRACING
if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled())
{
CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spin.Count);
}
-#endif
+
poppedHead = null;
return 0;
}
@@ -681,12 +678,11 @@ namespace System.Collections.Concurrent
// Try to swap the new head. If we succeed, break out of the loop.
if (Interlocked.CompareExchange(ref _head, next._next, head) == head)
{
-#if FEATURE_TRACING
if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled())
{
CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spin.Count);
}
-#endif
+
// Return the popped Node.
poppedHead = head;
return nodesCount;
diff --git a/src/System.Collections.Concurrent/tests/ConcurrentBagTests.cs b/src/System.Collections.Concurrent/tests/ConcurrentBagTests.cs
index 9c3293dc6a..39a93b0401 100644
--- a/src/System.Collections.Concurrent/tests/ConcurrentBagTests.cs
+++ b/src/System.Collections.Concurrent/tests/ConcurrentBagTests.cs
@@ -3,8 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
-using System.Collections.Tests;
-using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -12,457 +10,197 @@ using Xunit;
namespace System.Collections.Concurrent.Tests
{
- /// <summary>The class that contains the unit tests of the LazyInit.</summary>
- public class ConcurrentBagTests : IEnumerable_Generic_Tests<int>
+ public class ConcurrentBagTests : ProducerConsumerCollectionTests
{
- protected override IEnumerable<ModifyEnumerable> ModifyEnumerables => new List<ModifyEnumerable>();
- protected override IEnumerable<int> GenericIEnumerableFactory(int count) => new ConcurrentBag<int>(Enumerable.Range(0, count));
- protected override int CreateT(int seed) => new Random(seed).Next();
- protected override EnumerableOrder Order => EnumerableOrder.Unspecified;
- protected override bool ResetImplemented => true;
-
- [Fact]
- public static void TestBasicScenarios()
+ protected override IProducerConsumerCollection<T> CreateProducerConsumerCollection<T>() => new ConcurrentBag<T>();
+ protected override IProducerConsumerCollection<int> CreateProducerConsumerCollection(IEnumerable<int> collection) => new ConcurrentBag<int>(collection);
+ protected override bool IsEmpty(IProducerConsumerCollection<int> pcc) => ((ConcurrentBag<int>)pcc).IsEmpty;
+ protected override bool TryPeek<T>(IProducerConsumerCollection<T> pcc, out T result) => ((ConcurrentBag<T>)pcc).TryPeek(out result);
+ protected override IProducerConsumerCollection<int> CreateOracle(IEnumerable<int> collection) => new BagOracle(collection);
+
+ [Theory]
+ [InlineData(1, 10)]
+ [InlineData(3, 100)]
+ [InlineData(8, 1000)]
+ public static void AddThenPeek_LatestLocalItemReturned(int threadsCount, int itemsPerThread)
{
- ConcurrentBag<int> cb = new ConcurrentBag<int>();
- Assert.True(cb.IsEmpty);
- Task[] tks = new Task[2];
- tks[0] = Task.Run(() =>
- {
- cb.Add(4);
- cb.Add(5);
- cb.Add(6);
- });
+ var bag = new ConcurrentBag<int>();
- // Consume the items in the bag
- tks[1] = Task.Run(() =>
+ using (var b = new Barrier(threadsCount))
+ {
+ WaitAllOrAnyFailed((Enumerable.Range(0, threadsCount).Select(_ => Task.Factory.StartNew(() =>
{
- int item;
- while (!cb.IsEmpty)
+ b.SignalAndWait();
+ for (int i = 1; i < itemsPerThread + 1; i++)
{
- bool ret = cb.TryTake(out item);
- Assert.True(ret);
- // loose check
- Assert.Contains(item, new[] { 4, 5, 6 });
+ bag.Add(i);
+ int item;
+ Assert.True(bag.TryPeek(out item)); // ordering implementation detail that's not guaranteed
+ Assert.Equal(i, item);
}
- });
-
- Task.WaitAll(tks);
- }
-
- [Fact]
- public static void RTest1_Ctor()
- {
- ConcurrentBag<int> bag = new ConcurrentBag<int>(new int[] { 1, 2, 3 });
- Assert.False(bag.IsEmpty);
- Assert.Equal(3, bag.Count);
-
- Assert.Throws<ArgumentNullException>( () => {bag = new ConcurrentBag<int>(null);} );
- }
-
- [Fact]
- public static void RTest2_Add()
- {
- RTest2_Add(1, 10);
- RTest2_Add(3, 100);
- }
-
- [Fact]
- [OuterLoop]
- public static void RTest2_Add01()
- {
- RTest2_Add(8, 1000);
- }
-
- [Fact]
- public static void RTest3_TakeOrPeek()
- {
- ConcurrentBag<int> bag = CreateBag(100);
- RTest3_TakeOrPeek(bag, 1, 100, true);
-
- bag = CreateBag(100);
- RTest3_TakeOrPeek(bag, 4, 10, false);
-
- bag = CreateBag(1000);
- RTest3_TakeOrPeek(bag, 11, 100, true);
- }
-
- [Fact]
- public static void RTest4_AddAndTake()
- {
- RTest4_AddAndTake(8);
- RTest4_AddAndTake(16);
- }
-
- [Fact]
- public static void RTest5_CopyTo()
- {
- const int SIZE = 10;
- Array array = new int[SIZE];
- int index = 0;
-
- ConcurrentBag<int> bag = CreateBag(SIZE);
- bag.CopyTo((int[])array, index);
+ }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default))).ToArray());
+ }
- Assert.Throws<ArgumentNullException>(() => bag.CopyTo(null, index));
- Assert.Throws<ArgumentOutOfRangeException>(() => bag.CopyTo((int[]) array, -1));
- Assert.Throws<ArgumentException>(() => bag.CopyTo((int[])array, SIZE));
- Assert.Throws<ArgumentException>(() => bag.CopyTo((int[])array, SIZE-2));
+ Assert.Equal(itemsPerThread * threadsCount, bag.Count);
}
[Fact]
- public static void RTest5_ICollectionCopyTo()
- {
- const int SIZE = 10;
- Array array = new int[SIZE];
- int index = 0;
-
- ConcurrentBag<int> bag = CreateBag(SIZE);
- ICollection collection = bag as ICollection;
- Assert.NotNull(collection);
- collection.CopyTo(array, index);
-
- Assert.Throws<ArgumentNullException>(() => collection.CopyTo(null, index));
- Assert.Throws<ArgumentOutOfRangeException>(() => collection.CopyTo((int[])array, -1));
- Assert.Throws<ArgumentException>(() => collection.CopyTo((int[])array, SIZE));
- Assert.Throws<ArgumentException>(() => collection.CopyTo((int[])array, SIZE - 2));
-
- Array array2 = new int[SIZE, 5];
- Assert.Throws<ArgumentException>(() => collection.CopyTo(array2, 0));
- }
-
- /// <summary>
- /// Test bag addition
- /// </summary>
- /// <param name="threadsCount"></param>
- /// <param name="itemsPerThread"></param>
- /// <returns>True if succeeded, false otherwise</returns>
- private static void RTest2_Add(int threadsCount, int itemsPerThread)
+ public static void AddOnOneThread_PeekOnAnother_EnsureWeCanTakeOnTheOriginal()
{
- int failures = 0;
- ConcurrentBag<int> bag = new ConcurrentBag<int>();
+ var bag = new ConcurrentBag<int>(Enumerable.Range(1, 5));
- Task[] threads = new Task[threadsCount];
- for (int i = 0; i < threads.Length; i++)
+ Task.Factory.StartNew(() =>
{
- threads[i] = Task.Run(() =>
+ int item;
+ for (int i = 1; i <= 5; i++)
{
- for (int j = 0; j < itemsPerThread; j++)
- {
- try
- {
- bag.Add(j);
- int item;
- if (!bag.TryPeek(out item) || item != j)
- {
- Interlocked.Increment(ref failures);
- }
- }
- catch
- {
- Interlocked.Increment(ref failures);
- }
- }
- });
- }
-
- Task.WaitAll(threads);
+ Assert.True(bag.TryPeek(out item));
+ Assert.Equal(1, item);
+ }
+ }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).GetAwaiter().GetResult();
- Assert.Equal(0, failures);
- Assert.Equal(itemsPerThread * threadsCount, bag.Count);
- }
+ Assert.Equal(5, bag.Count);
- /// <summary>
- /// Test bag Take and Peek operations
- /// </summary>
- /// <param name="bag"></param>
- /// <param name="threadsCount"></param>
- /// <param name="itemsPerThread"></param>
- /// <param name="take"></param>
- /// <returns>True if succeeded, false otherwise</returns>
- private static void RTest3_TakeOrPeek(ConcurrentBag<int> bag, int threadsCount, int itemsPerThread, bool take)
- {
- int bagCount = bag.Count;
- int succeeded = 0;
- int failures = 0;
- Task[] threads = new Task[threadsCount];
- for (int i = 0; i < threads.Length; i++)
+ for (int i = 5; i > 0; i--)
{
- threads[i] = Task.Run(() =>
- {
- for (int j = 0; j < itemsPerThread; j++)
- {
- int data;
- bool result = false;
- if (take)
- {
- result = bag.TryTake(out data);
- }
- else
- {
- result = bag.TryPeek(out data);
- }
-
- if (result)
- {
- Interlocked.Increment(ref succeeded);
- }
- else
- {
- Interlocked.Increment(ref failures);
- }
- }
- });
- }
+ int item;
- Task.WaitAll(threads);
+ Assert.True(bag.TryPeek(out item));
+ Assert.Equal(i, item); // ordering implementation detail that's not guaranteed
- if (take)
- {
- Assert.Equal(bagCount - succeeded, bag.Count);
- }
- else
- {
- Assert.Equal(0, failures);
+ Assert.Equal(i, bag.Count);
+ Assert.True(bag.TryTake(out item));
+ Assert.Equal(i - 1, bag.Count);
+ Assert.Equal(i, item); // ordering implementation detail that's not guaranteed
}
}
- /// <summary>
- /// Test parallel Add/Take, insert unique elements in the bag, and each element should be removed once
- /// </summary>
- /// <param name="threadsCount"></param>
- /// <returns>True if succeeded, false otherwise</returns>
- private static void RTest4_AddAndTake(int threadsCount)
+ [Fact]
+ public static void AddManyItems_ThenTakeOnDifferentThread_ItemsOutputInExpectedOrder()
{
- ConcurrentBag<int> bag = new ConcurrentBag<int>();
-
- Task[] threads = new Task[threadsCount];
- int start = 0;
- int end = 10;
-
- int[] validation = new int[(end - start) * threads.Length / 2];
- for (int i = 0; i < threads.Length; i += 2)
- {
- Interval v = new Interval(start, end);
- threads[i] = Task.Factory.StartNew(
- (o) =>
- {
- Interval n = (Interval)o;
- Add(bag, n.m_start, n.m_end);
- }, v, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
-
- threads[i + 1] = Task.Run(() => Take(bag, end - start - 1, validation));
-
- int step = end - start;
- start = end;
- end += step;
- }
-
- Task.WaitAll(threads);
-
- int value = -1;
-
- //validation
- for (int i = 0; i < validation.Length; i++)
+ var bag = new ConcurrentBag<int>(Enumerable.Range(0, 100000));
+ Task.Factory.StartNew(() =>
{
- if (validation[i] == 0)
- {
- Assert.True(bag.TryTake(out value), String.Format("Add/Take failed, the list is not empty and TryTake returned false; thread count={0}", threadsCount));
- }
- else
+ for (int i = 0; i < 100000; i++)
{
- Assert.Equal(1, validation[i]);
+ int item;
+ Assert.True(bag.TryTake(out item));
+ Assert.Equal(i, item); // Testing an implementation detail rather than guaranteed ordering
}
- }
-
- Assert.False(bag.Count > 0 || bag.TryTake(out value), String.Format("Add/Take failed, this list is not empty after all remove operations; thread count={0}", threadsCount));
+ }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).GetAwaiter().GetResult();
}
- [Fact]
- public static void RTest6_GetEnumerator()
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(10)]
+ [InlineData(33)]
+ public static void IterativelyAddOnOneThreadThenTakeOnAnother_OrderMaintained(int initialCount)
{
- ConcurrentBag<int> bag = new ConcurrentBag<int>();
+ var bag = new ConcurrentBag<int>(Enumerable.Range(0, initialCount));
- // Empty bag should not enumerate
- Assert.Empty(bag);
-
- for (int i = 0; i < 100; i++)
- {
- bag.Add(i);
- }
-
- int count = 0;
- foreach (int x in bag)
- {
- count++;
- }
-
- Assert.Equal(count, bag.Count);
- }
-
- [Fact]
- public static void RTest7_BugFix575975()
- {
- BlockingCollection<int> bc = new BlockingCollection<int>(new ConcurrentBag<int>());
- bool succeeded = true;
- Task[] threads = new Task[4];
- for (int t = 0; t < threads.Length; t++)
+ const int Iterations = 100;
+ using (AutoResetEvent itemConsumed = new AutoResetEvent(false), itemProduced = new AutoResetEvent(false))
{
- threads[t] = Task.Factory.StartNew((obj) =>
+ Task t = Task.Run(() =>
{
- int index = (int)obj;
- for (int i = 0; i < 100000; i++)
+ for (int i = 0; i < Iterations; i++)
{
- if (index < threads.Length / 2)
- {
- int k = 0;
- for (int j = 0; j < 1000; j++)
- k++;
- bc.Add(i);
- }
- else
- {
- try
- {
- bc.Take();
- }
- catch // Take must not fail
- {
- succeeded = false;
- break;
- }
- }
+ itemProduced.WaitOne();
+ int item;
+ Assert.True(bag.TryTake(out item));
+ Assert.Equal(i, item); // Testing an implementation detail rather than guaranteed ordering
+ itemConsumed.Set();
}
+ });
- }, t, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
-
- Task.WaitAll(threads);
- Assert.True(succeeded);
- }
-
- [Fact]
- public static void RTest8_Interfaces()
- {
- ConcurrentBag<int> bag = new ConcurrentBag<int>();
- //IPCC
- IProducerConsumerCollection<int> ipcc = bag as IProducerConsumerCollection<int>;
- Assert.False(ipcc == null, "RTest8_Interfaces: ConcurrentBag<T> doesn't implement IPCC<T>");
- Assert.True(ipcc.TryAdd(1), "RTest8_Interfaces: IPCC<T>.TryAdd failed");
- Assert.Equal(1, bag.Count);
-
- int result = -1;
- Assert.True(ipcc.TryTake(out result), "RTest8_Interfaces: IPCC<T>.TryTake failed");
- Assert.True(1 == result, "RTest8_Interfaces: IPCC<T>.TryTake failed");
- Assert.Equal(0, bag.Count);
-
- //ICollection
- ICollection collection = bag as ICollection;
- Assert.False(collection == null, "RTest8_Interfaces: ConcurrentBag<T> doesn't implement ICollection");
- Assert.False(collection.IsSynchronized, "RTest8_Interfaces: IsSynchronized returned true");
+ for (int i = initialCount; i < Iterations + initialCount; i++)
+ {
+ bag.Add(i);
+ itemProduced.Set();
+ itemConsumed.WaitOne();
+ }
- //IEnumerable
- IEnumerable enumerable = bag as IEnumerable;
- Assert.False(enumerable == null, "RTest8_Interfaces: ConcurrentBag<T> doesn't implement IEnumerable");
- // Empty bag shouldn't enumerate.
- Assert.Empty(enumerable);
- }
+ t.GetAwaiter().GetResult();
+ }
- [Fact]
- public static void RTest8_Interfaces_Negative()
- {
- ConcurrentBag<int> bag = new ConcurrentBag<int>();
- //IPCC
- IProducerConsumerCollection<int> ipcc = bag as IProducerConsumerCollection<int>;
- ICollection collection = bag as ICollection;
- Assert.Throws<NotSupportedException>(() => { object obj = collection.SyncRoot; });
+ Assert.Equal(initialCount, bag.Count);
}
[Fact]
- public static void RTest9_ToArray()
+ public static void CopyTo_TypeMismatch()
{
- var bag = new ConcurrentBag<int>();
-
- Assert.NotNull(bag.ToArray());
- Assert.Equal(0, bag.ToArray().Length);
-
- int[] allItems = new int[10000];
- for (int i = 0; i < allItems.Length; i++)
- allItems[i] = i;
-
- bag = new ConcurrentBag<int>(allItems);
- int failCount = 0;
- Task[] tasks = new Task[10];
- for (int i = 0; i < tasks.Length; i++)
- {
- tasks[i] = Task.Run(() =>
- {
- int[] array = bag.ToArray();
- if (array == null || array.Length != 10000)
- Interlocked.Increment(ref failCount);
- });
- }
+ const int Size = 10;
- Task.WaitAll(tasks);
- Assert.True(0 == failCount, "RTest9_ToArray: One or more thread failed to get the correct bag items from ToArray");
+ var c = new ConcurrentBag<Exception>(Enumerable.Range(0, Size).Select(_ => new Exception()));
+ c.CopyTo(new Exception[Size], 0);
+ Assert.Throws<InvalidCastException>(() => c.CopyTo(new InvalidOperationException[Size], 0));
}
[Fact]
- public static void RTest10_DebuggerAttributes()
+ public static void ICollectionCopyTo_TypeMismatch()
{
- DebuggerAttributes.ValidateDebuggerDisplayReferences(new ConcurrentBag<int>());
- DebuggerAttributes.ValidateDebuggerTypeProxyProperties(new ConcurrentBag<int>());
- }
+ const int Size = 10;
+ ICollection c;
- #region Helper Methods / Classes
+ c = new ConcurrentBag<Exception>(Enumerable.Range(0, Size).Select(_ => new Exception()));
+ c.CopyTo(new Exception[Size], 0);
+ Assert.Throws<InvalidCastException>(() => c.CopyTo(new InvalidOperationException[Size], 0));
- private struct Interval
- {
- public Interval(int start, int end)
- {
- m_start = start;
- m_end = end;
- }
- internal int m_start;
- internal int m_end;
+ c = new ConcurrentBag<ArgumentException>(Enumerable.Range(0, Size).Select(_ => new ArgumentException()));
+ c.CopyTo(new Exception[Size], 0);
+ c.CopyTo(new ArgumentException[Size], 0);
+ Assert.Throws<InvalidCastException>(() => c.CopyTo(new ArgumentNullException[Size], 0));
}
- /// <summary>
- /// Create a ComcurrentBag object
- /// </summary>
- /// <param name="numbers">number of the elements in the bag</param>
- /// <returns>The bag object</returns>
- private static ConcurrentBag<int> CreateBag(int numbers)
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(10)]
+ public static void ToArray_AddTakeDifferentThreads_ExpectedResultsAfterAddsAndTakes(int initialCount)
{
- ConcurrentBag<int> bag = new ConcurrentBag<int>();
- for (int i = 0; i < numbers; i++)
- {
- bag.Add(i);
- }
- return bag;
- }
+ var bag = new ConcurrentBag<int>(Enumerable.Range(0, initialCount));
+ int items = 20 + initialCount;
- private static void Add(ConcurrentBag<int> bag, int start, int end)
- {
- for (int i = start; i < end; i++)
+ for (int i = 0; i < items; i++)
{
- bag.Add(i);
+ bag.Add(i + initialCount);
+ ThreadFactory.StartNew(() =>
+ {
+ int item;
+ Assert.True(bag.TryTake(out item));
+ Assert.Equal(item, i);
+ }).GetAwaiter().GetResult();
+ Assert.Equal(Enumerable.Range(i + 1, initialCount).Reverse(), bag.ToArray());
}
}
- private static void Take(ConcurrentBag<int> bag, int count, int[] validation)
+ protected sealed class BagOracle : IProducerConsumerCollection<int>
{
- for (int i = 0; i < count; i++)
+ private readonly Stack<int> _stack;
+ public BagOracle(IEnumerable<int> collection) { _stack = new Stack<int>(collection); }
+ public int Count => _stack.Count;
+ public bool IsSynchronized => false;
+ public object SyncRoot => null;
+ public void CopyTo(Array array, int index) => _stack.ToArray().CopyTo(array, index);
+ public void CopyTo(int[] array, int index) => _stack.ToArray().CopyTo(array, index);
+ public IEnumerator<int> GetEnumerator() => _stack.GetEnumerator();
+ public int[] ToArray() => _stack.ToArray();
+ public bool TryAdd(int item) { _stack.Push(item); return true; }
+ public bool TryTake(out int item)
{
- int value = -1;
-
- if (bag.TryTake(out value) && validation != null)
+ if (_stack.Count > 0)
{
- Interlocked.Increment(ref validation[value]);
+ item = _stack.Pop();
+ return true;
+ }
+ else
+ {
+ item = 0;
+ return false;
}
}
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
-
- #endregion
}
}
diff --git a/src/System.Collections.Concurrent/tests/ConcurrentDicionary/ConcurrentDictionary.Generic.Tests.cs b/src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionary.Generic.Tests.cs
index 6622884e5a..2f29e74c26 100644
--- a/src/System.Collections.Concurrent/tests/ConcurrentDicionary/ConcurrentDictionary.Generic.Tests.cs
+++ b/src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionary.Generic.Tests.cs
@@ -59,8 +59,6 @@ namespace System.Collections.Concurrent.Tests
protected override bool IDictionary_Generic_Keys_Values_Enumeration_ThrowsInvalidOperation_WhenParentModified => false;
- protected override bool IEnumerable_Generic_Enumerator_Current_EnumerationNotStarted_ThrowsInvalidOperationException => false;
-
protected override bool IDictionary_Generic_Keys_Values_ModifyingTheDictionaryUpdatesTheCollection => false;
protected override bool ResetImplemented => false;
diff --git a/src/System.Collections.Concurrent/tests/ConcurrentDicionary/ConcurrentDictionary.NonGeneric.Tests.cs b/src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionary.NonGeneric.Tests.cs
index b59782a7a0..b59782a7a0 100644
--- a/src/System.Collections.Concurrent/tests/ConcurrentDicionary/ConcurrentDictionary.NonGeneric.Tests.cs
+++ b/src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionary.NonGeneric.Tests.cs
diff --git a/src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionaryExtensions.cs b/src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionaryExtensions.cs
new file mode 100644
index 0000000000..8035939cb9
--- /dev/null
+++ b/src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionaryExtensions.cs
@@ -0,0 +1,59 @@
+// 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.Collections.Concurrent.Tests
+{
+ // Allows the ConcurrentDictionary tests to run on targets that do not have the new GetOrAdd/AddOrUpdate overloads.
+ internal static class ConcurrentDictionaryExtensions
+ {
+ public static TValue GetOrAdd<TKey, TValue, TArg>(
+ this ConcurrentDictionary<TKey, TValue> dictionary,
+ TKey key, Func<TKey, TArg, TValue> valueFactory, TArg factoryArgument)
+ {
+ if (key == null) throw new ArgumentNullException(nameof(key));
+ if (valueFactory == null) throw new ArgumentNullException(nameof(valueFactory));
+
+ while (true)
+ {
+ TValue value;
+ if (dictionary.TryGetValue(key, out value))
+ return value;
+
+ value = valueFactory(key, factoryArgument);
+ if (dictionary.TryAdd(key, value))
+ return value;
+ }
+ }
+
+ public static TValue AddOrUpdate<TKey, TValue, TArg>(
+ this ConcurrentDictionary<TKey, TValue> dictionary,
+ TKey key, Func<TKey, TArg, TValue> addValueFactory, Func<TKey, TValue, TArg, TValue> updateValueFactory, TArg factoryArgument)
+ {
+ if (key == null) throw new ArgumentNullException(nameof(key));
+ if (addValueFactory == null) throw new ArgumentNullException(nameof(addValueFactory));
+ if (updateValueFactory == null) throw new ArgumentNullException(nameof(updateValueFactory));
+
+ while (true)
+ {
+ TValue value;
+ if (dictionary.TryGetValue(key, out value))
+ {
+ TValue updatedValue = updateValueFactory(key, value, factoryArgument);
+ if (dictionary.TryUpdate(key, updatedValue, value))
+ {
+ return updatedValue;
+ }
+ }
+ else
+ {
+ value = addValueFactory(key, factoryArgument);
+ if (dictionary.TryAdd(key, value))
+ {
+ return value;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Collections.Concurrent/tests/ConcurrentDicionary/ConcurrentDictionaryTests.cs b/src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionaryTests.cs
index 6ec53d85f4..bd99df56d9 100644
--- a/src/System.Collections.Concurrent/tests/ConcurrentDicionary/ConcurrentDictionaryTests.cs
+++ b/src/System.Collections.Concurrent/tests/ConcurrentDictionary/ConcurrentDictionaryTests.cs
@@ -441,25 +441,33 @@ namespace System.Collections.Concurrent.Tests
{
if (isAdd)
{
- //call either of the two overloads of GetOrAdd
- if (j + ii % 2 == 0)
+ //call one of the overloads of GetOrAdd
+ switch (j % 3)
{
- dict.GetOrAdd(j, -j);
- }
- else
- {
- dict.GetOrAdd(j, x => -x);
+ case 0:
+ dict.GetOrAdd(j, -j);
+ break;
+ case 1:
+ dict.GetOrAdd(j, x => -x);
+ break;
+ case 2:
+ dict.GetOrAdd(j, (x,m) => x * m, -1);
+ break;
}
}
else
{
- if (j + ii % 2 == 0)
- {
- dict.AddOrUpdate(j, -j, (k, v) => -j);
- }
- else
+ switch (j % 3)
{
- dict.AddOrUpdate(j, (k) => -k, (k, v) => -k);
+ case 0:
+ dict.AddOrUpdate(j, -j, (k, v) => -j);
+ break;
+ case 1:
+ dict.AddOrUpdate(j, (k) => -k, (k, v) => -k);
+ break;
+ case 2:
+ dict.AddOrUpdate(j, (k,m) => k*m, (k, v, m) => k * m, -1);
+ break;
}
}
}
@@ -616,6 +624,12 @@ namespace System.Collections.Concurrent.Tests
// "TestExceptions: FAILED. this[] didn't throw ANE when null key is passed");
Assert.Throws<ArgumentNullException>(
+ () => dictionary.GetOrAdd(null, (k,m) => 0, 0));
+ // "TestExceptions: FAILED. GetOrAdd didn't throw ANE when null key is passed");
+ Assert.Throws<ArgumentNullException>(
+ () => dictionary.GetOrAdd("1", null, 0));
+ // "TestExceptions: FAILED. GetOrAdd didn't throw ANE when null valueFactory is passed");
+ Assert.Throws<ArgumentNullException>(
() => dictionary.GetOrAdd(null, (k) => 0));
// "TestExceptions: FAILED. GetOrAdd didn't throw ANE when null key is passed");
Assert.Throws<ArgumentNullException>(
@@ -626,6 +640,15 @@ namespace System.Collections.Concurrent.Tests
// "TestExceptions: FAILED. GetOrAdd didn't throw ANE when null key is passed");
Assert.Throws<ArgumentNullException>(
+ () => dictionary.AddOrUpdate(null, (k, m) => 0, (k, v, m) => 0, 42));
+ // "TestExceptions: FAILED. AddOrUpdate didn't throw ANE when null key is passed");
+ Assert.Throws<ArgumentNullException>(
+ () => dictionary.AddOrUpdate("1", (k, m) => 0, null, 42));
+ // "TestExceptions: FAILED. AddOrUpdate didn't throw ANE when null updateFactory is passed");
+ Assert.Throws<ArgumentNullException>(
+ () => dictionary.AddOrUpdate("1", null, (k, v, m) => 0, 42));
+ // "TestExceptions: FAILED. AddOrUpdate didn't throw ANE when null addFactory is passed");
+ Assert.Throws<ArgumentNullException>(
() => dictionary.AddOrUpdate(null, (k) => 0, (k, v) => 0));
// "TestExceptions: FAILED. AddOrUpdate didn't throw ANE when null key is passed");
Assert.Throws<ArgumentNullException>(
diff --git a/src/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs b/src/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs
index fd7cca1a2c..4147dad482 100644
--- a/src/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs
+++ b/src/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs
@@ -2,9 +2,7 @@
// 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.Tests;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -12,128 +10,14 @@ using Xunit;
namespace System.Collections.Concurrent.Tests
{
- public class ConcurrentQueueTests : IEnumerable_Generic_Tests<int>
+ public class ConcurrentQueueTests : ProducerConsumerCollectionTests
{
- protected override IEnumerable<ModifyEnumerable> ModifyEnumerables => new List<ModifyEnumerable>();
- protected override IEnumerable<int> GenericIEnumerableFactory(int count) => new ConcurrentQueue<int>(Enumerable.Range(0, count));
- protected override int CreateT(int seed) => new Random(seed).Next();
- protected override EnumerableOrder Order => EnumerableOrder.Unspecified;
+ protected override IProducerConsumerCollection<T> CreateProducerConsumerCollection<T>() => new ConcurrentQueue<T>();
+ protected override IProducerConsumerCollection<int> CreateProducerConsumerCollection(IEnumerable<int> collection) => new ConcurrentQueue<int>(collection);
+ protected override bool IsEmpty(IProducerConsumerCollection<int> pcc) => ((ConcurrentQueue<int>)pcc).IsEmpty;
+ protected override bool TryPeek<T>(IProducerConsumerCollection<T> pcc, out T result) => ((ConcurrentQueue<T>)pcc).TryPeek(out result);
protected override bool ResetImplemented => false;
- protected override bool IEnumerable_Generic_Enumerator_Current_EnumerationNotStarted_ThrowsInvalidOperationException => false;
-
- [Fact]
- public void Ctor_NoArg_ItemsAndCountMatch()
- {
- var q = new ConcurrentQueue<int>();
- Assert.True(q.IsEmpty);
- Assert.Equal(0, q.Count);
- Assert.Equal(Enumerable.Empty<int>(), q);
- }
-
- [Theory]
- [InlineData(0)]
- [InlineData(1)]
- [InlineData(1000)]
- public void Ctor_Collection_ItemsAndCountMatch(int count)
- {
- var q = new ConcurrentQueue<int>(Enumerable.Range(1, count));
- Assert.Equal(count == 0, q.IsEmpty);
- Assert.Equal(count, q.Count);
- Assert.Equal(Enumerable.Range(1, count), q);
- }
-
- [Fact]
- public void Ctor_NullEnumerable_Throws()
- {
- Assert.Throws<ArgumentNullException>("collection", () => new ConcurrentQueue<int>(null));
- }
-
- [Theory]
- [InlineData(0)]
- [InlineData(1)]
- [InlineData(1000)]
- public static void ToArray_ItemsAndCountMatch(int count)
- {
- ConcurrentQueue<int> q = new ConcurrentQueue<int>(Enumerable.Range(42, count));
- Assert.Equal(Enumerable.Range(42, count), q.ToArray());
-
- if (count > 0)
- {
- int item;
- Assert.True(q.TryDequeue(out item));
- Assert.Equal(42, item);
- Assert.Equal(Enumerable.Range(43, count - 1), q.ToArray());
- }
- }
-
- [Fact]
- public void DebuggerAttributes_Success()
- {
- var q = new ConcurrentQueue<int>(Enumerable.Range(0, 10));
- DebuggerAttributes.ValidateDebuggerDisplayReferences(q);
- DebuggerAttributes.ValidateDebuggerTypeProxyProperties(q);
- }
-
- [Fact]
- public void Enqueue_TryDequeue_MatchesQueue()
- {
- var q = new Queue<int>();
- var cq = new ConcurrentQueue<int>();
-
- Action dequeue = () =>
- {
- int item1 = q.Dequeue();
- int item2;
- Assert.True(cq.TryDequeue(out item2));
- Assert.Equal(item1, item2);
- Assert.Equal(q.Count, cq.Count);
- Assert.Equal(q, cq);
- };
-
- for (int i = 0; i < 100; i++)
- {
- cq.Enqueue(i);
- q.Enqueue(i);
- Assert.Equal(q.Count, cq.Count);
- Assert.Equal(q, cq);
-
- // Start dequeueing some after we've added some
- if (i > 50)
- {
- dequeue();
- }
- }
-
- // Dequeue the rest
- while (q.Count > 0)
- {
- dequeue();
- }
- }
-
- [Fact]
- public void TryPeek_Idempotent()
- {
- var cq = new ConcurrentQueue<int>();
- int item;
-
- Assert.False(cq.TryPeek(out item));
- Assert.Equal(0, item);
- Assert.False(cq.TryPeek(out item));
- Assert.Equal(0, item);
-
- cq.Enqueue(42);
-
- Assert.True(cq.TryPeek(out item));
- Assert.Equal(42, item);
- Assert.True(cq.TryPeek(out item));
- Assert.Equal(42, item);
-
- Assert.True(cq.TryDequeue(out item));
- Assert.Equal(42, item);
- Assert.False(cq.TryPeek(out item));
- Assert.Equal(0, item);
- }
+ protected override IProducerConsumerCollection<int> CreateOracle(IEnumerable<int> collection) => new QueueOracle(collection);
[Fact]
public void Concurrent_Enqueue_TryDequeue_AllItemsReceived()
@@ -205,77 +89,6 @@ namespace System.Collections.Concurrent.Tests
Task.WaitAll(producer, consumer);
}
- [Fact]
- public void Concurrent_EnqueueDequeue_IsEmpty_AlwaysFalse()
- {
- int items = 1000;
-
- var q = new ConcurrentQueue<int>();
- q.Enqueue(0); // make sure it's never empty
- var cts = new CancellationTokenSource();
-
- // Consumer repeatedly calls IsEmpty until it's told to stop
- Task consumer = Task.Run(() =>
- {
- while (!cts.IsCancellationRequested) Assert.False(q.IsEmpty);
- });
-
- // Producer enqueues/dequeues a bunch of items, then tells the consumer to stop
- Task producer = Task.Run(() =>
- {
- int ignored;
- for (int i = 1; i <= items; i++)
- {
- q.Enqueue(i);
- Assert.True(q.TryDequeue(out ignored));
- }
- cts.Cancel();
- });
-
- Task.WaitAll(producer, consumer);
- }
-
- [Fact]
- public void Concurrent_EnqueueObjects_Enumerate_NeverEmptyOrNull()
- {
- int items = 1000;
- object obj = new object();
-
- var q = new ConcurrentQueue<object>();
- q.Enqueue(obj); // ensure always at least one item
-
- var cts = new CancellationTokenSource();
-
- // Consumer repeatedly iterates the collection until it's told to stop
- Task consumer = Task.Run(() =>
- {
- while (!cts.IsCancellationRequested)
- {
- bool gotOne = false;
- foreach (object o in q)
- {
- gotOne = true;
- Assert.NotNull(o);
- }
- Assert.True(gotOne);
- }
- });
-
- // Producer enqueues and dequeues a bunch of items, then tells consumer to stop
- Task producer = Task.Run(() =>
- {
- for (int iters = 0; iters < 3; iters++)
- {
- for (int i = 1; i <= items; i++) q.Enqueue(i);
- object item;
- for (int i = 1; i <= items; i++) Assert.True(q.TryDequeue(out item));
- }
- cts.Cancel();
- });
-
- Task.WaitAll(producer, consumer);
- }
-
[Theory]
[InlineData(1, 4, 1024)]
[InlineData(4, 1, 1024)]
@@ -321,21 +134,6 @@ namespace System.Collections.Concurrent.Tests
Assert.Equal(producers * (itemsPerProducer * (itemsPerProducer + 1) / 2), sum);
}
- [Fact]
- public void CopyTo_InvalidArgs_Throws()
- {
- Assert.Throws<ArgumentNullException>("array", () => new ConcurrentQueue<int>().CopyTo(null, 0));
- Assert.Throws<ArgumentOutOfRangeException>(() => new ConcurrentQueue<int>().CopyTo(new int[1], -1));
- Assert.Throws<ArgumentException>(() => new ConcurrentQueue<int>().CopyTo(new int[1], 2));
- }
-
- [Fact]
- public void CopyTo_Empty_Success()
- {
- var q = new ConcurrentQueue<int>();
- q.CopyTo(Array.Empty<int>(), 0);
- }
-
[Theory]
[InlineData(1, false)]
[InlineData(100, false)]
@@ -388,50 +186,6 @@ namespace System.Collections.Concurrent.Tests
}
[Fact]
- public void ICollection_Count_Success()
- {
- ICollection c = new ConcurrentQueue<int>(Enumerable.Range(0, 5));
- Assert.Equal(5, c.Count);
- }
-
- [Fact]
- public void ICollection_IsSynchronized_AlwaysFalse()
- {
- ICollection c = new ConcurrentQueue<int>(Enumerable.Range(0, 5));
- Assert.False(c.IsSynchronized);
- }
-
- [Fact]
- public void ICollection_SyncRoot_AlwaysNull()
- {
- ICollection c = new ConcurrentQueue<int>(Enumerable.Range(0, 5));
- Assert.Throws<NotSupportedException>(() => c.SyncRoot);
- }
-
- [Fact]
- public void ICollection_CopyTo_InvalidArg_ThrowsException()
- {
- Assert.Throws<ArgumentNullException>(() => ((ICollection)new ConcurrentQueue<int>()).CopyTo(null, 0));
- Assert.Throws<ArgumentOutOfRangeException>(() => ((ICollection)new ConcurrentQueue<int>()).CopyTo(new int[0], -1));
- Assert.Throws<ArgumentException>(() => ((ICollection)new ConcurrentQueue<int>()).CopyTo(new int[0], 1));
- }
-
- [Fact]
- public void IProducerConsumerCollection_TryAddTryTake_Success()
- {
- IProducerConsumerCollection<int> pcc = new ConcurrentQueue<int>();
-
- Assert.True(pcc.TryAdd(1));
- Assert.True(pcc.TryAdd(2));
-
- int item;
- Assert.True(pcc.TryTake(out item));
- Assert.Equal(1, item);
- Assert.True(pcc.TryTake(out item));
- Assert.Equal(2, item);
- }
-
- [Fact]
public void IEnumerable_GetAllExpectedItems()
{
IEnumerable<int> enumerable1 = new ConcurrentQueue<int>(Enumerable.Range(1, 5));
@@ -490,6 +244,56 @@ namespace System.Collections.Concurrent.Tests
GC.KeepAlive(queue);
}
+ [Fact]
+ public void ManySegments_ConcurrentDequeues_RemainsConsistent()
+ {
+ var cq = new ConcurrentQueue<int>();
+ const int Iters = 10000;
+
+ for (int i = 0; i < Iters; i++)
+ {
+ cq.Enqueue(i);
+ cq.GetEnumerator().Dispose(); // force new segment
+ }
+
+ int dequeues = 0;
+ Parallel.For(0, Environment.ProcessorCount, i =>
+ {
+ while (!cq.IsEmpty)
+ {
+ int item;
+ if (cq.TryDequeue(out item))
+ {
+ Interlocked.Increment(ref dequeues);
+ }
+ }
+ });
+
+ Assert.Equal(0, cq.Count);
+ Assert.True(cq.IsEmpty);
+ Assert.Equal(Iters, dequeues);
+ }
+
+ [Fact]
+ public void ManySegments_ConcurrentEnqueues_RemainsConsistent()
+ {
+ var cq = new ConcurrentQueue<int>();
+ const int ItemsPerThread = 1000;
+ int threads = Environment.ProcessorCount;
+
+ Parallel.For(0, threads, i =>
+ {
+ for (int item = 0; item < ItemsPerThread; item++)
+ {
+ cq.Enqueue(item + (i * ItemsPerThread));
+ cq.GetEnumerator().Dispose();
+ }
+ });
+
+ Assert.Equal(ItemsPerThread * threads, cq.Count);
+ Assert.Equal(Enumerable.Range(0, ItemsPerThread * threads), cq.OrderBy(i => i));
+ }
+
/// <summary>Sets an event when finalized.</summary>
private sealed class Finalizable
{
@@ -499,6 +303,33 @@ namespace System.Collections.Concurrent.Tests
~Finalizable() { _mres.Set(); }
}
-
+
+ protected sealed class QueueOracle : IProducerConsumerCollection<int>
+ {
+ private readonly Queue<int> _queue;
+ public QueueOracle(IEnumerable<int> collection) { _queue = new Queue<int>(collection); }
+ public int Count => _queue.Count;
+ public bool IsSynchronized => false;
+ public object SyncRoot => null;
+ public void CopyTo(Array array, int index) => ((ICollection)_queue).CopyTo(array, index);
+ public void CopyTo(int[] array, int index) => _queue.CopyTo(array, index);
+ public IEnumerator<int> GetEnumerator() => _queue.GetEnumerator();
+ public int[] ToArray() => _queue.ToArray();
+ public bool TryAdd(int item) { _queue.Enqueue(item); return true; }
+ public bool TryTake(out int item)
+ {
+ if (_queue.Count > 0)
+ {
+ item = _queue.Dequeue();
+ return true;
+ }
+ else
+ {
+ item = 0;
+ return false;
+ }
+ }
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ }
}
}
diff --git a/src/System.Collections.Concurrent/tests/ConcurrentStackTests.cs b/src/System.Collections.Concurrent/tests/ConcurrentStackTests.cs
index 7f987e7700..83dbd34e96 100644
--- a/src/System.Collections.Concurrent/tests/ConcurrentStackTests.cs
+++ b/src/System.Collections.Concurrent/tests/ConcurrentStackTests.cs
@@ -3,8 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
-using System.Collections.Tests;
-using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -12,229 +10,43 @@ using Xunit;
namespace System.Collections.Concurrent.Tests
{
- public class ConcurrentStackTests : IEnumerable_Generic_Tests<int>
+ public class ConcurrentStackTests : ProducerConsumerCollectionTests
{
- protected override IEnumerable<ModifyEnumerable> ModifyEnumerables => new List<ModifyEnumerable>();
- protected override IEnumerable<int> GenericIEnumerableFactory(int count) => new ConcurrentStack<int>(Enumerable.Range(0, count));
- protected override int CreateT(int seed) => new Random(seed).Next();
- protected override EnumerableOrder Order => EnumerableOrder.Unspecified;
+ protected override IProducerConsumerCollection<T> CreateProducerConsumerCollection<T>() => new ConcurrentStack<T>();
+ protected override IProducerConsumerCollection<int> CreateProducerConsumerCollection(IEnumerable<int> collection) => new ConcurrentStack<int>(collection);
+ protected override bool IsEmpty(IProducerConsumerCollection<int> pcc) => ((ConcurrentStack<int>)pcc).IsEmpty;
+ protected override bool TryPeek<T>(IProducerConsumerCollection<T> pcc, out T result) => ((ConcurrentStack<T>)pcc).TryPeek(out result);
+ protected override IProducerConsumerCollection<int> CreateOracle(IEnumerable<int> collection) => new StackOracle(collection);
protected override bool ResetImplemented => false;
- protected override bool IEnumerable_Generic_Enumerator_Current_EnumerationNotStarted_ThrowsInvalidOperationException => false;
[Fact]
- public static void Test0_Empty()
+ public void IsEmpty_TrueWhenEmpty_FalseWhenNot()
{
- ConcurrentStack<int> s = new ConcurrentStack<int>();
+ var s = new ConcurrentStack<int>();
int item;
- Assert.False(s.TryPop(out item), "Test0_Empty: TryPop returned true when the stack is empty");
- Assert.False(s.TryPeek(out item), "Test0_Empty: TryPeek returned true when the stack is empty");
- Assert.True(s.TryPopRange(new int[1]) == 0, "Test0_Empty: TryPopRange returned non zero when the stack is empty");
+ Assert.False(s.TryPop(out item));
+ Assert.False(s.TryPeek(out item));
+ Assert.Equal(0, s.TryPopRange(new int[1]));
int count = 15;
for (int i = 0; i < count; i++)
+ {
s.Push(i);
+ }
+ Assert.Equal(0, s.TryPopRange(new int[1], 0, 0));
Assert.Equal(count, s.Count);
Assert.False(s.IsEmpty);
}
- [Fact]
- public static void Test1_PushAndPop()
- {
- Test1_PushAndPop(0, 0);
- Test1_PushAndPop(9, 9);
- }
-
- [Fact]
- [OuterLoop]
- public static void Test1_PushAndPop01()
- {
- Test1_PushAndPop(3, 0);
- Test1_PushAndPop(1024, 512);
- }
-
- [Fact]
- public static void Test2_ConcPushAndPop()
- {
- Test2_ConcPushAndPop(3, 1024, 0);
- }
-
- [Fact]
- public static void Test2_ConcPushAndPop01()
- {
- Test2_ConcPushAndPop(8, 1024, 512);
- }
-
- [Fact]
- public static void Test3_Clear()
- {
- Test3_Clear(0);
- Test3_Clear(16);
- Test3_Clear(1024);
- }
-
- [Fact]
- public static void Test4_Enumerator()
- {
- Test4_Enumerator(0);
- Test4_Enumerator(16);
- }
-
- [Fact]
- [OuterLoop]
- public static void Test4_Enumerator01()
- {
- Test4_Enumerator(1024);
- }
-
- [Fact]
- public static void Test5_CtorAndCopyToAndToArray()
- {
- Test5_CtorAndCopyToAndToArray(0);
- Test5_CtorAndCopyToAndToArray(16);
- }
-
- [Fact]
- [OuterLoop]
- public static void Test5_CtorAndCopyToAndToArray01()
- {
- Test5_CtorAndCopyToAndToArray(1024);
- }
-
- [Fact]
- public static void Test6_PushRange()
- {
- Test6_PushRange(8, 10);
- Test6_PushRange(16, 100);
- }
-
- [Fact]
- public static void Test7_PopRange()
- {
- Test7_PopRange(8, 10);
- Test7_PopRange(16, 100);
- }
-
- [Fact]
- [OuterLoop]
- public static void Test_PushPopRange()
- {
- Test6_PushRange(128, 100);
- Test7_PopRange(128, 100);
- }
-
- // Pushes and pops a certain number of times, and validates the resulting count.
- // These operations happen sequentially in a somewhat-interleaved fashion. We use
- // a BCL stack on the side to validate contents are correctly maintained.
- private static void Test1_PushAndPop(int pushes, int pops)
- {
- // It utilized a random generator to do x number of pushes and
- // y number of pops where x = random, y = random. Removed it
- // because it used System.Runtime.Extensions.
-
- ConcurrentStack<int> s = new ConcurrentStack<int>();
- Stack<int> s2 = new Stack<int>();
-
- int donePushes = 0, donePops = 0;
- while (donePushes < pushes || donePops < pops)
- {
- for (int i = 0; i < 10; i++)
- {
- if (donePushes == pushes)
- break;
-
- int val = i;
- s.Push(val);
- s2.Push(val);
- donePushes++;
-
- Assert.Equal(s.Count, s2.Count);
- }
-
- for (int i = 0; i < 6; i++)
- {
- if (donePops == pops)
- break;
- if ((donePushes - donePops) <= 0)
- break;
-
- int e0, e1, e2;
- bool b0 = s.TryPeek(out e0);
- bool b1 = s.TryPop(out e1);
- e2 = s2.Pop();
- donePops++;
-
- Assert.True(b0);
- Assert.True(b1);
-
- Assert.Equal(e0, e1);
- Assert.Equal(e1, e2);
- Assert.Equal(s.Count, s2.Count);
- }
- }
-
- Assert.Equal(pushes - pops, s.Count);
- }
-
- // Pushes and pops a certain number of times, and validates the resulting count.
- // These operations happen concurrently.
- private static void Test2_ConcPushAndPop(int threads, int pushes, int pops)
- {
- // It utilized a random generator to do x number of pushes and
- // y number of pops where x = random, y = random. Removed it
- // because it used System.Runtime.Extensions.
-
- ConcurrentStack<int> s = new ConcurrentStack<int>();
- ManualResetEvent mre = new ManualResetEvent(false);
- Task[] tt = new Task[threads];
-
- // Create all threads.
- for (int k = 0; k < tt.Length; k++)
- {
- tt[k] = Task.Run(delegate()
- {
- mre.WaitOne();
-
- int donePushes = 0, donePops = 0;
- while (donePushes < pushes || donePops < pops)
- {
- for (int i = 0; i < 8; i++)
- {
- if (donePushes == pushes)
- break;
-
- s.Push(i);
- donePushes++;
- }
- for (int i = 0; i < 4; i++)
- {
- if (donePops == pops)
- break;
- if ((donePushes - donePops) <= 0)
- break;
-
- int e;
- if (s.TryPop(out e))
- donePops++;
- }
- }
- });
- }
-
- // Kick 'em off and wait for them to finish.
- mre.Set();
- Task.WaitAll(tt);
-
- // Validate the count.
- Assert.Equal(threads * (pushes - pops), s.Count);
- }
-
- // Just validates clearing the stack's contents.
- private static void Test3_Clear(int count)
+ [Theory]
+ [InlineData(0)]
+ [InlineData(16)]
+ [InlineData(1024)]
+ public void Clear_AllElementsRemoved(int count)
{
- ConcurrentStack<int> s = new ConcurrentStack<int>();
- for (int i = 0; i < count; i++)
- s.Push(i);
+ var s = new ConcurrentStack<int>(Enumerable.Range(0, count));
+ Assert.Equal(count, s.Count);
s.Clear();
@@ -242,240 +54,128 @@ namespace System.Collections.Concurrent.Tests
Assert.Equal(0, s.Count);
}
- // Just validates enumerating the stack.
- private static void Test4_Enumerator(int count)
- {
- ConcurrentStack<int> s = new ConcurrentStack<int>();
- for (int i = 0; i < count; i++)
- s.Push(i);
-
- // Test enumerator.
- int j = count - 1;
- foreach (int x in s)
- {
- // Clear the stack to ensure concurrent modifications are dealt w/.
- if (x == count - 1)
- {
- int e;
- while (s.TryPop(out e)) ;
- }
-
- Assert.Equal(j, x);
- j--;
- }
-
- Assert.True(j <= 0, " > did not enumerate all elements in the stack");
- }
-
- // Instantiates the stack w/ the enumerator ctor and validates the resulting copyto & toarray.
- private static void Test5_CtorAndCopyToAndToArray(int count)
+ [Fact]
+ public void PushRange_NoItems_NothingAdded()
{
- int[] arr = new int[count];
- for (int i = 0; i < count; i++) arr[i] = i;
- ConcurrentStack<int> s = new ConcurrentStack<int>(arr);
-
- // try toarray.
- int[] sa1 = s.ToArray();
- Assert.Equal(arr.Length, sa1.Length);
-
- for (int i = 0; i < sa1.Length; i++)
- {
- Assert.Equal(arr[count - i - 1], sa1[i]);
- }
-
- int[] sa2 = new int[count];
- s.CopyTo(sa2, 0);
- Assert.Equal(arr.Length, sa2.Length);
-
- for (int i = 0; i < sa2.Length; i++)
- {
- Assert.Equal(arr[count - i - 1], sa2[i]);
- }
-
- object[] sa3 = new object[count]; // test array variance.
- ((System.Collections.ICollection)s).CopyTo(sa3, 0);
- Assert.Equal(arr.Length, sa3.Length);
+ var s = new ConcurrentStack<int>();
+ Assert.True(s.IsEmpty);
- for (int i = 0; i < sa3.Length; i++)
- {
- Assert.Equal(arr[count - i - 1], (int)sa3[i]);
- }
+ s.PushRange(new int[1], 0, 0);
+ Assert.True(s.IsEmpty);
}
- //Tests COncurrentSTack.PushRange
- private static void Test6_PushRange(int NumOfThreads, int localArraySize)
+ [Theory]
+ [InlineData(8, 10)]
+ [InlineData(16, 100)]
+ [InlineData(128, 100)]
+ public void PushRange_Concurrent_ConsecutiveItemsInEachRange(int numThreads, int numItemsPerThread)
{
- ConcurrentStack<int> stack = new ConcurrentStack<int>();
+ var stack = new ConcurrentStack<int>();
- Task[] threads = new Task[NumOfThreads];
- for (int i = 0; i < threads.Length; i++)
+ Task.WaitAll(Enumerable.Range(0, numThreads).Select(i => Task.Factory.StartNew((obj) =>
{
- threads[i] = Task.Factory.StartNew((obj) =>
+ int index = (int)obj;
+ int[] array = new int[numItemsPerThread];
+ for (int j = 0; j < numItemsPerThread; j++)
{
- int index = (int)obj;
- int[] array = new int[localArraySize];
- for (int j = 0; j < localArraySize; j++)
- {
- array[j] = index + j;
- }
-
- stack.PushRange(array);
- }, i * localArraySize, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
+ array[j] = index + j;
+ }
- Task.WaitAll(threads);
+ stack.PushRange(array);
+ }, i * numItemsPerThread, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default)).ToArray());
//validation
- for (int i = 0; i < threads.Length; i++)
+ for (int i = 0; i < numThreads; i++)
{
int lastItem = -1;
- for (int j = 0; j < localArraySize; j++)
+ for (int j = 0; j < numItemsPerThread; j++)
{
int currentItem = 0;
-
- Assert.True(stack.TryPop(out currentItem),
- String.Format("* Test6_PushRange({0},{1})L TryPop returned false.", NumOfThreads, localArraySize));
-
- Assert.True((lastItem <= -1) || lastItem - currentItem == 1,
- String.Format("* Test6_PushRange({0},{1}): Failed {2} - {3} shouldn't be consecutive", NumOfThreads, localArraySize, lastItem, currentItem));
-
+ Assert.True(stack.TryPop(out currentItem));
+ Assert.True((lastItem <= -1) || lastItem - currentItem == 1);
lastItem = currentItem;
}
}
}
- //Tests ConcurrentStack.PopRange by pushing consecutive numbers and run n threads each thread tries to pop m itmes
- // the popped m items should be consecutive
- private static void Test7_PopRange(int NumOfThreads, int elementsPerThread)
+ [Theory]
+ [InlineData(8, 10)]
+ [InlineData(16, 100)]
+ [InlineData(128, 100)]
+ public void TryPopRange_Concurrent_PoppedItemsAreConsecutive(int numThreads, int numElementsPerThread)
{
- int lastValue = NumOfThreads * elementsPerThread;
- List<int> allValues = new List<int>();
- for (int i = 1; i <= lastValue; i++)
- allValues.Add(i);
+ int numTotalElements = numThreads * numElementsPerThread;
+ var allValues = new List<int>(Enumerable.Range(1, numTotalElements));
+ var stack = new ConcurrentStack<int>(allValues);
- ConcurrentStack<int> stack = new ConcurrentStack<int>(allValues);
-
- Task[] threads = new Task[NumOfThreads];
-
- int[] array = new int[threads.Length * elementsPerThread];
- for (int i = 0; i < threads.Length; i++)
+ int[] array = new int[numTotalElements];
+ Task.WaitAll(Enumerable.Range(0, numThreads).Select(i => Task.Factory.StartNew(obj =>
{
- threads[i] = Task.Factory.StartNew((obj) =>
- {
- int index = (int)obj;
-
- int res = stack.TryPopRange(array, index, elementsPerThread);
- Assert.Equal(elementsPerThread, res);
- }, i * elementsPerThread, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
+ int index = (int)obj;
+ int res = stack.TryPopRange(array, index, numElementsPerThread);
+ Assert.Equal(numElementsPerThread, res);
+ }, i * numElementsPerThread, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default)).ToArray());
- Task.WaitAll(threads);
-
- // validation
- for (int i = 0; i < NumOfThreads; i++)
+ for (int i = 0; i < numThreads; i++)
{
- for (int j = 1; j < elementsPerThread; j++)
+ for (int j = 1; j < numElementsPerThread; j++)
{
- int currentIndex = i * elementsPerThread + j;
+ int currentIndex = i * numElementsPerThread + j;
Assert.Equal(array[currentIndex - 1], array[currentIndex] + 1);
}
}
}
[Fact]
- public static void Test8_Exceptions()
+ public void PushRange_InvalidArguments_Throws()
{
- ConcurrentStack<int> stack = null;
- Assert.Throws<ArgumentNullException>(
- () => stack = new ConcurrentStack<int>((IEnumerable<int>)null));
- // "Test8_Exceptions: The constructor didn't throw ANE when null collection passed");
-
- stack = new ConcurrentStack<int>();
- //CopyTo
- Assert.Throws<ArgumentNullException>(
- () => stack.CopyTo(null, 0));
- // "Test8_Exceptions: CopyTo didn't throw ANE when null array passed");
- Assert.Throws<ArgumentOutOfRangeException>(
- () => stack.CopyTo(new int[1], -1));
- // "Test8_Exceptions: CopyTo didn't throw AORE when negative array index passed");
-
- //PushRange
- Assert.Throws<ArgumentNullException>(
- () => stack.PushRange(null));
- // "Test8_Exceptions: PushRange didn't throw ANE when null array passed");
- Assert.Throws<ArgumentOutOfRangeException>(
- () => stack.PushRange(new int[1], 0, -1));
- // "Test8_Exceptions: PushRange didn't throw AORE when negative count passed");
- Assert.Throws<ArgumentOutOfRangeException>(
- () => stack.PushRange(new int[1], -1, 1));
- // "Test8_Exceptions: PushRange didn't throw AORE when negative index passed");
- Assert.Throws<ArgumentOutOfRangeException>(
- () => stack.PushRange(new int[1], 2, 1));
- // "Test8_Exceptions: PushRange didn't throw AORE when start index > array length");
- Assert.Throws<ArgumentException>(
- () => stack.PushRange(new int[1], 0, 10));
- // "Test8_Exceptions: PushRange didn't throw AE when count + index > array length");
-
- //PopRange
- Assert.Throws<ArgumentNullException>(
- () => stack.TryPopRange(null));
- // "Test8_Exceptions: TryPopRange didn't throw ANE when null array passed");
- Assert.Throws<ArgumentOutOfRangeException>(
- () => stack.TryPopRange(new int[1], 0, -1));
- // "Test8_Exceptions: TryPopRange didn't throw AORE when negative count passed");
- Assert.Throws<ArgumentOutOfRangeException>(
- () => stack.TryPopRange(new int[1], -1, 1));
- // "Test8_Exceptions: TryPopRange didn't throw AORE when negative index passed");
- Assert.Throws<ArgumentOutOfRangeException>(
- () => stack.TryPopRange(new int[1], 2, 1));
- // "Test8_Exceptions: TryPopRange didn't throw AORE when start index > array length");
- Assert.Throws<ArgumentException>(
- () => stack.TryPopRange(new int[1], 0, 10));
- // "Test8_Exceptions: TryPopRange didn't throw AE when count + index > array length");
+ var stack = new ConcurrentStack<int>();
+ Assert.Throws<ArgumentNullException>(() => stack.PushRange(null));
+ Assert.Throws<ArgumentNullException>(() => stack.PushRange(null, 0, 0));
+ Assert.Throws<ArgumentOutOfRangeException>(() => stack.PushRange(new int[1], 0, -1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => stack.PushRange(new int[1], -1, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => stack.PushRange(new int[1], 2, 1));
+ Assert.Throws<ArgumentException>(() => stack.PushRange(new int[1], 0, 10));
}
[Fact]
- public static void Test9_Interfaces_Negative()
+ public void TryPopRange_InvalidArguments_Throws()
{
- ConcurrentStack<int> stack = new ConcurrentStack<int>();
-
- ICollection collection = stack;
- Assert.Throws<ArgumentNullException>(
- () => collection.CopyTo(null, 0));
- // "TestICollection: ICollection.CopyTo didn't throw ANE when null collection passed for collection type: ConcurrentStack");
- Assert.Throws<NotSupportedException>(
- () => { object obj = collection.SyncRoot; });
- // "TestICollection: ICollection.SyncRoot didn't throw NotSupportedException! for collection type: ConcurrentStack");
+ var stack = new ConcurrentStack<int>();
+ Assert.Throws<ArgumentNullException>(() => stack.TryPopRange(null));
+ Assert.Throws<ArgumentNullException>(() => stack.TryPopRange(null, 0, 0));
+ Assert.Throws<ArgumentOutOfRangeException>(() => stack.TryPopRange(new int[1], 0, -1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => stack.TryPopRange(new int[1], -1, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => stack.TryPopRange(new int[1], 2, 1));
+ Assert.Throws<ArgumentException>(() => stack.TryPopRange(new int[1], 0, 10));
}
- [Fact]
- public static void Test10_DebuggerAttributes()
+ protected sealed class StackOracle : IProducerConsumerCollection<int>
{
- DebuggerAttributes.ValidateDebuggerDisplayReferences(new ConcurrentStack<int>());
- DebuggerAttributes.ValidateDebuggerTypeProxyProperties(new ConcurrentStack<int>());
- }
-
- [Fact]
- public static void Test9_Interfaces()
- {
- ConcurrentStack<int> stack = new ConcurrentStack<int>();
- IProducerConsumerCollection<int> ipcc = stack;
-
- Assert.Equal(0, ipcc.Count);
- int item;
- Assert.False(ipcc.TryTake(out item));
- Assert.True(ipcc.TryAdd(1));
-
- ICollection collection = stack;
- Assert.False(collection.IsSynchronized);
-
- stack.Push(1);
- int count = stack.Count;
- IEnumerable enumerable = stack;
- foreach (object o in enumerable)
- count--;
-
- Assert.Equal(0, count);
+ private readonly Stack<int> _stack;
+ public StackOracle(IEnumerable<int> collection) { _stack = new Stack<int>(collection); }
+ public int Count => _stack.Count;
+ public bool IsSynchronized => false;
+ public object SyncRoot => null;
+ public void CopyTo(Array array, int index) => ((ICollection)_stack).CopyTo(array, index);
+ public void CopyTo(int[] array, int index) => _stack.CopyTo(array, index);
+ public IEnumerator<int> GetEnumerator() => _stack.GetEnumerator();
+ public int[] ToArray() => _stack.ToArray();
+ public bool TryAdd(int item) { _stack.Push(item); return true; }
+ public bool TryTake(out int item)
+ {
+ if (_stack.Count > 0)
+ {
+ item = _stack.Pop();
+ return true;
+ }
+ else
+ {
+ item = 0;
+ return false;
+ }
+ }
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
}
diff --git a/src/System.Collections.Concurrent/tests/ProducerConsumerCollectionTests.cs b/src/System.Collections.Concurrent/tests/ProducerConsumerCollectionTests.cs
new file mode 100644
index 0000000000..27def42b6d
--- /dev/null
+++ b/src/System.Collections.Concurrent/tests/ProducerConsumerCollectionTests.cs
@@ -0,0 +1,1073 @@
+// 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.
+
+// #define StressTest // set to raise the amount of time spent in concurrency tests that stress the collections
+
+using System.Collections.Generic;
+using System.Collections.Tests;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Collections.Concurrent.Tests
+{
+ public abstract class ProducerConsumerCollectionTests : IEnumerable_Generic_Tests<int>
+ {
+ protected override IEnumerable<ModifyEnumerable> ModifyEnumerables => new List<ModifyEnumerable>();
+ protected override int CreateT(int seed) => new Random(seed).Next();
+ protected override EnumerableOrder Order => EnumerableOrder.Unspecified;
+ protected override IEnumerable<int> GenericIEnumerableFactory(int count) => CreateProducerConsumerCollection(count);
+ protected IProducerConsumerCollection<int> CreateProducerConsumerCollection() => CreateProducerConsumerCollection<int>();
+ protected IProducerConsumerCollection<int> CreateProducerConsumerCollection(int count) => CreateProducerConsumerCollection(Enumerable.Range(0, count));
+
+ protected abstract IProducerConsumerCollection<T> CreateProducerConsumerCollection<T>();
+ protected abstract IProducerConsumerCollection<int> CreateProducerConsumerCollection(IEnumerable<int> collection);
+ protected abstract bool IsEmpty(IProducerConsumerCollection<int> pcc);
+ protected abstract bool TryPeek<T>(IProducerConsumerCollection<T> pcc, out T result);
+ protected virtual IProducerConsumerCollection<int> CreateOracle() => CreateOracle(Enumerable.Empty<int>());
+ protected abstract IProducerConsumerCollection<int> CreateOracle(IEnumerable<int> collection);
+
+ protected static TaskFactory ThreadFactory { get; } = new TaskFactory(
+ CancellationToken.None, TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning, TaskScheduler.Default);
+ private const double ConcurrencyTestSeconds =
+#if StressTest
+ 8.0;
+#else
+ 1.0;
+#endif
+
+ [Fact]
+ public void Ctor_InvalidArgs_Throws()
+ {
+ Assert.Throws<ArgumentNullException>("collection", () => CreateProducerConsumerCollection(null));
+ }
+
+ [Fact]
+ public void Ctor_NoArg_ItemsAndCountMatch()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ Assert.Equal(0, c.Count);
+ Assert.True(IsEmpty(c));
+ Assert.Equal(Enumerable.Empty<int>(), c);
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(1000)]
+ public void Ctor_Collection_ItemsAndCountMatch(int count)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection(Enumerable.Range(1, count));
+ IProducerConsumerCollection<int> oracle = CreateOracle(Enumerable.Range(1, count));
+
+ Assert.Equal(oracle.Count == 0, IsEmpty(c));
+ Assert.Equal(oracle.Count, c.Count);
+ Assert.Equal<int>(oracle, c);
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(3)]
+ [InlineData(1000)]
+ public void Ctor_InitializeFromCollection_ContainsExpectedItems(int numItems)
+ {
+ var expected = new HashSet<int>(Enumerable.Range(0, numItems));
+
+ IProducerConsumerCollection<int> pcc = CreateProducerConsumerCollection(expected);
+ Assert.Equal(expected.Count, pcc.Count);
+
+ int item;
+ var actual = new HashSet<int>();
+ for (int i = 0; i < expected.Count; i++)
+ {
+ Assert.Equal(expected.Count - i, pcc.Count);
+ Assert.True(pcc.TryTake(out item));
+ actual.Add(item);
+ }
+
+ Assert.False(pcc.TryTake(out item));
+ Assert.Equal(0, item);
+ AssertSetsEqual(expected, actual);
+ }
+
+ [Fact]
+ public void Add_TakeFromAnotherThread_ExpectedItemsTaken()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ Assert.True(IsEmpty(c));
+ Assert.Equal(0, c.Count);
+
+ const int NumItems = 100000;
+
+ Task producer = Task.Run(() => Parallel.For(1, NumItems + 1, i => Assert.True(c.TryAdd(i))));
+
+ var hs = new HashSet<int>();
+ while (hs.Count < NumItems)
+ {
+ int item;
+ if (c.TryTake(out item)) hs.Add(item);
+ }
+
+ producer.GetAwaiter().GetResult();
+
+ Assert.True(IsEmpty(c));
+ Assert.Equal(0, c.Count);
+ AssertSetsEqual(new HashSet<int>(Enumerable.Range(1, NumItems)), hs);
+ }
+
+ [Fact]
+ public void AddSome_ThenInterleaveAddsAndTakes_MatchesOracle()
+ {
+ IProducerConsumerCollection<int> c = CreateOracle();
+ IProducerConsumerCollection<int> oracle = CreateProducerConsumerCollection();
+
+ Action take = () =>
+ {
+ int item1;
+ Assert.True(c.TryTake(out item1));
+ int item2;
+ Assert.True(oracle.TryTake(out item2));
+ Assert.Equal(item1, item2);
+ Assert.Equal(c.Count, oracle.Count);
+ Assert.Equal<int>(c, oracle);
+ };
+
+ for (int i = 0; i < 100; i++)
+ {
+ Assert.True(oracle.TryAdd(i));
+ Assert.True(c.TryAdd(i));
+ Assert.Equal(c.Count, oracle.Count);
+ Assert.Equal<int>(c, oracle);
+
+ // Start taking some after we've added some
+ if (i > 50)
+ {
+ take();
+ }
+ }
+
+ // Take the rest
+ while (c.Count > 0)
+ {
+ take();
+ }
+ }
+
+ [Fact]
+ public void AddTake_RandomChangesMatchOracle()
+ {
+ const int Iters = 1000;
+ var r = new Random(42);
+
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ IProducerConsumerCollection<int> oracle = CreateOracle();
+
+ for (int i = 0; i < Iters; i++)
+ {
+ if (r.NextDouble() < .5)
+ {
+ Assert.Equal(oracle.TryAdd(i), c.TryAdd(i));
+ }
+ else
+ {
+ int expected, actual;
+ Assert.Equal(oracle.TryTake(out expected), c.TryTake(out actual));
+ Assert.Equal(expected, actual);
+ }
+ }
+
+ Assert.Equal(oracle.Count, c.Count);
+ }
+
+ [Theory]
+ [InlineData(100, 1, 100, true)]
+ [InlineData(100, 4, 10, false)]
+ [InlineData(1000, 11, 100, true)]
+ [InlineData(100000, 2, 50000, true)]
+ public void Initialize_ThenTakeOrPeekInParallel_ItemsObtainedAsExpected(int numStartingItems, int threadsCount, int itemsPerThread, bool take)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection(Enumerable.Range(1, numStartingItems));
+ int successes = 0;
+
+ using (var b = new Barrier(threadsCount))
+ {
+ WaitAllOrAnyFailed(Enumerable.Range(0, threadsCount).Select(threadNum => ThreadFactory.StartNew(() =>
+ {
+ b.SignalAndWait();
+ for (int j = 0; j < itemsPerThread; j++)
+ {
+ int data;
+ if (take ? c.TryTake(out data) : TryPeek(c, out data))
+ {
+ Interlocked.Increment(ref successes);
+ Assert.NotEqual(0, data); // shouldn't be default(T)
+ }
+ }
+ })).ToArray());
+ }
+
+ Assert.Equal(
+ take ? numStartingItems : threadsCount * itemsPerThread,
+ successes);
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(1000)]
+ public void ToArray_AddAllItemsThenEnumerate_ItemsAndCountMatch(int count)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ IProducerConsumerCollection<int> oracle = CreateOracle();
+
+ for (int i = 0; i < count; i++)
+ {
+ Assert.Equal(oracle.TryAdd(i + count), c.TryAdd(i + count));
+ }
+
+ Assert.Equal(oracle.ToArray(), c.ToArray());
+
+ if (count > 0)
+ {
+ int expected, actual;
+ Assert.Equal(oracle.TryTake(out expected), c.TryTake(out actual));
+ Assert.Equal(expected, actual);
+ Assert.Equal(oracle.ToArray(), c.ToArray());
+ }
+ }
+
+ [Theory]
+ [InlineData(1, 10)]
+ [InlineData(2, 10)]
+ [InlineData(10, 10)]
+ [InlineData(100, 10)]
+ public void ToArray_AddAndTakeItemsIntermixedWithEnumeration_ItemsAndCountMatch(int initialCount, int iters)
+ {
+ IEnumerable<int> initialItems = Enumerable.Range(1, initialCount);
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection(initialItems);
+ IProducerConsumerCollection<int> oracle = CreateOracle(initialItems);
+
+ for (int i = 0; i < iters; i++)
+ {
+ Assert.Equal<int>(oracle, c);
+
+ Assert.Equal(oracle.TryAdd(initialCount + i), c.TryAdd(initialCount + i));
+ Assert.Equal<int>(oracle, c);
+
+ int expected, actual;
+ Assert.Equal(oracle.TryTake(out expected), c.TryTake(out actual));
+ Assert.Equal(expected, actual);
+ Assert.Equal<int>(oracle, c);
+ }
+ }
+
+ [Fact]
+ public void AddFromMultipleThreads_ItemsRemainAfterThreadsGoAway()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+
+ for (int i = 0; i < 1000; i += 100)
+ {
+ // Create a thread that adds items to the collection
+ ThreadFactory.StartNew(() =>
+ {
+ for (int j = i; j < i + 100; j++)
+ {
+ Assert.True(c.TryAdd(j));
+ }
+ }).GetAwaiter().GetResult();
+
+ // Allow threads to be collected
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
+ }
+
+ AssertSetsEqual(new HashSet<int>(Enumerable.Range(0, 1000)), new HashSet<int>(c));
+ }
+
+ [Fact]
+ public void AddManyItems_ThenTakeOnSameThread_ItemsOutputInExpectedOrder()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection(Enumerable.Range(0, 100000));
+ IProducerConsumerCollection<int> oracle = CreateOracle(Enumerable.Range(0, 100000));
+
+ for (int i = 99999; i >= 0; --i)
+ {
+ int expected, actual;
+ Assert.Equal(oracle.TryTake(out expected), c.TryTake(out actual));
+ Assert.Equal(expected, actual);
+ }
+ }
+
+ [Fact]
+ public void TryPeek_SucceedsOnEmptyCollectionThatWasOnceNonEmpty()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ int item;
+
+ for (int i = 0; i < 2; i++)
+ {
+ Assert.False(TryPeek(c, out item));
+ Assert.Equal(0, item);
+ }
+
+ Assert.True(c.TryAdd(42));
+
+ for (int i = 0; i < 2; i++)
+ {
+ Assert.True(TryPeek(c, out item));
+ Assert.Equal(42, item);
+ }
+
+ Assert.True(c.TryTake(out item));
+ Assert.Equal(42, item);
+
+ Assert.False(TryPeek(c, out item));
+ Assert.Equal(0, item);
+ Assert.False(c.TryTake(out item));
+ Assert.Equal(0, item);
+ }
+
+ [Fact]
+ public void AddTakeWithAtLeastOneElementInCollection_IsEmpty_AlwaysFalse()
+ {
+ int items = 1000;
+
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ Assert.True(c.TryAdd(0)); // make sure it's never empty
+ var cts = new CancellationTokenSource();
+
+ // Consumer repeatedly calls IsEmpty until it's told to stop
+ Task consumer = Task.Run(() =>
+ {
+ while (!cts.IsCancellationRequested) Assert.False(IsEmpty(c));
+ });
+
+ // Producer adds/takes a bunch of items, then tells the consumer to stop
+ Task producer = Task.Run(() =>
+ {
+ int ignored;
+ for (int i = 1; i <= items; i++)
+ {
+ Assert.True(c.TryAdd(i));
+ Assert.True(c.TryTake(out ignored));
+ }
+ cts.Cancel();
+ });
+
+ Task.WaitAll(producer, consumer);
+ }
+
+ [Fact]
+ public void CopyTo_Empty_NothingCopied()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ c.CopyTo(new int[0], 0);
+ c.CopyTo(new int[10], 10);
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(100)]
+ public void CopyTo_SzArray_ZeroIndex_ExpectedElementsCopied(int size)
+ {
+ IEnumerable<int> initialItems = Enumerable.Range(1, size);
+
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection(initialItems);
+ int[] actual = new int[size];
+ c.CopyTo(actual, 0);
+
+ IProducerConsumerCollection<int> oracle = CreateOracle(initialItems);
+ int[] expected = new int[size];
+ oracle.CopyTo(expected, 0);
+
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(100)]
+ public void CopyTo_SzArray_NonZeroIndex_ExpectedElementsCopied(int size)
+ {
+ IEnumerable<int> initialItems = Enumerable.Range(1, size);
+
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection(initialItems);
+ int[] actual = new int[size + 2];
+ c.CopyTo(actual, 1);
+
+ IProducerConsumerCollection<int> oracle = CreateOracle(initialItems);
+ int[] expected = new int[size + 2];
+ oracle.CopyTo(expected, 1);
+
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(100)]
+ public void CopyTo_ArrayZeroLowerBound_ZeroIndex_ExpectedElementsCopied(int size)
+ {
+ IEnumerable<int> initialItems = Enumerable.Range(1, size);
+
+ ICollection c = CreateProducerConsumerCollection(initialItems);
+ Array actual = Array.CreateInstance(typeof(int), new int[] { size }, new int[] { 0 });
+ c.CopyTo(actual, 0);
+
+ ICollection oracle = CreateOracle(initialItems);
+ Array expected = Array.CreateInstance(typeof(int), new int[] { size }, new int[] { 0 });
+ oracle.CopyTo(expected, 0);
+
+ Assert.Equal(expected.Cast<int>(), actual.Cast<int>());
+ }
+
+ [Fact]
+ public void CopyTo_ArrayNonZeroLowerBound_ExpectedElementsCopied()
+ {
+ int[] initialItems = Enumerable.Range(1, 10).ToArray();
+
+ const int LowerBound = 1;
+ ICollection c = CreateProducerConsumerCollection(initialItems);
+ Array actual = Array.CreateInstance(typeof(int), new int[] { initialItems.Length }, new int[] { LowerBound });
+ c.CopyTo(actual, LowerBound);
+
+ ICollection oracle = CreateOracle(initialItems);
+ int[] expected = new int[initialItems.Length];
+ oracle.CopyTo(expected, 0);
+
+ for (int i = 0; i < expected.Length; i++)
+ {
+ Assert.Equal(expected[i], actual.GetValue(i + LowerBound));
+ }
+ }
+
+ [Fact]
+ public void CopyTo_InvalidArgs_Throws()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection(Enumerable.Range(0, 10));
+ int[] dest = new int[10];
+
+ Assert.Throws<ArgumentNullException>("array", () => c.CopyTo(null, 0));
+ Assert.Throws<ArgumentOutOfRangeException>(() => c.CopyTo(dest, -1));
+ Assert.Throws<ArgumentException>(() => c.CopyTo(dest, dest.Length));
+ Assert.Throws<ArgumentException>(() => c.CopyTo(dest, dest.Length - 2));
+
+ Assert.Throws<ArgumentException>(() => c.CopyTo(new int[7, 7], 0));
+ }
+
+ [Fact]
+ public void ICollectionCopyTo_InvalidArgs_Throws()
+ {
+ ICollection c = CreateProducerConsumerCollection(Enumerable.Range(0, 10));
+ Array dest = new int[10];
+
+ Assert.Throws<ArgumentNullException>("array", () => c.CopyTo(null, 0));
+ Assert.Throws<ArgumentOutOfRangeException>(() => c.CopyTo(dest, -1));
+ Assert.Throws<ArgumentException>(() => c.CopyTo(dest, dest.Length));
+ Assert.Throws<ArgumentException>(() => c.CopyTo(dest, dest.Length - 2));
+ }
+
+ [Theory]
+ [InlineData(100, 1, 10)]
+ [InlineData(4, 100000, 10)]
+ public void BlockingCollection_WrappingCollection_ExpectedElementsTransferred(int numThreadsPerConsumerProducer, int numItemsPerThread, int producerSpin)
+ {
+ var bc = new BlockingCollection<int>(CreateProducerConsumerCollection());
+ long dummy = 0;
+
+ Task[] producers = Enumerable.Range(0, numThreadsPerConsumerProducer).Select(_ => ThreadFactory.StartNew(() =>
+ {
+ for (int i = 1; i <= numItemsPerThread; i++)
+ {
+ for (int j = 0; j < producerSpin; j++) dummy *= j; // spin a little
+ bc.Add(i);
+ }
+ })).ToArray();
+
+ Task[] consumers = Enumerable.Range(0, numThreadsPerConsumerProducer).Select(_ => ThreadFactory.StartNew(() =>
+ {
+ for (int i = 0; i < numItemsPerThread; i++)
+ {
+ const int TimeoutMs = 100000;
+ int item;
+ Assert.True(bc.TryTake(out item, TimeoutMs), $"Couldn't get {i}th item after {TimeoutMs}ms");
+ Assert.NotEqual(0, item);
+ }
+ })).ToArray();
+
+ WaitAllOrAnyFailed(producers);
+ WaitAllOrAnyFailed(consumers);
+ }
+
+ [Fact]
+ public void GetEnumerator_NonGeneric()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ IEnumerable e = c;
+
+ Assert.False(e.GetEnumerator().MoveNext());
+
+ Assert.True(c.TryAdd(42));
+ Assert.True(c.TryAdd(84));
+
+ var hs = new HashSet<int>(e.Cast<int>());
+ Assert.Equal(2, hs.Count);
+ Assert.Contains(42, hs);
+ Assert.Contains(84, hs);
+ }
+
+ [Fact]
+ public void GetEnumerator_EnumerationsAreSnapshots()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ Assert.Empty(c);
+
+ using (IEnumerator<int> e1 = c.GetEnumerator())
+ {
+ Assert.True(c.TryAdd(1));
+ using (IEnumerator<int> e2 = c.GetEnumerator())
+ {
+ Assert.True(c.TryAdd(2));
+ using (IEnumerator<int> e3 = c.GetEnumerator())
+ {
+ int item;
+ Assert.True(c.TryTake(out item));
+ using (IEnumerator<int> e4 = c.GetEnumerator())
+ {
+ Assert.False(e1.MoveNext());
+
+ Assert.True(e2.MoveNext());
+ Assert.False(e2.MoveNext());
+
+ Assert.True(e3.MoveNext());
+ Assert.True(e3.MoveNext());
+ Assert.False(e3.MoveNext());
+
+ Assert.True(e4.MoveNext());
+ Assert.False(e4.MoveNext());
+ }
+ }
+ }
+ }
+ }
+
+ [Theory]
+ [InlineData(0, true)]
+ [InlineData(1, true)]
+ [InlineData(1, false)]
+ [InlineData(10, true)]
+ [InlineData(100, true)]
+ [InlineData(100, false)]
+ public async Task GetEnumerator_Generic_ExpectedElementsYielded(int numItems, bool consumeFromSameThread)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ using (var e = c.GetEnumerator())
+ {
+ Assert.False(e.MoveNext());
+ }
+
+ // Add, and validate enumeration after each item added
+ for (int i = 1; i <= numItems; i++)
+ {
+ Assert.True(c.TryAdd(i));
+ Assert.Equal(i, c.Count);
+ Assert.Equal(i, c.Distinct().Count());
+ }
+
+ // Take, and validate enumerate after each item removed.
+ Action consume = () =>
+ {
+ for (int i = 1; i <= numItems; i++)
+ {
+ int item;
+ Assert.True(c.TryTake(out item));
+ Assert.Equal(numItems - i, c.Count);
+ Assert.Equal(numItems - i, c.Distinct().Count());
+ }
+ };
+ if (consumeFromSameThread)
+ {
+ consume();
+ }
+ else
+ {
+ await ThreadFactory.StartNew(consume);
+ }
+ }
+
+ [Fact]
+ public void TryAdd_TryTake_ToArray()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+
+ Assert.True(c.TryAdd(42));
+ Assert.Equal(new[] { 42 }, c.ToArray());
+
+ Assert.True(c.TryAdd(84));
+ Assert.Equal(new[] { 42, 84 }, c.ToArray().OrderBy(i => i));
+
+ int item;
+
+ Assert.True(c.TryTake(out item));
+ int remainingItem = item == 42 ? 84 : 42;
+ Assert.Equal(new[] { remainingItem }, c.ToArray());
+ Assert.True(c.TryTake(out item));
+ Assert.Equal(remainingItem, item);
+ Assert.Empty(c.ToArray());
+ }
+
+ [Fact]
+ public void ICollection_IsSynchronized_SyncRoot()
+ {
+ ICollection c = CreateProducerConsumerCollection();
+ Assert.False(c.IsSynchronized);
+ Assert.Throws<NotSupportedException>(() => c.SyncRoot);
+ }
+
+ [Fact]
+ public void ToArray_ParallelInvocations_Succeed()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ Assert.Empty(c.ToArray());
+
+ const int NumItems = 10000;
+
+ Parallel.For(0, NumItems, i => Assert.True(c.TryAdd(i)));
+ Assert.Equal(NumItems, c.Count);
+
+ Parallel.For(0, 10, i =>
+ {
+ var hs = new HashSet<int>(c.ToArray());
+ Assert.Equal(NumItems, hs.Count);
+ });
+ }
+
+ [Fact]
+ public void ToArray_AddTakeSameThread_ExpectedResultsAfterAddsAndTakes()
+ {
+ const int Items = 20;
+
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ IProducerConsumerCollection<int> oracle = CreateOracle();
+
+ for (int i = 0; i < Items; i++)
+ {
+ Assert.True(c.TryAdd(i));
+ Assert.True(oracle.TryAdd(i));
+ Assert.Equal(oracle.ToArray(), c.ToArray());
+ }
+
+ for (int i = Items - 1; i >= 0; i--)
+ {
+ int expected, actual;
+ Assert.Equal(oracle.TryTake(out expected), c.TryTake(out actual));
+ Assert.Equal(expected, actual);
+ Assert.Equal(oracle.ToArray(), c.ToArray());
+ }
+ }
+
+ [Fact]
+ public void GetEnumerator_ParallelInvocations_Succeed()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ Assert.Empty(c.ToArray());
+
+ const int NumItems = 10000;
+
+ Parallel.For(0, NumItems, i => Assert.True(c.TryAdd(i)));
+ Assert.Equal(NumItems, c.Count);
+
+ Parallel.For(0, 10, i =>
+ {
+ var hs = new HashSet<int>(c);
+ Assert.Equal(NumItems, hs.Count);
+ });
+ }
+
+ [Theory]
+ [InlineData(1, ConcurrencyTestSeconds / 2)]
+ [InlineData(4, ConcurrencyTestSeconds / 2)]
+ public void ManyConcurrentAddsTakes_EnsureTrackedCountsMatchResultingCollection(int threadsPerProc, double seconds)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+
+ DateTime end = default(DateTime);
+ using (var b = new Barrier(Environment.ProcessorCount * threadsPerProc, _ => end = DateTime.UtcNow + TimeSpan.FromSeconds(seconds)))
+ {
+ Task<int>[] tasks = Enumerable.Range(0, b.ParticipantCount).Select(_ => ThreadFactory.StartNew(() =>
+ {
+ b.SignalAndWait();
+
+ int count = 0;
+ var rand = new Random();
+
+ while (DateTime.UtcNow < end)
+ {
+ if (rand.NextDouble() < .5)
+ {
+ Assert.True(c.TryAdd(rand.Next()));
+ count++;
+ }
+ else
+ {
+ int item;
+ if (c.TryTake(out item)) count--;
+ }
+ }
+
+ return count;
+ })).ToArray();
+ Task.WaitAll(tasks);
+ Assert.Equal(tasks.Sum(t => t.Result), c.Count);
+ }
+ }
+
+ [Theory]
+ [InlineData(ConcurrencyTestSeconds)]
+ public void ManyConcurrentAddsTakes_CollectionRemainsConsistent(double seconds)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+
+ DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(seconds);
+
+ // Thread that adds
+ Task<HashSet<int>> adds = ThreadFactory.StartNew(() =>
+ {
+ var added = new HashSet<int>();
+ int i = int.MinValue;
+ while (DateTime.UtcNow < end)
+ {
+ i++;
+ Assert.True(c.TryAdd(i));
+ added.Add(i);
+ }
+ return added;
+ });
+
+ // Thread that adds and takes
+ Task<KeyValuePair<HashSet<int>, HashSet<int>>> addsAndTakes = ThreadFactory.StartNew(() =>
+ {
+ var added = new HashSet<int>();
+ var taken = new HashSet<int>();
+
+ int i = 1; // avoid 0 as default(T), to detect accidentally reading a default value
+ while (DateTime.UtcNow < end)
+ {
+ i++;
+ Assert.True(c.TryAdd(i));
+ added.Add(i);
+
+ int item;
+ if (c.TryTake(out item))
+ {
+ Assert.NotEqual(0, item);
+ taken.Add(item);
+ }
+ }
+
+ return new KeyValuePair<HashSet<int>, HashSet<int>>(added, taken);
+ });
+
+ // Thread that just takes
+ Task<HashSet<int>> takes = ThreadFactory.StartNew(() =>
+ {
+ var taken = new HashSet<int>();
+ while (DateTime.UtcNow < end)
+ {
+ int item;
+ if (c.TryTake(out item))
+ {
+ Assert.NotEqual(0, item);
+ taken.Add(item);
+ }
+ }
+ return taken;
+ });
+
+ // Wait for them all to finish
+ WaitAllOrAnyFailed(adds, addsAndTakes, takes);
+
+ // Combine everything they added and remove everything they took
+ var total = new HashSet<int>(adds.Result);
+ total.UnionWith(addsAndTakes.Result.Key);
+ total.ExceptWith(addsAndTakes.Result.Value);
+ total.ExceptWith(takes.Result);
+
+ // What's left should match what's in the collection
+ Assert.Equal(total.OrderBy(i => i), c.OrderBy(i => i));
+ }
+
+ [Theory]
+ [InlineData(ConcurrencyTestSeconds)]
+ public void ManyConcurrentAddsTakesPeeks_ForceContentionWithOtherThreadsTaking(double seconds)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ const int MaxCount = 4;
+
+ DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(seconds);
+
+ Task<long> addsTakes = ThreadFactory.StartNew(() =>
+ {
+ long total = 0;
+ while (DateTime.UtcNow < end)
+ {
+ for (int i = 1; i <= MaxCount; i++)
+ {
+ Assert.True(c.TryAdd(i));
+ total++;
+ }
+
+ int item;
+ if (TryPeek(c, out item))
+ {
+ Assert.InRange(item, 1, MaxCount);
+ }
+
+ for (int i = 1; i <= MaxCount; i++)
+ {
+ if (c.TryTake(out item))
+ {
+ total--;
+ Assert.InRange(item, 1, MaxCount);
+ }
+ }
+ }
+ return total;
+ });
+
+ Task<long> takesFromOtherThread = ThreadFactory.StartNew(() =>
+ {
+ long total = 0;
+ int item;
+ while (DateTime.UtcNow < end)
+ {
+ if (c.TryTake(out item))
+ {
+ total++;
+ Assert.InRange(item, 1, MaxCount);
+ }
+ }
+ return total;
+ });
+
+ WaitAllOrAnyFailed(addsTakes, takesFromOtherThread);
+ long remaining = addsTakes.Result - takesFromOtherThread.Result;
+ Assert.InRange(remaining, 0, long.MaxValue);
+ Assert.Equal(remaining, c.Count);
+ }
+
+ [Theory]
+ [InlineData(ConcurrencyTestSeconds)]
+ public void ManyConcurrentAddsTakesPeeks_ForceContentionWithOtherThreadsPeeking(double seconds)
+ {
+ IProducerConsumerCollection<LargeStruct> c = CreateProducerConsumerCollection<LargeStruct>();
+ const int MaxCount = 4;
+
+ DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(seconds);
+
+ Task<long> addsTakes = ThreadFactory.StartNew(() =>
+ {
+ long total = 0;
+ while (DateTime.UtcNow < end)
+ {
+ for (int i = 1; i <= MaxCount; i++)
+ {
+ Assert.True(c.TryAdd(new LargeStruct(i)));
+ total++;
+ }
+
+ LargeStruct item;
+ Assert.True(TryPeek(c, out item));
+ Assert.InRange(item.Value, 1, MaxCount);
+
+ for (int i = 1; i <= MaxCount; i++)
+ {
+ if (c.TryTake(out item))
+ {
+ total--;
+ Assert.InRange(item.Value, 1, MaxCount);
+ }
+ }
+ }
+ return total;
+ });
+
+ Task peeksFromOtherThread = ThreadFactory.StartNew(() =>
+ {
+ LargeStruct item;
+ while (DateTime.UtcNow < end)
+ {
+ if (TryPeek(c, out item))
+ {
+ Assert.InRange(item.Value, 1, MaxCount);
+ }
+ }
+ });
+
+ WaitAllOrAnyFailed(addsTakes, peeksFromOtherThread);
+ Assert.Equal(0, addsTakes.Result);
+ Assert.Equal(0, c.Count);
+ }
+
+ [Theory]
+ [InlineData(ConcurrencyTestSeconds)]
+ public void ManyConcurrentAddsTakes_ForceContentionWithToArray(double seconds)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ const int MaxCount = 4;
+
+ DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(seconds);
+
+ Task addsTakes = ThreadFactory.StartNew(() =>
+ {
+ while (DateTime.UtcNow < end)
+ {
+ for (int i = 1; i <= MaxCount; i++)
+ {
+ Assert.True(c.TryAdd(i));
+ }
+ for (int i = 1; i <= MaxCount; i++)
+ {
+ int item;
+ Assert.True(c.TryTake(out item));
+ Assert.InRange(item, 1, MaxCount);
+ }
+ }
+ });
+
+ while (DateTime.UtcNow < end)
+ {
+ int[] arr = c.ToArray();
+ Assert.InRange(arr.Length, 0, MaxCount);
+ Assert.DoesNotContain(0, arr); // make sure we didn't get default(T)
+ }
+
+ addsTakes.GetAwaiter().GetResult();
+ Assert.Equal(0, c.Count);
+ }
+
+ [Theory]
+ [InlineData(0, ConcurrencyTestSeconds / 2)]
+ [InlineData(1, ConcurrencyTestSeconds / 2)]
+ public void ManyConcurrentAddsTakes_ForceContentionWithGetEnumerator(int initialCount, double seconds)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection(Enumerable.Range(1, initialCount));
+ const int MaxCount = 4;
+
+ DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(seconds);
+
+ Task addsTakes = ThreadFactory.StartNew(() =>
+ {
+ while (DateTime.UtcNow < end)
+ {
+ for (int i = 1; i <= MaxCount; i++)
+ {
+ Assert.True(c.TryAdd(i));
+ }
+ for (int i = 1; i <= MaxCount; i++)
+ {
+ int item;
+ Assert.True(c.TryTake(out item));
+ Assert.InRange(item, 1, MaxCount);
+ }
+ }
+ });
+
+ while (DateTime.UtcNow < end)
+ {
+ int[] arr = c.Select(i => i).ToArray();
+ Assert.InRange(arr.Length, initialCount, MaxCount + initialCount);
+ Assert.DoesNotContain(0, arr); // make sure we didn't get default(T)
+ }
+
+ addsTakes.GetAwaiter().GetResult();
+ Assert.Equal(initialCount, c.Count);
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(10)]
+ public void DebuggerAttributes_Success(int count)
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection(count);
+ DebuggerAttributes.ValidateDebuggerDisplayReferences(c);
+ DebuggerAttributes.ValidateDebuggerTypeProxyProperties(c);
+ }
+
+ [Fact]
+ public void DebuggerTypeProxy_Ctor_NullArgument_Throws()
+ {
+ IProducerConsumerCollection<int> c = CreateProducerConsumerCollection();
+ Type proxyType = DebuggerAttributes.GetProxyType(c);
+ var tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, new object[] { null }));
+ Assert.IsType<ArgumentNullException>(tie.InnerException);
+ }
+
+ protected static void AssertSetsEqual<T>(HashSet<T> expected, HashSet<T> actual)
+ {
+ Assert.Equal(expected.Count, actual.Count);
+ Assert.Subset(expected, actual);
+ Assert.Subset(actual, expected);
+ }
+
+ protected static void WaitAllOrAnyFailed(params Task[] tasks)
+ {
+ if (tasks.Length == 0)
+ {
+ return;
+ }
+
+ int remaining = tasks.Length;
+ var mres = new ManualResetEventSlim();
+
+ foreach (Task task in tasks)
+ {
+ task.ContinueWith(t =>
+ {
+ if (Interlocked.Decrement(ref remaining) == 0 || t.IsFaulted)
+ {
+ mres.Set();
+ }
+ }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ }
+
+ mres.Wait();
+
+ // Either all tasks are completed or at least one failed
+ foreach (Task t in tasks)
+ {
+ if (t.IsFaulted)
+ {
+ t.GetAwaiter().GetResult(); // propagate for the first one that failed
+ }
+ }
+ }
+
+ private struct LargeStruct // used to help validate that values aren't torn while being read
+ {
+ private readonly long _a, _b, _c, _d, _e, _f, _g, _h;
+
+ public LargeStruct(long value) { _a = _b = _c = _d = _e = _f = _g = _h = value; }
+
+ public long Value
+ {
+ get
+ {
+ if (_a != _b || _a != _c || _a != _d || _a != _e || _a != _f || _a != _g || _a != _h)
+ {
+ throw new Exception($"Inconsistent {nameof(LargeStruct)}: {_a} {_b} {_c} {_d} {_e} {_f} {_g} {_h}");
+ }
+ return _a;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.builds b/src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.builds
index ee6fae6eac..15a1cc3feb 100644
--- a/src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.builds
+++ b/src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.builds
@@ -8,6 +8,9 @@
<TestTFMs>netcoreapp1.0</TestTFMs>
</Project>
<Project Include="System.Collections.Concurrent.Tests.csproj">
+ <TargetGroup>netcoreapp1.1</TargetGroup>
+ </Project>
+ <Project Include="System.Collections.Concurrent.Tests.csproj">
<TargetGroup>netstandard1.3</TargetGroup>
<OSGroup>Windows_NT</OSGroup>
<TestTFMs>netcore50;net46</TestTFMs>
diff --git a/src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.csproj b/src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.csproj
index 07f03e1728..feea24aead 100644
--- a/src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.csproj
+++ b/src/System.Collections.Concurrent/tests/System.Collections.Concurrent.Tests.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
@@ -61,22 +61,26 @@
<Compile Include="BlockingCollectionCancellationTests.cs" />
<Compile Include="BlockingCollectionTests.cs" />
<Compile Include="ConcurrentBagTests.cs" />
- <Compile Include="ConcurrentDicionary\ConcurrentDictionary.NonGeneric.Tests.cs" />
- <Compile Include="ConcurrentDicionary\ConcurrentDictionary.Generic.Tests.cs" />
- <Compile Include="ConcurrentDicionary\ConcurrentDictionaryTests.cs" />
+ <Compile Include="ConcurrentDictionary\ConcurrentDictionary.NonGeneric.Tests.cs" />
+ <Compile Include="ConcurrentDictionary\ConcurrentDictionary.Generic.Tests.cs" />
+ <Compile Include="ConcurrentDictionary\ConcurrentDictionaryTests.cs" />
<Compile Include="ConcurrentQueueTests.cs" />
<Compile Include="ConcurrentStackTests.cs" />
<Compile Include="EtwTests.cs" />
<Compile Include="IntRangePartitionerTests.cs" />
<Compile Include="LongRangePartitionerTests.cs" />
+ <Compile Include="PartitionerHelpers.cs" />
<Compile Include="PartitionerStaticTests.cs" />
<Compile Include="PartitionerTests.cs" />
+ <Compile Include="ProducerConsumerCollectionTests.cs" />
<Compile Include="RangePartitionerNegativeTests.cs" />
- <Compile Include="PartitionerHelpers.cs" />
<Compile Include="$(CommonTestPath)\System\Diagnostics\DebuggerAttributes.cs">
<Link>Common\System\Diagnostics\DebuggerAttributes.cs</Link>
</Compile>
</ItemGroup>
+ <ItemGroup Condition="'$(TargetGroup)' != 'netstandard1.7">
+ <Compile Include="ConcurrentDictionary\ConcurrentDictionaryExtensions.cs" />
+ </ItemGroup>
<ItemGroup Condition="'$(TargetGroup)'!='netstandard1.7'">
<Compile Include="$(CommonPath)\System\SerializableAttribute.cs">
<Link>Common\System\SerializableAttribute.cs</Link>
diff --git a/src/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj b/src/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj
index a242ab6fc6..0a412d3d92 100644
--- a/src/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj
+++ b/src/System.Collections.NonGeneric/src/System.Collections.NonGeneric.csproj
@@ -28,8 +28,6 @@
<Compile Include="$(CommonPath)\System\Collections\CompatibleComparer.cs">
<Link>Common\System\Collections\CompatibleComparer.cs</Link>
</Compile>
- <!-- ToDo: Remove this P2P reference once packages are updated -->
- <ProjectReference Include="..\..\System.Runtime.Extensions\ref\System.Runtime.Extensions.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'net463'">
<TargetingPackReference Include="System" />
diff --git a/src/System.Collections/System.Collections.sln b/src/System.Collections/System.Collections.sln
index 91e0cae307..7866eb3861 100644
--- a/src/System.Collections/System.Collections.sln
+++ b/src/System.Collections/System.Collections.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.21005.1
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Collections", "src\System.Collections.csproj", "{D5FF747F-7A0B-9003-885A-FE9A63E755E5}"
EndProject
@@ -29,14 +29,14 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D5FF747F-7A0B-9003-885A-FE9A63E755E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5FF747F-7A0B-9003-885A-FE9A63E755E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.net46_Debug|Any CPU.ActiveCfg = net46_Debug|Any CPU
- {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.net46_Debug|Any CPU.Build.0 = net46_Debug|Any CPU
- {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.net46_Release|Any CPU.ActiveCfg = net46_Release|Any CPU
- {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.net46_Release|Any CPU.Build.0 = net46_Release|Any CPU
- {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.netcore50_Debug|Any CPU.ActiveCfg = netcore50aotao_Release|Any CPU
- {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.netcore50_Debug|Any CPU.Build.0 = netcore50aotao_Release|Any CPU
- {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.netcore50_Release|Any CPU.ActiveCfg = netcore50aotao_Release|Any CPU
- {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.netcore50_Release|Any CPU.Build.0 = netcore50aotao_Release|Any CPU
+ {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.net46_Debug|Any CPU.ActiveCfg = net463_Release|Any CPU
+ {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.net46_Debug|Any CPU.Build.0 = net463_Release|Any CPU
+ {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.net46_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.net46_Release|Any CPU.Build.0 = Release|Any CPU
+ {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.netcore50_Debug|Any CPU.ActiveCfg = netcoreapp1.1_Release|Any CPU
+ {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.netcore50_Debug|Any CPU.Build.0 = netcoreapp1.1_Release|Any CPU
+ {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.netcore50_Release|Any CPU.ActiveCfg = netcoreapp1.1_Release|Any CPU
+ {D5FF747F-7A0B-9003-885A-FE9A63E755E5}.netcore50_Release|Any CPU.Build.0 = netcoreapp1.1_Release|Any CPU
{D5FF747F-7A0B-9003-885A-FE9A63E755E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5FF747F-7A0B-9003-885A-FE9A63E755E5}.Release|Any CPU.Build.0 = Release|Any CPU
{62E1C77D-E8C7-46F5-9499-8AC302F533A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
diff --git a/src/System.Collections/ref/System.Collections.cs b/src/System.Collections/ref/System.Collections.cs
index 754593c23c..7a445894df 100644
--- a/src/System.Collections/ref/System.Collections.cs
+++ b/src/System.Collections/ref/System.Collections.cs
@@ -31,6 +31,10 @@ namespace System.Collections
public void SetAll(bool value) { }
public void CopyTo(System.Array array, int index) { }
public System.Collections.BitArray Xor(System.Collections.BitArray value) { throw null; }
+#if netcoreapp11
+ public System.Collections.BitArray RightShift(int count) { throw null; }
+ public System.Collections.BitArray LeftShift(int count) { throw null; }
+#endif //netcoreapp11
}
public static partial class StructuralComparisons
{
@@ -53,6 +57,10 @@ namespace System.Collections.Generic
public Dictionary() { }
public Dictionary(System.Collections.Generic.IDictionary<TKey, TValue> dictionary) { }
public Dictionary(System.Collections.Generic.IDictionary<TKey, TValue> dictionary, System.Collections.Generic.IEqualityComparer<TKey> comparer) { }
+#if netcoreapp11
+ public Dictionary(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>> collection) { }
+ public Dictionary(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>> collection, System.Collections.Generic.IEqualityComparer<TKey> comparer) { }
+#endif
public Dictionary(System.Collections.Generic.IEqualityComparer<TKey> comparer) { }
protected Dictionary(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public Dictionary(int capacity) { }
diff --git a/src/System.Collections/src/System/Collections/BitArray.cs b/src/System.Collections/src/System/Collections/BitArray.cs
index b724cde7df..6645534645 100644
--- a/src/System.Collections/src/System/Collections/BitArray.cs
+++ b/src/System.Collections/src/System/Collections/BitArray.cs
@@ -9,7 +9,6 @@ namespace System.Collections
{
// A vector of bits. Use this to store bits efficiently, without having to do bit
// shifting yourself.
- [System.Runtime.InteropServices.ComVisible(true)]
[Serializable]
public sealed class BitArray : ICollection, ICloneable
{
@@ -341,6 +340,126 @@ namespace System.Collections
return this;
}
+ /*=========================================================================
+ ** Shift all the bit values to right on count bits. The current instance is
+ ** updated and returned.
+ *
+ ** Exceptions: ArgumentOutOfRangeException if count < 0
+ =========================================================================*/
+ public BitArray RightShift(int count)
+ {
+ if (count <= 0)
+ {
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(count), count, SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ _version++;
+ return this;
+ }
+
+ int toIndex = 0;
+ int ints = GetArrayLength(m_length, BitsPerInt32);
+ if (count < m_length)
+ {
+ int shiftCount;
+ // We can not use Math.DivRem without taking a dependency on System.Runtime.Extensions
+ int fromIndex = count / BitsPerInt32;
+ shiftCount = count - fromIndex * BitsPerInt32; // Optimized Rem
+
+ if (shiftCount == 0)
+ {
+ unchecked
+ {
+ uint mask = uint.MaxValue >> (BitsPerInt32 - m_length % BitsPerInt32);
+ m_array[ints - 1] &= (int)mask;
+ }
+ Array.Copy(m_array, fromIndex, m_array, 0, ints - fromIndex);
+ toIndex = ints - fromIndex;
+ }
+ else
+ {
+ int lastIndex = ints - 1;
+ unchecked
+ {
+ while (fromIndex < lastIndex)
+ {
+ uint right = (uint)m_array[fromIndex] >> shiftCount;
+ int left = m_array[++fromIndex] << (BitsPerInt32 - shiftCount);
+ m_array[toIndex++] = left | (int)right;
+ }
+ uint mask = uint.MaxValue >> (BitsPerInt32 - m_length % BitsPerInt32);
+ mask &= (uint)m_array[fromIndex];
+ m_array[toIndex++] = (int)(mask >> shiftCount);
+ }
+ }
+ }
+
+ Array.Clear(m_array, toIndex, ints - toIndex);
+ _version++;
+ return this;
+ }
+
+ /*=========================================================================
+ ** Shift all the bit values to left on count bits. The current instance is
+ ** updated and returned.
+ *
+ ** Exceptions: ArgumentOutOfRangeException if count < 0
+ =========================================================================*/
+ public BitArray LeftShift(int count)
+ {
+ if (count <= 0)
+ {
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(count), count, SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ _version++;
+ return this;
+ }
+
+ int lengthToClear;
+ if (count < m_length)
+ {
+ int lastIndex = (m_length - 1) / BitsPerInt32;
+
+ int shiftCount;
+ // We can not use Math.DivRem without taking a dependency on System.Runtime.Extensions
+ lengthToClear = count / BitsPerInt32;
+ shiftCount = count - lengthToClear * BitsPerInt32; // Optimized Rem
+
+ if (shiftCount == 0)
+ {
+ Array.Copy(m_array, 0, m_array, lengthToClear, lastIndex + 1 - lengthToClear);
+ }
+ else
+ {
+ int fromindex = lastIndex - lengthToClear;
+ unchecked
+ {
+ while (fromindex > 0)
+ {
+ int left = m_array[fromindex] << shiftCount;
+ uint right = (uint)m_array[--fromindex] >> (BitsPerInt32 - shiftCount);
+ m_array[lastIndex] = left | (int)right;
+ lastIndex--;
+ }
+ m_array[lastIndex] = m_array[fromindex] << shiftCount;
+ }
+ }
+ }
+ else
+ {
+ lengthToClear = GetArrayLength(m_length, BitsPerInt32); // Clear all
+ }
+
+ Array.Clear(m_array, 0, lengthToClear);
+ _version++;
+ return this;
+ }
+
public int Length
{
get
diff --git a/src/System.Collections/src/System/Collections/Generic/BitHelper.cs b/src/System.Collections/src/System/Collections/Generic/BitHelper.cs
index 5075bfb7be..53853fdcf3 100644
--- a/src/System.Collections/src/System/Collections/Generic/BitHelper.cs
+++ b/src/System.Collections/src/System/Collections/Generic/BitHelper.cs
@@ -41,7 +41,7 @@ namespace System.Collections.Generic
/// on a bit array and then need to loop over it. In particular, if it avoided visiting
/// every bit, it would allow good perf improvements when the bit array is sparse.
/// </summary>
- unsafe internal sealed class BitHelper
+ internal unsafe sealed class BitHelper
{ // should not be serialized
private const byte MarkedBitFlag = 1;
private const byte IntSize = 32;
diff --git a/src/System.Collections/src/System/Collections/Generic/Dictionary.cs b/src/System.Collections/src/System/Collections/Generic/Dictionary.cs
index b556d4e5e6..8dd5d845b0 100644
--- a/src/System.Collections/src/System/Collections/Generic/Dictionary.cs
+++ b/src/System.Collections/src/System/Collections/Generic/Dictionary.cs
@@ -13,7 +13,6 @@ namespace System.Collections.Generic
{
[DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))]
[DebuggerDisplay("Count = {Count}")]
- [System.Runtime.InteropServices.ComVisible(false)]
[Serializable]
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>, ISerializable, IDeserializationCallback
{
@@ -91,6 +90,22 @@ namespace System.Collections.Generic
}
}
+ public Dictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) : this(collection, null) { }
+
+ public Dictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) :
+ this((collection as ICollection<KeyValuePair<TKey, TValue>>)?.Count ?? 0, comparer)
+ {
+ if (collection == null)
+ {
+ throw new ArgumentNullException(nameof(collection));
+ }
+
+ foreach (KeyValuePair<TKey, TValue> pair in collection)
+ {
+ Add(pair.Key, pair.Value);
+ }
+ }
+
protected Dictionary(SerializationInfo info, StreamingContext context)
{
// We can't do anything with the keys and values until the entire graph has been deserialized
diff --git a/src/System.Collections/src/System/Collections/Generic/LinkedList.cs b/src/System.Collections/src/System/Collections/Generic/LinkedList.cs
index d0661087b6..eca68c7e9b 100644
--- a/src/System.Collections/src/System/Collections/Generic/LinkedList.cs
+++ b/src/System.Collections/src/System/Collections/Generic/LinkedList.cs
@@ -562,7 +562,7 @@ namespace System.Collections.Generic
_siInfo = null;
}
- internal Enumerator(SerializationInfo info, StreamingContext context)
+ private Enumerator(SerializationInfo info, StreamingContext context)
{
_siInfo = info;
_list = null;
diff --git a/src/System.Collections/tests/BitArray/BitArray_CtorTests.cs b/src/System.Collections/tests/BitArray/BitArray_CtorTests.cs
index a514adc8f2..f667b13bd6 100644
--- a/src/System.Collections/tests/BitArray/BitArray_CtorTests.cs
+++ b/src/System.Collections/tests/BitArray/BitArray_CtorTests.cs
@@ -236,6 +236,16 @@ namespace System.Collections.Tests
Assert.False(bitArray.IsReadOnly);
Assert.Equal(bitArray, bitArray.Clone());
}
+
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "A bug in BitArray.Clone() caused an ArgumentExeption to be thrown in this case.")]
+ [Fact]
+ public static void Clone_LongLength_Works()
+ {
+ BitArray bitArray = new BitArray(int.MaxValue - 30);
+ BitArray clone = (BitArray)bitArray.Clone();
+
+ Assert.Equal(bitArray.Length, clone.Length);
+ }
#endif //netstandard17
}
}
diff --git a/src/System.Collections/tests/BitArray/BitArray_GetSetTests.cs b/src/System.Collections/tests/BitArray/BitArray_GetSetTests.cs
index 0fabd72eda..ade93a73de 100644
--- a/src/System.Collections/tests/BitArray/BitArray_GetSetTests.cs
+++ b/src/System.Collections/tests/BitArray/BitArray_GetSetTests.cs
@@ -359,6 +359,7 @@ namespace System.Collections.Tests
}
[Theory]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Desktop Framework hasn't received the fix for #9838 yet.")]
[MemberData(nameof(CopyTo_Hidden_Data))]
public static void CopyTo_Int_Hidden(string label, BitArray bits)
{
@@ -379,6 +380,24 @@ namespace System.Collections.Tests
}
[Theory]
+ [SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "Desktop Framework hasn't received the fix for #9838 yet.")]
+ [MemberData(nameof(CopyTo_Hidden_Data))]
+ public static void CopyTo_Int_Hidden_Desktop(string label, BitArray bits)
+ {
+ int allBitsSet = unchecked((int)0xffffffff); // 32 bits set to 1 = -1
+ int fullInts = bits.Length / BitsPerInt32;
+ int remainder = bits.Length % BitsPerInt32;
+ int arrayLength = fullInts + (remainder > 0 ? 1 : 0);
+
+ int[] data = new int[arrayLength];
+ ((ICollection)bits).CopyTo(data, 0);
+
+ Assert.All(data, d => Assert.Equal(allBitsSet, d));
+
+ }
+
+ [Theory]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Desktop Framework hasn't received the fix for #9838 yet.")]
[MemberData(nameof(CopyTo_Hidden_Data))]
public static void CopyTo_Byte_Hidden(string label, BitArray bits)
{
@@ -398,5 +417,23 @@ namespace System.Collections.Tests
Assert.Equal((byte)((1 << remainder) - 1), data[fullBytes]);
}
}
+
+ [Theory]
+ [SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "Desktop Framework hasn't received the fix for #9838 yet.")]
+ [MemberData(nameof(CopyTo_Hidden_Data))]
+ public static void CopyTo_Byte_Hidden_Desktop(string label, BitArray bits)
+ {
+ byte allBitsSet = (1 << BitsPerByte) - 1; // 8 bits set to 1 = 255
+
+ int fullBytes = bits.Length / BitsPerByte;
+ int remainder = bits.Length % BitsPerByte;
+ int arrayLength = fullBytes + (remainder > 0 ? 1 : 0);
+
+ byte[] data = new byte[arrayLength];
+ ((ICollection)bits).CopyTo(data, 0);
+
+ Assert.All(data, d => Assert.Equal(allBitsSet, d));
+
+ }
}
}
diff --git a/src/System.Collections/tests/BitArray/BitArray_OperatorsTests.cs b/src/System.Collections/tests/BitArray/BitArray_OperatorsTests.cs
index d8e94de2b8..17545035dc 100644
--- a/src/System.Collections/tests/BitArray/BitArray_OperatorsTests.cs
+++ b/src/System.Collections/tests/BitArray/BitArray_OperatorsTests.cs
@@ -8,7 +8,7 @@ using Xunit;
namespace System.Collections.Tests
{
- public static class BitArray_OperatorsTests
+ public static partial class BitArray_OperatorsTests
{
private const int BitsPerByte = 8;
private const int BitsPerInt32 = 32;
@@ -189,3 +189,4 @@ namespace System.Collections.Tests
}
}
}
+
diff --git a/src/System.Collections/tests/BitArray/BitArray_OperatorsTests.netcoreapp1.1.cs b/src/System.Collections/tests/BitArray/BitArray_OperatorsTests.netcoreapp1.1.cs
new file mode 100644
index 0000000000..7ba027e122
--- /dev/null
+++ b/src/System.Collections/tests/BitArray/BitArray_OperatorsTests.netcoreapp1.1.cs
@@ -0,0 +1,130 @@
+// 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.Generic;
+using System.Linq;
+using Xunit;
+
+namespace System.Collections.Tests
+{
+ public static partial class BitArray_OperatorsTests
+ {
+ #region Shift Tests
+
+ public static IEnumerable<object> Shift_Data()
+ {
+ foreach (int size in new[] { 0, 1, BitsPerInt32 / 2, BitsPerInt32, BitsPerInt32 + 1, 2 * BitsPerInt32, 2 * BitsPerInt32 + 1 })
+ {
+ foreach (int shift in new[] { 0, 1, size / 2, size - 1, size }.Where(s => s >= 0).Distinct())
+ {
+ yield return new object[] { size, new int[] { /* deliberately empty */ }, shift };
+ yield return new object[] { size, Enumerable.Range(0, size), shift };
+
+ if (size > 1)
+ {
+ foreach (int position in new[] { 0, size / 2, size - 1 })
+ {
+ yield return new object[] { size, new[] { position }, shift };
+ }
+ yield return new object[] { size, new[] { 0, size / 2, size - 1 }, shift };
+ }
+ }
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(Shift_Data))]
+ public static void RightShift(int length, IEnumerable<int> set, int shift)
+ {
+ BitArray ba = new BitArray(GetBoolArray(length, set));
+ bool[] expected = GetBoolArray(length, set.Select(i => i - shift).Where(i => i >= 0));
+
+ BitArray returned = ba.RightShift(shift);
+ Assert.Same(ba, returned);
+
+ int index = 0;
+ Assert.All(ba.Cast<bool>(), bit => Assert.Equal(expected[index++], bit));
+ }
+
+ [Theory]
+ [MemberData(nameof(Shift_Data))]
+ public static void LeftShift(int length, IEnumerable<int> set, int shift)
+ {
+ BitArray ba = new BitArray(GetBoolArray(length, set));
+ bool[] expected = GetBoolArray(length, set.Select(i => i + shift).Where(i => i < length));
+
+ BitArray returned = ba.LeftShift(shift);
+ Assert.Same(ba, returned);
+
+ int index = 0;
+ Assert.All(ba.Cast<bool>(), bit => Assert.Equal(expected[index++], bit));
+ }
+
+ private static bool[] GetBoolArray(int length, IEnumerable<int> set)
+ {
+ bool[] b = new bool[length];
+ foreach (int position in set)
+ {
+ b[position] = true;
+ }
+ return b;
+ }
+
+ [Fact]
+ public static void LeftShift_Iterator()
+ {
+ BitArray ba = new BitArray(BitsPerInt32 / 2);
+ IEnumerator enumerator = ba.GetEnumerator();
+ Assert.True(enumerator.MoveNext());
+ ba.LeftShift(1);
+ Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ }
+
+ [Fact]
+ public static void RightShift_Iterator()
+ {
+ BitArray ba = new BitArray(BitsPerInt32 / 2);
+ IEnumerator enumerator = ba.GetEnumerator();
+ Assert.True(enumerator.MoveNext());
+ ba.RightShift(1);
+ Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ }
+
+ public static IEnumerable<object> RightShift_Hidden_Data()
+ {
+ yield return new object[] { "Constructor", Unset_Visible_Bits(new BitArray(BitsPerInt32 / 2, true)) };
+ yield return new object[] { "Not", Unset_Visible_Bits(new BitArray(BitsPerInt32 / 2, false).Not()) };
+ BitArray setAll = new BitArray(BitsPerInt32 / 2, false);
+ setAll.SetAll(true);
+ yield return new object[] { "SetAll", Unset_Visible_Bits(setAll) };
+ BitArray lengthShort = new BitArray(BitsPerInt32, true);
+ lengthShort.Length = BitsPerInt32 / 2;
+ yield return new object[] { "Length-Short", Unset_Visible_Bits(lengthShort) };
+ BitArray lengthLong = new BitArray(2 * BitsPerInt32, true);
+ lengthLong.Length = BitsPerInt32;
+ yield return new object[] { "Length-Long", Unset_Visible_Bits(lengthLong) };
+ BitArray leftShift = new BitArray(BitsPerInt32 / 2);
+ for (int i = 0; i < leftShift.Length; i++) leftShift[i] = true;
+ yield return new object[] { "LeftShift", leftShift.LeftShift(BitsPerInt32 / 2) };
+ }
+
+ private static BitArray Unset_Visible_Bits(BitArray ba)
+ {
+ for (int i = 0; i < ba.Length; i++) ba[i] = false;
+ return ba;
+ }
+
+ [Theory]
+ [MemberData(nameof(RightShift_Hidden_Data))]
+ public static void RightShift_Hidden(string label, BitArray bits)
+ {
+ Assert.All(bits.Cast<bool>(), bit => Assert.False(bit));
+ bits.RightShift(1);
+ Assert.All(bits.Cast<bool>(), bit => Assert.False(bit));
+ }
+
+ #endregion
+ }
+}
+
diff --git a/src/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs b/src/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs
index da4720e328..3298856b6c 100644
--- a/src/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs
+++ b/src/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs
@@ -11,7 +11,7 @@ namespace System.Collections.Tests
/// <summary>
/// Contains tests that ensure the correctness of the Dictionary class.
/// </summary>
- public abstract class Dictionary_Generic_Tests<TKey, TValue> : IDictionary_Generic_Tests<TKey, TValue>
+ public abstract partial class Dictionary_Generic_Tests<TKey, TValue> : IDictionary_Generic_Tests<TKey, TValue>
{
#region IDictionary<TKey, TValue Helper Methods
diff --git a/src/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.netcoreapp1.1.cs b/src/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.netcoreapp1.1.cs
new file mode 100644
index 0000000000..56846ff27d
--- /dev/null
+++ b/src/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.netcoreapp1.1.cs
@@ -0,0 +1,37 @@
+using System.Collections.Generic;
+using System.Linq;
+using Xunit;
+
+namespace System.Collections.Tests
+{
+ public abstract partial class Dictionary_Generic_Tests<TKey, TValue> : IDictionary_Generic_Tests<TKey, TValue>
+ {
+ [Fact]
+ public void Dictionary_Generic_Constructor_IEnumerable_ThrowsOnNull()
+ {
+ Assert.Throws<ArgumentNullException>("collection", () => new Dictionary<TKey, TValue>((IEnumerable<KeyValuePair<TKey, TValue>>)null));
+ Assert.Throws<ArgumentNullException>("collection", () => new Dictionary<TKey, TValue>((IEnumerable<KeyValuePair<TKey, TValue>>)null, EqualityComparer<TKey>.Default));
+ }
+
+ [Theory]
+ [MemberData(nameof(ValidCollectionSizes))]
+ public void Dictionary_Generic_Constructor_IEnumerable(int count)
+ {
+ IEnumerable<KeyValuePair<TKey, TValue>> collection = GenericIEnumerableFactory(count);
+ var copied = new Dictionary<TKey, TValue>(collection);
+ Assert.Equal(count, collection.Count());
+ Assert.Equal(collection, copied);
+ }
+
+ [Theory]
+ [MemberData(nameof(ValidCollectionSizes))]
+ public void Dictionary_Generic_Constructor_IEnumerable_IEqualityComparer(int count)
+ {
+ IEqualityComparer<TKey> comparer = GetKeyIEqualityComparer();
+ IEnumerable<KeyValuePair<TKey, TValue>> collection = GenericIEnumerableFactory(count);
+ var copied = new Dictionary<TKey, TValue>(collection, comparer);
+ Assert.Equal(collection, copied);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/System.Collections/tests/System.Collections.Tests.csproj b/src/System.Collections/tests/System.Collections.Tests.csproj
index d9065af1cd..16fee27ea4 100644
--- a/src/System.Collections/tests/System.Collections.Tests.csproj
+++ b/src/System.Collections/tests/System.Collections.Tests.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
@@ -69,6 +69,7 @@
<Compile Include="BitArray\BitArray_CtorTests.cs" />
<Compile Include="BitArray\BitArray_GetSetTests.cs" />
<Compile Include="BitArray\BitArray_OperatorsTests.cs" />
+ <Compile Include="BitArray\BitArray_OperatorsTests.netcoreapp1.1.cs" Condition="'$(TargetGroup)'=='netcoreapp1.1'" />
<Compile Include="Generic\Comparers\Comparer.Generic.Tests.cs" />
<Compile Include="Generic\Comparers\Comparer.Tests.cs" />
<Compile Include="Generic\Comparers\Comparers.Generic.cs" />
@@ -79,6 +80,7 @@
<Compile Include="Generic\Dictionary\HashCollisionScenarios\OutOfBoundsRegression.cs" />
<Compile Include="Generic\Dictionary\Dictionary.Generic.cs" />
<Compile Include="Generic\Dictionary\Dictionary.Generic.Tests.cs" />
+ <Compile Include="Generic\Dictionary\Dictionary.Generic.Tests.netcoreapp1.1.cs" Condition="'$(TargetGroup)'=='netcoreapp1.1'" />
<Compile Include="Generic\Dictionary\Dictionary.Generic.Tests.Keys.cs" />
<Compile Include="Generic\Dictionary\Dictionary.Generic.Tests.Values.cs" />
<Compile Include="Generic\HashSet\HashSet.Generic.cs" />
diff --git a/src/System.ComponentModel.Primitives/src/FxCopBaseline.cs b/src/System.ComponentModel.Primitives/src/FxCopBaseline.cs
new file mode 100644
index 0000000000..b702751c5d
--- /dev/null
+++ b/src/System.ComponentModel.Primitives/src/FxCopBaseline.cs
@@ -0,0 +1,3 @@
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.ComponentModel.Component.#Dispose(System.Boolean)")]
diff --git a/src/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj b/src/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj
index 1d656de5a4..c2621cfb63 100644
--- a/src/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj
+++ b/src/System.ComponentModel.Primitives/src/System.ComponentModel.Primitives.csproj
@@ -37,6 +37,9 @@
<Compile Include="System\ComponentModel\RefreshProperties.cs" />
<Compile Include="System\ComponentModel\RefreshPropertiesAttribute.cs" />
</ItemGroup>
+ <ItemGroup>
+ <Compile Include="FxCopBaseline.cs"/>
+ </ItemGroup>
<ItemGroup Condition="'$(TargetGroup)'=='netstandard'">
<Compile Include="System\ComponentModel\Component.cs" />
</ItemGroup>
diff --git a/src/System.ComponentModel.Primitives/src/System/ComponentModel/Component.cs b/src/System.ComponentModel.Primitives/src/System/ComponentModel/Component.cs
index 657393c26c..51261a81b6 100644
--- a/src/System.ComponentModel.Primitives/src/System/ComponentModel/Component.cs
+++ b/src/System.ComponentModel.Primitives/src/System/ComponentModel/Component.cs
@@ -13,7 +13,6 @@ namespace System.ComponentModel
/// interface and enables object-sharing between applications.</para>
/// </summary>
[
- ComVisible(true),
DesignerCategory("Component")
]
public class Component : MarshalByRefObject, IComponent
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AddingNewEventArgs.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AddingNewEventArgs.cs
index a26edf9a50..62813b0d72 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AddingNewEventArgs.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AddingNewEventArgs.cs
@@ -16,13 +16,11 @@ namespace System.ComponentModel
/// </summary>
public class AddingNewEventArgs : EventArgs
{
- private object _newObject = null;
-
/// <summary>
/// Initializes a new instance of the <see cref='System.ComponentModel.AddingNewEventArgs'/> class,
/// with no new object defined.
/// </summary>
- public AddingNewEventArgs() : base()
+ public AddingNewEventArgs()
{
}
@@ -30,25 +28,14 @@ namespace System.ComponentModel
/// Initializes a new instance of the <see cref='System.ComponentModel.AddingNewEventArgs'/> class,
/// with the specified object defined as the default new object.
/// </summary>
- public AddingNewEventArgs(object newObject) : base()
+ public AddingNewEventArgs(object newObject)
{
- _newObject = newObject;
+ NewObject = newObject;
}
/// <summary>
/// Gets or sets the new object that will be added to the list.
/// </summary>
- public object NewObject
- {
- get
- {
- return _newObject;
- }
-
- set
- {
- _newObject = value;
- }
- }
+ public object NewObject { get; set; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs
index 393f088227..4b26b4074b 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs
@@ -19,8 +19,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.All)]
public sealed class AmbientValueAttribute : Attribute
{
- private readonly object _value;
-
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class, converting the
/// specified value to the
@@ -34,11 +32,11 @@ namespace System.ComponentModel
// load an otherwise normal class.
try
{
- _value = TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value);
+ Value = TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value);
}
catch
{
- Debug.Fail("Ambient value attribute of type " + type.FullName + " threw converting from the string '" + value + "'.");
+ Debug.Fail($"Ambient value attribute of type {type.FullName} threw converting from the string '{value}'.");
}
}
@@ -48,7 +46,7 @@ namespace System.ComponentModel
/// </summary>
public AmbientValueAttribute(char value)
{
- _value = value;
+ Value = value;
}
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class using an 8-bit unsigned
@@ -56,7 +54,7 @@ namespace System.ComponentModel
/// </summary>
public AmbientValueAttribute(byte value)
{
- _value = value;
+ Value = value;
}
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class using a 16-bit signed
@@ -64,7 +62,7 @@ namespace System.ComponentModel
/// </summary>
public AmbientValueAttribute(short value)
{
- _value = value;
+ Value = value;
}
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class using a 32-bit signed
@@ -72,7 +70,7 @@ namespace System.ComponentModel
/// </summary>
public AmbientValueAttribute(int value)
{
- _value = value;
+ Value = value;
}
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class using a 64-bit signed
@@ -80,7 +78,7 @@ namespace System.ComponentModel
/// </summary>
public AmbientValueAttribute(long value)
{
- _value = value;
+ Value = value;
}
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class using a
@@ -89,7 +87,7 @@ namespace System.ComponentModel
/// </summary>
public AmbientValueAttribute(float value)
{
- _value = value;
+ Value = value;
}
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class using a
@@ -98,7 +96,7 @@ namespace System.ComponentModel
/// </summary>
public AmbientValueAttribute(double value)
{
- _value = value;
+ Value = value;
}
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class using a <see cref='System.Boolean'/>
@@ -106,14 +104,14 @@ namespace System.ComponentModel
/// </summary>
public AmbientValueAttribute(bool value)
{
- _value = value;
+ Value = value;
}
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class using a <see cref='System.String'/>.</para>
/// </summary>
public AmbientValueAttribute(string value)
{
- _value = value;
+ Value = value;
}
/// <summary>
@@ -122,7 +120,7 @@ namespace System.ComponentModel
/// </summary>
public AmbientValueAttribute(object value)
{
- _value = value;
+ Value = value;
}
/// <summary>
@@ -132,13 +130,7 @@ namespace System.ComponentModel
/// bound to.
/// </para>
/// </summary>
- public object Value
- {
- get
- {
- return _value;
- }
- }
+ public object Value { get; }
public override bool Equals(object obj)
{
@@ -151,9 +143,9 @@ namespace System.ComponentModel
if (other != null)
{
- if (_value != null)
+ if (Value != null)
{
- return _value.Equals(other.Value);
+ return Value.Equals(other.Value);
}
else
{
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeCollection.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeCollection.cs
index c81640d75f..211b047f44 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeCollection.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeCollection.cs
@@ -34,7 +34,7 @@ namespace System.ComponentModel
private AttributeEntry[] _foundAttributeTypes;
- private int _index = 0;
+ private int _index;
/// <summary>
/// Creates a new AttributeCollection.
@@ -107,7 +107,7 @@ namespace System.ComponentModel
// Now, if we collapsed some attributes, create a new array.
//
- Attribute[] attributes = null;
+ Attribute[] attributes;
if (actualCount < newArray.Length)
{
attributes = new Attribute[actualCount];
@@ -125,35 +125,17 @@ namespace System.ComponentModel
/// Gets the attributes collection.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Matches constructor input type")]
- protected virtual Attribute[] Attributes
- {
- get
- {
- return _attributes;
- }
- }
+ protected virtual Attribute[] Attributes => _attributes;
/// <summary>
/// Gets the number of attributes.
/// </summary>
- public int Count
- {
- get
- {
- return Attributes.Length;
- }
- }
+ public int Count => Attributes.Length;
/// <summary>
/// Gets the attribute with the specified index number.
/// </summary>
- public virtual Attribute this[int index]
- {
- get
- {
- return Attributes[index];
- }
- }
+ public virtual Attribute this[int index] => Attributes[index];
/// <summary>
/// Gets the attribute with the specified type.
@@ -361,30 +343,12 @@ namespace System.ComponentModel
}
/// <internalonly/>
- bool ICollection.IsSynchronized
- {
- get
- {
- return false;
- }
- }
+ bool ICollection.IsSynchronized => false;
/// <internalonly/>
- object ICollection.SyncRoot
- {
- get
- {
- return null;
- }
- }
+ object ICollection.SyncRoot => null;
- int ICollection.Count
- {
- get
- {
- return Count;
- }
- }
+ int ICollection.Count => Count;
IEnumerator IEnumerable.GetEnumerator()
{
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeProviderAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeProviderAttribute.cs
index ba396d8e3d..eb2ef0b87b 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeProviderAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeProviderAttribute.cs
@@ -10,9 +10,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Property)]
public class AttributeProviderAttribute : Attribute
{
- private readonly string _typeName;
- private readonly string _propertyName;
-
/// <summary>
/// Creates a new AttributeProviderAttribute object.
/// </summary>
@@ -23,7 +20,7 @@ namespace System.ComponentModel
throw new ArgumentNullException(nameof(typeName));
}
- _typeName = typeName;
+ TypeName = typeName;
}
/// <summary>
@@ -40,8 +37,8 @@ namespace System.ComponentModel
throw new ArgumentNullException(nameof(propertyName));
}
- _typeName = typeName;
- _propertyName = propertyName;
+ TypeName = typeName;
+ PropertyName = propertyName;
}
/// <summary>
@@ -54,31 +51,19 @@ namespace System.ComponentModel
throw new ArgumentNullException(nameof(type));
}
- _typeName = type.AssemblyQualifiedName;
+ TypeName = type.AssemblyQualifiedName;
}
/// <summary>
/// The TypeName property returns the assembly qualified type name
/// passed into the constructor.
/// </summary>
- public string TypeName
- {
- get
- {
- return _typeName;
- }
- }
+ public string TypeName { get; }
/// <summary>
/// The TypeName property returns the property name that will be used to query attributes from.
/// </summary>
- public string PropertyName
- {
- get
- {
- return _propertyName;
- }
- }
+ public string PropertyName { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BaseNumberConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BaseNumberConverter.cs
index 71be45eec5..31ee42b7f8 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BaseNumberConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BaseNumberConverter.cs
@@ -15,13 +15,7 @@ namespace System.ComponentModel
/// <summary>
/// Determines whether this editor will attempt to convert hex (0x or #) strings
/// </summary>
- internal virtual bool AllowHex
- {
- get
- {
- return true;
- }
- }
+ internal virtual bool AllowHex => true;
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindableAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindableAttribute.cs
index a51ce380fe..a7db254516 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindableAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindableAttribute.cs
@@ -41,9 +41,7 @@ namespace System.ComponentModel
/// </summary>
public static readonly BindableAttribute Default = No;
- private bool _bindable = false;
- private bool _isDefault = false;
- private BindingDirection _direction;
+ private bool _isDefault;
/// <summary>
/// <para>
@@ -61,8 +59,8 @@ namespace System.ComponentModel
/// </summary>
public BindableAttribute(bool bindable, BindingDirection direction)
{
- _bindable = bindable;
- _direction = direction;
+ Bindable = bindable;
+ Direction = direction;
}
/// <summary>
@@ -81,9 +79,9 @@ namespace System.ComponentModel
/// </summary>
public BindableAttribute(BindableSupport flags, BindingDirection direction)
{
- _bindable = (flags != BindableSupport.No);
+ Bindable = (flags != BindableSupport.No);
_isDefault = (flags == BindableSupport.Default);
- _direction = direction;
+ Direction = direction;
}
/// <summary>
@@ -92,13 +90,7 @@ namespace System.ComponentModel
/// whether a property is appropriate to bind data to.
/// </para>
/// </summary>
- public bool Bindable
- {
- get
- {
- return _bindable;
- }
- }
+ public bool Bindable { get; }
/// <summary>
/// <para>
@@ -106,13 +98,7 @@ namespace System.ComponentModel
/// the direction(s) this property be bound to data.
/// </para>
/// </summary>
- public BindingDirection Direction
- {
- get
- {
- return _direction;
- }
- }
+ public BindingDirection Direction { get; }
/// <internalonly/>
/// <summary>
@@ -126,7 +112,7 @@ namespace System.ComponentModel
if (obj != null && obj is BindableAttribute)
{
- return (((BindableAttribute)obj).Bindable == _bindable);
+ return (((BindableAttribute)obj).Bindable == Bindable);
}
return false;
@@ -137,7 +123,7 @@ namespace System.ComponentModel
/// </summary>
public override int GetHashCode()
{
- return _bindable.GetHashCode();
+ return Bindable.GetHashCode();
}
/// <summary>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindingList.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindingList.cs
index aa7b5ef32d..a28abe8e81 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindingList.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindingList.cs
@@ -23,13 +23,13 @@ namespace System.ComponentModel
{
private int _addNewPos = -1;
private bool _raiseListChangedEvents = true;
- private bool _raiseItemChangedEvents = false;
+ private bool _raiseItemChangedEvents;
[NonSerialized]
- private PropertyDescriptorCollection _itemTypeProperties = null;
+ private PropertyDescriptorCollection _itemTypeProperties;
[NonSerialized]
- private PropertyChangedEventHandler _propertyChangedEventHandler = null;
+ private PropertyChangedEventHandler _propertyChangedEventHandler;
[NonSerialized]
private AddingNewEventHandler _onAddingNew;
@@ -43,14 +43,14 @@ namespace System.ComponentModel
private bool _allowNew = true;
private bool _allowEdit = true;
private bool _allowRemove = true;
- private bool _userSetAllowNew = false;
+ private bool _userSetAllowNew;
#region Constructors
/// <summary>
/// Default constructor.
/// </summary>
- public BindingList() : base()
+ public BindingList()
{
Initialize();
}
@@ -93,7 +93,7 @@ namespace System.ComponentModel
return true;
}
- if (itemType.GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, new Type[0], null) != null)
+ if (itemType.GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, Array.Empty<Type>(), null) != null)
{
return true;
}
@@ -136,10 +136,7 @@ namespace System.ComponentModel
/// </summary>
protected virtual void OnAddingNew(AddingNewEventArgs e)
{
- if (_onAddingNew != null)
- {
- _onAddingNew(this, e);
- }
+ _onAddingNew?.Invoke(this, e);
}
// Private helper method
@@ -168,16 +165,14 @@ namespace System.ComponentModel
_onListChanged -= value;
}
}
+
/// <summary>
/// Raises the ListChanged event.
/// </summary>
protected virtual void OnListChanged(ListChangedEventArgs e)
{
- if (_onListChanged != null)
- {
- _onListChanged(this, e);
- }
+ _onListChanged?.Invoke(this, e);
}
public bool RaiseListChangedEvents
@@ -348,13 +343,7 @@ namespace System.ComponentModel
return newItem;
}
- private bool AddingNewHandled
- {
- get
- {
- return _onAddingNew != null && _onAddingNew.GetInvocationList().Length > 0;
- }
- }
+ private bool AddingNewHandled => _onAddingNew != null && _onAddingNew.GetInvocationList().Length > 0;
/// <summary>
/// Creates a new item and adds it to the list.
@@ -415,13 +404,7 @@ namespace System.ComponentModel
}
/* private */
- bool IBindingList.AllowNew
- {
- get
- {
- return AllowNew;
- }
- }
+ bool IBindingList.AllowNew => AllowNew;
/// <summary>
/// </summary>
@@ -442,13 +425,7 @@ namespace System.ComponentModel
}
/* private */
- bool IBindingList.AllowEdit
- {
- get
- {
- return AllowEdit;
- }
- }
+ bool IBindingList.AllowEdit => AllowEdit;
/// <summary>
/// </summary>
@@ -469,109 +446,31 @@ namespace System.ComponentModel
}
/* private */
- bool IBindingList.AllowRemove
- {
- get
- {
- return AllowRemove;
- }
- }
+ bool IBindingList.AllowRemove => AllowRemove;
- bool IBindingList.SupportsChangeNotification
- {
- get
- {
- return SupportsChangeNotificationCore;
- }
- }
+ bool IBindingList.SupportsChangeNotification => SupportsChangeNotificationCore;
- protected virtual bool SupportsChangeNotificationCore
- {
- get
- {
- return true;
- }
- }
+ protected virtual bool SupportsChangeNotificationCore => true;
- bool IBindingList.SupportsSearching
- {
- get
- {
- return SupportsSearchingCore;
- }
- }
+ bool IBindingList.SupportsSearching => SupportsSearchingCore;
- protected virtual bool SupportsSearchingCore
- {
- get
- {
- return false;
- }
- }
+ protected virtual bool SupportsSearchingCore => false;
- bool IBindingList.SupportsSorting
- {
- get
- {
- return SupportsSortingCore;
- }
- }
+ bool IBindingList.SupportsSorting => SupportsSortingCore;
- protected virtual bool SupportsSortingCore
- {
- get
- {
- return false;
- }
- }
+ protected virtual bool SupportsSortingCore => false;
- bool IBindingList.IsSorted
- {
- get
- {
- return IsSortedCore;
- }
- }
+ bool IBindingList.IsSorted => IsSortedCore;
- protected virtual bool IsSortedCore
- {
- get
- {
- return false;
- }
- }
+ protected virtual bool IsSortedCore => false;
- PropertyDescriptor IBindingList.SortProperty
- {
- get
- {
- return SortPropertyCore;
- }
- }
+ PropertyDescriptor IBindingList.SortProperty => SortPropertyCore;
- protected virtual PropertyDescriptor SortPropertyCore
- {
- get
- {
- return null;
- }
- }
+ protected virtual PropertyDescriptor SortPropertyCore => null;
- ListSortDirection IBindingList.SortDirection
- {
- get
- {
- return SortDirectionCore;
- }
- }
+ ListSortDirection IBindingList.SortDirection => SortDirectionCore;
- protected virtual ListSortDirection SortDirectionCore
- {
- get
- {
- return ListSortDirection.Ascending;
- }
- }
+ protected virtual ListSortDirection SortDirectionCore => ListSortDirection.Ascending;
void IBindingList.ApplySort(PropertyDescriptor prop, ListSortDirection direction)
{
@@ -718,13 +617,7 @@ namespace System.ComponentModel
/// of type ItemChanged as a result of property changes on individual list items
/// unless those items support INotifyPropertyChanged
/// </summary>
- bool IRaiseItemChangedEvents.RaisesItemChangedEvents
- {
- get
- {
- return _raiseItemChangedEvents;
- }
- }
+ bool IRaiseItemChangedEvents.RaisesItemChangedEvents => _raiseItemChangedEvents;
#endregion
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BooleanConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BooleanConverter.cs
index 2a7145d0df..0f90ced4f1 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BooleanConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/BooleanConverter.cs
@@ -51,11 +51,7 @@ namespace System.ComponentModel
/// </summary>
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
- if (s_values == null)
- {
- s_values = new StandardValuesCollection(new object[] { true, false });
- }
- return s_values;
+ return s_values ?? (s_values = new StandardValuesCollection(new object[] {true, false}));
}
/// <summary>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ByteConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ByteConverter.cs
index f6734b3526..163a0f082c 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ByteConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ByteConverter.cs
@@ -16,13 +16,7 @@ namespace System.ComponentModel
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(Byte);
- }
- }
+ internal override Type TargetType => typeof(byte);
/// <summary>
/// Convert the given string to a Byte using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionChangeEventArgs.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionChangeEventArgs.cs
index 2a63801d29..7b16f4e8ec 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionChangeEventArgs.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionChangeEventArgs.cs
@@ -9,38 +9,23 @@ namespace System.ComponentModel
/// </summary>
public class CollectionChangeEventArgs : EventArgs
{
- private readonly CollectionChangeAction _action;
- private readonly object _element;
-
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.CollectionChangeEventArgs'/> class.</para>
/// </summary>
public CollectionChangeEventArgs(CollectionChangeAction action, object element)
{
- _action = action;
- _element = element;
+ Action = action;
+ Element = element;
}
/// <summary>
/// <para>Gets an action that specifies how the collection changed.</para>
/// </summary>
- public virtual CollectionChangeAction Action
- {
- get
- {
- return _action;
- }
- }
+ public virtual CollectionChangeAction Action { get; }
/// <summary>
/// <para>Gets the instance of the collection with the change. </para>
/// </summary>
- public virtual object Element
- {
- get
- {
- return _element;
- }
- }
+ public virtual object Element { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComplexBindingPropertiesAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComplexBindingPropertiesAttribute.cs
index 2ac2e39c1d..33045927c6 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComplexBindingPropertiesAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComplexBindingPropertiesAttribute.cs
@@ -15,9 +15,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Class)]
public sealed class ComplexBindingPropertiesAttribute : Attribute
{
- private readonly string _dataSource;
- private readonly string _dataMember;
-
/// <summary>
/// <para>
/// Initializes a new instance of
@@ -26,8 +23,6 @@ namespace System.ComponentModel
/// </summary>
public ComplexBindingPropertiesAttribute()
{
- _dataSource = null;
- _dataMember = null;
}
/// <summary>
@@ -38,8 +33,7 @@ namespace System.ComponentModel
/// </summary>
public ComplexBindingPropertiesAttribute(string dataSource)
{
- _dataSource = dataSource;
- _dataMember = null;
+ DataSource = dataSource;
}
/// <summary>
@@ -50,8 +44,8 @@ namespace System.ComponentModel
/// </summary>
public ComplexBindingPropertiesAttribute(string dataSource, string dataMember)
{
- _dataSource = dataSource;
- _dataMember = dataMember;
+ DataSource = dataSource;
+ DataMember = dataMember;
}
/// <summary>
@@ -60,13 +54,7 @@ namespace System.ComponentModel
/// bound to.
/// </para>
/// </summary>
- public string DataSource
- {
- get
- {
- return _dataSource;
- }
- }
+ public string DataSource { get; }
/// <summary>
/// <para>
@@ -74,13 +62,7 @@ namespace System.ComponentModel
/// bound to.
/// </para>
/// </summary>
- public string DataMember
- {
- get
- {
- return _dataMember;
- }
- }
+ public string DataMember { get; }
/// <summary>
/// <para>
@@ -94,8 +76,8 @@ namespace System.ComponentModel
{
ComplexBindingPropertiesAttribute other = obj as ComplexBindingPropertiesAttribute;
return other != null &&
- other.DataSource == _dataSource &&
- other.DataMember == _dataMember;
+ other.DataSource == DataSource &&
+ other.DataMember == DataMember;
}
public override int GetHashCode()
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs
index c45d6e89cf..e7baf6f8e6 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs
@@ -22,7 +22,8 @@ namespace System.ComponentModel
private Hashtable _resourceSets;
private CultureInfo _neutralResourcesCulture;
- public ComponentResourceManager() : base() {
+ public ComponentResourceManager()
+ {
}
public ComponentResourceManager(Type t) : base(t)
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs
index e45c8d47f2..41017d3167 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs
@@ -25,7 +25,7 @@ namespace System.ComponentModel
private ContainerFilterService _filter;
private bool _checkedFilter;
- private object _syncObj = new Object();
+ private readonly object _syncObj = new Object();
~Container()
{
@@ -86,10 +86,7 @@ namespace System.ComponentModel
}
}
- if (site != null)
- {
- site.Container.Remove(component);
- }
+ site?.Container.Remove(component);
ISite newSite = CreateSite(component, name);
_sites[_siteCount++] = newSite;
@@ -232,9 +229,7 @@ namespace System.ComponentModel
{
lock (_syncObj)
{
- if (component == null)
- return;
- ISite site = component.Site;
+ ISite site = component?.Site;
if (site == null || site.Container != this)
return;
if (!preserveSite)
@@ -276,9 +271,7 @@ namespace System.ComponentModel
{
ISite s = _sites[i];
- if (s != null && s.Name != null
- && string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase)
- && s.Component != component)
+ if (s?.Name != null && string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase) && s.Component != component)
{
InheritanceAttribute inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(s.Component)[typeof(InheritanceAttribute)];
if (inheritanceAttribute.InheritanceLevel != InheritanceLevel.InheritedReadOnly)
@@ -292,49 +285,29 @@ namespace System.ComponentModel
private class Site : ISite
{
- private IComponent _component;
- private Container _container;
private String _name;
internal Site(IComponent component, Container container, String name)
{
- _component = component;
- _container = container;
+ Component = component;
+ Container = container;
_name = name;
}
// The component sited by this component site.
- public IComponent Component
- {
- get
- {
- return _component;
- }
- }
+ public IComponent Component { get; }
// The container in which the component is sited.
- public IContainer Container
- {
- get
- {
- return _container;
- }
- }
+ public IContainer Container { get; }
public Object GetService(Type service)
{
- return ((service == typeof(ISite)) ? this : _container.GetService(service));
+ return ((service == typeof(ISite)) ? this : ((Container)Container).GetService(service));
}
// Indicates whether the component is in design mode.
- public bool DesignMode
- {
- get
- {
- return false;
- }
- }
+ public bool DesignMode => false;
// The name of the component.
//
@@ -346,7 +319,7 @@ namespace System.ComponentModel
if (value == null || _name == null || !value.Equals(_name))
{
// UNDONE : This is a breaking change.
- _container.ValidateName(_component, value);
+ ((Container)Container).ValidateName(Component, value);
_name = value;
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CultureInfoConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CultureInfoConverter.cs
index 2898015935..889241c02a 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CultureInfoConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CultureInfoConverter.cs
@@ -4,6 +4,7 @@
using Microsoft.Win32;
using System.Collections;
+using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Globalization;
@@ -25,13 +26,7 @@ namespace System.ComponentModel
/// <summary>
/// Retrieves the "default" name for our culture.
/// </summary>
- private string DefaultCultureString
- {
- get
- {
- return SR.CultureInfoConverterDefaultCultureString;
- }
- }
+ private string DefaultCultureString => SR.CultureInfoConverterDefaultCultureString;
/// <summary>
/// Retrieves the Name for a input CultureInfo.
@@ -111,17 +106,15 @@ namespace System.ComponentModel
//
if (retVal == null)
{
- ICollection values = GetStandardValues(context);
- IEnumerator e = values.GetEnumerator();
- while (e.MoveNext())
+ foreach (CultureInfo info in GetStandardValues(context))
{
- CultureInfo info = (CultureInfo)e.Current;
if (info != null && string.Compare(GetCultureName(info), text, StringComparison.Ordinal) == 0)
{
retVal = info;
break;
}
}
+
}
// Now try to create a new culture info from this value
@@ -140,16 +133,15 @@ namespace System.ComponentModel
if (retVal == null)
{
text = text.ToLower(CultureInfo.CurrentCulture);
- IEnumerator e = _values.GetEnumerator();
- while (e.MoveNext())
+ foreach (CultureInfo info in _values)
{
- CultureInfo info = (CultureInfo)e.Current;
if (info != null && GetCultureName(info).ToLower(CultureInfo.CurrentCulture).StartsWith(text))
{
retVal = info;
break;
}
}
+
}
}
@@ -339,26 +331,12 @@ namespace System.ComponentModel
{
/// Dictionary of CultureInfo.DisplayName, CultureInfo.Name for cultures that have changed DisplayName over releases.
/// This is to workaround an issue with CultureInfoConverter that serializes DisplayName (fixing it would introduce breaking changes).
- private static volatile System.Collections.Generic.Dictionary<string, string> s_cultureInfoNameMap;
-
- public static string GetCultureInfoName(string cultureInfoDisplayName)
- {
- if (s_cultureInfoNameMap == null)
- {
- InitializeCultureInfoMap();
- }
-
- if (s_cultureInfoNameMap.ContainsKey(cultureInfoDisplayName))
- {
- return s_cultureInfoNameMap[cultureInfoDisplayName];
- }
+ private static readonly Dictionary<string, string> s_cultureInfoNameMap = CreateMap();
- return cultureInfoDisplayName;
- }
-
- private static void InitializeCultureInfoMap()
+ private static Dictionary<string,string> CreateMap()
{
- s_cultureInfoNameMap = new System.Collections.Generic.Dictionary<string, string>() {
+ const int Count = 274;
+ var result = new Dictionary<string, string>(Count) {
{"Afrikaans", "af"},
{"Afrikaans (South Africa)", "af-ZA"},
{"Albanian", "sq"},
@@ -634,7 +612,19 @@ namespace System.ComponentModel
{"Yi (PRC)", "ii-CN"},
{"Yoruba (Nigeria)", "yo-NG"}
};
+
+ Debug.Assert(result.Count == Count);
+ return result;
}
+
+ public static string GetCultureInfoName(string cultureInfoDisplayName)
+ {
+ string name;
+ return s_cultureInfoNameMap.TryGetValue(cultureInfoDisplayName, out name) ?
+ name :
+ cultureInfoDisplayName;
+ }
+
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs
index 99e97b8345..50810cc5f7 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs
@@ -60,12 +60,7 @@ namespace System.ComponentModel
/// </summary>
public virtual string GetClassName()
{
- if (_parent != null)
- {
- return _parent.GetClassName();
- }
-
- return null;
+ return _parent?.GetClassName();
}
/// <summary>
@@ -74,12 +69,7 @@ namespace System.ComponentModel
/// </summary>
public virtual string GetComponentName()
{
- if (_parent != null)
- {
- return _parent.GetComponentName();
- }
-
- return null;
+ return _parent?.GetComponentName();
}
/// <summary>
@@ -102,12 +92,7 @@ namespace System.ComponentModel
/// </summary>
public virtual EventDescriptor GetDefaultEvent()
{
- if (_parent != null)
- {
- return _parent.GetDefaultEvent();
- }
-
- return null;
+ return _parent?.GetDefaultEvent();
}
/// <summary>
@@ -116,12 +101,7 @@ namespace System.ComponentModel
/// </summary>
public virtual PropertyDescriptor GetDefaultProperty()
{
- if (_parent != null)
- {
- return _parent.GetDefaultProperty();
- }
-
- return null;
+ return _parent?.GetDefaultProperty();
}
/// <summary>
@@ -130,12 +110,7 @@ namespace System.ComponentModel
/// </summary>
public virtual object GetEditor(Type editorBaseType)
{
- if (_parent != null)
- {
- return _parent.GetEditor(editorBaseType);
- }
-
- return null;
+ return _parent?.GetEditor(editorBaseType);
}
/// <summary>
@@ -215,12 +190,7 @@ namespace System.ComponentModel
/// </summary>
public virtual object GetPropertyOwner(PropertyDescriptor pd)
{
- if (_parent != null)
- {
- return _parent.GetPropertyOwner(pd);
- }
-
- return null;
+ return _parent?.GetPropertyOwner(pd);
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectAttribute.cs
index 8ae81e771c..e7c899cfcd 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectAttribute.cs
@@ -18,24 +18,16 @@ namespace System.ComponentModel
public static readonly DataObjectAttribute Default = NonDataObject;
- private bool _isDataObject;
-
public DataObjectAttribute() : this(true)
{
}
public DataObjectAttribute(bool isDataObject)
{
- _isDataObject = isDataObject;
+ IsDataObject = isDataObject;
}
- public bool IsDataObject
- {
- get
- {
- return _isDataObject;
- }
- }
+ public bool IsDataObject { get; }
/// <internalonly/>
public override bool Equals(object obj)
@@ -52,7 +44,7 @@ namespace System.ComponentModel
/// <internalonly/>
public override int GetHashCode()
{
- return _isDataObject.GetHashCode();
+ return IsDataObject.GetHashCode();
}
/// <internalonly/>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectFieldAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectFieldAttribute.cs
index 18993c5331..290387e367 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectFieldAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectFieldAttribute.cs
@@ -14,11 +14,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Property)]
public sealed class DataObjectFieldAttribute : Attribute
{
- private bool _primaryKey;
- private bool _isIdentity;
- private bool _isNullable;
- private int _length;
-
public DataObjectFieldAttribute(bool primaryKey) : this(primaryKey, false, false, -1)
{
}
@@ -33,43 +28,19 @@ namespace System.ComponentModel
public DataObjectFieldAttribute(bool primaryKey, bool isIdentity, bool isNullable, int length)
{
- _primaryKey = primaryKey;
- _isIdentity = isIdentity;
- _isNullable = isNullable;
- _length = length;
+ PrimaryKey = primaryKey;
+ IsIdentity = isIdentity;
+ IsNullable = isNullable;
+ Length = length;
}
- public bool IsIdentity
- {
- get
- {
- return _isIdentity;
- }
- }
+ public bool IsIdentity { get; }
- public bool IsNullable
- {
- get
- {
- return _isNullable;
- }
- }
+ public bool IsNullable { get; }
- public int Length
- {
- get
- {
- return _length;
- }
- }
+ public int Length { get; }
- public bool PrimaryKey
- {
- get
- {
- return _primaryKey;
- }
- }
+ public bool PrimaryKey { get; }
public override bool Equals(object obj)
{
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectMethodAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectMethodAttribute.cs
index a80b59632d..2fe8d8dbe2 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectMethodAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DataObjectMethodAttribute.cs
@@ -12,34 +12,19 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Method)]
public sealed class DataObjectMethodAttribute : Attribute
{
- private bool _isDefault;
- private DataObjectMethodType _methodType;
-
public DataObjectMethodAttribute(DataObjectMethodType methodType) : this(methodType, false)
{
}
public DataObjectMethodAttribute(DataObjectMethodType methodType, bool isDefault)
{
- _methodType = methodType;
- _isDefault = isDefault;
+ MethodType = methodType;
+ IsDefault = isDefault;
}
- public bool IsDefault
- {
- get
- {
- return _isDefault;
- }
- }
+ public bool IsDefault { get; }
- public DataObjectMethodType MethodType
- {
- get
- {
- return _methodType;
- }
- }
+ public DataObjectMethodType MethodType { get; }
/// <internalonly/>
public override bool Equals(object obj)
@@ -56,7 +41,7 @@ namespace System.ComponentModel
/// <internalonly/>
public override int GetHashCode()
{
- return ((int)_methodType).GetHashCode() ^ _isDefault.GetHashCode();
+ return ((int)MethodType).GetHashCode() ^ IsDefault.GetHashCode();
}
/// <internalonly/>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DecimalConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DecimalConverter.cs
index 8687f0cdf3..5d1aecb30f 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DecimalConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DecimalConverter.cs
@@ -19,24 +19,12 @@ namespace System.ComponentModel
/// <summary>
/// Determines whether this editor will attempt to convert hex (0x or #) strings
/// </summary>
- internal override bool AllowHex
- {
- get
- {
- return false;
- }
- }
+ internal override bool AllowHex => false;
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(Decimal);
- }
- }
+ internal override Type TargetType => typeof(decimal);
/// <summary>
/// <para>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultBindingPropertyAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultBindingPropertyAttribute.cs
index 7f953d2dad..0923dd97a8 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultBindingPropertyAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultBindingPropertyAttribute.cs
@@ -14,8 +14,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Class)]
public sealed class DefaultBindingPropertyAttribute : Attribute
{
- private readonly string _name;
-
/// <summary>
/// <para>
/// Initializes a new instance of
@@ -24,7 +22,6 @@ namespace System.ComponentModel
/// </summary>
public DefaultBindingPropertyAttribute()
{
- _name = null;
}
/// <summary>
@@ -35,7 +32,7 @@ namespace System.ComponentModel
/// </summary>
public DefaultBindingPropertyAttribute(string name)
{
- _name = name;
+ Name = name;
}
/// <summary>
@@ -44,13 +41,7 @@ namespace System.ComponentModel
/// bound to.
/// </para>
/// </summary>
- public string Name
- {
- get
- {
- return _name;
- }
- }
+ public string Name { get; }
/// <summary>
/// <para>
@@ -63,7 +54,7 @@ namespace System.ComponentModel
public override bool Equals(object obj)
{
DefaultBindingPropertyAttribute other = obj as DefaultBindingPropertyAttribute;
- return other != null && other.Name == _name;
+ return other != null && other.Name == Name;
}
public override int GetHashCode()
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultEventAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultEventAttribute.cs
index 48bbadaab8..99aa66e200 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultEventAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultEventAttribute.cs
@@ -12,11 +12,6 @@ namespace System.ComponentModel
public sealed class DefaultEventAttribute : Attribute
{
/// <summary>
- /// This is the default event name.
- /// </summary>
- private readonly string _name;
-
- /// <summary>
/// <para>
/// Initializes
/// a new instance of the <see cref='System.ComponentModel.DefaultEventAttribute'/> class.
@@ -24,7 +19,7 @@ namespace System.ComponentModel
/// </summary>
public DefaultEventAttribute(string name)
{
- _name = name;
+ Name = name;
}
/// <summary>
@@ -33,13 +28,7 @@ namespace System.ComponentModel
/// the component this attribute is bound to.
/// </para>
/// </summary>
- public string Name
- {
- get
- {
- return _name;
- }
- }
+ public string Name { get; }
/// <summary>
/// <para>
@@ -53,7 +42,7 @@ namespace System.ComponentModel
public override bool Equals(object obj)
{
DefaultEventAttribute other = obj as DefaultEventAttribute;
- return (other != null) && other.Name == _name;
+ return (other != null) && other.Name == Name;
}
public override int GetHashCode()
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultPropertyAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultPropertyAttribute.cs
index d9d8237266..6464317e8d 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultPropertyAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DefaultPropertyAttribute.cs
@@ -11,11 +11,6 @@ namespace System.ComponentModel
public sealed class DefaultPropertyAttribute : Attribute
{
/// <summary>
- /// This is the default event name.
- /// </summary>
- private readonly string _name;
-
- /// <summary>
/// <para>
/// Initializes a new instance of
/// the <see cref='System.ComponentModel.DefaultPropertyAttribute'/> class.
@@ -23,7 +18,7 @@ namespace System.ComponentModel
/// </summary>
public DefaultPropertyAttribute(string name)
{
- _name = name;
+ Name = name;
}
/// <summary>
@@ -32,13 +27,7 @@ namespace System.ComponentModel
/// bound to.
/// </para>
/// </summary>
- public string Name
- {
- get
- {
- return _name;
- }
- }
+ public string Name { get; }
/// <summary>
/// <para>
@@ -51,7 +40,7 @@ namespace System.ComponentModel
public override bool Equals(object obj)
{
DefaultPropertyAttribute other = obj as DefaultPropertyAttribute;
- return (other != null) && other.Name == _name;
+ return (other != null) && other.Name == Name;
}
public override int GetHashCode()
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs
index dc47fbe001..e10692bc73 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs
@@ -28,13 +28,7 @@ namespace System.ComponentModel
/// <summary>
///
/// </summary>
- internal TypeDescriptionProvider Provider
- {
- get
- {
- return TypeDescriptor.GetProviderRecursive(_type);
- }
- }
+ internal TypeDescriptionProvider Provider => TypeDescriptor.GetProviderRecursive(_type);
/// <summary>
/// This method is used to create an instance that can substitute for another
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ActiveDocumentEvent.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ActiveDocumentEvent.cs
index f510154e14..968d914ee6 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ActiveDocumentEvent.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ActiveDocumentEvent.cs
@@ -17,23 +17,13 @@ namespace System.ComponentModel.Design
public class ActiveDesignerEventArgs : EventArgs
{
/// <summary>
- /// The document that is losing activation.
- /// </summary>
- private readonly IDesignerHost _oldDesigner;
-
- /// <summary>
- /// The document that is gaining activation.
- /// </summary>
- private readonly IDesignerHost _newDesigner;
-
- /// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.Design.ActiveDesignerEventArgs'/>
/// class.</para>
/// </summary>
public ActiveDesignerEventArgs(IDesignerHost oldDesigner, IDesignerHost newDesigner)
{
- _oldDesigner = oldDesigner;
- _newDesigner = newDesigner;
+ OldDesigner = oldDesigner;
+ NewDesigner = newDesigner;
}
/// <summary>
@@ -42,13 +32,7 @@ namespace System.ComponentModel.Design
/// sets the document that is losing activation.
/// </para>
/// </summary>
- public IDesignerHost OldDesigner
- {
- get
- {
- return _oldDesigner;
- }
- }
+ public IDesignerHost OldDesigner { get; }
/// <summary>
/// <para>
@@ -56,12 +40,6 @@ namespace System.ComponentModel.Design
/// sets the document that is gaining activation.
/// </para>
/// </summary>
- public IDesignerHost NewDesigner
- {
- get
- {
- return _newDesigner;
- }
- }
+ public IDesignerHost NewDesigner { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CheckoutException.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CheckoutException.cs
index 58ebb24e50..0b2ba36106 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CheckoutException.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CheckoutException.cs
@@ -29,7 +29,7 @@ namespace System.ComponentModel.Design
/// canceled. This field is read-only.
/// </para>
/// </summary>
- public readonly static CheckoutException Canceled = new CheckoutException(SR.CHECKOUTCanceled, E_ABORT);
+ public static readonly CheckoutException Canceled = new CheckoutException(SR.CHECKOUTCanceled, E_ABORT);
/// <summary>
/// <para>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CommandID.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CommandID.cs
index d485afa738..1e452eac3e 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CommandID.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/CommandID.cs
@@ -19,9 +19,6 @@ namespace System.ComponentModel.Design
/// </summary>
public class CommandID
{
- private readonly Guid _menuGroup;
- private readonly int _commandID;
-
/// <summary>
/// <para>
/// Initializes a new instance of the <see cref='System.ComponentModel.Design.CommandID'/>
@@ -31,8 +28,8 @@ namespace System.ComponentModel.Design
/// </summary>
public CommandID(Guid menuGroup, int commandID)
{
- _menuGroup = menuGroup;
- _commandID = commandID;
+ Guid = menuGroup;
+ ID = commandID;
}
/// <summary>
@@ -40,13 +37,7 @@ namespace System.ComponentModel.Design
/// Gets or sets the numeric command ID.
/// </para>
/// </summary>
- public virtual int ID
- {
- get
- {
- return _commandID;
- }
- }
+ public virtual int ID { get; }
/// <summary>
/// <para>
@@ -60,7 +51,7 @@ namespace System.ComponentModel.Design
return false;
}
CommandID cid = (CommandID)obj;
- return cid._menuGroup.Equals(_menuGroup) && cid._commandID == _commandID;
+ return cid.Guid.Equals(Guid) && cid.ID == ID;
}
/// <summary>
@@ -68,7 +59,7 @@ namespace System.ComponentModel.Design
/// </summary>
public override int GetHashCode()
{
- return _menuGroup.GetHashCode() << 2 | _commandID;
+ return Guid.GetHashCode() << 2 | ID;
}
/// <summary>
@@ -79,13 +70,7 @@ namespace System.ComponentModel.Design
/// represents belongs to.
/// </para>
/// </summary>
- public virtual Guid Guid
- {
- get
- {
- return _menuGroup;
- }
- }
+ public virtual Guid Guid { get; }
/// <summary>
/// <para>
@@ -94,7 +79,7 @@ namespace System.ComponentModel.Design
/// </summary>
public override string ToString()
{
- return _menuGroup.ToString() + " : " + _commandID.ToString(CultureInfo.CurrentCulture);
+ return Guid.ToString() + " : " + ID.ToString(CultureInfo.CurrentCulture);
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangedEvent.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangedEvent.cs
index dbe9ee3ff0..dcaaed9c21 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangedEvent.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangedEvent.cs
@@ -15,72 +15,43 @@ namespace System.ComponentModel.Design
/// </summary>
public sealed class ComponentChangedEventArgs : EventArgs
{
- private object _component;
- private MemberDescriptor _member;
- private object _oldValue;
- private object _newValue;
-
/// <summary>
/// <para>
/// Gets or sets the component that is the cause of this event.
/// </para>
/// </summary>
- public object Component
- {
- get
- {
- return _component;
- }
- }
+ public object Component { get; }
/// <summary>
/// <para>
/// Gets or sets the member that is about to change.
/// </para>
/// </summary>
- public MemberDescriptor Member
- {
- get
- {
- return _member;
- }
- }
+ public MemberDescriptor Member { get; }
/// <summary>
/// <para>
/// Gets or sets the new value of the changed member.
/// </para>
/// </summary>
- public object NewValue
- {
- get
- {
- return _newValue;
- }
- }
+ public object NewValue { get; }
/// <summary>
/// <para>
/// Gets or sets the old value of the changed member.
/// </para>
/// </summary>
- public object OldValue
- {
- get
- {
- return _oldValue;
- }
- }
+ public object OldValue { get; }
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.Design.ComponentChangedEventArgs'/> class.</para>
/// </summary>
public ComponentChangedEventArgs(object component, MemberDescriptor member, object oldValue, object newValue)
{
- _component = component;
- _member = member;
- _oldValue = oldValue;
- _newValue = newValue;
+ Component = component;
+ Member = member;
+ OldValue = oldValue;
+ NewValue = newValue;
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangingEvent.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangingEvent.cs
index c2672b9cf3..87192175c2 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangingEvent.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentChangingEvent.cs
@@ -15,34 +15,19 @@ namespace System.ComponentModel.Design
/// </summary>
public sealed class ComponentChangingEventArgs : EventArgs
{
- private object _component;
- private MemberDescriptor _member;
-
/// <summary>
/// <para>
/// Gets or sets the component that is being changed or that is the parent container of the member being changed.
/// </para>
/// </summary>
- public object Component
- {
- get
- {
- return _component;
- }
- }
+ public object Component { get; }
/// <summary>
/// <para>
/// Gets or sets the member of the component that is about to be changed.
/// </para>
/// </summary>
- public MemberDescriptor Member
- {
- get
- {
- return _member;
- }
- }
+ public MemberDescriptor Member { get; }
/// <summary>
/// <para>
@@ -51,8 +36,8 @@ namespace System.ComponentModel.Design
/// </summary>
public ComponentChangingEventArgs(object component, MemberDescriptor member)
{
- _component = component;
- _member = member;
+ Component = component;
+ Member = member;
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentEvent.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentEvent.cs
index a188b58051..1c0139e1a8 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentEvent.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentEvent.cs
@@ -16,20 +16,12 @@ namespace System.ComponentModel.Design
/// </summary>
public class ComponentEventArgs : EventArgs
{
- private IComponent _component;
-
/// <summary>
/// <para>
/// Gets or sets the component associated with the event.
/// </para>
/// </summary>
- public virtual IComponent Component
- {
- get
- {
- return _component;
- }
- }
+ public virtual IComponent Component { get; }
/// <summary>
/// <para>
@@ -38,7 +30,7 @@ namespace System.ComponentModel.Design
/// </summary>
public ComponentEventArgs(IComponent component)
{
- _component = component;
+ Component = component;
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentRenameEvent.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentRenameEvent.cs
index b7d2773343..436accfd53 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentRenameEvent.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ComponentRenameEvent.cs
@@ -15,22 +15,12 @@ namespace System.ComponentModel.Design
/// </summary>
public class ComponentRenameEventArgs : EventArgs
{
- private object _component;
- private string _oldName;
- private string _newName;
-
/// <summary>
/// <para>
/// Gets or sets the component that is being renamed.
/// </para>
/// </summary>
- public object Component
- {
- get
- {
- return _component;
- }
- }
+ public object Component { get; }
/// <summary>
/// <para>
@@ -38,13 +28,7 @@ namespace System.ComponentModel.Design
/// sets the name of the component before the rename.
/// </para>
/// </summary>
- public virtual string OldName
- {
- get
- {
- return _oldName;
- }
- }
+ public virtual string OldName { get; }
/// <summary>
/// <para>
@@ -52,13 +36,7 @@ namespace System.ComponentModel.Design
/// sets the current name of the component.
/// </para>
/// </summary>
- public virtual string NewName
- {
- get
- {
- return _newName;
- }
- }
+ public virtual string NewName { get; }
/// <summary>
/// <para>
@@ -68,9 +46,9 @@ namespace System.ComponentModel.Design
/// </summary>
public ComponentRenameEventArgs(object component, string oldName, string newName)
{
- _oldName = oldName;
- _newName = newName;
- _component = component;
+ OldName = oldName;
+ NewName = newName;
+ Component = component;
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs
index 614e2e07a6..3d77209844 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs
@@ -4,11 +4,13 @@
using System;
using System.Collections;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Security.Permissions;
+using Enumerable = System.Linq.Enumerable;
namespace System.ComponentModel.Design
{
@@ -18,21 +20,14 @@ namespace System.ComponentModel.Design
public abstract class DesignerOptionService : IDesignerOptionService
{
private DesignerOptionCollection _options;
-
+ private static readonly char[] s_slash = {'\\'};
/// <summary>
/// Returns the options collection for this service. There is
/// always a global options collection that contains child collections.
/// </summary>
public DesignerOptionCollection Options
{
- get
- {
- if (_options == null)
- {
- _options = new DesignerOptionCollection(this, null, string.Empty, null);
- }
- return _options;
- }
+ get { return _options ?? (_options = new DesignerOptionCollection(this, null, string.Empty, null)); }
}
/// <summary>
@@ -80,7 +75,7 @@ namespace System.ComponentModel.Design
throw new ArgumentNullException(nameof(valueName));
}
- string[] optionNames = pageName.Split(new char[] { '\\' });
+ string[] optionNames = pageName.Split(s_slash);
DesignerOptionCollection options = Options;
foreach (string optionName in optionNames)
@@ -119,11 +114,7 @@ namespace System.ComponentModel.Design
object IDesignerOptionService.GetOptionValue(string pageName, string valueName)
{
PropertyDescriptor optionProp = GetOptionProperty(pageName, valueName);
- if (optionProp != null)
- {
- return optionProp.GetValue(null);
- }
- return null;
+ return optionProp?.GetValue(null);
}
/// <internalonly/>
@@ -133,10 +124,7 @@ namespace System.ComponentModel.Design
void IDesignerOptionService.SetOptionValue(string pageName, string valueName, object value)
{
PropertyDescriptor optionProp = GetOptionProperty(pageName, valueName);
- if (optionProp != null)
- {
- optionProp.SetValue(null, value);
- }
+ optionProp?.SetValue(null, value);
}
/// <summary>
@@ -150,8 +138,6 @@ namespace System.ComponentModel.Design
public sealed class DesignerOptionCollection : IList
{
private DesignerOptionService _service;
- private DesignerOptionCollection _parent;
- private string _name;
private object _value;
private ArrayList _children;
private PropertyDescriptorCollection _properties;
@@ -162,17 +148,17 @@ namespace System.ComponentModel.Design
internal DesignerOptionCollection(DesignerOptionService service, DesignerOptionCollection parent, string name, object value)
{
_service = service;
- _parent = parent;
- _name = name;
+ Parent = parent;
+ Name = name;
_value = value;
- if (_parent != null)
+ if (Parent != null)
{
- if (_parent._children == null)
+ if (Parent._children == null)
{
- _parent._children = new ArrayList(1);
+ Parent._children = new ArrayList(1);
}
- _parent._children.Add(this);
+ Parent._children.Add(this);
}
}
@@ -192,24 +178,12 @@ namespace System.ComponentModel.Design
/// The name of this collection. Names are programmatic names and are not
/// localized. A name search is case insensitive.
/// </summary>
- public string Name
- {
- get
- {
- return _name;
- }
- }
+ public string Name { get; }
/// <summary>
/// Returns the parent collection object, or null if there is no parent.
/// </summary>
- public DesignerOptionCollection Parent
- {
- get
- {
- return _parent;
- }
- }
+ public DesignerOptionCollection Parent { get; }
/// <summary>
/// The collection of properties that this OptionCollection, along with all of
@@ -377,49 +351,25 @@ namespace System.ComponentModel.Design
/// <summary>
/// Private ICollection implementation.
/// </summary>
- bool ICollection.IsSynchronized
- {
- get
- {
- return false;
- }
- }
+ bool ICollection.IsSynchronized => false;
/// <internalonly/>
/// <summary>
/// Private ICollection implementation.
/// </summary>
- object ICollection.SyncRoot
- {
- get
- {
- return this;
- }
- }
+ object ICollection.SyncRoot => this;
/// <internalonly/>
/// <summary>
/// Private IList implementation.
/// </summary>
- bool IList.IsFixedSize
- {
- get
- {
- return true;
- }
- }
+ bool IList.IsFixedSize => true;
/// <internalonly/>
/// <summary>
/// Private IList implementation.
/// </summary>
- bool IList.IsReadOnly
- {
- get
- {
- return true;
- }
- }
+ bool IList.IsReadOnly => true;
/// <internalonly/>
/// <summary>
@@ -518,37 +468,13 @@ namespace System.ComponentModel.Design
_target = target;
}
- public override AttributeCollection Attributes
- {
- get
- {
- return _property.Attributes;
- }
- }
+ public override AttributeCollection Attributes => _property.Attributes;
- public override Type ComponentType
- {
- get
- {
- return _property.ComponentType;
- }
- }
+ public override Type ComponentType => _property.ComponentType;
- public override bool IsReadOnly
- {
- get
- {
- return _property.IsReadOnly;
- }
- }
+ public override bool IsReadOnly => _property.IsReadOnly;
- public override Type PropertyType
- {
- get
- {
- return _property.PropertyType;
- }
- }
+ public override Type PropertyType => _property.PropertyType;
public override bool CanResetValue(object component)
{
@@ -626,29 +552,11 @@ namespace System.ComponentModel.Design
_option = option;
}
- public override Type ComponentType
- {
- get
- {
- return _option.GetType();
- }
- }
+ public override Type ComponentType => _option.GetType();
- public override bool IsReadOnly
- {
- get
- {
- return true;
- }
- }
+ public override bool IsReadOnly => true;
- public override Type PropertyType
- {
- get
- {
- return _option.GetType();
- }
- }
+ public override Type PropertyType => _option.GetType();
public override bool CanResetValue(object component)
{
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransaction.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransaction.cs
index 6914cbe4f6..22b389aa7c 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransaction.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransaction.cs
@@ -14,10 +14,7 @@ namespace System.ComponentModel.Design
/// </summary>
public abstract class DesignerTransaction : IDisposable
{
- private bool _committed = false;
- private bool _canceled = false;
- private bool _suppressedFinalization = false;
- private string _desc;
+ private bool _suppressedFinalization;
/// <summary>
/// <para>[To be supplied.]</para>
@@ -32,51 +29,33 @@ namespace System.ComponentModel.Design
/// </summary>
protected DesignerTransaction(string description)
{
- _desc = description;
+ Description = description;
}
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public bool Canceled
- {
- get
- {
- return _canceled;
- }
- }
+ public bool Canceled { get; private set; }
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public bool Committed
- {
- get
- {
- return _committed;
- }
- }
+ public bool Committed { get; private set; }
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public string Description
- {
- get
- {
- return _desc;
- }
- }
+ public string Description { get; }
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
public void Cancel()
{
- if (!_canceled && !_committed)
+ if (!Canceled && !Committed)
{
- _canceled = true;
+ Canceled = true;
GC.SuppressFinalize(this);
_suppressedFinalization = true;
OnCancel();
@@ -92,9 +71,9 @@ namespace System.ComponentModel.Design
/// </summary>
public void Commit()
{
- if (!_committed && !_canceled)
+ if (!Committed && !Canceled)
{
- _committed = true;
+ Committed = true;
GC.SuppressFinalize(this);
_suppressedFinalization = true;
OnCommit();
@@ -144,7 +123,7 @@ namespace System.ComponentModel.Design
protected virtual void Dispose(bool disposing)
{
System.Diagnostics.Debug.Assert(disposing, "Designer transaction garbage collected, unable to cancel, please Cancel, Close, or Dispose your transaction.");
- System.Diagnostics.Debug.Assert(disposing || _canceled || _committed, "Disposing DesignerTransaction that has not been comitted or canceled; forcing Cancel");
+ System.Diagnostics.Debug.Assert(disposing || Canceled || Committed, "Disposing DesignerTransaction that has not been comitted or canceled; forcing Cancel");
Cancel();
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransactionCloseEvent.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransactionCloseEvent.cs
index 89e405ea8d..1077dda6ae 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransactionCloseEvent.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerTransactionCloseEvent.cs
@@ -16,9 +16,6 @@ namespace System.ComponentModel.Design
/// </summary>
public class DesignerTransactionCloseEventArgs : EventArgs
{
- private bool _commit;
- private bool _lastTransaction;
-
/// <summary>
/// Creates a new event args. Commit is true if the transaction is committed. This
/// defaults the LastTransaction property to true.
@@ -34,30 +31,18 @@ namespace System.ComponentModel.Design
/// </summary>
public DesignerTransactionCloseEventArgs(bool commit, bool lastTransaction)
{
- _commit = commit;
- _lastTransaction = lastTransaction;
+ TransactionCommitted = commit;
+ LastTransaction = lastTransaction;
}
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public bool TransactionCommitted
- {
- get
- {
- return _commit;
- }
- }
+ public bool TransactionCommitted { get; }
/// <summary>
/// Returns true if this is the last transaction to close.
/// </summary>
- public bool LastTransaction
- {
- get
- {
- return _lastTransaction;
- }
- }
+ public bool LastTransaction { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContext.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContext.cs
index 44f8c71360..4aa960fcde 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContext.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContext.cs
@@ -30,13 +30,8 @@ namespace System.ComponentModel.Design
/// Gets or sets the license usage mode.
/// </para>
/// </summary>
- public override LicenseUsageMode UsageMode
- {
- get
- {
- return LicenseUsageMode.Designtime;
- }
- }
+ public override LicenseUsageMode UsageMode => LicenseUsageMode.Designtime;
+
/// <summary>
/// <para>
/// Gets a saved license key.
@@ -175,8 +170,8 @@ namespace System.ComponentModel.Design
if (licenseFile != null)
{
- Debug.WriteLineIf(s_runtimeLicenseContextSwitch.TraceVerbose, "licenseFile: " + licenseFile.ToString());
- Debug.WriteLineIf(s_runtimeLicenseContextSwitch.TraceVerbose, "opening licenses file over URI " + licenseFile.ToString());
+ Debug.WriteLineIf(s_runtimeLicenseContextSwitch.TraceVerbose, $"licenseFile: {licenseFile.ToString()}");
+ Debug.WriteLineIf(s_runtimeLicenseContextSwitch.TraceVerbose, $"opening licenses file over URI {licenseFile.ToString()}");
Stream s = OpenRead(licenseFile);
if (s != null)
{
@@ -187,7 +182,7 @@ namespace System.ComponentModel.Design
}
}
}
- Debug.WriteLineIf(s_runtimeLicenseContextSwitch.TraceVerbose, "returning : " + (string)savedLicenseKeys[type.AssemblyQualifiedName]);
+ Debug.WriteLineIf(s_runtimeLicenseContextSwitch.TraceVerbose, $"returning : {(string)savedLicenseKeys[type.AssemblyQualifiedName]}");
return (string)savedLicenseKeys[type.AssemblyQualifiedName];
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentCollection.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentCollection.cs
index c031e7c152..c14fcfb5ff 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentCollection.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentCollection.cs
@@ -56,25 +56,13 @@ namespace System.ComponentModel.Design
/// sets the number
/// of documents in the collection.</para>
/// </summary>
- public int Count
- {
- get
- {
- return _designers.Count;
- }
- }
+ public int Count => _designers.Count;
/// <summary>
/// <para> Gets
/// or sets the document at the specified index.</para>
/// </summary>
- public virtual IDesignerHost this[int index]
- {
- get
- {
- return (IDesignerHost)_designers[index];
- }
- }
+ public virtual IDesignerHost this[int index] => (IDesignerHost)_designers[index];
/// <summary>
/// <para>Creates and retrieves a new enumerator for this collection.</para>
@@ -85,31 +73,13 @@ namespace System.ComponentModel.Design
}
/// <internalonly/>
- int ICollection.Count
- {
- get
- {
- return Count;
- }
- }
+ int ICollection.Count => Count;
/// <internalonly/>
- bool ICollection.IsSynchronized
- {
- get
- {
- return false;
- }
- }
+ bool ICollection.IsSynchronized => false;
/// <internalonly/>
- object ICollection.SyncRoot
- {
- get
- {
- return null;
- }
- }
+ object ICollection.SyncRoot => null;
/// <internalonly/>
void ICollection.CopyTo(Array array, int index)
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentEventArgs.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentEventArgs.cs
index 0863758bd8..a118e6c131 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentEventArgs.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DocumentEventArgs.cs
@@ -16,8 +16,6 @@ namespace System.ComponentModel.Design
/// </summary>
public class DesignerEventArgs : EventArgs
{
- private readonly IDesignerHost _host;
-
/// <summary>
/// <para>
/// Initializes a new instance of the System.ComponentModel.Design.DesignerEventArgs
@@ -26,7 +24,7 @@ namespace System.ComponentModel.Design
/// </summary>
public DesignerEventArgs(IDesignerHost host)
{
- _host = host;
+ Designer = host;
}
/// <summary>
@@ -35,13 +33,7 @@ namespace System.ComponentModel.Design
/// sets the host of the document.
/// </para>
/// </summary>
- public IDesignerHost Designer
- {
- get
- {
- return _host;
- }
- }
+ public IDesignerHost Designer { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/HelpKeywordAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/HelpKeywordAttribute.cs
index 3ce6d6f1ba..ea8e88d70c 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/HelpKeywordAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/HelpKeywordAttribute.cs
@@ -52,8 +52,6 @@ namespace System.ComponentModel.Design
/// </summary>
public static readonly HelpKeywordAttribute Default = new HelpKeywordAttribute();
- private string _contextKeyword;
-
/// <summary>
/// Default constructor, which creates an attribute with a null HelpKeyword.
/// </summary>
@@ -70,7 +68,7 @@ namespace System.ComponentModel.Design
{
throw new ArgumentNullException(nameof(keyword));
}
- _contextKeyword = keyword;
+ HelpKeyword = keyword;
}
/// <summary>
@@ -82,19 +80,13 @@ namespace System.ComponentModel.Design
{
throw new ArgumentNullException(nameof(t));
}
- _contextKeyword = t.FullName;
+ HelpKeyword = t.FullName;
}
/// <summary>
/// Retrieves the HelpKeyword this attribute supplies.
/// </summary>
- public string HelpKeyword
- {
- get
- {
- return _contextKeyword;
- }
- }
+ public string HelpKeyword { get; }
/// <summary>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/InheritanceAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/InheritanceAttribute.cs
index 36a78c11df..abcb42de0c 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/InheritanceAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/InheritanceAttribute.cs
@@ -13,8 +13,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event)]
public sealed class InheritanceAttribute : Attribute
{
- private readonly InheritanceLevel _inheritanceLevel;
-
/// <summary>
/// <para>
/// Specifies that the component is inherited. This field is
@@ -54,7 +52,7 @@ namespace System.ComponentModel
/// </summary>
public InheritanceAttribute()
{
- _inheritanceLevel = Default._inheritanceLevel;
+ InheritanceLevel = Default.InheritanceLevel;
}
/// <summary>
@@ -64,7 +62,7 @@ namespace System.ComponentModel
/// </summary>
public InheritanceAttribute(InheritanceLevel inheritanceLevel)
{
- _inheritanceLevel = inheritanceLevel;
+ InheritanceLevel = inheritanceLevel;
}
/// <summary>
@@ -73,13 +71,7 @@ namespace System.ComponentModel
/// the current inheritance level stored in this attribute.
/// </para>
/// </summary>
- public InheritanceLevel InheritanceLevel
- {
- get
- {
- return _inheritanceLevel;
- }
- }
+ public InheritanceLevel InheritanceLevel { get; }
/// <summary>
/// <para>
@@ -99,7 +91,7 @@ namespace System.ComponentModel
}
InheritanceLevel valueLevel = ((InheritanceAttribute)value).InheritanceLevel;
- return (valueLevel == _inheritanceLevel);
+ return (valueLevel == InheritanceLevel);
}
/// <summary>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/MenuCommand.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/MenuCommand.cs
index be43aa5e20..b66f4ca8a3 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/MenuCommand.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/MenuCommand.cs
@@ -23,9 +23,7 @@ namespace System.ComponentModel.Design
// Events that we suface or call on
//
private EventHandler _execHandler;
- private EventHandler _statusHandler;
- private CommandID _commandID;
private int _status;
private IDictionary _properties;
@@ -61,7 +59,7 @@ namespace System.ComponentModel.Design
public MenuCommand(EventHandler handler, CommandID command)
{
_execHandler = handler;
- _commandID = command;
+ CommandID = command;
_status = SUPPORTED | ENABLED;
}
@@ -120,20 +118,7 @@ namespace System.ComponentModel.Design
/// <summary>
/// </summary>
- public virtual IDictionary Properties
- {
- get
- {
- if (_properties == null)
- {
- _properties = new HybridDictionary();
- }
-
- return _properties;
- }
- }
-
-
+ public virtual IDictionary Properties => _properties ?? (_properties = new HybridDictionary());
/// <summary>
@@ -173,28 +158,13 @@ namespace System.ComponentModel.Design
/// Occurs when the menu command changes.
/// </para>
/// </summary>
- public event EventHandler CommandChanged
- {
- add
- {
- _statusHandler += value;
- }
- remove
- {
- _statusHandler -= value;
- }
- }
+ public event EventHandler CommandChanged;
+
/// <summary>
/// <para>Gets the <see cref='System.ComponentModel.Design.CommandID'/> associated with this menu command.</para>
/// </summary>
- public virtual CommandID CommandID
- {
- get
- {
- return _commandID;
- }
- }
+ public virtual CommandID CommandID { get; }
/// <summary>
/// <para>
@@ -235,13 +205,7 @@ namespace System.ComponentModel.Design
/// Gets the OLE command status code for this menu item.
/// </para>
/// </summary>
- public virtual int OleStatus
- {
- get
- {
- return _status;
- }
- }
+ public virtual int OleStatus => _status;
/// <summary>
/// <para>Provides notification and is called in response to
@@ -250,10 +214,7 @@ namespace System.ComponentModel.Design
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")] // Safe: FullTrust LinkDemand to instantiate an object of this class.
protected virtual void OnCommandChanged(EventArgs e)
{
- if (_statusHandler != null)
- {
- _statusHandler(this, e);
- }
+ CommandChanged?.Invoke(this, e);
}
/// <summary>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/PropertyTabAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/PropertyTabAttribute.cs
index d9b3bf7df8..c3f70c3c06 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/PropertyTabAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/PropertyTabAttribute.cs
@@ -17,7 +17,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.All)]
public class PropertyTabAttribute : Attribute
{
- private PropertyTabScope[] _tabScopes;
private Type[] _tabClasses;
private string[] _tabClassNames;
@@ -29,8 +28,8 @@ namespace System.ComponentModel
/// </summary>
public PropertyTabAttribute()
{
- _tabScopes = new PropertyTabScope[0];
- _tabClassNames = new string[0];
+ TabScopes = Array.Empty<PropertyTabScope>();
+ _tabClassNames = Array.Empty<string>();
}
/// <summary>
@@ -66,7 +65,7 @@ namespace System.ComponentModel
{
throw new ArgumentException(SR.Format(SR.PropertyTabAttributeBadPropertyTabScope), nameof(tabScope));
}
- _tabScopes = new PropertyTabScope[] { tabScope };
+ TabScopes = new PropertyTabScope[] { tabScope };
}
@@ -83,7 +82,7 @@ namespace System.ComponentModel
{
throw new ArgumentException(SR.Format(SR.PropertyTabAttributeBadPropertyTabScope), nameof(tabScope));
}
- _tabScopes = new PropertyTabScope[] { tabScope };
+ TabScopes = new PropertyTabScope[] { tabScope };
}
/// <summary>
@@ -138,31 +137,13 @@ namespace System.ComponentModel
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- protected string[] TabClassNames
- {
- get
- {
- if (_tabClassNames != null)
- {
- return (string[])_tabClassNames.Clone();
- }
- else
- {
- return null;
- }
- }
- }
+ protected string[] TabClassNames => (string[]) _tabClassNames?.Clone();
/// <summary>
/// <para>Gets the scopes of tabs for this System.ComponentModel.Design.PropertyTabAttribute, from System.ComponentModel.Design.PropertyTabScope.</para>
/// </summary>
- public PropertyTabScope[] TabScopes
- {
- get
- {
- return _tabScopes;
- }
- }
+ public PropertyTabScope[] TabScopes { get; private set; }
+
/// <internalonly/>
public override bool Equals(object other)
{
@@ -262,15 +243,15 @@ namespace System.ComponentModel
throw new ArgumentException(SR.PropertyTabAttributeBadPropertyTabScope);
}
}
- _tabScopes = (PropertyTabScope[])tabScopes.Clone();
+ TabScopes = (PropertyTabScope[])tabScopes.Clone();
}
else
{
- _tabScopes = new PropertyTabScope[tabClasses.Length];
+ TabScopes = new PropertyTabScope[tabClasses.Length];
for (int i = 0; i < TabScopes.Length; i++)
{
- _tabScopes[i] = PropertyTabScope.Component;
+ TabScopes[i] = PropertyTabScope.Component;
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DefaultSerializationProviderAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DefaultSerializationProviderAttribute.cs
index ed05e05225..a9f957d089 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DefaultSerializationProviderAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DefaultSerializationProviderAttribute.cs
@@ -16,8 +16,6 @@ namespace System.ComponentModel.Design.Serialization
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class DefaultSerializationProviderAttribute : Attribute
{
- private string _providerTypeName;
-
/// <summary>
/// Creates a new DefaultSerializationProviderAttribute
/// </summary>
@@ -28,7 +26,7 @@ namespace System.ComponentModel.Design.Serialization
throw new ArgumentNullException(nameof(providerType));
}
- _providerTypeName = providerType.AssemblyQualifiedName;
+ ProviderTypeName = providerType.AssemblyQualifiedName;
}
/// <summary>
@@ -41,19 +39,13 @@ namespace System.ComponentModel.Design.Serialization
throw new ArgumentNullException(nameof(providerTypeName));
}
- _providerTypeName = providerTypeName;
+ ProviderTypeName = providerTypeName;
}
/// <summary>
/// Returns the type name for the default serialization provider.
/// </summary>
- public string ProviderTypeName
- {
- get
- {
- return _providerTypeName;
- }
- }
+ public string ProviderTypeName { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerLoader.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerLoader.cs
index daffb6febd..7261308bc0 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerLoader.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerLoader.cs
@@ -30,13 +30,7 @@ namespace System.ComponentModel.Design.Serialization
/// sinking notifications from the designer often want to ignore them while the desingner is loading
/// and only respond to them if they result from user interatcions.
/// </summary>
- public virtual bool Loading
- {
- get
- {
- return false;
- }
- }
+ public virtual bool Loading => false;
/// <summary>
/// Called by the designer host to begin the loading process. The designer
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerSerializerAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerSerializerAttribute.cs
index bb7ebfb5f8..dacbf07f72 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerSerializerAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/DesignerSerializerAttribute.cs
@@ -13,8 +13,6 @@ namespace System.ComponentModel.Design.Serialization
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
public sealed class DesignerSerializerAttribute : Attribute
{
- private string _serializerTypeName;
- private string _serializerBaseTypeName;
private string _typeId;
/// <summary>
@@ -22,8 +20,8 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public DesignerSerializerAttribute(Type serializerType, Type baseSerializerType)
{
- _serializerTypeName = serializerType.AssemblyQualifiedName;
- _serializerBaseTypeName = baseSerializerType.AssemblyQualifiedName;
+ SerializerTypeName = serializerType.AssemblyQualifiedName;
+ SerializerBaseTypeName = baseSerializerType.AssemblyQualifiedName;
}
/// <summary>
@@ -31,8 +29,8 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public DesignerSerializerAttribute(string serializerTypeName, Type baseSerializerType)
{
- _serializerTypeName = serializerTypeName;
- _serializerBaseTypeName = baseSerializerType.AssemblyQualifiedName;
+ SerializerTypeName = serializerTypeName;
+ SerializerBaseTypeName = baseSerializerType.AssemblyQualifiedName;
}
/// <summary>
@@ -40,31 +38,19 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public DesignerSerializerAttribute(string serializerTypeName, string baseSerializerTypeName)
{
- _serializerTypeName = serializerTypeName;
- _serializerBaseTypeName = baseSerializerTypeName;
+ SerializerTypeName = serializerTypeName;
+ SerializerBaseTypeName = baseSerializerTypeName;
}
/// <summary>
/// Retrieves the fully qualified type name of the serializer.
/// </summary>
- public string SerializerTypeName
- {
- get
- {
- return _serializerTypeName;
- }
- }
+ public string SerializerTypeName { get; }
/// <summary>
/// Retrieves the fully qualified type name of the serializer base type.
/// </summary>
- public string SerializerBaseTypeName
- {
- get
- {
- return _serializerBaseTypeName;
- }
- }
+ public string SerializerBaseTypeName { get; }
/// <internalonly/>
/// <summary>
@@ -82,7 +68,7 @@ namespace System.ComponentModel.Design.Serialization
{
if (_typeId == null)
{
- string baseType = _serializerBaseTypeName;
+ string baseType = SerializerBaseTypeName;
int comma = baseType.IndexOf(',');
if (comma != -1)
{
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/InstanceDescriptor.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/InstanceDescriptor.cs
index 24c045ee2c..f528c51228 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/InstanceDescriptor.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/InstanceDescriptor.cs
@@ -17,10 +17,6 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public sealed class InstanceDescriptor
{
- private MemberInfo _member;
- private ICollection _arguments;
- private bool _isComplete;
-
/// <summary>
/// Creates a new InstanceDescriptor.
/// </summary>
@@ -33,18 +29,18 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public InstanceDescriptor(MemberInfo member, ICollection arguments, bool isComplete)
{
- _member = member;
- _isComplete = isComplete;
+ MemberInfo = member;
+ IsComplete = isComplete;
if (arguments == null)
{
- _arguments = new object[0];
+ Arguments = Array.Empty<object>();
}
else
{
object[] args = new object[arguments.Count];
arguments.CopyTo(args, 0);
- _arguments = args;
+ Arguments = args;
}
if (member is FieldInfo)
@@ -54,7 +50,7 @@ namespace System.ComponentModel.Design.Serialization
{
throw new ArgumentException(SR.InstanceDescriptorMustBeStatic);
}
- if (_arguments.Count != 0)
+ if (Arguments.Count != 0)
{
throw new ArgumentException(SR.InstanceDescriptorLengthMismatch);
}
@@ -66,7 +62,7 @@ namespace System.ComponentModel.Design.Serialization
{
throw new ArgumentException(SR.InstanceDescriptorCannotBeStatic);
}
- if (_arguments.Count != ci.GetParameters().Length)
+ if (Arguments.Count != ci.GetParameters().Length)
{
throw new ArgumentException(SR.InstanceDescriptorLengthMismatch);
}
@@ -78,7 +74,7 @@ namespace System.ComponentModel.Design.Serialization
{
throw new ArgumentException(SR.InstanceDescriptorMustBeStatic);
}
- if (_arguments.Count != mi.GetParameters().Length)
+ if (Arguments.Count != mi.GetParameters().Length)
{
throw new ArgumentException(SR.InstanceDescriptorLengthMismatch);
}
@@ -102,13 +98,7 @@ namespace System.ComponentModel.Design.Serialization
/// The collection of arguments that should be passed to
/// MemberInfo in order to create an instance.
/// </summary>
- public ICollection Arguments
- {
- get
- {
- return _arguments;
- }
- }
+ public ICollection Arguments { get; }
/// <summary>
/// Determines if the contents of this instance descriptor completely identify the instance.
@@ -116,25 +106,13 @@ namespace System.ComponentModel.Design.Serialization
/// or constructor to represent. IsComplete can be used to identify these objects and take
/// additional steps to further describe their state.
/// </summary>
- public bool IsComplete
- {
- get
- {
- return _isComplete;
- }
- }
+ public bool IsComplete { get; }
/// <summary>
/// The MemberInfo object that was passed into the constructor
/// of this InstanceDescriptor.
/// </summary>
- public MemberInfo MemberInfo
- {
- get
- {
- return _member;
- }
- }
+ public MemberInfo MemberInfo { get; }
/// <summary>
/// Invokes this instance descriptor, returning the object
@@ -142,8 +120,8 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public object Invoke()
{
- object[] translatedArguments = new object[_arguments.Count];
- _arguments.CopyTo(translatedArguments, 0);
+ object[] translatedArguments = new object[Arguments.Count];
+ Arguments.CopyTo(translatedArguments, 0);
// Instance descriptors can contain other instance
// descriptors. Translate them if necessary.
@@ -156,25 +134,25 @@ namespace System.ComponentModel.Design.Serialization
}
}
- if (_member is ConstructorInfo)
+ if (MemberInfo is ConstructorInfo)
{
- return ((ConstructorInfo)_member).Invoke(translatedArguments);
+ return ((ConstructorInfo)MemberInfo).Invoke(translatedArguments);
}
- else if (_member is MethodInfo)
+ else if (MemberInfo is MethodInfo)
{
- return ((MethodInfo)_member).Invoke(null, translatedArguments);
+ return ((MethodInfo)MemberInfo).Invoke(null, translatedArguments);
}
- else if (_member is PropertyInfo)
+ else if (MemberInfo is PropertyInfo)
{
- return ((PropertyInfo)_member).GetValue(null, translatedArguments);
+ return ((PropertyInfo)MemberInfo).GetValue(null, translatedArguments);
}
- else if (_member is FieldInfo)
+ else if (MemberInfo is FieldInfo)
{
- return ((FieldInfo)_member).GetValue(null);
+ return ((FieldInfo)MemberInfo).GetValue(null);
}
else
{
- Debug.Fail("Unrecognized reflection type in instance descriptor: " + _member.GetType().Name);
+ Debug.Fail($"Unrecognized reflection type in instance descriptor: {MemberInfo.GetType().Name}");
}
return null;
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs
index e855b1e054..f5d82cc275 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs
@@ -182,9 +182,6 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public struct MemberRelationship
{
- private object _owner;
- private MemberDescriptor _member;
-
public static readonly MemberRelationship Empty = new MemberRelationship();
/// <summary>
@@ -195,42 +192,24 @@ namespace System.ComponentModel.Design.Serialization
if (owner == null) throw new ArgumentNullException(nameof(owner));
if (member == null) throw new ArgumentNullException(nameof(member));
- _owner = owner;
- _member = member;
+ Owner = owner;
+ Member = member;
}
/// <summary>
/// Returns true if this relationship is empty.
/// </summary>
- public bool IsEmpty
- {
- get
- {
- return _owner == null;
- }
- }
+ public bool IsEmpty => Owner == null;
/// <summary>
/// The member in this relationship.
/// </summary>
- public MemberDescriptor Member
- {
- get
- {
- return _member;
- }
- }
+ public MemberDescriptor Member { get; }
/// <summary>
/// The object owning the member.
/// </summary>
- public object Owner
- {
- get
- {
- return _owner;
- }
- }
+ public object Owner { get; }
/// <summary>
/// Infrastructure support to make this a first class struct
@@ -249,8 +228,8 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public override int GetHashCode()
{
- if (_owner == null) return base.GetHashCode();
- return _owner.GetHashCode() ^ _member.GetHashCode();
+ if (Owner == null) return base.GetHashCode();
+ return Owner.GetHashCode() ^ Member.GetHashCode();
}
/// <summary>
/// Infrastructure support to make this a first class struct
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/ResolveNameEventArgs.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/ResolveNameEventArgs.cs
index 02edebbdc8..551f4141ec 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/ResolveNameEventArgs.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/ResolveNameEventArgs.cs
@@ -14,43 +14,24 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public class ResolveNameEventArgs : EventArgs
{
- private string _name;
- private object _value;
-
/// <summary>
/// Creates a new resolve name event args object.
/// </summary>
public ResolveNameEventArgs(string name)
{
- _name = name;
- _value = null;
+ Name = name;
+ Value = null;
}
/// <summary>
/// The name of the object that needs to be resolved.
/// </summary>
- public string Name
- {
- get
- {
- return _name;
- }
- }
+ public string Name { get; }
/// <summary>
/// The object that matches the name.
/// </summary>
- public object Value
- {
- get
- {
- return _value;
- }
- set
- {
- _value = value;
- }
- }
+ public object Value { get; set; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/RootDesignerSerializerAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/RootDesignerSerializerAttribute.cs
index 2d61d04699..afc47f765d 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/RootDesignerSerializerAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/RootDesignerSerializerAttribute.cs
@@ -15,9 +15,6 @@ namespace System.ComponentModel.Design.Serialization
[Obsolete("This attribute has been deprecated. Use DesignerSerializerAttribute instead. For example, to specify a root designer for CodeDom, use DesignerSerializerAttribute(...,typeof(TypeCodeDomSerializer)). http://go.microsoft.com/fwlink/?linkid=14202")]
public sealed class RootDesignerSerializerAttribute : Attribute
{
- private bool _reloadable;
- private string _serializerTypeName;
- private string _serializerBaseTypeName;
private string _typeId;
/// <summary>
@@ -25,9 +22,9 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public RootDesignerSerializerAttribute(Type serializerType, Type baseSerializerType, bool reloadable)
{
- _serializerTypeName = serializerType.AssemblyQualifiedName;
- _serializerBaseTypeName = baseSerializerType.AssemblyQualifiedName;
- _reloadable = reloadable;
+ SerializerTypeName = serializerType.AssemblyQualifiedName;
+ SerializerBaseTypeName = baseSerializerType.AssemblyQualifiedName;
+ Reloadable = reloadable;
}
/// <summary>
@@ -35,9 +32,9 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public RootDesignerSerializerAttribute(string serializerTypeName, Type baseSerializerType, bool reloadable)
{
- _serializerTypeName = serializerTypeName;
- _serializerBaseTypeName = baseSerializerType.AssemblyQualifiedName;
- _reloadable = reloadable;
+ SerializerTypeName = serializerTypeName;
+ SerializerBaseTypeName = baseSerializerType.AssemblyQualifiedName;
+ Reloadable = reloadable;
}
/// <summary>
@@ -45,9 +42,9 @@ namespace System.ComponentModel.Design.Serialization
/// </summary>
public RootDesignerSerializerAttribute(string serializerTypeName, string baseSerializerTypeName, bool reloadable)
{
- _serializerTypeName = serializerTypeName;
- _serializerBaseTypeName = baseSerializerTypeName;
- _reloadable = reloadable;
+ SerializerTypeName = serializerTypeName;
+ SerializerBaseTypeName = baseSerializerTypeName;
+ Reloadable = reloadable;
}
/// <summary>
@@ -55,35 +52,17 @@ namespace System.ComponentModel.Design.Serialization
/// will not automatically perform a reload on behalf of the user. It will be the user's
/// responsibility to reload the document themselves.
/// </summary>
- public bool Reloadable
- {
- get
- {
- return _reloadable;
- }
- }
+ public bool Reloadable { get; }
/// <summary>
/// Retrieves the fully qualified type name of the serializer.
/// </summary>
- public string SerializerTypeName
- {
- get
- {
- return _serializerTypeName;
- }
- }
+ public string SerializerTypeName { get; }
/// <summary>
/// Retrieves the fully qualified type name of the serializer base type.
/// </summary>
- public string SerializerBaseTypeName
- {
- get
- {
- return _serializerBaseTypeName;
- }
- }
+ public string SerializerBaseTypeName { get; }
/// <internalonly/>
/// <summary>
@@ -101,7 +80,7 @@ namespace System.ComponentModel.Design.Serialization
{
if (_typeId == null)
{
- string baseType = _serializerBaseTypeName;
+ string baseType = SerializerBaseTypeName;
int comma = baseType.IndexOf(',');
if (comma != -1)
{
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ServiceObjectContainer.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ServiceObjectContainer.cs
index 0dfdec6ce0..8b797d84c8 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ServiceObjectContainer.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ServiceObjectContainer.cs
@@ -59,29 +59,13 @@ namespace System.ComponentModel.Design
/// types. You may override this proeprty and return your own types, modifying the default behavior
/// of GetService.
/// </summary>
- protected virtual Type[] DefaultServices
- {
- get
- {
- return s_defaultServices;
- }
- }
+ protected virtual Type[] DefaultServices => s_defaultServices;
/// <summary>
/// Our collection of services. The service collection is demand
/// created here.
/// </summary>
- private ServiceCollection<object> Services
- {
- get
- {
- if (_services == null)
- {
- _services = new ServiceCollection<object>();
- }
- return _services;
- }
- }
+ private ServiceCollection<object> Services => _services ?? (_services = new ServiceCollection<object>());
/// <summary>
/// Adds the given service to the service container.
@@ -96,7 +80,7 @@ namespace System.ComponentModel.Design
/// </summary>
public virtual void AddService(Type serviceType, object serviceInstance, bool promote)
{
- Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, "Adding service (instance) " + serviceType.Name + ". Promoting: " + promote.ToString());
+ Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, $"Adding service (instance) {serviceType.Name}. Promoting: {promote.ToString()}");
if (promote)
{
IServiceContainer container = Container;
@@ -139,7 +123,7 @@ namespace System.ComponentModel.Design
/// </summary>
public virtual void AddService(Type serviceType, ServiceCreatorCallback callback, bool promote)
{
- Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, "Adding service (callback) " + serviceType.Name + ". Promoting: " + promote.ToString());
+ Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, $"Adding service (callback) {serviceType.Name}. Promoting: {promote.ToString()}");
if (promote)
{
IServiceContainer container = Container;
@@ -204,7 +188,7 @@ namespace System.ComponentModel.Design
{
object service = null;
- Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, "Searching for service " + serviceType.Name);
+ Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, $"Searching for service {serviceType.Name}");
// Try locally. We first test for services we
// implement and then look in our service collection.
@@ -230,12 +214,12 @@ namespace System.ComponentModel.Design
{
Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, "Encountered a callback. Invoking it");
service = ((ServiceCreatorCallback)service)(this, serviceType);
- Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, "Callback return object: " + (service == null ? "(null)" : service.ToString()));
+ Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, $"Callback return object: {(service == null ? "(null)" : service.ToString())}");
if (service != null && !service.GetType().IsCOMObject && !serviceType.IsAssignableFrom(service.GetType()))
{
// Callback passed us a bad service. NULL it, rather than throwing an exception.
// Callers here do not need to be prepared to handle bad callback implemetations.
- Debug.Fail("Object " + service.GetType().Name + " was returned from a service creator callback but it does not implement the registered type of " + serviceType.Name);
+ Debug.Fail($"Object {service.GetType().Name} was returned from a service creator callback but it does not implement the registered type of {serviceType.Name}");
Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, "**** Object does not implement service interface");
service = null;
}
@@ -277,7 +261,7 @@ namespace System.ComponentModel.Design
/// </summary>
public virtual void RemoveService(Type serviceType, bool promote)
{
- Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, "Removing service: " + serviceType.Name + ", Promote: " + promote.ToString());
+ Debug.WriteLineIf(s_TRACESERVICE.TraceVerbose, $"Removing service: {serviceType.Name}, Promote: {promote.ToString()}");
if (promote)
{
IServiceContainer container = Container;
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ToolboxItemAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ToolboxItemAttribute.cs
index 32cf7373c4..04a1e51c75 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ToolboxItemAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/ToolboxItemAttribute.cs
@@ -70,7 +70,7 @@ namespace System.ComponentModel
public ToolboxItemAttribute(string toolboxItemTypeName)
{
string temp = toolboxItemTypeName.ToUpper(CultureInfo.InvariantCulture);
- Debug.Assert(temp.IndexOf(".DLL") == -1, "Came across: " + toolboxItemTypeName + " . Please remove the .dll extension");
+ Debug.Assert(temp.IndexOf(".DLL") == -1, $"Came across: {toolboxItemTypeName}. Please remove the .dll extension");
_toolboxItemTypeName = toolboxItemTypeName;
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignTimeVisibleAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignTimeVisibleAttribute.cs
index 56adea0c34..ae51f0f051 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignTimeVisibleAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignTimeVisibleAttribute.cs
@@ -17,15 +17,13 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public sealed class DesignTimeVisibleAttribute : Attribute
{
- private bool _visible;
-
/// <summary>
/// Creates a new DesignTimeVisibleAttribute with the visible
/// property set to the given value.
/// </summary>
public DesignTimeVisibleAttribute(bool visible)
{
- _visible = visible;
+ Visible = visible;
}
/// <summary>
@@ -40,13 +38,7 @@ namespace System.ComponentModel
/// True if this component should be shown at design time, or false
/// if it shouldn't.
/// </summary>
- public bool Visible
- {
- get
- {
- return _visible;
- }
- }
+ public bool Visible { get; }
/// <summary>
/// Marks a component as visible in a visual designer.
@@ -74,7 +66,7 @@ namespace System.ComponentModel
}
DesignTimeVisibleAttribute other = obj as DesignTimeVisibleAttribute;
- return other != null && other.Visible == _visible;
+ return other != null && other.Visible == Visible;
}
/// <summary>
@@ -82,7 +74,7 @@ namespace System.ComponentModel
/// </summary>
public override int GetHashCode()
{
- return typeof(DesignTimeVisibleAttribute).GetHashCode() ^ (_visible ? -1 : 0);
+ return typeof(DesignTimeVisibleAttribute).GetHashCode() ^ (Visible ? -1 : 0);
}
/// <summary>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignerAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignerAttribute.cs
index 59050e918b..05997fdc03 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignerAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignerAttribute.cs
@@ -17,8 +17,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
public sealed class DesignerAttribute : Attribute
{
- private readonly string _designerTypeName;
- private readonly string _designerBaseTypeName;
private string _typeId;
/// <summary>
@@ -30,9 +28,9 @@ namespace System.ComponentModel
public DesignerAttribute(string designerTypeName)
{
string temp = designerTypeName.ToUpper(CultureInfo.InvariantCulture);
- Debug.Assert(temp.IndexOf(".DLL") == -1, "Came across: " + designerTypeName + " . Please remove the .dll extension");
- _designerTypeName = designerTypeName;
- _designerBaseTypeName = typeof(IDesigner).FullName;
+ Debug.Assert(temp.IndexOf(".DLL") == -1, $"Came across: {designerTypeName}. Please remove the .dll extension");
+ DesignerTypeName = designerTypeName;
+ DesignerBaseTypeName = typeof(IDesigner).FullName;
}
/// <summary>
@@ -43,8 +41,8 @@ namespace System.ComponentModel
/// </summary>
public DesignerAttribute(Type designerType)
{
- _designerTypeName = designerType.AssemblyQualifiedName;
- _designerBaseTypeName = typeof(IDesigner).FullName;
+ DesignerTypeName = designerType.AssemblyQualifiedName;
+ DesignerBaseTypeName = typeof(IDesigner).FullName;
}
/// <summary>
@@ -56,9 +54,9 @@ namespace System.ComponentModel
public DesignerAttribute(string designerTypeName, string designerBaseTypeName)
{
string temp = designerTypeName.ToUpper(CultureInfo.InvariantCulture);
- Debug.Assert(temp.IndexOf(".DLL") == -1, "Came across: " + designerTypeName + " . Please remove the .dll extension");
- _designerTypeName = designerTypeName;
- _designerBaseTypeName = designerBaseTypeName;
+ Debug.Assert(temp.IndexOf(".DLL") == -1, $"Came across: {designerTypeName}. Please remove the .dll extension");
+ DesignerTypeName = designerTypeName;
+ DesignerBaseTypeName = designerBaseTypeName;
}
/// <summary>
@@ -70,9 +68,9 @@ namespace System.ComponentModel
public DesignerAttribute(string designerTypeName, Type designerBaseType)
{
string temp = designerTypeName.ToUpper(CultureInfo.InvariantCulture);
- Debug.Assert(temp.IndexOf(".DLL") == -1, "Came across: " + designerTypeName + " . Please remove the .dll extension");
- _designerTypeName = designerTypeName;
- _designerBaseTypeName = designerBaseType.AssemblyQualifiedName;
+ Debug.Assert(temp.IndexOf(".DLL") == -1, $"Came across: {designerTypeName}. Please remove the .dll extension");
+ DesignerTypeName = designerTypeName;
+ DesignerBaseTypeName = designerBaseType.AssemblyQualifiedName;
}
/// <summary>
@@ -83,8 +81,8 @@ namespace System.ComponentModel
/// </summary>
public DesignerAttribute(Type designerType, Type designerBaseType)
{
- _designerTypeName = designerType.AssemblyQualifiedName;
- _designerBaseTypeName = designerBaseType.AssemblyQualifiedName;
+ DesignerTypeName = designerType.AssemblyQualifiedName;
+ DesignerBaseTypeName = designerBaseType.AssemblyQualifiedName;
}
/// <summary>
@@ -93,26 +91,14 @@ namespace System.ComponentModel
/// the name of the base type of this designer.
/// </para>
/// </summary>
- public string DesignerBaseTypeName
- {
- get
- {
- return _designerBaseTypeName;
- }
- }
+ public string DesignerBaseTypeName { get; }
/// <summary>
/// <para>
/// Gets the name of the designer type associated with this designer attribute.
/// </para>
/// </summary>
- public string DesignerTypeName
- {
- get
- {
- return _designerTypeName;
- }
- }
+ public string DesignerTypeName { get; }
/// <internalonly/>
/// <summary>
@@ -130,7 +116,7 @@ namespace System.ComponentModel
{
if (_typeId == null)
{
- string baseType = _designerBaseTypeName;
+ string baseType = DesignerBaseTypeName;
int comma = baseType.IndexOf(',');
if (comma != -1)
{
@@ -151,12 +137,12 @@ namespace System.ComponentModel
DesignerAttribute other = obj as DesignerAttribute;
- return (other != null) && other._designerBaseTypeName == _designerBaseTypeName && other._designerTypeName == _designerTypeName;
+ return (other != null) && other.DesignerBaseTypeName == DesignerBaseTypeName && other.DesignerTypeName == DesignerTypeName;
}
public override int GetHashCode()
{
- return _designerTypeName.GetHashCode() ^ _designerBaseTypeName.GetHashCode();
+ return DesignerTypeName.GetHashCode() ^ DesignerBaseTypeName.GetHashCode();
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DoubleConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DoubleConverter.cs
index 02e546ab87..cd5d9441ce 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DoubleConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DoubleConverter.cs
@@ -16,24 +16,12 @@ namespace System.ComponentModel
/// <summary>
/// Determines whether this editor will attempt to convert hex (0x or #) strings
/// </summary>
- internal override bool AllowHex
- {
- get
- {
- return false;
- }
- }
+ internal override bool AllowHex => false;
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(Double);
- }
- }
+ internal override Type TargetType => typeof(double);
/// <summary>
/// Convert the given value to a string using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EditorAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EditorAttribute.cs
index e2db049d73..2a95373f21 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EditorAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EditorAttribute.cs
@@ -14,8 +14,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
public sealed class EditorAttribute : Attribute
{
- private string _baseTypeName;
- private string _typeName;
private string _typeId;
/// <summary>
@@ -24,8 +22,8 @@ namespace System.ComponentModel
/// </summary>
public EditorAttribute()
{
- _typeName = string.Empty;
- _baseTypeName = string.Empty;
+ EditorTypeName = string.Empty;
+ EditorBaseTypeName = string.Empty;
}
/// <summary>
@@ -35,9 +33,9 @@ namespace System.ComponentModel
public EditorAttribute(string typeName, string baseTypeName)
{
string temp = typeName.ToUpper(CultureInfo.InvariantCulture);
- Debug.Assert(temp.IndexOf(".DLL") == -1, "Came across: " + typeName + " . Please remove the .dll extension");
- _typeName = typeName;
- _baseTypeName = baseTypeName;
+ Debug.Assert(temp.IndexOf(".DLL") == -1, $"Came across: {typeName} . Please remove the .dll extension");
+ EditorTypeName = typeName;
+ EditorBaseTypeName = baseTypeName;
}
/// <summary>
@@ -46,9 +44,9 @@ namespace System.ComponentModel
public EditorAttribute(string typeName, Type baseType)
{
string temp = typeName.ToUpper(CultureInfo.InvariantCulture);
- Debug.Assert(temp.IndexOf(".DLL") == -1, "Came across: " + typeName + " . Please remove the .dll extension");
- _typeName = typeName;
- _baseTypeName = baseType.AssemblyQualifiedName;
+ Debug.Assert(temp.IndexOf(".DLL") == -1, $"Came across: {typeName} . Please remove the .dll extension");
+ EditorTypeName = typeName;
+ EditorBaseTypeName = baseType.AssemblyQualifiedName;
}
/// <summary>
@@ -57,31 +55,19 @@ namespace System.ComponentModel
/// </summary>
public EditorAttribute(Type type, Type baseType)
{
- _typeName = type.AssemblyQualifiedName;
- _baseTypeName = baseType.AssemblyQualifiedName;
+ EditorTypeName = type.AssemblyQualifiedName;
+ EditorBaseTypeName = baseType.AssemblyQualifiedName;
}
/// <summary>
/// <para>Gets the name of the base class or interface serving as a lookup key for this editor.</para>
/// </summary>
- public string EditorBaseTypeName
- {
- get
- {
- return _baseTypeName;
- }
- }
+ public string EditorBaseTypeName { get; }
/// <summary>
/// <para>Gets the name of the editor class.</para>
/// </summary>
- public string EditorTypeName
- {
- get
- {
- return _typeName;
- }
- }
+ public string EditorTypeName { get; }
/// <internalonly/>
/// <summary>
@@ -99,7 +85,7 @@ namespace System.ComponentModel
{
if (_typeId == null)
{
- string baseType = _baseTypeName;
+ string baseType = EditorBaseTypeName;
int comma = baseType.IndexOf(',');
if (comma != -1)
{
@@ -120,7 +106,7 @@ namespace System.ComponentModel
EditorAttribute other = obj as EditorAttribute;
- return (other != null) && other._typeName == _typeName && other._baseTypeName == _baseTypeName;
+ return (other != null) && other.EditorTypeName == EditorTypeName && other.EditorBaseTypeName == EditorBaseTypeName;
}
public override int GetHashCode()
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs
index e3e1b62f5f..31f020b501 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs
@@ -16,6 +16,7 @@ namespace System.ComponentModel
/// </summary>
public class EnumConverter : TypeConverter
{
+ private static readonly char[] s_separators = {','};
/// <summary>
/// <para>
/// Provides a <see cref='System.ComponentModel.TypeConverter.StandardValuesCollection'/> that specifies the
@@ -26,35 +27,19 @@ namespace System.ComponentModel
/// <summary>
/// <para>
- /// Specifies
- /// the
- /// type of the enumerator this converter is
- /// associated with.
- /// </para>
- /// </summary>
- private readonly Type _type;
-
- /// <summary>
- /// <para>
/// Initializes a new instance of the <see cref='System.ComponentModel.EnumConverter'/> class for the given
/// type.
/// </para>
/// </summary>
public EnumConverter(Type type)
{
- _type = type;
+ EnumType = type;
}
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- protected Type EnumType
- {
- get
- {
- return _type;
- }
- }
+ protected Type EnumType { get; }
/// <summary>
/// <para>[To be supplied.]</para>
@@ -105,13 +90,7 @@ namespace System.ComponentModel
/// be used to sort the values of the enumerator.
/// </para>
/// </summary>
- protected virtual IComparer Comparer
- {
- get
- {
- return InvariantComparer.Default;
- }
- }
+ protected virtual IComparer Comparer => InvariantComparer.Default;
/// <internalonly/>
/// <summary>
@@ -127,21 +106,21 @@ namespace System.ComponentModel
if (strValue.IndexOf(',') != -1)
{
long convertedValue = 0;
- string[] values = strValue.Split(new char[] { ',' });
+ string[] values = strValue.Split(s_separators);
foreach (string v in values)
{
- convertedValue |= Convert.ToInt64((Enum)Enum.Parse(_type, v, true), culture);
+ convertedValue |= Convert.ToInt64((Enum)Enum.Parse(EnumType, v, true), culture);
}
- return Enum.ToObject(_type, convertedValue);
+ return Enum.ToObject(EnumType, convertedValue);
}
else
{
- return Enum.Parse(_type, strValue, true);
+ return Enum.Parse(EnumType, strValue, true);
}
}
catch (Exception e)
{
- throw new FormatException(SR.Format(SR.ConvertInvalidPrimitive, (string)value, _type.Name), e);
+ throw new FormatException(SR.Format(SR.ConvertInvalidPrimitive, (string)value, EnumType.Name), e);
}
}
else if (value is Enum[])
@@ -151,7 +130,7 @@ namespace System.ComponentModel
{
finalValue |= Convert.ToInt64(e, culture);
}
- return Enum.ToObject(_type, finalValue);
+ return Enum.ToObject(EnumType, finalValue);
}
return base.ConvertFrom(context, culture, value);
}
@@ -174,21 +153,21 @@ namespace System.ComponentModel
// Raise an argument exception if the value isn't defined and if
// the enum isn't a flags style.
//
- if (!_type.GetTypeInfo().IsDefined(typeof(FlagsAttribute), false) && !Enum.IsDefined(_type, value))
+ if (!EnumType.GetTypeInfo().IsDefined(typeof(FlagsAttribute), false) && !Enum.IsDefined(EnumType, value))
{
- throw new ArgumentException(SR.Format(SR.EnumConverterInvalidValue, value.ToString(), _type.Name));
+ throw new ArgumentException(SR.Format(SR.EnumConverterInvalidValue, value.ToString(), EnumType.Name));
}
- return Enum.Format(_type, value, "G");
+ return Enum.Format(EnumType, value, "G");
}
if (destinationType == typeof(Enum[]) && value != null)
{
- if (_type.GetTypeInfo().IsDefined(typeof(FlagsAttribute), false))
+ if (EnumType.GetTypeInfo().IsDefined(typeof(FlagsAttribute), false))
{
List<Enum> flagValues = new List<Enum>();
- Array objValues = Enum.GetValues(_type);
+ Array objValues = Enum.GetValues(EnumType);
long[] ulValues = new long[objValues.Length];
for (int idx = 0; idx < objValues.Length; idx++)
{
@@ -204,7 +183,7 @@ namespace System.ComponentModel
{
if ((ul != 0 && (ul & longValue) == ul) || ul == longValue)
{
- flagValues.Add((Enum)Enum.ToObject(_type, ul));
+ flagValues.Add((Enum)Enum.ToObject(EnumType, ul));
valueFound = true;
longValue &= ~ul;
break;
@@ -219,14 +198,14 @@ namespace System.ComponentModel
if (!valueFound && longValue != 0)
{
- flagValues.Add((Enum)Enum.ToObject(_type, longValue));
+ flagValues.Add((Enum)Enum.ToObject(EnumType, longValue));
}
return flagValues.ToArray();
}
else
{
- return new Enum[] { (Enum)Enum.ToObject(_type, value) };
+ return new Enum[] { (Enum)Enum.ToObject(EnumType, value) };
}
}
@@ -246,18 +225,14 @@ namespace System.ComponentModel
// out fields marked Browsable(false). Note that if multiple fields have the same value,
// the behavior is undefined, since what we return are just enum values, not names.
- Type reflectType = TypeDescriptor.GetReflectionType(_type);
- if (reflectType == null)
- {
- reflectType = _type;
- }
+ Type reflectType = TypeDescriptor.GetReflectionType(EnumType) ?? EnumType;
FieldInfo[] fields = reflectType.GetFields(BindingFlags.Public | BindingFlags.Static);
- ArrayList objValues = null;
+ List<object> objValues = null;
if (fields != null && fields.Length > 0)
{
- objValues = new ArrayList(fields.Length);
+ objValues = new List<object>(fields.Length);
}
if (objValues != null)
@@ -278,7 +253,7 @@ namespace System.ComponentModel
{
if (field.Name != null)
{
- value = Enum.Parse(_type, field.Name);
+ value = Enum.Parse(EnumType, field.Name);
}
}
catch (ArgumentException)
@@ -296,11 +271,11 @@ namespace System.ComponentModel
IComparer comparer = Comparer;
if (comparer != null)
{
- objValues.Sort(comparer);
+ objValues.Sort((IComparer<object>) comparer);
}
}
- Array arr = (objValues != null) ? objValues.ToArray() : null;
+ Array arr = objValues?.ToArray();
_values = new StandardValuesCollection(arr);
}
return _values;
@@ -314,7 +289,7 @@ namespace System.ComponentModel
/// </summary>
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
- return !_type.GetTypeInfo().IsDefined(typeof(FlagsAttribute), false);
+ return !EnumType.GetTypeInfo().IsDefined(typeof(FlagsAttribute), false);
}
/// <internalonly/>
@@ -335,7 +310,7 @@ namespace System.ComponentModel
/// </summary>
public override bool IsValid(ITypeDescriptorContext context, object value)
{
- return Enum.IsDefined(_type, value);
+ return Enum.IsDefined(EnumType, value);
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EventDescriptorCollection.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EventDescriptorCollection.cs
index f57edaade9..527f109b86 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EventDescriptorCollection.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/EventDescriptorCollection.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections;
+using System.Collections.Generic;
using System.Diagnostics;
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2112:SecuredTypesShouldNotExposeFields", Scope = "type", Target = "System.ComponentModel.EventDescriptorCollection")]
@@ -20,9 +21,8 @@ namespace System.ComponentModel
private string[] _namedSort;
private readonly IComparer _comparer;
private bool _eventsOwned;
- private bool _needSort = false;
- private int _eventCount;
- private readonly bool _readOnly = false;
+ private bool _needSort;
+ private readonly bool _readOnly;
/// <summary>
/// An empty AttributeCollection that can used instead of creating a new one with no items.
@@ -39,12 +39,11 @@ namespace System.ComponentModel
if (events == null)
{
_events = Array.Empty<EventDescriptor>();
- _eventCount = 0;
}
else
{
_events = events;
- _eventCount = events.Length;
+ Count = events.Length;
}
_eventsOwned = true;
}
@@ -67,7 +66,7 @@ namespace System.ComponentModel
}
_comparer = comparer;
_events = events;
- _eventCount = eventCount;
+ Count = eventCount;
_needSort = true;
}
@@ -77,13 +76,7 @@ namespace System.ComponentModel
/// of event descriptors in the collection.
/// </para>
/// </summary>
- public int Count
- {
- get
- {
- return _eventCount;
- }
- }
+ public int Count { get; private set; }
/// <summary>
/// <para>Gets the event with the specified index
@@ -93,7 +86,7 @@ namespace System.ComponentModel
{
get
{
- if (index >= _eventCount)
+ if (index >= Count)
{
throw new IndexOutOfRangeException();
}
@@ -107,13 +100,7 @@ namespace System.ComponentModel
/// Gets the event with the specified name.
/// </para>
/// </summary>
- public virtual EventDescriptor this[string name]
- {
- get
- {
- return Find(name, false);
- }
- }
+ public virtual EventDescriptor this[string name] => Find(name, false);
/// <summary>
/// <para>[To be supplied.]</para>
@@ -125,9 +112,9 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- EnsureSize(_eventCount + 1);
- _events[_eventCount++] = value;
- return _eventCount - 1;
+ EnsureSize(Count + 1);
+ _events[Count++] = value;
+ return Count - 1;
}
/// <summary>
@@ -140,7 +127,7 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- _eventCount = 0;
+ Count = 0;
}
/// <summary>
@@ -187,7 +174,7 @@ namespace System.ComponentModel
if (_events.Length == 0)
{
- _eventCount = 0;
+ Count = 0;
_events = new EventDescriptor[sizeNeeded];
return;
}
@@ -196,7 +183,7 @@ namespace System.ComponentModel
int newSize = Math.Max(sizeNeeded, _events.Length * 2);
EventDescriptor[] newEvents = new EventDescriptor[newSize];
- Array.Copy(_events, 0, newEvents, 0, _eventCount);
+ Array.Copy(_events, 0, newEvents, 0, Count);
_events = newEvents;
}
@@ -242,7 +229,7 @@ namespace System.ComponentModel
/// </summary>
public int IndexOf(EventDescriptor value)
{
- return Array.IndexOf(_events, value, 0, _eventCount);
+ return Array.IndexOf(_events, value, 0, Count);
}
/// <summary>
@@ -255,13 +242,13 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- EnsureSize(_eventCount + 1);
- if (index < _eventCount)
+ EnsureSize(Count + 1);
+ if (index < Count)
{
- Array.Copy(_events, index, _events, index + 1, _eventCount - index);
+ Array.Copy(_events, index, _events, index + 1, Count - index);
}
_events[index] = value;
- _eventCount++;
+ Count++;
}
/// <summary>
@@ -292,12 +279,12 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- if (index < _eventCount - 1)
+ if (index < Count - 1)
{
- Array.Copy(_events, index + 1, _events, index, _eventCount - index - 1);
+ Array.Copy(_events, index + 1, _events, index, Count - index - 1);
}
- _events[_eventCount - 1] = null;
- _eventCount--;
+ _events[Count - 1] = null;
+ Count--;
}
/// <summary>
@@ -308,13 +295,13 @@ namespace System.ComponentModel
public IEnumerator GetEnumerator()
{
// we can only return an enumerator on the events we actually have...
- if (_events.Length == _eventCount)
+ if (_events.Length == Count)
{
return _events.GetEnumerator();
}
else
{
- return new ArraySubsetEnumerator(_events, _eventCount);
+ return new ArraySubsetEnumerator(_events, Count);
}
}
@@ -326,7 +313,7 @@ namespace System.ComponentModel
/// </summary>
public virtual EventDescriptorCollection Sort()
{
- return new EventDescriptorCollection(_events, _eventCount, _namedSort, _comparer);
+ return new EventDescriptorCollection(_events, Count, _namedSort, _comparer);
}
@@ -338,7 +325,7 @@ namespace System.ComponentModel
/// </summary>
public virtual EventDescriptorCollection Sort(string[] names)
{
- return new EventDescriptorCollection(_events, _eventCount, names, _comparer);
+ return new EventDescriptorCollection(_events, Count, names, _comparer);
}
/// <summary>
@@ -349,7 +336,7 @@ namespace System.ComponentModel
/// </summary>
public virtual EventDescriptorCollection Sort(string[] names, IComparer comparer)
{
- return new EventDescriptorCollection(_events, _eventCount, names, comparer);
+ return new EventDescriptorCollection(_events, Count, names, comparer);
}
/// <summary>
@@ -360,7 +347,7 @@ namespace System.ComponentModel
/// </summary>
public virtual EventDescriptorCollection Sort(IComparer comparer)
{
- return new EventDescriptorCollection(_events, _eventCount, _namedSort, comparer);
+ return new EventDescriptorCollection(_events, Count, _namedSort, comparer);
}
/// <summary>
@@ -380,7 +367,7 @@ namespace System.ComponentModel
if (names != null && names.Length > 0)
{
- ArrayList eventArrayList = new ArrayList(_events);
+ List<EventDescriptor> eventList = new List<EventDescriptor>(_events);
int foundCount = 0;
int eventCount = _events.Length;
@@ -388,7 +375,7 @@ namespace System.ComponentModel
{
for (int j = 0; j < eventCount; j++)
{
- EventDescriptor currentEvent = (EventDescriptor)eventArrayList[j];
+ EventDescriptor currentEvent = eventList[j];
// Found a matching event. Here, we add it to our array. We also
// mark it as null in our array list so we don't add it twice later.
@@ -396,7 +383,7 @@ namespace System.ComponentModel
if (currentEvent != null && currentEvent.Name.Equals(names[i]))
{
_events[foundCount++] = currentEvent;
- eventArrayList[j] = null;
+ eventList[j] = null;
break;
}
}
@@ -409,9 +396,9 @@ namespace System.ComponentModel
//
for (int i = 0; i < eventCount; i++)
{
- if (eventArrayList[i] != null)
+ if (eventList[i] != null)
{
- _events[foundCount++] = (EventDescriptor)eventArrayList[i];
+ _events[foundCount++] = eventList[i];
}
}
@@ -437,30 +424,12 @@ namespace System.ComponentModel
}
/// <internalonly/>
- bool ICollection.IsSynchronized
- {
- get
- {
- return false;
- }
- }
+ bool ICollection.IsSynchronized => false;
/// <internalonly/>
- object ICollection.SyncRoot
- {
- get
- {
- return null;
- }
- }
+ object ICollection.SyncRoot => null;
- int ICollection.Count
- {
- get
- {
- return Count;
- }
- }
+ int ICollection.Count => Count;
IEnumerator IEnumerable.GetEnumerator()
{
@@ -481,7 +450,7 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- if (index >= _eventCount)
+ if (index >= Count)
{
throw new IndexOutOfRangeException();
}
@@ -531,22 +500,10 @@ namespace System.ComponentModel
}
/// <internalonly/>
- bool IList.IsReadOnly
- {
- get
- {
- return _readOnly;
- }
- }
+ bool IList.IsReadOnly => _readOnly;
/// <internalonly/>
- bool IList.IsFixedSize
- {
- get
- {
- return _readOnly;
- }
- }
+ bool IList.IsFixedSize => _readOnly;
private class ArraySubsetEnumerator : IEnumerator
{
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtendedPropertyDescriptor.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtendedPropertyDescriptor.cs
index 02eedf9bae..88ba8fbbb7 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtendedPropertyDescriptor.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtendedPropertyDescriptor.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections;
+using System.Collections.Generic;
using System.Diagnostics;
namespace System.ComponentModel
@@ -29,7 +30,7 @@ namespace System.ComponentModel
Debug.Assert(extenderInfo != null, "ExtendedPropertyDescriptor must have extenderInfo");
Debug.Assert(provider != null, "ExtendedPropertyDescriptor must have provider");
- ArrayList attrList = new ArrayList(AttributeArray);
+ List<Attribute> attrList = new List<Attribute>(AttributeArray);
attrList.Add(ExtenderProvidedPropertyAttribute.Create(extenderInfo, receiverType, provider));
if (extenderInfo.IsReadOnly)
{
@@ -72,35 +73,17 @@ namespace System.ComponentModel
/// <summary>
/// Retrieves the type of the component this PropertyDescriptor is bound to.
/// </summary>
- public override Type ComponentType
- {
- get
- {
- return _extenderInfo.ComponentType;
- }
- }
+ public override Type ComponentType => _extenderInfo.ComponentType;
/// <summary>
/// Determines if the property can be written to.
/// </summary>
- public override bool IsReadOnly
- {
- get
- {
- return Attributes[typeof(ReadOnlyAttribute)].Equals(ReadOnlyAttribute.Yes);
- }
- }
+ public override bool IsReadOnly => Attributes[typeof(ReadOnlyAttribute)].Equals(ReadOnlyAttribute.Yes);
/// <summary>
/// Retrieves the data type of the property.
/// </summary>
- public override Type PropertyType
- {
- get
- {
- return _extenderInfo.ExtenderGetType(_provider);
- }
- }
+ public override Type PropertyType => _extenderInfo.ExtenderGetType(_provider);
/// <summary>
/// Retrieves the display name of the property. This is the name that will
@@ -117,13 +100,10 @@ namespace System.ComponentModel
if (displayNameAttr == null || displayNameAttr.IsDefaultAttribute())
{
ISite site = GetSite(_provider);
- if (site != null)
+ string providerName = site?.Name;
+ if (providerName != null && providerName.Length > 0)
{
- string providerName = site.Name;
- if (providerName != null && providerName.Length > 0)
- {
- name = string.Format(SR.MetaExtenderName, name, providerName);
- }
+ name = string.Format(SR.MetaExtenderName, name, providerName);
}
}
return name;
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtenderProvidedPropertyAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtenderProvidedPropertyAttribute.cs
index 55e69d0f10..eed2e0e16d 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtenderProvidedPropertyAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExtenderProvidedPropertyAttribute.cs
@@ -14,19 +14,15 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.All)]
public sealed class ExtenderProvidedPropertyAttribute : Attribute
{
- private PropertyDescriptor _extenderProperty;
- private IExtenderProvider _provider;
- private Type _receiverType;
-
/// <summary>
/// Creates a new ExtenderProvidedPropertyAttribute.
/// </summary>
internal static ExtenderProvidedPropertyAttribute Create(PropertyDescriptor extenderProperty, Type receiverType, IExtenderProvider provider)
{
ExtenderProvidedPropertyAttribute e = new ExtenderProvidedPropertyAttribute();
- e._extenderProperty = extenderProperty;
- e._receiverType = receiverType;
- e._provider = provider;
+ e.ExtenderProperty = extenderProperty;
+ e.ReceiverType = receiverType;
+ e.Provider = provider;
return e;
}
@@ -40,35 +36,17 @@ namespace System.ComponentModel
/// <summary>
/// PropertyDescriptor of the property that is being provided.
/// </summary>
- public PropertyDescriptor ExtenderProperty
- {
- get
- {
- return _extenderProperty;
- }
- }
+ public PropertyDescriptor ExtenderProperty { get; private set; }
/// <summary>
/// Extender provider that is providing the property.
/// </summary>
- public IExtenderProvider Provider
- {
- get
- {
- return _provider;
- }
- }
+ public IExtenderProvider Provider { get; private set; }
/// <summary>
/// The type of object that can receive these properties.
/// </summary>
- public Type ReceiverType
- {
- get
- {
- return _receiverType;
- }
- }
+ public Type ReceiverType { get; private set; }
public override bool Equals(object obj)
{
@@ -79,7 +57,7 @@ namespace System.ComponentModel
ExtenderProvidedPropertyAttribute other = obj as ExtenderProvidedPropertyAttribute;
- return (other != null) && other._extenderProperty.Equals(_extenderProperty) && other._provider.Equals(_provider) && other._receiverType.Equals(_receiverType);
+ return (other != null) && other.ExtenderProperty.Equals(ExtenderProperty) && other.Provider.Equals(Provider) && other.ReceiverType.Equals(ReceiverType);
}
public override int GetHashCode()
@@ -89,7 +67,7 @@ namespace System.ComponentModel
public override bool IsDefaultAttribute()
{
- return _receiverType == null;
+ return ReceiverType == null;
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/HandledEventArgs.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/HandledEventArgs.cs
index f137fed918..9ba7b11f62 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/HandledEventArgs.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/HandledEventArgs.cs
@@ -29,7 +29,6 @@ namespace System.ComponentModel
/// </para>
/// </summary>
public HandledEventArgs(bool defaultHandledValue)
- : base()
{
Handled = defaultHandledValue;
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstallerTypeAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstallerTypeAttribute.cs
index fde5cdc761..d104fd1044 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstallerTypeAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstallerTypeAttribute.cs
@@ -37,13 +37,7 @@ namespace System.ComponentModel
/// <para> Gets the
/// type of installer associated with this attribute.</para>
/// </summary>
- public virtual Type InstallerType
- {
- get
- {
- return Type.GetType(_typeName);
- }
- }
+ public virtual Type InstallerType => Type.GetType(_typeName);
public override bool Equals(object obj)
{
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstanceCreationEditor.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstanceCreationEditor.cs
index e5708678c1..34c2bd3b7f 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstanceCreationEditor.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/InstanceCreationEditor.cs
@@ -22,13 +22,7 @@ namespace System.ComponentModel
{
/// <summary>
/// </summary>
- public virtual string Text
- {
- get
- {
- return SR.InstanceCreationEditorDefaultText;
- }
- }
+ public virtual string Text => SR.InstanceCreationEditorDefaultText;
/// <summary>
/// This method is invoked when you user chooses the link displayed by the PropertyGrid for the InstanceCreationEditor.
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int16Converter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int16Converter.cs
index 619aaff323..dbc27d94da 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int16Converter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int16Converter.cs
@@ -15,13 +15,7 @@ namespace System.ComponentModel
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(Int16);
- }
- }
+ internal override Type TargetType => typeof(short);
/// <summary>
/// Convert the given value to a string using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int32Converter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int32Converter.cs
index e104919d31..b1e49ac205 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int32Converter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int32Converter.cs
@@ -15,13 +15,7 @@ namespace System.ComponentModel
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(Int32);
- }
- }
+ internal override Type TargetType => typeof(int);
/// <summary>
/// Convert the given value to a string using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int64Converter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int64Converter.cs
index ed082a0f74..96f0ecb7e9 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int64Converter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/Int64Converter.cs
@@ -15,13 +15,7 @@ namespace System.ComponentModel
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(Int64);
- }
- }
+ internal override Type TargetType => typeof(long);
/// <summary>
/// Convert the given value to a string using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs
index d4aa92ca2d..ce43765fde 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs
@@ -83,7 +83,7 @@ namespace System.ComponentModel
string moduleDir = Path.GetDirectoryName(modulePath);
string licenseFile = moduleDir + "\\" + type.FullName + ".lic";
- Debug.WriteLine("Looking for license in: " + licenseFile);
+ Debug.WriteLine($"Looking for license in: {licenseFile}");
if (File.Exists(licenseFile))
{
Stream licStream = new FileStream(licenseFile, FileMode.Open, FileAccess.Read, FileShare.Read);
@@ -108,20 +108,14 @@ namespace System.ComponentModel
private class LicFileLicense : License
{
private LicFileLicenseProvider _owner;
- private string _key;
public LicFileLicense(LicFileLicenseProvider owner, string key)
{
_owner = owner;
- _key = key;
- }
- public override string LicenseKey
- {
- get
- {
- return _key;
- }
+ LicenseKey = key;
}
+ public override string LicenseKey { get; }
+
public override void Dispose()
{
GC.SuppressFinalize(this);
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseContext.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseContext.cs
index d325d4581b..91e1101211 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseContext.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseContext.cs
@@ -18,13 +18,7 @@ namespace System.ComponentModel
/// <summary>
/// <para>When overridden in a derived class, gets a value that specifies when a license can be used.</para>
/// </summary>
- public virtual LicenseUsageMode UsageMode
- {
- get
- {
- return LicenseUsageMode.Runtime;
- }
- }
+ public virtual LicenseUsageMode UsageMode => LicenseUsageMode.Runtime;
/// <summary>
/// <para>When overridden in a derived class, gets a saved license
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseException.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseException.cs
index 7d8e8986f9..20b7424100 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseException.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseException.cs
@@ -17,7 +17,6 @@ namespace System.ComponentModel
[Serializable]
public class LicenseException : SystemException
{
- private Type _type;
private object _instance;
/// <summary>
@@ -40,7 +39,7 @@ namespace System.ComponentModel
/// </summary>
public LicenseException(Type type, object instance, string message) : base(message)
{
- _type = type;
+ LicensedType = type;
_instance = instance;
HResult = HResults.License;
}
@@ -50,7 +49,7 @@ namespace System.ComponentModel
/// </summary>
public LicenseException(Type type, object instance, string message, Exception innerException) : base(message, innerException)
{
- _type = type;
+ LicensedType = type;
_instance = instance;
HResult = HResults.License;
}
@@ -60,20 +59,14 @@ namespace System.ComponentModel
/// </summary>
protected LicenseException(SerializationInfo info, StreamingContext context) : base(info, context)
{
- _type = (Type)info.GetValue("type", typeof(Type));
+ LicensedType = (Type)info.GetValue("type", typeof(Type));
_instance = info.GetValue("instance", typeof(object));
}
/// <summary>
/// <para>Gets the type of the component that was not granted a license.</para>
/// </summary>
- public Type LicensedType
- {
- get
- {
- return _type;
- }
- }
+ public Type LicensedType { get; }
/// <summary>
/// Need this since Exception implements ISerializable and we have fields to save out.
@@ -86,7 +79,7 @@ namespace System.ComponentModel
throw new ArgumentNullException(nameof(info));
}
- info.AddValue("type", _type);
+ info.AddValue("type", LicensedType);
info.AddValue("instance", _instance);
base.GetObjectData(info, context);
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseManager.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseManager.cs
index 986e22d200..2a1ab92ed1 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseManager.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseManager.cs
@@ -22,11 +22,11 @@ namespace System.ComponentModel
{
private static readonly object s_selfLock = new object();
- private static volatile LicenseContext s_context = null;
- private static object s_contextLockHolder = null;
+ private static volatile LicenseContext s_context;
+ private static object s_contextLockHolder;
private static volatile Hashtable s_providers;
private static volatile Hashtable s_providerInstances;
- private static object s_internalSyncObject = new object();
+ private static readonly object s_internalSyncObject = new object();
// not creatable...
//
@@ -118,7 +118,7 @@ namespace System.ComponentModel
/// </summary>
public static object CreateWithContext(Type type, LicenseContext creationContext)
{
- return CreateWithContext(type, creationContext, new object[0]);
+ return CreateWithContext(type, creationContext, Array.Empty<object>());
}
@@ -178,11 +178,7 @@ namespace System.ComponentModel
/// </summary>
private static LicenseProvider GetCachedProvider(Type type)
{
- if (s_providers != null)
- {
- return (LicenseProvider)s_providers[type];
- }
- return null;
+ return (LicenseProvider) s_providers?[type];
}
@@ -193,11 +189,7 @@ namespace System.ComponentModel
private static LicenseProvider GetCachedProviderInstance(Type providerType)
{
Debug.Assert(providerType != null, "Type cannot ever be null");
- if (s_providerInstances != null)
- {
- return (LicenseProvider)s_providerInstances[providerType];
- }
- return null;
+ return (LicenseProvider) s_providerInstances?[providerType];
}
/// <summary>
@@ -308,12 +300,8 @@ namespace System.ComponentModel
if (attr != null)
{
Type providerType = attr.LicenseProvider;
- provider = GetCachedProviderInstance(providerType);
-
- if (provider == null)
- {
- provider = (LicenseProvider)SecurityUtils.SecureCreateInstance(providerType);
- }
+ provider = GetCachedProviderInstance(providerType) ??
+ (LicenseProvider)SecurityUtils.SecureCreateInstance(providerType);
}
CacheProvider(type, provider);
@@ -600,23 +588,16 @@ namespace System.ComponentModel
// of a single Type.
internal class CLRLicenseContext : LicenseContext
{
- private LicenseUsageMode _usageMode;
private Type _type;
private string _key;
public CLRLicenseContext(LicenseUsageMode usageMode, Type type)
{
- _usageMode = usageMode;
+ UsageMode = usageMode;
_type = type;
}
- public override LicenseUsageMode UsageMode
- {
- get
- {
- return _usageMode;
- }
- }
+ public override LicenseUsageMode UsageMode { get; }
public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly)
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseProviderAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseProviderAttribute.cs
index 81445d8fb5..9a0b3f231a 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseProviderAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicenseProviderAttribute.cs
@@ -21,8 +21,8 @@ namespace System.ComponentModel
/// </summary>
public static readonly LicenseProviderAttribute Default = new LicenseProviderAttribute();
- private Type _licenseProviderType = null;
- private string _licenseProviderName = null;
+ private Type _licenseProviderType;
+ private string _licenseProviderName;
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.LicenseProviderAttribute'/> class without a license
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListBindableAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListBindableAttribute.cs
index d3722b5756..102a6dde87 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListBindableAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListBindableAttribute.cs
@@ -30,15 +30,14 @@ namespace System.ComponentModel
/// </summary>
public static readonly ListBindableAttribute Default = Yes;
- private bool _listBindable = false;
- private bool _isDefault = false;
+ private bool _isDefault;
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
public ListBindableAttribute(bool listBindable)
{
- _listBindable = listBindable;
+ ListBindable = listBindable;
}
/// <summary>
@@ -46,20 +45,14 @@ namespace System.ComponentModel
/// </summary>
public ListBindableAttribute(BindableSupport flags)
{
- _listBindable = (flags != BindableSupport.No);
+ ListBindable = (flags != BindableSupport.No);
_isDefault = (flags == BindableSupport.Default);
}
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public bool ListBindable
- {
- get
- {
- return _listBindable;
- }
- }
+ public bool ListBindable { get; }
/// <summary>
/// <para>[To be supplied.]</para>
@@ -72,7 +65,7 @@ namespace System.ComponentModel
}
ListBindableAttribute other = obj as ListBindableAttribute;
- return other != null && other.ListBindable == _listBindable;
+ return other != null && other.ListBindable == ListBindable;
}
/// <summary>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListChangedEventArgs.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListChangedEventArgs.cs
index e63d04138f..b229996149 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListChangedEventArgs.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListChangedEventArgs.cs
@@ -16,11 +16,6 @@ namespace System.ComponentModel
/// </summary>
public class ListChangedEventArgs : EventArgs
{
- private ListChangedType _listChangedType;
- private int _newIndex;
- private int _oldIndex;
- private PropertyDescriptor _propDesc;
-
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
@@ -33,8 +28,8 @@ namespace System.ComponentModel
/// </summary>
public ListChangedEventArgs(ListChangedType listChangedType, int newIndex, PropertyDescriptor propDesc) : this(listChangedType, newIndex)
{
- _propDesc = propDesc;
- _oldIndex = newIndex;
+ PropertyDescriptor = propDesc;
+ OldIndex = newIndex;
}
/// <summary>
@@ -47,8 +42,8 @@ namespace System.ComponentModel
Debug.Assert(listChangedType != ListChangedType.ItemDeleted, "this constructor is used only for changes in the list MetaData");
Debug.Assert(listChangedType != ListChangedType.ItemChanged, "this constructor is used only for changes in the list MetaData");
- _listChangedType = listChangedType;
- _propDesc = propDesc;
+ ListChangedType = listChangedType;
+ PropertyDescriptor = propDesc;
}
/// <summary>
@@ -59,54 +54,30 @@ namespace System.ComponentModel
Debug.Assert(listChangedType != ListChangedType.PropertyDescriptorAdded, "this constructor is used only for item changed in the list");
Debug.Assert(listChangedType != ListChangedType.PropertyDescriptorDeleted, "this constructor is used only for item changed in the list");
Debug.Assert(listChangedType != ListChangedType.PropertyDescriptorChanged, "this constructor is used only for item changed in the list");
- _listChangedType = listChangedType;
- _newIndex = newIndex;
- _oldIndex = oldIndex;
+ ListChangedType = listChangedType;
+ NewIndex = newIndex;
+ OldIndex = oldIndex;
}
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public ListChangedType ListChangedType
- {
- get
- {
- return _listChangedType;
- }
- }
+ public ListChangedType ListChangedType { get; }
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public int NewIndex
- {
- get
- {
- return _newIndex;
- }
- }
+ public int NewIndex { get; }
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public int OldIndex
- {
- get
- {
- return _oldIndex;
- }
- }
+ public int OldIndex { get; }
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public PropertyDescriptor PropertyDescriptor
- {
- get
- {
- return _propDesc;
- }
- }
+ public PropertyDescriptor PropertyDescriptor { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescription.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescription.cs
index ec13092099..c4214b46db 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescription.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescription.cs
@@ -12,45 +12,23 @@ namespace System.ComponentModel
/// </summary>
public class ListSortDescription
{
- private PropertyDescriptor _property;
- private ListSortDirection _sortDirection;
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
public ListSortDescription(PropertyDescriptor property, ListSortDirection direction)
{
- _property = property;
- _sortDirection = direction;
+ PropertyDescriptor = property;
+ SortDirection = direction;
}
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public PropertyDescriptor PropertyDescriptor
- {
- get
- {
- return _property;
- }
- set
- {
- _property = value;
- }
- }
+ public PropertyDescriptor PropertyDescriptor { get; set; }
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public ListSortDirection SortDirection
- {
- get
- {
- return _sortDirection;
- }
- set
- {
- _sortDirection = value;
- }
- }
+ public ListSortDirection SortDirection { get; set; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescriptionCollection.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescriptionCollection.cs
index f1e55f27bc..cda7c97972 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescriptionCollection.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ListSortDescriptionCollection.cs
@@ -56,24 +56,12 @@ namespace System.ComponentModel
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- bool IList.IsFixedSize
- {
- get
- {
- return true;
- }
- }
+ bool IList.IsFixedSize => true;
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- bool IList.IsReadOnly
- {
- get
- {
- return true;
- }
- }
+ bool IList.IsReadOnly => true;
/// <summary>
/// <para>[To be supplied.]</para>
@@ -152,36 +140,17 @@ namespace System.ComponentModel
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- public int Count
- {
- get
- {
- return _sorts.Count;
- }
- }
+ public int Count => _sorts.Count;
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- bool ICollection.IsSynchronized
- {
- get
- {
- // true because after the constructor finished running the ListSortDescriptionCollection is Read Only
- return true;
- }
- }
+ bool ICollection.IsSynchronized => true;
/// <summary>
/// <para>[To be supplied.]</para>
/// </summary>
- object ICollection.SyncRoot
- {
- get
- {
- return this;
- }
- }
+ object ICollection.SyncRoot => this;
/// <summary>
/// <para>[To be supplied.]</para>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LookupBindingPropertiesAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LookupBindingPropertiesAttribute.cs
index 12f0d98092..fad5bbfedc 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LookupBindingPropertiesAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/LookupBindingPropertiesAttribute.cs
@@ -15,11 +15,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Class)]
public sealed class LookupBindingPropertiesAttribute : Attribute
{
- private readonly string _dataSource;
- private readonly string _displayMember;
- private readonly string _valueMember;
- private readonly string _lookupMember;
-
/// <summary>
/// <para>
/// Initializes a new instance of
@@ -28,10 +23,10 @@ namespace System.ComponentModel
/// </summary>
public LookupBindingPropertiesAttribute()
{
- _dataSource = null;
- _displayMember = null;
- _valueMember = null;
- _lookupMember = null;
+ DataSource = null;
+ DisplayMember = null;
+ ValueMember = null;
+ LookupMember = null;
}
/// <summary>
@@ -42,10 +37,10 @@ namespace System.ComponentModel
/// </summary>
public LookupBindingPropertiesAttribute(string dataSource, string displayMember, string valueMember, string lookupMember)
{
- _dataSource = dataSource;
- _displayMember = displayMember;
- _valueMember = valueMember;
- _lookupMember = lookupMember;
+ DataSource = dataSource;
+ DisplayMember = displayMember;
+ ValueMember = valueMember;
+ LookupMember = lookupMember;
}
/// <summary>
@@ -54,13 +49,7 @@ namespace System.ComponentModel
/// bound to.
/// </para>
/// </summary>
- public string DataSource
- {
- get
- {
- return _dataSource;
- }
- }
+ public string DataSource { get; }
/// <summary>
/// <para>
@@ -68,13 +57,7 @@ namespace System.ComponentModel
/// bound to.
/// </para>
/// </summary>
- public string DisplayMember
- {
- get
- {
- return _displayMember;
- }
- }
+ public string DisplayMember { get; }
/// <summary>
/// <para>
@@ -82,13 +65,7 @@ namespace System.ComponentModel
/// bound to.
/// </para>
/// </summary>
- public string ValueMember
- {
- get
- {
- return _valueMember;
- }
- }
+ public string ValueMember { get; }
/// <summary>
/// <para>
@@ -96,13 +73,7 @@ namespace System.ComponentModel
/// bound to.
/// </para>
/// </summary>
- public string LookupMember
- {
- get
- {
- return _lookupMember;
- }
- }
+ public string LookupMember { get; }
/// <summary>
/// <para>
@@ -116,10 +87,10 @@ namespace System.ComponentModel
{
LookupBindingPropertiesAttribute other = obj as LookupBindingPropertiesAttribute;
return other != null &&
- other.DataSource == _dataSource &&
- other._displayMember == _displayMember &&
- other._valueMember == _valueMember &&
- other._lookupMember == _lookupMember;
+ other.DataSource == DataSource &&
+ other.DisplayMember == DisplayMember &&
+ other.ValueMember == ValueMember &&
+ other.LookupMember == LookupMember;
}
public override int GetHashCode()
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MarshalByValueComponent.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MarshalByValueComponent.cs
index 584dbf4815..e51dc0772b 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MarshalByValueComponent.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MarshalByValueComponent.cs
@@ -59,17 +59,7 @@ namespace System.ComponentModel
/// <summary>
/// <para>Gets the list of event handlers that are attached to this component.</para>
/// </summary>
- protected EventHandlerList Events
- {
- get
- {
- if (_events == null)
- {
- _events = new EventHandlerList();
- }
- return _events;
- }
- }
+ protected EventHandlerList Events => _events ?? (_events = new EventHandlerList());
/// <summary>
/// <para>Gets or sets the site of the component.</para>
@@ -154,15 +144,8 @@ namespace System.ComponentModel
{
lock (this)
{
- if (_site != null && _site.Container != null)
- {
- _site.Container.Remove(this);
- }
- if (_events != null)
- {
- EventHandler handler = (EventHandler)_events[s_eventDisposed];
- if (handler != null) handler(this, EventArgs.Empty);
- }
+ _site?.Container?.Remove(this);
+ ((EventHandler) _events?[s_eventDisposed])?.Invoke(this, EventArgs.Empty);
}
}
}
@@ -171,21 +154,14 @@ namespace System.ComponentModel
/// <para>Gets the container for the component.</para>
/// </summary>
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public virtual IContainer Container
- {
- get
- {
- ISite s = _site;
- return s == null ? null : s.Container;
- }
- }
+ public virtual IContainer Container => _site?.Container;
/// <summary>
/// <para>Gets the implementer of the <see cref='System.IServiceProvider'/>.</para>
/// </summary>
public virtual object GetService(Type service)
{
- return ((_site == null) ? null : _site.GetService(service));
+ return _site?.GetService(service);
}
@@ -198,7 +174,7 @@ namespace System.ComponentModel
get
{
ISite s = _site;
- return (s == null) ? false : s.DesignMode;
+ return s?.DesignMode ?? false;
}
}
/// <internalonly/>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs
index 4652186f7d..5e57661f4a 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs
@@ -104,16 +104,16 @@ namespace System.ComponentModel
//// class data.
- private const char spaceChar = ' ';
- private const char defaultPromptChar = '_';
- private const char nullPasswordChar = '\0';
- private const bool defaultAllowPrompt = true;
- private const int invalidIndex = -1;
- private const byte editAny = 0;
- private const byte editUnassigned = 1;
- private const byte editAssigned = 2;
- private const bool forward = true;
- private const bool backward = false;
+ private const char SPACE_CHAR = ' ';
+ private const char DEFAULT_PROMPT_CHAR = '_';
+ private const char NULL_PASSWORD_CHAR = '\0';
+ private const bool DEFAULT_ALLOW_PROMPT = true;
+ private const int INVALID_INDEX = -1;
+ private const byte EDIT_ANY = 0;
+ private const byte EDIT_UNASSIGNED = 1;
+ private const byte EDIT_ASSIGNED = 2;
+ private const bool FORWARD = true;
+ private const bool BACKWARD = false;
// Bit masks for bool properties.
private static int s_ASCII_ONLY = BitVector32.CreateMask();
@@ -133,13 +133,11 @@ namespace System.ComponentModel
private BitVector32 _flagState;
// Used to obtained localized placeholder chars (date separator for instance).
- private CultureInfo _culture;
// the formatted string.
private StringBuilder _testString;
// the number of assigned edit chars.
- private int _assignedCharCount;
// the number of assigned required edit chars.
private int _requiredCharCount;
@@ -151,7 +149,6 @@ namespace System.ComponentModel
private int _optionalEditChars;
// Properties backend fields (see corresponding property for info).
- private string _mask;
private char _passwordChar;
private char _promptChar;
@@ -166,7 +163,7 @@ namespace System.ComponentModel
/// Creates a MaskedTextProvider object from the specified mask.
/// </summary>
public MaskedTextProvider(string mask)
- : this(mask, null, defaultAllowPrompt, defaultPromptChar, nullPasswordChar, false)
+ : this(mask, null, DEFAULT_ALLOW_PROMPT, DEFAULT_PROMPT_CHAR, NULL_PASSWORD_CHAR, false)
{
}
@@ -175,7 +172,7 @@ namespace System.ComponentModel
/// 'restrictToAscii' specifies whether the input characters should be restricted to ASCII characters only.
/// </summary>
public MaskedTextProvider(string mask, bool restrictToAscii)
- : this(mask, null, defaultAllowPrompt, defaultPromptChar, nullPasswordChar, restrictToAscii)
+ : this(mask, null, DEFAULT_ALLOW_PROMPT, DEFAULT_PROMPT_CHAR, NULL_PASSWORD_CHAR, restrictToAscii)
{
}
@@ -185,7 +182,7 @@ namespace System.ComponentModel
/// culture is used.
/// </summary>
public MaskedTextProvider(string mask, CultureInfo culture)
- : this(mask, culture, defaultAllowPrompt, defaultPromptChar, nullPasswordChar, false)
+ : this(mask, culture, DEFAULT_ALLOW_PROMPT, DEFAULT_PROMPT_CHAR, NULL_PASSWORD_CHAR, false)
{
}
@@ -196,7 +193,7 @@ namespace System.ComponentModel
/// 'restrictToAscii' specifies whether the input characters should be restricted to ASCII characters only.
/// </summary>
public MaskedTextProvider(string mask, CultureInfo culture, bool restrictToAscii)
- : this(mask, culture, defaultAllowPrompt, defaultPromptChar, nullPasswordChar, restrictToAscii)
+ : this(mask, culture, DEFAULT_ALLOW_PROMPT, DEFAULT_PROMPT_CHAR, NULL_PASSWORD_CHAR, restrictToAscii)
{
}
@@ -206,7 +203,7 @@ namespace System.ComponentModel
/// 'allowPromptAsInput' specifies whether the prompt character should be accepted as a valid input or not.
/// </summary>
public MaskedTextProvider(string mask, char passwordChar, bool allowPromptAsInput)
- : this(mask, null, allowPromptAsInput, defaultPromptChar, passwordChar, false)
+ : this(mask, null, allowPromptAsInput, DEFAULT_PROMPT_CHAR, passwordChar, false)
{
}
@@ -216,7 +213,7 @@ namespace System.ComponentModel
/// 'allowPromptAsInput' specifies whether the prompt character should be accepted as a valid input or not.
/// </summary>
public MaskedTextProvider(string mask, CultureInfo culture, char passwordChar, bool allowPromptAsInput)
- : this(mask, culture, allowPromptAsInput, defaultPromptChar, passwordChar, false)
+ : this(mask, culture, allowPromptAsInput, DEFAULT_PROMPT_CHAR, passwordChar, false)
{
}
@@ -253,7 +250,7 @@ namespace System.ComponentModel
// read only property-backend fields.
- _mask = mask;
+ Mask = mask;
_promptChar = promptChar;
_passwordChar = passwordChar;
@@ -265,25 +262,25 @@ namespace System.ComponentModel
{
if (culture.Equals(tempCulture.Parent))
{
- _culture = tempCulture;
+ Culture = tempCulture;
break;
}
}
// Last resort use invariant culture.
- if (_culture == null)
+ if (Culture == null)
{
- _culture = CultureInfo.InvariantCulture;
+ Culture = CultureInfo.InvariantCulture;
}
}
else
{
- _culture = culture;
+ Culture = culture;
}
- if (!_culture.IsReadOnly)
+ if (!Culture.IsReadOnly)
{
- _culture = CultureInfo.ReadOnly(_culture);
+ Culture = CultureInfo.ReadOnly(Culture);
}
_flagState[s_ALLOW_PROMPT_AS_INPUT] = allowPromptAsInput;
@@ -322,9 +319,9 @@ namespace System.ComponentModel
// Traverse the mask to generate the test string and the string descriptor table so we don't have
// to traverse those strings anymore.
//
- for (int maskPos = 0; maskPos < _mask.Length; maskPos++)
+ for (int maskPos = 0; maskPos < Mask.Length; maskPos++)
{
- ch = _mask[maskPos];
+ ch = Mask[maskPos];
if (!escapedChar) // if false treat the char as literal.
{
switch (ch)
@@ -334,27 +331,27 @@ namespace System.ComponentModel
// set the corresponding localized char to be added to the test string.
//
case '.': // decimal separator.
- locSymbol = _culture.NumberFormat.NumberDecimalSeparator;
+ locSymbol = Culture.NumberFormat.NumberDecimalSeparator;
charType = CharType.Separator;
break;
case ',': // thousands separator.
- locSymbol = _culture.NumberFormat.NumberGroupSeparator;
+ locSymbol = Culture.NumberFormat.NumberGroupSeparator;
charType = CharType.Separator;
break;
case ':': // time separator.
- locSymbol = _culture.DateTimeFormat.TimeSeparator;
+ locSymbol = Culture.DateTimeFormat.TimeSeparator;
charType = CharType.Separator;
break;
case '/': // date separator.
- locSymbol = _culture.DateTimeFormat.DateSeparator;
+ locSymbol = Culture.DateTimeFormat.DateSeparator;
charType = CharType.Separator;
break;
case '$': // currency symbol.
- locSymbol = _culture.NumberFormat.CurrencySymbol;
+ locSymbol = Culture.NumberFormat.CurrencySymbol;
charType = CharType.Separator;
break;
@@ -455,35 +452,17 @@ namespace System.ComponentModel
/// <summary>
/// Specifies whether the prompt character should be treated as a valid input character or not.
/// </summary>
- public bool AllowPromptAsInput
- {
- get
- {
- return _flagState[s_ALLOW_PROMPT_AS_INPUT];
- }
- }
+ public bool AllowPromptAsInput => _flagState[s_ALLOW_PROMPT_AS_INPUT];
/// <summary>
/// Retreives the number of editable characters that have been set.
/// </summary>
- public int AssignedEditPositionCount
- {
- get
- {
- return _assignedCharCount;
- }
- }
+ public int AssignedEditPositionCount { get; private set; }
/// <summary>
/// Retreives the number of editable characters that have been set.
/// </summary>
- public int AvailableEditPositionCount
- {
- get
- {
- return EditPositionCount - _assignedCharCount;
- }
- }
+ public int AvailableEditPositionCount => EditPositionCount - AssignedEditPositionCount;
/// <summary>
/// Creates a 'clean' (no text assigned) MaskedTextProvider instance with the same property values as the
@@ -548,37 +527,21 @@ namespace System.ComponentModel
/// <summary>
/// The culture that determines the value of the localizable mask language separators and placeholders.
/// </summary>
- public CultureInfo Culture
- {
- get
- {
- return _culture;
- }
- }
+ public CultureInfo Culture { get; }
/// <summary>
/// The system password char.
/// </summary>
- public static char DefaultPasswordChar
- {
- get
- {
- // ComCtl32.dll V6 (WindowsXP) provides a nice black circle but we don't want to attempt to simulate it
- // here to avoid hard coding values. MaskedTextBox picks up the right value at run time from comctl32.
- return '*';
- }
- }
+ /// <remarks>
+ /// ComCtl32.dll V6 (WindowsXP) provides a nice black circle but we don't want to attempt to simulate it
+ /// here to avoid hard coding values. MaskedTextBox picks up the right value at run time from comctl32.
+ /// </remarks>
+ public static char DefaultPasswordChar => '*';
/// <summary>
/// The number of editable positions in the test string.
/// </summary>
- public int EditPositionCount
- {
- get
- {
- return _optionalEditChars + _requiredEditChars;
- }
- }
+ public int EditPositionCount => _optionalEditChars + _requiredEditChars;
/// <summary>
/// Returns a new IEnumerator object containing the editable positions in the test string.
@@ -638,13 +601,7 @@ namespace System.ComponentModel
/// <summary>
/// Specifies whether only ASCII characters are accepted as valid input.
/// </summary>
- public bool AsciiOnly
- {
- get
- {
- return _flagState[s_ASCII_ONLY];
- }
- }
+ public bool AsciiOnly => _flagState[s_ASCII_ONLY];
/// <summary>
/// Specifies whether the user text is to be rendered as password characters.
@@ -660,7 +617,7 @@ namespace System.ComponentModel
{
if (IsPassword != value)
{
- _passwordChar = value ? DefaultPasswordChar : nullPasswordChar;
+ _passwordChar = value ? DefaultPasswordChar : NULL_PASSWORD_CHAR;
}
}
}
@@ -668,47 +625,23 @@ namespace System.ComponentModel
/// <summary>
/// A negative value representing an index outside the test string.
/// </summary>
- public static int InvalidIndex
- {
- get
- {
- return invalidIndex;
- }
- }
+ public static int InvalidIndex => INVALID_INDEX;
/// <summary>
/// The last edit position (relative to the origin not to time) in the test string where
/// an input character has been placed. If no position has been assigned, InvalidIndex is returned.
/// </summary>
- public int LastAssignedPosition
- {
- get
- {
- return FindAssignedEditPositionFrom(_testString.Length - 1, backward);
- }
- }
+ public int LastAssignedPosition => FindAssignedEditPositionFrom(_testString.Length - 1, BACKWARD);
/// <summary>
/// Specifies the length of the test string.
/// </summary>
- public int Length
- {
- get
- {
- return _testString.Length;
- }
- }
+ public int Length => _testString.Length;
/// <summary>
/// The mask to be applied to the test string.
/// </summary>
- public string Mask
- {
- get
- {
- return _mask;
- }
- }
+ public string Mask { get; }
/// <summary>
/// Specifies whether all required inputs have been provided into the mask successfully.
@@ -717,7 +650,7 @@ namespace System.ComponentModel
{
get
{
- Debug.Assert(_assignedCharCount >= 0, "Invalid count of assigned chars.");
+ Debug.Assert(AssignedEditPositionCount >= 0, "Invalid count of assigned chars.");
return _requiredCharCount == _requiredEditChars;
}
}
@@ -729,8 +662,8 @@ namespace System.ComponentModel
{
get
{
- Debug.Assert(_assignedCharCount >= 0, "Invalid count of assigned chars.");
- return _assignedCharCount == EditPositionCount;
+ Debug.Assert(AssignedEditPositionCount >= 0, "Invalid count of assigned chars.");
+ return AssignedEditPositionCount == EditPositionCount;
}
}
@@ -753,7 +686,7 @@ namespace System.ComponentModel
throw new InvalidOperationException(SR.MaskedTextProviderPasswordAndPromptCharError);
}
- if (!IsValidPasswordChar(value) && (value != nullPasswordChar))
+ if (!IsValidPasswordChar(value) && (value != NULL_PASSWORD_CHAR))
{
// Same message as in SR.MaskedTextBoxInvalidCharError.
throw new ArgumentException(SR.MaskedTextProviderInvalidCharError);
@@ -918,9 +851,9 @@ namespace System.ComponentModel
// Get position after last assigned position.
testPosition = lastAssignedPos + 1;
- testPosition = FindEditPositionFrom(testPosition, forward);
+ testPosition = FindEditPositionFrom(testPosition, FORWARD);
- if (testPosition == invalidIndex)
+ if (testPosition == INVALID_INDEX)
{
resultHint = MaskedTextResultHint.UnavailableEditPosition;
testPosition = _testString.Length;
@@ -989,7 +922,7 @@ namespace System.ComponentModel
/// </summary>
public void Clear(out MaskedTextResultHint resultHint)
{
- if (_assignedCharCount == 0)
+ if (AssignedEditPositionCount == 0)
{
resultHint = MaskedTextResultHint.NoEffect;
return;
@@ -1010,15 +943,15 @@ namespace System.ComponentModel
/// </summary>
public int FindAssignedEditPositionFrom(int position, bool direction)
{
- if (_assignedCharCount == 0)
+ if (AssignedEditPositionCount == 0)
{
- return invalidIndex;
+ return INVALID_INDEX;
}
int startPosition;
int endPosition;
- if (direction == forward)
+ if (direction == FORWARD)
{
startPosition = position;
endPosition = _testString.Length - 1;
@@ -1039,12 +972,12 @@ namespace System.ComponentModel
/// </summary>
public int FindAssignedEditPositionInRange(int startPosition, int endPosition, bool direction)
{
- if (_assignedCharCount == 0)
+ if (AssignedEditPositionCount == 0)
{
- return invalidIndex;
+ return INVALID_INDEX;
}
- return FindEditPositionInRange(startPosition, endPosition, direction, editAssigned);
+ return FindEditPositionInRange(startPosition, endPosition, direction, EDIT_ASSIGNED);
}
/// <summary>
@@ -1058,7 +991,7 @@ namespace System.ComponentModel
int startPosition;
int endPosition;
- if (direction == forward)
+ if (direction == FORWARD)
{
startPosition = position;
endPosition = _testString.Length - 1;
@@ -1099,7 +1032,7 @@ namespace System.ComponentModel
{
testPosition = FindEditPositionInRange(startPosition, endPosition, direction);
- if (testPosition == invalidIndex) // didn't find any.
+ if (testPosition == INVALID_INDEX) // didn't find any.
{
break;
}
@@ -1108,14 +1041,14 @@ namespace System.ComponentModel
switch (assignedStatus)
{
- case editUnassigned:
+ case EDIT_UNASSIGNED:
if (!chDex.IsAssigned)
{
return testPosition;
}
break;
- case editAssigned:
+ case EDIT_ASSIGNED:
if (chDex.IsAssigned)
{
return testPosition;
@@ -1126,7 +1059,7 @@ namespace System.ComponentModel
return testPosition;
}
- if (direction == forward)
+ if (direction == FORWARD)
{
startPosition++;
}
@@ -1137,7 +1070,7 @@ namespace System.ComponentModel
}
while (startPosition <= endPosition);
- return invalidIndex;
+ return INVALID_INDEX;
}
/// <summary>
@@ -1151,7 +1084,7 @@ namespace System.ComponentModel
int startPosition;
int endPosition;
- if (direction == forward)
+ if (direction == FORWARD)
{
startPosition = position;
endPosition = _testString.Length - 1;
@@ -1196,7 +1129,7 @@ namespace System.ComponentModel
if (startPosition > endPosition)
{
- return invalidIndex;
+ return INVALID_INDEX;
}
// Iterate through the test string until we find an edit char position.
@@ -1204,7 +1137,7 @@ namespace System.ComponentModel
while (startPosition <= endPosition)
{
- testPosition = (direction == forward) ? startPosition++ : endPosition--;
+ testPosition = (direction == FORWARD) ? startPosition++ : endPosition--;
CharDescriptor chDex = _stringDescriptor[testPosition];
@@ -1214,7 +1147,7 @@ namespace System.ComponentModel
}
}
- return invalidIndex;
+ return INVALID_INDEX;
}
/// <summary>
@@ -1227,7 +1160,7 @@ namespace System.ComponentModel
int startPosition;
int endPosition;
- if (direction == forward)
+ if (direction == FORWARD)
{
startPosition = position;
endPosition = _testString.Length - 1;
@@ -1238,7 +1171,7 @@ namespace System.ComponentModel
endPosition = position;
}
- return FindEditPositionInRange(startPosition, endPosition, direction, editUnassigned);
+ return FindEditPositionInRange(startPosition, endPosition, direction, EDIT_UNASSIGNED);
}
/// <summary>
@@ -1253,11 +1186,11 @@ namespace System.ComponentModel
while (true)
{
- position = FindEditPositionInRange(startPosition, endPosition, direction, editAny);
+ position = FindEditPositionInRange(startPosition, endPosition, direction, EDIT_ANY);
- if (position == invalidIndex)
+ if (position == INVALID_INDEX)
{
- return invalidIndex;
+ return INVALID_INDEX;
}
CharDescriptor chDex = _stringDescriptor[position];
@@ -1267,7 +1200,7 @@ namespace System.ComponentModel
return position;
}
- if (direction == forward)
+ if (direction == FORWARD)
{
startPosition++;
}
@@ -1381,8 +1314,8 @@ namespace System.ComponentModel
// Now check if we need to open room for the input characters (shift characters right) and if so test the shifting characters.
- int srcPos = FindEditPositionFrom(position, forward); // source position.
- bool shiftNeeded = FindAssignedEditPositionInRange(srcPos, testPosition, forward) != invalidIndex;
+ int srcPos = FindEditPositionFrom(position, FORWARD); // source position.
+ bool shiftNeeded = FindAssignedEditPositionInRange(srcPos, testPosition, FORWARD) != INVALID_INDEX;
int lastAssignedPos = LastAssignedPosition;
if (shiftNeeded && (testPosition == _testString.Length - 1)) // no room for shifting.
@@ -1392,7 +1325,7 @@ namespace System.ComponentModel
return false;
}
- int dstPos = FindEditPositionFrom(testPosition + 1, forward); // destination position.
+ int dstPos = FindEditPositionFrom(testPosition + 1, FORWARD); // destination position.
if (shiftNeeded)
{
@@ -1402,7 +1335,7 @@ namespace System.ComponentModel
// Test shifting characters.
while (true)
{
- if (dstPos == invalidIndex)
+ if (dstPos == INVALID_INDEX)
{
resultHint = MaskedTextResultHint.UnavailableEditPosition;
testPosition = _testString.Length;
@@ -1426,8 +1359,8 @@ namespace System.ComponentModel
break;
}
- srcPos = FindEditPositionFrom(srcPos + 1, forward);
- dstPos = FindEditPositionFrom(dstPos + 1, forward);
+ srcPos = FindEditPositionFrom(srcPos + 1, FORWARD);
+ dstPos = FindEditPositionFrom(dstPos + 1, FORWARD);
}
if (tempHint > resultHint)
@@ -1458,8 +1391,8 @@ namespace System.ComponentModel
ResetChar(dstPos);
}
- dstPos = FindEditPositionFrom(dstPos - 1, backward);
- srcPos = FindEditPositionFrom(srcPos - 1, backward);
+ dstPos = FindEditPositionFrom(dstPos - 1, BACKWARD);
+ srcPos = FindEditPositionFrom(srcPos - 1, BACKWARD);
}
}
@@ -1551,7 +1484,7 @@ namespace System.ComponentModel
/// </summary>
private static bool IsPrintableChar(char c)
{
- return char.IsLetterOrDigit(c) || char.IsPunctuation(c) || char.IsSymbol(c) || (c == spaceChar);
+ return char.IsLetterOrDigit(c) || char.IsPunctuation(c) || char.IsSymbol(c) || (c == SPACE_CHAR);
}
/// <summary>
@@ -1599,7 +1532,7 @@ namespace System.ComponentModel
{
int lastAssignedPos = LastAssignedPosition;
- if (lastAssignedPos == invalidIndex)
+ if (lastAssignedPos == INVALID_INDEX)
{
testPosition = 0;
resultHint = MaskedTextResultHint.NoEffect;
@@ -1680,11 +1613,11 @@ namespace System.ComponentModel
// Check if we need to shift characters left to occupied the positions left by the characters being removed.
int lastAssignedPos = LastAssignedPosition;
- int dstPos = FindEditPositionInRange(startPosition, endPosition, forward); // first edit position in range.
+ int dstPos = FindEditPositionInRange(startPosition, endPosition, FORWARD); // first edit position in range.
resultHint = MaskedTextResultHint.NoEffect;
- if (dstPos == invalidIndex || dstPos > lastAssignedPos) // nothing to remove.
+ if (dstPos == INVALID_INDEX || dstPos > lastAssignedPos) // nothing to remove.
{
testPosition = startPosition;
return true;
@@ -1696,7 +1629,7 @@ namespace System.ComponentModel
// if there are assigned characters to be removed (could be that the range doesn't have one, in such case we may be just
// be shifting chars), the result hint is success, let's check.
- if (FindAssignedEditPositionInRange(startPosition, endPosition, forward) != invalidIndex)
+ if (FindAssignedEditPositionInRange(startPosition, endPosition, FORWARD) != INVALID_INDEX)
{
resultHint = MaskedTextResultHint.Success;
}
@@ -1705,7 +1638,7 @@ namespace System.ComponentModel
{
// Test shifting characters.
- int srcPos = FindEditPositionFrom(endPosition + 1, forward); // first position to shift left.
+ int srcPos = FindEditPositionFrom(endPosition + 1, FORWARD); // first position to shift left.
int shiftStart = srcPos; // cache it here so we don't have to search for it later if needed.
MaskedTextResultHint testHint;
@@ -1732,8 +1665,8 @@ namespace System.ComponentModel
break;
}
- srcPos = FindEditPositionFrom(srcPos + 1, forward);
- dstPos = FindEditPositionFrom(dstPos + 1, forward);
+ srcPos = FindEditPositionFrom(srcPos + 1, FORWARD);
+ dstPos = FindEditPositionFrom(dstPos + 1, FORWARD);
}
// shifting characters is a resultHint == sideEffect, update hint if no characters removed (which would be hint == success).
@@ -1772,8 +1705,8 @@ namespace System.ComponentModel
break;
}
- srcPos = FindEditPositionFrom(srcPos + 1, forward);
- dstPos = FindEditPositionFrom(dstPos + 1, forward);
+ srcPos = FindEditPositionFrom(srcPos + 1, FORWARD);
+ dstPos = FindEditPositionFrom(dstPos + 1, FORWARD);
}
// If shifting character are less than characters to remove in the range, we need to remove the remaining ones in the range;
@@ -1825,10 +1758,10 @@ namespace System.ComponentModel
// If character is not to be escaped, we need to find the first edit position to test it in.
if (!TestEscapeChar(input, testPosition))
{
- testPosition = FindEditPositionFrom(testPosition, forward);
+ testPosition = FindEditPositionFrom(testPosition, FORWARD);
}
- if (testPosition == invalidIndex)
+ if (testPosition == INVALID_INDEX)
{
resultHint = MaskedTextResultHint.UnavailableEditPosition;
testPosition = position;
@@ -1985,7 +1918,7 @@ namespace System.ComponentModel
return false;
}
- if (_assignedCharCount > 0)
+ if (AssignedEditPositionCount > 0)
{
// cache out params to preserve the ones from the primary operation (in case of success).
int tempPos;
@@ -2016,10 +1949,10 @@ namespace System.ComponentModel
while (true)
{
- srcPos = FindEditPositionFrom(srcPos, forward);
- dstPos = FindEditPositionFrom(dstPos, forward);
+ srcPos = FindEditPositionFrom(srcPos, FORWARD);
+ dstPos = FindEditPositionFrom(dstPos, FORWARD);
- if (dstPos == invalidIndex)
+ if (dstPos == INVALID_INDEX)
{
testPosition = _testString.Length;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
@@ -2054,8 +1987,8 @@ namespace System.ComponentModel
{
SetChar(_testString[srcPos], dstPos);
- srcPos = FindEditPositionFrom(srcPos - 1, backward);
- dstPos = FindEditPositionFrom(dstPos - 1, backward);
+ srcPos = FindEditPositionFrom(srcPos - 1, BACKWARD);
+ dstPos = FindEditPositionFrom(dstPos - 1, BACKWARD);
}
}
// else endPosition == testPosition, this means replacing the entire text which is the same as Set().
@@ -2077,14 +2010,14 @@ namespace System.ComponentModel
{
chDex.IsAssigned = false;
_testString[testPosition] = _promptChar;
- _assignedCharCount--;
+ AssignedEditPositionCount--;
if (chDex.CharType == CharType.EditRequired)
{
_requiredCharCount--;
}
- Debug.Assert(_assignedCharCount >= 0, "Invalid count of assigned chars.");
+ Debug.Assert(AssignedEditPositionCount >= 0, "Invalid count of assigned chars.");
}
}
@@ -2096,15 +2029,15 @@ namespace System.ComponentModel
{
Debug.Assert(startPosition >= 0 && endPosition >= 0 && endPosition >= startPosition && endPosition < _testString.Length, "position out of range.");
- startPosition = FindAssignedEditPositionFrom(startPosition, forward);
+ startPosition = FindAssignedEditPositionFrom(startPosition, FORWARD);
- if (startPosition != invalidIndex)
+ if (startPosition != INVALID_INDEX)
{
- endPosition = FindAssignedEditPositionFrom(endPosition, backward);
+ endPosition = FindAssignedEditPositionFrom(endPosition, BACKWARD);
while (startPosition <= endPosition)
{
- startPosition = FindAssignedEditPositionFrom(startPosition, forward);
+ startPosition = FindAssignedEditPositionFrom(startPosition, FORWARD);
ResetChar(startPosition);
startPosition++;
}
@@ -2154,9 +2087,9 @@ namespace System.ComponentModel
}
// Reset remaining characters (if any).
- int resetPos = FindAssignedEditPositionFrom(testPosition + 1, forward);
+ int resetPos = FindAssignedEditPositionFrom(testPosition + 1, FORWARD);
- if (resetPos != invalidIndex)
+ if (resetPos != INVALID_INDEX)
{
ResetString(resetPos, _testString.Length - 1);
}
@@ -2204,14 +2137,14 @@ namespace System.ComponentModel
{
if (charDescriptor.CaseConversion == CaseConversion.ToLower)
{
- input = _culture.TextInfo.ToLower(input);
+ input = Culture.TextInfo.ToLower(input);
}
}
else // Char.IsLower( input )
{
if (charDescriptor.CaseConversion == CaseConversion.ToUpper)
{
- input = _culture.TextInfo.ToUpper(input);
+ input = Culture.TextInfo.ToUpper(input);
}
}
}
@@ -2221,7 +2154,7 @@ namespace System.ComponentModel
if (!charDescriptor.IsAssigned) // if position not counted for already (replace case) we do it (add case).
{
charDescriptor.IsAssigned = true;
- _assignedCharCount++;
+ AssignedEditPositionCount++;
if (charDescriptor.CharType == CharType.EditRequired)
{
@@ -2229,7 +2162,7 @@ namespace System.ComponentModel
}
}
- Debug.Assert(_assignedCharCount <= EditPositionCount, "Invalid count of assigned chars.");
+ Debug.Assert(AssignedEditPositionCount <= EditPositionCount, "Invalid count of assigned chars.");
}
/// <summary>
@@ -2245,7 +2178,7 @@ namespace System.ComponentModel
// If character is not to be escaped, we need to find the first edit position to test it in.
if (!TestEscapeChar(ch, testPosition))
{
- testPosition = FindEditPositionFrom(testPosition, forward);
+ testPosition = FindEditPositionFrom(testPosition, FORWARD);
}
SetChar(ch, testPosition);
@@ -2356,7 +2289,7 @@ namespace System.ComponentModel
}
}
- if (input == spaceChar && ResetOnSpace)
+ if (input == SPACE_CHAR && ResetOnSpace)
{
if (IsEditPosition(charDex) && charDex.IsAssigned) // Position would be reset.
{
@@ -2374,10 +2307,10 @@ namespace System.ComponentModel
// Test the character against the mask constraints. The switch tests false conditions.
// Space char succeeds the test if the char type is optional.
- switch (_mask[charDex.MaskPosition])
+ switch (Mask[charDex.MaskPosition])
{
case '#': // digit or plus/minus sign optional.
- if (!Char.IsDigit(input) && (input != '-') && (input != '+') && input != spaceChar)
+ if (!Char.IsDigit(input) && (input != '-') && (input != '+') && input != SPACE_CHAR)
{
resultHint = MaskedTextResultHint.DigitExpected;
return false;
@@ -2393,7 +2326,7 @@ namespace System.ComponentModel
break;
case '9': // digit optional.
- if (!Char.IsDigit(input) && input != spaceChar)
+ if (!Char.IsDigit(input) && input != SPACE_CHAR)
{
resultHint = MaskedTextResultHint.DigitExpected;
return false;
@@ -2414,7 +2347,7 @@ namespace System.ComponentModel
break;
case '?': // letter optional.
- if (!Char.IsLetter(input) && input != spaceChar)
+ if (!Char.IsLetter(input) && input != SPACE_CHAR)
{
resultHint = MaskedTextResultHint.LetterExpected;
return false;
@@ -2435,7 +2368,7 @@ namespace System.ComponentModel
break;
case 'C': // any character optional.
- if ((!IsAscii(input) && AsciiOnly) && input != spaceChar)
+ if ((!IsAscii(input) && AsciiOnly) && input != SPACE_CHAR)
{
resultHint = MaskedTextResultHint.AsciiCharacterExpected;
return false;
@@ -2456,7 +2389,7 @@ namespace System.ComponentModel
break;
case 'a': // Alphanumeric optional.
- if (!IsAlphanumeric(input) && input != spaceChar)
+ if (!IsAlphanumeric(input) && input != SPACE_CHAR)
{
resultHint = MaskedTextResultHint.AlphanumericCharacterExpected;
return false;
@@ -2506,7 +2439,7 @@ namespace System.ComponentModel
return SkipLiterals && input == _testString[position];
}
- if ((ResetOnPrompt && (input == _promptChar)) || (ResetOnSpace && (input == spaceChar)))
+ if ((ResetOnPrompt && (input == _promptChar)) || (ResetOnSpace && (input == SPACE_CHAR)))
{
return true;
}
@@ -2591,9 +2524,9 @@ namespace System.ComponentModel
// If character is not to be escaped, we need to find an edit position to test it in.
if (!TestEscapeChar(ch, testPosition))
{
- testPosition = FindEditPositionFrom(testPosition, forward);
+ testPosition = FindEditPositionFrom(testPosition, FORWARD);
- if (testPosition == invalidIndex)
+ if (testPosition == INVALID_INDEX)
{
testPosition = _testString.Length;
resultHint = MaskedTextResultHint.UnavailableEditPosition;
@@ -2628,7 +2561,7 @@ namespace System.ComponentModel
/// </summary>
public string ToDisplayString()
{
- if (!IsPassword || _assignedCharCount == 0) // just return the testString since it contains the formatted text.
+ if (!IsPassword || AssignedEditPositionCount == 0) // just return the testString since it contains the formatted text.
{
return _testString.ToString();
}
@@ -2754,8 +2687,8 @@ namespace System.ComponentModel
// the last assigned position or last literal position if including literals, whichever is higher; upper unassigned
// positions are not included in the resulting string.
- int lastLiteralPos = includeLiterals ? FindNonEditPositionInRange(startPosition, lastPosition, backward) : InvalidIndex;
- int lastAssignedPos = FindAssignedEditPositionInRange(lastLiteralPos == InvalidIndex ? startPosition : lastLiteralPos, lastPosition, backward);
+ int lastLiteralPos = includeLiterals ? FindNonEditPositionInRange(startPosition, lastPosition, BACKWARD) : InvalidIndex;
+ int lastAssignedPos = FindAssignedEditPositionInRange(lastLiteralPos == InvalidIndex ? startPosition : lastLiteralPos, lastPosition, BACKWARD);
// If lastLiteralPos is in the range and lastAssignedPos is not InvalidIndex, the lastAssignedPos is the upper limit
// we are looking for since it is searched in the range from lastLiteralPos and lastPosition. In any other case
@@ -2791,7 +2724,7 @@ namespace System.ComponentModel
{
if (!includePrompt)
{
- st.Append(spaceChar); // replace prompt with space.
+ st.Append(SPACE_CHAR); // replace prompt with space.
break;
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MemberDescriptor.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MemberDescriptor.cs
index 838b663e72..b53ba36a05 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MemberDescriptor.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/MemberDescriptor.cs
@@ -24,8 +24,8 @@ namespace System.ComponentModel
private AttributeCollection _attributeCollection;
private Attribute[] _attributes;
private Attribute[] _originalAttributes;
- private bool _attributesFiltered = false;
- private bool _attributesFilled = false;
+ private bool _attributesFiltered;
+ private bool _attributesFilled;
private int _metadataVersion;
private string _category;
private string _description;
@@ -97,26 +97,26 @@ namespace System.ComponentModel
_displayName = oldMemberDescriptor.DisplayName;
_nameHash = _name.GetHashCode();
- ArrayList newArray = new ArrayList();
+ List<Attribute> newList = new List<Attribute>();
if (oldMemberDescriptor.Attributes.Count != 0)
{
- foreach (object o in oldMemberDescriptor.Attributes)
+ foreach (Attribute o in oldMemberDescriptor.Attributes)
{
- newArray.Add(o);
+ newList.Add(o);
}
}
if (newAttributes != null)
{
- foreach (object o in newAttributes)
+ foreach (Attribute o in newAttributes)
{
- newArray.Add(o);
+ newList.Add(o);
}
}
- _attributes = new Attribute[newArray.Count];
- newArray.CopyTo(_attributes, 0);
+ _attributes = new Attribute[newList.Count];
+ newList.CopyTo(_attributes, 0);
_attributesFiltered = false;
_originalAttributes = _attributes;
@@ -177,17 +177,7 @@ namespace System.ComponentModel
/// in the <see cref='System.ComponentModel.CategoryAttribute'/>.
/// </para>
/// </summary>
- public virtual string Category
- {
- get
- {
- if (_category == null)
- {
- _category = ((CategoryAttribute)Attributes[typeof(CategoryAttribute)]).Category;
- }
- return _category;
- }
- }
+ public virtual string Category => _category ?? (_category = ((CategoryAttribute) Attributes[typeof(CategoryAttribute)]).Category);
/// <summary>
/// <para>
@@ -195,17 +185,8 @@ namespace System.ComponentModel
/// the member as specified in the <see cref='System.ComponentModel.DescriptionAttribute'/>.
/// </para>
/// </summary>
- public virtual string Description
- {
- get
- {
- if (_description == null)
- {
- _description = ((DescriptionAttribute)Attributes[typeof(DescriptionAttribute)]).Description;
- }
- return _description;
- }
- }
+ public virtual string Description => _description ??
+ (_description = ((DescriptionAttribute) Attributes[typeof(DescriptionAttribute)]).Description);
/// <summary>
/// <para>
@@ -213,13 +194,7 @@ namespace System.ComponentModel
/// <see cref='System.ComponentModel.BrowsableAttribute'/>.
/// </para>
/// </summary>
- public virtual bool IsBrowsable
- {
- get
- {
- return ((BrowsableAttribute)Attributes[typeof(BrowsableAttribute)]).Browsable;
- }
- }
+ public virtual bool IsBrowsable => ((BrowsableAttribute)Attributes[typeof(BrowsableAttribute)]).Browsable;
/// <summary>
/// <para>
@@ -227,17 +202,7 @@ namespace System.ComponentModel
/// name of the member.
/// </para>
/// </summary>
- public virtual string Name
- {
- get
- {
- if (_name == null)
- {
- return "";
- }
- return _name;
- }
- }
+ public virtual string Name => _name ?? "";
/// <summary>
/// <para>
@@ -245,13 +210,7 @@ namespace System.ComponentModel
/// code for the name of the member as specified in <see cref='System.String.GetHashCode'/>.
/// </para>
/// </summary>
- protected virtual int NameHashCode
- {
- get
- {
- return _nameHash;
- }
- }
+ protected virtual int NameHashCode => _nameHash;
/// <summary>
/// <para>
@@ -259,13 +218,7 @@ namespace System.ComponentModel
/// design time as specified in the <see cref='System.ComponentModel.DesignOnlyAttribute'/>.
/// </para>
/// </summary>
- public virtual bool DesignTimeOnly
- {
- get
- {
- return (DesignOnlyAttribute.Yes.Equals(Attributes[typeof(DesignOnlyAttribute)]));
- }
- }
+ public virtual bool DesignTimeOnly => (DesignOnlyAttribute.Yes.Equals(Attributes[typeof(DesignOnlyAttribute)]));
/// <summary>
/// <para>
@@ -525,12 +478,7 @@ namespace System.ComponentModel
/// </summary>
protected static ISite GetSite(object component)
{
- if (!(component is IComponent))
- {
- return null;
- }
-
- return ((IComponent)component).Site;
+ return (component as IComponent)?.Site;
}
[Obsolete("This method has been deprecated. Use GetInvocationTarget instead. http://go.microsoft.com/fwlink/?linkid=14202")]
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NestedContainer.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NestedContainer.cs
index d5f029cbdc..f1c8122c9f 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NestedContainer.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NestedContainer.cs
@@ -19,8 +19,6 @@ namespace System.ComponentModel
/// </summary>
public class NestedContainer : Container, INestedContainer
{
- private IComponent _owner;
-
/// <summary>
/// Creates a new NestedContainer.
/// </summary>
@@ -30,20 +28,14 @@ namespace System.ComponentModel
{
throw new ArgumentNullException(nameof(owner));
}
- _owner = owner;
- _owner.Disposed += new EventHandler(OnOwnerDisposed);
+ Owner = owner;
+ Owner.Disposed += new EventHandler(OnOwnerDisposed);
}
/// <summary>
/// The component that owns this nested container.
/// </summary>
- public IComponent Owner
- {
- get
- {
- return _owner;
- }
- }
+ public IComponent Owner { get; }
/// <summary>
/// Retrieves the name of the owning component. This may be overridden to
@@ -56,16 +48,16 @@ namespace System.ComponentModel
get
{
string ownerName = null;
- if (_owner != null && _owner.Site != null)
+ if (Owner != null && Owner.Site != null)
{
- INestedSite nestedOwnerSite = _owner.Site as INestedSite;
+ INestedSite nestedOwnerSite = Owner.Site as INestedSite;
if (nestedOwnerSite != null)
{
ownerName = nestedOwnerSite.FullName;
}
else
{
- ownerName = _owner.Site.Name;
+ ownerName = Owner.Site.Name;
}
}
@@ -92,7 +84,7 @@ namespace System.ComponentModel
{
if (disposing)
{
- _owner.Disposed -= new EventHandler(OnOwnerDisposed);
+ Owner.Disposed -= new EventHandler(OnOwnerDisposed);
}
base.Dispose(disposing);
}
@@ -126,38 +118,24 @@ namespace System.ComponentModel
/// </summary>
private class Site : INestedSite
{
- private IComponent _component;
- private NestedContainer _container;
private string _name;
internal Site(IComponent component, NestedContainer container, string name)
{
- _component = component;
- _container = container;
+ Component = component;
+ Container = container;
_name = name;
}
// The component sited by this component site.
- public IComponent Component
- {
- get
- {
- return _component;
- }
- }
+ public IComponent Component { get; }
// The container in which the component is sited.
- public IContainer Container
- {
- get
- {
- return _container;
- }
- }
+ public IContainer Container { get; }
public Object GetService(Type service)
{
- return ((service == typeof(ISite)) ? this : _container.GetService(service));
+ return ((service == typeof(ISite)) ? this : ((NestedContainer)Container).GetService(service));
}
// Indicates whether the component is in design mode.
@@ -165,7 +143,7 @@ namespace System.ComponentModel
{
get
{
- IComponent owner = _container.Owner;
+ IComponent owner = ((NestedContainer)Container).Owner;
if (owner != null && owner.Site != null)
{
return owner.Site.DesignMode;
@@ -180,7 +158,7 @@ namespace System.ComponentModel
{
if (_name != null)
{
- string ownerName = _container.OwnerName;
+ string ownerName = ((NestedContainer)Container).OwnerName;
string childName = _name;
if (ownerName != null)
{
@@ -206,7 +184,7 @@ namespace System.ComponentModel
{
if (value == null || _name == null || !value.Equals(_name))
{
- _container.ValidateName(_component, value);
+ ((NestedContainer)Container).ValidateName(Component, value);
_name = value;
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs
index e12d6ef595..f318db135b 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs
@@ -13,24 +13,20 @@ namespace System.ComponentModel
/// </summary>
public class NullableConverter : TypeConverter
{
- private readonly Type _nullableType;
- private readonly Type _simpleType;
- private readonly TypeConverter _simpleTypeConverter;
-
/// <summary>
/// Nullable converter is initialized with the underlying simple type.
/// </summary>
public NullableConverter(Type type)
{
- _nullableType = type;
+ NullableType = type;
- _simpleType = Nullable.GetUnderlyingType(type);
- if (_simpleType == null)
+ UnderlyingType = Nullable.GetUnderlyingType(type);
+ if (UnderlyingType == null)
{
throw new ArgumentException(SR.NullableConverterBadCtorArg, nameof(type));
}
- _simpleTypeConverter = TypeDescriptor.GetConverter(_simpleType);
+ UnderlyingTypeConverter = TypeDescriptor.GetConverter(UnderlyingType);
}
/// <summary>
@@ -39,13 +35,13 @@ namespace System.ComponentModel
/// </summary>
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
- if (sourceType == _simpleType)
+ if (sourceType == UnderlyingType)
{
return true;
}
- else if (_simpleTypeConverter != null)
+ else if (UnderlyingTypeConverter != null)
{
- return _simpleTypeConverter.CanConvertFrom(context, sourceType);
+ return UnderlyingTypeConverter.CanConvertFrom(context, sourceType);
}
else
{
@@ -58,7 +54,7 @@ namespace System.ComponentModel
/// </summary>
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
- if (value == null || value.GetType() == _simpleType)
+ if (value == null || value.GetType() == UnderlyingType)
{
return value;
}
@@ -66,9 +62,9 @@ namespace System.ComponentModel
{
return null;
}
- else if (_simpleTypeConverter != null)
+ else if (UnderlyingTypeConverter != null)
{
- return _simpleTypeConverter.ConvertFrom(context, culture, value);
+ return UnderlyingTypeConverter.ConvertFrom(context, culture, value);
}
else
{
@@ -81,13 +77,13 @@ namespace System.ComponentModel
/// </summary>
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
- if (destinationType == _simpleType)
+ if (destinationType == UnderlyingType)
{
return true;
}
- else if (_simpleTypeConverter != null)
+ else if (UnderlyingTypeConverter != null)
{
- return _simpleTypeConverter.CanConvertTo(context, destinationType);
+ return UnderlyingTypeConverter.CanConvertTo(context, destinationType);
}
else
{
@@ -105,7 +101,7 @@ namespace System.ComponentModel
throw new ArgumentNullException(nameof(destinationType));
}
- if (destinationType == _simpleType && value != null && _nullableType.GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo()))
+ if (destinationType == UnderlyingType && value != null && NullableType.GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo()))
{
return value;
}
@@ -117,9 +113,9 @@ namespace System.ComponentModel
return string.Empty;
}
}
- else if (_simpleTypeConverter != null)
+ else if (UnderlyingTypeConverter != null)
{
- return _simpleTypeConverter.ConvertTo(context, culture, value, destinationType);
+ return UnderlyingTypeConverter.ConvertTo(context, culture, value, destinationType);
}
return base.ConvertTo(context, culture, value, destinationType);
@@ -129,9 +125,9 @@ namespace System.ComponentModel
/// </summary>
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
{
- if (_simpleTypeConverter != null)
+ if (UnderlyingTypeConverter != null)
{
- object instance = _simpleTypeConverter.CreateInstance(context, propertyValues);
+ object instance = UnderlyingTypeConverter.CreateInstance(context, propertyValues);
return instance;
}
@@ -147,9 +143,9 @@ namespace System.ComponentModel
/// </summary>
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
- if (_simpleTypeConverter != null)
+ if (UnderlyingTypeConverter != null)
{
- return _simpleTypeConverter.GetCreateInstanceSupported(context);
+ return UnderlyingTypeConverter.GetCreateInstanceSupported(context);
}
return base.GetCreateInstanceSupported(context);
@@ -163,10 +159,10 @@ namespace System.ComponentModel
/// </summary>
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
- if (_simpleTypeConverter != null)
+ if (UnderlyingTypeConverter != null)
{
object unwrappedValue = value;
- return _simpleTypeConverter.GetProperties(context, unwrappedValue, attributes);
+ return UnderlyingTypeConverter.GetProperties(context, unwrappedValue, attributes);
}
return base.GetProperties(context, value, attributes);
@@ -177,9 +173,9 @@ namespace System.ComponentModel
/// </summary>
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
- if (_simpleTypeConverter != null)
+ if (UnderlyingTypeConverter != null)
{
- return _simpleTypeConverter.GetPropertiesSupported(context);
+ return UnderlyingTypeConverter.GetPropertiesSupported(context);
}
return base.GetPropertiesSupported(context);
@@ -190,9 +186,9 @@ namespace System.ComponentModel
/// </summary>
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
- if (_simpleTypeConverter != null)
+ if (UnderlyingTypeConverter != null)
{
- StandardValuesCollection values = _simpleTypeConverter.GetStandardValues(context);
+ StandardValuesCollection values = UnderlyingTypeConverter.GetStandardValues(context);
if (GetStandardValuesSupported(context) && values != null)
{
// Create a set of standard values around nullable instances.
@@ -221,9 +217,9 @@ namespace System.ComponentModel
/// </summary>
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
- if (_simpleTypeConverter != null)
+ if (UnderlyingTypeConverter != null)
{
- return _simpleTypeConverter.GetStandardValuesExclusive(context);
+ return UnderlyingTypeConverter.GetStandardValuesExclusive(context);
}
return base.GetStandardValuesExclusive(context);
@@ -237,9 +233,9 @@ namespace System.ComponentModel
/// </summary>
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
- if (_simpleTypeConverter != null)
+ if (UnderlyingTypeConverter != null)
{
- return _simpleTypeConverter.GetStandardValuesSupported(context);
+ return UnderlyingTypeConverter.GetStandardValuesSupported(context);
}
return base.GetStandardValuesSupported(context);
@@ -250,7 +246,7 @@ namespace System.ComponentModel
/// </summary>
public override bool IsValid(ITypeDescriptorContext context, object value)
{
- if (_simpleTypeConverter != null)
+ if (UnderlyingTypeConverter != null)
{
object unwrappedValue = value;
if (unwrappedValue == null)
@@ -259,7 +255,7 @@ namespace System.ComponentModel
}
else
{
- return _simpleTypeConverter.IsValid(context, unwrappedValue);
+ return UnderlyingTypeConverter.IsValid(context, unwrappedValue);
}
}
@@ -269,34 +265,16 @@ namespace System.ComponentModel
/// <summary>
/// The type this converter was initialized with.
/// </summary>
- public Type NullableType
- {
- get
- {
- return _nullableType;
- }
- }
+ public Type NullableType { get; }
/// <summary>
/// The simple type that is represented as a nullable.
/// </summary>
- public Type UnderlyingType
- {
- get
- {
- return _simpleType;
- }
- }
+ public Type UnderlyingType { get; }
/// <summary>
/// Converter associated with the underlying simple type.
/// </summary>
- public TypeConverter UnderlyingTypeConverter
- {
- get
- {
- return _simpleTypeConverter;
- }
- }
+ public TypeConverter UnderlyingTypeConverter { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PasswordPropertyTextAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PasswordPropertyTextAttribute.cs
index fcfce71c8f..1a54e58dc7 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PasswordPropertyTextAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PasswordPropertyTextAttribute.cs
@@ -34,8 +34,6 @@ namespace System.ComponentModel
/// </summary>
public static readonly PasswordPropertyTextAttribute Default = No;
- private bool _password;
-
/// <summary>
/// Creates a default PasswordPropertyTextAttribute.
/// </summary>
@@ -48,19 +46,13 @@ namespace System.ComponentModel
/// </summary>
public PasswordPropertyTextAttribute(bool password)
{
- _password = password;
+ Password = password;
}
/// <summary>
/// Gets a value indicating if the property this attribute is defined for should be shown as password text.
/// </summary>
- public bool Password
- {
- get
- {
- return _password;
- }
- }
+ public bool Password { get; }
/// <summary>
/// Overload for object equality
@@ -69,7 +61,7 @@ namespace System.ComponentModel
{
if (o is PasswordPropertyTextAttribute)
{
- return ((PasswordPropertyTextAttribute)o).Password == _password;
+ return ((PasswordPropertyTextAttribute)o).Password == Password;
}
return false;
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs
index 86b5d0802d..cda6d7ef36 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs
@@ -12,7 +12,7 @@ namespace System.ComponentModel
/// </summary>
public abstract class PropertyDescriptor : MemberDescriptor
{
- private TypeConverter _converter = null;
+ private TypeConverter _converter;
private Hashtable _valueChangedHandlers;
private object[] _editors;
private Type[] _editorTypes;
@@ -103,13 +103,7 @@ namespace System.ComponentModel
/// specified in the <see cref='System.ComponentModel.LocalizableAttribute'/>.
/// </para>
/// </summary>
- public virtual bool IsLocalizable
- {
- get
- {
- return (LocalizableAttribute.Yes.Equals(Attributes[typeof(LocalizableAttribute)]));
- }
- }
+ public virtual bool IsLocalizable => (LocalizableAttribute.Yes.Equals(Attributes[typeof(LocalizableAttribute)]));
/// <summary>
/// <para>
@@ -442,9 +436,9 @@ namespace System.ComponentModel
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
protected virtual void OnValueChanged(object component, EventArgs e)
{
- if (component != null && _valueChangedHandlers != null)
+ if (component != null)
{
- ((EventHandler)_valueChangedHandlers[component])?.Invoke(component, e);
+ ((EventHandler) _valueChangedHandlers?[component])?.Invoke(component, e);
}
}
@@ -476,7 +470,7 @@ namespace System.ComponentModel
/// component, in the form of a combined multicast event handler.
/// Returns null if no event handlers currently assigned to component.
/// </summary>
- internal protected EventHandler GetValueChangedHandler(object component)
+ protected internal EventHandler GetValueChangedHandler(object component)
{
if (component != null && _valueChangedHandlers != null)
{
@@ -517,12 +511,6 @@ namespace System.ComponentModel
/// from direct calls made to PropertyDescriptor.SetValue (value=false). For example, the component may
/// implement the INotifyPropertyChanged interface, or may have an explicit '{name}Changed' event for this property.
/// </summary>
- public virtual bool SupportsChangeEvents
- {
- get
- {
- return false;
- }
- }
+ public virtual bool SupportsChangeEvents => false;
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptorCollection.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptorCollection.cs
index bc9da9041d..0fa013822f 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptorCollection.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptorCollection.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections;
+using System.Collections.Generic;
using System.Diagnostics;
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", Scope = "member", Target = "System.ComponentModel.PropertyDescriptorCollection.System.Collections.IDictionary.Add(System.Object,System.Object):System.Void")]
@@ -28,12 +29,11 @@ namespace System.ComponentModel
private IDictionary _cachedFoundProperties;
private bool _cachedIgnoreCase;
private PropertyDescriptor[] _properties;
- private int _propCount = 0;
private readonly string[] _namedSort;
private readonly IComparer _comparer;
private bool _propsOwned;
- private bool _needSort = false;
- private bool _readOnly = false;
+ private bool _needSort;
+ private bool _readOnly;
private readonly object _internalSyncObject = new object();
@@ -48,12 +48,12 @@ namespace System.ComponentModel
if (properties == null)
{
_properties = Array.Empty<PropertyDescriptor>();
- _propCount = 0;
+ Count = 0;
}
else
{
_properties = properties;
- _propCount = properties.Length;
+ Count = properties.Length;
}
_propsOwned = true;
}
@@ -77,7 +77,7 @@ namespace System.ComponentModel
}
_comparer = comparer;
_properties = properties;
- _propCount = propCount;
+ Count = propCount;
_needSort = true;
}
@@ -88,13 +88,7 @@ namespace System.ComponentModel
/// collection.
/// </para>
/// </summary>
- public int Count
- {
- get
- {
- return _propCount;
- }
- }
+ public int Count { get; private set; }
/// <summary>
/// <para>Gets the property with the specified index
@@ -104,7 +98,7 @@ namespace System.ComponentModel
{
get
{
- if (index >= _propCount)
+ if (index >= Count)
{
throw new IndexOutOfRangeException();
}
@@ -116,13 +110,7 @@ namespace System.ComponentModel
/// <summary>
/// <para>Gets the property with the specified name.</para>
/// </summary>
- public virtual PropertyDescriptor this[string name]
- {
- get
- {
- return Find(name, false);
- }
- }
+ public virtual PropertyDescriptor this[string name] => Find(name, false);
/// <summary>
/// <para>[To be supplied.]</para>
@@ -134,9 +122,9 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- EnsureSize(_propCount + 1);
- _properties[_propCount++] = value;
- return _propCount - 1;
+ EnsureSize(Count + 1);
+ _properties[Count++] = value;
+ return Count - 1;
}
/// <summary>
@@ -149,7 +137,7 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- _propCount = 0;
+ Count = 0;
_cachedFoundProperties = null;
}
@@ -199,7 +187,7 @@ namespace System.ComponentModel
if (_properties.Length == 0)
{
- _propCount = 0;
+ Count = 0;
_properties = new PropertyDescriptor[sizeNeeded];
return;
}
@@ -208,7 +196,7 @@ namespace System.ComponentModel
int newSize = Math.Max(sizeNeeded, _properties.Length * 2);
PropertyDescriptor[] newProps = new PropertyDescriptor[newSize];
- Array.Copy(_properties, 0, newProps, 0, _propCount);
+ Array.Copy(_properties, 0, newProps, 0, Count);
_properties = newProps;
}
@@ -246,7 +234,7 @@ namespace System.ComponentModel
// Now start walking from where we last left off, filling
// the cache as we go.
//
- for (int i = 0; i < _propCount; i++)
+ for (int i = 0; i < Count; i++)
{
if (ignoreCase)
{
@@ -277,7 +265,7 @@ namespace System.ComponentModel
/// </summary>
public int IndexOf(PropertyDescriptor value)
{
- return Array.IndexOf(_properties, value, 0, _propCount);
+ return Array.IndexOf(_properties, value, 0, Count);
}
/// <summary>
@@ -290,13 +278,13 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- EnsureSize(_propCount + 1);
- if (index < _propCount)
+ EnsureSize(Count + 1);
+ if (index < Count)
{
- Array.Copy(_properties, index, _properties, index + 1, _propCount - index);
+ Array.Copy(_properties, index, _properties, index + 1, Count - index);
}
_properties[index] = value;
- _propCount++;
+ Count++;
}
/// <summary>
@@ -327,12 +315,12 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- if (index < _propCount - 1)
+ if (index < Count - 1)
{
- Array.Copy(_properties, index + 1, _properties, index, _propCount - index - 1);
+ Array.Copy(_properties, index + 1, _properties, index, Count - index - 1);
}
- _properties[_propCount - 1] = null;
- _propCount--;
+ _properties[Count - 1] = null;
+ Count--;
}
/// <summary>
@@ -343,7 +331,7 @@ namespace System.ComponentModel
/// </summary>
public virtual PropertyDescriptorCollection Sort()
{
- return new PropertyDescriptorCollection(_properties, _propCount, _namedSort, _comparer);
+ return new PropertyDescriptorCollection(_properties, Count, _namedSort, _comparer);
}
@@ -355,7 +343,7 @@ namespace System.ComponentModel
/// </summary>
public virtual PropertyDescriptorCollection Sort(string[] names)
{
- return new PropertyDescriptorCollection(_properties, _propCount, names, _comparer);
+ return new PropertyDescriptorCollection(_properties, Count, names, _comparer);
}
/// <summary>
@@ -366,7 +354,7 @@ namespace System.ComponentModel
/// </summary>
public virtual PropertyDescriptorCollection Sort(string[] names, IComparer comparer)
{
- return new PropertyDescriptorCollection(_properties, _propCount, names, comparer);
+ return new PropertyDescriptorCollection(_properties, Count, names, comparer);
}
/// <summary>
@@ -377,7 +365,7 @@ namespace System.ComponentModel
/// </summary>
public virtual PropertyDescriptorCollection Sort(IComparer comparer)
{
- return new PropertyDescriptorCollection(_properties, _propCount, _namedSort, comparer);
+ return new PropertyDescriptorCollection(_properties, Count, _namedSort, comparer);
}
/// <summary>
@@ -397,7 +385,7 @@ namespace System.ComponentModel
if (names != null && names.Length > 0)
{
- ArrayList propArrayList = new ArrayList(_properties);
+ List<PropertyDescriptor> propList = new List<PropertyDescriptor>(_properties);
int foundCount = 0;
int propCount = _properties.Length;
@@ -405,7 +393,7 @@ namespace System.ComponentModel
{
for (int j = 0; j < propCount; j++)
{
- PropertyDescriptor currentProp = (PropertyDescriptor)propArrayList[j];
+ PropertyDescriptor currentProp = propList[j];
// Found a matching property. Here, we add it to our array. We also
// mark it as null in our array list so we don't add it twice later.
@@ -413,7 +401,7 @@ namespace System.ComponentModel
if (currentProp != null && currentProp.Name.Equals(names[i]))
{
_properties[foundCount++] = currentProp;
- propArrayList[j] = null;
+ propList[j] = null;
break;
}
}
@@ -426,9 +414,9 @@ namespace System.ComponentModel
//
for (int i = 0; i < propCount; i++)
{
- if (propArrayList[i] != null)
+ if (propList[i] != null)
{
- _properties[foundCount++] = (PropertyDescriptor)propArrayList[i];
+ _properties[foundCount++] = propList[i];
}
}
@@ -462,40 +450,22 @@ namespace System.ComponentModel
{
EnsurePropsOwned();
// we can only return an enumerator on the props we actually have...
- if (_properties.Length != _propCount)
+ if (_properties.Length != Count)
{
- PropertyDescriptor[] enumProps = new PropertyDescriptor[_propCount];
- Array.Copy(_properties, 0, enumProps, 0, _propCount);
+ PropertyDescriptor[] enumProps = new PropertyDescriptor[Count];
+ Array.Copy(_properties, 0, enumProps, 0, Count);
return enumProps.GetEnumerator();
}
return _properties.GetEnumerator();
}
/// <internalonly/>
- bool ICollection.IsSynchronized
- {
- get
- {
- return false;
- }
- }
+ bool ICollection.IsSynchronized => false;
/// <internalonly/>
- object ICollection.SyncRoot
- {
- get
- {
- return null;
- }
- }
+ object ICollection.SyncRoot => null;
- int ICollection.Count
- {
- get
- {
- return Count;
- }
- }
+ int ICollection.Count => Count;
void IList.Clear()
{
@@ -546,22 +516,10 @@ namespace System.ComponentModel
}
/// <internalonly/>
- bool IDictionary.IsFixedSize
- {
- get
- {
- return _readOnly;
- }
- }
+ bool IDictionary.IsFixedSize => _readOnly;
/// <internalonly/>
- bool IDictionary.IsReadOnly
- {
- get
- {
- return _readOnly;
- }
- }
+ bool IDictionary.IsReadOnly => _readOnly;
/// <internalonly/>
object IDictionary.this[object key]
@@ -593,14 +551,14 @@ namespace System.ComponentModel
{
index = (int)key;
- if (index < 0 || index >= _propCount)
+ if (index < 0 || index >= Count)
{
throw new IndexOutOfRangeException();
}
}
else if (key is string)
{
- for (int i = 0; i < _propCount; i++)
+ for (int i = 0; i < Count; i++)
{
if (_properties[i].Name.Equals((string)key))
{
@@ -635,8 +593,8 @@ namespace System.ComponentModel
{
get
{
- string[] keys = new string[_propCount];
- for (int i = 0; i < _propCount; i++)
+ string[] keys = new string[Count];
+ for (int i = 0; i < Count; i++)
{
keys[i] = _properties[i].Name;
}
@@ -651,10 +609,10 @@ namespace System.ComponentModel
{
// we can only return an enumerator on the props we actually have...
//
- if (_properties.Length != _propCount)
+ if (_properties.Length != Count)
{
- PropertyDescriptor[] newProps = new PropertyDescriptor[_propCount];
- Array.Copy(_properties, 0, newProps, 0, _propCount);
+ PropertyDescriptor[] newProps = new PropertyDescriptor[Count];
+ Array.Copy(_properties, 0, newProps, 0, Count);
return newProps;
}
else
@@ -702,22 +660,10 @@ namespace System.ComponentModel
}
/// <internalonly/>
- bool IList.IsReadOnly
- {
- get
- {
- return _readOnly;
- }
- }
+ bool IList.IsReadOnly => _readOnly;
/// <internalonly/>
- bool IList.IsFixedSize
- {
- get
- {
- return _readOnly;
- }
- }
+ bool IList.IsFixedSize => _readOnly;
/// <internalonly/>
void IList.Remove(object value)
@@ -739,7 +685,7 @@ namespace System.ComponentModel
throw new NotSupportedException();
}
- if (index >= _propCount)
+ if (index >= Count)
{
throw new IndexOutOfRangeException();
}
@@ -765,13 +711,7 @@ namespace System.ComponentModel
_owner = owner;
}
- public object Current
- {
- get
- {
- return Entry;
- }
- }
+ public object Current => Entry;
public DictionaryEntry Entry
{
@@ -782,21 +722,9 @@ namespace System.ComponentModel
}
}
- public object Key
- {
- get
- {
- return _owner[_index].Name;
- }
- }
+ public object Key => _owner[_index].Name;
- public object Value
- {
- get
- {
- return _owner[_index].Name;
- }
- }
+ public object Value => _owner[_index].Name;
public bool MoveNext()
{
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ProvidePropertyAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ProvidePropertyAttribute.cs
index 436a0edf5f..655ba38578 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ProvidePropertyAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ProvidePropertyAttribute.cs
@@ -11,16 +11,13 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class ProvidePropertyAttribute : Attribute
{
- private readonly string _propertyName;
- private readonly string _receiverTypeName;
-
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.ProvidePropertyAttribute'/> class.</para>
/// </summary>
public ProvidePropertyAttribute(string propertyName, Type receiverType)
{
- _propertyName = propertyName;
- _receiverTypeName = receiverType.AssemblyQualifiedName;
+ PropertyName = propertyName;
+ ReceiverTypeName = receiverType.AssemblyQualifiedName;
}
/// <summary>
@@ -28,8 +25,8 @@ namespace System.ComponentModel
/// </summary>
public ProvidePropertyAttribute(string propertyName, string receiverTypeName)
{
- _propertyName = propertyName;
- _receiverTypeName = receiverTypeName;
+ PropertyName = propertyName;
+ ReceiverTypeName = receiverTypeName;
}
/// <summary>
@@ -37,26 +34,14 @@ namespace System.ComponentModel
/// Gets the name of a property that this class provides.
/// </para>
/// </summary>
- public string PropertyName
- {
- get
- {
- return _propertyName;
- }
- }
+ public string PropertyName { get; }
/// <summary>
/// <para>
/// Gets the name of the data type this property can extend
/// </para>
/// </summary>
- public string ReceiverTypeName
- {
- get
- {
- return _receiverTypeName;
- }
- }
+ public string ReceiverTypeName { get; }
public override bool Equals(object obj)
{
@@ -67,21 +52,15 @@ namespace System.ComponentModel
ProvidePropertyAttribute other = obj as ProvidePropertyAttribute;
- return (other != null) && other._propertyName == _propertyName && other._receiverTypeName == _receiverTypeName;
+ return (other != null) && other.PropertyName == PropertyName && other.ReceiverTypeName == ReceiverTypeName;
}
public override int GetHashCode()
{
- return _propertyName.GetHashCode() ^ _receiverTypeName.GetHashCode();
+ return PropertyName.GetHashCode() ^ ReceiverTypeName.GetHashCode();
}
- public override object TypeId
- {
- get
- {
- return base.GetType().FullName + _propertyName;
- }
- }
+ public override object TypeId => base.GetType().FullName + PropertyName;
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RecommendedAsConfigurableAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RecommendedAsConfigurableAttribute.cs
index 6a77e02f86..363e0a036b 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RecommendedAsConfigurableAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RecommendedAsConfigurableAttribute.cs
@@ -16,8 +16,6 @@ namespace System.ComponentModel
[Obsolete("Use System.ComponentModel.SettingsBindableAttribute instead to work with the new settings model.")]
public class RecommendedAsConfigurableAttribute : Attribute
{
- private bool _recommendedAsConfigurable = false;
-
/// <summary>
/// <para>
/// Initializes a new instance of
@@ -26,20 +24,14 @@ namespace System.ComponentModel
/// </summary>
public RecommendedAsConfigurableAttribute(bool recommendedAsConfigurable)
{
- _recommendedAsConfigurable = recommendedAsConfigurable;
+ RecommendedAsConfigurable = recommendedAsConfigurable;
}
/// <summary>
/// <para>Gets a value indicating whether the property this
/// attribute is bound to can be used as an application setting.</para>
/// </summary>
- public bool RecommendedAsConfigurable
- {
- get
- {
- return _recommendedAsConfigurable;
- }
- }
+ public bool RecommendedAsConfigurable { get; }
/// <summary>
/// <para>
@@ -77,7 +69,7 @@ namespace System.ComponentModel
RecommendedAsConfigurableAttribute other = obj as RecommendedAsConfigurableAttribute;
- return other != null && other.RecommendedAsConfigurable == _recommendedAsConfigurable;
+ return other != null && other.RecommendedAsConfigurable == RecommendedAsConfigurable;
}
/// <summary>
@@ -95,7 +87,7 @@ namespace System.ComponentModel
/// </summary>
public override bool IsDefaultAttribute()
{
- return !_recommendedAsConfigurable;
+ return !RecommendedAsConfigurable;
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReferenceConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReferenceConverter.cs
index 70b8e9ee06..dc56e81290 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReferenceConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReferenceConverter.cs
@@ -4,6 +4,7 @@
using Microsoft.Win32;
using System.Collections;
+using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Globalization;
@@ -104,16 +105,13 @@ namespace System.ComponentModel
{
// Try the reference service first.
//
- if (context != null)
+ IReferenceService refSvc = (IReferenceService) context?.GetService(typeof(IReferenceService));
+ if (refSvc != null)
{
- IReferenceService refSvc = (IReferenceService)context.GetService(typeof(IReferenceService));
- if (refSvc != null)
+ string name = refSvc.GetName(value);
+ if (name != null)
{
- string name = refSvc.GetName(value);
- if (name != null)
- {
- return name;
- }
+ return name;
}
}
@@ -123,13 +121,10 @@ namespace System.ComponentModel
{
IComponent comp = (IComponent)value;
ISite site = comp.Site;
- if (site != null)
+ string name = site?.Name;
+ if (name != null)
{
- string name = site.Name;
- if (name != null)
- {
- return name;
- }
+ return name;
}
}
@@ -152,7 +147,7 @@ namespace System.ComponentModel
if (context != null)
{
- ArrayList list = new ArrayList();
+ List<object> list = new List<object>();
list.Add(null);
// Try the reference service first.
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectEventDescriptor.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectEventDescriptor.cs
index 01fd0321d7..5a79bff3ad 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectEventDescriptor.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectEventDescriptor.cs
@@ -66,7 +66,7 @@ namespace System.ComponentModel
private MethodInfo _addMethod; // the method to use when adding an event
private MethodInfo _removeMethod; // the method to use when removing an event
private EventInfo _realEvent; // actual event info... may be null
- private bool _filledMethods = false; // did we already call FillMethods() once?
+ private bool _filledMethods; // did we already call FillMethods() once?
/// <summary>
/// This is the main constructor for an ReflectEventDescriptor.
@@ -82,7 +82,7 @@ namespace System.ComponentModel
{
throw new ArgumentException(SR.Format(SR.ErrorInvalidEventType, name));
}
- Debug.Assert(type.GetTypeInfo().IsSubclassOf(typeof(Delegate)), "Not a valid ReflectEvent: " + componentClass.FullName + "." + name + " " + type.FullName);
+ Debug.Assert(type.GetTypeInfo().IsSubclassOf(typeof(Delegate)), $"Not a valid ReflectEvent: {componentClass.FullName}. {name} {type.FullName}");
_componentClass = componentClass;
_type = type;
}
@@ -120,13 +120,7 @@ namespace System.ComponentModel
/// <summary>
/// Retrieves the type of the component this EventDescriptor is bound to.
/// </summary>
- public override Type ComponentType
- {
- get
- {
- return _componentClass;
- }
- }
+ public override Type ComponentType => _componentClass;
/// <summary>
/// Retrieves the type of the delegate for this event.
@@ -143,13 +137,7 @@ namespace System.ComponentModel
/// <summary>
/// Indicates whether the delegate type for this event is a multicast delegate.
/// </summary>
- public override bool IsMulticast
- {
- get
- {
- return (typeof(MulticastDelegate)).IsAssignableFrom(EventType);
- }
- }
+ public override bool IsMulticast => (typeof(MulticastDelegate)).IsAssignableFrom(EventType);
/// <summary>
/// This adds the delegate value as a listener to when this event is fired
@@ -211,10 +199,7 @@ namespace System.ComponentModel
// Now notify the change service that the change was successful.
//
- if (changeService != null)
- {
- changeService.OnComponentChanged(component, this, null, value);
- }
+ changeService?.OnComponentChanged(component, this, null, value);
}
}
@@ -249,10 +234,10 @@ namespace System.ComponentModel
}
else
{
- Debug.Assert(_removeMethod != null, "Null remove method for " + Name);
+ Debug.Assert(_removeMethod != null, $"Null remove method for {Name}");
FillSingleMethodAttribute(_removeMethod, attributes);
- Debug.Assert(_addMethod != null, "Null remove method for " + Name);
+ Debug.Assert(_addMethod != null, $"Null remove method for {Name}");
FillSingleMethodAttribute(_addMethod, attributes);
}
@@ -379,7 +364,7 @@ namespace System.ComponentModel
_removeMethod = FindMethod(_componentClass, "RemoveOn" + Name, argsType, typeof(void));
if (_addMethod == null || _removeMethod == null)
{
- Debug.Fail("Missing event accessors for " + _componentClass.FullName + "." + Name);
+ Debug.Fail($"Missing event accessors for {_componentClass.FullName}. {Name}");
throw new ArgumentException(SR.Format(SR.ErrorMissingEventAccessors, Name));
}
}
@@ -500,10 +485,7 @@ namespace System.ComponentModel
// Now notify the change service that the change was successful.
//
- if (changeService != null)
- {
- changeService.OnComponentChanged(component, this, null, value);
- }
+ changeService?.OnComponentChanged(component, this, null, value);
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs
index 267e60d19b..d972501412 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs
@@ -90,12 +90,12 @@ namespace System.ComponentModel
{
if (type == null)
{
- Debug.WriteLine("type == null, name == " + name);
+ Debug.WriteLine($"type == null, name == {name}");
throw new ArgumentException(string.Format(SR.ErrorInvalidPropertyType, name));
}
if (componentClass == null)
{
- Debug.WriteLine("componentClass == null, name == " + name);
+ Debug.WriteLine($"componentClass == null, name == {name}");
throw new ArgumentException(string.Format(SR.InvalidNullArgument, nameof(componentClass)));
}
_type = type;
@@ -103,7 +103,7 @@ namespace System.ComponentModel
}
catch (Exception t)
{
- Debug.Fail("Property '" + name + "' on component " + componentClass.FullName + " failed to init.");
+ Debug.Fail($"Property '{name}' on component {componentClass.FullName} failed to init.");
Debug.Fail(t.ToString());
throw;
}
@@ -273,13 +273,7 @@ namespace System.ComponentModel
/// <summary>
/// Retrieves the type of the component this PropertyDescriptor is bound to.
/// </summary>
- public override Type ComponentType
- {
- get
- {
- return _componentClass;
- }
- }
+ public override Type ComponentType => _componentClass;
/// <summary>
/// Retrieves the default value for this property.
@@ -356,36 +350,18 @@ namespace System.ComponentModel
/// <summary>
/// Determines if this property is an extender property.
/// </summary>
- private bool IsExtender
- {
- get
- {
- return (_receiverType != null);
- }
- }
+ private bool IsExtender => (_receiverType != null);
/// <summary>
/// Indicates whether this property is read only.
/// </summary>
- public override bool IsReadOnly
- {
- get
- {
- return SetMethodValue == null || ((ReadOnlyAttribute)Attributes[typeof(ReadOnlyAttribute)]).IsReadOnly;
- }
- }
+ public override bool IsReadOnly => SetMethodValue == null || ((ReadOnlyAttribute)Attributes[typeof(ReadOnlyAttribute)]).IsReadOnly;
/// <summary>
/// Retrieves the type of the property.
/// </summary>
- public override Type PropertyType
- {
- get
- {
- return _type;
- }
- }
+ public override Type PropertyType => _type;
/// <summary>
/// Access to the reset method, if one exists for this property.
@@ -528,10 +504,7 @@ namespace System.ComponentModel
if (GetValueChangedHandler(component) == null)
{
EventDescriptor iPropChangedEvent = IPropChangedEventValue;
- if (iPropChangedEvent != null)
- {
- iPropChangedEvent.AddEventHandler(component, new PropertyChangedEventHandler(OnINotifyPropertyChanged));
- }
+ iPropChangedEvent?.AddEventHandler(component, new PropertyChangedEventHandler(OnINotifyPropertyChanged));
}
base.AddValueChanged(component, handler);
@@ -687,10 +660,7 @@ namespace System.ComponentModel
// Now notify the change service that the change was successful.
//
- if (changeService != null)
- {
- changeService.OnComponentChanged(component, notifyDesc, oldValue, value);
- }
+ changeService?.OnComponentChanged(component, notifyDesc, oldValue, value);
}
}
}
@@ -950,7 +920,7 @@ namespace System.ComponentModel
if (IsExtender)
{
- Debug.WriteLine("[" + Name + "]: ---> returning: null");
+ Debug.WriteLine($"[{Name}]: ---> returning: null");
return null;
}
@@ -969,13 +939,10 @@ namespace System.ComponentModel
{
string name = null;
IComponent comp = component as IComponent;
- if (comp != null)
+ ISite site = comp?.Site;
+ if (site?.Name != null)
{
- ISite site = comp.Site;
- if (site != null && site.Name != null)
- {
- name = site.Name;
- }
+ name = site.Name;
}
if (name == null)
@@ -988,11 +955,7 @@ namespace System.ComponentModel
t = t.InnerException;
}
- string message = t.Message;
- if (message == null)
- {
- message = t.GetType().Name;
- }
+ string message = t.Message ?? t.GetType().Name;
throw new TargetInvocationException(string.Format(SR.ErrorPropertyAccessorException, Name, name, message), t);
}
@@ -1054,10 +1017,7 @@ namespace System.ComponentModel
if (GetValueChangedHandler(component) == null)
{
EventDescriptor iPropChangedEvent = IPropChangedEventValue;
- if (iPropChangedEvent != null)
- {
- iPropChangedEvent.RemoveEventHandler(component, new PropertyChangedEventHandler(OnINotifyPropertyChanged));
- }
+ iPropChangedEvent?.RemoveEventHandler(component, new PropertyChangedEventHandler(OnINotifyPropertyChanged));
}
}
}
@@ -1216,10 +1176,7 @@ namespace System.ComponentModel
{
// Now notify the change service that the change was successful.
//
- if (changeService != null)
- {
- changeService.OnComponentChanged(component, this, oldValue, value);
- }
+ changeService?.OnComponentChanged(component, this, oldValue, value);
}
}
}
@@ -1273,12 +1230,6 @@ namespace System.ComponentModel
/// from direct calls made to PropertyDescriptor.SetValue (value=false). For example, the component may
/// implement the INotifyPropertyChanged interface, or may have an explicit '{name}Changed' event for this property.
/// </summary>
- public override bool SupportsChangeEvents
- {
- get
- {
- return IPropChangedEventValue != null || ChangedEventValue != null;
- }
- }
+ public override bool SupportsChangeEvents => IPropChangedEventValue != null || ChangedEventValue != null;
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs
index f6476b6841..7240b7e641 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs
@@ -36,13 +36,7 @@ namespace System.ComponentModel
/// This method returns true if the data cache in this reflection
/// type descriptor has data in it.
/// </summary>
- internal bool IsPopulated
- {
- get
- {
- return (_attributes != null) | (_events != null) | (_properties != null);
- }
- }
+ internal bool IsPopulated => (_attributes != null) | (_events != null) | (_properties != null);
/// <summary>
/// Retrieves custom attributes.
@@ -173,21 +167,11 @@ namespace System.ComponentModel
internal string GetComponentName(object instance)
{
IComponent comp = instance as IComponent;
- if (comp != null)
+ ISite site = comp?.Site;
+ if (site != null)
{
- ISite site = comp.Site;
- if (site != null)
- {
- INestedSite nestedSite = site as INestedSite;
- if (nestedSite != null)
- {
- return nestedSite.FullName;
- }
- else
- {
- return site.Name;
- }
- }
+ INestedSite nestedSite = site as INestedSite;
+ return (nestedSite?.FullName) ?? site.Name;
}
return null;
@@ -387,7 +371,7 @@ namespace System.ComponentModel
//
if (editor != null && !editorBaseType.GetTypeInfo().IsInstanceOfType(editor))
{
- Debug.Fail("Editor " + editor.GetType().FullName + " is not an instance of " + editorBaseType.FullName + " but it is in that base types table.");
+ Debug.Fail($"Editor {editor.GetType().FullName} is not an instance of {editorBaseType.FullName} but it is in that base types table.");
editor = null;
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs
index f1b40d6ab1..39358a8fef 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections;
+using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Linq;
@@ -62,7 +63,6 @@ namespace System.ComponentModel
// These are keys we stuff into our object cache. We use this
// cache data to store extender provider info for an object.
//
- private static readonly Guid s_extenderProviderKey = Guid.NewGuid();
private static readonly Guid s_extenderPropertiesKey = Guid.NewGuid();
private static readonly Guid s_extenderProviderPropertiesKey = Guid.NewGuid();
@@ -78,16 +78,10 @@ namespace System.ComponentModel
};
- internal static Guid ExtenderProviderKey
- {
- get
- {
- return s_extenderProviderKey;
- }
- }
+ internal static Guid ExtenderProviderKey { get; } = Guid.NewGuid();
- private static object s_internalSyncObject = new object();
+ private static readonly object s_internalSyncObject = new object();
/// <summary>
/// Creates a new ReflectTypeDescriptionProvider. The type is the
/// type we will obtain type information for.
@@ -228,12 +222,7 @@ namespace System.ComponentModel
obj = objectType.GetTypeInfo().GetConstructor(argTypes)?.Invoke(args);
}
- if (obj == null)
- {
- obj = Activator.CreateInstance(objectType, args);
- }
-
- return obj;
+ return obj ?? Activator.CreateInstance(objectType, args);
}
@@ -515,7 +504,7 @@ namespace System.ComponentModel
// Unlike normal properties, it is fine for there to be properties with
// duplicate names here.
//
- ArrayList propertyList = null;
+ List<PropertyDescriptor> propertyList = null;
for (int idx = 0; idx < extenders.Length; idx++)
{
@@ -523,7 +512,7 @@ namespace System.ComponentModel
if (propertyList == null)
{
- propertyList = new ArrayList(propertyArray.Length * extenders.Length);
+ propertyList = new List<PropertyDescriptor>(propertyArray.Length * extenders.Length);
}
for (int propIdx = 0; propIdx < propertyArray.Length; propIdx++)
@@ -531,7 +520,7 @@ namespace System.ComponentModel
PropertyDescriptor prop = propertyArray[propIdx];
ExtenderProvidedPropertyAttribute eppa = prop.Attributes[typeof(ExtenderProvidedPropertyAttribute)] as ExtenderProvidedPropertyAttribute;
- Debug.Assert(eppa != null, "Extender property " + prop.Name + " has no provider attribute. We will skip it.");
+ Debug.Assert(eppa != null, $"Extender property {prop.Name} has no provider attribute. We will skip it.");
if (eppa != null)
{
Type receiverType = eppa.ReceiverType;
@@ -628,7 +617,7 @@ namespace System.ComponentModel
if (cache != null)
{
- existingExtenders = cache[s_extenderProviderKey] as IExtenderProvider[];
+ existingExtenders = cache[ExtenderProviderKey] as IExtenderProvider[];
}
if (existingExtenders == null)
@@ -703,10 +692,9 @@ namespace System.ComponentModel
}
else if (extenderCount > 0)
{
- IEnumerator componentEnum = components.GetEnumerator();
- while (componentEnum.MoveNext())
+ foreach (var component in components)
{
- IExtenderProvider p = componentEnum.Current as IExtenderProvider;
+ IExtenderProvider p = component as IExtenderProvider;
if (p != null && ((curIdx < maxCanExtendResults && (canExtend & ((UInt64)1 << curIdx)) != 0) ||
(curIdx >= maxCanExtendResults && p.CanExtend(instance))))
@@ -723,7 +711,7 @@ namespace System.ComponentModel
if (cache != null)
{
- cache[s_extenderProviderKey] = currentExtenders;
+ cache[ExtenderProviderKey] = currentExtenders;
cache.Remove(s_extenderPropertiesKey);
}
}
@@ -765,13 +753,10 @@ namespace System.ComponentModel
public override string GetFullComponentName(object component)
{
IComponent comp = component as IComponent;
- if (comp != null)
+ INestedSite ns = comp?.Site as INestedSite;
+ if (ns != null)
{
- INestedSite ns = comp.Site as INestedSite;
- if (ns != null)
- {
- return ns.FullName;
- }
+ return ns.FullName;
}
return TypeDescriptor.GetComponentName(component);
@@ -783,7 +768,7 @@ namespace System.ComponentModel
/// </summary>
internal Type[] GetPopulatedTypes(Module module)
{
- ArrayList typeList = new ArrayList(); ;
+ List<Type> typeList = new List<Type>();
// Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations.
IDictionaryEnumerator e = _typeData.GetEnumerator();
@@ -799,7 +784,7 @@ namespace System.ComponentModel
}
}
- return (Type[])typeList.ToArray(typeof(Type));
+ return typeList.ToArray();
}
/// <summary>
@@ -1142,7 +1127,7 @@ namespace System.ComponentModel
if (extendedProperties == null)
{
AttributeCollection attributes = TypeDescriptor.GetAttributes(providerType);
- ArrayList extendedList = new ArrayList(attributes.Count);
+ List<ReflectPropertyDescriptor> extendedList = new List<ReflectPropertyDescriptor>(attributes.Count);
foreach (Attribute attr in attributes)
{
@@ -1279,7 +1264,7 @@ namespace System.ComponentModel
properties = newProperties;
}
- Debug.Assert(!properties.Any(dbgProp => dbgProp == null), "Holes in property array for type " + type);
+ Debug.Assert(!properties.Any(dbgProp => dbgProp == null), $"Holes in property array for type {type}");
s_propertyCache[type] = properties;
}
@@ -1296,10 +1281,7 @@ namespace System.ComponentModel
internal void Refresh(Type type)
{
ReflectedTypeData td = GetTypeData(type, false);
- if (td != null)
- {
- td.Refresh();
- }
+ td?.Refresh();
}
/// <summary>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RefreshEventArgs.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RefreshEventArgs.cs
index 46abce6055..659c36fee1 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RefreshEventArgs.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RefreshEventArgs.cs
@@ -11,9 +11,6 @@ namespace System.ComponentModel
/// </summary>
public class RefreshEventArgs : EventArgs
{
- private readonly object _componentChanged;
- private readonly Type _typeChanged;
-
/// <summary>
/// <para>
/// Initializes a new instance of the <see cref='System.ComponentModel.RefreshEventArgs'/> class with
@@ -22,8 +19,8 @@ namespace System.ComponentModel
/// </summary>
public RefreshEventArgs(object componentChanged)
{
- _componentChanged = componentChanged;
- _typeChanged = componentChanged.GetType();
+ ComponentChanged = componentChanged;
+ TypeChanged = componentChanged.GetType();
}
/// <summary>
@@ -34,7 +31,7 @@ namespace System.ComponentModel
/// </summary>
public RefreshEventArgs(Type typeChanged)
{
- _typeChanged = typeChanged;
+ TypeChanged = typeChanged;
}
/// <summary>
@@ -42,25 +39,13 @@ namespace System.ComponentModel
/// Gets the component that has changed its properties, events, or extenders.
/// </para>
/// </summary>
- public object ComponentChanged
- {
- get
- {
- return _componentChanged;
- }
- }
+ public object ComponentChanged { get; }
/// <summary>
/// <para>
/// Gets the type that has changed its properties, or events.
/// </para>
/// </summary>
- public Type TypeChanged
- {
- get
- {
- return _typeChanged;
- }
- }
+ public Type TypeChanged { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RunInstallerAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RunInstallerAttribute.cs
index 4f1939d26e..7d6e3def37 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RunInstallerAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/RunInstallerAttribute.cs
@@ -15,9 +15,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Class)]
public class RunInstallerAttribute : Attribute
{
- private bool _runInstaller;
-
-
/// <summary>
/// <para>
/// Initializes a new instance of
@@ -26,7 +23,7 @@ namespace System.ComponentModel
/// </summary>
public RunInstallerAttribute(bool runInstaller)
{
- _runInstaller = runInstaller;
+ RunInstaller = runInstaller;
}
@@ -36,13 +33,7 @@ namespace System.ComponentModel
/// invoked during installation of an assembly.
/// </para>
/// </summary>
- public bool RunInstaller
- {
- get
- {
- return _runInstaller;
- }
- }
+ public bool RunInstaller { get; }
/// <summary>
@@ -86,7 +77,7 @@ namespace System.ComponentModel
}
RunInstallerAttribute other = obj as RunInstallerAttribute;
- return other != null && other.RunInstaller == _runInstaller;
+ return other != null && other.RunInstaller == RunInstaller;
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SByteConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SByteConverter.cs
index ed16747f96..55e7596bff 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SByteConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SByteConverter.cs
@@ -16,13 +16,7 @@ namespace System.ComponentModel
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(SByte);
- }
- }
+ internal override Type TargetType => typeof(sbyte);
/// <summary>
/// Convert the given value to a string using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SettingsBindableAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SettingsBindableAttribute.cs
index 751900d676..c5adb7e0aa 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SettingsBindableAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SettingsBindableAttribute.cs
@@ -25,23 +25,15 @@ namespace System.ComponentModel
/// </summary>
public static readonly SettingsBindableAttribute No = new SettingsBindableAttribute(false);
- private bool _bindable = false;
-
public SettingsBindableAttribute(bool bindable)
{
- _bindable = bindable;
+ Bindable = bindable;
}
/// <summary>
/// Gets a value indicating whether a property is appropriate to bind settings to.
/// </summary>
- public bool Bindable
- {
- get
- {
- return _bindable;
- }
- }
+ public bool Bindable { get; }
public override bool Equals(object obj)
{
@@ -52,7 +44,7 @@ namespace System.ComponentModel
if (obj != null && obj is SettingsBindableAttribute)
{
- return (((SettingsBindableAttribute)obj).Bindable == _bindable);
+ return (((SettingsBindableAttribute)obj).Bindable == Bindable);
}
return false;
@@ -60,7 +52,7 @@ namespace System.ComponentModel
public override int GetHashCode()
{
- return _bindable.GetHashCode();
+ return Bindable.GetHashCode();
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SingleConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SingleConverter.cs
index 78ccbdbe57..12e3c2e099 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SingleConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/SingleConverter.cs
@@ -16,24 +16,12 @@ namespace System.ComponentModel
/// <summary>
/// Determines whether this editor will attempt to convert hex (0x or #) strings
/// </summary>
- internal override bool AllowHex
- {
- get
- {
- return false;
- }
- }
+ internal override bool AllowHex => false;
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(Single);
- }
- }
+ internal override Type TargetType => typeof(float);
/// <summary>
/// Convert the given value to a string using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ToolboxItemFilterAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ToolboxItemFilterAttribute.cs
index e598149f8e..9d88eb395b 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ToolboxItemFilterAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ToolboxItemFilterAttribute.cs
@@ -50,8 +50,6 @@ namespace System.ComponentModel
]
public sealed class ToolboxItemFilterAttribute : Attribute
{
- private ToolboxItemFilterType _filterType;
- private string _filterString;
private string _typeId;
/// <summary>
@@ -67,51 +65,27 @@ namespace System.ComponentModel
/// </summary>
public ToolboxItemFilterAttribute(string filterString, ToolboxItemFilterType filterType)
{
- if (filterString == null) filterString = String.Empty;
-
- _filterString = filterString;
- _filterType = filterType;
+ FilterString = filterString ?? string.Empty;
+ FilterType = filterType;
}
/// <summary>
/// Retrieves the filter string for this attribute. The filter string is a user-defined string that
/// is used to identify matching attributes.
/// </summary>
- public string FilterString
- {
- get
- {
- return _filterString;
- }
- }
+ public string FilterString { get; }
/// <summary>
/// Retrieves the filter type for this attribute. The filter type determines how the filter string should
/// be applied.
/// </summary>
- public ToolboxItemFilterType FilterType
- {
- get
- {
- return _filterType;
- }
- }
+ public ToolboxItemFilterType FilterType { get; }
/// <summary>
/// The unique identifier for this attribute. All ToolboxItemFilterAttributes with the same filter string
/// are considered the same, so they return the same TypeId.
/// </summary>
- public override object TypeId
- {
- get
- {
- if (_typeId == null)
- {
- _typeId = GetType().FullName + _filterString;
- }
- return _typeId;
- }
- }
+ public override object TypeId => _typeId ?? (_typeId = GetType().FullName + FilterString);
public override bool Equals(object obj)
{
@@ -127,7 +101,7 @@ namespace System.ComponentModel
public override int GetHashCode()
{
// No need to hash on filter type as well; there shouldn't be that many duplicates.
- return _filterString.GetHashCode();
+ return FilterString.GetHashCode();
}
public override bool Match(object obj)
@@ -150,7 +124,7 @@ namespace System.ComponentModel
public override string ToString()
{
- return _filterString + "," + Enum.GetName(typeof(ToolboxItemFilterType), _filterType);
+ return FilterString + "," + Enum.GetName(typeof(ToolboxItemFilterType), FilterType);
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs
index 48abd26d8c..1297b6d53c 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs
@@ -211,14 +211,7 @@ namespace System.ComponentModel
{
string valueTypeName;
- if (value == null)
- {
- valueTypeName = SR.Null;
- }
- else
- {
- valueTypeName = value.GetType().FullName;
- }
+ valueTypeName = value == null ? SR.Null : value.GetType().FullName;
throw new NotSupportedException(SR.Format(SR.ConvertFromException, GetType().Name, valueTypeName));
}
@@ -231,14 +224,7 @@ namespace System.ComponentModel
{
string valueTypeName;
- if (value == null)
- {
- valueTypeName = SR.Null;
- }
- else
- {
- valueTypeName = value.GetType().FullName;
- }
+ valueTypeName = value == null ? SR.Null : value.GetType().FullName;
throw new NotSupportedException(SR.Format(SR.ConvertToException, GetType().Name, valueTypeName, destinationType.FullName));
}
@@ -425,15 +411,12 @@ namespace System.ComponentModel
/// </summary>
protected abstract class SimplePropertyDescriptor : PropertyDescriptor
{
- private Type _componentType;
- private Type _propertyType;
-
/// <summary>
/// <para>
/// Initializes a new instance of the <see cref='System.ComponentModel.TypeConverter.SimplePropertyDescriptor'/> class.
/// </para>
/// </summary>
- protected SimplePropertyDescriptor(Type componentType, string name, Type propertyType) : this(componentType, name, propertyType, new Attribute[0])
+ protected SimplePropertyDescriptor(Type componentType, string name, Type propertyType) : this(componentType, name, propertyType, Array.Empty<Attribute>())
{
}
@@ -444,42 +427,24 @@ namespace System.ComponentModel
/// </summary>
protected SimplePropertyDescriptor(Type componentType, string name, Type propertyType, Attribute[] attributes) : base(name, attributes)
{
- _componentType = componentType;
- _propertyType = propertyType;
+ ComponentType = componentType;
+ PropertyType = propertyType;
}
/// <summary>
/// <para>Gets the type of the component this property description is bound to.</para>
/// </summary>
- public override Type ComponentType
- {
- get
- {
- return _componentType;
- }
- }
+ public override Type ComponentType { get; }
/// <summary>
/// <para>Gets a value indicating whether this property is read-only.</para>
/// </summary>
- public override bool IsReadOnly
- {
- get
- {
- return Attributes.Contains(ReadOnlyAttribute.Yes);
- }
- }
+ public override bool IsReadOnly => Attributes.Contains(ReadOnlyAttribute.Yes);
/// <summary>
/// <para>Gets the type of the property.</para>
/// </summary>
- public override Type PropertyType
- {
- get
- {
- return _propertyType;
- }
- }
+ public override Type PropertyType { get; }
/// <summary>
/// <para>
@@ -534,7 +499,7 @@ namespace System.ComponentModel
{
if (values == null)
{
- values = new object[0];
+ values = Array.Empty<object>();
}
Array a = values as Array;
@@ -615,26 +580,14 @@ namespace System.ComponentModel
/// Determines if this collection is synchronized. The ValidatorCollection is not synchronized for
/// speed. Also, since it is read-only, there is no need to synchronize it.
/// </summary>
- bool ICollection.IsSynchronized
- {
- get
- {
- return false;
- }
- }
+ bool ICollection.IsSynchronized => false;
/// <internalonly/>
/// <summary>
/// Retrieves the synchronization root for this collection. Because we are not synchronized,
/// this returns null.
/// </summary>
- object ICollection.SyncRoot
- {
- get
- {
- return null;
- }
- }
+ object ICollection.SyncRoot => null;
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverterAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverterAttribute.cs
index 9b6c029e85..37fd6ddb47 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverterAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverterAttribute.cs
@@ -13,8 +13,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.All)]
public sealed class TypeConverterAttribute : Attribute
{
- private readonly string _typeName;
-
/// <summary>
/// <para>
/// Specifies the type to use as a converter for the object this attribute is bound to. This
@@ -30,7 +28,7 @@ namespace System.ComponentModel
/// </summary>
public TypeConverterAttribute()
{
- _typeName = string.Empty;
+ ConverterTypeName = string.Empty;
}
/// <summary>
@@ -41,7 +39,7 @@ namespace System.ComponentModel
/// </summary>
public TypeConverterAttribute(Type type)
{
- _typeName = type.AssemblyQualifiedName;
+ ConverterTypeName = type.AssemblyQualifiedName;
}
/// <summary>
@@ -52,7 +50,7 @@ namespace System.ComponentModel
/// </summary>
public TypeConverterAttribute(string typeName)
{
- _typeName = typeName;
+ ConverterTypeName = typeName;
}
/// <summary>
@@ -61,23 +59,17 @@ namespace System.ComponentModel
/// the object this attribute is bound to.
/// </para>
/// </summary>
- public string ConverterTypeName
- {
- get
- {
- return _typeName;
- }
- }
+ public string ConverterTypeName { get; }
public override bool Equals(object obj)
{
TypeConverterAttribute other = obj as TypeConverterAttribute;
- return (other != null) && other.ConverterTypeName == _typeName;
+ return (other != null) && other.ConverterTypeName == ConverterTypeName;
}
public override int GetHashCode()
{
- return _typeName.GetHashCode();
+ return ConverterTypeName.GetHashCode();
}
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs
index 363cc76407..8b4a23879d 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs
@@ -79,12 +79,7 @@ namespace System.ComponentModel
/// </summary>
public virtual IDictionary GetCache(object instance)
{
- if (_parent != null)
- {
- return _parent.GetCache(instance);
- }
-
- return null;
+ return _parent?.GetCache(instance);
}
/// <summary>
@@ -108,12 +103,7 @@ namespace System.ComponentModel
return _parent.GetExtendedTypeDescriptor(instance);
}
- if (_emptyDescriptor == null)
- {
- _emptyDescriptor = new EmptyCustomTypeDescriptor();
- }
-
- return _emptyDescriptor;
+ return _emptyDescriptor ?? (_emptyDescriptor = new EmptyCustomTypeDescriptor());
}
protected internal virtual IExtenderProvider[] GetExtenderProviders(object instance)
@@ -276,12 +266,7 @@ namespace System.ComponentModel
return _parent.GetTypeDescriptor(objectType, instance);
}
- if (_emptyDescriptor == null)
- {
- _emptyDescriptor = new EmptyCustomTypeDescriptor();
- }
-
- return _emptyDescriptor;
+ return _emptyDescriptor ?? (_emptyDescriptor = new EmptyCustomTypeDescriptor());
}
/// <summary>
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProviderAttribute.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProviderAttribute.cs
index 09911bfb34..6d47503f13 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProviderAttribute.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProviderAttribute.cs
@@ -9,8 +9,6 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public sealed class TypeDescriptionProviderAttribute : Attribute
{
- private readonly string _typeName;
-
/// <summary>
/// Creates a new TypeDescriptionProviderAttribute object.
/// </summary>
@@ -21,7 +19,7 @@ namespace System.ComponentModel
throw new ArgumentNullException(nameof(typeName));
}
- _typeName = typeName;
+ TypeName = typeName;
}
/// <summary>
@@ -34,20 +32,14 @@ namespace System.ComponentModel
throw new ArgumentNullException(nameof(type));
}
- _typeName = type.AssemblyQualifiedName;
+ TypeName = type.AssemblyQualifiedName;
}
/// <summary>
/// The TypeName property returns the assembly qualified type name
/// for the type description provider.
/// </summary>
- public string TypeName
- {
- get
- {
- return _typeName;
- }
- }
+ public string TypeName { get; }
}
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
index b703048434..04e314754d 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
@@ -84,24 +84,12 @@ namespace System.ComponentModel
/// AddProvider methods to define a type description provider for interface types.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Advanced)]
- public static Type InterfaceType
- {
- get
- {
- return typeof(TypeDescriptorInterface);
- }
- }
+ public static Type InterfaceType => typeof(TypeDescriptorInterface);
/// <summary>
/// This value increments each time someone refreshes or changes metadata.
/// </summary>
- internal static int MetadataVersion
- {
- get
- {
- return s_metadataVersion;
- }
- }
+ internal static int MetadataVersion => s_metadataVersion;
/// <summary>
/// Occurs when Refreshed is raised for a component.
@@ -498,21 +486,13 @@ namespace System.ComponentModel
// See if the provider wants to offer a TypeDescriptionProvider to delegate to. This allows
// a caller to have complete control over all object instantiation.
- if (provider != null)
- {
- TypeDescriptionProvider p = provider.GetService(typeof(TypeDescriptionProvider)) as TypeDescriptionProvider;
- if (p != null)
- {
- instance = p.CreateInstance(provider, objectType, argTypes, args);
- }
- }
-
- if (instance == null)
+ TypeDescriptionProvider p = provider?.GetService(typeof(TypeDescriptionProvider)) as TypeDescriptionProvider;
+ if (p != null)
{
- instance = NodeFor(objectType).CreateInstance(provider, objectType, argTypes, args);
+ instance = p.CreateInstance(provider, objectType, argTypes, args);
}
- return instance;
+ return instance ?? NodeFor(objectType).CreateInstance(provider, objectType, argTypes, args);
}
/// <summary>
/// This dynamically binds a PropertyDescriptor to a type.
@@ -592,9 +572,9 @@ namespace System.ComponentModel
}
}
}
- else if (newMembers != null)
+ else
{
- newMembers.Add(members[idx]);
+ newMembers?.Add(members[idx]);
}
}
@@ -625,28 +605,25 @@ namespace System.ComponentModel
// Check our association table for a match.
//
Hashtable assocTable = s_associationTable;
- if (assocTable != null)
+ IList associations = (IList) assocTable?[primary];
+ if (associations != null)
{
- IList associations = (IList)assocTable[primary];
- if (associations != null)
+ lock (associations)
{
- lock (associations)
+ for (int idx = associations.Count - 1; idx >= 0; idx--)
{
- for (int idx = associations.Count - 1; idx >= 0; idx--)
+ // Look for an associated object that has a type that
+ // matches the given type.
+ //
+ WeakReference weakRef = (WeakReference)associations[idx];
+ object secondary = weakRef.Target;
+ if (secondary == null)
{
- // Look for an associated object that has a type that
- // matches the given type.
- //
- WeakReference weakRef = (WeakReference)associations[idx];
- object secondary = weakRef.Target;
- if (secondary == null)
- {
- associations.RemoveAt(idx);
- }
- else if (type.GetTypeInfo().IsInstanceOfType(secondary))
- {
- associatedObject = secondary;
- }
+ associations.RemoveAt(idx);
+ }
+ else if (type.GetTypeInfo().IsInstanceOfType(secondary))
+ {
+ associatedObject = secondary;
}
}
}
@@ -1209,28 +1186,25 @@ namespace System.ComponentModel
string suffix = null;
ExtenderProvidedPropertyAttribute exAttr = member.Attributes[typeof(ExtenderProvidedPropertyAttribute)] as ExtenderProvidedPropertyAttribute;
- if (exAttr != null)
+ IExtenderProvider prov = exAttr?.Provider;
+
+ if (prov != null)
{
- IExtenderProvider prov = exAttr.Provider;
+ string name = null;
+ IComponent component = prov as IComponent;
- if (prov != null)
+ if (component != null && component.Site != null)
{
- string name = null;
- IComponent component = prov as IComponent;
-
- if (component != null && component.Site != null)
- {
- name = component.Site.Name;
- }
-
- if (name == null || name.Length == 0)
- {
- int ci = System.Threading.Interlocked.Increment(ref s_collisionIndex) - 1;
- name = ci.ToString(CultureInfo.InvariantCulture);
- }
+ name = component.Site.Name;
+ }
- suffix = string.Format(CultureInfo.InvariantCulture, "_{0}", name);
+ if (name == null || name.Length == 0)
+ {
+ int ci = System.Threading.Interlocked.Increment(ref s_collisionIndex) - 1;
+ name = ci.ToString(CultureInfo.InvariantCulture);
}
+
+ suffix = string.Format(CultureInfo.InvariantCulture, "_{0}", name);
}
return suffix;
@@ -1548,11 +1522,8 @@ namespace System.ComponentModel
while (node == null)
{
- node = (TypeDescriptionNode)s_providerTypeTable[searchType];
- if (node == null)
- {
- node = (TypeDescriptionNode)s_providerTable[searchType];
- }
+ node = (TypeDescriptionNode)s_providerTypeTable[searchType] ??
+ (TypeDescriptionNode)s_providerTable[searchType];
if (node == null)
{
@@ -1720,8 +1691,7 @@ namespace System.ComponentModel
// In that case, we can remove the node
// altogether since no one is pointing to it.
- Type keyType = key as Type;
- if (keyType == null) keyType = key.GetType();
+ Type keyType = key as Type ?? key.GetType();
target.Provider = new DelegatingTypeDescriptionProvider(keyType.GetTypeInfo().BaseType);
}
@@ -1822,13 +1792,10 @@ namespace System.ComponentModel
IComponent component = instance as IComponent;
ITypeDescriptorFilterService componentFilter = null;
- if (component != null)
+ ISite site = component?.Site;
+ if (site != null)
{
- ISite site = component.Site;
- if (site != null)
- {
- componentFilter = site.GetService(typeof(ITypeDescriptorFilterService)) as ITypeDescriptorFilterService;
- }
+ componentFilter = site.GetService(typeof(ITypeDescriptorFilterService)) as ITypeDescriptorFilterService;
}
// If we have no filter, there is nothing for us to do.
@@ -2070,43 +2037,40 @@ namespace System.ComponentModel
// Next, if we were given a cache, see if it has accurate data.
//
- if (cache != null)
+ ICollection mergeCache = cache?[s_pipelineMergeKeys[pipelineType]] as ICollection;
+ if (mergeCache != null && mergeCache.Count == (primary.Count + secondary.Count))
{
- ICollection mergeCache = cache[s_pipelineMergeKeys[pipelineType]] as ICollection;
- if (mergeCache != null && mergeCache.Count == (primary.Count + secondary.Count))
- {
- // Walk the merge cache.
- IEnumerator mergeEnum = mergeCache.GetEnumerator();
- IEnumerator primaryEnum = primary.GetEnumerator();
- bool match = true;
+ // Walk the merge cache.
+ IEnumerator mergeEnum = mergeCache.GetEnumerator();
+ IEnumerator primaryEnum = primary.GetEnumerator();
+ bool match = true;
- while (primaryEnum.MoveNext() && mergeEnum.MoveNext())
+ while (primaryEnum.MoveNext() && mergeEnum.MoveNext())
+ {
+ if (primaryEnum.Current != mergeEnum.Current)
{
- if (primaryEnum.Current != mergeEnum.Current)
- {
- match = false;
- break;
- }
+ match = false;
+ break;
}
+ }
- if (match)
- {
- IEnumerator secondaryEnum = secondary.GetEnumerator();
+ if (match)
+ {
+ IEnumerator secondaryEnum = secondary.GetEnumerator();
- while (secondaryEnum.MoveNext() && mergeEnum.MoveNext())
+ while (secondaryEnum.MoveNext() && mergeEnum.MoveNext())
+ {
+ if (secondaryEnum.Current != mergeEnum.Current)
{
- if (secondaryEnum.Current != mergeEnum.Current)
- {
- match = false;
- break;
- }
+ match = false;
+ break;
}
}
+ }
- if (match)
- {
- return mergeCache;
- }
+ if (match)
+ {
+ return mergeCache;
}
}
@@ -2170,20 +2134,14 @@ namespace System.ComponentModel
// the JIT makes those changes is mostly theoretical
RefreshEventHandler handler = Volatile.Read(ref Refreshed);
- if (handler != null)
- {
- handler(new RefreshEventArgs(component));
- }
+ handler?.Invoke(new RefreshEventArgs(component));
}
private static void RaiseRefresh(Type type)
{
RefreshEventHandler handler = Volatile.Read(ref Refreshed);
- if (handler != null)
- {
- handler(new RefreshEventArgs(type));
- }
+ handler?.Invoke(new RefreshEventArgs(type));
}
/// <summary>
@@ -2436,13 +2394,7 @@ namespace System.ComponentModel
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
- public static Type ComObjectType
- {
- get
- {
- return typeof(TypeDescriptor.TypeDescriptorComObject);
- }
- }
+ public static Type ComObjectType => typeof(TypeDescriptor.TypeDescriptorComObject);
public static IDesigner CreateDesigner(IComponent component, Type designerBaseType)
{
@@ -2459,14 +2411,11 @@ namespace System.ComponentModel
{
ISite site = component.Site;
bool flag = false;
- if (site != null)
+ ITypeResolutionService typeResolutionService = (ITypeResolutionService) site?.GetService(typeof(ITypeResolutionService));
+ if (typeResolutionService != null)
{
- ITypeResolutionService typeResolutionService = (ITypeResolutionService)site.GetService(typeof(ITypeResolutionService));
- if (typeResolutionService != null)
- {
- flag = true;
- type = typeResolutionService.GetType(designerAttribute.DesignerTypeName);
- }
+ flag = true;
+ type = typeResolutionService.GetType(designerAttribute.DesignerTypeName);
}
if (!flag)
{
@@ -2499,11 +2448,7 @@ namespace System.ComponentModel
typeDescriptionNode = typeDescriptionNode.Next;
}
while (typeDescriptionNode != null && comNativeDescriptionProvider == null);
- if (comNativeDescriptionProvider != null)
- {
- return comNativeDescriptionProvider.Handler;
- }
- return null;
+ return comNativeDescriptionProvider?.Handler;
}
set
{
@@ -2539,24 +2484,21 @@ namespace System.ComponentModel
}
Hashtable assocTable = s_associationTable;
- if (assocTable != null)
+ IList associations = (IList) assocTable?[primary];
+ if (associations != null)
{
- IList associations = (IList)assocTable[primary];
- if (associations != null)
+ lock (associations)
{
- lock (associations)
+ for (int idx = associations.Count - 1; idx >= 0; idx--)
{
- for (int idx = associations.Count - 1; idx >= 0; idx--)
+ // Look for an associated object that has a type that
+ // matches the given type.
+ //
+ WeakReference weakRef = (WeakReference)associations[idx];
+ object secondaryItem = weakRef.Target;
+ if (secondaryItem == null || secondaryItem == secondary)
{
- // Look for an associated object that has a type that
- // matches the given type.
- //
- WeakReference weakRef = (WeakReference)associations[idx];
- object secondaryItem = weakRef.Target;
- if (secondaryItem == null || secondaryItem == secondary)
- {
- associations.RemoveAt(idx);
- }
+ associations.RemoveAt(idx);
}
}
}
@@ -2575,10 +2517,7 @@ namespace System.ComponentModel
}
Hashtable assocTable = s_associationTable;
- if (assocTable != null)
- {
- assocTable.Remove(primary);
- }
+ assocTable?.Remove(primary);
}
/// <summary>
@@ -3059,11 +2998,7 @@ namespace System.ComponentModel
/// </summary>
AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
- AttributeCollection attrs = _primary.GetAttributes();
- if (attrs == null)
- {
- attrs = _secondary.GetAttributes();
- }
+ AttributeCollection attrs = _primary.GetAttributes() ?? _secondary.GetAttributes();
Debug.Assert(attrs != null, "Someone should have handled this");
return attrs;
@@ -3074,11 +3009,7 @@ namespace System.ComponentModel
/// </summary>
string ICustomTypeDescriptor.GetClassName()
{
- string className = _primary.GetClassName();
- if (className == null)
- {
- className = _secondary.GetClassName();
- }
+ string className = _primary.GetClassName() ?? _secondary.GetClassName();
Debug.Assert(className != null, "Someone should have handled this");
return className;
@@ -3089,11 +3020,7 @@ namespace System.ComponentModel
/// </summary>
string ICustomTypeDescriptor.GetComponentName()
{
- string name = _primary.GetComponentName();
- if (name == null)
- {
- name = _secondary.GetComponentName();
- }
+ string name = _primary.GetComponentName() ?? _secondary.GetComponentName();
return name;
}
@@ -3103,11 +3030,7 @@ namespace System.ComponentModel
/// </summary>
TypeConverter ICustomTypeDescriptor.GetConverter()
{
- TypeConverter converter = _primary.GetConverter();
- if (converter == null)
- {
- converter = _secondary.GetConverter();
- }
+ TypeConverter converter = _primary.GetConverter() ?? _secondary.GetConverter();
Debug.Assert(converter != null, "Someone should have handled this");
return converter;
@@ -3118,11 +3041,7 @@ namespace System.ComponentModel
/// </summary>
EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{
- EventDescriptor evt = _primary.GetDefaultEvent();
- if (evt == null)
- {
- evt = _secondary.GetDefaultEvent();
- }
+ EventDescriptor evt = _primary.GetDefaultEvent() ?? _secondary.GetDefaultEvent();
return evt;
}
@@ -3132,11 +3051,7 @@ namespace System.ComponentModel
/// </summary>
PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{
- PropertyDescriptor prop = _primary.GetDefaultProperty();
- if (prop == null)
- {
- prop = _secondary.GetDefaultProperty();
- }
+ PropertyDescriptor prop = _primary.GetDefaultProperty() ?? _secondary.GetDefaultProperty();
return prop;
}
@@ -3151,11 +3066,7 @@ namespace System.ComponentModel
throw new ArgumentNullException(nameof(editorBaseType));
}
- object editor = _primary.GetEditor(editorBaseType);
- if (editor == null)
- {
- editor = _secondary.GetEditor(editorBaseType);
- }
+ object editor = _primary.GetEditor(editorBaseType) ?? _secondary.GetEditor(editorBaseType);
return editor;
}
@@ -3165,11 +3076,7 @@ namespace System.ComponentModel
/// </summary>
EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
- EventDescriptorCollection events = _primary.GetEvents();
- if (events == null)
- {
- events = _secondary.GetEvents();
- }
+ EventDescriptorCollection events = _primary.GetEvents() ?? _secondary.GetEvents();
Debug.Assert(events != null, "Someone should have handled this");
return events;
@@ -3180,11 +3087,7 @@ namespace System.ComponentModel
/// </summary>
EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
- EventDescriptorCollection events = _primary.GetEvents(attributes);
- if (events == null)
- {
- events = _secondary.GetEvents(attributes);
- }
+ EventDescriptorCollection events = _primary.GetEvents(attributes) ?? _secondary.GetEvents(attributes);
Debug.Assert(events != null, "Someone should have handled this");
return events;
@@ -3195,11 +3098,7 @@ namespace System.ComponentModel
/// </summary>
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
- PropertyDescriptorCollection properties = _primary.GetProperties();
- if (properties == null)
- {
- properties = _secondary.GetProperties();
- }
+ PropertyDescriptorCollection properties = _primary.GetProperties() ?? _secondary.GetProperties();
Debug.Assert(properties != null, "Someone should have handled this");
return properties;
@@ -3225,11 +3124,7 @@ namespace System.ComponentModel
/// </summary>
object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{
- object owner = _primary.GetPropertyOwner(pd);
- if (owner == null)
- {
- owner = _secondary.GetPropertyOwner(pd);
- }
+ object owner = _primary.GetPropertyOwner(pd) ?? _secondary.GetPropertyOwner(pd);
return owner;
}
@@ -3455,8 +3350,7 @@ namespace System.ComponentModel
ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
if (desc == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
- string name = desc.GetClassName();
- if (name == null) name = _instance.GetType().FullName;
+ string name = desc.GetClassName() ?? _instance.GetType().FullName;
return name;
}
@@ -3702,8 +3596,7 @@ namespace System.ComponentModel
ICustomTypeDescriptor desc = p.GetExtendedTypeDescriptor(_instance);
if (desc == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetExtendedTypeDescriptor"));
- object owner = desc.GetPropertyOwner(pd);
- if (owner == null) owner = _instance;
+ object owner = desc.GetPropertyOwner(pd) ?? _instance;
return owner;
}
}
@@ -3776,8 +3669,7 @@ namespace System.ComponentModel
{
ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
if (desc == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
- name = desc.GetClassName();
- if (name == null) name = _objectType.FullName;
+ name = desc.GetClassName() ?? _objectType.FullName;
}
return name;
@@ -4057,8 +3949,7 @@ namespace System.ComponentModel
{
ICustomTypeDescriptor desc = p.GetTypeDescriptor(_objectType, _instance);
if (desc == null) throw new InvalidOperationException(SR.Format(SR.TypeDescriptorProviderError, _node.Provider.GetType().FullName, "GetTypeDescriptor"));
- owner = desc.GetPropertyOwner(pd);
- if (owner == null) owner = _instance;
+ owner = desc.GetPropertyOwner(pd) ?? _instance;
}
return owner;
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt16Converter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt16Converter.cs
index c10be5cd9e..3de486cdbf 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt16Converter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt16Converter.cs
@@ -15,13 +15,7 @@ namespace System.ComponentModel
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(UInt16);
- }
- }
+ internal override Type TargetType => typeof(short);
/// <summary>
/// Convert the given value to a string using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt32Converter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt32Converter.cs
index f9b89b2e2d..201bbfb3ef 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt32Converter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt32Converter.cs
@@ -15,13 +15,7 @@ namespace System.ComponentModel
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt32, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(UInt32);
- }
- }
+ internal override Type TargetType => typeof(uint);
/// <summary>
/// Convert the given value to a string using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt64Converter.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt64Converter.cs
index 1355ebe7e0..913a9ce1a8 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt64Converter.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/UInt64Converter.cs
@@ -15,13 +15,7 @@ namespace System.ComponentModel
/// <summary>
/// The Type this converter is targeting (e.g. Int16, UInt64, etc.)
/// </summary>
- internal override Type TargetType
- {
- get
- {
- return typeof(UInt64);
- }
- }
+ internal override Type TargetType => typeof(ulong);
/// <summary>
/// Convert the given value to a string using the given radix
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WarningException.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WarningException.cs
index 99d6d75f30..ef1924d4b9 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WarningException.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WarningException.cs
@@ -17,9 +17,6 @@ namespace System.ComponentModel
[Serializable]
public class WarningException : SystemException
{
- private readonly string _helpUrl;
- private readonly string _helpTopic;
-
/// <summary>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.Win32Exception'/> class with the last Win32 error
/// that occured.</para>
@@ -61,8 +58,8 @@ namespace System.ComponentModel
public WarningException(string message, string helpUrl, string helpTopic)
: base(message)
{
- _helpUrl = helpUrl;
- _helpTopic = helpTopic;
+ HelpUrl = helpUrl;
+ HelpTopic = helpTopic;
}
/// <summary>
@@ -70,33 +67,21 @@ namespace System.ComponentModel
/// </summary>
protected WarningException(SerializationInfo info, StreamingContext context) : base(info, context)
{
- _helpUrl = (string)info.GetValue("helpUrl", typeof(string));
- _helpTopic = (string)info.GetValue("helpTopic", typeof(string));
+ HelpUrl = (string)info.GetValue("helpUrl", typeof(string));
+ HelpTopic = (string)info.GetValue("helpTopic", typeof(string));
}
/// <summary>
/// <para> Specifies the Help file associated with the
/// warning. This field is read-only.</para>
/// </summary>
- public string HelpUrl
- {
- get
- {
- return _helpUrl;
- }
- }
+ public string HelpUrl { get; }
/// <summary>
/// <para> Specifies the
/// Help topic associated with the warning. This field is read-only. </para>
/// </summary>
- public string HelpTopic
- {
- get
- {
- return _helpTopic;
- }
- }
+ public string HelpTopic { get; }
/// <summary>
/// Need this since Exception implements ISerializable and we have fields to save out.
@@ -109,8 +94,8 @@ namespace System.ComponentModel
throw new ArgumentNullException(nameof(info));
}
- info.AddValue("helpUrl", _helpUrl);
- info.AddValue("helpTopic", _helpTopic);
+ info.AddValue("helpUrl", HelpUrl);
+ info.AddValue("helpTopic", HelpTopic);
base.GetObjectData(info, context);
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WeakHashtable.cs b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WeakHashtable.cs
index f4faf2fdbb..f52133ceed 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WeakHashtable.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/WeakHashtable.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections;
+using System.Collections.Generic;
namespace System.ComponentModel
{
@@ -91,7 +92,7 @@ namespace System.ComponentModel
// Perform a scavenge through our keys, looking
// for dead references.
//
- ArrayList cleanupList = null;
+ List<object> cleanupList = null;
foreach (object o in Keys)
{
WeakReference wr = o as WeakReference;
@@ -99,7 +100,7 @@ namespace System.ComponentModel
{
if (cleanupList == null)
{
- cleanupList = new ArrayList();
+ cleanupList = new List<object>();
}
cleanupList.Add(wr);
@@ -180,12 +181,7 @@ namespace System.ComponentModel
public override bool Equals(object o)
{
- if (o == null)
- {
- return false;
- }
-
- if (o.GetHashCode() != _hashCode)
+ if (o?.GetHashCode() != _hashCode)
{
return false;
}
diff --git a/src/System.ComponentModel.TypeConverter/src/System/Timers/Timer.cs b/src/System.ComponentModel.TypeConverter/src/System/Timers/Timer.cs
index fed219acb7..cd2fa4ea36 100644
--- a/src/System.ComponentModel.TypeConverter/src/System/Timers/Timer.cs
+++ b/src/System.ComponentModel.TypeConverter/src/System/Timers/Timer.cs
@@ -231,12 +231,9 @@ namespace System.Timers
if (_synchronizingObject == null && DesignMode)
{
IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
- if (host != null)
- {
- object baseComponent = host.RootComponent;
- if (baseComponent != null && baseComponent is ISynchronizeInvoke)
- _synchronizingObject = (ISynchronizeInvoke)baseComponent;
- }
+ object baseComponent = host?.RootComponent;
+ if (baseComponent != null && baseComponent is ISynchronizeInvoke)
+ _synchronizingObject = (ISynchronizeInvoke)baseComponent;
}
return _synchronizingObject;
diff --git a/src/System.ComponentModel.TypeConverter/tests/SampleClasses.cs b/src/System.ComponentModel.TypeConverter/tests/SampleClasses.cs
index f1a56418cb..3608d1ad25 100644
--- a/src/System.ComponentModel.TypeConverter/tests/SampleClasses.cs
+++ b/src/System.ComponentModel.TypeConverter/tests/SampleClasses.cs
@@ -9,7 +9,7 @@ namespace System.ComponentModel.Tests
{
public class MyTypeDescriptorContext : ITypeDescriptorContext
{
- public IContainer Container { get { return null; } }
+ public IContainer Container => null;
public object Instance { get { return null; } }
public PropertyDescriptor PropertyDescriptor { get { return null; } }
public bool OnComponentChanging() { return true; }
diff --git a/src/System.Composition.Convention/src/System/Composition/Convention/PartConventionBuilder.cs b/src/System.Composition.Convention/src/System/Composition/Convention/PartConventionBuilder.cs
index aefe7355a6..1e1077c03a 100644
--- a/src/System.Composition.Convention/src/System/Composition/Convention/PartConventionBuilder.cs
+++ b/src/System.Composition.Convention/src/System/Composition/Convention/PartConventionBuilder.cs
@@ -22,8 +22,8 @@ namespace System.Composition.Convention
{
private readonly Type[] _emptyTypeArray = EmptyArray<Type>.Value;
private static List<Attribute> s_onImportsSatisfiedAttributeList;
- private readonly static List<Attribute> s_importingConstructorList = new List<Attribute>() { new ImportingConstructorAttribute() };
- private readonly static Type s_exportAttributeType = typeof(ExportAttribute);
+ private static readonly List<Attribute> s_importingConstructorList = new List<Attribute>() { new ImportingConstructorAttribute() };
+ private static readonly Type s_exportAttributeType = typeof(ExportAttribute);
private readonly List<ExportConventionBuilder> _typeExportBuilders;
private readonly List<ImportConventionBuilder> _constructorImportBuilders;
private bool _isShared;
diff --git a/src/System.Composition.Hosting/src/Microsoft/Internal/ThrowHelper.cs b/src/System.Composition.Hosting/src/Microsoft/Internal/ThrowHelper.cs
index d2353fc060..5be34faf8c 100644
--- a/src/System.Composition.Hosting/src/Microsoft/Internal/ThrowHelper.cs
+++ b/src/System.Composition.Hosting/src/Microsoft/Internal/ThrowHelper.cs
@@ -18,21 +18,21 @@ namespace Microsoft.Internal
return e;
}
- static public ArgumentException ArgumentException(string message)
+ public static ArgumentException ArgumentException(string message)
{
var e = new ArgumentException(message);
LogException(e);
return e;
}
- static public CompositionFailedException CardinalityMismatch_TooManyExports(string exportKey)
+ public static CompositionFailedException CardinalityMismatch_TooManyExports(string exportKey)
{
var e = new CompositionFailedException(string.Format(Resources.CardinalityMismatch_TooManyExports, exportKey));
LogException(e);
return e;
}
- static public CompositionFailedException CompositionException(string message)
+ public static CompositionFailedException CompositionException(string message)
{
var e = new CompositionFailedException(message);
LogException(e);
diff --git a/src/System.Configuration/System.Configuration.sln b/src/System.Configuration/System.Configuration.sln
new file mode 100644
index 0000000000..30d78a4a26
--- /dev/null
+++ b/src/System.Configuration/System.Configuration.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Configuration", "src\System.Configuration.csproj", "{B7697463-7C98-4462-BA09-67B7BF3842B6}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6BF3AE2C-3EEE-42F0-8C62-BAAC04AE6897}"
+ ProjectSection(SolutionItems) = preProject
+ src\System.Configuration.builds = src\System.Configuration.builds
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{A6D1680E-20AB-4253-AD1F-AACC478A2510}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{76C3F1E4-2EA8-4700-A9C0-EFEF909D7983}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Configuration.Tests", "tests\System.Configuration.Tests.csproj", "{7669C397-C21C-4C08-83F1-BE6691911E88}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Configuration", "ref\System.Configuration.csproj", "{2BFEAC8A-DE97-4E50-B992-802C2AD66524}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pkg", "pkg", "{CDDB4E69-37E9-4EE9-93A8-0B5DC240AC11}"
+ ProjectSection(SolutionItems) = preProject
+ pkg\System.Configuration.builds = pkg\System.Configuration.builds
+ pkg\System.Configuration.pkgproj = pkg\System.Configuration.pkgproj
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B7697463-7C98-4462-BA09-67B7BF3842B6}.Debug|Any CPU.ActiveCfg = Windows_Debug|Any CPU
+ {B7697463-7C98-4462-BA09-67B7BF3842B6}.Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
+ {B7697463-7C98-4462-BA09-67B7BF3842B6}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {B7697463-7C98-4462-BA09-67B7BF3842B6}.Release|Any CPU.Build.0 = Debug|Any CPU
+ {7669C397-C21C-4C08-83F1-BE6691911E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7669C397-C21C-4C08-83F1-BE6691911E88}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7669C397-C21C-4C08-83F1-BE6691911E88}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {7669C397-C21C-4C08-83F1-BE6691911E88}.Release|Any CPU.Build.0 = Debug|Any CPU
+ {2BFEAC8A-DE97-4E50-B992-802C2AD66524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2BFEAC8A-DE97-4E50-B992-802C2AD66524}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2BFEAC8A-DE97-4E50-B992-802C2AD66524}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2BFEAC8A-DE97-4E50-B992-802C2AD66524}.Release|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {B7697463-7C98-4462-BA09-67B7BF3842B6} = {6BF3AE2C-3EEE-42F0-8C62-BAAC04AE6897}
+ {7669C397-C21C-4C08-83F1-BE6691911E88} = {76C3F1E4-2EA8-4700-A9C0-EFEF909D7983}
+ {2BFEAC8A-DE97-4E50-B992-802C2AD66524} = {A6D1680E-20AB-4253-AD1F-AACC478A2510}
+ EndGlobalSection
+EndGlobal
diff --git a/src/System.Configuration/dir.props b/src/System.Configuration/dir.props
new file mode 100644
index 0000000000..ea772032c8
--- /dev/null
+++ b/src/System.Configuration/dir.props
@@ -0,0 +1,7 @@
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\dir.props" />
+ <PropertyGroup>
+ <AssemblyVersion>4.0.0.0</AssemblyVersion>
+ </PropertyGroup>
+</Project>
+
diff --git a/src/System.Configuration/pkg/System.Configuration.builds b/src/System.Configuration/pkg/System.Configuration.builds
new file mode 100644
index 0000000000..b6ea2f4e29
--- /dev/null
+++ b/src/System.Configuration/pkg/System.Configuration.builds
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <Project Include="System.Configuration.pkgproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project>
+
diff --git a/src/System.Configuration/pkg/System.Configuration.pkgproj b/src/System.Configuration/pkg/System.Configuration.pkgproj
new file mode 100644
index 0000000000..eb8e5a6396
--- /dev/null
+++ b/src/System.Configuration/pkg/System.Configuration.pkgproj
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <ProjectReference Include="..\ref\System.Configuration.csproj">
+ <SupportedFramework>netcoreapp1.1;net461;$(AllXamarinFrameworks)</SupportedFramework>
+ </ProjectReference>
+ <ProjectReference Include="..\src\System.Configuration.builds" />
+ <InboxOnTargetFramework Include="net461" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.Configuration/ref/System.Configuration.cs b/src/System.Configuration/ref/System.Configuration.cs
new file mode 100644
index 0000000000..9b8a035447
--- /dev/null
+++ b/src/System.Configuration/ref/System.Configuration.cs
@@ -0,0 +1,1109 @@
+// 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.
+
+#pragma warning disable CS0618
+namespace System.Configuration
+{
+ public sealed partial class AppSettingsSection : System.Configuration.ConfigurationSection
+ {
+ public AppSettingsSection() { }
+ [System.Configuration.ConfigurationPropertyAttribute("file", DefaultValue = "")]
+ public string File { get { throw null; } set { } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ [System.Configuration.ConfigurationPropertyAttribute("", IsDefaultCollection = true)]
+ public System.Configuration.KeyValueConfigurationCollection Settings { get { throw null; } }
+ protected internal override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey) { }
+ protected internal override object GetRuntimeObject() { throw null; }
+ protected internal override bool IsModified() { throw null; }
+ protected internal override void Reset(System.Configuration.ConfigurationElement parentSection) { }
+ protected internal override string SerializeSection(System.Configuration.ConfigurationElement parentElement, string name, System.Configuration.ConfigurationSaveMode saveMode) { throw null; }
+ }
+ public sealed partial class CallbackValidator : System.Configuration.ConfigurationValidatorBase
+ {
+ public CallbackValidator(System.Type type, System.Configuration.ValidatorCallback callback) { }
+ public override bool CanValidate(System.Type type) { throw null; }
+ public override void Validate(object value) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public sealed partial class CallbackValidatorAttribute : System.Configuration.ConfigurationValidatorAttribute
+ {
+ public CallbackValidatorAttribute() { }
+ public string CallbackMethodName { get { throw null; } set { } }
+ public System.Type Type { get { throw null; } set { } }
+ public override System.Configuration.ConfigurationValidatorBase ValidatorInstance { get { throw null; } }
+ }
+ public sealed partial class CommaDelimitedStringCollection : System.Collections.Specialized.StringCollection
+ {
+ public CommaDelimitedStringCollection() { }
+ public bool IsModified { get { throw null; } }
+ public new bool IsReadOnly { get { throw null; } }
+ public new string this[int index] { get { throw null; } set { } }
+ public new void Add(string value) { }
+ public new void AddRange(string[] range) { }
+ public new void Clear() { }
+ public System.Configuration.CommaDelimitedStringCollection Clone() { throw null; }
+ public new void Insert(int index, string value) { }
+ public new void Remove(string value) { }
+ public void SetReadOnly() { }
+ public override string ToString() { throw null; }
+ }
+ public sealed partial class CommaDelimitedStringCollectionConverter : System.Configuration.ConfigurationConverterBase
+ {
+ public CommaDelimitedStringCollectionConverter() { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+ public sealed partial class Configuration
+ {
+ internal Configuration() { }
+ public System.Configuration.AppSettingsSection AppSettings { get { throw null; } }
+ public System.Func<string, string> AssemblyStringTransformer { get { throw null; } set { } }
+ public System.Configuration.ConnectionStringsSection ConnectionStrings { get { throw null; } }
+ public System.Configuration.ContextInformation EvaluationContext { get { throw null; } }
+ public string FilePath { get { throw null; } }
+ public bool HasFile { get { throw null; } }
+ public System.Configuration.ConfigurationLocationCollection Locations { get { throw null; } }
+ public bool NamespaceDeclared { get { throw null; } set { } }
+ public System.Configuration.ConfigurationSectionGroup RootSectionGroup { get { throw null; } }
+ public System.Configuration.ConfigurationSectionGroupCollection SectionGroups { get { throw null; } }
+ public System.Configuration.ConfigurationSectionCollection Sections { get { throw null; } }
+ public System.Runtime.Versioning.FrameworkName TargetFramework { get { throw null; } set { } }
+ public System.Func<string, string> TypeStringTransformer { get { throw null; } set { } }
+ public System.Configuration.ConfigurationSection GetSection(string sectionName) { throw null; }
+ public System.Configuration.ConfigurationSectionGroup GetSectionGroup(string sectionGroupName) { throw null; }
+ public void Save() { }
+ public void Save(System.Configuration.ConfigurationSaveMode saveMode) { }
+ public void Save(System.Configuration.ConfigurationSaveMode saveMode, bool forceSaveAll) { }
+ public void SaveAs(string filename) { }
+ public void SaveAs(string filename, System.Configuration.ConfigurationSaveMode saveMode) { }
+ public void SaveAs(string filename, System.Configuration.ConfigurationSaveMode saveMode, bool forceSaveAll) { }
+ }
+ public enum ConfigurationAllowDefinition
+ {
+ Everywhere = 300,
+ MachineOnly = 0,
+ MachineToApplication = 200,
+ MachineToWebRoot = 100,
+ }
+ public enum ConfigurationAllowExeDefinition
+ {
+ MachineOnly = 0,
+ MachineToApplication = 100,
+ MachineToLocalUser = 300,
+ MachineToRoamingUser = 200,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(132))]
+ public sealed partial class ConfigurationCollectionAttribute : System.Attribute
+ {
+ public ConfigurationCollectionAttribute(System.Type itemType) { }
+ public string AddItemName { get { throw null; } set { } }
+ public string ClearItemsName { get { throw null; } set { } }
+ public System.Configuration.ConfigurationElementCollectionType CollectionType { get { throw null; } set { } }
+ public System.Type ItemType { get { throw null; } }
+ public string RemoveItemName { get { throw null; } set { } }
+ }
+ public abstract partial class ConfigurationConverterBase : System.ComponentModel.TypeConverter
+ {
+ protected ConfigurationConverterBase() { }
+ public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Type type) { throw null; }
+ public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Type type) { throw null; }
+ }
+ public abstract partial class ConfigurationElement
+ {
+ protected ConfigurationElement() { }
+ public System.Configuration.Configuration CurrentConfiguration { get { throw null; } }
+ public System.Configuration.ElementInformation ElementInformation { get { throw null; } }
+ protected internal virtual System.Configuration.ConfigurationElementProperty ElementProperty { get { throw null; } }
+ protected System.Configuration.ContextInformation EvaluationContext { get { throw null; } }
+ protected bool HasContext { get { throw null; } }
+ protected internal object this[System.Configuration.ConfigurationProperty prop] { get { throw null; } set { } }
+ protected internal object this[string propertyName] { get { throw null; } set { } }
+ public System.Configuration.ConfigurationLockCollection LockAllAttributesExcept { get { throw null; } }
+ public System.Configuration.ConfigurationLockCollection LockAllElementsExcept { get { throw null; } }
+ public System.Configuration.ConfigurationLockCollection LockAttributes { get { throw null; } }
+ public System.Configuration.ConfigurationLockCollection LockElements { get { throw null; } }
+ public bool LockItem { get { throw null; } set { } }
+ protected internal virtual System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ protected internal virtual void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey) { }
+ public override bool Equals(object compareTo) { throw null; }
+ public override int GetHashCode() { throw null; }
+ protected virtual string GetTransformedAssemblyString(string assemblyName) { throw null; }
+ protected virtual string GetTransformedTypeString(string typeName) { throw null; }
+ protected internal virtual void Init() { }
+ protected internal virtual void InitializeDefault() { }
+ protected internal virtual bool IsModified() { throw null; }
+ public virtual bool IsReadOnly() { throw null; }
+ protected virtual void ListErrors(System.Collections.IList errorList) { }
+ protected virtual bool OnDeserializeUnrecognizedAttribute(string name, string value) { throw null; }
+ protected virtual bool OnDeserializeUnrecognizedElement(string elementName, System.Xml.XmlReader reader) { throw null; }
+ protected virtual object OnRequiredPropertyNotFound(string name) { throw null; }
+ protected virtual void PostDeserialize() { }
+ protected virtual void PreSerialize(System.Xml.XmlWriter writer) { }
+ protected internal virtual void Reset(System.Configuration.ConfigurationElement parentElement) { }
+ protected internal virtual void ResetModified() { }
+ protected internal virtual bool SerializeElement(System.Xml.XmlWriter writer, bool serializeCollectionKey) { throw null; }
+ protected internal virtual bool SerializeToXmlElement(System.Xml.XmlWriter writer, string elementName) { throw null; }
+ protected void SetPropertyValue(System.Configuration.ConfigurationProperty prop, object value, bool ignoreLocks) { }
+ protected internal virtual void SetReadOnly() { }
+ protected internal virtual void Unmerge(System.Configuration.ConfigurationElement sourceElement, System.Configuration.ConfigurationElement parentElement, System.Configuration.ConfigurationSaveMode saveMode) { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ public abstract partial class ConfigurationElementCollection : System.Configuration.ConfigurationElement, System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ protected ConfigurationElementCollection() { }
+ protected ConfigurationElementCollection(System.Collections.IComparer comparer) { }
+ protected internal string AddElementName { get { throw null; } set { } }
+ protected internal string ClearElementName { get { throw null; } set { } }
+ public virtual System.Configuration.ConfigurationElementCollectionType CollectionType { get { throw null; } }
+ public int Count { get { throw null; } }
+ protected virtual string ElementName { get { throw null; } }
+ public bool EmitClear { get { throw null; } set { } }
+ public bool IsSynchronized { get { throw null; } }
+ protected internal string RemoveElementName { get { throw null; } set { } }
+ public object SyncRoot { get { throw null; } }
+ protected virtual bool ThrowOnDuplicate { get { throw null; } }
+ protected virtual void BaseAdd(System.Configuration.ConfigurationElement element) { }
+ protected internal void BaseAdd(System.Configuration.ConfigurationElement element, bool throwIfExists) { }
+ protected virtual void BaseAdd(int index, System.Configuration.ConfigurationElement element) { }
+ protected internal void BaseClear() { }
+ protected internal System.Configuration.ConfigurationElement BaseGet(int index) { throw null; }
+ protected internal System.Configuration.ConfigurationElement BaseGet(object key) { throw null; }
+ protected internal object[] BaseGetAllKeys() { throw null; }
+ protected internal object BaseGetKey(int index) { throw null; }
+ protected int BaseIndexOf(System.Configuration.ConfigurationElement element) { throw null; }
+ protected internal bool BaseIsRemoved(object key) { throw null; }
+ protected internal void BaseRemove(object key) { }
+ protected internal void BaseRemoveAt(int index) { }
+ public void CopyTo(System.Configuration.ConfigurationElement[] array, int index) { }
+ protected abstract System.Configuration.ConfigurationElement CreateNewElement();
+ protected virtual System.Configuration.ConfigurationElement CreateNewElement(string elementName) { throw null; }
+ public override bool Equals(object compareTo) { throw null; }
+ protected abstract object GetElementKey(System.Configuration.ConfigurationElement element);
+ public System.Collections.IEnumerator GetEnumerator() { throw null; }
+ public override int GetHashCode() { throw null; }
+ protected virtual bool IsElementName(string elementName) { throw null; }
+ protected virtual bool IsElementRemovable(System.Configuration.ConfigurationElement element) { throw null; }
+ protected internal override bool IsModified() { throw null; }
+ public override bool IsReadOnly() { throw null; }
+ protected override bool OnDeserializeUnrecognizedElement(string elementName, System.Xml.XmlReader reader) { throw null; }
+ protected internal override void Reset(System.Configuration.ConfigurationElement parentElement) { }
+ protected internal override void ResetModified() { }
+ protected internal override bool SerializeElement(System.Xml.XmlWriter writer, bool serializeCollectionKey) { throw null; }
+ protected internal override void SetReadOnly() { }
+ void System.Collections.ICollection.CopyTo(System.Array arr, int index) { }
+ protected internal override void Unmerge(System.Configuration.ConfigurationElement sourceElement, System.Configuration.ConfigurationElement parentElement, System.Configuration.ConfigurationSaveMode saveMode) { }
+ }
+ public enum ConfigurationElementCollectionType
+ {
+ AddRemoveClearMap = 1,
+ AddRemoveClearMapAlternate = 3,
+ BasicMap = 0,
+ BasicMapAlternate = 2,
+ }
+ public sealed partial class ConfigurationElementProperty
+ {
+ public ConfigurationElementProperty(System.Configuration.ConfigurationValidatorBase validator) { }
+ public System.Configuration.ConfigurationValidatorBase Validator { get { throw null; } }
+ }
+ public partial class ConfigurationException : System.SystemException
+ {
+ [System.ObsoleteAttribute("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException() { }
+ protected ConfigurationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ [System.ObsoleteAttribute("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message) { }
+ [System.ObsoleteAttribute("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, System.Exception inner) { }
+ [System.ObsoleteAttribute("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, System.Exception inner, string filename, int line) { }
+ [System.ObsoleteAttribute("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, System.Exception inner, System.Xml.XmlNode node) { }
+ [System.ObsoleteAttribute("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, string filename, int line) { }
+ [System.ObsoleteAttribute("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, System.Xml.XmlNode node) { }
+ public virtual string BareMessage { get { throw null; } }
+ public virtual string Filename { get { throw null; } }
+ public virtual int Line { get { throw null; } }
+ public override string Message { get { throw null; } }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ [System.ObsoleteAttribute("This class is obsolete, use System.Configuration!System.Configuration.ConfigurationErrorsException.GetFilename instead")]
+ public static string GetXmlNodeFilename(System.Xml.XmlNode node) { throw null; }
+ [System.ObsoleteAttribute("This class is obsolete, use System.Configuration!System.Configuration.ConfigurationErrorsException.GetLinenumber instead")]
+ public static int GetXmlNodeLineNumber(System.Xml.XmlNode node) { throw null; }
+ }
+ public partial class ConfigurationErrorsException : System.Configuration.ConfigurationException
+ {
+ public ConfigurationErrorsException() { }
+ protected ConfigurationErrorsException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public ConfigurationErrorsException(string message) { }
+ public ConfigurationErrorsException(string message, System.Exception inner) { }
+ public ConfigurationErrorsException(string message, System.Exception inner, string filename, int line) { }
+ public ConfigurationErrorsException(string message, System.Exception inner, System.Xml.XmlNode node) { }
+ public ConfigurationErrorsException(string message, System.Exception inner, System.Xml.XmlReader reader) { }
+ public ConfigurationErrorsException(string message, string filename, int line) { }
+ public ConfigurationErrorsException(string message, System.Xml.XmlNode node) { }
+ public ConfigurationErrorsException(string message, System.Xml.XmlReader reader) { }
+ public override string BareMessage { get { throw null; } }
+ public System.Collections.ICollection Errors { get { throw null; } }
+ public override string Filename { get { throw null; } }
+ public override int Line { get { throw null; } }
+ public override string Message { get { throw null; } }
+ public static string GetFilename(System.Xml.XmlNode node) { throw null; }
+ public static string GetFilename(System.Xml.XmlReader reader) { throw null; }
+ public static int GetLineNumber(System.Xml.XmlNode node) { throw null; }
+ public static int GetLineNumber(System.Xml.XmlReader reader) { throw null; }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ public partial class ConfigurationFileMap : System.ICloneable
+ {
+ public ConfigurationFileMap() { }
+ public ConfigurationFileMap(string machineConfigFilename) { }
+ public string MachineConfigFilename { get { throw null; } set { } }
+ public virtual object Clone() { throw null; }
+ }
+ public partial class ConfigurationLocation
+ {
+ internal ConfigurationLocation() { }
+ public string Path { get { throw null; } }
+ public System.Configuration.Configuration OpenConfiguration() { throw null; }
+ }
+ public partial class ConfigurationLocationCollection : System.Collections.ReadOnlyCollectionBase
+ {
+ internal ConfigurationLocationCollection() { }
+ public System.Configuration.ConfigurationLocation this[int index] { get { throw null; } }
+ }
+ public sealed partial class ConfigurationLockCollection : System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ internal ConfigurationLockCollection() { }
+ public string AttributeList { get { throw null; } }
+ public int Count { get { throw null; } }
+ public bool HasParentElements { get { throw null; } }
+ public bool IsModified { get { throw null; } }
+ public bool IsSynchronized { get { throw null; } }
+ public object SyncRoot { get { throw null; } }
+ public void Add(string name) { }
+ public void Clear() { }
+ public bool Contains(string name) { throw null; }
+ public void CopyTo(string[] array, int index) { }
+ public System.Collections.IEnumerator GetEnumerator() { throw null; }
+ public bool IsReadOnly(string name) { throw null; }
+ public void Remove(string name) { }
+ public void SetFromList(string attributeList) { }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ }
+ public static partial class ConfigurationManager
+ {
+ public static System.Collections.Specialized.NameValueCollection AppSettings { get { throw null; } }
+ public static System.Configuration.ConnectionStringSettingsCollection ConnectionStrings { get { throw null; } }
+ public static object GetSection(string sectionName) { throw null; }
+ public static System.Configuration.Configuration OpenExeConfiguration(System.Configuration.ConfigurationUserLevel userLevel) { throw null; }
+ public static System.Configuration.Configuration OpenExeConfiguration(string exePath) { throw null; }
+ public static System.Configuration.Configuration OpenMachineConfiguration() { throw null; }
+ public static System.Configuration.Configuration OpenMappedExeConfiguration(System.Configuration.ExeConfigurationFileMap fileMap, System.Configuration.ConfigurationUserLevel userLevel) { throw null; }
+ public static System.Configuration.Configuration OpenMappedExeConfiguration(System.Configuration.ExeConfigurationFileMap fileMap, System.Configuration.ConfigurationUserLevel userLevel, bool preLoad) { throw null; }
+ public static System.Configuration.Configuration OpenMappedMachineConfiguration(System.Configuration.ConfigurationFileMap fileMap) { throw null; }
+ public static void RefreshSection(string sectionName) { }
+ }
+
+ public sealed partial class ConfigurationProperty
+ {
+ public ConfigurationProperty(string name, System.Type type) { }
+ public ConfigurationProperty(string name, System.Type type, object defaultValue) { }
+ public ConfigurationProperty(string name, System.Type type, object defaultValue, System.ComponentModel.TypeConverter typeConverter, System.Configuration.ConfigurationValidatorBase validator, System.Configuration.ConfigurationPropertyOptions options) { }
+ public ConfigurationProperty(string name, System.Type type, object defaultValue, System.ComponentModel.TypeConverter typeConverter, System.Configuration.ConfigurationValidatorBase validator, System.Configuration.ConfigurationPropertyOptions options, string description) { }
+ public ConfigurationProperty(string name, System.Type type, object defaultValue, System.Configuration.ConfigurationPropertyOptions options) { }
+ public System.ComponentModel.TypeConverter Converter { get { throw null; } }
+ public object DefaultValue { get { throw null; } }
+ public string Description { get { throw null; } }
+ public bool IsAssemblyStringTransformationRequired { get { throw null; } }
+ public bool IsDefaultCollection { get { throw null; } }
+ public bool IsKey { get { throw null; } }
+ public bool IsRequired { get { throw null; } }
+ public bool IsTypeStringTransformationRequired { get { throw null; } }
+ public bool IsVersionCheckRequired { get { throw null; } }
+ public string Name { get { throw null; } }
+ public System.Type Type { get { throw null; } }
+ public System.Configuration.ConfigurationValidatorBase Validator { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public sealed partial class ConfigurationPropertyAttribute : System.Attribute
+ {
+ public ConfigurationPropertyAttribute(string name) { }
+ public object DefaultValue { get { throw null; } set { } }
+ public bool IsDefaultCollection { get { throw null; } set { } }
+ public bool IsKey { get { throw null; } set { } }
+ public bool IsRequired { get { throw null; } set { } }
+ public string Name { get { throw null; } }
+ public System.Configuration.ConfigurationPropertyOptions Options { get { throw null; } set { } }
+ }
+ public partial class ConfigurationPropertyCollection : System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ public ConfigurationPropertyCollection() { }
+ public int Count { get { throw null; } }
+ public bool IsSynchronized { get { throw null; } }
+ public System.Configuration.ConfigurationProperty this[string name] { get { throw null; } }
+ public object SyncRoot { get { throw null; } }
+ public void Add(System.Configuration.ConfigurationProperty property) { }
+ public void Clear() { }
+ public bool Contains(string name) { throw null; }
+ public void CopyTo(System.Configuration.ConfigurationProperty[] array, int index) { }
+ public System.Collections.IEnumerator GetEnumerator() { throw null; }
+ public bool Remove(string name) { throw null; }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ }
+ [System.FlagsAttribute]
+ public enum ConfigurationPropertyOptions
+ {
+ IsAssemblyStringTransformationRequired = 16,
+ IsDefaultCollection = 1,
+ IsKey = 4,
+ IsRequired = 2,
+ IsTypeStringTransformationRequired = 8,
+ IsVersionCheckRequired = 32,
+ None = 0,
+ }
+ public enum ConfigurationSaveMode
+ {
+ Full = 2,
+ Minimal = 1,
+ Modified = 0,
+ }
+ public abstract partial class ConfigurationSection : System.Configuration.ConfigurationElement
+ {
+ protected ConfigurationSection() { }
+ public System.Configuration.SectionInformation SectionInformation { get { throw null; } }
+ protected internal virtual void DeserializeSection(System.Xml.XmlReader reader) { }
+ protected internal virtual object GetRuntimeObject() { throw null; }
+ protected internal override bool IsModified() { throw null; }
+ protected internal override void ResetModified() { }
+ protected internal virtual string SerializeSection(System.Configuration.ConfigurationElement parentElement, string name, System.Configuration.ConfigurationSaveMode saveMode) { throw null; }
+ protected internal virtual bool ShouldSerializeElementInTargetVersion(System.Configuration.ConfigurationElement element, string elementName, System.Runtime.Versioning.FrameworkName targetFramework) { throw null; }
+ protected internal virtual bool ShouldSerializePropertyInTargetVersion(System.Configuration.ConfigurationProperty property, string propertyName, System.Runtime.Versioning.FrameworkName targetFramework, System.Configuration.ConfigurationElement parentConfigurationElement) { throw null; }
+ protected internal virtual bool ShouldSerializeSectionInTargetVersion(System.Runtime.Versioning.FrameworkName targetFramework) { throw null; }
+ }
+ public sealed partial class ConfigurationSectionCollection : System.Collections.Specialized.NameObjectCollectionBase
+ {
+ internal ConfigurationSectionCollection() { }
+ public override int Count { get { throw null; } }
+ public System.Configuration.ConfigurationSection this[int index] { get { throw null; } }
+ public System.Configuration.ConfigurationSection this[string name] { get { throw null; } }
+ public override System.Collections.Specialized.NameObjectCollectionBase.KeysCollection Keys { get { throw null; } }
+ public void Add(string name, System.Configuration.ConfigurationSection section) { }
+ public void Clear() { }
+ public void CopyTo(System.Configuration.ConfigurationSection[] array, int index) { }
+ public System.Configuration.ConfigurationSection Get(int index) { throw null; }
+ public System.Configuration.ConfigurationSection Get(string name) { throw null; }
+ public override System.Collections.IEnumerator GetEnumerator() { throw null; }
+ public string GetKey(int index) { throw null; }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public void Remove(string name) { }
+ public void RemoveAt(int index) { }
+ }
+ public partial class ConfigurationSectionGroup
+ {
+ public ConfigurationSectionGroup() { }
+ public bool IsDeclarationRequired { get { throw null; } }
+ public bool IsDeclared { get { throw null; } }
+ public string Name { get { throw null; } }
+ public string SectionGroupName { get { throw null; } }
+ public System.Configuration.ConfigurationSectionGroupCollection SectionGroups { get { throw null; } }
+ public System.Configuration.ConfigurationSectionCollection Sections { get { throw null; } }
+ public string Type { get { throw null; } set { } }
+ public void ForceDeclaration() { }
+ public void ForceDeclaration(bool force) { }
+ protected internal virtual bool ShouldSerializeSectionGroupInTargetVersion(System.Runtime.Versioning.FrameworkName targetFramework) { throw null; }
+ }
+ public sealed partial class ConfigurationSectionGroupCollection : System.Collections.Specialized.NameObjectCollectionBase
+ {
+ internal ConfigurationSectionGroupCollection() { }
+ public override int Count { get { throw null; } }
+ public System.Configuration.ConfigurationSectionGroup this[int index] { get { throw null; } }
+ public System.Configuration.ConfigurationSectionGroup this[string name] { get { throw null; } }
+ public override System.Collections.Specialized.NameObjectCollectionBase.KeysCollection Keys { get { throw null; } }
+ public void Add(string name, System.Configuration.ConfigurationSectionGroup sectionGroup) { }
+ public void Clear() { }
+ public void CopyTo(System.Configuration.ConfigurationSectionGroup[] array, int index) { }
+ public System.Configuration.ConfigurationSectionGroup Get(int index) { throw null; }
+ public System.Configuration.ConfigurationSectionGroup Get(string name) { throw null; }
+ public override System.Collections.IEnumerator GetEnumerator() { throw null; }
+ public string GetKey(int index) { throw null; }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public void Remove(string name) { }
+ public void RemoveAt(int index) { }
+ }
+ public enum ConfigurationUserLevel
+ {
+ None = 0,
+ PerUserRoaming = 10,
+ PerUserRoamingAndLocal = 20,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public partial class ConfigurationValidatorAttribute : System.Attribute
+ {
+ protected ConfigurationValidatorAttribute() { }
+ public ConfigurationValidatorAttribute(System.Type validator) { }
+ public virtual System.Configuration.ConfigurationValidatorBase ValidatorInstance { get { throw null; } }
+ public System.Type ValidatorType { get { throw null; } }
+ }
+ public abstract partial class ConfigurationValidatorBase
+ {
+ protected ConfigurationValidatorBase() { }
+ public virtual bool CanValidate(System.Type type) { throw null; }
+ public abstract void Validate(object value);
+ }
+ public sealed partial class ConnectionStringSettings : System.Configuration.ConfigurationElement
+ {
+ public ConnectionStringSettings() { }
+ public ConnectionStringSettings(string name, string connectionString) { }
+ public ConnectionStringSettings(string name, string connectionString, string providerName) { }
+ [System.Configuration.ConfigurationPropertyAttribute("connectionString", Options = (System.Configuration.ConfigurationPropertyOptions)(2), DefaultValue = "")]
+ public string ConnectionString { get { throw null; } set { } }
+ [System.Configuration.ConfigurationPropertyAttribute("name", Options = (System.Configuration.ConfigurationPropertyOptions)(6), DefaultValue = "")]
+ public string Name { get { throw null; } set { } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ [System.Configuration.ConfigurationPropertyAttribute("providerName", DefaultValue = "System.Data.SqlClient")]
+ public string ProviderName { get { throw null; } set { } }
+ public override string ToString() { throw null; }
+ }
+ [System.Configuration.ConfigurationCollectionAttribute(typeof(System.Configuration.ConnectionStringSettings))]
+ public sealed partial class ConnectionStringSettingsCollection : System.Configuration.ConfigurationElementCollection
+ {
+ public ConnectionStringSettingsCollection() { }
+ public System.Configuration.ConnectionStringSettings this[int index] { get { throw null; } set { } }
+ public new System.Configuration.ConnectionStringSettings this[string name] { get { throw null; } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ public void Add(System.Configuration.ConnectionStringSettings settings) { }
+ protected override void BaseAdd(int index, System.Configuration.ConfigurationElement element) { }
+ public void Clear() { }
+ protected override System.Configuration.ConfigurationElement CreateNewElement() { throw null; }
+ protected override object GetElementKey(System.Configuration.ConfigurationElement element) { throw null; }
+ public int IndexOf(System.Configuration.ConnectionStringSettings settings) { throw null; }
+ public void Remove(System.Configuration.ConnectionStringSettings settings) { }
+ public void Remove(string name) { }
+ public void RemoveAt(int index) { }
+ }
+ public sealed partial class ConnectionStringsSection : System.Configuration.ConfigurationSection
+ {
+ public ConnectionStringsSection() { }
+ [System.Configuration.ConfigurationPropertyAttribute("", Options = (System.Configuration.ConfigurationPropertyOptions)(1))]
+ public System.Configuration.ConnectionStringSettingsCollection ConnectionStrings { get { throw null; } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ protected internal override object GetRuntimeObject() { throw null; }
+ }
+ public sealed partial class ContextInformation
+ {
+ internal ContextInformation() { }
+ public object HostingContext { get { throw null; } }
+ public bool IsMachineLevel { get { throw null; } }
+ public object GetSection(string sectionName) { throw null; }
+ }
+ public sealed partial class DefaultSection : System.Configuration.ConfigurationSection
+ {
+ public DefaultSection() { }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ protected internal override void DeserializeSection(System.Xml.XmlReader xmlReader) { }
+ protected internal override bool IsModified() { throw null; }
+ protected internal override void Reset(System.Configuration.ConfigurationElement parentSection) { }
+ protected internal override void ResetModified() { }
+ protected internal override string SerializeSection(System.Configuration.ConfigurationElement parentSection, string name, System.Configuration.ConfigurationSaveMode saveMode) { throw null; }
+ }
+ public sealed partial class DefaultValidator : System.Configuration.ConfigurationValidatorBase
+ {
+ public DefaultValidator() { }
+ public override bool CanValidate(System.Type type) { throw null; }
+ public override void Validate(object value) { }
+ }
+ public sealed partial class ElementInformation
+ {
+ internal ElementInformation() { }
+ public System.Collections.ICollection Errors { get { throw null; } }
+ public bool IsCollection { get { throw null; } }
+ public bool IsLocked { get { throw null; } }
+ public bool IsPresent { get { throw null; } }
+ public int LineNumber { get { throw null; } }
+ public System.Configuration.PropertyInformationCollection Properties { get { throw null; } }
+ public string Source { get { throw null; } }
+ public System.Type Type { get { throw null; } }
+ public System.Configuration.ConfigurationValidatorBase Validator { get { throw null; } }
+ }
+ public sealed partial class ExeConfigurationFileMap : System.Configuration.ConfigurationFileMap
+ {
+ public ExeConfigurationFileMap() { }
+ public ExeConfigurationFileMap(string machineConfigFileName) { }
+ public string ExeConfigFilename { get { throw null; } set { } }
+ public string LocalUserConfigFilename { get { throw null; } set { } }
+ public string RoamingUserConfigFilename { get { throw null; } set { } }
+ public override object Clone() { throw null; }
+ }
+ public sealed partial class ExeContext
+ {
+ internal ExeContext() { }
+ public string ExePath { get { throw null; } }
+ public System.Configuration.ConfigurationUserLevel UserLevel { get { throw null; } }
+ }
+ public sealed partial class GenericEnumConverter : System.Configuration.ConfigurationConverterBase
+ {
+ public GenericEnumConverter(System.Type typeEnum) { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+ public sealed partial class IgnoreSection : System.Configuration.ConfigurationSection
+ {
+ public IgnoreSection() { }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ protected internal override void DeserializeSection(System.Xml.XmlReader xmlReader) { }
+ protected internal override bool IsModified() { throw null; }
+ protected internal override void Reset(System.Configuration.ConfigurationElement parentSection) { }
+ protected internal override void ResetModified() { }
+ protected internal override string SerializeSection(System.Configuration.ConfigurationElement parentSection, string name, System.Configuration.ConfigurationSaveMode saveMode) { throw null; }
+ }
+ public sealed partial class InfiniteIntConverter : System.Configuration.ConfigurationConverterBase
+ {
+ public InfiniteIntConverter() { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+ public sealed partial class InfiniteTimeSpanConverter : System.Configuration.ConfigurationConverterBase
+ {
+ public InfiniteTimeSpanConverter() { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+ public partial class IntegerValidator : System.Configuration.ConfigurationValidatorBase
+ {
+ public IntegerValidator(int minValue, int maxValue) { }
+ public IntegerValidator(int minValue, int maxValue, bool rangeIsExclusive) { }
+ public IntegerValidator(int minValue, int maxValue, bool rangeIsExclusive, int resolution) { }
+ public override bool CanValidate(System.Type type) { throw null; }
+ public override void Validate(object value) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public sealed partial class IntegerValidatorAttribute : System.Configuration.ConfigurationValidatorAttribute
+ {
+ public IntegerValidatorAttribute() { }
+ public bool ExcludeRange { get { throw null; } set { } }
+ public int MaxValue { get { throw null; } set { } }
+ public int MinValue { get { throw null; } set { } }
+ public override System.Configuration.ConfigurationValidatorBase ValidatorInstance { get { throw null; } }
+ }
+ [System.Configuration.ConfigurationCollectionAttribute(typeof(System.Configuration.KeyValueConfigurationElement))]
+ public partial class KeyValueConfigurationCollection : System.Configuration.ConfigurationElementCollection
+ {
+ public KeyValueConfigurationCollection() { }
+ public string[] AllKeys { get { throw null; } }
+ public new System.Configuration.KeyValueConfigurationElement this[string key] { get { throw null; } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ protected override bool ThrowOnDuplicate { get { throw null; } }
+ public void Add(System.Configuration.KeyValueConfigurationElement keyValue) { }
+ public void Add(string key, string value) { }
+ public void Clear() { }
+ protected override System.Configuration.ConfigurationElement CreateNewElement() { throw null; }
+ protected override object GetElementKey(System.Configuration.ConfigurationElement element) { throw null; }
+ public void Remove(string key) { }
+ }
+ public partial class KeyValueConfigurationElement : System.Configuration.ConfigurationElement
+ {
+ public KeyValueConfigurationElement(string key, string value) { }
+ [System.Configuration.ConfigurationPropertyAttribute("key", Options = (System.Configuration.ConfigurationPropertyOptions)(4), DefaultValue = "")]
+ public string Key { get { throw null; } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ [System.Configuration.ConfigurationPropertyAttribute("value", DefaultValue = "")]
+ public string Value { get { throw null; } set { } }
+ protected internal override void Init() { }
+ }
+ public partial class LongValidator : System.Configuration.ConfigurationValidatorBase
+ {
+ public LongValidator(long minValue, long maxValue) { }
+ public LongValidator(long minValue, long maxValue, bool rangeIsExclusive) { }
+ public LongValidator(long minValue, long maxValue, bool rangeIsExclusive, long resolution) { }
+ public override bool CanValidate(System.Type type) { throw null; }
+ public override void Validate(object value) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public sealed partial class LongValidatorAttribute : System.Configuration.ConfigurationValidatorAttribute
+ {
+ public LongValidatorAttribute() { }
+ public bool ExcludeRange { get { throw null; } set { } }
+ public long MaxValue { get { throw null; } set { } }
+ public long MinValue { get { throw null; } set { } }
+ public override System.Configuration.ConfigurationValidatorBase ValidatorInstance { get { throw null; } }
+ }
+ [System.Configuration.ConfigurationCollectionAttribute(typeof(System.Configuration.NameValueConfigurationElement))]
+ public sealed partial class NameValueConfigurationCollection : System.Configuration.ConfigurationElementCollection
+ {
+ public NameValueConfigurationCollection() { }
+ public string[] AllKeys { get { throw null; } }
+ public new System.Configuration.NameValueConfigurationElement this[string name] { get { throw null; } set { } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ public void Add(System.Configuration.NameValueConfigurationElement nameValue) { }
+ public void Clear() { }
+ protected override System.Configuration.ConfigurationElement CreateNewElement() { throw null; }
+ protected override object GetElementKey(System.Configuration.ConfigurationElement element) { throw null; }
+ public void Remove(System.Configuration.NameValueConfigurationElement nameValue) { }
+ public void Remove(string name) { }
+ }
+ public sealed partial class NameValueConfigurationElement : System.Configuration.ConfigurationElement
+ {
+ public NameValueConfigurationElement(string name, string value) { }
+ [System.Configuration.ConfigurationPropertyAttribute("name", IsKey = true, DefaultValue = "")]
+ public string Name { get { throw null; } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ [System.Configuration.ConfigurationPropertyAttribute("value", DefaultValue = "")]
+ public string Value { get { throw null; } set { } }
+ }
+ public enum OverrideMode
+ {
+ Allow = 1,
+ Deny = 2,
+ Inherit = 0,
+ }
+ public partial class PositiveTimeSpanValidator : System.Configuration.ConfigurationValidatorBase
+ {
+ public PositiveTimeSpanValidator() { }
+ public override bool CanValidate(System.Type type) { throw null; }
+ public override void Validate(object value) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public sealed partial class PositiveTimeSpanValidatorAttribute : System.Configuration.ConfigurationValidatorAttribute
+ {
+ public PositiveTimeSpanValidatorAttribute() { }
+ public override System.Configuration.ConfigurationValidatorBase ValidatorInstance { get { throw null; } }
+ }
+ public sealed partial class PropertyInformation
+ {
+ internal PropertyInformation() { }
+ public System.ComponentModel.TypeConverter Converter { get { throw null; } }
+ public object DefaultValue { get { throw null; } }
+ public string Description { get { throw null; } }
+ public bool IsKey { get { throw null; } }
+ public bool IsLocked { get { throw null; } }
+ public bool IsModified { get { throw null; } }
+ public bool IsRequired { get { throw null; } }
+ public int LineNumber { get { throw null; } }
+ public string Name { get { throw null; } }
+ public string Source { get { throw null; } }
+ public System.Type Type { get { throw null; } }
+ public System.Configuration.ConfigurationValidatorBase Validator { get { throw null; } }
+ public object Value { get { throw null; } set { } }
+ public System.Configuration.PropertyValueOrigin ValueOrigin { get { throw null; } }
+ }
+ public sealed partial class PropertyInformationCollection : System.Collections.Specialized.NameObjectCollectionBase
+ {
+ internal PropertyInformationCollection() { }
+ public System.Configuration.PropertyInformation this[string propertyName] { get { throw null; } }
+ public void CopyTo(System.Configuration.PropertyInformation[] array, int index) { }
+ public override System.Collections.IEnumerator GetEnumerator() { throw null; }
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ public enum PropertyValueOrigin
+ {
+ Default = 0,
+ Inherited = 1,
+ SetHere = 2,
+ }
+ public static partial class ProtectedConfiguration
+ {
+ public const string DataProtectionProviderName = "DataProtectionConfigurationProvider";
+ public const string ProtectedDataSectionName = "configProtectedData";
+ public const string RsaProviderName = "RsaProtectedConfigurationProvider";
+ public static string DefaultProvider { get { throw null; } }
+ public static System.Configuration.ProtectedConfigurationProviderCollection Providers { get { throw null; } }
+ }
+ public abstract partial class ProtectedConfigurationProvider : System.Configuration.Provider.ProviderBase
+ {
+ protected ProtectedConfigurationProvider() { }
+ public abstract System.Xml.XmlNode Decrypt(System.Xml.XmlNode encryptedNode);
+ public abstract System.Xml.XmlNode Encrypt(System.Xml.XmlNode node);
+ }
+ public partial class ProtectedConfigurationProviderCollection : System.Configuration.Provider.ProviderCollection
+ {
+ public ProtectedConfigurationProviderCollection() { }
+ public new System.Configuration.ProtectedConfigurationProvider this[string name] { get { throw null; } }
+ public override void Add(System.Configuration.Provider.ProviderBase provider) { }
+ }
+ public sealed partial class ProtectedConfigurationSection : System.Configuration.ConfigurationSection
+ {
+ public ProtectedConfigurationSection() { }
+ [System.Configuration.ConfigurationPropertyAttribute("defaultProvider", DefaultValue = "RsaProtectedConfigurationProvider")]
+ public string DefaultProvider { get { throw null; } set { } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ [System.Configuration.ConfigurationPropertyAttribute("providers")]
+ public System.Configuration.ProviderSettingsCollection Providers { get { throw null; } }
+ }
+ public partial class ProtectedProviderSettings : System.Configuration.ConfigurationElement
+ {
+ public ProtectedProviderSettings() { }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ [System.Configuration.ConfigurationPropertyAttribute("", IsDefaultCollection = true, Options = (System.Configuration.ConfigurationPropertyOptions)(1))]
+ public System.Configuration.ProviderSettingsCollection Providers { get { throw null; } }
+ }
+ public sealed partial class ProviderSettings : System.Configuration.ConfigurationElement
+ {
+ public ProviderSettings() { }
+ public ProviderSettings(string name, string type) { }
+ [System.Configuration.ConfigurationPropertyAttribute("name", IsRequired = true, IsKey = true)]
+ public string Name { get { throw null; } set { } }
+ public System.Collections.Specialized.NameValueCollection Parameters { get { throw null; } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ [System.Configuration.ConfigurationPropertyAttribute("type", IsRequired = true)]
+ public string Type { get { throw null; } set { } }
+ protected internal override bool IsModified() { throw null; }
+ protected override bool OnDeserializeUnrecognizedAttribute(string name, string value) { throw null; }
+ protected internal override void Reset(System.Configuration.ConfigurationElement parentElement) { }
+ protected internal override void Unmerge(System.Configuration.ConfigurationElement sourceElement, System.Configuration.ConfigurationElement parentElement, System.Configuration.ConfigurationSaveMode saveMode) { }
+ }
+ [System.Configuration.ConfigurationCollectionAttribute(typeof(System.Configuration.ProviderSettings))]
+ public sealed partial class ProviderSettingsCollection : System.Configuration.ConfigurationElementCollection
+ {
+ public ProviderSettingsCollection() { }
+ public System.Configuration.ProviderSettings this[int index] { get { throw null; } set { } }
+ public new System.Configuration.ProviderSettings this[string key] { get { throw null; } }
+ protected internal override System.Configuration.ConfigurationPropertyCollection Properties { get { throw null; } }
+ public void Add(System.Configuration.ProviderSettings provider) { }
+ public void Clear() { }
+ protected override System.Configuration.ConfigurationElement CreateNewElement() { throw null; }
+ protected override object GetElementKey(System.Configuration.ConfigurationElement element) { throw null; }
+ public void Remove(string name) { }
+ }
+ public partial class RegexStringValidator : System.Configuration.ConfigurationValidatorBase
+ {
+ public RegexStringValidator(string regex) { }
+ public override bool CanValidate(System.Type type) { throw null; }
+ public override void Validate(object value) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public sealed partial class RegexStringValidatorAttribute : System.Configuration.ConfigurationValidatorAttribute
+ {
+ public RegexStringValidatorAttribute(string regex) { }
+ public string Regex { get { throw null; } }
+ public override System.Configuration.ConfigurationValidatorBase ValidatorInstance { get { throw null; } }
+ }
+ public sealed partial class SectionInformation
+ {
+ internal SectionInformation() { }
+ public System.Configuration.ConfigurationAllowDefinition AllowDefinition { get { throw null; } set { } }
+ public System.Configuration.ConfigurationAllowExeDefinition AllowExeDefinition { get { throw null; } set { } }
+ public bool AllowLocation { get { throw null; } set { } }
+ public bool AllowOverride { get { throw null; } set { } }
+ public string ConfigSource { get { throw null; } set { } }
+ public bool ForceSave { get { throw null; } set { } }
+ public bool InheritInChildApplications { get { throw null; } set { } }
+ public bool IsDeclarationRequired { get { throw null; } }
+ public bool IsDeclared { get { throw null; } }
+ public bool IsLocked { get { throw null; } }
+ public bool IsProtected { get { throw null; } }
+ public string Name { get { throw null; } }
+ public System.Configuration.OverrideMode OverrideMode { get { throw null; } set { } }
+ public System.Configuration.OverrideMode OverrideModeDefault { get { throw null; } set { } }
+ public System.Configuration.OverrideMode OverrideModeEffective { get { throw null; } }
+ public System.Configuration.ProtectedConfigurationProvider ProtectionProvider { get { throw null; } }
+ public bool RequirePermission { get { throw null; } set { } }
+ public bool RestartOnExternalChanges { get { throw null; } set { } }
+ public string SectionName { get { throw null; } }
+ public string Type { get { throw null; } set { } }
+ public void ForceDeclaration() { }
+ public void ForceDeclaration(bool force) { }
+ public System.Configuration.ConfigurationSection GetParentSection() { throw null; }
+ public string GetRawXml() { throw null; }
+ public void ProtectSection(string protectionProvider) { }
+ public void RevertToParent() { }
+ public void SetRawXml(string rawXml) { }
+ public void UnprotectSection() { }
+ }
+ public partial class StringValidator : System.Configuration.ConfigurationValidatorBase
+ {
+ public StringValidator(int minLength) { }
+ public StringValidator(int minLength, int maxLength) { }
+ public StringValidator(int minLength, int maxLength, string invalidCharacters) { }
+ public override bool CanValidate(System.Type type) { throw null; }
+ public override void Validate(object value) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public sealed partial class StringValidatorAttribute : System.Configuration.ConfigurationValidatorAttribute
+ {
+ public StringValidatorAttribute() { }
+ public string InvalidCharacters { get { throw null; } set { } }
+ public int MaxLength { get { throw null; } set { } }
+ public int MinLength { get { throw null; } set { } }
+ public override System.Configuration.ConfigurationValidatorBase ValidatorInstance { get { throw null; } }
+ }
+ public sealed partial class SubclassTypeValidator : System.Configuration.ConfigurationValidatorBase
+ {
+ public SubclassTypeValidator(System.Type baseClass) { }
+ public override bool CanValidate(System.Type type) { throw null; }
+ public override void Validate(object value) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public sealed partial class SubclassTypeValidatorAttribute : System.Configuration.ConfigurationValidatorAttribute
+ {
+ public SubclassTypeValidatorAttribute(System.Type baseClass) { }
+ public System.Type BaseClass { get { throw null; } }
+ public override System.Configuration.ConfigurationValidatorBase ValidatorInstance { get { throw null; } }
+ }
+ public partial class TimeSpanMinutesConverter : System.Configuration.ConfigurationConverterBase
+ {
+ public TimeSpanMinutesConverter() { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+ public sealed partial class TimeSpanMinutesOrInfiniteConverter : System.Configuration.TimeSpanMinutesConverter
+ {
+ public TimeSpanMinutesOrInfiniteConverter() { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+ public partial class TimeSpanSecondsConverter : System.Configuration.ConfigurationConverterBase
+ {
+ public TimeSpanSecondsConverter() { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+ public sealed partial class TimeSpanSecondsOrInfiniteConverter : System.Configuration.TimeSpanSecondsConverter
+ {
+ public TimeSpanSecondsOrInfiniteConverter() { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+ public partial class TimeSpanValidator : System.Configuration.ConfigurationValidatorBase
+ {
+ public TimeSpanValidator(System.TimeSpan minValue, System.TimeSpan maxValue) { }
+ public TimeSpanValidator(System.TimeSpan minValue, System.TimeSpan maxValue, bool rangeIsExclusive) { }
+ public TimeSpanValidator(System.TimeSpan minValue, System.TimeSpan maxValue, bool rangeIsExclusive, long resolutionInSeconds) { }
+ public override bool CanValidate(System.Type type) { throw null; }
+ public override void Validate(object value) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public sealed partial class TimeSpanValidatorAttribute : System.Configuration.ConfigurationValidatorAttribute
+ {
+ public const string TimeSpanMaxValue = "10675199.02:48:05.4775807";
+ public const string TimeSpanMinValue = "-10675199.02:48:05.4775808";
+ public TimeSpanValidatorAttribute() { }
+ public bool ExcludeRange { get { throw null; } set { } }
+ public System.TimeSpan MaxValue { get { throw null; } }
+ public string MaxValueString { get { throw null; } set { } }
+ public System.TimeSpan MinValue { get { throw null; } }
+ public string MinValueString { get { throw null; } set { } }
+ public override System.Configuration.ConfigurationValidatorBase ValidatorInstance { get { throw null; } }
+ }
+ public sealed partial class TypeNameConverter : System.Configuration.ConfigurationConverterBase
+ {
+ public TypeNameConverter() { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+ public delegate void ValidatorCallback(object value);
+ public sealed partial class WhiteSpaceTrimStringConverter : System.Configuration.ConfigurationConverterBase
+ {
+ public WhiteSpaceTrimStringConverter() { }
+ public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object data) { throw null; }
+ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext ctx, System.Globalization.CultureInfo ci, object value, System.Type type) { throw null; }
+ }
+}
+namespace System.Configuration.Internal
+{
+ public partial class DelegatingConfigHost : System.Configuration.Internal.IInternalConfigHost
+ {
+ protected DelegatingConfigHost() { }
+ protected System.Configuration.Internal.IInternalConfigHost Host { get { throw null; } set { } }
+ public virtual bool IsRemote { get { throw null; } }
+ public virtual bool SupportsChangeNotifications { get { throw null; } }
+ public virtual bool SupportsLocation { get { throw null; } }
+ public virtual bool SupportsPath { get { throw null; } }
+ public virtual bool SupportsRefresh { get { throw null; } }
+ public virtual object CreateConfigurationContext(string configPath, string locationSubPath) { throw null; }
+ public virtual object CreateDeprecatedConfigContext(string configPath) { throw null; }
+ public virtual string DecryptSection(string encryptedXml, System.Configuration.ProtectedConfigurationProvider protectionProvider, System.Configuration.ProtectedConfigurationSection protectedConfigSection) { throw null; }
+ public virtual void DeleteStream(string streamName) { }
+ public virtual string EncryptSection(string clearTextXml, System.Configuration.ProtectedConfigurationProvider protectionProvider, System.Configuration.ProtectedConfigurationSection protectedConfigSection) { throw null; }
+ public virtual string GetConfigPathFromLocationSubPath(string configPath, string locationSubPath) { throw null; }
+ public virtual System.Type GetConfigType(string typeName, bool throwOnError) { throw null; }
+ public virtual string GetConfigTypeName(System.Type t) { throw null; }
+ public virtual string GetStreamName(string configPath) { throw null; }
+ public virtual string GetStreamNameForConfigSource(string streamName, string configSource) { throw null; }
+ public virtual object GetStreamVersion(string streamName) { throw null; }
+ public virtual void Init(System.Configuration.Internal.IInternalConfigRoot configRoot, params object[] hostInitParams) { }
+ public virtual void InitForConfiguration(ref string locationSubPath, out string configPath, out string locationConfigPath, System.Configuration.Internal.IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams) { configPath = default(string); locationConfigPath = default(string); }
+ public virtual bool IsAboveApplication(string configPath) { throw null; }
+ public virtual bool IsConfigRecordRequired(string configPath) { throw null; }
+ public virtual bool IsDefinitionAllowed(string configPath, System.Configuration.ConfigurationAllowDefinition allowDefinition, System.Configuration.ConfigurationAllowExeDefinition allowExeDefinition) { throw null; }
+ public virtual bool IsFile(string streamName) { throw null; }
+ public virtual bool IsInitDelayed(System.Configuration.Internal.IInternalConfigRecord configRecord) { throw null; }
+ public virtual bool IsLocationApplicable(string configPath) { throw null; }
+ public virtual bool IsSecondaryRoot(string configPath) { throw null; }
+ public virtual System.IO.Stream OpenStreamForRead(string streamName) { throw null; }
+ public virtual System.IO.Stream OpenStreamForRead(string streamName, bool assertPermissions) { throw null; }
+ public virtual System.IO.Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext) { throw null; }
+ public virtual System.IO.Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext, bool assertPermissions) { throw null; }
+ public virtual bool PrefetchAll(string configPath, string streamName) { throw null; }
+ public virtual bool PrefetchSection(string sectionGroupName, string sectionName) { throw null; }
+ public virtual void RequireCompleteInit(System.Configuration.Internal.IInternalConfigRecord configRecord) { }
+ public virtual object StartMonitoringStreamForChanges(string streamName, System.Configuration.Internal.StreamChangeCallback callback) { throw null; }
+ public virtual void StopMonitoringStreamForChanges(string streamName, System.Configuration.Internal.StreamChangeCallback callback) { }
+ public virtual void VerifyDefinitionAllowed(string configPath, System.Configuration.ConfigurationAllowDefinition allowDefinition, System.Configuration.ConfigurationAllowExeDefinition allowExeDefinition, System.Configuration.Internal.IConfigErrorInfo errorInfo) { }
+ public virtual void WriteCompleted(string streamName, bool success, object writeContext) { }
+ public virtual void WriteCompleted(string streamName, bool success, object writeContext, bool assertPermissions) { }
+ }
+ public partial interface IConfigErrorInfo
+ {
+ string Filename { get; }
+ int LineNumber { get; }
+ }
+ public partial interface IConfigSystem
+ {
+ System.Configuration.Internal.IInternalConfigHost Host { get; }
+ System.Configuration.Internal.IInternalConfigRoot Root { get; }
+ void Init(System.Type typeConfigHost, params object[] hostInitParams);
+ }
+ public partial interface IConfigurationManagerHelper
+ {
+ void EnsureNetConfigLoaded();
+ }
+ public partial interface IConfigurationManagerInternal
+ {
+ string ApplicationConfigUri { get; }
+ string ExeLocalConfigDirectory { get; }
+ string ExeLocalConfigPath { get; }
+ string ExeProductName { get; }
+ string ExeProductVersion { get; }
+ string ExeRoamingConfigDirectory { get; }
+ string ExeRoamingConfigPath { get; }
+ string MachineConfigPath { get; }
+ bool SetConfigurationSystemInProgress { get; }
+ bool SupportsUserConfig { get; }
+ string UserConfigFilename { get; }
+ }
+ public partial interface IInternalConfigClientHost
+ {
+ string GetExeConfigPath();
+ string GetLocalUserConfigPath();
+ string GetRoamingUserConfigPath();
+ bool IsExeConfig(string configPath);
+ bool IsLocalUserConfig(string configPath);
+ bool IsRoamingUserConfig(string configPath);
+ }
+ public partial interface IInternalConfigConfigurationFactory
+ {
+ System.Configuration.Configuration Create(System.Type typeConfigHost, params object[] hostInitConfigurationParams);
+ string NormalizeLocationSubPath(string subPath, System.Configuration.Internal.IConfigErrorInfo errorInfo);
+ }
+ public partial interface IInternalConfigHost
+ {
+ bool IsRemote { get; }
+ bool SupportsChangeNotifications { get; }
+ bool SupportsLocation { get; }
+ bool SupportsPath { get; }
+ bool SupportsRefresh { get; }
+ object CreateConfigurationContext(string configPath, string locationSubPath);
+ object CreateDeprecatedConfigContext(string configPath);
+ string DecryptSection(string encryptedXml, System.Configuration.ProtectedConfigurationProvider protectionProvider, System.Configuration.ProtectedConfigurationSection protectedConfigSection);
+ void DeleteStream(string streamName);
+ string EncryptSection(string clearTextXml, System.Configuration.ProtectedConfigurationProvider protectionProvider, System.Configuration.ProtectedConfigurationSection protectedConfigSection);
+ string GetConfigPathFromLocationSubPath(string configPath, string locationSubPath);
+ System.Type GetConfigType(string typeName, bool throwOnError);
+ string GetConfigTypeName(System.Type t);
+ string GetStreamName(string configPath);
+ string GetStreamNameForConfigSource(string streamName, string configSource);
+ object GetStreamVersion(string streamName);
+ void Init(System.Configuration.Internal.IInternalConfigRoot configRoot, params object[] hostInitParams);
+ void InitForConfiguration(ref string locationSubPath, out string configPath, out string locationConfigPath, System.Configuration.Internal.IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams);
+ bool IsAboveApplication(string configPath);
+ bool IsConfigRecordRequired(string configPath);
+ bool IsDefinitionAllowed(string configPath, System.Configuration.ConfigurationAllowDefinition allowDefinition, System.Configuration.ConfigurationAllowExeDefinition allowExeDefinition);
+ bool IsFile(string streamName);
+ bool IsInitDelayed(System.Configuration.Internal.IInternalConfigRecord configRecord);
+ bool IsLocationApplicable(string configPath);
+ bool IsSecondaryRoot(string configPath);
+ System.IO.Stream OpenStreamForRead(string streamName);
+ System.IO.Stream OpenStreamForRead(string streamName, bool assertPermissions);
+ System.IO.Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext);
+ System.IO.Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext, bool assertPermissions);
+ bool PrefetchAll(string configPath, string streamName);
+ bool PrefetchSection(string sectionGroupName, string sectionName);
+ void RequireCompleteInit(System.Configuration.Internal.IInternalConfigRecord configRecord);
+ object StartMonitoringStreamForChanges(string streamName, System.Configuration.Internal.StreamChangeCallback callback);
+ void StopMonitoringStreamForChanges(string streamName, System.Configuration.Internal.StreamChangeCallback callback);
+ void VerifyDefinitionAllowed(string configPath, System.Configuration.ConfigurationAllowDefinition allowDefinition, System.Configuration.ConfigurationAllowExeDefinition allowExeDefinition, System.Configuration.Internal.IConfigErrorInfo errorInfo);
+ void WriteCompleted(string streamName, bool success, object writeContext);
+ void WriteCompleted(string streamName, bool success, object writeContext, bool assertPermissions);
+ }
+ public partial interface IInternalConfigRecord
+ {
+ string ConfigPath { get; }
+ bool HasInitErrors { get; }
+ string StreamName { get; }
+ object GetLkgSection(string configKey);
+ object GetSection(string configKey);
+ void RefreshSection(string configKey);
+ void Remove();
+ void ThrowIfInitErrors();
+ }
+ public partial interface IInternalConfigRoot
+ {
+ bool IsDesignTime { get; }
+ event System.Configuration.Internal.InternalConfigEventHandler ConfigChanged;
+ event System.Configuration.Internal.InternalConfigEventHandler ConfigRemoved;
+ System.Configuration.Internal.IInternalConfigRecord GetConfigRecord(string configPath);
+ object GetSection(string section, string configPath);
+ string GetUniqueConfigPath(string configPath);
+ System.Configuration.Internal.IInternalConfigRecord GetUniqueConfigRecord(string configPath);
+ void Init(System.Configuration.Internal.IInternalConfigHost host, bool isDesignTime);
+ void RemoveConfig(string configPath);
+ }
+ public partial interface IInternalConfigSettingsFactory
+ {
+ void CompleteInit();
+ void SetConfigurationSystem(System.Configuration.Internal.IInternalConfigSystem internalConfigSystem, bool initComplete);
+ }
+ public partial interface IInternalConfigSystem
+ {
+ bool SupportsUserConfig { get; }
+ object GetSection(string configKey);
+ void RefreshConfig(string sectionName);
+ }
+ public sealed partial class InternalConfigEventArgs : System.EventArgs
+ {
+ public InternalConfigEventArgs(string configPath) { }
+ public string ConfigPath { get { throw null; } set { } }
+ }
+ public delegate void InternalConfigEventHandler(object sender, System.Configuration.Internal.InternalConfigEventArgs e);
+ public delegate void StreamChangeCallback(string streamName);
+}
+namespace System.Configuration.Provider
+{
+ public abstract partial class ProviderBase
+ {
+ protected ProviderBase() { }
+ public virtual string Description { get { throw null; } }
+ public virtual string Name { get { throw null; } }
+ public virtual void Initialize(string name, System.Collections.Specialized.NameValueCollection config) { }
+ }
+ public partial class ProviderCollection : System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ public ProviderCollection() { }
+ public int Count { get { throw null; } }
+ public bool IsSynchronized { get { throw null; } }
+ public System.Configuration.Provider.ProviderBase this[string name] { get { throw null; } }
+ public object SyncRoot { get { throw null; } }
+ public virtual void Add(System.Configuration.Provider.ProviderBase provider) { }
+ public void Clear() { }
+ public void CopyTo(System.Configuration.Provider.ProviderBase[] array, int index) { }
+ public System.Collections.IEnumerator GetEnumerator() { throw null; }
+ public void Remove(string name) { }
+ public void SetReadOnly() { }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ }
+ public partial class ProviderException : System.Exception
+ {
+ public ProviderException() { }
+ protected ProviderException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public ProviderException(string message) { }
+ public ProviderException(string message, System.Exception innerException) { }
+ }
+}
+
+#pragma warning restore CS0618
+
+
+
diff --git a/src/System.Configuration/ref/System.Configuration.csproj b/src/System.Configuration/ref/System.Configuration.csproj
new file mode 100644
index 0000000000..e9b7453d12
--- /dev/null
+++ b/src/System.Configuration/ref/System.Configuration.csproj
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ <ProjectGuid>{2BFEAC8A-DE97-4E50-B992-802C2AD66524}</ProjectGuid>
+ <PackageTargetFramework>netstandard1.7;uap10.1</PackageTargetFramework>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="System.Configuration.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.Configuration/src/Resources/Strings.resx b/src/System.Configuration/src/Resources/Strings.resx
new file mode 100644
index 0000000000..43fc94e192
--- /dev/null
+++ b/src/System.Configuration/src/Resources/Strings.resx
@@ -0,0 +1,718 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Parameter_Invalid" xml:space="preserve">
+ <value>The parameter '{0}' is invalid.</value>
+ </data>
+ <data name="Parameter_NullOrEmpty" xml:space="preserve">
+ <value>The string parameter '{0}' cannot be null or empty.</value>
+ </data>
+ <data name="Property_NullOrEmpty" xml:space="preserve">
+ <value>The value assigned to property '{0}' cannot be null or empty.</value>
+ </data>
+ <data name="Property_Invalid" xml:space="preserve">
+ <value>The value assigned to property '{0}' is invalid.</value>
+ </data>
+ <data name="Unexpected_Error" xml:space="preserve">
+ <value>An unexpected error occurred in '{0}'.</value>
+ </data>
+ <data name="Wrapped_exception_message" xml:space="preserve">
+ <value>{0}: {1}</value>
+ </data>
+ <!--
+ Messages that are wrapped by WrapAsConfigException.
+ Note that the messages do not end in a period.
+ -->
+ <data name="Config_error_loading_XML_file" xml:space="preserve">
+ <value>An error occurred loading a configuration file</value>
+ </data>
+ <data name="Config_exception_creating_section_handler" xml:space="preserve">
+ <value>An error occurred creating the configuration section handler for {0}</value>
+ </data>
+ <data name="Config_exception_creating_section" xml:space="preserve">
+ <value>An error occurred creating the configuration section for {0}</value>
+ </data>
+ <data name="Config_tag_name_invalid" xml:space="preserve">
+ <value>Invalid format for a section or section group name</value>
+ </data>
+ <!--
+ other exceptions
+ -->
+ <data name="Argument_AddingDuplicate" xml:space="preserve">
+ <value>An entry with the same key already exists.</value>
+ </data>
+ <data name="Config_add_configurationsection_already_added" xml:space="preserve">
+ <value>Cannot add a ConfigurationSection that already belongs to the Configuration.</value>
+ </data>
+ <data name="Config_add_configurationsection_already_exists" xml:space="preserve">
+ <value>Cannot add a ConfigurationSection with the same name that already exists.</value>
+ </data>
+ <data name="Config_add_configurationsection_in_location_config" xml:space="preserve">
+ <value>Cannot add a ConfigurationSection to a Configuration with a location.</value>
+ </data>
+ <data name="Config_add_configurationsectiongroup_already_added" xml:space="preserve">
+ <value>Cannot add a ConfigurationSectionGroup that already belongs to the Configuration.</value>
+ </data>
+ <data name="Config_add_configurationsectiongroup_already_exists" xml:space="preserve">
+ <value>Cannot add a ConfigurationSectionGroup with the same name that already exists.</value>
+ </data>
+ <data name="Config_add_configurationsectiongroup_in_location_config" xml:space="preserve">
+ <value>Cannot add a ConfigurationSectionGroup to a Configuration with a location.</value>
+ </data>
+ <data name="Config_allow_exedefinition_error_application" xml:space="preserve">
+ <value>It is an error to use a section registered as allowExeDefinition='MachineToApplication' beyond the application, in the user's config. (This is the default behavior if not specified)</value>
+ </data>
+ <data name="Config_allow_exedefinition_error_machine" xml:space="preserve">
+ <value>It is an error to use a section registered as allowExeDefinition='MachineOnly' beyond machine.config.</value>
+ </data>
+ <data name="Config_allow_exedefinition_error_roaminguser" xml:space="preserve">
+ <value>It is an error to use a section registered as allowExeDefinition='MachineToRoamingUser' beyond the roaming user config, in the local user config.</value>
+ </data>
+ <data name="Config_appsettings_declaration_invalid" xml:space="preserve">
+ <value>The configuration section 'appSettings' has an unexpected declaration.</value>
+ </data>
+ <data name="Config_base_attribute_locked" xml:space="preserve">
+ <value>The attribute '{0}' has been locked in a higher level configuration.</value>
+ </data>
+ <data name="Config_base_collection_item_locked_cannot_clear" xml:space="preserve">
+ <value>A collection item has been locked in a higher level configuration. The collection may not be cleared.</value>
+ </data>
+ <data name="Config_base_collection_item_locked" xml:space="preserve">
+ <value>The collection item has been locked in a higher level configuration and may not be changed.</value>
+ </data>
+ <data name="Config_base_cannot_add_items_above_inherited_items" xml:space="preserve">
+ <value>This collection does not permit items to be added in or above the inherited items.</value>
+ </data>
+ <data name="Config_base_cannot_add_items_below_inherited_items" xml:space="preserve">
+ <value>This collection does not permit items to be added in or below the inherited items.</value>
+ </data>
+ <data name="Config_base_cannot_remove_inherited_items" xml:space="preserve">
+ <value>Inherited items may not be removed.</value>
+ </data>
+ <data name="Config_base_collection_elements_may_not_be_removed" xml:space="preserve">
+ <value>Elements of this collection may not be removed.</value>
+ </data>
+ <data name="Config_base_collection_entry_already_exists" xml:space="preserve">
+ <value>The entry '{0}' has already been added.</value>
+ </data>
+ <data name="Config_base_collection_entry_already_removed" xml:space="preserve">
+ <value>Entry already removed.</value>
+ </data>
+ <data name="Config_base_collection_entry_not_found" xml:space="preserve">
+ <value>The entry '{0}' is not in the collection.</value>
+ </data>
+ <data name="Config_base_element_cannot_have_multiple_child_elements" xml:space="preserve">
+ <value>The element &lt;{0}&gt; may only appear once in this section.</value>
+ </data>
+ <data name="Config_base_element_default_collection_cannot_be_locked" xml:space="preserve">
+ <value>Locks on this collection must be placed on the parent object.</value>
+ </data>
+ <data name="Config_base_element_locked" xml:space="preserve">
+ <value>The element '{0}' has been locked in a higher level configuration.</value>
+ </data>
+ <data name="Config_base_expected_enum" xml:space="preserve">
+ <value>Invalid enum value.</value>
+ </data>
+ <data name="Config_base_expected_to_find_element" xml:space="preserve">
+ <value>Expected to find an element.</value>
+ </data>
+ <data name="Config_base_invalid_attribute_to_lock" xml:space="preserve">
+ <value>The attribute '{0}' is not valid in the locked list for this section. The following attributes can be locked: {1}. Multiple attributes may be listed separated by commas.</value>
+ </data>
+ <data name="Config_base_invalid_attribute_to_lock_by_add" xml:space="preserve">
+ <value>The attribute '{0}' is not valid in the locked list for this section. The following attributes can be locked: {1}.</value>
+ </data>
+ <data name="Config_base_invalid_element_key" xml:space="preserve">
+ <value>Invalid key value.</value>
+ </data>
+ <data name="Config_base_invalid_element_to_lock" xml:space="preserve">
+ <value>The element '{0}' is not valid in the locked list for this section. The following elements can be locked: {1}. Multiple elements may be listed separated by commas.</value>
+ </data>
+ <data name="Config_base_invalid_element_to_lock_by_add" xml:space="preserve">
+ <value>The element '{0}' is not valid in the locked list for this section. The following elements can be locked: {1}.</value>
+ </data>
+ <data name="Config_base_property_is_not_a_configuration_element" xml:space="preserve">
+ <value>Property '{0}' is not a ConfigurationElement.</value>
+ </data>
+ <data name="Config_base_read_only" xml:space="preserve">
+ <value>The configuration is read only.</value>
+ </data>
+ <data name="Config_base_required_attribute_locked" xml:space="preserve">
+ <value>The attribute '{0}' is required and is locked at a higher level configuration. The configuration with the lock should lock the entire element if it needs to lock required attributes.</value>
+ </data>
+ <data name="Config_base_required_attribute_lock_attempt" xml:space="preserve">
+ <value>The attribute '{0}' is required and cannot be locked. The configuration should lock the entire element if it needs to lock required attributes.</value>
+ </data>
+ <data name="Config_base_required_attribute_missing" xml:space="preserve">
+ <value>Required attribute '{0}' not found.</value>
+ </data>
+ <data name="Config_base_section_cannot_contain_cdata" xml:space="preserve">
+ <value>The configuration section cannot contain a CDATA element.</value>
+ </data>
+ <data name="Config_base_section_invalid_content" xml:space="preserve">
+ <value>The configuration section cannot contain a CDATA or text element.</value>
+ </data>
+ <data name="Config_base_unrecognized_attribute" xml:space="preserve">
+ <value>Unrecognized attribute '{0}'. Note that attribute names are case-sensitive.</value>
+ </data>
+ <data name="Config_base_unrecognized_element" xml:space="preserve">
+ <value>Unrecognized element.</value>
+ </data>
+ <data name="Config_base_unrecognized_element_name" xml:space="preserve">
+ <value>Unrecognized element '{0}'.</value>
+ </data>
+ <data name="Config_base_value_cannot_contain" xml:space="preserve">
+ <value>The value may not contain the '{0}' character.</value>
+ </data>
+ <data name="Config_cannot_edit_configurationsection_in_location_config" xml:space="preserve">
+ <value>ConfigurationSection properties for a &lt;section&gt; declaration cannot be edited in a Configuration with a location.</value>
+ </data>
+ <data name="Config_cannot_edit_configurationsection_parentsection" xml:space="preserve">
+ <value>ConfigurationSection properties can not be edited for the parent section of another section (ie. a section retrieved by calling GetParentSection on a section)</value>
+ </data>
+ <data name="Config_cannot_edit_configurationsection_when_location_locked" xml:space="preserve">
+ <value>ConfigurationSection properties for a location section cannot be edited when allowLocation=false.</value>
+ </data>
+ <data name="Config_cannot_edit_configurationsection_when_locked" xml:space="preserve">
+ <value>ConfigurationSection properties cannot be edited when locked.</value>
+ </data>
+ <data name="Config_cannot_edit_configurationsection_when_not_attached" xml:space="preserve">
+ <value>ConfigurationSection cannot be edited before being added to a section group belonging to an instance of class Configuration.</value>
+ </data>
+ <data name="Config_cannot_edit_configurationsection_when_it_is_implicit" xml:space="preserve">
+ <value>ConfigurationSection cannot be edited because it is a built-in section.</value>
+ </data>
+ <data name="Config_cannot_edit_configurationsection_when_it_is_undeclared" xml:space="preserve">
+ <value>ConfigurationSection cannot be edited because it is not declared.</value>
+ </data>
+ <data name="Config_cannot_edit_configurationsectiongroup_in_location_config" xml:space="preserve">
+ <value>ConfigurationSectionGroup properties for a &lt;sectionGroup&gt; declaration cannot be edited in a Configuration with a location.</value>
+ </data>
+ <data name="Config_cannot_edit_configurationsectiongroup_when_not_attached" xml:space="preserve">
+ <value>ConfigurationSectionGroup cannot be edited before being added to a section group belonging to an instance of class Configuration.</value>
+ </data>
+ <data name="Config_cannot_edit_locationattriubtes" xml:space="preserve">
+ <value>AllowOverride and InheritInChildApplications can not be set in the exe configuration, these settings have no meaning there.</value>
+ </data>
+ <data name="Config_cannot_open_config_source" xml:space="preserve">
+ <value>Unable to open configSource file '{0}'.</value>
+ </data>
+ <data name="Config_client_config_init_error" xml:space="preserve">
+ <value>Configuration system failed to initialize</value>
+ </data>
+ <data name="Config_client_config_init_security" xml:space="preserve">
+ <value>Failed to initialize configuration because we didn't have necessary security requirements.</value>
+ </data>
+ <data name="Config_client_config_too_many_configsections_elements" xml:space="preserve">
+ <value>Only one &lt;configSections&gt; element allowed per config file and if present must be the first child of the root &lt;configuration&gt; element.</value>
+ </data>
+ <data name="Config_configmanager_open_noexe" xml:space="preserve">
+ <value>exePath must be specified when not running inside a stand alone exe.</value>
+ </data>
+ <data name="Config_configsection_parentnotvalid" xml:space="preserve">
+ <value>This is not valid for the parent section of another section (ie. a section retrieved by calling GetParentSection on a section)</value>
+ </data>
+ <data name="Config_connectionstrings_declaration_invalid" xml:space="preserve">
+ <value>The configuration section 'connectionStrings' has an unexpected declaration.</value>
+ </data>
+ <data name="Config_data_read_count_mismatch" xml:space="preserve">
+ <value>Data read count is not equal to data available.</value>
+ </data>
+ <data name="Config_element_no_context" xml:space="preserve">
+ <value>This element is not currently associated with any context</value>
+ </data>
+ <data name="Config_empty_lock_attributes_except" xml:space="preserve">
+ <value>The '{0}' attribute cannot be an empty string. {1}="*" may be used to lock all attributes.</value>
+ </data>
+ <data name="Config_empty_lock_attributes_except_effective" xml:space="preserve">
+ <value>The {0}="{1}" is invalid because the attributes have all been locked at a higher level. {2}="*" must be used to lock all attributes.</value>
+ </data>
+ <data name="Config_empty_lock_element_except" xml:space="preserve">
+ <value>The '{0}' attribute cannot be an empty string. {1}="*" may be used to lock all elements.</value>
+ </data>
+ <data name="Config_exception_in_config_section_handler" xml:space="preserve">
+ <value>An error occurred executing the configuration section handler for {0}.</value>
+ </data>
+ <data name="Config_file_doesnt_have_root_configuration" xml:space="preserve">
+ <value>Configuration file {0} does not have root &lt;configuration&gt; tag</value>
+ </data>
+ <data name="Config_file_has_changed" xml:space="preserve">
+ <value>The configuration file has been changed by another program.</value>
+ </data>
+ <data name="Config_getparentconfigurationsection_first_instance" xml:space="preserve">
+ <value>GetParentSection can only be applied to ConfigurationSections from the first instance of a Configuration.</value>
+ </data>
+ <data name="Config_inconsistent_location_attributes" xml:space="preserve">
+ <value>Error in configuration section "{0}": AllowLocation is false and either AllowOverride or InheritInChildApplications is true.</value>
+ </data>
+ <data name="Config_invalid_attributes_for_write" xml:space="preserve">
+ <value>Unable to open file '{0}' for writing because it is read-only or hidden.</value>
+ </data>
+ <data name="Config_invalid_boolean_attribute" xml:space="preserve">
+ <value>The property '{0}' must have value 'true' or 'false'.</value>
+ </data>
+ <data name="Config_invalid_configurationsection_constructor" xml:space="preserve">
+ <value>Invalid constructor for ConfigurationSection.</value>
+ </data>
+ <data name="Config_invalid_node_type" xml:space="preserve">
+ <value>Invalid node type.</value>
+ </data>
+ <data name="Config_location_location_not_allowed" xml:space="preserve">
+ <value>&lt;location&gt; sections are allowed only within &lt;configuration&gt; sections.</value>
+ </data>
+ <data name="Config_location_path_invalid_character" xml:space="preserve">
+ <value>&lt;location&gt; path attribute must be a relative virtual path. It cannot contain any of '?' ':' '\\' '*' '"' '&lt;' '>' or '|'.</value>
+ </data>
+ <data name="Config_location_path_invalid_first_character" xml:space="preserve">
+ <value>&lt;location&gt; path attribute must be a relative virtual path. It cannot start with any of ' ' '.' '/' or '\\'.</value>
+ </data>
+ <data name="Config_location_path_invalid_last_character" xml:space="preserve">
+ <value>&lt;location&gt; path attribute must be a relative virtual path. It cannot end with any of ' ' '.' '/' or '\\'.</value>
+ </data>
+ <data name="Config_missing_required_attribute" xml:space="preserve">
+ <value>The '{0}' attribute must be specified on the '{1}' tag.</value>
+ </data>
+ <data name="Config_more_data_than_expected" xml:space="preserve">
+ <value>More data than expected.</value>
+ </data>
+ <data name="Config_name_value_file_section_file_invalid_root" xml:space="preserve">
+ <value>The root element must match the name of the section referencing the file, '{0}'</value>
+ </data>
+ <data name="Config_namespace_invalid" xml:space="preserve">
+ <value>Namespace of '{0}' on configuration element is invalid, only '{1}' is valid.</value>
+ </data>
+ <data name="Config_no_stream_to_write" xml:space="preserve">
+ <value>A configuration file cannot be created for the requested Configuration object.</value>
+ </data>
+ <data name="Config_not_allowed_to_encrypt_this_section" xml:space="preserve">
+ <value>This configuration section cannot be encrypted.</value>
+ </data>
+ <data name="Config_object_is_null" xml:space="preserve">
+ <value>Configuration section handler returned a null object.</value>
+ </data>
+ <data name="Config_operation_not_runtime" xml:space="preserve">
+ <value>This operation does not apply at runtime.</value>
+ </data>
+ <data name="Config_properties_may_not_be_derived_from_configuration_section" xml:space="preserve">
+ <value>The Configuration property '{0}' may not be derived from ConfigurationSection.</value>
+ </data>
+ <data name="Config_protection_section_not_found" xml:space="preserve">
+ <value>Protection Section not found.</value>
+ </data>
+ <data name="Config_provider_must_implement_type" xml:space="preserve">
+ <value>Provider must implement the class '{0}'.</value>
+ </data>
+ <data name="Config_root_section_group_cannot_be_edited" xml:space="preserve">
+ <value>The RootSectionGroup cannot be edited</value>
+ </data>
+ <data name="Config_section_allow_definition_attribute_invalid" xml:space="preserve">
+ <value>The 'allowDefinition' attribute must be one of the following values: Everywhere, MachineOnly, MachineToWebRoot, MachineToApplication.</value>
+ </data>
+ <data name="Config_section_allow_exe_definition_attribute_invalid" xml:space="preserve">
+ <value>The 'allowExeDefinition' attribute must be one of the following values: MachineOnly, MachineToApplication, MachineToRoamingUser, MachineToLocalUser.</value>
+ </data>
+ <data name="Config_section_cannot_be_used_in_location" xml:space="preserve">
+ <value>This section is not allowed in &lt;location&gt; elements. This section has been marked allowLocation="false".</value>
+ </data>
+ <data name="Config_section_group_missing_public_constructor" xml:space="preserve">
+ <value>SectionGroup type does not have a public instance constructor that takes no arguments.</value>
+ </data>
+ <data name="Config_section_locked" xml:space="preserve">
+ <value>This configuration section cannot be used at this path. This happens when the site administrator has locked access to this section using &lt;location allowOverride="false"&gt; from an inherited configuration file.</value>
+ </data>
+ <data name="Config_sections_must_be_unique" xml:space="preserve">
+ <value>Sections must only appear once per config file. See the help topic &lt;location&gt; for exceptions.</value>
+ </data>
+ <data name="Config_source_cannot_be_shared" xml:space="preserve">
+ <value>The configSource file '{0}' can only be used by one type of section, and may not be the same as the configuration file.</value>
+ </data>
+ <data name="Config_source_parent_conflict" xml:space="preserve">
+ <value>The configSource file '{0}' is also used in a parent, this is not allowed.</value>
+ </data>
+ <data name="Config_source_file_format" xml:space="preserve">
+ <value>The format of a configSource file must be an element containing the name of the section.</value>
+ </data>
+ <data name="Config_source_invalid_format" xml:space="preserve">
+ <value>The configSource attribute must be a relative physical path.</value>
+ </data>
+ <data name="Config_source_invalid_chars" xml:space="preserve">
+ <value>The configSource attribute must be a relative physical path, so the '/' character is not allowed.</value>
+ </data>
+ <data name="Config_source_requires_file" xml:space="preserve">
+ <value>The 'configSource' property may not be set in a configuration that has no associated file.</value>
+ </data>
+ <data name="Config_source_syntax_error" xml:space="preserve">
+ <value>A section using 'configSource' may contain no other attributes or elements.</value>
+ </data>
+ <data name="Config_system_already_set" xml:space="preserve">
+ <value>The configuration system has already been initialized.</value>
+ </data>
+ <data name="Config_tag_name_already_defined" xml:space="preserve">
+ <value>Section or group name '{0}' is already defined. Updates to this may only occur at the configuration level where it is defined.</value>
+ </data>
+ <data name="Config_tag_name_already_defined_at_this_level" xml:space="preserve">
+ <value>Section or group name '{0}' is already defined. This can not be defined multiple times.</value>
+ </data>
+ <data name="Config_tag_name_cannot_be_location" xml:space="preserve">
+ <value>The section name 'location' is reserved for &lt;location&gt; sections.</value>
+ </data>
+ <data name="Config_tag_name_cannot_begin_with_config" xml:space="preserve">
+ <value>Section names beginning with config are reserved.</value>
+ </data>
+ <data name="Config_type_doesnt_inherit_from_type" xml:space="preserve">
+ <value>Type '{0}' does not inherit from '{1}'.</value>
+ </data>
+ <data name="Config_unexpected_element_end" xml:space="preserve">
+ <value>Unexpected end of element {0}.</value>
+ </data>
+ <data name="Config_unexpected_element_name" xml:space="preserve">
+ <value>Unexpected element name {0}.</value>
+ </data>
+ <data name="Config_unexpected_node_type" xml:space="preserve">
+ <value>expected XmlNodeType.Element, type is {0}.</value>
+ </data>
+ <data name="Config_unrecognized_configuration_section" xml:space="preserve">
+ <value>Unrecognized configuration section {0}.</value>
+ </data>
+ <data name="Config_write_failed" xml:space="preserve">
+ <value>Unable to save config to file '{0}'.</value>
+ </data>
+ <data name="Converter_timespan_not_in_second" xml:space="preserve">
+ <value>The expected format is an integer value in seconds.</value>
+ </data>
+ <data name="Converter_unsupported_value_type" xml:space="preserve">
+ <value>The converter cannot convert values with type '{0}'.</value>
+ </data>
+ <data name="Decryption_failed" xml:space="preserve">
+ <value>Failed to decrypt using provider '{0}'. Error message from the provider: {1}</value>
+ </data>
+ <data name="Default_value_conversion_error_from_string" xml:space="preserve">
+ <value>The default value of the property '{0}' cannot be parsed. The error is: {1}</value>
+ </data>
+ <data name="Default_value_wrong_type" xml:space="preserve">
+ <value>The default value for the property '{0}' has different type than the one of the property itself.</value>
+ </data>
+ <data name="DPAPI_bad_data" xml:space="preserve">
+ <value>The data specified for decryption is bad.</value>
+ </data>
+ <data name="Empty_attribute" xml:space="preserve">
+ <value>The '{0}' attribute cannot be an empty string.</value>
+ </data>
+ <data name="EncryptedNode_not_found" xml:space="preserve">
+ <value>The section is marked as being protected. However, the &lt;EncryptedData&gt; child node was not found in the section's node. Make sure that the section is correctly encrypted.</value>
+ </data>
+ <data name="EncryptedNode_is_in_invalid_format" xml:space="preserve">
+ <value>The section is marked as being protected, but it does not have the correct format. It should contain only the &lt;EncryptedData&gt; child node.</value>
+ </data>
+ <data name="Encryption_failed" xml:space="preserve">
+ <value>Failed to encrypt the section '{0}' using provider '{1}'. Error message from the provider: {2}</value>
+ </data>
+ <data name="Expect_bool_value_for_DoNotShowUI" xml:space="preserve">
+ <value>You must specify a boolean value for doNotShowUI.</value>
+ </data>
+ <data name="Expect_bool_value_for_useMachineProtection" xml:space="preserve">
+ <value>You must specify a boolean value for useMachineProtection.</value>
+ </data>
+ <data name="IndexOutOfRange" xml:space="preserve">
+ <value>Index {0} is out of range.</value>
+ </data>
+ <data name="Invalid_enum_value" xml:space="preserve">
+ <value>The enumeration value must be one of the following: {0}.</value>
+ </data>
+ <data name="Key_container_doesnt_exist_or_access_denied" xml:space="preserve">
+ <value>The RSA key container could not be opened.</value>
+ </data>
+ <data name="Must_add_to_config_before_protecting_it" xml:space="preserve">
+ <value>The configuration section must be added to a configuration hierarchy before you can protect it.</value>
+ </data>
+ <data name="No_converter" xml:space="preserve">
+ <value>Unable to find a converter that supports conversion to/from string for the property '{0}' of type '{1}'.</value>
+ </data>
+ <data name="No_exception_information_available" xml:space="preserve">
+ <value>No information about the exception is available.</value>
+ </data>
+ <data name="Property_name_reserved" xml:space="preserve">
+ <value>A configuration property cannot have the name '{0}' because it starts with the reserved prefix 'config' or 'lock'.</value>
+ </data>
+ <data name="Item_name_reserved" xml:space="preserve">
+ <value>A configuration item alias for '{0}' cannot have the name '{1}' because it starts with the reserved prefix 'config' or 'lock'.</value>
+ </data>
+ <data name="Basicmap_item_name_reserved" xml:space="preserve">
+ <value>A configuration item cannot have the name '{0}' because it starts with the reserved prefix 'config' or 'lock'.</value>
+ </data>
+ <data name="ProtectedConfigurationProvider_not_found" xml:space="preserve">
+ <value>The protection provider '{0}' was not found.</value>
+ </data>
+ <data name="Regex_validator_error" xml:space="preserve">
+ <value>The value does not conform to the validation regex string '{0}'.</value>
+ </data>
+ <data name="String_null_or_empty" xml:space="preserve">
+ <value>The string cannot be null or empty.</value>
+ </data>
+ <data name="Subclass_validator_error" xml:space="preserve">
+ <value>The type '{0}' must be derived from the type '{1}'.</value>
+ </data>
+ <data name="Top_level_conversion_error_from_string" xml:space="preserve">
+ <value>The value of the property '{0}' cannot be parsed. The error is: {1}</value>
+ </data>
+ <data name="Top_level_conversion_error_to_string" xml:space="preserve">
+ <value>The value of the property '{0}' cannot be converted to string. The error is: {1}</value>
+ </data>
+ <data name="Top_level_validation_error" xml:space="preserve">
+ <value>The value for the property '{0}' is not valid. The error is: {1}</value>
+ </data>
+ <data name="Type_cannot_be_resolved" xml:space="preserve">
+ <value>The type '{0}' cannot be resolved. Please verify the spelling is correct or that the full type name is provided.</value>
+ </data>
+ <data name="TypeNotPublic" xml:space="preserve">
+ <value>Unable to load type '{0}' because it is not public.</value>
+ </data>
+ <data name="Unrecognized_initialization_value" xml:space="preserve">
+ <value>The configuration setting '{0}' was not recognized.</value>
+ </data>
+ <data name="UseMachineContainer_must_be_bool" xml:space="preserve">
+ <value>You must specify a boolean value for useMachineContainer.</value>
+ </data>
+ <data name="UseOAEP_must_be_bool" xml:space="preserve">
+ <value>You must specify a boolean value for useOAEP.</value>
+ </data>
+ <data name="Validation_scalar_range_violation_not_different" xml:space="preserve">
+ <value>The value must be different than {0}.</value>
+ </data>
+ <data name="Validation_scalar_range_violation_not_equal" xml:space="preserve">
+ <value>The value must be equal to {0}.</value>
+ </data>
+ <data name="Validation_scalar_range_violation_not_in_range" xml:space="preserve">
+ <value>The value must be inside the range {0}-{1}.</value>
+ </data>
+ <data name="Validation_scalar_range_violation_not_outside_range" xml:space="preserve">
+ <value>The value must not be in the range {0}-{1}.</value>
+ </data>
+ <data name="Validator_Attribute_param_not_validator" xml:space="preserve">
+ <value>Only types derived from {0} are valid validator types.</value>
+ </data>
+ <data name="Validator_does_not_support_elem_type" xml:space="preserve">
+ <value>The supplied validator does not support validating the configuration element type {0}.</value>
+ </data>
+ <data name="Validator_does_not_support_prop_type" xml:space="preserve">
+ <value>The supplied validator does not support the type of the property '{0}'.</value>
+ </data>
+ <data name="Validator_element_not_valid" xml:space="preserve">
+ <value>The configuration element '{0}' is not valid. The error is: {1}</value>
+ </data>
+ <data name="Validator_method_not_found" xml:space="preserve">
+ <value>The supplied method name '{0}' was not found. The callback method must be a public static void method with one object parameter.</value>
+ </data>
+ <data name="Validator_min_greater_than_max" xml:space="preserve">
+ <value>The upper range limit value must be greater than the lower range limit value.</value>
+ </data>
+ <data name="Validator_scalar_resolution_violation" xml:space="preserve">
+ <value>The value must have a resolution of {0}.</value>
+ </data>
+ <data name="Validator_string_invalid_chars" xml:space="preserve">
+ <value>The string cannot contain any of the following characters: '{0}'.</value>
+ </data>
+ <data name="Validator_string_max_length" xml:space="preserve">
+ <value>The string must be no more than {0} characters long.</value>
+ </data>
+ <data name="Validator_string_min_length" xml:space="preserve">
+ <value>The string must be at least {0} characters long.</value>
+ </data>
+ <data name="Validator_value_type_invalid" xml:space="preserve">
+ <value>The supplied value is not of type which the validator can process.</value>
+ </data>
+ <data name="Validator_multiple_validator_attributes" xml:space="preserve">
+ <value>Multiple validator attributes are not currently supported. The property '{0}' has more than one validator attribute associated with it.</value>
+ </data>
+ <data name="Validator_timespan_value_must_be_positive" xml:space="preserve">
+ <value>The time span value must be positive.</value>
+ </data>
+ <data name="WrongType_of_Protected_provider" xml:space="preserve">
+ <value>The type specified does not extend ProtectedConfigurationProvider class.</value>
+ </data>
+ <data name="Type_from_untrusted_assembly" xml:space="preserve">
+ <value>Type '{0}' cannot be instantiated under a partially trusted security policy (AllowPartiallyTrustedCallersAttribute is not present on the target assembly).</value>
+ </data>
+ <data name="Config_element_locking_not_supported" xml:space="preserve">
+ <value>Locking of elements or attributes within a configuration section is not supported for legacy section '{0}'.</value>
+ </data>
+ <data name="Config_element_null_instance" xml:space="preserve">
+ <value>The property '{0}' must not return null from the property's get method. Typically the getter should return base["{1}"].</value>
+ </data>
+ <data name="ConfigurationPermissionBadXml" xml:space="preserve">
+ <value>Bad Xml {0}</value>
+ </data>
+ <data name="ConfigurationPermission_Denied" xml:space="preserve">
+ <value>Request for ConfigurationPermission failed while attempting to access configuration section '{0}'. To allow all callers to access the data for this section, set section attribute 'requirePermission' equal 'false' in the configuration file where this section is declared.</value>
+ </data>
+ <data name="Section_from_untrusted_assembly" xml:space="preserve">
+ <value>Configuration section '{0}' cannot be instantiated under a partially trusted security policy (AllowPartiallyTrustedCallersAttribute is not present on the configuration section handler).</value>
+ </data>
+ <data name="Protection_provider_syntax_error" xml:space="preserve">
+ <value>A section using 'configProtectionProvider' may contain no other attributes.</value>
+ </data>
+ <data name="Protection_provider_invalid_format" xml:space="preserve">
+ <value>The configProtectionProvider attribute cannot be an empty string.</value>
+ </data>
+ <data name="Cannot_declare_or_remove_implicit_section" xml:space="preserve">
+ <value>The section '{0}' is a built-in section. It cannot be declared by the user.</value>
+ </data>
+ <data name="Config_reserved_attribute" xml:space="preserve">
+ <value>The attribute '{0}' cannot be specified because its name starts with the reserved prefix 'config' or 'lock'.</value>
+ </data>
+ <data name="Filename_in_SaveAs_is_used_already" xml:space="preserve">
+ <value>The file name '{0}' is invalid because the same file name is already referenced by the configuration hierarchy you have opened.</value>
+ </data>
+ <data name="Provider_Already_Initialized" xml:space="preserve">
+ <value>This provider instance has already been initialized.</value>
+ </data>
+ <data name="Config_provider_name_null_or_empty" xml:space="preserve">
+ <value>Provider name cannot be null or empty.</value>
+ </data>
+ <data name="CollectionReadOnly" xml:space="preserve">
+ <value>Collection is read-only.</value>
+ </data>
+ <data name="Config_source_not_under_config_dir" xml:space="preserve">
+ <value>The configSource '{0}' is invalid. It must refer to a file in the same directory or in a subdirectory as the configuration file.</value>
+ </data>
+ <data name="Config_source_invalid" xml:space="preserve">
+ <value>The configSource attribute is invalid.</value>
+ </data>
+ <data name="Location_invalid_inheritInChildApplications_in_machine_or_root_web_config" xml:space="preserve">
+ <value>InheritInChildApplications cannot be set to "false" if the location path is referring to machine.config or the root web.config.</value>
+ </data>
+ <data name="Cannot_change_both_AllowOverride_and_OverrideMode" xml:space="preserve">
+ <value>Changing both AllowOverride and OverrideMode is not supported for compatibility reasons. Please use only one or the other.</value>
+ </data>
+ <data name="Config_section_override_mode_attribute_invalid" xml:space="preserve">
+ <value>The 'overrideMode' and 'overrideModeDefault' attributes must be one of the following values: Inherited, Allow, Deny.</value>
+ </data>
+ <data name="Invalid_override_mode_declaration" xml:space="preserve">
+ <value>A &lt;location&gt; tag may contain only one of the 'allowOverride' or 'overrideMode' attributes.</value>
+ </data>
+ <data name="Config_cannot_edit_locked_configurationsection_when_mode_is_not_allow" xml:space="preserve">
+ <value>ConfigurationSection properties cannot be edited when locked but they can be unlocked by explicitly setting SectionInforamtion.OverrideMode to OverrideMode.Allow.</value>
+ </data>
+ <data name="Machine_config_file_not_found" xml:space="preserve">
+ <value>The machine.config file '{0}' was not found.</value>
+ </data>
+ <data name="ObjectDisposed_StreamClosed" xml:space="preserve">
+ <value>Cannot access a closed Stream.</value>
+ </data>
+</root>
diff --git a/src/System.Configuration/src/System.Configuration.builds b/src/System.Configuration/src/System.Configuration.builds
new file mode 100644
index 0000000000..e5272d27c7
--- /dev/null
+++ b/src/System.Configuration/src/System.Configuration.builds
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <Project Include="System.Configuration.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.Configuration/src/System.Configuration.csproj b/src/System.Configuration/src/System.Configuration.csproj
new file mode 100644
index 0000000000..7c3465ee53
--- /dev/null
+++ b/src/System.Configuration/src/System.Configuration.csproj
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>System.Configuration</AssemblyName>
+ <ProjectGuid>{B7697463-7C98-4462-BA09-67B7BF3842B6}</ProjectGuid>
+ <NuGetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ <PackageTargetFramework Condition="'$(TargetGroup)' == ''">netstandard1.7</PackageTargetFramework>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the options -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
+ <ItemGroup>
+ <Compile Include="System\Configuration\AppSettingsSection.cs" />
+ <Compile Include="System\Configuration\BaseConfigurationRecord.cs" />
+ <Compile Include="System\Configuration\CallbackValidator.cs" />
+ <Compile Include="System\Configuration\CallbackValidatorAttribute.cs" />
+ <Compile Include="System\Configuration\ClientConfigPaths.cs" />
+ <Compile Include="System\Configuration\ClientConfigurationHost.cs" />
+ <Compile Include="System\Configuration\ClientConfigurationSystem.cs" />
+ <Compile Include="System\Configuration\CommaDelimitedStringAttributeCollectionConverter.cs" />
+ <Compile Include="System\Configuration\ConfigDefinitionUpdates.cs" />
+ <Compile Include="System\Configuration\ConfigPathUtility.cs" />
+ <Compile Include="System\Configuration\Configuration.cs" />
+ <Compile Include="System\Configuration\ConfigurationAllowDefinition.cs" />
+ <Compile Include="System\Configuration\ConfigurationAllowExeDefinition.cs" />
+ <Compile Include="System\Configuration\ConfigurationCollectionAttribute.cs" />
+ <Compile Include="System\Configuration\ConfigurationConverterBase.cs" />
+ <Compile Include="System\Configuration\ConfigurationElement.cs" />
+ <Compile Include="System\Configuration\ConfigurationElementCollection.cs" />
+ <Compile Include="System\Configuration\ConfigurationElementCollectionType.cs" />
+ <Compile Include="System\Configuration\ConfigurationElementProperty.cs" />
+ <Compile Include="System\Configuration\ConfigurationErrorsException.cs" />
+ <Compile Include="System\Configuration\ConfigurationException.cs" />
+ <Compile Include="System\Configuration\ConfigurationFileMap.cs" />
+ <Compile Include="System\Configuration\ConfigurationLocation.cs" />
+ <Compile Include="System\Configuration\ConfigurationLocationCollection.cs" />
+ <Compile Include="System\Configuration\ConfigurationLockCollection.cs" />
+ <Compile Include="System\Configuration\ConfigurationLockCollectionType.cs" />
+ <Compile Include="System\Configuration\ConfigurationManager.cs" />
+ <Compile Include="System\Configuration\ConfigurationPermission.cs" />
+ <Compile Include="System\Configuration\ConfigurationProperty.cs" />
+ <Compile Include="System\Configuration\ConfigurationPropertyAttribute.cs" />
+ <Compile Include="System\Configuration\ConfigurationPropertyCollection.cs" />
+ <Compile Include="System\Configuration\ConfigurationPropertyOptions.cs" />
+ <Compile Include="System\Configuration\ConfigurationSaveMode.cs" />
+ <Compile Include="System\Configuration\ConfigurationSchemaErrors.cs" />
+ <Compile Include="System\Configuration\ConfigurationSection.cs" />
+ <Compile Include="System\Configuration\ConfigurationSectionCollection.cs" />
+ <Compile Include="System\Configuration\ConfigurationSectionGroup.cs" />
+ <Compile Include="System\Configuration\ConfigurationSectionGroupCollection.cs" />
+ <Compile Include="System\Configuration\ConfigurationUserLevel.cs" />
+ <Compile Include="System\Configuration\ConfigurationValidatorAttribute.cs" />
+ <Compile Include="System\Configuration\ConfigurationValidatorBase.cs" />
+ <Compile Include="System\Configuration\ConfigurationValue.cs" />
+ <Compile Include="System\Configuration\ConfigurationValueFlags.cs" />
+ <Compile Include="System\Configuration\ConfigurationValues.cs" />
+ <Compile Include="System\Configuration\ConfigXmlAttribute.cs" />
+ <Compile Include="System\Configuration\ConfigXmlCDataSection.cs" />
+ <Compile Include="System\Configuration\ConfigXmlComment.cs" />
+ <Compile Include="System\Configuration\ConfigXmlElement.cs" />
+ <Compile Include="System\Configuration\ConfigXmlReader.cs" />
+ <Compile Include="System\Configuration\ConfigXmlSignificantWhitespace.cs" />
+ <Compile Include="System\Configuration\ConfigXmlText.cs" />
+ <Compile Include="System\Configuration\ConfigXmlWhitespace.cs" />
+ <Compile Include="System\Configuration\ConnectionStringSettings.cs" />
+ <Compile Include="System\Configuration\ConnectionStringSettingsCollection.cs" />
+ <Compile Include="System\Configuration\ConnectionStringsSection.cs" />
+ <Compile Include="System\Configuration\ContextInformation.cs" />
+ <Compile Include="System\Configuration\DateTimeConfigurationCollection.cs" />
+ <Compile Include="System\Configuration\DateTimeConfigurationElement.cs" />
+ <Compile Include="System\Configuration\DeclarationUpdate.cs" />
+ <Compile Include="System\Configuration\DefaultSection.cs" />
+ <Compile Include="System\Configuration\DefaultValidator.cs" />
+ <Compile Include="System\Configuration\DefinitionUpdate.cs" />
+ <Compile Include="System\Configuration\ElementInformation.cs" />
+ <Compile Include="System\Configuration\EmptyImpersonationContext.cs" />
+ <Compile Include="System\Configuration\ErrorInfoXmlDocument.cs" />
+ <Compile Include="System\Configuration\ErrorsHelper.cs" />
+ <Compile Include="System\Configuration\ExceptionAction.cs" />
+ <Compile Include="System\Configuration\ExceptionUtil.cs" />
+ <Compile Include="System\Configuration\ExeConfigurationFileMap.cs" />
+ <Compile Include="System\Configuration\ExeContext.cs" />
+ <Compile Include="System\Configuration\FactoryId.cs" />
+ <Compile Include="System\Configuration\FactoryRecord.cs" />
+ <Compile Include="System\Configuration\GenericEnumConverter.cs" />
+ <Compile Include="System\Configuration\IConfigurationSectionHandler.cs" />
+ <Compile Include="System\Configuration\IgnoreSection.cs" />
+ <Compile Include="System\Configuration\IgnoreSectionHandler.cs" />
+ <Compile Include="System\Configuration\ImplicitMachineConfigHost.cs" />
+ <Compile Include="System\Configuration\InfiniteIntConverter.cs" />
+ <Compile Include="System\Configuration\InfiniteTimeSpanConverter.cs" />
+ <Compile Include="System\Configuration\IntegerValidator.cs" />
+ <Compile Include="System\Configuration\IntegerValidatorAttribute.cs" />
+ <Compile Include="System\Configuration\Internal\ConfigSystem.cs" />
+ <Compile Include="System\Configuration\Internal\ConfigurationManagerInternal.cs" />
+ <Compile Include="System\Configuration\Internal\DelegatingConfigHost.cs" />
+ <Compile Include="System\Configuration\Internal\FileVersion.cs" />
+ <Compile Include="System\Configuration\HResults.cs" />
+ <Compile Include="System\Configuration\Internal\IConfigErrorInfo.cs" />
+ <Compile Include="System\Configuration\Internal\IConfigSystem.cs" />
+ <Compile Include="System\Configuration\Internal\IConfigurationManagerHelper.cs" />
+ <Compile Include="System\Configuration\Internal\IConfigurationManagerInternal.cs" />
+ <Compile Include="System\Configuration\Internal\IInternalConfigClientHost.cs" />
+ <Compile Include="System\Configuration\Internal\IInternalConfigConfigurationFactory.cs" />
+ <Compile Include="System\Configuration\Internal\IInternalConfigHost.cs" />
+ <Compile Include="System\Configuration\Internal\IInternalConfigHostPaths.cs" />
+ <Compile Include="System\Configuration\Internal\IInternalConfigRecord.cs" />
+ <Compile Include="System\Configuration\Internal\IInternalConfigRoot.cs" />
+ <Compile Include="System\Configuration\Internal\IInternalConfigSettingsFactory.cs" />
+ <Compile Include="System\Configuration\Internal\IInternalConfigSystem.cs" />
+ <Compile Include="System\Configuration\Internal\InternalConfigConfigurationFactory.cs" />
+ <Compile Include="System\Configuration\Internal\InternalConfigEventArgs.cs" />
+ <Compile Include="System\Configuration\Internal\InternalConfigEventHandler.cs" />
+ <Compile Include="System\Configuration\Internal\InternalConfigHost.cs" />
+ <Compile Include="System\Configuration\Internal\InternalConfigRoot.cs" />
+ <Compile Include="System\Configuration\Internal\InternalConfigSettingsFactory.cs" />
+ <Compile Include="System\Configuration\Internal\StreamChangeCallback.cs" />
+ <Compile Include="System\Configuration\Internal\WriteFileContext.cs" />
+ <Compile Include="System\Configuration\InvalidPropValue.cs" />
+ <Compile Include="System\Configuration\KeyValueConfigurationCollection.cs" />
+ <Compile Include="System\Configuration\KeyValueConfigurationElement.cs" />
+ <Compile Include="System\Configuration\KeyValueInternalCollection.cs" />
+ <Compile Include="System\Configuration\LocationSectionRecord.cs" />
+ <Compile Include="System\Configuration\LocationUpdates.cs" />
+ <Compile Include="System\Configuration\LongValidator.cs" />
+ <Compile Include="System\Configuration\LongValidatorAttribute.cs" />
+ <Compile Include="System\Configuration\MgmtConfigurationRecord.cs" />
+ <Compile Include="System\Configuration\NamespaceChange.cs" />
+ <Compile Include="System\Configuration\NameValueConfigurationCollection.cs" />
+ <Compile Include="System\Configuration\NameValueConfigurationElement.cs" />
+ <Compile Include="System\Configuration\OverrideMode.cs" />
+ <Compile Include="System\Configuration\OverrideModeSetting.cs" />
+ <Compile Include="System\Configuration\PositiveTimeSpanValidator.cs" />
+ <Compile Include="System\Configuration\PositiveTimeSpanValidatorAttribute.cs" />
+ <Compile Include="System\Configuration\PrivilegedConfigurationManager.cs" />
+ <Compile Include="System\Configuration\PropertyInformation.cs" />
+ <Compile Include="System\Configuration\PropertyInformationCollection.cs" />
+ <Compile Include="System\Configuration\PropertySourceInfo.cs" />
+ <Compile Include="System\Configuration\PropertyValueOrigin.cs" />
+ <Compile Include="System\Configuration\ProtectedConfiguration.cs" />
+ <Compile Include="System\Configuration\ProtectedConfigurationProvider.cs" />
+ <Compile Include="System\Configuration\ProtectedConfigurationProviderCollection.cs" />
+ <Compile Include="System\Configuration\ProtectedConfigurationSection.cs" />
+ <Compile Include="System\Configuration\ProtectedProviderSettings.cs" />
+ <Compile Include="System\Configuration\Provider\ProviderBase.cs" />
+ <Compile Include="System\Configuration\Provider\ProviderCollection.cs" />
+ <Compile Include="System\Configuration\Provider\ProviderException.cs" />
+ <Compile Include="System\Configuration\ProviderSettings.cs" />
+ <Compile Include="System\Configuration\ProviderSettingsCollection.cs" />
+ <Compile Include="System\Configuration\RegexStringValidator.cs" />
+ <Compile Include="System\Configuration\RegexStringValidatorAttribute.cs" />
+ <Compile Include="System\Configuration\RuntimeConfigurationRecord.cs" />
+ <Compile Include="System\Configuration\SafeBitVector32.cs" />
+ <Compile Include="System\Configuration\SectionInformation.cs" />
+ <Compile Include="System\Configuration\SectionInput.cs" />
+ <Compile Include="System\Configuration\SectionRecord.cs" />
+ <Compile Include="System\Configuration\SectionUpdates.cs" />
+ <Compile Include="System\Configuration\SectionXmlInfo.cs" />
+ <Compile Include="System\Configuration\SimpleBitVector32.cs" />
+ <Compile Include="System\Configuration\StreamInfo.cs" />
+ <Compile Include="System\Configuration\StreamUpdate.cs" />
+ <Compile Include="System\Configuration\StringAttributeCollection.cs" />
+ <Compile Include="System\Configuration\StringUtil.cs" />
+ <Compile Include="System\Configuration\StringValidator.cs" />
+ <Compile Include="System\Configuration\StringValidatorAttribute.cs" />
+ <Compile Include="System\Configuration\SubclassTypeValidator.cs" />
+ <Compile Include="System\Configuration\SubclassTypeValidatorAttribute.cs" />
+ <Compile Include="System\Configuration\TimeSpanMinutesConverter.cs" />
+ <Compile Include="System\Configuration\TimeSpanMinutesOrInfiniteConverter.cs" />
+ <Compile Include="System\Configuration\TimeSpanSecondsConverter.cs" />
+ <Compile Include="System\Configuration\TimeSpanSecondsOrInfiniteConverter.cs" />
+ <Compile Include="System\Configuration\TimeSpanValidator.cs" />
+ <Compile Include="System\Configuration\TimeSpanValidatorAttribute.cs" />
+ <Compile Include="System\Configuration\TypeNameConverter.cs" />
+ <Compile Include="System\Configuration\TypeUtil.cs" />
+ <Compile Include="System\Configuration\Update.cs" />
+ <Compile Include="System\Configuration\UpdateConfigHost.cs" />
+ <Compile Include="System\Configuration\UrlPath.cs" />
+ <Compile Include="System\Configuration\ValidatorCallback.cs" />
+ <Compile Include="System\Configuration\ValidatorUtils.cs" />
+ <Compile Include="System\Configuration\WhiteSpaceTrimStringConverter.cs" />
+ <Compile Include="System\Configuration\XmlUtil.cs" />
+ <Compile Include="System\Configuration\XmlUtilWriter.cs" />
+ <Compile Include="$(CommonPath)\System\Security\IdentityHelper.cs">
+ <Link>Common\System\Security\IdentityHelper.cs</Link>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/AppSettingsSection.cs b/src/System.Configuration/src/System/Configuration/AppSettingsSection.cs
new file mode 100644
index 0000000000..09fac3281a
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/AppSettingsSection.cs
@@ -0,0 +1,144 @@
+// 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.Specialized;
+using System.IO;
+using System.Xml;
+
+namespace System.Configuration
+{
+ public sealed class AppSettingsSection : ConfigurationSection
+ {
+ private static volatile ConfigurationPropertyCollection s_properties;
+ private static volatile ConfigurationProperty s_propAppSettings;
+ private static volatile ConfigurationProperty s_propFile;
+
+ private KeyValueInternalCollection _keyValueCollection;
+
+ public AppSettingsSection()
+ {
+ EnsureStaticPropertyBag();
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => EnsureStaticPropertyBag();
+
+ internal NameValueCollection InternalSettings
+ => _keyValueCollection ?? (_keyValueCollection = new KeyValueInternalCollection(this));
+
+ [ConfigurationProperty("", IsDefaultCollection = true)]
+ public KeyValueConfigurationCollection Settings => (KeyValueConfigurationCollection)base[s_propAppSettings];
+
+ [ConfigurationProperty("file", DefaultValue = "")]
+ public string File
+ {
+ get
+ {
+ string fileValue = (string)base[s_propFile];
+ return fileValue ?? string.Empty;
+ }
+ set { base[s_propFile] = value; }
+ }
+
+ private static ConfigurationPropertyCollection EnsureStaticPropertyBag()
+ {
+ if (s_properties != null) return s_properties;
+
+ ConfigurationProperty propAppSettings = new ConfigurationProperty(
+ name: null,
+ type: typeof(KeyValueConfigurationCollection),
+ defaultValue: null,
+ options: ConfigurationPropertyOptions.IsDefaultCollection);
+
+ ConfigurationProperty propFile = new ConfigurationProperty(
+ name: "file",
+ type: typeof(string),
+ defaultValue: string.Empty,
+ options: ConfigurationPropertyOptions.None);
+
+ ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection
+ {
+ propAppSettings,
+ propFile
+ };
+
+ s_propAppSettings = propAppSettings;
+ s_propFile = propFile;
+ s_properties = properties;
+
+ return s_properties;
+ }
+
+ protected internal override object GetRuntimeObject()
+ {
+ SetReadOnly();
+ return InternalSettings; // return the read only object
+ }
+
+ protected internal override void Reset(ConfigurationElement parentSection)
+ {
+ _keyValueCollection = null;
+ base.Reset(parentSection);
+ if (!string.IsNullOrEmpty((string)base[s_propFile]))
+ {
+ // don't inherit from the parent by ignoring locks
+ SetPropertyValue(prop: s_propFile, value: null, ignoreLocks: true);
+ }
+ }
+
+ protected internal override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
+ {
+ string elementName = reader.Name;
+
+ base.DeserializeElement(reader, serializeCollectionKey);
+ if (!(File?.Length > 0)) return;
+
+ string sourceFileFullPath;
+
+ // Determine file location
+ string configFile = ElementInformation.Source;
+
+ sourceFileFullPath = string.IsNullOrEmpty(configFile)
+ ? File
+ : Path.Combine(Path.GetDirectoryName(configFile), File);
+
+ if (!IO.File.Exists(sourceFileFullPath)) return;
+ int lineOffset;
+ string rawXml;
+
+ using (Stream sourceFileStream = new FileStream(sourceFileFullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
+ using (XmlUtil xmlUtil = new XmlUtil(sourceFileStream, sourceFileFullPath, true))
+ {
+ if (xmlUtil.Reader.Name != elementName)
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_name_value_file_section_file_invalid_root, elementName),
+ xmlUtil);
+
+ lineOffset = xmlUtil.Reader.LineNumber;
+ rawXml = xmlUtil.CopySection();
+
+ // Detect if there is any XML left over after the section
+ while (!xmlUtil.Reader.EOF)
+ {
+ XmlNodeType t = xmlUtil.Reader.NodeType;
+ if (t != XmlNodeType.Comment)
+ throw new ConfigurationErrorsException(SR.Config_source_file_format, xmlUtil);
+
+ xmlUtil.Reader.Read();
+ }
+ }
+
+ ConfigXmlReader internalReader = new ConfigXmlReader(rawXml, sourceFileFullPath, lineOffset);
+ internalReader.Read();
+
+ if (internalReader.MoveToNextAttribute())
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_unrecognized_attribute, internalReader.Name),
+ (XmlReader)internalReader);
+
+ internalReader.MoveToElement();
+
+ base.DeserializeElement(internalReader, serializeCollectionKey);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/BaseConfigurationRecord.cs b/src/System.Configuration/src/System/Configuration/BaseConfigurationRecord.cs
new file mode 100644
index 0000000000..967ecb9b7e
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/BaseConfigurationRecord.cs
@@ -0,0 +1,3817 @@
+// 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.Collections.Generic;
+using System.Collections.Specialized;
+using System.Configuration.Internal;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.Versioning;
+using System.Text;
+using System.Threading;
+using System.Xml;
+
+namespace System.Configuration
+{
+ // This object represents the configuration for a request path, and is cached per-path.
+ [DebuggerDisplay("ConfigPath = {ConfigPath}")]
+ internal abstract class BaseConfigurationRecord : IInternalConfigRecord
+ {
+ protected const string NewLine = "\r\n";
+
+ internal const string KeywordTrue = "true";
+ internal const string KeywordFalse = "false";
+
+ protected const string ConfigurationTag = "configuration";
+ protected const string XmlnsAttribute = "xmlns";
+ protected const string ConfigurationNamespace = "http://schemas.microsoft.com/.NetConfiguration/v2.0";
+
+ protected const string ConfigSectionsTag = "configSections";
+
+ protected const string SectionTag = "section";
+ protected const string SectionNameAttribute = "name";
+ protected const string SectionTypeAttribute = "type";
+ protected const string SectionAllowLocationAttribute = "allowLocation";
+ protected const string SectionAllowDefinitionAttribute = "allowDefinition";
+ protected const string AllowDefinitionEverywhere = "Everywhere";
+ protected const string AllowDefinitionMachineOnly = "MachineOnly";
+ protected const string AllowDefinitionMachineToApplication = "MachineToApplication";
+ protected const string AllowDefinitionMachineToWebRoot = "MachineToWebRoot";
+ protected const string SectionAllowExeDefinitionAttribute = "allowExeDefinition";
+ protected const string AllowExeDefinitionMachineToRoaming = "MachineToRoamingUser";
+ protected const string AllowExeDefinitionMachineToLocal = "MachineToLocalUser";
+ protected const string SectionRestartonExternalChangesAttribute = "restartOnExternalChanges";
+ protected const string SectionRequirePermissionAttribute = "requirePermission";
+ internal const string SectionOverrideModeDefaultAttribute = "overrideModeDefault";
+
+ internal const string OverrideModeInherit = "Inherit";
+ internal const string OverrideModeAllow = "Allow";
+ internal const string OverrideModeDeny = "Deny";
+
+ protected const string SectionGroupTag = "sectionGroup";
+ protected const string SectionGroupNameAttribute = "name";
+ protected const string SectionGroupTypeAttribute = "type";
+
+ protected const string RemoveTag = "remove";
+ protected const string ClearTag = "clear";
+
+ protected const string LocationTag = "location";
+ protected const string LocationPathAttribute = "path";
+ internal const string LocationAllowOverrideAttribute = "allowOverride";
+ internal const string LocationOverrideModeAttribute = "overrideMode";
+ protected const string LocationInheritInChildApplicationsAttribute = "inheritInChildApplications";
+
+ protected const string ConfigSourceAttribute = "configSource";
+ internal const string ProtectionProviderAttibute = "configProtectionProvider";
+
+ protected const string FormatNewConfigFile = "<?xml version=\"1.0\" encoding=\"{0}\"?>\r\n";
+ protected const string FormatConfiguration = "<configuration>\r\n";
+ protected const string FormatConfigurationNamespace = "<configuration xmlns=\"{0}\">\r\n";
+ protected const string FormatConfigurationEndElement = "</configuration>";
+
+ protected const string FormatLocationNoPath = "<location {0} inheritInChildApplications=\"{1}\">\r\n";
+ protected const string FormatLocationPath = "<location path=\"{2}\" {0} inheritInChildApplications=\"{1}\">\r\n";
+ protected const string FormatLocationEndElement = "</location>";
+ internal const string KeywordLocationOverrideModeString = "{0}=\"{1}\"";
+ protected const string FormatSectionConfigSource = "<{0} configSource=\"{1}\" />";
+ protected const string FormatConfigSourceFile = "<?xml version=\"1.0\" encoding=\"{0}\"?>\r\n";
+ protected const string FormatSectionGroupEndElement = "</sectionGroup>";
+
+ // Class flags should only be used with the ClassFlags property.
+ protected const int ClassSupportsChangeNotifications = 0x00000001;
+ protected const int ClassSupportsRefresh = 0x00000002;
+ protected const int ClassSupportsImpersonation = 0x00000004;
+ protected const int ClassSupportsRestrictedPermissions = 0x00000008;
+ protected const int ClassSupportsKeepInputs = 0x00000010;
+ protected const int ClassSupportsDelayedInit = 0x00000020;
+ protected const int ClassIgnoreLocalErrors = 0x00000040;
+
+ // Flags to use with the _flags field.
+ protected const int ProtectedDataInitialized = 0x00000001;
+ protected const int Closed = 0x00000002;
+ protected const int PrefetchAll = 0x00000008;
+ protected const int IsAboveApplication = 0x00000020;
+ private const int ContextEvaluated = 0x00000080;
+ private const int IsLocationListResolved = 0x00000100;
+ protected const int NamespacePresentInFile = 0x00000200;
+ protected const int IsTrusted = 0x00002000;
+ protected const int SupportsChangeNotifications = 0x00010000;
+ protected const int SupportsRefresh = 0x00020000;
+ protected const int SupportsPath = 0x00040000;
+ protected const int SupportsKeepInputs = 0x00080000;
+ protected const int SupportsLocation = 0x00100000;
+
+ // Flags for Mgmt Configuration Record
+ protected const int ForceLocationWritten = 0x01000000;
+ protected const int SuggestLocationRemoval = 0x02000000;
+ protected const int NamespacePresentCurrent = 0x04000000;
+
+ internal const char ConfigPathSeparatorChar = '/';
+ internal const string ConfigPathSeparatorString = "/";
+
+ // From http://www.w3.org/Addressing/
+ // reserved = ';' | '/' | '?' | ':' | '@' | '&' | '=' | '+' | '$' | ','
+ // From Platform SDK
+ // reserved = '\' | '/' | '|' | ':' | '"' | '<' | '>'
+
+ // NOTE: If you change these strings, you must change the associated error message
+ private const string InvalidFirstSubPathCharacters = @"\./";
+ private const string InvalidLastSubPathCharacters = @"\./";
+ private const string InvalidSubPathCharactersString = @"\?:*""<>|";
+
+ private const string ProtectedConfigurationSectionTypeName = "System.Configuration.ProtectedConfigurationSection, System.Configuration";
+
+ internal const string ReservedSectionProtectedConfiguration = "configProtectedData";
+ internal static readonly char[] s_configPathSeparatorParams = { ConfigPathSeparatorChar };
+ private static string s_appConfigPath;
+
+ // Comparer used in sorting IndirectInputs.
+ private static readonly IComparer<SectionInput> s_indirectInputsComparer = new IndirectLocationInputComparer();
+ private static readonly char[] s_invalidSubPathCharactersArray = InvalidSubPathCharactersString.ToCharArray();
+ protected Hashtable _children; // configName -> record
+
+ private object _configContext; // Context for config level
+ protected string _configName; // the last part of the config path
+ protected string _configPath; // the full config path
+ protected InternalConfigRoot _configRoot; // root of configuration
+
+ private ConfigRecordStreamInfo _configStreamInfo; // stream info for the config record
+
+ // Records information about <configSections> present in this web.config file.
+ // config key -> FactoryRecord
+ protected Hashtable _factoryRecords;
+
+ protected SafeBitVector32 _flags; // state
+ private BaseConfigurationRecord _initDelayedRoot; // root of delayed initialization
+ private ConfigurationSchemaErrors _initErrors; // errors encountered during the parse of the configuration file
+
+ // Records information about sections in a <location> directive
+ // that do not apply to this configPath (sections where path != ".")
+ protected ArrayList _locationSections;
+ protected string _locationSubPath; // subPath for the config record when editing a location configuration
+ protected BaseConfigurationRecord _parent; // parent record
+ private ProtectedConfigurationSection _protectedConfig; // section containing the encryption providers
+
+ // Records information about sections that apply to this path,
+ // which may be found in this web.config file, in a parent through
+ // inheritance, or in a parent through <location>
+ // config key -> SectionRecord
+ protected Hashtable _sectionRecords;
+
+ internal BaseConfigurationRecord()
+ {
+ // not strictly necessary, but compiler spits out a warning without this initiailization
+ _flags = new SafeBitVector32();
+ }
+
+ protected abstract SimpleBitVector32 ClassFlags { get; }
+
+ internal bool HasStream => ConfigStreamInfo.HasStream;
+
+ private bool IsInitDelayed => _initDelayedRoot != null;
+
+ internal IInternalConfigHost Host => _configRoot.Host;
+
+ internal BaseConfigurationRecord Parent => _parent;
+
+ internal bool IsRootConfig => _parent == null;
+
+ internal bool IsMachineConfig => _parent == _configRoot.RootConfigRecord;
+
+ internal string LocationSubPath => _locationSubPath;
+
+ internal bool IsLocationConfig => _locationSubPath != null;
+
+ protected ConfigRecordStreamInfo ConfigStreamInfo
+ => IsLocationConfig ? _parent._configStreamInfo : _configStreamInfo;
+
+ internal string DefaultProviderName => ProtectedConfig.DefaultProvider;
+
+ private ProtectedConfigurationSection ProtectedConfig
+ {
+ get
+ {
+ if (!_flags[ProtectedDataInitialized]) InitProtectedConfigurationSection();
+ return _protectedConfig;
+ }
+ }
+
+ private bool HasFactoryRecords => _factoryRecords != null;
+
+ // Return true if there is no unique configuration information in this record.
+ internal bool IsEmpty => (_parent != null)
+ && !_initErrors.HasErrors(false)
+ && ((_sectionRecords == null) || (_sectionRecords.Count == 0))
+ && ((_factoryRecords == null) || (_factoryRecords.Count == 0))
+ && ((_locationSections == null) || (_locationSections.Count == 0));
+
+ internal object ConfigContext
+ {
+ get
+ {
+ if (!_flags[ContextEvaluated])
+ {
+ // Retrieve context for Path
+ _configContext = Host.CreateConfigurationContext(ConfigPath, LocationSubPath);
+ _flags[ContextEvaluated] = true;
+ }
+
+ return _configContext;
+ }
+ }
+
+ // Does it make sense to put use location tags in this file?
+ // In the web case this is true at any level. In the exe case
+ // this is only true for machine.config (since machine.config
+ // can really be used for any scenario)
+ internal bool RecordSupportsLocation => _flags[SupportsLocation] || IsMachineConfig;
+
+ internal Configuration CurrentConfiguration => _configRoot.CurrentConfiguration;
+
+ internal bool TypeStringTransformerIsSet => CurrentConfiguration?.TypeStringTransformerIsSet ?? false;
+
+ internal bool AssemblyStringTransformerIsSet => CurrentConfiguration?.AssemblyStringTransformerIsSet ?? false;
+
+ internal Func<string, string> TypeStringTransformer => CurrentConfiguration?.TypeStringTransformer;
+
+ internal Func<string, string> AssemblyStringTransformer => CurrentConfiguration?.AssemblyStringTransformer;
+
+ internal FrameworkName TargetFramework => CurrentConfiguration?.TargetFramework;
+
+ internal Stack SectionsStack => CurrentConfiguration == null ? new Stack() : CurrentConfiguration.SectionsStack;
+
+ public string ConfigPath => _configPath;
+
+ public string StreamName => ConfigStreamInfo.StreamName;
+
+ public bool HasInitErrors => _initErrors.HasErrors(ClassFlags[ClassIgnoreLocalErrors]);
+
+ public void ThrowIfInitErrors()
+ {
+ ThrowIfParseErrors(_initErrors);
+ }
+
+ public object GetSection(string configKey)
+ {
+ return GetSection(configKey, false, true);
+ }
+
+ public object GetLkgSection(string configKey)
+ {
+ return GetSection(configKey, true, true);
+ }
+
+ public void RefreshSection(string configKey)
+ {
+ _configRoot.ClearResult(this, configKey, true);
+ }
+
+ public void Remove()
+ {
+ _configRoot.RemoveConfigRecord(this);
+ }
+
+ // Create the factory that will evaluate configuration
+ protected abstract object CreateSectionFactory(FactoryRecord factoryRecord);
+
+ // Create the configuration object
+ protected abstract object CreateSection(bool inputIsTrusted, FactoryRecord factoryRecord,
+ SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader);
+
+ // Use the parent result in creating the child
+ protected abstract object UseParentResult(string configKey, object parentResult, SectionRecord sectionRecord);
+
+ // Return the runtime object from GetSection
+ protected abstract object GetRuntimeObject(object result);
+
+ // Determine which sections should be prefetched during the first scan.
+ private bool ShouldPrefetchRawXml(FactoryRecord factoryRecord)
+ {
+ if (_flags[PrefetchAll])
+ return true;
+
+ switch (factoryRecord.ConfigKey)
+ {
+ case ReservedSectionProtectedConfiguration:
+ case "system.diagnostics":
+ case "appSettings":
+ case "connectionStrings":
+ return true;
+ }
+
+ return Host.PrefetchSection(factoryRecord.Group, factoryRecord.Name);
+ }
+
+ internal void Init(
+ IInternalConfigRoot configRoot,
+ BaseConfigurationRecord parent,
+ string configPath,
+ string locationSubPath)
+ {
+ _initErrors = new ConfigurationSchemaErrors();
+
+ // try/catch here is only for unexpected exceptions due to errors in
+ // our own code, as we always want the configuration record to be usable
+ try
+ {
+ _configRoot = (InternalConfigRoot)configRoot;
+ _parent = parent;
+ _configPath = configPath;
+ _locationSubPath = locationSubPath;
+ _configName = ConfigPathUtility.GetName(configPath);
+
+ _configStreamInfo = IsLocationConfig ? _parent.ConfigStreamInfo : new ConfigRecordStreamInfo();
+
+ // no more initialization in case of root config
+ if (IsRootConfig)
+ return;
+
+ // determine what features we support
+ _flags[SupportsChangeNotifications] = ClassFlags[ClassSupportsChangeNotifications] &&
+ Host.SupportsChangeNotifications;
+ _flags[SupportsRefresh] = ClassFlags[ClassSupportsRefresh] && Host.SupportsRefresh;
+ _flags[SupportsKeepInputs] = ClassFlags[ClassSupportsKeepInputs] || _flags[SupportsRefresh];
+ _flags[SupportsPath] = Host.SupportsPath;
+ _flags[SupportsLocation] = Host.SupportsLocation;
+
+ // get static state based on the configPath
+ if (_flags[SupportsLocation])
+ _flags[IsAboveApplication] = Host.IsAboveApplication(_configPath);
+
+ _flags[IsTrusted] = true;
+
+ ArrayList locationSubPathInputs = null;
+
+ if (_flags[SupportsLocation])
+ {
+ // Treat location inputs from parent record
+ // as though they were bonafide sections in this record.
+ if (IsLocationConfig && (_parent._locationSections != null))
+ {
+ // Resolve paths and check for errors in location sections.
+ _parent.ResolveLocationSections();
+
+ int i = 0;
+ while (i < _parent._locationSections.Count)
+ {
+ LocationSectionRecord locationSectionRecord =
+ (LocationSectionRecord)_parent._locationSections[i];
+
+ if (!StringUtil.EqualsIgnoreCase(locationSectionRecord.SectionXmlInfo.TargetConfigPath, ConfigPath))
+ {
+ i++;
+ }
+ else
+ {
+ // remove the LocationSectionRecord from the list
+ _parent._locationSections.RemoveAt(i);
+
+ if (locationSubPathInputs == null) locationSubPathInputs = new ArrayList();
+
+ locationSubPathInputs.Add(locationSectionRecord);
+ }
+ }
+ }
+
+ // Handle indirect inputs for location config record.
+ if (IsLocationConfig && Host.IsLocationApplicable(_configPath))
+ {
+ Dictionary<string, List<SectionInput>> indirectLocationInputs = null;
+ BaseConfigurationRecord current = _parent;
+
+ // Note that the code will also go thru all parents, just like what we did
+ // with the location inputs later. But perf-wise it's okay not to merge the two loops
+ // because a Configuration object will contain at most one location config record.
+ while (!current.IsRootConfig)
+ {
+ if (current._locationSections != null)
+ {
+ current.ResolveLocationSections();
+
+ foreach (LocationSectionRecord locationSectionRecord in current._locationSections)
+ if (
+ // Check #1
+ IsLocationConfig &&
+ // Check #2.1
+ UrlPath.IsSubpath(locationSectionRecord.SectionXmlInfo.TargetConfigPath, ConfigPath) &&
+ // Check #2.2
+ UrlPath.IsSubpath(parent.ConfigPath, locationSectionRecord.SectionXmlInfo.TargetConfigPath) &&
+ // Check #3
+ !ShouldSkipDueToInheritInChildApplications(
+ locationSectionRecord.SectionXmlInfo.SkipInChildApps,
+ locationSectionRecord.SectionXmlInfo.TargetConfigPath)
+ )
+ {
+ // In order to separate these kinds of input from "file inputs" and "location inputs"
+ // we introduce a new kind of input called the "indirect location inputs".
+
+ // First add all indirect inputs per configKey to a local list.
+ // We will sort all lists after the while loop.
+ if (indirectLocationInputs == null)
+ indirectLocationInputs = new Dictionary<string, List<SectionInput>>(1);
+
+ string configKey = locationSectionRecord.SectionXmlInfo.ConfigKey;
+
+ if (!((IDictionary)indirectLocationInputs).Contains(configKey))
+ indirectLocationInputs.Add(configKey, new List<SectionInput>(1));
+
+ indirectLocationInputs[configKey].Add(
+ new SectionInput(locationSectionRecord.SectionXmlInfo,
+ locationSectionRecord.ErrorsList));
+
+ // copy the initialization errors to the record
+ if (locationSectionRecord.HasErrors)
+ _initErrors.AddSavedLocalErrors(locationSectionRecord.Errors);
+ }
+ }
+
+ current = current._parent;
+ }
+
+ if (indirectLocationInputs != null)
+ {
+ // Add indirect inputs per configKey
+ foreach (KeyValuePair<string, List<SectionInput>> keyValuePair in indirectLocationInputs)
+ {
+ List<SectionInput> inputsPerConfigKey = keyValuePair.Value;
+ string configKey = keyValuePair.Key;
+
+ // We have to sort the indirect inputs
+ // 1. First by the location tag's target config path, and if they're the same,
+ // 2. Then by the location tag's definition config path.
+ inputsPerConfigKey.Sort(s_indirectInputsComparer);
+
+ // Add them to the section record.
+ // In the sorted list, the closest parent is at the beginning of the
+ // list, which is what we'll add first.
+ SectionRecord sectionRecord = EnsureSectionRecord(configKey, true);
+ Debug.Assert(inputsPerConfigKey.Count > 0, "We won't get here unless we have inputs.");
+ foreach (SectionInput sectionInput in inputsPerConfigKey)
+ sectionRecord.AddIndirectLocationInput(sectionInput);
+
+ DebugValidateIndirectInputs(sectionRecord);
+ }
+ }
+ }
+
+ // Add location inputs that apply to this path, all the way up the parent hierarchy.
+ if (Host.IsLocationApplicable(_configPath))
+ {
+ BaseConfigurationRecord current = _parent;
+ while (!current.IsRootConfig)
+ {
+ if (current._locationSections != null)
+ {
+ current.ResolveLocationSections();
+ foreach (LocationSectionRecord locationSectionRecord in current._locationSections)
+ if (StringUtil.EqualsIgnoreCase(locationSectionRecord.SectionXmlInfo.TargetConfigPath, _configPath) &&
+ !ShouldSkipDueToInheritInChildApplications(locationSectionRecord.SectionXmlInfo.SkipInChildApps))
+ {
+ // add the location input for this section
+ SectionRecord sectionRecord =
+ EnsureSectionRecord(locationSectionRecord.ConfigKey, true);
+ SectionInput sectionInput = new SectionInput(
+ locationSectionRecord.SectionXmlInfo, locationSectionRecord.ErrorsList);
+
+ sectionRecord.AddLocationInput(sectionInput);
+
+ // copy the initialization errors to the record
+ if (locationSectionRecord.HasErrors)
+ _initErrors.AddSavedLocalErrors(locationSectionRecord.Errors);
+ }
+ }
+
+ current = current._parent;
+ }
+ }
+ }
+
+ if (!IsLocationConfig)
+ {
+ // If config file exists, open it and parse it once so we can
+ // find what to evaluate later.
+ InitConfigFromFile();
+ }
+ else
+ {
+ // Add location sections for this record as bonafide sections.
+ if (locationSubPathInputs == null) return;
+ foreach (LocationSectionRecord locationSectionRecord in locationSubPathInputs)
+ {
+ // add the file input
+ SectionRecord sectionRecord = EnsureSectionRecord(locationSectionRecord.ConfigKey, true);
+ SectionInput sectionInput = new SectionInput(locationSectionRecord.SectionXmlInfo,
+ locationSectionRecord.ErrorsList);
+ sectionRecord.AddFileInput(sectionInput);
+
+ // copy the initialization errors to the record
+ if (locationSectionRecord.HasErrors)
+ _initErrors.AddSavedLocalErrors(locationSectionRecord.Errors);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ // Capture all exceptions and include them in initialization errors.
+ string streamname = ConfigStreamInfo?.StreamName;
+
+ _initErrors.AddError(
+ ExceptionUtil.WrapAsConfigException(SR.Config_error_loading_XML_file, e, streamname, 0),
+ ExceptionAction.Global);
+ }
+ }
+
+ private void InitConfigFromFile()
+ {
+ bool implicitSectionsAdded = false;
+
+ try
+ {
+ // If initialization should be delayed, do not read the file.
+ if (ClassFlags[ClassSupportsDelayedInit] && Host.IsInitDelayed(this))
+ {
+ // determine the root of delayed initialization
+ _initDelayedRoot = _parent._initDelayedRoot ?? this;
+ }
+ else
+ {
+ // This parent of a record that is not initDelayed must also
+ // not be initDelayed.
+ Debug.Assert(!_parent.IsInitDelayed, "!_parent.IsInitDelayed");
+
+ // Get the stream name. Note that this may be an expensive operation
+ // for the client configuration host, which is why it comes after the
+ // check for delayed init.
+ ConfigStreamInfo.StreamName = Host.GetStreamName(_configPath);
+ if (!string.IsNullOrEmpty(ConfigStreamInfo.StreamName))
+ {
+ // Lets listen to the stream
+ ConfigStreamInfo.StreamVersion = MonitorStream(null, null, ConfigStreamInfo.StreamName);
+ using (Stream stream = Host.OpenStreamForRead(ConfigStreamInfo.StreamName))
+ {
+ if (stream == null)
+ {
+ // There is no stream to load from
+ return;
+ }
+
+ ConfigStreamInfo.HasStream = true;
+
+ // Determine whether or not to prefetch.
+ _flags[PrefetchAll] = Host.PrefetchAll(_configPath, ConfigStreamInfo.StreamName);
+
+ using (XmlUtil xmlUtil = new XmlUtil(stream, ConfigStreamInfo.StreamName, true, _initErrors))
+ {
+ ConfigStreamInfo.StreamEncoding = xmlUtil.Reader.Encoding;
+
+ // Read the factories
+ Hashtable factoryList = ScanFactories(xmlUtil);
+ _factoryRecords = factoryList;
+
+ // Add implicit sections before scanning sections
+ AddImplicitSections(null);
+ implicitSectionsAdded = true;
+
+ // Read the sections themselves
+ if (xmlUtil.Reader.Depth == 1) ScanSections(xmlUtil);
+ }
+ }
+ }
+ }
+ }
+ catch (XmlException e)
+ {
+ // Capture all exceptions and include them in _initErrors so execution in Init can continue.
+
+ // Treat invalid XML as unrecoverable by replacing all errors with the XML error.
+ _initErrors.SetSingleGlobalError(
+ ExceptionUtil.WrapAsConfigException(SR.Config_error_loading_XML_file, e,
+ ConfigStreamInfo.StreamName, 0));
+ }
+ catch (Exception e)
+ {
+ _initErrors.AddError(
+ ExceptionUtil.WrapAsConfigException(SR.Config_error_loading_XML_file, e,
+ ConfigStreamInfo.StreamName, 0),
+ ExceptionAction.Global);
+ }
+
+ // If there are global errors that make all input invalid,
+ // reset our state so that inherited configuration can still be used,
+ // including location sections that apply to this file.
+ if (_initErrors.HasGlobalErrors)
+ {
+ // Parsing of a section may have been in progress when the exception
+ // was thrown, so clear any accumulated local errors.
+ _initErrors.ResetLocalErrors();
+
+ // Stop monitoring any configSource streams, but still continue
+ // to monitor the main config file if it was successfully monitored.
+ HybridDictionary streamInfos = null;
+ lock (this)
+ {
+ if (ConfigStreamInfo.HasStreamInfos)
+ {
+ streamInfos = ConfigStreamInfo.StreamInfos;
+ ConfigStreamInfo.ClearStreamInfos();
+
+ if (!string.IsNullOrEmpty(ConfigStreamInfo.StreamName))
+ {
+ StreamInfo fileStreamInfo = (StreamInfo)streamInfos[ConfigStreamInfo.StreamName];
+
+ // add this file's streaminfo to the now empty list
+ if (fileStreamInfo != null)
+ {
+ streamInfos.Remove(ConfigStreamInfo.StreamName);
+ ConfigStreamInfo.StreamInfos.Add(ConfigStreamInfo.StreamName, fileStreamInfo);
+ }
+ }
+ }
+ }
+
+ // Stop monitoring streams outside the lock, to prevent deadlock.
+ if (streamInfos != null)
+ {
+ foreach (StreamInfo streamInfo in streamInfos.Values)
+ if (streamInfo.IsMonitored)
+ Host.StopMonitoringStreamForChanges(streamInfo.StreamName, ConfigStreamInfo.CallbackDelegate);
+ }
+
+ // Remove file input
+ if (_sectionRecords != null)
+ {
+ List<SectionRecord> removes = null;
+ foreach (SectionRecord sectionRecord in _sectionRecords.Values)
+ {
+ Debug.Assert(!sectionRecord.HasIndirectLocationInputs,
+ "Don't expect to have any IndirectLocationInputs because location config record shouldn't call InitConfigFromFile");
+
+ if (sectionRecord.HasLocationInputs)
+ {
+ // Remove any file input
+ sectionRecord.RemoveFileInput();
+ }
+ else
+ {
+ // Remove the entire section record
+ if (removes == null) removes = new List<SectionRecord>();
+
+ removes.Add(sectionRecord);
+ }
+ }
+
+ if (removes != null)
+ {
+ foreach (SectionRecord sectionRecord in removes)
+ _sectionRecords.Remove(sectionRecord.ConfigKey);
+ }
+ }
+
+ // Remove all location section input defined here
+ _locationSections?.Clear();
+
+ // Remove all factory records
+ _factoryRecords?.Clear();
+ }
+
+ if (!implicitSectionsAdded)
+ {
+ // Always add implicit sections no matter we have a file or not.
+ AddImplicitSections(null);
+ }
+ }
+
+ // Refresh the Factory Record for a particular section.
+ private void RefreshFactoryRecord(string configKey)
+ {
+ Hashtable factoryList = null;
+ FactoryRecord factoryRecord = null;
+
+ ConfigurationSchemaErrors errors = new ConfigurationSchemaErrors();
+
+ // Get Updated Factory List from File
+ int lineNumber = 0;
+ try
+ {
+ using (Stream stream = Host.OpenStreamForRead(ConfigStreamInfo.StreamName))
+ {
+ if (stream != null)
+ {
+ ConfigStreamInfo.HasStream = true;
+
+ using (XmlUtil xmlUtil = new XmlUtil(stream, ConfigStreamInfo.StreamName, true, errors))
+ {
+ try
+ {
+ factoryList = ScanFactories(xmlUtil);
+ ThrowIfParseErrors(xmlUtil.SchemaErrors);
+ }
+ catch
+ {
+ lineNumber = xmlUtil.LineNumber;
+ throw;
+ }
+ }
+ }
+ }
+
+ // Add implicit sections to the factory list
+ if (factoryList == null)
+ {
+ // But if factoryList isn't found in this config, we still try to
+ // add implicit sections to an empty factoryList.
+ factoryList = new Hashtable();
+ }
+
+ AddImplicitSections(factoryList);
+ factoryRecord = (FactoryRecord)factoryList[configKey];
+ }
+
+ // Guarantee that exceptions contain the name of the stream and an approximate line number if available.
+ // And don't allow frames up the stack to run exception filters while impersonated.
+ catch (Exception e)
+ {
+ errors.AddError(
+ ExceptionUtil.WrapAsConfigException(SR.Config_error_loading_XML_file, e,
+ ConfigStreamInfo.StreamName, lineNumber),
+ ExceptionAction.Global);
+ }
+
+ // Set/Add/Remove Record
+ // Note that the _factoryRecords hashtable is protected by the hierarchy lock.
+ if ((factoryRecord != null) || HasFactoryRecords) EnsureFactories()[configKey] = factoryRecord;
+
+ // Throw accumulated errors
+ ThrowIfParseErrors(errors);
+ }
+
+ private object GetSection(string configKey, bool getLkg, bool checkPermission)
+ {
+ object result;
+ object resultRuntimeObject;
+
+ // Note that GetSectionRecursive may invalidate this record,
+ // so there should be no further references to 'this' after the call.
+ GetSectionRecursive(
+ configKey,
+ getLkg,
+ checkPermission,
+ getRuntimeObject: true,
+ requestIsHere: true,
+ result: out result,
+ resultRuntimeObject: out resultRuntimeObject);
+
+ return resultRuntimeObject;
+ }
+
+ private void GetSectionRecursive(
+ string configKey, bool getLkg, bool checkPermission, bool getRuntimeObject, bool requestIsHere,
+ out object result, out object resultRuntimeObject)
+ {
+ result = null;
+ resultRuntimeObject = null;
+
+#if DEBUG
+ Debug.Assert(requestIsHere || !checkPermission, "requestIsHere || !checkPermission");
+ if (getLkg)
+ {
+ Debug.Assert(getRuntimeObject, "getRuntimeObject == true");
+ Debug.Assert(requestIsHere, "requestIsHere == true");
+ }
+#endif
+
+ object tmpResult = null;
+ object tmpResultRuntimeObject = null;
+
+ // Throw errors from initial parse, if any.
+ if (!getLkg) ThrowIfInitErrors();
+
+ // check for a cached result
+ bool hasResult = false;
+ SectionRecord sectionRecord = GetSectionRecord(configKey, getLkg);
+ if ((sectionRecord != null) && sectionRecord.HasResult)
+ {
+ // Results should never be stored if the section has errors.
+ Debug.Assert(!sectionRecord.HasErrors, "!sectionRecord.HasErrors");
+
+ // Create the runtime object if requested and does not yet exist.
+ if (getRuntimeObject && !sectionRecord.HasResultRuntimeObject)
+ {
+ try
+ {
+ sectionRecord.ResultRuntimeObject = GetRuntimeObject(sectionRecord.Result);
+ }
+ catch
+ {
+ // Ignore the error if we are attempting to retreive
+ // the last known good configuration.
+ if (!getLkg) throw;
+ }
+ }
+
+ // Get the cached result.
+ if (!getRuntimeObject || sectionRecord.HasResultRuntimeObject)
+ {
+ tmpResult = sectionRecord.Result;
+ if (getRuntimeObject) tmpResultRuntimeObject = sectionRecord.ResultRuntimeObject;
+
+ hasResult = true;
+ }
+ }
+
+ // If there is no cached result, get the parent's section,
+ // then merge it with our own input if we have any.
+ if (!hasResult)
+ {
+ bool hasInput = (sectionRecord != null) && sectionRecord.HasInput;
+
+ // We want to cache results in a section record if:
+ // - The request is made at this level, and so is likely to be
+ // made here again.
+ // OR
+ // - The section has input, in which case we want to
+ // avoid evaluating the same input multiple times.
+ bool cacheResults = requestIsHere || hasInput;
+
+ try
+ {
+ // We need to get a factory record to:
+ // - Check whether the caller has permission to access a section.
+ // - Determine if this is the root declaration of a config section,
+ // and thus the termination point for recursion.
+ // - Get a factory that can create a configuration section.
+ //
+ // Since most factories will be declared in machine.config and not in
+ // child config files, we do not optimize for checking whether a
+ // factory record is the root declaration, as the calculation at
+ // machine.config is trivial.
+ //
+ // It WILL be common in web scenarios for there to be
+ // deep hierarchies of config files, most of which have
+ // sparse input. Therefore we do not want to retreive a
+ // factory record if it is not necessary to do so, as
+ // it would always lead to an order N-squared operation,
+ // where N is the depth of the config hierarchy.
+ //
+ // We can skip the reteival of a factory record if:
+ // - This is the recursive call to GetSectionRecursive,
+ // AND
+ // - There is no section input at this level,
+ // AND
+ // - No factory is declared at this level.
+ //
+ // In this case, we'll simply continue the recursion to our parent.
+
+ FactoryRecord factoryRecord;
+ bool isRootDeclaration;
+
+ if (requestIsHere)
+ {
+ // Ensure that we have a valid factory record and a valid factory
+ // for creating sections when a request for a section is first
+ // made.
+ factoryRecord = FindAndEnsureFactoryRecord(configKey, out isRootDeclaration);
+
+ // If initialization is delayed, complete initialization if:
+ // - We can't find the requested factory, and it therefore
+ // may be in the file we haven't yet read,
+ // OR
+ // - The definition of that factory is allowed at
+ // levels of the config hierarchy that have not
+ // been initialized.
+ //
+ // This works for client config scenarios because the default
+ // for AllowExeDefinition is MachineToApplication. It would not
+ // be useful for Web scenarios, as most sections can be requested
+ // Everywhere.
+ //
+ // Note that configuration errors that may be present in the
+ // file where intialization is delayed will be ignored, and
+ // thus the order in which configuration sections are requested
+ // will affect results. This is considered OK as it is very
+ // expensive to determine configuration paths to
+ // client user configuration files, which aren't needed by
+ // most applications.
+ if (IsInitDelayed
+ && ((factoryRecord == null)
+ ||
+ _initDelayedRoot.IsDefinitionAllowed(factoryRecord.AllowDefinition,
+ factoryRecord.AllowExeDefinition)))
+ {
+ // We are going to remove this record, so get any data we need
+ // before the reference to 'this' becomes invalid.
+ string configPath = _configPath;
+ InternalConfigRoot configRoot = _configRoot;
+
+ // Tell the host to no longer permit delayed initialization.
+ Host.RequireCompleteInit(_initDelayedRoot);
+
+ // Removed config at the root of where initialization is delayed.
+ _initDelayedRoot.Remove();
+
+ // Get the config record for this config path
+ BaseConfigurationRecord newRecord =
+ (BaseConfigurationRecord)configRoot.GetConfigRecord(configPath);
+
+ // Repeat the call to GetSectionRecursive
+ newRecord.GetSectionRecursive(
+ configKey, getLkg, checkPermission,
+ getRuntimeObject, requestIsHere,
+ out result, out resultRuntimeObject);
+
+ // Return and make no more references to this record.
+ return;
+ }
+
+ // For compatibility with previous versions,
+ // return null if the section is not found
+ // or is a group.
+ if ((factoryRecord == null) || factoryRecord.IsGroup) return;
+
+ // Use the factory record's copy of the configKey,
+ // so that we don't store more than one instance
+ // of the same configKey.
+ configKey = factoryRecord.ConfigKey;
+ }
+ else
+ {
+ if (hasInput)
+ {
+ // We'll need a factory to evaluate the input.
+ factoryRecord = FindAndEnsureFactoryRecord(configKey, out isRootDeclaration);
+ Debug.Assert(factoryRecord != null, "factoryRecord != null");
+ }
+ else
+ {
+ // We don't need a factory record unless this is the root declaration.
+ // We know it is not the root declaration if there is no factory
+ // declared here. This is important to avoid a walk up the config
+ // hierachy when there is no input in this record.
+ factoryRecord = GetFactoryRecord(configKey, false);
+ if (factoryRecord == null) isRootDeclaration = false;
+ else
+ {
+ factoryRecord = FindAndEnsureFactoryRecord(configKey, out isRootDeclaration);
+ Debug.Assert(factoryRecord != null, "factoryRecord != null");
+ }
+ }
+ }
+
+ // We need a factory record to check permission.
+ Debug.Assert(!checkPermission || (factoryRecord != null),
+ "!checkPermission || factoryRecord != null");
+
+ // If this is the root declaration, then we always want to cache
+ // the result, in order to prevent the section default from being
+ // created multiple times.
+ if (isRootDeclaration) cacheResults = true;
+
+ // We'll need a section record to cache results,
+ // and maybe to use in creating the section default.
+ if ((sectionRecord == null) && cacheResults) sectionRecord = EnsureSectionRecord(configKey, true);
+
+ // Retrieve the parent's runtime object if the runtimeObject
+ // is requested, and we are not going to merge that input
+ // with input in this section.
+ bool getParentRuntimeObject = getRuntimeObject && !hasInput;
+
+ object parentResult;
+ object parentResultRuntimeObject;
+ if (isRootDeclaration)
+ {
+ // Create the default section.
+ //
+ // Use the existing section record to create it if there is no input,
+ // so that the cached result is attached to the correct record.
+ SectionRecord sectionRecordForDefault = hasInput ? null : sectionRecord;
+ CreateSectionDefault(configKey, getParentRuntimeObject, factoryRecord, sectionRecordForDefault,
+ out parentResult, out parentResultRuntimeObject);
+ }
+ else
+ {
+ // Get the parent section.
+ _parent.GetSectionRecursive(
+ configKey: configKey,
+ getLkg: false,
+ checkPermission: false,
+ getRuntimeObject: getParentRuntimeObject,
+ requestIsHere: false,
+ result: out parentResult,
+ resultRuntimeObject: out parentResultRuntimeObject);
+ }
+
+ if (hasInput)
+ {
+ // Evaluate the input.
+ //
+ // If Evaluate() encounters an error, it may not throw an exception
+ // when getLkg == true.
+ //
+ // The complete success of the evaluation is determined by the return value.
+ bool success = Evaluate(factoryRecord, sectionRecord, parentResult, getLkg, getRuntimeObject,
+ out tmpResult, out tmpResultRuntimeObject);
+
+ Debug.Assert(success || getLkg, "success || getLkg");
+
+ if (!success)
+ {
+ Debug.Assert(getLkg, "getLkg == true");
+ // Do not cache partial results if getLkg was specified.
+ cacheResults = false;
+ }
+ }
+ else
+ {
+ // If we are going to cache results here, we will need
+ // to create a copy in the case of MgmtConfigurationRecord -
+ // otherwise we could inadvertently return the parent to the user,
+ // which could then be modified.
+ if (sectionRecord != null)
+ {
+ tmpResult = UseParentResult(configKey, parentResult, sectionRecord);
+ if (getRuntimeObject)
+ {
+ // If the parent result is the same as the parent runtime object,
+ // then use the same copy of the parent result for our own runtime object.
+ if (ReferenceEquals(parentResult, parentResultRuntimeObject))
+ tmpResultRuntimeObject = tmpResult;
+ else
+ {
+ tmpResultRuntimeObject = UseParentResult(configKey, parentResultRuntimeObject,
+ sectionRecord);
+ }
+ }
+ }
+ else
+ {
+ Debug.Assert(!requestIsHere, "!requestIsHere");
+
+ // We don't need to make a copy if we are not storing
+ // the result, and thus not returning the result to the
+ // caller of GetSection.
+ tmpResult = parentResult;
+ tmpResultRuntimeObject = parentResultRuntimeObject;
+ }
+ }
+
+ // Determine which permissions are required of the caller.
+ if (cacheResults || checkPermission)
+ {
+ bool requirePermission = factoryRecord.RequirePermission;
+
+ // Cache the results.
+ if (cacheResults)
+ {
+ if (sectionRecord == null) sectionRecord = EnsureSectionRecord(configKey, true);
+
+ sectionRecord.Result = tmpResult;
+ if (getRuntimeObject) sectionRecord.ResultRuntimeObject = tmpResultRuntimeObject;
+
+ sectionRecord.RequirePermission = requirePermission;
+ }
+ }
+
+ hasResult = true;
+ }
+ catch
+ {
+ // Ignore the error if we are attempting to retreive
+ // the last known good configuration.
+ if (!getLkg) throw;
+ }
+
+ // If we don't have a result, ask our parent for its
+ // last known good result.
+ if (!hasResult)
+ {
+ Debug.Assert(getLkg, "getLkg == true");
+
+ _parent.GetSectionRecursive(
+ configKey,
+ getLkg: true,
+ checkPermission: checkPermission,
+ getRuntimeObject: true,
+ requestIsHere: true,
+ result: out result,
+ resultRuntimeObject: out resultRuntimeObject);
+
+ return;
+ }
+ }
+
+ // Return the results.
+ result = tmpResult;
+ if (getRuntimeObject) resultRuntimeObject = tmpResultRuntimeObject;
+ }
+
+ protected void CreateSectionDefault(
+ string configKey, bool getRuntimeObject, FactoryRecord factoryRecord, SectionRecord sectionRecord,
+ out object result, out object resultRuntimeObject)
+ {
+ SectionRecord sectionRecordForDefault = sectionRecord ?? new SectionRecord(configKey);
+
+ object tmpResult = CallCreateSection(true, factoryRecord, sectionRecordForDefault, null, null, null, -1);
+ object tmpResultRuntimeObject = getRuntimeObject ? GetRuntimeObject(tmpResult) : null;
+
+ result = tmpResult;
+ resultRuntimeObject = tmpResultRuntimeObject;
+ }
+
+ // Check if an input should be skipped based on inheritInChildApplications setting.
+ //
+ // If skipInChildApps == true (it means inheritInChildApplications=="false" in the location tag):
+ //
+ // - If _flags[IsAboveApplication]==true, that means the app pointed to by _configPath is above of the
+ // current running app. In another word, the running app is a child app of the app pointed to by _configPath.
+ // In this case, we should skip the input.
+ //
+ // - If _flags[IsAboveApplication]==false, that means the app pointed to by _configPath == current running app.
+ // In this case it's okay to use the input.
+ private bool ShouldSkipDueToInheritInChildApplications(bool skipInChildApps)
+ {
+ return skipInChildApps && _flags[IsAboveApplication];
+ }
+
+ // configPath - The config path of the config record to which a location tag points to.
+ private bool ShouldSkipDueToInheritInChildApplications(bool skipInChildApps, string configPath)
+ {
+ return skipInChildApps && Host.IsAboveApplication(configPath);
+ }
+
+ // Evaluate the input.
+ //
+ // If Evaluate() encounters an error, it may not throw an exception
+ // when getLkg == true.
+ //
+ // The complete success of the evaluation is determined by the return value.
+ private bool Evaluate(
+ FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentResult,
+ bool getLkg, bool getRuntimeObject, out object result, out object resultRuntimeObject)
+ {
+ result = null;
+ resultRuntimeObject = null;
+
+ // Store results in temporary variables, because we don't want to return
+ // results if an exception is thrown.
+ object tmpResult = null;
+ object tmpResultRuntimeObject = null;
+
+ // Factory record should be error-free.
+ Debug.Assert(!factoryRecord.HasErrors, "!factoryRecord.HasErrors");
+
+ // We should have some input
+ Debug.Assert(sectionRecord.HasInput, "sectionRecord.HasInput");
+
+ // Grab inputs before checking result,
+ // as inputs may be cleared once the result is set.
+ List<SectionInput> locationInputs = sectionRecord.LocationInputs;
+ List<SectionInput> indirectLocationInputs = sectionRecord.IndirectLocationInputs;
+ SectionInput fileInput = sectionRecord.FileInput;
+
+ Debug.Assert(!(IsLocationConfig && getLkg),
+ "Don't expect getLkg to be true when we're dealing with a location config record");
+
+ // Now that we have our inputs, lets check if there
+ // is a result, because if there is, our inputs might
+ // have been invalidated.
+ bool success = false;
+ if (sectionRecord.HasResult)
+ {
+ // Results should never be stored if the section has errors.
+ Debug.Assert(!sectionRecord.HasErrors, "!sectionRecord.HasErrors");
+
+ // Create the runtime object if requested and it does not yet exist.
+ if (getRuntimeObject && !sectionRecord.HasResultRuntimeObject)
+ {
+ try
+ {
+ sectionRecord.ResultRuntimeObject = GetRuntimeObject(sectionRecord.Result);
+ }
+ catch
+ {
+ // Ignore the error if we are attempting to retreive
+ // the last known good configuration.
+ if (!getLkg) throw;
+ }
+ }
+
+ // Get the cached result.
+ if (!getRuntimeObject || sectionRecord.HasResultRuntimeObject)
+ {
+ tmpResult = sectionRecord.Result;
+ if (getRuntimeObject) tmpResultRuntimeObject = sectionRecord.ResultRuntimeObject;
+
+ success = true;
+ }
+ }
+
+ if (!success)
+ {
+ Exception savedException = null;
+ try
+ {
+ string configKey = factoryRecord.ConfigKey;
+ string[] keys = configKey.Split(s_configPathSeparatorParams);
+ object currentResult = parentResult;
+
+ // Evaluate indirectLocationInputs. Used only in location config record.
+ // See the comment for VSWhidbey 540184 in Init() for more details.
+ if (indirectLocationInputs != null)
+ {
+ Debug.Assert(IsLocationConfig,
+ "indirectLocationInputs is non-null only in location config record");
+ foreach (SectionInput input in indirectLocationInputs)
+ {
+ if (!input.HasResult)
+ {
+ input.ThrowOnErrors();
+ input.Result = EvaluateOne(keys, input, true, factoryRecord, sectionRecord,
+ currentResult);
+ }
+
+ currentResult = input.Result;
+ }
+ }
+
+ // Evaluate location inputs
+ if (locationInputs != null)
+ {
+ foreach (SectionInput locationInput in locationInputs)
+ {
+ if (!locationInput.HasResult)
+ {
+ locationInput.ThrowOnErrors();
+ locationInput.Result = EvaluateOne(keys, locationInput, true, factoryRecord,
+ sectionRecord, currentResult);
+ }
+
+ currentResult = locationInput.Result;
+ }
+ }
+
+ // Evaluate file input
+ if (fileInput != null)
+ {
+ if (!fileInput.HasResult)
+ {
+ fileInput.ThrowOnErrors();
+ bool isTrusted = _flags[IsTrusted];
+ fileInput.Result = EvaluateOne(keys, fileInput, isTrusted, factoryRecord, sectionRecord,
+ currentResult);
+ }
+
+ currentResult = fileInput.Result;
+ }
+ else
+ {
+ // The section needs its own copy of the result that is distinct
+ // from its location parent result.
+ //
+ // Please note that this is needed only in design-time because any
+ // change to the section shouldn't go to the locationInput.Result.
+ //
+ // In runtime, UseParentResult does nothing.
+ Debug.Assert((locationInputs != null) || (indirectLocationInputs != null),
+ "locationInputs != null || indirectLocationInputs != null");
+ currentResult = UseParentResult(configKey, currentResult, sectionRecord);
+ }
+
+ if (getRuntimeObject) tmpResultRuntimeObject = GetRuntimeObject(currentResult);
+
+ tmpResult = currentResult;
+ success = true;
+ }
+ catch (Exception e)
+ {
+ // Catch the exception if LKG is requested and we have
+ // location input to fall back on.
+ if (getLkg && (locationInputs != null)) savedException = e;
+ else throw;
+ }
+
+ // If getLkg, then return a result from the last valid location input.
+ if (!success)
+ {
+ Debug.Assert(getLkg, "getLkg == true");
+
+ int i = locationInputs.Count;
+ while (--i >= 0)
+ {
+ SectionInput locationInput = locationInputs[i];
+ if (!locationInput.HasResult) continue;
+ if (getRuntimeObject && !locationInput.HasResultRuntimeObject)
+ {
+ try
+ {
+ locationInput.ResultRuntimeObject = GetRuntimeObject(locationInput.Result);
+ }
+ catch { }
+ }
+
+ if (getRuntimeObject && !locationInput.HasResultRuntimeObject) continue;
+ tmpResult = locationInput.Result;
+ if (getRuntimeObject) tmpResultRuntimeObject = locationInput.ResultRuntimeObject;
+
+ break;
+ }
+
+ if (i < 0) throw savedException;
+ }
+ }
+
+ // If evaluation was successful, we can remove any saved rawXml.
+ if (success && !_flags[SupportsKeepInputs]) sectionRecord.ClearRawXml();
+
+ result = tmpResult;
+ if (getRuntimeObject) resultRuntimeObject = tmpResultRuntimeObject;
+
+ return success;
+ }
+
+ private object EvaluateOne(
+ string[] keys, SectionInput input, bool isTrusted,
+ FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentResult)
+ {
+ object result;
+ try
+ {
+ ConfigXmlReader reader = GetSectionXmlReader(keys, input);
+ if (reader == null)
+ {
+ // If section is not found in a file, use the parent result
+ result = UseParentResult(factoryRecord.ConfigKey, parentResult, sectionRecord);
+ }
+ else
+ {
+ result = CallCreateSection(
+ isTrusted, factoryRecord, sectionRecord, parentResult,
+ reader, input.SectionXmlInfo.Filename, input.SectionXmlInfo.LineNumber);
+ }
+ }
+ catch (Exception e)
+ {
+ throw ExceptionUtil.WrapAsConfigException(
+ string.Format(SR.Config_exception_creating_section, factoryRecord.ConfigKey),
+ e, input.SectionXmlInfo);
+ }
+
+ return result;
+ }
+
+ private ConfigXmlReader FindSection(string[] keys, SectionXmlInfo sectionXmlInfo, out int lineNumber)
+ {
+ lineNumber = 0;
+ ConfigXmlReader section = null;
+
+ using (Stream stream = Host.OpenStreamForRead(sectionXmlInfo.Filename))
+ {
+ if (!_flags[SupportsRefresh]
+ &&
+ ((stream == null) || HasStreamChanged(sectionXmlInfo.Filename, sectionXmlInfo.StreamVersion)))
+ {
+ throw new ConfigurationErrorsException(SR.Config_file_has_changed,
+ sectionXmlInfo.Filename, 0);
+ }
+
+ if (stream == null) return null;
+
+ // CONSIDER: In refresh case, need to recheck validity of file - can't make assumptions
+ using (XmlUtil xmlUtil = new XmlUtil(stream, sectionXmlInfo.Filename, true))
+ {
+ if (sectionXmlInfo.SubPath == null)
+ section = FindSectionRecursive(keys, 0, xmlUtil, ref lineNumber);
+ else
+ {
+ // search children of <configuration> for <location>
+ xmlUtil.ReadToNextElement();
+ while (xmlUtil.Reader.Depth > 0)
+ {
+ if (xmlUtil.Reader.Name == LocationTag)
+ {
+ bool locationValid = false;
+ string locationSubPathAttribute =
+ xmlUtil.Reader.GetAttribute(LocationPathAttribute);
+
+ try
+ {
+ locationSubPathAttribute =
+ NormalizeLocationSubPath(locationSubPathAttribute, xmlUtil);
+ locationValid = true;
+ }
+ catch (ConfigurationException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.NonSpecific);
+ }
+
+ if (locationValid &&
+ StringUtil.EqualsIgnoreCase(sectionXmlInfo.SubPath,
+ locationSubPathAttribute))
+ {
+ section = FindSectionRecursive(keys, 0, xmlUtil, ref lineNumber);
+ if (section != null)
+ break;
+ }
+ }
+
+ xmlUtil.SkipToNextElement();
+ }
+ }
+
+ // Throw accumulated errors
+ ThrowIfParseErrors(xmlUtil.SchemaErrors);
+ }
+ }
+
+ return section;
+ }
+
+ private ConfigXmlReader FindSectionRecursive(string[] keys, int iKey, XmlUtil xmlUtil, ref int lineNumber)
+ {
+ string name = keys[iKey];
+ ConfigXmlReader section = null;
+
+ int depth = xmlUtil.Reader.Depth;
+ xmlUtil.ReadToNextElement();
+
+ while (xmlUtil.Reader.Depth > depth)
+ {
+ if (xmlUtil.Reader.Name == name)
+ {
+ if (iKey < keys.Length - 1)
+ {
+ // We haven't reached the section yet, so keep evaluating
+ section = FindSectionRecursive(keys, iKey + 1, xmlUtil, ref lineNumber);
+ if (section != null) break;
+
+ continue; // don't call "Skip" -- FindSectionRecursive forwards the reader
+ }
+
+ // We've reached the section. Load the section into a string.
+ string filename = xmlUtil.Filename;
+ int lineOffset = xmlUtil.Reader.LineNumber;
+ string rawXml = xmlUtil.CopySection();
+ section = new ConfigXmlReader(rawXml, filename, lineOffset);
+ break;
+ }
+
+ if ((iKey == 0) && (xmlUtil.Reader.Name == LocationTag))
+ {
+ string locationSubPath = xmlUtil.Reader.GetAttribute(LocationPathAttribute);
+ bool isValid = false;
+ try
+ {
+ locationSubPath = NormalizeLocationSubPath(locationSubPath, xmlUtil);
+ isValid = true;
+ }
+ catch (ConfigurationException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.NonSpecific);
+ }
+
+ if (isValid && (locationSubPath == null))
+ {
+ // Location sections that don't have a subpath are treated
+ // as ordinary sections.
+ section = FindSectionRecursive(keys, iKey, xmlUtil, ref lineNumber);
+ if (section != null) break;
+
+ continue; // don't call "Skip" -- FindSectionRecursive forwards the reader
+ }
+ }
+
+ xmlUtil.SkipToNextElement();
+ }
+
+ return section;
+ }
+
+ private ConfigXmlReader LoadConfigSource(string name, SectionXmlInfo sectionXmlInfo)
+ {
+ string configSourceStreamName = sectionXmlInfo.ConfigSourceStreamName;
+
+ using (Stream stream = Host.OpenStreamForRead(configSourceStreamName))
+ {
+ if (stream == null)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_cannot_open_config_source, sectionXmlInfo.ConfigSource),
+ sectionXmlInfo);
+ }
+
+ using (XmlUtil xmlUtil = new XmlUtil(stream, configSourceStreamName, true))
+ {
+ if (xmlUtil.Reader.Name != name)
+ throw new ConfigurationErrorsException(SR.Config_source_file_format, xmlUtil);
+
+ // Check for protectionProvider
+ string protectionProviderAttribute = xmlUtil.Reader.GetAttribute(ProtectionProviderAttibute);
+ if (protectionProviderAttribute != null)
+ {
+ if (xmlUtil.Reader.AttributeCount != 1)
+ {
+ // Error: elements with protectionProvider should not have other attributes
+ throw new ConfigurationErrorsException(SR.Protection_provider_syntax_error, xmlUtil);
+ }
+
+ sectionXmlInfo.ProtectionProviderName =
+ ValidateProtectionProviderAttribute(protectionProviderAttribute, xmlUtil);
+ }
+
+ int lineOffset = xmlUtil.Reader.LineNumber;
+ string rawXml = xmlUtil.CopySection();
+
+ // Detect if there is any XML left over after the section
+ while (!xmlUtil.Reader.EOF)
+ {
+ XmlNodeType t = xmlUtil.Reader.NodeType;
+ if (t != XmlNodeType.Comment)
+ throw new ConfigurationErrorsException(SR.Config_source_file_format, xmlUtil);
+
+ xmlUtil.Reader.Read();
+ }
+
+ ConfigXmlReader section = new ConfigXmlReader(rawXml, configSourceStreamName, lineOffset);
+ return section;
+ }
+ }
+ }
+
+ protected ConfigXmlReader GetSectionXmlReader(string[] keys, SectionInput input)
+ {
+ ConfigXmlReader reader;
+ string filename = input.SectionXmlInfo.Filename;
+ int lineNumber = input.SectionXmlInfo.LineNumber;
+
+ try
+ {
+ string name = keys[keys.Length - 1];
+ string rawXml = input.SectionXmlInfo.RawXml;
+ if (rawXml != null)
+ {
+ // Use the stored raw xml to provide the content of the section.
+ reader = new ConfigXmlReader(rawXml, input.SectionXmlInfo.Filename, input.SectionXmlInfo.LineNumber);
+ }
+ else
+ {
+ if (!string.IsNullOrEmpty(input.SectionXmlInfo.ConfigSource))
+ {
+ // Load the config source to provide the content of the section.
+ filename = input.SectionXmlInfo.ConfigSourceStreamName;
+ lineNumber = 0;
+ reader = LoadConfigSource(name, input.SectionXmlInfo);
+ }
+ else
+ {
+ // Find the content of the section in the config file.
+ lineNumber = 0;
+ reader = FindSection(keys, input.SectionXmlInfo, out lineNumber);
+ }
+ }
+
+ if (reader != null)
+ {
+ if (!input.IsProtectionProviderDetermined)
+ {
+ input.ProtectionProvider =
+ GetProtectionProviderFromName(input.SectionXmlInfo.ProtectionProviderName, false);
+ }
+
+ if (input.ProtectionProvider != null)
+ reader = DecryptConfigSection(reader, input.ProtectionProvider);
+ }
+ }
+ catch (Exception e)
+ {
+ // Guarantee that exceptions contain the name of the stream and an approximate line number.
+ throw ExceptionUtil.WrapAsConfigException(SR.Config_error_loading_XML_file, e, filename,
+ lineNumber);
+ }
+
+ return reader;
+ }
+
+ internal ProtectedConfigurationProvider GetProtectionProviderFromName(string providerName, bool throwIfNotFound)
+ {
+ if (!string.IsNullOrEmpty(providerName)) return ProtectedConfig.GetProviderFromName(providerName);
+
+ if (!throwIfNotFound) return null;
+
+ throw new ConfigurationErrorsException(string.Format(SR.ProtectedConfigurationProvider_not_found,
+ providerName));
+ }
+
+ internal void InitProtectedConfigurationSection()
+ {
+ if (_flags[ProtectedDataInitialized]) return;
+
+ _protectedConfig =
+ GetSection(ReservedSectionProtectedConfiguration, false, false) as ProtectedConfigurationSection;
+
+ Debug.Assert(_protectedConfig != null,
+ "<configProtectedData> section should always be available because it's a built-in section");
+
+ _flags[ProtectedDataInitialized] = true;
+ }
+
+ protected object CallCreateSection(bool inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord,
+ object parentConfig, ConfigXmlReader reader, string filename, int line)
+ {
+ object config;
+
+ // Call into config section while impersonating process or UNC identity
+ // so that the section could read files from disk if needed
+ try
+ {
+ config = CreateSection(inputIsTrusted, factoryRecord, sectionRecord, parentConfig, reader);
+ if ((config == null) && (parentConfig != null))
+ throw new ConfigurationErrorsException(SR.Config_object_is_null, filename, line);
+ }
+ catch (ThreadAbortException)
+ {
+ throw;
+ }
+ catch (Exception e)
+ {
+ throw ExceptionUtil.WrapAsConfigException(
+ string.Format(SR.Config_exception_creating_section_handler, factoryRecord.ConfigKey), e, filename,
+ line);
+ }
+
+ return config;
+ }
+
+ // Is this the Root Record of where this configKey is Declared
+ //
+ // If parent is null, or there is not a factory record above
+ // this one, then it is the root of where it can be declared
+ //
+ // Optionally consider whether implicit sections are to be considered rooted.
+ internal bool IsRootDeclaration(string configKey, bool implicitIsRooted)
+ {
+ if (!implicitIsRooted && IsImplicitSection(configKey)) return false;
+
+ return _parent.IsRootConfig || (_parent.FindFactoryRecord(configKey, true) == null);
+ }
+
+ // Search the config hierarchy for a FactoryRecord.
+ // Note that callers should check whether the returned factory has errors.
+ internal FactoryRecord FindFactoryRecord(string configKey, bool permitErrors,
+ out BaseConfigurationRecord configRecord)
+ {
+ configRecord = null;
+ BaseConfigurationRecord tConfigRecord = this;
+
+ while (!tConfigRecord.IsRootConfig)
+ {
+ FactoryRecord factoryRecord = tConfigRecord.GetFactoryRecord(configKey, permitErrors);
+ if (factoryRecord != null)
+ {
+#if DEBUG
+ if (IsImplicitSection(configKey) && !factoryRecord.HasErrors)
+ {
+ Debug.Assert(tConfigRecord._parent.IsRootConfig,
+ "Implicit section should be found only at the record beneath the root (e.g. machine.config)");
+ }
+#endif
+
+ configRecord = tConfigRecord;
+ return factoryRecord;
+ }
+
+ tConfigRecord = tConfigRecord._parent;
+ }
+
+ return null;
+ }
+
+
+ internal FactoryRecord FindFactoryRecord(string configKey, bool permitErrors)
+ {
+ BaseConfigurationRecord dummy;
+ return FindFactoryRecord(configKey, permitErrors, out dummy);
+ }
+
+ // - Find the nearest factory record
+ // - Determine if it is the root
+ // - Create the factory in the root if it doesn't exist.
+ private FactoryRecord FindAndEnsureFactoryRecord(string configKey, out bool isRootDeclaredHere)
+ {
+ isRootDeclaredHere = false;
+
+ BaseConfigurationRecord configRecord;
+ FactoryRecord factoryRecord = FindFactoryRecord(configKey, false, out configRecord);
+ if ((factoryRecord == null) || factoryRecord.IsGroup) return factoryRecord;
+
+ // Find the root declaration
+ FactoryRecord rootFactoryRecord = factoryRecord;
+ BaseConfigurationRecord rootConfigRecord = configRecord;
+
+ BaseConfigurationRecord currentConfigRecord = configRecord._parent;
+ while (!currentConfigRecord.IsRootConfig)
+ {
+ BaseConfigurationRecord tempConfigRecord;
+ FactoryRecord tempFactoryRecord = currentConfigRecord.FindFactoryRecord(configKey, false,
+ out tempConfigRecord);
+ if (tempFactoryRecord == null)
+ break;
+
+ rootFactoryRecord = tempFactoryRecord;
+ rootConfigRecord = tempConfigRecord;
+
+ // continue the search from the parent of the configRecord we found
+ currentConfigRecord = tempConfigRecord.Parent;
+ }
+
+ // A child factory record must be equivalent to its parent,
+ // so if the child has no errors, the parent must also have no errors.
+ Debug.Assert(!rootFactoryRecord.HasErrors, "!rootFactoryRecord.HasErrors");
+ if (rootFactoryRecord.Factory == null)
+ {
+ try
+ {
+ // Create the factory from the type string, and cache it
+ object factory = rootConfigRecord.CreateSectionFactory(rootFactoryRecord);
+ rootFactoryRecord.Factory = factory;
+ }
+ catch (Exception e)
+ {
+ throw ExceptionUtil.WrapAsConfigException(
+ string.Format(SR.Config_exception_creating_section_handler, factoryRecord.ConfigKey), e,
+ factoryRecord);
+ }
+ }
+
+ if (factoryRecord.Factory == null)
+ {
+ factoryRecord.Factory = rootFactoryRecord.Factory;
+ }
+
+ isRootDeclaredHere = ReferenceEquals(this, rootConfigRecord);
+
+ return factoryRecord;
+ }
+
+ private Hashtable ScanFactories(XmlUtil xmlUtil)
+ {
+ Hashtable factoryList = new Hashtable();
+
+ // Check for a root <configuration>
+ if ((xmlUtil.Reader.NodeType != XmlNodeType.Element) || (xmlUtil.Reader.Name != ConfigurationTag))
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_file_doesnt_have_root_configuration, xmlUtil.Filename), xmlUtil);
+
+ // Look at the configuration attributes
+ while (xmlUtil.Reader.MoveToNextAttribute())
+ switch (xmlUtil.Reader.Name)
+ {
+ case XmlnsAttribute: // xmlns
+ if (xmlUtil.Reader.Value == ConfigurationNamespace)
+ {
+ // http://schemas.microsoft.com/.NetConfiguration/v2.0
+ _flags[NamespacePresentInFile] = true;
+ _flags[NamespacePresentCurrent] = true;
+ }
+ else
+ {
+ // A configuration namespace was defined that we don't understand
+ ConfigurationErrorsException ce = new ConfigurationErrorsException(
+ string.Format(SR.Config_namespace_invalid, xmlUtil.Reader.Value, ConfigurationNamespace),
+ xmlUtil);
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Global);
+ }
+ break;
+ default:
+ xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.NonSpecific);
+ break;
+ }
+
+ // If the first child of <configuration> isn't <configSections>, bail
+ xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
+ if ((xmlUtil.Reader.Depth != 1) || (xmlUtil.Reader.Name != ConfigSectionsTag))
+ return factoryList;
+
+ // Log an error for any attributes <configSections> might have
+ xmlUtil.VerifyNoUnrecognizedAttributes(ExceptionAction.NonSpecific);
+
+ // Scan in the <configSections> data
+ ScanFactoriesRecursive(xmlUtil, parentConfigKey: string.Empty, factoryList: factoryList);
+
+ return factoryList;
+ }
+
+
+ // Scans the <configSections> section of a configuration file. The function is recursive
+ // to traverse arbitrarily nested config groups.
+ //
+ // <sectionGroup name="foo">
+ // <sectionGroup name="bar">
+ // <section name="fooBarSection" type="..." />
+ // ...
+ //
+ // Note: This function valiates that the factory record has not been
+ // declared before in a parent record. (it does not check
+ // current record, which allows you to update list)
+ private void ScanFactoriesRecursive(XmlUtil xmlUtil, string parentConfigKey, Hashtable factoryList)
+ {
+ // discard any accumulated local errors
+ xmlUtil.SchemaErrors.ResetLocalErrors();
+
+ int depth = xmlUtil.Reader.Depth;
+ xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
+
+ while (xmlUtil.Reader.Depth == depth + 1)
+ {
+ bool positionedAtNextElement = false;
+
+ switch (xmlUtil.Reader.Name)
+ {
+ case SectionGroupTag: // <sectionGroup>
+ {
+ string tagName = null;
+ string typeName = null;
+
+ int lineNumber = xmlUtil.Reader.LineNumber;
+ while (xmlUtil.Reader.MoveToNextAttribute())
+ switch (xmlUtil.Reader.Name)
+ {
+ case SectionGroupNameAttribute:
+ tagName = xmlUtil.Reader.Value;
+ VerifySectionName(tagName, xmlUtil, ExceptionAction.Local, false);
+ break;
+ case SectionGroupTypeAttribute:
+ xmlUtil.VerifyAndGetNonEmptyStringAttribute(ExceptionAction.Local, out typeName);
+ break;
+ default:
+ xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.Local);
+ break;
+ }
+
+ // Move back to the element
+ xmlUtil.Reader.MoveToElement();
+
+ if (!xmlUtil.VerifyRequiredAttribute(tagName, SectionGroupNameAttribute, ExceptionAction.NonSpecific))
+ {
+ // Without a name="", we cannot continue parsing the sections and groups within.
+ // Skip the entire section.
+ xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true);
+ xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+ }
+ else
+ {
+ string configKey = CombineConfigKey(parentConfigKey, tagName);
+
+ FactoryRecord factoryRecord = (FactoryRecord)factoryList[configKey];
+ if (factoryRecord != null)
+ {
+ // Error: duplicate <sectionGroup> declaration
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined_at_this_level, tagName), xmlUtil),
+ ExceptionAction.Local);
+ }
+ else
+ {
+ // Look for a factory of the same name in the parent
+ FactoryRecord parentFactoryRecord = _parent.FindFactoryRecord(configKey, true);
+ if (parentFactoryRecord != null)
+ {
+ configKey = parentFactoryRecord.ConfigKey;
+
+ // make sure that an ancestor has not defined a <section> with the same name as the <sectionGroup>
+ if ((parentFactoryRecord != null) &&
+ (!parentFactoryRecord.IsGroup || !parentFactoryRecord.IsEquivalentSectionGroupFactory(Host, typeName)))
+ {
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, tagName), xmlUtil),
+ ExceptionAction.Local);
+ parentFactoryRecord = null;
+ }
+ }
+
+ factoryRecord = parentFactoryRecord?.CloneSectionGroup(typeName, xmlUtil.Filename, lineNumber)
+ ?? new FactoryRecord(configKey, parentConfigKey, tagName, typeName, xmlUtil.Filename, lineNumber);
+
+ factoryList[configKey] = factoryRecord;
+ }
+
+ // Add any errors we may have encountered
+ factoryRecord.AddErrors(xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true));
+
+ // continue recursive scan
+ ScanFactoriesRecursive(xmlUtil, configKey, factoryList);
+ }
+
+ continue;
+ }
+
+ case SectionTag: // <section>
+ {
+ string tagName = null;
+ string typeName = null;
+ ConfigurationAllowDefinition allowDefinition = ConfigurationAllowDefinition.Everywhere;
+ ConfigurationAllowExeDefinition allowExeDefinition = ConfigurationAllowExeDefinition.MachineToApplication;
+ OverrideModeSetting overrideModeDefault = OverrideModeSetting.s_sectionDefault;
+ bool allowLocation = true;
+ bool restartOnExternalChanges = true;
+ bool requirePermission = true;
+ bool gotType = false;
+
+ // parse section attributes
+ int lineNumber = xmlUtil.Reader.LineNumber;
+ while (xmlUtil.Reader.MoveToNextAttribute())
+ switch (xmlUtil.Reader.Name)
+ {
+ case SectionNameAttribute:
+ tagName = xmlUtil.Reader.Value;
+ VerifySectionName(tagName, xmlUtil, ExceptionAction.Local, false);
+ break;
+ case SectionTypeAttribute:
+ xmlUtil.VerifyAndGetNonEmptyStringAttribute(ExceptionAction.Local, out typeName);
+ gotType = true;
+ break;
+ case SectionAllowLocationAttribute:
+ xmlUtil.VerifyAndGetBooleanAttribute(ExceptionAction.Local, true, out allowLocation);
+ break;
+ case SectionAllowExeDefinitionAttribute:
+ try
+ {
+ allowExeDefinition = AllowExeDefinitionToEnum(xmlUtil.Reader.Value, xmlUtil);
+ }
+ catch (ConfigurationException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
+ }
+ break;
+ case SectionAllowDefinitionAttribute:
+ try
+ {
+ allowDefinition = AllowDefinitionToEnum(xmlUtil.Reader.Value, xmlUtil);
+ }
+ catch (ConfigurationException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
+ }
+ break;
+ case SectionRestartonExternalChangesAttribute:
+ xmlUtil.VerifyAndGetBooleanAttribute(ExceptionAction.Local, true, out restartOnExternalChanges);
+ break;
+ case SectionRequirePermissionAttribute:
+ xmlUtil.VerifyAndGetBooleanAttribute(ExceptionAction.Local, true, out requirePermission);
+ break;
+ case SectionOverrideModeDefaultAttribute:
+ try
+ {
+ overrideModeDefault = OverrideModeSetting.CreateFromXmlReadValue(
+ OverrideModeSetting.ParseOverrideModeXmlValue(xmlUtil.Reader.Value, xmlUtil));
+
+ // Inherit means Allow when comming from the default value
+ if (overrideModeDefault.OverrideMode == OverrideMode.Inherit)
+ overrideModeDefault.ChangeModeInternal(OverrideMode.Allow);
+ }
+ catch (ConfigurationException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
+ }
+ break;
+ default:
+ xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.Local);
+ break;
+ }
+
+ // if on an attribute move back to the element
+ xmlUtil.Reader.MoveToElement();
+
+ if (!xmlUtil.VerifyRequiredAttribute(
+ tagName, SectionNameAttribute, ExceptionAction.NonSpecific))
+ {
+ // Without a name, we cannot continue to create a factoryRecord.
+ xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true);
+ }
+ else
+ {
+ // Verify that the Type attribute was present.
+ // Note that 'typeName' will be null if the attribute was present
+ // but specified as an empty string.
+ if (!gotType)
+ xmlUtil.AddErrorRequiredAttribute(SectionTypeAttribute, ExceptionAction.Local);
+
+ string configKey = CombineConfigKey(parentConfigKey, tagName);
+
+ FactoryRecord factoryRecord = (FactoryRecord)factoryList[configKey];
+ if (factoryRecord != null)
+ {
+ // Error: duplicate section declaration
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(
+ string.Format(SR.Config_tag_name_already_defined_at_this_level, tagName),
+ xmlUtil),
+ ExceptionAction.Local);
+ }
+ else
+ {
+ FactoryRecord parentFactoryRecord = _parent.FindFactoryRecord(configKey, true);
+ if (parentFactoryRecord != null)
+ {
+ // We have a parent factory record with the same name
+ configKey = parentFactoryRecord.ConfigKey;
+
+ // Look for collisions
+ if (parentFactoryRecord.IsGroup)
+ {
+ // Already a <sectionGroup> with this name
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(
+ string.Format(SR.Config_tag_name_already_defined, tagName), xmlUtil),
+ ExceptionAction.Local);
+ parentFactoryRecord = null;
+ }
+ else if (!parentFactoryRecord.IsEquivalentSectionFactory(
+ Host, typeName, allowLocation, allowDefinition, allowExeDefinition, restartOnExternalChanges, requirePermission))
+ {
+ // Already a <section> with the same name
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, tagName), xmlUtil),
+ ExceptionAction.Local);
+ parentFactoryRecord = null;
+ }
+ }
+
+ // Note - Clone will propagate the IsFromTrustedConfigRecord bit,
+ // which is what we want - if this record is a duplicate of an ancestor,
+ // the ancestor may be from a trusted config record.
+ factoryRecord = parentFactoryRecord?.CloneSection(xmlUtil.Filename, lineNumber)
+ ?? new FactoryRecord(
+ configKey,
+ parentConfigKey,
+ tagName,
+ typeName,
+ allowLocation,
+ allowDefinition,
+ allowExeDefinition,
+ overrideModeDefault,
+ restartOnExternalChanges,
+ requirePermission,
+ _flags[IsTrusted],
+ isUndeclared: false,
+ filename: xmlUtil.Filename,
+ lineNumber: lineNumber);
+
+ factoryList[configKey] = factoryRecord;
+ }
+
+ // Add any errors we may have encountered
+ factoryRecord.AddErrors(xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true));
+ }
+ break;
+ }
+ case RemoveTag: // <remove>
+ // Find the name attribute
+ string name = null;
+ while (xmlUtil.Reader.MoveToNextAttribute())
+ {
+ if (xmlUtil.Reader.Name != SectionNameAttribute)
+ xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.NonSpecific);
+ else
+ name = xmlUtil.Reader.Value;
+ }
+ xmlUtil.Reader.MoveToElement();
+ if (xmlUtil.VerifyRequiredAttribute(
+ name, SectionNameAttribute, ExceptionAction.NonSpecific))
+ VerifySectionName(name, xmlUtil, ExceptionAction.NonSpecific, false);
+ break;
+ case ClearTag: // <clear>
+ xmlUtil.VerifyNoUnrecognizedAttributes(ExceptionAction.NonSpecific);
+ break;
+ default:
+ // Unknown element, skip over it
+ xmlUtil.AddErrorUnrecognizedElement(ExceptionAction.NonSpecific);
+ xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+ positionedAtNextElement = true;
+ break;
+ }
+
+ if (positionedAtNextElement) continue;
+
+ xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
+
+ if (xmlUtil.Reader.Depth > depth + 1)
+ {
+ // Unrecognized children are not allowed in <configSections>
+ xmlUtil.AddErrorUnrecognizedElement(ExceptionAction.NonSpecific);
+
+ // Try to backup to where we are suppose to be
+ while (xmlUtil.Reader.Depth > depth + 1) xmlUtil.ReadToNextElement();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Translate an ExeDefinition string from the Declaration in a file
+ /// to the appropriate enumeration
+ /// </summary>
+ /// <param name="allowExeDefinition">string representation of value</param>
+ /// <param name="xmlUtil">[optional] - can provide better error</param>
+ internal static ConfigurationAllowExeDefinition
+ AllowExeDefinitionToEnum(string allowExeDefinition, XmlUtil xmlUtil)
+ {
+ switch (allowExeDefinition)
+ {
+ case AllowDefinitionMachineOnly:
+ return ConfigurationAllowExeDefinition.MachineOnly;
+ case AllowDefinitionMachineToApplication:
+ return ConfigurationAllowExeDefinition.MachineToApplication;
+ case AllowExeDefinitionMachineToRoaming:
+ return ConfigurationAllowExeDefinition.MachineToRoamingUser;
+ case AllowExeDefinitionMachineToLocal:
+ return ConfigurationAllowExeDefinition.MachineToLocalUser;
+ default:
+ throw new ConfigurationErrorsException(
+ SR.Config_section_allow_exe_definition_attribute_invalid,
+ xmlUtil);
+ }
+ }
+
+ internal static ConfigurationAllowDefinition
+ AllowDefinitionToEnum(string allowDefinition, XmlUtil xmlUtil)
+ {
+ switch (xmlUtil.Reader.Value)
+ {
+ case AllowDefinitionEverywhere:
+ return ConfigurationAllowDefinition.Everywhere;
+ case AllowDefinitionMachineOnly:
+ return ConfigurationAllowDefinition.MachineOnly;
+ case AllowDefinitionMachineToApplication:
+ return ConfigurationAllowDefinition.MachineToApplication;
+ case AllowDefinitionMachineToWebRoot:
+ return ConfigurationAllowDefinition.MachineToWebRoot;
+ default:
+ throw new ConfigurationErrorsException(
+ SR.Config_section_allow_definition_attribute_invalid,
+ xmlUtil);
+ }
+ }
+
+ internal static string CombineConfigKey(string parentConfigKey, string tagName)
+ {
+ if (string.IsNullOrEmpty(parentConfigKey)) return tagName;
+
+ if (string.IsNullOrEmpty(tagName)) return parentConfigKey;
+
+ return parentConfigKey + "/" + tagName;
+ }
+
+ internal static void SplitConfigKey(string configKey, out string group, out string name)
+ {
+ int lastSlash = configKey.LastIndexOf('/');
+ if (lastSlash == -1)
+ {
+ group = string.Empty;
+ name = configKey;
+ }
+ else
+ {
+ group = configKey.Substring(0, lastSlash);
+ name = configKey.Substring(lastSlash + 1);
+ }
+ }
+
+ [Conditional("DEBUG")]
+ private void DebugValidateIndirectInputs(SectionRecord sectionRecord)
+ {
+ if (_parent.IsRootConfig) return;
+
+ // Verify that for each indirect input, its target config path is a child path of _parent.
+ // That's the definition of indirect input.
+ for (int i = sectionRecord.IndirectLocationInputs.Count - 1; i >= 0; i--)
+ {
+ SectionInput input = sectionRecord.IndirectLocationInputs[i];
+
+ // Get the override mode starting from the closest input.
+ Debug.Assert(UrlPath.IsSubpath(_parent.ConfigPath, input.SectionXmlInfo.TargetConfigPath));
+ }
+ }
+
+ // Return the lock mode for a section as comming from parent config levels
+ private OverrideMode ResolveOverrideModeFromParent(string configKey, out OverrideMode childLockMode)
+ {
+ // When the current record is a location config level we are a direct child of the config level of the actual
+ // config file inside which the location tag is. For example we have a file d:\inetpub\wwwroot\web.config which
+ // containts <location path="Sub"> then "this" will be the config level inside the location tag and this.Parent
+ // is the config level of d:\inetpub\wwwroot\web.config.
+
+ // What we will do to come up with the result is:
+ // 1) Try to find an existing section record somewhere above us.
+ // If we find an existing section record then it will have the effective value of the lock mode
+ // that applies to us in it's LockChidlren. We dont need to go further up once we find a section record
+ // as it has the lock mode of all it's parents accumulated
+ //
+ // There is one huge trick though - Location config records are different ( see begining of the func for what a location config record is )
+ // A location config record is not locked if the config level of the web.config file in which it lives is not locked.
+ // I.e. when we are looking for the effective value for a location config we have two cases
+ // a) There is a section record in our immediate parent ( remember our immediate parent is the config file in which we /as a location tag/ are defined )
+ // In this case our lock mode is not the LockChildren of this section record because this lock mode applies to child config levels in child config files
+ // The real lock mode for us is the Locked mode of the section record in self.
+ // b) There is no section record in our immediate parent - in this case the locking is the same as for normal config - LockChildren value of any section
+ // record we may find above us.
+ //
+ // 2) If we can't find an existing section record we have two cases again:
+ // a) We are at the section declaration level - at this level a section is always unlocked by definition
+ // If this wasnt so there would be no way to unlock a section that is locked by default
+ // A Location config is a bit wierd again in a sence that a location config is unlocked if its in the config file where the section is declared
+ // I.e. if "this" is a location record then a section is unconditionally unlocked if "this.Parent" is the section declaration level
+ // b) We are not at section declaration level - in this case the result is whatever the default lock mode for the section is ( remember
+ // that we fall back to the default since we couldnt find a section record with explicit lock mode nowhere above us)
+ //
+ // I sure hope that made some sense!
+
+ OverrideMode mode = OverrideMode.Inherit;
+ BaseConfigurationRecord parent = Parent;
+ BaseConfigurationRecord immediateParent = Parent;
+
+ childLockMode = OverrideMode.Inherit;
+
+ // Walk the hierarchy until we find an explicit setting for lock state at a config level or we reach to root
+ while (!parent.IsRootConfig && (mode == OverrideMode.Inherit))
+ {
+ SectionRecord sectionRecord = parent.GetSectionRecord(configKey, true);
+
+ if (sectionRecord != null)
+ {
+ // Check for 1a
+ if (IsLocationConfig && ReferenceEquals(immediateParent, parent))
+ {
+ // Apply case 1a
+ mode = sectionRecord.Locked ? OverrideMode.Deny : OverrideMode.Allow;
+
+ // In this specific case the lock mode for our children is whatever the children of our parent should inherit
+ // For example imagine a web.config which has a <location path="." overrideMode="Deny"> and we open "locationSubPath" from this web.config
+ // The lock for the section is not Deny and will be allow ( see the code line above ). However the chidlren of this location tag
+ // inherit the lock that applies to the children of the web.config file itself
+ childLockMode = sectionRecord.LockChildren ? OverrideMode.Deny : OverrideMode.Allow;
+ }
+ else
+ {
+ mode = sectionRecord.LockChildren ? OverrideMode.Deny : OverrideMode.Allow;
+
+ // When the lock mode is comming from a parent level the
+ // lock mode that applies to children of "this" is the same as what applies to "this"
+ childLockMode = mode;
+ }
+ }
+
+ parent = parent._parent;
+ }
+
+ // Case 2
+ if (mode == OverrideMode.Inherit)
+ {
+ Debug.Assert(FindFactoryRecord(configKey, true) != null);
+
+ bool atDeclarationLevel;
+ OverrideMode defaultMode = FindFactoryRecord(configKey, true).OverrideModeDefault.OverrideMode;
+
+ if (IsLocationConfig) atDeclarationLevel = Parent.GetFactoryRecord(configKey, true) != null;
+ else atDeclarationLevel = GetFactoryRecord(configKey, true) != null;
+
+ if (!atDeclarationLevel)
+ {
+ // Case 2b
+ //
+ // Lock mode for children and self is the same since the default value is comming
+ // from a parent level and hence - applies to both
+ childLockMode = mode = defaultMode;
+
+ Debug.Assert(mode != OverrideMode.Inherit); // Remember that the default is never Inherit
+ }
+ else
+ {
+ // Case 2a
+ //
+ // Self is always allow at section declaration level
+ // Child lock mode is the default value ( remember we are here because no explici mode was set anywhere above us )
+
+ mode = OverrideMode.Allow;
+ childLockMode = defaultMode;
+ }
+ }
+
+ // This function must return Allow or Deny
+ Debug.Assert(mode != OverrideMode.Inherit);
+
+ return mode;
+ }
+
+ protected OverrideMode GetSectionLockedMode(string configKey)
+ {
+ OverrideMode dummy;
+ return GetSectionLockedMode(configKey, out dummy);
+ }
+
+ // Return the current lock mode for a section
+ protected OverrideMode GetSectionLockedMode(string configKey, out OverrideMode childLockMode)
+ {
+ OverrideMode result;
+
+ SectionRecord sectionRecord = GetSectionRecord(configKey, true);
+
+ // If there is a section record it has the effective locking settings resolved
+ // There is no need to do ResolveOverrideModeFromParent because it was done in:
+ // 1) In EnsureSectionRecord when the section record was creteted
+ // 2) Right after the SectionRecord was created without initialization of the lock settings
+ // in this:ScanSectionsRecursive().
+ // As long as nobody uses EnsureSectionRecordUnsafe this method will be returning the correct
+ // lock value only by looking at the section record
+
+ if (sectionRecord != null)
+ {
+ result = sectionRecord.Locked ? OverrideMode.Deny : OverrideMode.Allow;
+ childLockMode = sectionRecord.LockChildren ? OverrideMode.Deny : OverrideMode.Allow;
+ }
+ else result = ResolveOverrideModeFromParent(configKey, out childLockMode);
+
+ return result;
+ }
+
+ private void ScanSections(XmlUtil xmlUtil)
+ {
+ ScanSectionsRecursive(xmlUtil, string.Empty, false, null, OverrideModeSetting.s_locationDefault, false);
+ }
+
+ private void ScanSectionsRecursive(
+ XmlUtil xmlUtil,
+ string parentConfigKey,
+ bool inLocation,
+ string locationSubPath,
+ OverrideModeSetting overrideMode,
+ bool skipInChildApps)
+ {
+ // discard any accumulated local errors
+ xmlUtil.SchemaErrors.ResetLocalErrors();
+
+ int depth;
+
+ // only move to child nodes when not on first level (we've already passed the first <configsections>)
+ if ((parentConfigKey.Length == 0) && !inLocation)
+ {
+ depth = 0;
+ }
+ else
+ {
+ depth = xmlUtil.Reader.Depth;
+ xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
+ }
+
+ while (xmlUtil.Reader.Depth == depth + 1)
+ {
+ string tagName = xmlUtil.Reader.Name;
+
+ // Check for reserved elements before looking up the factory,
+ // which may have the same name if it is in error.
+ switch (tagName)
+ {
+ case ConfigSectionsTag: // <configSections>
+ // Either a duplicate or not the first tag under <configuration>
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(string.Format(SR.Config_client_config_too_many_configsections_elements, tagName), xmlUtil),
+ ExceptionAction.NonSpecific);
+ xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+ continue;
+ case LocationTag: // <location>
+ if ((parentConfigKey.Length > 0) || inLocation)
+ {
+ // The section isn't at the top level
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(SR.Config_location_location_not_allowed, xmlUtil),
+ ExceptionAction.Global);
+ xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+ }
+ else
+ {
+ // Recurse into the location section
+ ScanLocationSection(xmlUtil);
+ }
+ continue;
+ }
+
+ string configKey = CombineConfigKey(parentConfigKey, tagName);
+
+ // Find the relevant factory record
+ FactoryRecord factoryRecord = FindFactoryRecord(configKey, true);
+
+ if (factoryRecord == null)
+ {
+ // Unregistered configuration section, add DefaultSection factory for it.
+ //
+ // At runtime, it is a local error to have an unrecognized section.
+ // By treating it as local we avoid throwing an error if the
+ // section is encountered within a location section, just as we treat
+ // other section errors in a location tag.
+ //
+ // At designtime, we do not consider it an error, so that programs
+ // that worked on version N config files can continue to work with
+ // version N+1 config files that may introduce new sections.
+ if (!ClassFlags[ClassIgnoreLocalErrors])
+ {
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(
+ string.Format(SR.Config_unrecognized_configuration_section, configKey), xmlUtil),
+ ExceptionAction.Local);
+ }
+
+ VerifySectionName(tagName, xmlUtil, ExceptionAction.Local, false);
+
+ factoryRecord = new FactoryRecord(
+ configKey,
+ parentConfigKey,
+ tagName,
+ typeof(DefaultSection).AssemblyQualifiedName,
+ allowLocation: true,
+ allowDefinition: ConfigurationAllowDefinition.Everywhere,
+ allowExeDefinition: ConfigurationAllowExeDefinition.MachineToRoamingUser,
+ overrideModeDefault: OverrideModeSetting.s_sectionDefault,
+ restartOnExternalChanges: true,
+ requirePermission: true,
+ isFromTrustedConfigRecord: _flags[IsTrusted],
+ isUndeclared: true,
+ filename: null,
+ lineNumber: -1);
+
+ // Add any errors we may have encountered to the factory record,
+ // so that child config that also refer to this unrecognized section
+ // get the error.
+ factoryRecord.AddErrors(xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true));
+
+ // Add the factory to the list of factories
+ EnsureFactories()[configKey] = factoryRecord;
+ }
+
+ if (factoryRecord.IsGroup)
+ {
+ // A section group
+ if (factoryRecord.HasErrors) xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+ else
+ {
+ if (xmlUtil.Reader.AttributeCount > 0)
+ {
+ // We allow unrecognized attributes for backward compatibility
+ // However, we will still throw if the unrecognized attribute is reserved.
+ while (xmlUtil.Reader.MoveToNextAttribute())
+ if (IsReservedAttributeName(xmlUtil.Reader.Name))
+ xmlUtil.AddErrorReservedAttribute(ExceptionAction.NonSpecific);
+
+ xmlUtil.Reader.MoveToElement(); // if on an attribute move back to the element
+ }
+
+ // Recurse into group definition
+ ScanSectionsRecursive(xmlUtil, configKey, inLocation, locationSubPath, overrideMode,
+ skipInChildApps);
+ }
+ }
+ else
+ {
+ // A section
+ configKey = factoryRecord.ConfigKey;
+ string fileName = xmlUtil.Filename;
+ int lineNumber = xmlUtil.LineNumber;
+ string rawXml = null;
+ string configSource = null;
+ string configSourceStreamName = null;
+ object configSourceStreamVersion = null;
+ string protectionProviderName = null;
+ OverrideMode sectionLockMode = OverrideMode.Inherit;
+ OverrideMode sectionChildLockMode = OverrideMode.Inherit;
+ bool positionedAtNextElement = false;
+ bool isFileInput = locationSubPath == null;
+
+ if (!factoryRecord.HasErrors)
+ {
+ // We have a valid factoryRecord for a section
+ if (inLocation && (factoryRecord.AllowLocation == false))
+ {
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(
+ SR.Config_section_cannot_be_used_in_location, xmlUtil),
+ ExceptionAction.Local);
+ }
+
+ // Verify correctness for file inputs.
+ if (isFileInput)
+ {
+ // Verify that the section is unique
+ SectionRecord sectionRecord = GetSectionRecord(configKey, true);
+ if ((sectionRecord != null) && sectionRecord.HasFileInput)
+ {
+ if (!factoryRecord.IsIgnorable())
+ {
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(
+ SR.Config_sections_must_be_unique, xmlUtil),
+ ExceptionAction.Local);
+ }
+ }
+
+ // Verify that the definition is allowed.
+ try
+ {
+ VerifyDefinitionAllowed(factoryRecord, _configPath, xmlUtil);
+ }
+ catch (ConfigurationException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
+ }
+ }
+
+ // Verify that section is unlocked, both for file and location inputs.
+ sectionLockMode = GetSectionLockedMode(configKey, out sectionChildLockMode);
+
+ if (sectionLockMode == OverrideMode.Deny)
+ {
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(SR.Config_section_locked, xmlUtil),
+ ExceptionAction.Local);
+ }
+
+ // check for configSource or protectionProvider
+ if (xmlUtil.Reader.AttributeCount >= 1)
+ {
+ // First do all the attributes reading without advancing the reader.
+
+ string configSourceAttribute = xmlUtil.Reader.GetAttribute(ConfigSourceAttribute);
+ if (configSourceAttribute != null)
+ {
+ try
+ {
+ configSource = NormalizeConfigSource(configSourceAttribute, xmlUtil);
+ }
+ catch (ConfigurationException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
+ }
+
+ if (xmlUtil.Reader.AttributeCount != 1)
+ {
+ // Error: elements with configSource should not have other attributes
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(SR.Config_source_syntax_error, xmlUtil),
+ ExceptionAction.Local);
+ }
+ }
+
+ string protectionProviderAttribute = xmlUtil.Reader.GetAttribute(ProtectionProviderAttibute);
+ if (protectionProviderAttribute != null)
+ {
+ try
+ {
+ protectionProviderName =
+ ValidateProtectionProviderAttribute(protectionProviderAttribute, xmlUtil);
+ }
+ catch (ConfigurationException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
+ }
+
+ if (xmlUtil.Reader.AttributeCount != 1)
+ {
+ // Error: elements with protectionProvider should not have other attributes
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(
+ SR.Protection_provider_syntax_error, xmlUtil),
+ ExceptionAction.Local);
+ }
+ }
+
+ // The 2nd part of the configSource check requires advancing the reader.
+ // Please note that this part should be done only AFTER all other attributes
+ // checking are done.
+ if (configSourceAttribute != null)
+ {
+ if (!xmlUtil.Reader.IsEmptyElement)
+ {
+ while (xmlUtil.Reader.Read())
+ {
+ XmlNodeType t = xmlUtil.Reader.NodeType;
+ if (t == XmlNodeType.EndElement)
+ break;
+
+ if (t == XmlNodeType.Comment) continue;
+
+ // Error: elements with configSource should not subelements other than comments
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(SR.Config_source_syntax_error, xmlUtil),
+ ExceptionAction.Local);
+
+ if (t == XmlNodeType.Element)
+ xmlUtil.StrictSkipToOurParentsEndElement(ExceptionAction.NonSpecific);
+ else xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+
+ positionedAtNextElement = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (configSource != null)
+ {
+ try
+ {
+ try
+ {
+ configSourceStreamName =
+ Host.GetStreamNameForConfigSource(ConfigStreamInfo.StreamName, configSource);
+ }
+ catch (Exception e)
+ {
+ throw ExceptionUtil.WrapAsConfigException(SR.Config_source_invalid, e, xmlUtil);
+ }
+ ValidateUniqueConfigSource(configKey, configSourceStreamName, configSource, xmlUtil);
+ configSourceStreamVersion = MonitorStream(configKey, configSource,
+ configSourceStreamName);
+ }
+ catch (ConfigurationException ex)
+ {
+ xmlUtil.SchemaErrors.AddError(ex, ExceptionAction.Local);
+ }
+ }
+
+ // prefetch the raw xml
+ if (!xmlUtil.SchemaErrors.HasLocalErrors)
+ {
+ if ((configSource == null) && ShouldPrefetchRawXml(factoryRecord))
+ {
+ Debug.Assert(!positionedAtNextElement, "!positionedAtNextElement");
+
+ rawXml = xmlUtil.CopySection();
+ if (xmlUtil.Reader.NodeType != XmlNodeType.Element)
+ {
+ xmlUtil.VerifyIgnorableNodeType(ExceptionAction.NonSpecific);
+ xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
+ }
+
+ positionedAtNextElement = true;
+ }
+ }
+ }
+
+ // Get the list of errors before advancing the reader
+ List<ConfigurationException> localErrors =
+ xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(isFileInput);
+
+ // advance the reader to the next element
+ if (!positionedAtNextElement) xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+
+ // Add the input either to:
+ // 1. The file input at the current config level, or
+ // 2. LocationSections, where it will be used in sub paths
+ bool addInput = true;
+
+ if (isFileInput)
+ {
+ // If isFileInput==true, Input added will be used against this config level.
+ // Need to check if we need to skip it due to inheritInChildApplications.
+
+ if (ShouldSkipDueToInheritInChildApplications(skipInChildApps)) addInput = false;
+ }
+ else
+ {
+ if (!_flags[SupportsLocation])
+ {
+ // Skip if we have a location input but we don't support location tag.
+ addInput = false;
+ }
+ }
+
+ if (addInput)
+ {
+ string targetConfigPath = locationSubPath == null ? _configPath : null;
+
+ SectionXmlInfo sectionXmlInfo = new SectionXmlInfo(
+ configKey, _configPath, targetConfigPath, locationSubPath,
+ fileName, lineNumber, ConfigStreamInfo.StreamVersion, rawXml,
+ configSource, configSourceStreamName, configSourceStreamVersion,
+ protectionProviderName, overrideMode, skipInChildApps);
+
+ if (locationSubPath == null)
+ {
+ // Add this file input to the section record
+
+ // We've already checked for locked above, so use skip the second check
+ // and set the locked bit.
+ SectionRecord sectionRecord = EnsureSectionRecordUnsafe(configKey, true);
+
+ // Since we called EnsureSectionRecordUnsafe the section record does not have its lock mode resolved
+ // but we have it in sectionLockMode and childLockMode. Apply it now
+ sectionRecord.ChangeLockSettings(sectionLockMode, sectionChildLockMode);
+
+ // Note that we first apply the lock mode comming from parent levels ( the line above ) and then
+ // add the file input since the file input takes precedence over whats comming from parent
+ SectionInput fileInput = new SectionInput(sectionXmlInfo, localErrors);
+ sectionRecord.AddFileInput(fileInput);
+ }
+ else
+ {
+ // Add this location input to this list of location sections
+ LocationSectionRecord locationSectionRecord = new LocationSectionRecord(sectionXmlInfo,
+ localErrors);
+ EnsureLocationSections().Add(locationSectionRecord);
+ }
+ }
+ }
+ }
+ }
+
+ private void ScanLocationSection(XmlUtil xmlUtil)
+ {
+ string locationSubPath = null;
+ bool inheritInChildApp = true;
+ int errorCountBeforeScan = xmlUtil.SchemaErrors.GlobalErrorCount;
+ OverrideModeSetting overrideMode = OverrideModeSetting.s_locationDefault;
+ bool overrideModeInit = false;
+
+ // Get the location section attributes
+ while (xmlUtil.Reader.MoveToNextAttribute())
+ switch (xmlUtil.Reader.Name)
+ {
+ case LocationPathAttribute:
+ locationSubPath = xmlUtil.Reader.Value;
+ break;
+ case LocationAllowOverrideAttribute:
+ // Check that allowOverride and OverrideMode werent specified at the same time
+ if (overrideModeInit)
+ {
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(SR.Invalid_override_mode_declaration, xmlUtil),
+ ExceptionAction.Global);
+ }
+ else
+ {
+ bool value;
+
+ // Read the value
+ xmlUtil.VerifyAndGetBooleanAttribute(
+ ExceptionAction.Global, true, out value);
+
+ overrideMode = OverrideModeSetting.CreateFromXmlReadValue(value);
+ overrideModeInit = true;
+ }
+ break;
+ case LocationOverrideModeAttribute:
+ if (overrideModeInit)
+ {
+ xmlUtil.SchemaErrors.AddError(
+ new ConfigurationErrorsException(SR.Invalid_override_mode_declaration,
+ xmlUtil), ExceptionAction.Global);
+ }
+ else
+ {
+ overrideMode = OverrideModeSetting.CreateFromXmlReadValue(
+ OverrideModeSetting.ParseOverrideModeXmlValue(xmlUtil.Reader.Value, xmlUtil));
+ overrideModeInit = true;
+ }
+ break;
+ case LocationInheritInChildApplicationsAttribute:
+ xmlUtil.VerifyAndGetBooleanAttribute(
+ ExceptionAction.Global, true, out inheritInChildApp);
+ break;
+ default:
+ xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.Global);
+ break;
+ }
+
+ xmlUtil.Reader.MoveToElement(); // if on an attribute move back to the element
+
+ try
+ {
+ locationSubPath = NormalizeLocationSubPath(locationSubPath, xmlUtil);
+
+ // We throw if we see one of these in machine.config or root web.config:
+ //
+ // <location path="." inheritInChildApplications="false" >
+ // <location inheritInChildApplications="false" >
+ //
+ // To detect whetherewe're machine.config or root web.config, the current fix is to use
+ // Host.IsDefinitionAllowed. Instead of this we should invent a new method in
+ // IInternalConfigHost to return whether a configPath can be part of an app or not.
+ // But since it's Whidbey RC "Ask Mode" I chose not to do it due to bigger code churn.
+ if ((locationSubPath == null) &&
+ !inheritInChildApp &&
+ Host.IsDefinitionAllowed(_configPath, ConfigurationAllowDefinition.MachineToWebRoot,
+ ConfigurationAllowExeDefinition.MachineOnly))
+ {
+ throw new ConfigurationErrorsException(
+ SR.Location_invalid_inheritInChildApplications_in_machine_or_root_web_config,
+ xmlUtil);
+ }
+ }
+ catch (ConfigurationErrorsException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Global);
+ }
+
+ // Skip over this location section if there are errors
+ if (xmlUtil.SchemaErrors.GlobalErrorCount > errorCountBeforeScan)
+ {
+ xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+ return;
+ }
+
+ // Scan elements of the location section if the path is the current path.
+ // We do not add <location path="." /> to the _locationSections list.
+ if (locationSubPath == null)
+ {
+ ScanSectionsRecursive(xmlUtil, string.Empty, true, null, overrideMode, !inheritInChildApp);
+ return;
+ }
+
+ // Skip over location sections for client config
+ if (!_flags[SupportsLocation])
+ {
+ xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+ return;
+ }
+
+ // Skip over location sections that don't apply to this (application) host for runtime records
+ IInternalConfigHost host = Host;
+ if (this is RuntimeConfigurationRecord && (host != null) && (locationSubPath.Length != 0) &&
+ (locationSubPath[0] != '.'))
+ {
+ // The application's config path is global to the AppDomain
+ if (s_appConfigPath == null)
+ {
+ object ctx = ConfigContext;
+ if (ctx != null)
+ {
+ string appConfigPath = ctx.ToString();
+ Interlocked.CompareExchange(ref s_appConfigPath, appConfigPath, null);
+ }
+ }
+
+ // If targetConfigPath is not upstream or downstream of the application's config path,
+ // skip this location section.
+ //
+ // Example #1: <location path="Site1"> has a targetConfigPath of "machine/webroot/1". This applies
+ // to Site1, whose application config path is "machine/webroot/1", but it does not apply
+ // to Site2, whose application config path is "machine/webroot/2"
+ //
+ // Example #2: <location path="subdir"> has a targetConfigPath of "machine/webroot/1/root/subdir".
+ // This applies to an application with an application config path of "machine/webroot/1/root/subdir/app".
+ string targetConfigPath = host.GetConfigPathFromLocationSubPath(_configPath, locationSubPath);
+ if (!StringUtil.StartsWithOrdinalIgnoreCase(s_appConfigPath, targetConfigPath)
+ && !StringUtil.StartsWithOrdinalIgnoreCase(targetConfigPath, s_appConfigPath))
+ {
+ xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
+ return;
+ }
+ }
+
+ AddLocation(locationSubPath);
+ ScanSectionsRecursive(xmlUtil, string.Empty, true, locationSubPath, overrideMode, !inheritInChildApp);
+ }
+
+ // If you wish to keep track of the Location Fields, then use this
+ protected virtual void AddLocation(string locationSubPath) { }
+
+ // Resolve information about a location section at the time that the location section
+ // is being used by child configuration records. This allows us to:
+ // * Delay determining the configuration path for the location record until the sites section is available.
+ // * Delay reporting bad location paths until the location record has to be used.
+ private void ResolveLocationSections()
+ {
+ if (_flags[IsLocationListResolved]) return;
+
+ // Resolve outside of any lock
+ if (!_parent.IsRootConfig) _parent.ResolveLocationSections();
+
+ lock (this)
+ {
+ if (!_flags[IsLocationListResolved])
+ {
+ if (_locationSections != null)
+ {
+ // Create dictionary that maps configPaths to (dictionary that maps sectionNames to locationSectionRecords)
+ HybridDictionary locationConfigPaths = new HybridDictionary(true);
+ foreach (LocationSectionRecord locationSectionRecord in _locationSections)
+ {
+ // Resolve the target config path
+ string targetConfigPath = Host.GetConfigPathFromLocationSubPath(_configPath,
+ locationSectionRecord.SectionXmlInfo.SubPath);
+ locationSectionRecord.SectionXmlInfo.TargetConfigPath = targetConfigPath;
+
+ // Check uniqueness
+ HybridDictionary locationSectionRecordDictionary =
+ (HybridDictionary)locationConfigPaths[targetConfigPath];
+ if (locationSectionRecordDictionary == null)
+ {
+ locationSectionRecordDictionary = new HybridDictionary(false);
+ locationConfigPaths.Add(targetConfigPath, locationSectionRecordDictionary);
+ }
+
+ LocationSectionRecord duplicateRecord =
+ (LocationSectionRecord)
+ locationSectionRecordDictionary[locationSectionRecord.ConfigKey];
+ FactoryRecord factoryRecord = null;
+ if (duplicateRecord == null)
+ {
+ locationSectionRecordDictionary.Add(locationSectionRecord.ConfigKey,
+ locationSectionRecord);
+ }
+ else
+ {
+ factoryRecord = FindFactoryRecord(locationSectionRecord.ConfigKey, true);
+ if ((factoryRecord == null) || !factoryRecord.IsIgnorable())
+ {
+ if (!duplicateRecord.HasErrors)
+ {
+ duplicateRecord.AddError(
+ new ConfigurationErrorsException(
+ SR.Config_sections_must_be_unique,
+ duplicateRecord.SectionXmlInfo));
+ }
+
+ locationSectionRecord.AddError(
+ new ConfigurationErrorsException(
+ SR.Config_sections_must_be_unique,
+ locationSectionRecord.SectionXmlInfo));
+ }
+ }
+
+ // Check if the definition is allowed
+ if (factoryRecord == null)
+ factoryRecord = FindFactoryRecord(locationSectionRecord.ConfigKey, true);
+
+ if (factoryRecord.HasErrors) continue;
+
+ try
+ {
+ VerifyDefinitionAllowed(factoryRecord, targetConfigPath,
+ locationSectionRecord.SectionXmlInfo);
+ }
+ catch (ConfigurationException e)
+ {
+ locationSectionRecord.AddError(e);
+ }
+ }
+
+ // Check location section for being locked.
+ BaseConfigurationRecord parent = _parent;
+ while (!parent.IsRootConfig)
+ {
+ foreach (LocationSectionRecord locationSectionRecord in _locationSections)
+ {
+ bool locked = false;
+
+ // It is an error if a parent section with the same configKey is locked.
+ SectionRecord sectionRecord =
+ parent.GetSectionRecord(locationSectionRecord.ConfigKey, true);
+ if ((sectionRecord != null) &&
+ (sectionRecord.LockChildren || sectionRecord.Locked))
+ locked = true;
+ else
+ {
+ // It is an error if a parent configuration file locks a section for the
+ // locationConfigPath or any sub-path of the locationConfigPath.
+ if (parent._locationSections != null)
+ {
+ string targetConfigPath =
+ locationSectionRecord.SectionXmlInfo.TargetConfigPath;
+
+ foreach (
+ LocationSectionRecord parentLocationSectionRecord in
+ parent._locationSections)
+ {
+ string parentTargetConfigPath =
+ parentLocationSectionRecord.SectionXmlInfo.TargetConfigPath;
+
+ if (
+ parentLocationSectionRecord.SectionXmlInfo.OverrideModeSetting.IsLocked &&
+ (locationSectionRecord.ConfigKey ==
+ parentLocationSectionRecord.ConfigKey) &&
+ UrlPath.IsEqualOrSubpath(targetConfigPath, parentTargetConfigPath))
+ {
+ locked = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (locked)
+ {
+ locationSectionRecord.AddError(new ConfigurationErrorsException(
+ SR.Config_section_locked,
+ locationSectionRecord.SectionXmlInfo));
+ }
+ }
+
+ parent = parent._parent;
+ }
+ }
+ }
+
+ _flags[IsLocationListResolved] = true;
+ }
+ }
+
+
+ // Verify that the Definition is allowed at this place.
+ //
+ // For example, if this config record is an application then make sure the section
+ // says it can be defined in an application
+ private void VerifyDefinitionAllowed(FactoryRecord factoryRecord, string configPath, IConfigErrorInfo errorInfo)
+ {
+ Host.VerifyDefinitionAllowed(configPath, factoryRecord.AllowDefinition, factoryRecord.AllowExeDefinition,
+ errorInfo);
+ }
+
+ internal bool IsDefinitionAllowed(ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition)
+ {
+ return Host.IsDefinitionAllowed(_configPath, allowDefinition, allowExeDefinition);
+ }
+
+ protected static void VerifySectionName(string name, XmlUtil xmlUtil, ExceptionAction action, bool allowImplicit)
+ {
+ try
+ {
+ VerifySectionName(name, xmlUtil, allowImplicit);
+ }
+ catch (ConfigurationErrorsException ce)
+ {
+ xmlUtil.SchemaErrors.AddError(ce, action);
+ }
+ }
+
+ // Check if the section name contains reserved words from the config system,
+ // and is a valid name for an XML Element.
+ protected static void VerifySectionName(string name, IConfigErrorInfo errorInfo, bool allowImplicit)
+ {
+ if (string.IsNullOrEmpty(name))
+ throw new ConfigurationErrorsException(SR.Config_tag_name_invalid, errorInfo);
+
+ // must be a valid name in xml, so that it can be used as an element
+ // n.b. - it also excludes forward slash '/'
+ try
+ {
+ XmlConvert.VerifyName(name);
+ }
+ catch (Exception e)
+ {
+ // Do not let the exception propagate as an XML exception,
+ // for we want errors in the section name to be treated as local errors,
+ // not global ones.
+ throw ExceptionUtil.WrapAsConfigException(SR.Config_tag_name_invalid, e, errorInfo);
+ }
+
+ if (IsImplicitSection(name))
+ {
+ if (allowImplicit)
+ {
+ // avoid test below for strings starting with "config"
+ return;
+ }
+
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Cannot_declare_or_remove_implicit_section, name), errorInfo);
+ }
+
+ if (StringUtil.StartsWithOrdinal(name, "config"))
+ throw new ConfigurationErrorsException(SR.Config_tag_name_cannot_begin_with_config, errorInfo);
+
+ if (name == LocationTag)
+ throw new ConfigurationErrorsException(SR.Config_tag_name_cannot_be_location, errorInfo);
+ }
+
+ // Return null if the subPath represents the current directory, for example:
+ // path=""
+ // path=" "
+ // path="."
+ // path="./"
+ internal static string NormalizeLocationSubPath(string subPath, IConfigErrorInfo errorInfo)
+ {
+ // if subPath is null or empty, it is the current dir
+ if (string.IsNullOrEmpty(subPath))
+ return null;
+
+ // if subPath=".", it is the current dir
+ if (subPath == ".")
+ return null;
+
+ // do not allow whitespace in front of subPath, as the OS
+ // handles beginning and trailing whitespace inconsistently
+ string trimmedSubPath = subPath.TrimStart();
+ if (trimmedSubPath.Length != subPath.Length)
+ throw new ConfigurationErrorsException(SR.Config_location_path_invalid_first_character, errorInfo);
+
+ // do not allow problematic starting characters
+ if (InvalidFirstSubPathCharacters.IndexOf(subPath[0]) != -1)
+ throw new ConfigurationErrorsException(SR.Config_location_path_invalid_first_character, errorInfo);
+
+ // do not allow whitespace at end of subPath, as the OS
+ // handles beginning and trailing whitespace inconsistently
+ trimmedSubPath = subPath.TrimEnd();
+ if (trimmedSubPath.Length != subPath.Length)
+ throw new ConfigurationErrorsException(SR.Config_location_path_invalid_last_character, errorInfo);
+
+ // the file system ignores trailing '.', '\', or '/', so do not allow it in a location subpath specification
+ if (InvalidLastSubPathCharacters.IndexOf(subPath[subPath.Length - 1]) != -1)
+ throw new ConfigurationErrorsException(SR.Config_location_path_invalid_last_character, errorInfo);
+
+ // combination of URI reserved characters and OS invalid filename characters, minus / (allowed reserved character)
+ if (subPath.IndexOfAny(s_invalidSubPathCharactersArray) != -1)
+ throw new ConfigurationErrorsException(SR.Config_location_path_invalid_character, errorInfo);
+
+ return subPath;
+ }
+
+ // Return the SectionRecord for a section.
+ // If the record does not exist, return null.
+ // Throw cached errors if the section is in error and permitErrors == false.
+ protected SectionRecord GetSectionRecord(string configKey, bool permitErrors)
+ {
+ SectionRecord sectionRecord;
+
+ if (_sectionRecords != null) sectionRecord = (SectionRecord)_sectionRecords[configKey];
+ else sectionRecord = null;
+
+ if ((sectionRecord != null) && !permitErrors) sectionRecord.ThrowOnErrors();
+
+ return sectionRecord;
+ }
+
+ // Return an existing SectionRecord, or create one if one does not exist.
+ // Propagate the Locked bit from parent
+ protected SectionRecord EnsureSectionRecord(string configKey, bool permitErrors)
+ {
+ return EnsureSectionRecordImpl(configKey, permitErrors, true);
+ }
+
+ // Return an existing SectionRecord, or create one if one does not exist.
+ // Do not propagate the Locked bit from parent, because caller will check
+ // himself later.
+ protected SectionRecord EnsureSectionRecordUnsafe(string configKey, bool permitErrors)
+ {
+ return EnsureSectionRecordImpl(configKey, permitErrors, false);
+ }
+
+ // Return an existing SectionRecord, or create one if one does not exist.
+ // If desired, set the lock settings based on parent configs.
+ private SectionRecord EnsureSectionRecordImpl(string configKey, bool permitErrors, bool setLockSettings)
+ {
+ SectionRecord sectionRecord = GetSectionRecord(configKey, permitErrors);
+ if (sectionRecord != null) return sectionRecord;
+
+ lock (this)
+ {
+ if (_sectionRecords == null) _sectionRecords = new Hashtable();
+ else sectionRecord = GetSectionRecord(configKey, permitErrors);
+
+ if (sectionRecord == null)
+ {
+ sectionRecord = new SectionRecord(configKey);
+
+ _sectionRecords.Add(configKey, sectionRecord);
+ }
+ }
+
+ if (setLockSettings)
+ {
+ // Get the lock mode from parent configs
+ OverrideMode childLockMode;
+ OverrideMode parentMode = ResolveOverrideModeFromParent(configKey, out childLockMode);
+
+ sectionRecord.ChangeLockSettings(parentMode, childLockMode);
+ }
+
+ return sectionRecord;
+ }
+
+ internal FactoryRecord GetFactoryRecord(string configKey, bool permitErrors)
+ {
+ if (_factoryRecords == null) return null;
+
+ FactoryRecord factoryRecord = (FactoryRecord)_factoryRecords[configKey];
+ if ((factoryRecord != null) && !permitErrors) factoryRecord.ThrowOnErrors();
+
+ return factoryRecord;
+ }
+
+ // Only create a _factories hashtable when necessary.
+ // Most config records won't have factories, so we can save 120 bytes
+ // per record by creating the table on demand.
+ protected Hashtable EnsureFactories()
+ {
+ return _factoryRecords ?? (_factoryRecords = new Hashtable());
+ }
+
+ private ArrayList EnsureLocationSections()
+ {
+ return _locationSections ?? (_locationSections = new ArrayList());
+ }
+
+ internal static string NormalizeConfigSource(string configSource, IConfigErrorInfo errorInfo)
+ {
+ if (string.IsNullOrEmpty(configSource))
+ throw new ConfigurationErrorsException(SR.Config_source_invalid_format, errorInfo);
+
+ string trimmedConfigSource = configSource.Trim();
+ if (trimmedConfigSource.Length != configSource.Length)
+ throw new ConfigurationErrorsException(SR.Config_source_invalid_format, errorInfo);
+
+ if (configSource.IndexOf('/') != -1)
+ throw new ConfigurationErrorsException(SR.Config_source_invalid_chars, errorInfo);
+
+ if (string.IsNullOrEmpty(configSource) || Path.IsPathRooted(configSource))
+ throw new ConfigurationErrorsException(SR.Config_source_invalid_format, errorInfo);
+
+ return configSource;
+ }
+
+ protected object MonitorStream(string configKey, string configSource, string streamname)
+ {
+ lock (this)
+ {
+ if (_flags[Closed]) return null;
+
+ StreamInfo streamInfo = (StreamInfo)ConfigStreamInfo.StreamInfos[streamname];
+ if (streamInfo != null)
+ {
+ if (streamInfo.SectionName != configKey)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_source_cannot_be_shared,
+ streamname));
+ }
+
+ if (streamInfo.IsMonitored) return streamInfo.Version;
+ }
+ else
+ {
+ streamInfo = new StreamInfo(configKey, configSource, streamname);
+ ConfigStreamInfo.StreamInfos.Add(streamname, streamInfo);
+ }
+ }
+
+ // Call the host outside the lock to avoid deadlock.
+ object version = Host.GetStreamVersion(streamname);
+
+ StreamChangeCallback callbackDelegate = null;
+
+ lock (this)
+ {
+ if (_flags[Closed]) return null;
+
+ StreamInfo streamInfo = (StreamInfo)ConfigStreamInfo.StreamInfos[streamname];
+ if (streamInfo.IsMonitored) return streamInfo.Version;
+
+ streamInfo.IsMonitored = true;
+ streamInfo.Version = version;
+
+ if (_flags[SupportsChangeNotifications])
+ {
+ if (ConfigStreamInfo.CallbackDelegate == null)
+ ConfigStreamInfo.CallbackDelegate = OnStreamChanged;
+
+ callbackDelegate = ConfigStreamInfo.CallbackDelegate;
+ }
+ }
+
+ if (_flags[SupportsChangeNotifications]) Host.StartMonitoringStreamForChanges(streamname, callbackDelegate);
+
+ return version;
+ }
+
+ private void OnStreamChanged(string streamname)
+ {
+ bool notifyChanged;
+ string sectionName;
+
+ lock (this)
+ {
+ if (_flags[Closed])
+ return;
+
+ StreamInfo streamInfo = (StreamInfo)ConfigStreamInfo.StreamInfos[streamname];
+ if ((streamInfo == null) || !streamInfo.IsMonitored)
+ return;
+
+ sectionName = streamInfo.SectionName;
+ }
+
+ if (sectionName == null) notifyChanged = true;
+ else
+ {
+ FactoryRecord factoryRecord = FindFactoryRecord(sectionName, false);
+ notifyChanged = factoryRecord.RestartOnExternalChanges;
+ }
+
+ if (notifyChanged) _configRoot.FireConfigChanged(_configPath);
+ else _configRoot.ClearResult(this, sectionName, false);
+ }
+
+ // ValidateUniqueConfigSource
+ //
+ // Validate that the configSource is unique for this particular
+ // configKey. This looks up at the parents and makes sure it is
+ // unique. It if is in a child, then it's check will find this
+ // one. If it is in a peer, then we don't care as much, since it
+ // will not affect Merge and UnMerge
+ private void ValidateUniqueConfigSource(
+ string configKey, string configSourceStreamName, string configSourceArg, IConfigErrorInfo errorInfo)
+ {
+ // Detect if another section in this file is using the same configSource
+ // with has a different section name.
+ lock (this)
+ {
+ if (ConfigStreamInfo.HasStreamInfos)
+ {
+ StreamInfo streamInfo = (StreamInfo)ConfigStreamInfo.StreamInfos[configSourceStreamName];
+ if ((streamInfo != null) && (streamInfo.SectionName != configKey))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_source_cannot_be_shared, configSourceArg),
+ errorInfo);
+ }
+ }
+ }
+
+ ValidateUniqueChildConfigSource(configKey, configSourceStreamName, configSourceArg, errorInfo);
+ }
+
+ protected void ValidateUniqueChildConfigSource(
+ string configKey, string configSourceStreamName, string configSourceArg, IConfigErrorInfo errorInfo)
+ {
+ // Detect if a parent config file is using the same config source stream.
+ BaseConfigurationRecord current = IsLocationConfig ? _parent._parent : _parent;
+
+ while (!current.IsRootConfig)
+ {
+ lock (current)
+ {
+ if (current.ConfigStreamInfo.HasStreamInfos)
+ {
+ StreamInfo streamInfo =
+ (StreamInfo)current.ConfigStreamInfo.StreamInfos[configSourceStreamName];
+ if (streamInfo != null)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_source_parent_conflict, configSourceArg),
+ errorInfo);
+ }
+ }
+ }
+
+ current = current.Parent;
+ }
+ }
+
+ // Recursively clear the result.
+ // If forceEvaluation == true, force a rescan of the config file to find
+ // the section.
+ // Requires the hierarchy lock to be acquired (hl)
+ internal void HlClearResultRecursive(string configKey, bool forceEvaluatation)
+ {
+ // Refresh it's factory Record
+ RefreshFactoryRecord(configKey);
+
+ // Clear any stored result in the section
+ SectionRecord sectionRecord = GetSectionRecord(configKey, false);
+ if (sectionRecord != null)
+ {
+ sectionRecord.ClearResult();
+
+ // Need to clear all RawXml so that when GetSectionXmlReader is called later it will reload the file.
+ sectionRecord.ClearRawXml();
+ }
+
+ // If we need to reevaluate, add a dummy file input so
+ // that we open the file on the next evaluation
+ if (forceEvaluatation && !IsInitDelayed && !string.IsNullOrEmpty(ConfigStreamInfo.StreamName))
+ {
+ if (_flags[SupportsPath])
+ throw ExceptionUtil.UnexpectedError("BaseConfigurationRecord::hlClearResultRecursive");
+
+ FactoryRecord factoryRecord = FindFactoryRecord(configKey, false);
+ if ((factoryRecord != null) && !factoryRecord.IsGroup)
+ {
+ configKey = factoryRecord.ConfigKey;
+ sectionRecord = EnsureSectionRecord(configKey, false);
+ if (!sectionRecord.HasFileInput)
+ {
+ SectionXmlInfo sectionXmlInfo = new SectionXmlInfo(
+ configKey, _configPath, _configPath, null,
+ ConfigStreamInfo.StreamName, 0, null, null,
+ null, null, null,
+ null, OverrideModeSetting.s_locationDefault, false);
+
+ SectionInput fileInput = new SectionInput(sectionXmlInfo, null);
+ sectionRecord.AddFileInput(fileInput);
+ }
+ }
+ }
+
+ // Recurse
+ if (_children != null)
+ {
+ IEnumerable children = _children.Values;
+ foreach (BaseConfigurationRecord child in children)
+ child.HlClearResultRecursive(configKey, forceEvaluatation);
+ }
+ }
+
+ // Returns a child record.
+ // Requires the hierarchy lock to be acquired (hl)
+ internal BaseConfigurationRecord HlGetChild(string configName)
+ {
+ return (BaseConfigurationRecord)_children?[configName];
+ }
+
+ // Adds a child record.
+ // Requires the hierarchy lock to be acquired (hl)
+ internal void HlAddChild(string configName, BaseConfigurationRecord child)
+ {
+ if (_children == null) _children = new Hashtable(StringComparer.OrdinalIgnoreCase);
+
+ _children.Add(configName, child);
+ }
+
+ // Removes a child record.
+ // Requires the hierarchy lock to be acquired (hl)
+ internal void HlRemoveChild(string configName)
+ {
+ _children?.Remove(configName);
+ }
+
+ // Removes true if a child record is needed for a
+ // child config path.
+ // Requires the hierarchy lock to be acquired (hl)
+ internal bool HlNeedsChildFor(string configName)
+ {
+ // Always return true for root config record
+ if (IsRootConfig)
+ return true;
+
+ // Never create a child record when the parent has an exception.
+ if (HasInitErrors) return false;
+
+ string childConfigPath = ConfigPathUtility.Combine(_configPath, configName);
+
+ // check host if required
+ if (Host.IsConfigRecordRequired(childConfigPath)) return true;
+
+ // see if there's a location
+ if (!_flags[SupportsLocation]) return false;
+ BaseConfigurationRecord configRecord = this;
+
+ while (!configRecord.IsRootConfig)
+ {
+ if (configRecord._locationSections != null)
+ {
+ configRecord.ResolveLocationSections();
+ foreach (LocationSectionRecord locationSectionRecord in configRecord._locationSections)
+ if (UrlPath.IsEqualOrSubpath(childConfigPath,
+ locationSectionRecord.SectionXmlInfo.TargetConfigPath))
+ return true;
+ }
+
+ configRecord = configRecord._parent;
+ }
+
+ return false;
+ }
+
+ // Close the record. An explicit close is needed
+ // in order to stop monitoring streams used by
+ // this record. Stream monitors cause this record
+ // to be rooted in the GC heap.
+ //
+ // Note that we purposely do not cleanup the child/parent
+ // hierarchy. This is so that a config system which has
+ // a pointer to this record can still call GetSection on
+ // it while another thread closes it.
+ internal void CloseRecursive()
+ {
+ if (_flags[Closed]) return;
+ bool doClose = false;
+ HybridDictionary streamInfos = null;
+ StreamChangeCallback callbackDelegate = null;
+
+ lock (this)
+ {
+ if (!_flags[Closed])
+ {
+ _flags[Closed] = true;
+ doClose = true;
+
+ if (!IsLocationConfig && ConfigStreamInfo.HasStreamInfos)
+ {
+ callbackDelegate = ConfigStreamInfo.CallbackDelegate;
+ streamInfos = ConfigStreamInfo.StreamInfos;
+
+ ConfigStreamInfo.CallbackDelegate = null;
+ ConfigStreamInfo.ClearStreamInfos();
+ }
+ }
+ }
+
+ if (!doClose) return;
+
+ // no hierarchy lock is needed to access _children here,
+ // as it has already been detached from the hierarchy tree
+ if (_children != null)
+ foreach (BaseConfigurationRecord child in _children.Values) child.CloseRecursive();
+
+ if (streamInfos != null)
+ {
+ foreach (StreamInfo streamInfo in streamInfos.Values)
+ if (streamInfo.IsMonitored)
+ {
+ Host.StopMonitoringStreamForChanges(streamInfo.StreamName, callbackDelegate);
+ streamInfo.IsMonitored = false;
+ }
+ }
+ }
+
+ internal string FindChangedConfigurationStream()
+ {
+ BaseConfigurationRecord configRecord = this;
+ while (!configRecord.IsRootConfig)
+ {
+ lock (configRecord)
+ {
+ if (configRecord.ConfigStreamInfo.HasStreamInfos)
+ {
+ foreach (StreamInfo streamInfo in configRecord.ConfigStreamInfo.StreamInfos.Values)
+ if (streamInfo.IsMonitored && HasStreamChanged(streamInfo.StreamName, streamInfo.Version))
+ return streamInfo.StreamName;
+ }
+ }
+
+ configRecord = configRecord._parent;
+ }
+
+ return null;
+ }
+
+ private bool HasStreamChanged(string streamname, object lastVersion)
+ {
+ object currentVersion = Host.GetStreamVersion(streamname);
+
+ if (lastVersion != null) return (currentVersion == null) || !lastVersion.Equals(currentVersion);
+
+ return currentVersion != null;
+ }
+
+ protected virtual string CallHostDecryptSection(string encryptedXml,
+ ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfig)
+ {
+ return Host.DecryptSection(encryptedXml, protectionProvider, protectedConfig);
+ }
+
+ internal static string ValidateProtectionProviderAttribute(string protectionProvider, IConfigErrorInfo errorInfo)
+ {
+ if (string.IsNullOrEmpty(protectionProvider))
+ throw new ConfigurationErrorsException(SR.Protection_provider_invalid_format, errorInfo);
+
+ return protectionProvider;
+ }
+
+ private ConfigXmlReader DecryptConfigSection(ConfigXmlReader reader,
+ ProtectedConfigurationProvider protectionProvider)
+ {
+ ConfigXmlReader clone = reader.Clone();
+ IConfigErrorInfo err = clone;
+ string clearTextXml;
+ XmlNodeType nodeType;
+
+ clone.Read();
+
+ // Save the file and line at the top of the section
+ string filename = err.Filename;
+ int lineNumber = err.LineNumber;
+ int sectionLineNumber = lineNumber;
+
+ if (clone.IsEmptyElement)
+ throw new ConfigurationErrorsException(SR.EncryptedNode_not_found, filename, lineNumber);
+
+ // Find the <EncryptedData> node
+ for (;;)
+ {
+ clone.Read(); // Keep reading till we find a relavant node
+
+ nodeType = clone.NodeType;
+
+ if ((nodeType == XmlNodeType.Element) && (clone.Name == "EncryptedData"))
+ {
+ // Found it!
+ break;
+ }
+
+ if (nodeType == XmlNodeType.EndElement)
+ throw new ConfigurationErrorsException(SR.EncryptedNode_not_found, filename, lineNumber);
+
+ if ((nodeType != XmlNodeType.Comment) && (nodeType != XmlNodeType.Whitespace))
+ {
+ // some other unexpected content
+ throw new ConfigurationErrorsException(SR.EncryptedNode_is_in_invalid_format, filename, lineNumber);
+ }
+ }
+
+ // Do the decryption
+
+ // Save the line at the top of the <EncryptedData> node
+ lineNumber = err.LineNumber;
+
+ string encryptedXml = clone.ReadOuterXml();
+ try
+ {
+ clearTextXml = CallHostDecryptSection(encryptedXml, protectionProvider, ProtectedConfig);
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Decryption_failed, protectionProvider.Name, e.Message), e, filename, lineNumber);
+ }
+
+ // Detect if there is any XML left over after <EncryptedData>
+ do
+ {
+ nodeType = clone.NodeType;
+
+ if (nodeType == XmlNodeType.EndElement) break;
+
+ if ((nodeType != XmlNodeType.Comment) && (nodeType != XmlNodeType.Whitespace))
+ {
+ // Got other unexpected content
+ throw new ConfigurationErrorsException(SR.EncryptedNode_is_in_invalid_format, filename, lineNumber);
+ }
+ } while (clone.Read());
+
+ // Create a new reader, using the position of the original reader
+ return new ConfigXmlReader(clearTextXml, filename, sectionLineNumber, true);
+ }
+
+ private void ThrowIfParseErrors(ConfigurationSchemaErrors schemaErrors)
+ {
+ schemaErrors.ThrowIfErrors(ClassFlags[ClassIgnoreLocalErrors]);
+ }
+
+ internal static bool IsImplicitSection(string configKey)
+ {
+ return string.Equals(configKey, ReservedSectionProtectedConfiguration, StringComparison.Ordinal);
+ }
+
+ /// <summary>
+ /// Add implicit sections to the specified factory list.
+ /// </summary>
+ /// <param name="factoryList">The factory list to add to. If null, adds to the current record's factory list.</param>
+ private void AddImplicitSections(Hashtable factoryList)
+ {
+ // Only add implicit sections to the factoryList if we're under the root
+ // (e.g. if we're in machine.config)
+ if (!_parent.IsRootConfig) return;
+
+ if (factoryList == null) factoryList = EnsureFactories();
+
+ // Look to see if we already have a factory for "configProtectedData"
+ FactoryRecord factoryRecord = (FactoryRecord)factoryList[ReservedSectionProtectedConfiguration];
+
+ if (factoryRecord != null)
+ {
+ // If the user has mistakenly declared an implicit section, we should leave the factoryRecord
+ // alone because it contains the error and the error will be thrown later.
+
+ Debug.Assert(factoryRecord.HasErrors,
+ "If the user has mistakenly declared an implicit section, we should have recorded an error.");
+ return;
+ }
+
+ // Add our implicit "configProtectedData" for ProtectedConfigurationSection
+ factoryList[ReservedSectionProtectedConfiguration] =
+ new FactoryRecord(
+ configKey: ReservedSectionProtectedConfiguration,
+ group: string.Empty,
+ name: ReservedSectionProtectedConfiguration,
+ factoryTypeName: ProtectedConfigurationSectionTypeName,
+ allowLocation: true,
+ allowDefinition: ConfigurationAllowDefinition.Everywhere,
+ allowExeDefinition: ConfigurationAllowExeDefinition.MachineToApplication,
+ overrideModeDefault: OverrideModeSetting.s_sectionDefault,
+ restartOnExternalChanges: true,
+ requirePermission: true,
+ isFromTrustedConfigRecord: true,
+ isUndeclared: true,
+ filename: null,
+ lineNumber: -1);
+ }
+
+ // We reserve all attribute names starting with config or lock
+ internal static bool IsReservedAttributeName(string name)
+ {
+ return StringUtil.StartsWithOrdinal(name, "config") ||
+ StringUtil.StartsWithOrdinal(name, "lock");
+ }
+
+ protected class ConfigRecordStreamInfo
+ {
+ private HybridDictionary _streamInfos;
+
+ internal ConfigRecordStreamInfo()
+ {
+ StreamEncoding = Encoding.UTF8;
+ }
+
+ internal bool HasStream { get; set; }
+
+ internal string StreamName { get; set; }
+
+ internal object StreamVersion { get; set; }
+
+ internal Encoding StreamEncoding { get; set; }
+
+ internal StreamChangeCallback CallbackDelegate { get; set; }
+
+ internal HybridDictionary StreamInfos => _streamInfos ?? (_streamInfos = new HybridDictionary(true));
+
+ internal bool HasStreamInfos => _streamInfos != null;
+
+#if DEBUG
+ internal string[] Keys
+ {
+ get
+ {
+ string[] keys = new string[StreamInfos.Count];
+ StreamInfos.Keys.CopyTo(keys, 0);
+ return keys;
+ }
+ }
+#endif
+
+ internal void ClearStreamInfos()
+ {
+ _streamInfos = null;
+ }
+ }
+
+ private class IndirectLocationInputComparer : IComparer<SectionInput>
+ {
+ public int Compare(SectionInput x, SectionInput y)
+ {
+ // We have to sort the indirect inputs
+ // 1. First by the location tag's target config path, and if they're the same,
+ // 2. Then by the location tag's definition config path.
+ //
+ // In the final sorted list, a child will be smaller than a parent.
+
+ Debug.Assert(x.SectionXmlInfo.ConfigKey == y.SectionXmlInfo.ConfigKey);
+
+ if (ReferenceEquals(x, y))
+ {
+ // Check if they're the same object.
+ return 0;
+ }
+
+ string xTargetConfigPath = x.SectionXmlInfo.TargetConfigPath;
+ string yTargetConfigPath = y.SectionXmlInfo.TargetConfigPath;
+
+ // First compare using location tag's target config path:
+ if (UrlPath.IsSubpath(xTargetConfigPath, yTargetConfigPath))
+ {
+ // yTargetConfigPath is a child path of xTargetConfigPath, so y < x
+ return 1;
+ }
+
+ if (UrlPath.IsSubpath(yTargetConfigPath, xTargetConfigPath))
+ {
+ // xTargetConfigPath is a child path of yTargetConfigPath, so x < y
+ return -1;
+ }
+
+ // Because all indirect inputs must be pointing to nodes along a
+ // single branch of config hierarchy, so if the above two cases
+ // aren't true, then the two target config path must be equal;
+ // in another word, they should not be siblings.
+ Debug.Assert(StringUtil.EqualsIgnoreCase(yTargetConfigPath, xTargetConfigPath));
+
+ string xDefinitionConfigPath = x.SectionXmlInfo.DefinitionConfigPath;
+ string yDefinitionConfigPath = y.SectionXmlInfo.DefinitionConfigPath;
+
+ // Then compare using where the location tag is defined.
+ if (UrlPath.IsSubpath(xDefinitionConfigPath, yDefinitionConfigPath))
+ {
+ // yDefinitionConfigPath is a child path of xDefinitionConfigPath, so y < x
+ return 1;
+ }
+
+ if (UrlPath.IsSubpath(yDefinitionConfigPath, xDefinitionConfigPath))
+ {
+ // xDefinitionConfigPath is a child path of yDefinitionConfigPath, so x < y
+ return -1;
+ }
+
+ Debug.Assert(false,
+ "It's not possible for two location input to come from the same config file and point to the same target");
+ return 0;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/CallbackValidator.cs b/src/System.Configuration/src/System/Configuration/CallbackValidator.cs
new file mode 100644
index 0000000000..c29428ba57
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/CallbackValidator.cs
@@ -0,0 +1,36 @@
+// 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.Configuration
+{
+ public sealed class CallbackValidator : ConfigurationValidatorBase
+ {
+ private readonly ValidatorCallback _callback;
+ private readonly Type _type;
+
+ public CallbackValidator(Type type, ValidatorCallback callback) : this(callback)
+ {
+ if (type == null) throw new ArgumentNullException(nameof(type));
+ _type = type;
+ }
+
+ // Do not check for null type here to handle the callback attribute case
+ internal CallbackValidator(ValidatorCallback callback)
+ {
+ if (callback == null) throw new ArgumentNullException(nameof(callback));
+ _type = null;
+ _callback = callback;
+ }
+
+ public override bool CanValidate(Type type)
+ {
+ return (type == _type) || (_type == null);
+ }
+
+ public override void Validate(object value)
+ {
+ _callback(value);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/CallbackValidatorAttribute.cs b/src/System.Configuration/src/System/Configuration/CallbackValidatorAttribute.cs
new file mode 100644
index 0000000000..2eb9d1f059
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/CallbackValidatorAttribute.cs
@@ -0,0 +1,66 @@
+// 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.Reflection;
+
+namespace System.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class CallbackValidatorAttribute : ConfigurationValidatorAttribute
+ {
+ private ValidatorCallback _callbackMethod;
+ private string _callbackMethodName = string.Empty;
+ private Type _type;
+
+ public override ConfigurationValidatorBase ValidatorInstance
+ {
+ get
+ {
+ if (_callbackMethod == null)
+ {
+ if (_type == null) throw new ArgumentNullException("Type");
+
+ if (!string.IsNullOrEmpty(_callbackMethodName))
+ {
+ MethodInfo methodInfo = _type.GetMethod(_callbackMethodName, BindingFlags.Public | BindingFlags.Static);
+
+ if (methodInfo != null)
+ {
+ ParameterInfo[] parameters = methodInfo.GetParameters();
+ if ((parameters.Length == 1) && (parameters[0].ParameterType == typeof(object)))
+ {
+ _callbackMethod = (ValidatorCallback)Delegate.CreateDelegate(typeof(ValidatorCallback), methodInfo);
+ }
+ }
+ }
+ }
+
+ if (_callbackMethod == null)
+ throw new ArgumentException(string.Format(SR.Validator_method_not_found, _callbackMethodName));
+
+ return new CallbackValidator(_callbackMethod);
+ }
+ }
+
+ public Type Type
+ {
+ get { return _type; }
+ set
+ {
+ _type = value;
+ _callbackMethod = null;
+ }
+ }
+
+ public string CallbackMethodName
+ {
+ get { return _callbackMethodName; }
+ set
+ {
+ _callbackMethodName = value;
+ _callbackMethod = null;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ClientConfigPaths.cs b/src/System.Configuration/src/System/Configuration/ClientConfigPaths.cs
new file mode 100644
index 0000000000..556a27d094
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ClientConfigPaths.cs
@@ -0,0 +1,354 @@
+// 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.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Security;
+
+namespace System.Configuration
+{
+ internal class ClientConfigPaths
+ {
+ internal const string UserConfigFilename = "user.config";
+
+ private const string ConfigExtension = ".config";
+ private const int MaxLengthToUse = 25;
+ private const string FileUriLocal = "file:///";
+ private const string FileUriUnc = "file://";
+ private const string FileUri = "file:";
+ private const string HttpUri = "http://";
+
+ private const string StrongNameDesc = "StrongName";
+ private const string UrlDesc = "Url";
+ private const string PathDesc = "Path";
+
+ private static volatile ClientConfigPaths s_current;
+ private static volatile bool s_currentIncludesUserConfig;
+
+ private readonly bool _includesUserConfig;
+ private string _companyName;
+
+ private ClientConfigPaths(string exePath, bool includeUserConfig)
+ {
+ _includesUserConfig = includeUserConfig;
+
+ Assembly exeAssembly = null;
+ string applicationUri;
+ string applicationFilename = null;
+
+ // get the assembly and applicationUri for the file
+ if (exePath == null)
+ {
+ // Now figure out the application path.
+ exeAssembly = Assembly.GetEntryAssembly();
+
+ if (exeAssembly == null)
+ throw new PlatformNotSupportedException();
+
+ HasEntryAssembly = true;
+ applicationUri = exeAssembly.CodeBase;
+
+ bool isFile = false;
+
+ if (StringUtil.StartsWithOrdinalIgnoreCase(applicationUri, FileUriLocal))
+ {
+ // If it is a local file URI, convert it to its filename, without invoking Uri class.
+ // example: "file:///C:/WINNT/Microsoft.NET/Framework/v2.0.x86fre/csc.exe"
+ isFile = true;
+ applicationUri = applicationUri.Substring(FileUriLocal.Length);
+ }
+ else
+ {
+ // If it is a UNC file URI, convert it to its filename, without invoking Uri class.
+ // example: "file://server/share/csc.exe"
+ if (StringUtil.StartsWithOrdinalIgnoreCase(applicationUri, FileUriUnc))
+ {
+ isFile = true;
+ applicationUri = applicationUri.Substring(FileUri.Length);
+ }
+ }
+
+ if (isFile)
+ {
+ applicationUri = applicationUri.Replace('/', '\\');
+ applicationFilename = applicationUri;
+ }
+ else
+ {
+ applicationUri = exeAssembly.EscapedCodeBase;
+ }
+ }
+ else
+ {
+ applicationUri = Path.GetFullPath(exePath);
+ if (!File.Exists(applicationUri))
+ {
+ throw ExceptionUtil.ParameterInvalid(nameof(exePath));
+ }
+
+ applicationFilename = applicationUri;
+ }
+
+ // Fallback if we haven't set the app config file path yet.
+ if (ApplicationConfigUri == null) ApplicationConfigUri = applicationUri + ConfigExtension;
+
+ // Set application path
+ ApplicationUri = applicationUri;
+
+ // In the case when exePath was explicitly supplied, we will not be able to
+ // construct user.config paths, so quit here.
+ if (exePath != null) return;
+
+ // Skip expensive initialization of user config file information if requested.
+ if (!_includesUserConfig) return;
+
+ bool isHttp = StringUtil.StartsWithOrdinalIgnoreCase(ApplicationConfigUri, HttpUri);
+ SetNamesAndVersion(applicationFilename, exeAssembly, isHttp);
+ if (isHttp) return;
+
+ string part1 = Validate(_companyName, limitSize: true);
+ string validAppDomainName = Validate(AppDomain.CurrentDomain.FriendlyName, limitSize: true);
+ string applicationUriLower = !string.IsNullOrEmpty(ApplicationUri)
+ ? ApplicationUri.ToLower(CultureInfo.InvariantCulture)
+ : null;
+ string namePrefix = !string.IsNullOrEmpty(validAppDomainName)
+ ? validAppDomainName
+ : Validate(ProductName, limitSize: true);
+ string hashSuffix = GetTypeAndHashSuffix(applicationUriLower);
+
+ string part2 = !string.IsNullOrEmpty(namePrefix) && !string.IsNullOrEmpty(hashSuffix)
+ ? namePrefix + hashSuffix
+ : null;
+
+ string part3 = Validate(ProductVersion, limitSize: false);
+
+ string dirSuffix = CombineIfValid(CombineIfValid(part1, part2), part3);
+
+ string roamingFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+ if (Path.IsPathRooted(roamingFolderPath))
+ {
+ RoamingConfigDirectory = CombineIfValid(roamingFolderPath, dirSuffix);
+ RoamingConfigFilename = CombineIfValid(RoamingConfigDirectory, UserConfigFilename);
+ }
+
+ string localFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ if (Path.IsPathRooted(localFolderPath))
+ {
+ LocalConfigDirectory = CombineIfValid(localFolderPath, dirSuffix);
+ LocalConfigFilename = CombineIfValid(LocalConfigDirectory, UserConfigFilename);
+ }
+ }
+
+ internal static ClientConfigPaths Current => GetPaths(null, true);
+
+ internal bool HasEntryAssembly { get; }
+
+ internal string ApplicationUri { get; }
+
+ internal string ApplicationConfigUri { get; }
+
+ internal string RoamingConfigFilename { get; }
+
+ internal string RoamingConfigDirectory { get; }
+
+ internal bool HasRoamingConfig => (RoamingConfigFilename != null) || !_includesUserConfig;
+
+ internal string LocalConfigFilename { get; }
+
+ internal string LocalConfigDirectory { get; }
+
+ internal bool HasLocalConfig => (LocalConfigFilename != null) || !_includesUserConfig;
+
+ internal string ProductName { get; private set; }
+
+ internal string ProductVersion { get; private set; }
+
+ internal static ClientConfigPaths GetPaths(string exePath, bool includeUserConfig)
+ {
+ ClientConfigPaths result;
+
+ if (exePath == null)
+ {
+ if ((s_current == null) || (includeUserConfig && !s_currentIncludesUserConfig))
+ {
+ s_current = new ClientConfigPaths(null, includeUserConfig);
+ s_currentIncludesUserConfig = includeUserConfig;
+ }
+
+ result = s_current;
+ }
+ else result = new ClientConfigPaths(exePath, includeUserConfig);
+
+ return result;
+ }
+
+ internal static void RefreshCurrent()
+ {
+ s_currentIncludesUserConfig = false;
+ s_current = null;
+ }
+
+ // Combines path2 with path1 if possible, else returns null.
+ private static string CombineIfValid(string path1, string path2)
+ {
+ if ((path1 == null) || (path2 == null)) return null;
+
+ try
+ {
+ return Path.Combine(path1, path2);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ // Returns a type and hash suffix based on what used to come from app domain evidence.
+ // The evidence we use, in priority order, is Strong Name, Url and Exe Path. If one of
+ // these is found, we compute a SHA1 hash of it and return a suffix based on that.
+ // If none is found, we return null.
+ private static string GetTypeAndHashSuffix(string exePath)
+ {
+ Assembly assembly = Assembly.GetEntryAssembly();
+
+ string suffix = null;
+ string typeName = null;
+ string hash = null;
+
+ if (assembly != null)
+ {
+ AssemblyName assemblyName = assembly.GetName();
+ Uri codeBase = new Uri(assembly.CodeBase);
+
+ hash = IdentityHelper.GetNormalizedStrongNameHash(assemblyName);
+ if (hash != null)
+ {
+ typeName = StrongNameDesc;
+ }
+ else
+ {
+ hash = IdentityHelper.GetNormalizedUriHash(codeBase);
+ typeName = UrlDesc;
+ }
+ }
+ else if (!string.IsNullOrEmpty(exePath))
+ {
+ // Fall back on the exe name
+ hash = IdentityHelper.GetStrongHashSuitableForObjectName(exePath);
+ typeName = PathDesc;
+ }
+
+ if (!string.IsNullOrEmpty(hash)) suffix = "_" + typeName + "_" + hash;
+ return suffix;
+ }
+
+ private void SetNamesAndVersion(string applicationFilename, Assembly exeAssembly, bool isHttp)
+ {
+ Type mainType = null;
+
+ // Get CompanyName, ProductName, and ProductVersion
+ // First try custom attributes on the assembly.
+ if (exeAssembly != null)
+ {
+ object[] attrs = exeAssembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
+ if ((attrs != null) && (attrs.Length > 0))
+ {
+ _companyName = ((AssemblyCompanyAttribute)attrs[0]).Company;
+ _companyName = _companyName?.Trim();
+ }
+
+ attrs = exeAssembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
+ if ((attrs != null) && (attrs.Length > 0))
+ {
+ ProductName = ((AssemblyProductAttribute)attrs[0]).Product;
+ ProductName = ProductName?.Trim();
+ }
+
+ ProductVersion = exeAssembly.GetName().Version.ToString();
+ ProductVersion = ProductVersion?.Trim();
+ }
+
+ // If we couldn't get custom attributes, fall back on the entry type namespace
+ if (!isHttp &&
+ (string.IsNullOrEmpty(_companyName) || string.IsNullOrEmpty(ProductName) ||
+ string.IsNullOrEmpty(ProductVersion)))
+ {
+ if (exeAssembly != null)
+ {
+ MethodInfo entryPoint = exeAssembly.EntryPoint;
+ if (entryPoint != null)
+ {
+ mainType = entryPoint.ReflectedType;
+ }
+ }
+
+ string ns = null;
+ if (mainType != null) ns = mainType.Namespace;
+
+ if (string.IsNullOrEmpty(ProductName))
+ {
+ // Try the remainder of the namespace
+ if (ns != null)
+ {
+ int lastDot = ns.LastIndexOf(".", StringComparison.Ordinal);
+ if ((lastDot != -1) && (lastDot < ns.Length - 1)) ProductName = ns.Substring(lastDot + 1);
+ else ProductName = ns;
+
+ ProductName = ProductName.Trim();
+ }
+
+ // Try the type of the entry assembly
+ if (string.IsNullOrEmpty(ProductName) && (mainType != null)) ProductName = mainType.Name.Trim();
+
+ // give up, return empty string
+ if (ProductName == null) ProductName = string.Empty;
+ }
+
+ if (string.IsNullOrEmpty(_companyName))
+ {
+ // Try the first part of the namespace
+ if (ns != null)
+ {
+ int firstDot = ns.IndexOf(".", StringComparison.Ordinal);
+ _companyName = firstDot != -1 ? ns.Substring(0, firstDot) : ns;
+
+ _companyName = _companyName.Trim();
+ }
+
+ // If that doesn't work, use the product name
+ if (string.IsNullOrEmpty(_companyName)) _companyName = ProductName;
+ }
+ }
+
+ // Desperate measures for product version - assume 1.0
+ if (string.IsNullOrEmpty(ProductVersion)) ProductVersion = "1.0.0.0";
+ }
+
+ // Makes the passed in string suitable to use as a path name by replacing illegal characters
+ // with underscores. Additionally, we do two things - replace spaces too with underscores and
+ // limit the resultant string's length to MaxLengthToUse if limitSize is true.
+ private static string Validate(string str, bool limitSize)
+ {
+ string validated = str;
+
+ if (string.IsNullOrEmpty(validated)) return validated;
+
+ // First replace all illegal characters with underscores
+ foreach (char c in Path.GetInvalidFileNameChars()) validated = validated.Replace(c, '_');
+
+ // Replace all spaces with underscores
+ validated = validated.Replace(' ', '_');
+
+ if (limitSize)
+ {
+ validated = validated.Length > MaxLengthToUse
+ ? validated.Substring(0, MaxLengthToUse)
+ : validated;
+ }
+
+ return validated;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ClientConfigurationHost.cs b/src/System.Configuration/src/System/Configuration/ClientConfigurationHost.cs
new file mode 100644
index 0000000000..8ffbbab580
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ClientConfigurationHost.cs
@@ -0,0 +1,492 @@
+// 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.Configuration.Internal;
+using System.Diagnostics;
+using System.IO;
+using System.Net;
+using System.Runtime.InteropServices;
+
+namespace System.Configuration
+{
+ internal sealed class ClientConfigurationHost : DelegatingConfigHost, IInternalConfigClientHost
+ {
+ internal const string MachineConfigName = "MACHINE";
+ internal const string ExeConfigName = "EXE";
+ internal const string RoamingUserConfigName = "ROAMING_USER";
+ internal const string LocalUserConfigName = "LOCAL_USER";
+
+ internal const string MachineConfigPath = MachineConfigName;
+ internal const string ExeConfigPath = MachineConfigPath + "/" + ExeConfigName;
+ internal const string RoamingUserConfigPath = ExeConfigPath + "/" + RoamingUserConfigName;
+ internal const string LocalUserConfigPath = RoamingUserConfigPath + "/" + LocalUserConfigName;
+
+ private const string MachineConfigFilename = "machine.config";
+ private const string MachineConfigSubdirectory = "Config";
+
+ private static readonly object s_version = new object();
+ private static volatile string s_machineConfigFilePath;
+ private ClientConfigPaths _configPaths; // physical paths to client config files
+
+ private string _exePath; // the physical path to the exe being configured
+ private ExeConfigurationFileMap _fileMap; // optional file map
+ private bool _initComplete;
+
+ internal ClientConfigurationHost()
+ {
+ Host = new InternalConfigHost();
+ }
+
+ internal ClientConfigPaths ConfigPaths => _configPaths ?? (_configPaths = ClientConfigPaths.GetPaths(_exePath, _initComplete));
+
+ internal static string MachineConfigFilePath
+ {
+ get
+ {
+ if (s_machineConfigFilePath == null)
+ {
+ string directory = RuntimeEnvironment.GetRuntimeDirectory();
+ s_machineConfigFilePath = Path.Combine(Path.Combine(directory, MachineConfigSubdirectory),
+ MachineConfigFilename);
+ }
+
+ return s_machineConfigFilePath;
+ }
+ }
+
+ public override bool HasRoamingConfig
+ {
+ get
+ {
+ if (_fileMap != null) return !string.IsNullOrEmpty(_fileMap.RoamingUserConfigFilename);
+ else return ConfigPaths.HasRoamingConfig;
+ }
+ }
+
+ public override bool HasLocalConfig
+ {
+ get
+ {
+ if (_fileMap != null) return !string.IsNullOrEmpty(_fileMap.LocalUserConfigFilename);
+ else return ConfigPaths.HasLocalConfig;
+ }
+ }
+
+ public override bool IsAppConfigHttp => !IsFile(GetStreamName(ExeConfigPath));
+
+ public override bool SupportsRefresh => true;
+
+ public override bool SupportsPath => false;
+
+ // Do we support location tags?
+ public override bool SupportsLocation => false;
+
+ bool IInternalConfigClientHost.IsExeConfig(string configPath)
+ {
+ return StringUtil.EqualsIgnoreCase(configPath, ExeConfigPath);
+ }
+
+ bool IInternalConfigClientHost.IsRoamingUserConfig(string configPath)
+ {
+ return StringUtil.EqualsIgnoreCase(configPath, RoamingUserConfigPath);
+ }
+
+ bool IInternalConfigClientHost.IsLocalUserConfig(string configPath)
+ {
+ return StringUtil.EqualsIgnoreCase(configPath, LocalUserConfigPath);
+ }
+
+ string IInternalConfigClientHost.GetExeConfigPath()
+ {
+ return ExeConfigPath;
+ }
+
+ string IInternalConfigClientHost.GetRoamingUserConfigPath()
+ {
+ return RoamingUserConfigPath;
+ }
+
+ string IInternalConfigClientHost.GetLocalUserConfigPath()
+ {
+ return LocalUserConfigPath;
+ }
+
+ public override void RefreshConfigPaths()
+ {
+ // Refresh current config paths.
+ if ((_configPaths != null) && !_configPaths.HasEntryAssembly && (_exePath == null))
+ {
+ ClientConfigPaths.RefreshCurrent();
+ _configPaths = null;
+ }
+ }
+
+ // Return true if the config path is for a user.config file, false otherwise.
+ private bool IsUserConfig(string configPath)
+ {
+ return StringUtil.EqualsIgnoreCase(configPath, RoamingUserConfigPath) ||
+ StringUtil.EqualsIgnoreCase(configPath, LocalUserConfigPath);
+ }
+
+ public override void Init(IInternalConfigRoot configRoot, params object[] hostInitParams)
+ {
+ try
+ {
+ ConfigurationFileMap fileMap = (ConfigurationFileMap)hostInitParams[0];
+ _exePath = (string)hostInitParams[1];
+
+ Host.Init(configRoot, hostInitParams);
+
+ // Do not complete initialization in runtime config, to avoid expense of
+ // loading user.config files that may not be required.
+ _initComplete = configRoot.IsDesignTime;
+
+ if ((fileMap != null) && !string.IsNullOrEmpty(_exePath))
+ throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::Init");
+
+ if (string.IsNullOrEmpty(_exePath)) _exePath = null;
+
+ // Initialize the fileMap, if provided.
+ if (fileMap != null)
+ {
+ _fileMap = new ExeConfigurationFileMap();
+ if (!string.IsNullOrEmpty(fileMap.MachineConfigFilename))
+ _fileMap.MachineConfigFilename = Path.GetFullPath(fileMap.MachineConfigFilename);
+
+ ExeConfigurationFileMap exeFileMap = fileMap as ExeConfigurationFileMap;
+ if (exeFileMap != null)
+ {
+ if (!string.IsNullOrEmpty(exeFileMap.ExeConfigFilename))
+ _fileMap.ExeConfigFilename = Path.GetFullPath(exeFileMap.ExeConfigFilename);
+
+ if (!string.IsNullOrEmpty(exeFileMap.RoamingUserConfigFilename))
+ _fileMap.RoamingUserConfigFilename = Path.GetFullPath(exeFileMap.RoamingUserConfigFilename);
+
+ if (!string.IsNullOrEmpty(exeFileMap.LocalUserConfigFilename))
+ _fileMap.LocalUserConfigFilename = Path.GetFullPath(exeFileMap.LocalUserConfigFilename);
+ }
+ }
+ }
+ catch
+ {
+ throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::Init");
+ }
+ }
+
+ public override void InitForConfiguration(ref string locationSubPath, out string configPath,
+ out string locationConfigPath,
+ IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams)
+ {
+ locationSubPath = null;
+ configPath = (string)hostInitConfigurationParams[2];
+ locationConfigPath = null;
+
+ Init(configRoot, hostInitConfigurationParams);
+ }
+
+ // Delay init if we have not been asked to complete init, and it is a user.config file.
+ public override bool IsInitDelayed(IInternalConfigRecord configRecord)
+ {
+ return !_initComplete && IsUserConfig(configRecord.ConfigPath);
+ }
+
+ public override void RequireCompleteInit(IInternalConfigRecord record)
+ {
+ // Loading information about user.config files is expensive,
+ // so do it just once by locking.
+ lock (this)
+ {
+ if (!_initComplete)
+ {
+ // Note that all future requests for config must be complete.
+ _initComplete = true;
+
+ // Throw out the ConfigPath for this exe.
+ ClientConfigPaths.RefreshCurrent();
+
+ // Throw out our cached copy.
+ _configPaths = null;
+
+ // Force loading of user.config file information under lock.
+ ClientConfigPaths configPaths = ConfigPaths;
+ }
+ }
+ }
+
+ public override bool IsConfigRecordRequired(string configPath)
+ {
+ string configName = ConfigPathUtility.GetName(configPath);
+ switch (configName)
+ {
+ case MachineConfigName:
+ case ExeConfigName:
+ return true;
+ case RoamingUserConfigName:
+ // Makes the design easier even if we only have an empty Roaming config record.
+ return HasRoamingConfig || HasLocalConfig;
+ case LocalUserConfigName:
+ return HasLocalConfig;
+ default:
+ // should never get here
+ Debug.Fail("unexpected config name: " + configName);
+ return false;
+ }
+ }
+
+ public override string GetStreamName(string configPath)
+ {
+ string configName = ConfigPathUtility.GetName(configPath);
+ switch (configName)
+ {
+ case MachineConfigName:
+ return _fileMap?.MachineConfigFilename ?? MachineConfigFilePath;
+ case ExeConfigName:
+ return _fileMap?.ExeConfigFilename ?? ConfigPaths.ApplicationConfigUri;
+ case RoamingUserConfigName:
+ return _fileMap?.RoamingUserConfigFilename ?? ConfigPaths.RoamingConfigFilename;
+ case LocalUserConfigName:
+ return _fileMap?.LocalUserConfigFilename ?? ConfigPaths.LocalConfigFilename;
+ default:
+ // should never get here
+ Debug.Fail("unexpected config name: " + configName);
+ goto case MachineConfigName;
+ }
+ }
+
+ public override string GetStreamNameForConfigSource(string streamName, string configSource)
+ {
+ if (IsFile(streamName))
+ return Host.GetStreamNameForConfigSource(streamName, configSource);
+
+ int index = streamName.LastIndexOf('/');
+ if (index < 0)
+ return null;
+
+ string parentUri = streamName.Substring(0, index + 1);
+ string result = parentUri + configSource.Replace('\\', '/');
+
+ return result;
+ }
+
+ public override object GetStreamVersion(string streamName)
+ {
+ return IsFile(streamName) ? Host.GetStreamVersion(streamName) : s_version;
+ }
+
+ // default impl treats name as a file name
+ // null means stream doesn't exist for this name
+ public override Stream OpenStreamForRead(string streamName)
+ {
+ // the streamName can either be a file name, or a URI
+ if (IsFile(streamName)) return Host.OpenStreamForRead(streamName);
+
+ if (streamName == null) return null;
+
+ // scheme is http
+ WebClient client = new WebClient();
+
+ // Try using default credentials
+ try
+ {
+ client.Credentials = CredentialCache.DefaultCredentials;
+ }
+ catch { }
+
+ byte[] fileData = null;
+ try
+ {
+ fileData = client.DownloadData(streamName);
+ }
+ catch { }
+
+ if (fileData == null) return null;
+
+ MemoryStream stream = new MemoryStream(fileData);
+ return stream;
+ }
+
+ public override Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext)
+ {
+ // only support files, not URIs
+ if (!IsFile(streamName)) throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::OpenStreamForWrite");
+
+ return Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext);
+ }
+
+ public override void DeleteStream(string streamName)
+ {
+ // only support files, not URIs
+ if (!IsFile(streamName)) throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::Delete");
+
+ Host.DeleteStream(streamName);
+ }
+
+ public override bool IsDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition)
+ {
+ string allowedConfigPath;
+
+ switch (allowExeDefinition)
+ {
+ case ConfigurationAllowExeDefinition.MachineOnly:
+ allowedConfigPath = MachineConfigPath;
+ break;
+ case ConfigurationAllowExeDefinition.MachineToApplication:
+ allowedConfigPath = ExeConfigPath;
+ break;
+ case ConfigurationAllowExeDefinition.MachineToRoamingUser:
+ allowedConfigPath = RoamingUserConfigPath;
+ break;
+ // MachineToLocalUser does not current have any definition restrictions
+ case ConfigurationAllowExeDefinition.MachineToLocalUser:
+ return true;
+ default:
+ // If we have extended ConfigurationAllowExeDefinition
+ // make sure to update this switch accordingly
+ throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::IsDefinitionAllowed");
+ }
+
+ return configPath.Length <= allowedConfigPath.Length;
+ }
+
+ public override void VerifyDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition, IConfigErrorInfo errorInfo)
+ {
+ if (!IsDefinitionAllowed(configPath, allowDefinition, allowExeDefinition))
+ {
+ switch (allowExeDefinition)
+ {
+ case ConfigurationAllowExeDefinition.MachineOnly:
+ throw new ConfigurationErrorsException(
+ SR.Config_allow_exedefinition_error_machine, errorInfo);
+ case ConfigurationAllowExeDefinition.MachineToApplication:
+ throw new ConfigurationErrorsException(
+ SR.Config_allow_exedefinition_error_application, errorInfo);
+ case ConfigurationAllowExeDefinition.MachineToRoamingUser:
+ throw new ConfigurationErrorsException(
+ SR.Config_allow_exedefinition_error_roaminguser, errorInfo);
+ default:
+ // If we have extended ConfigurationAllowExeDefinition
+ // make sure to update this switch accordingly
+ throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::VerifyDefinitionAllowed");
+ }
+ }
+ }
+
+ // prefetch support
+ public override bool PrefetchAll(string configPath, string streamName)
+ {
+ // If it's a file, we don't need to. Otherwise (e.g. it's from the web), we'll prefetch everything.
+ return !IsFile(streamName);
+ }
+
+ public override bool PrefetchSection(string sectionGroupName, string sectionName)
+ {
+ return sectionGroupName == "system.net";
+ }
+
+ public override object CreateDeprecatedConfigContext(string configPath)
+ {
+ return null;
+ }
+
+ public override object
+ CreateConfigurationContext(string configPath,
+ string locationSubPath)
+ {
+ return new ExeContext(GetUserLevel(configPath), ConfigPaths.ApplicationUri);
+ }
+
+ private ConfigurationUserLevel GetUserLevel(string configPath)
+ {
+ ConfigurationUserLevel level;
+
+ switch (ConfigPathUtility.GetName(configPath))
+ {
+ case MachineConfigName:
+ level = ConfigurationUserLevel.None;
+ break;
+ case ExeConfigName:
+ level = ConfigurationUserLevel.None;
+ break;
+ case LocalUserConfigName:
+ level = ConfigurationUserLevel.PerUserRoamingAndLocal;
+ break;
+ case RoamingUserConfigName:
+ level = ConfigurationUserLevel.PerUserRoaming;
+ break;
+ default:
+ Debug.Fail("unrecognized configPath " + configPath);
+ level = ConfigurationUserLevel.None;
+ break;
+ }
+
+ return level;
+ }
+
+ internal static Configuration OpenExeConfiguration(ConfigurationFileMap fileMap, bool isMachine,
+ ConfigurationUserLevel userLevel, string exePath)
+ {
+ // validate userLevel argument
+ switch (userLevel)
+ {
+ case ConfigurationUserLevel.None:
+ case ConfigurationUserLevel.PerUserRoaming:
+ case ConfigurationUserLevel.PerUserRoamingAndLocal:
+ break;
+ default:
+ throw ExceptionUtil.ParameterInvalid(nameof(userLevel));
+ }
+
+ // validate fileMap arguments
+ if (fileMap != null)
+ {
+ if (string.IsNullOrEmpty(fileMap.MachineConfigFilename))
+ throw ExceptionUtil.ParameterNullOrEmpty("fileMap.MachineConfigFilename");
+
+ ExeConfigurationFileMap exeFileMap = fileMap as ExeConfigurationFileMap;
+ if (exeFileMap != null)
+ {
+ switch (userLevel)
+ {
+ case ConfigurationUserLevel.None:
+ if (string.IsNullOrEmpty(exeFileMap.ExeConfigFilename))
+ throw ExceptionUtil.ParameterNullOrEmpty("fileMap.ExeConfigFilename");
+ break;
+ case ConfigurationUserLevel.PerUserRoaming:
+ if (string.IsNullOrEmpty(exeFileMap.RoamingUserConfigFilename))
+ throw ExceptionUtil.ParameterNullOrEmpty("fileMap.RoamingUserConfigFilename");
+ goto case ConfigurationUserLevel.None;
+ case ConfigurationUserLevel.PerUserRoamingAndLocal:
+ if (string.IsNullOrEmpty(exeFileMap.LocalUserConfigFilename))
+ throw ExceptionUtil.ParameterNullOrEmpty("fileMap.LocalUserConfigFilename");
+ goto case ConfigurationUserLevel.PerUserRoaming;
+ }
+ }
+ }
+
+ string configPath = null;
+ if (isMachine) configPath = MachineConfigPath;
+ else
+ {
+ switch (userLevel)
+ {
+ case ConfigurationUserLevel.None:
+ configPath = ExeConfigPath;
+ break;
+ case ConfigurationUserLevel.PerUserRoaming:
+ configPath = RoamingUserConfigPath;
+ break;
+ case ConfigurationUserLevel.PerUserRoamingAndLocal:
+ configPath = LocalUserConfigPath;
+ break;
+ }
+ }
+
+ Configuration configuration = new Configuration(null, typeof(ClientConfigurationHost), fileMap, exePath, configPath);
+
+ return configuration;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ClientConfigurationSystem.cs b/src/System.Configuration/src/System/Configuration/ClientConfigurationSystem.cs
new file mode 100644
index 0000000000..0a7daae689
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ClientConfigurationSystem.cs
@@ -0,0 +1,225 @@
+// 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.Configuration.Internal;
+using System.Threading;
+
+namespace System.Configuration
+{
+ internal sealed class ClientConfigurationSystem : IInternalConfigSystem
+ {
+ private const string SystemDiagnosticsConfigKey = "system.diagnostics";
+ private const string SystemNetGroupKey = "system.net/";
+ private readonly IInternalConfigHost _configHost;
+ private readonly IInternalConfigRoot _configRoot;
+ private readonly bool _isAppConfigHttp;
+ private IInternalConfigRecord _completeConfigRecord;
+
+ private Exception _initError;
+ private bool _isInitInProgress;
+ private bool _isMachineConfigInited;
+ private bool _isUserConfigInited;
+ private IInternalConfigRecord _machineConfigRecord;
+
+ internal ClientConfigurationSystem()
+ {
+ IConfigSystem configSystem = new ConfigSystem();
+ configSystem.Init(typeof(ClientConfigurationHost), null, null);
+
+ _configHost = configSystem.Host;
+ _configRoot = configSystem.Root;
+
+ _configRoot.ConfigRemoved += OnConfigRemoved;
+
+ _isAppConfigHttp = ((IInternalConfigHostPaths)_configHost).IsAppConfigHttp;
+ }
+
+ object IInternalConfigSystem.GetSection(string sectionName)
+ {
+ PrepareClientConfigSystem(sectionName);
+
+ // Get the appropriate config record for the section.
+ IInternalConfigRecord configRecord = null;
+ if (DoesSectionOnlyUseMachineConfig(sectionName))
+ {
+ if (_isMachineConfigInited) configRecord = _machineConfigRecord;
+ }
+ else
+ {
+ if (_isUserConfigInited) configRecord = _completeConfigRecord;
+ }
+
+ // Call GetSection(), or return null if no configuration is yet available.
+ return configRecord?.GetSection(sectionName);
+ }
+
+ void IInternalConfigSystem.RefreshConfig(string sectionName)
+ {
+ PrepareClientConfigSystem(sectionName);
+
+ if (_isMachineConfigInited) _machineConfigRecord.RefreshSection(sectionName);
+ }
+
+ // Supports user config
+ bool IInternalConfigSystem.SupportsUserConfig => true;
+
+ // Return true if the section might be used during initialization of the configuration system,
+ // and thus lead to deadlock if appropriate measures are not taken.
+ private bool IsSectionUsedInInit(string configKey)
+ {
+ return (configKey == SystemDiagnosticsConfigKey) ||
+ (_isAppConfigHttp && configKey.StartsWith(SystemNetGroupKey, StringComparison.Ordinal));
+ }
+
+ // Return true if the section should only use the machine configuration and not use the
+ // application configuration. This is only true for system.net sections when the configuration
+ // file for the application is downloaded via http using System.Net.WebClient.
+ private bool DoesSectionOnlyUseMachineConfig(string configKey)
+ {
+ return _isAppConfigHttp && configKey.StartsWith(SystemNetGroupKey, StringComparison.Ordinal);
+ }
+
+ // Ensure that initialization has completed, while handling re-entrancy issues
+ // for certain sections that may be used during initialization itself.
+ private void EnsureInit(string configKey)
+ {
+ bool doInit = false;
+
+ lock (this)
+ {
+ // If the user config is not initialized, then we must either:
+ // a. Perform the initialization ourselves if no other thread is doing it, or
+ // b. Wait for the initialization to complete if we know the section is not used during initialization itself, or
+ // c. Ignore initialization if the section can be used during initialization. Note that GetSection()
+ // returns null is initialization has not completed.
+ if (!_isUserConfigInited)
+ {
+ if (!_isInitInProgress)
+ {
+ _isInitInProgress = true;
+ doInit = true;
+ }
+ else
+ {
+ if (!IsSectionUsedInInit(configKey))
+ {
+ // Wait for initialization to complete.
+ Monitor.Wait(this);
+ }
+ }
+ }
+ }
+
+ if (!doInit) return;
+ try
+ {
+ try
+ {
+ // Initialize machine configuration.
+ _machineConfigRecord = _configRoot.GetConfigRecord(
+ ClientConfigurationHost.MachineConfigPath);
+
+ _machineConfigRecord.ThrowIfInitErrors();
+
+ // Make machine configuration available to system.net sections
+ // when application configuration is downloaded via http.
+ _isMachineConfigInited = true;
+
+ // If we add System.Net.Configuration we'll need to kick the initialization here
+ // to prevent deadlocks in the networking classes by loading networking config
+ // before making any networking requests.
+ //
+ // Any requests for sections used in initialization during the call to
+ // EnsureConfigLoaded() will be served by _machine.config or will return null.
+
+ //if (_isAppConfigHttp)
+ //{
+ //}
+
+ // Now load the rest of configuration
+ var configHostPaths = (IInternalConfigHostPaths)_configHost;
+ configHostPaths.RefreshConfigPaths();
+
+ string configPath;
+ if (configHostPaths.HasLocalConfig)
+ {
+ configPath = ClientConfigurationHost.LocalUserConfigPath;
+ }
+ else
+ {
+ configPath = configHostPaths.HasRoamingConfig
+ ? ClientConfigurationHost.RoamingUserConfigPath
+ : ClientConfigurationHost.ExeConfigPath;
+ }
+
+ _completeConfigRecord = _configRoot.GetConfigRecord(configPath);
+ _completeConfigRecord.ThrowIfInitErrors();
+
+ _isUserConfigInited = true;
+ }
+ catch (Exception e)
+ {
+ _initError =
+ new ConfigurationErrorsException(SR.Config_client_config_init_error, e);
+ throw _initError;
+ }
+ }
+ catch
+ {
+ ConfigurationManager.SetInitError(_initError);
+ _isMachineConfigInited = true;
+ _isUserConfigInited = true;
+ throw;
+ }
+ finally
+ {
+ lock (this)
+ {
+ try
+ {
+ // Notify ConfigurationSettings that initialization has fully completed,
+ // even if unsuccessful.
+ ConfigurationManager.CompleteConfigInit();
+
+ _isInitInProgress = false;
+ }
+ finally
+ {
+ // Wake up all threads waiting for initialization to complete.
+ Monitor.PulseAll(this);
+ }
+ }
+ }
+ }
+
+ private void PrepareClientConfigSystem(string sectionName)
+ {
+ // Ensure the configuration system is inited for this section.
+ if (!_isUserConfigInited) EnsureInit(sectionName);
+
+ // If an error occurred during initialzation, throw it.
+ if (_initError != null) throw _initError;
+ }
+
+ // If config has been removed because initialization was not complete,
+ // fetch a new configuration record. The record will be created and
+ // completely initialized as RequireCompleteInit() will have been called
+ // on the ClientConfigurationHost before we receive this event.
+ private void OnConfigRemoved(object sender, InternalConfigEventArgs e)
+ {
+ try
+ {
+ IInternalConfigRecord newConfigRecord = _configRoot.GetConfigRecord(_completeConfigRecord.ConfigPath);
+ _completeConfigRecord = newConfigRecord;
+ _completeConfigRecord.ThrowIfInitErrors();
+ }
+ catch (Exception ex)
+ {
+ _initError = new ConfigurationErrorsException(SR.Config_client_config_init_error, ex);
+ ConfigurationManager.SetInitError(_initError);
+ throw _initError;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/CommaDelimitedStringAttributeCollectionConverter.cs b/src/System.Configuration/src/System/Configuration/CommaDelimitedStringAttributeCollectionConverter.cs
new file mode 100644
index 0000000000..90a776c76c
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/CommaDelimitedStringAttributeCollectionConverter.cs
@@ -0,0 +1,26 @@
+// 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.Globalization;
+using System.ComponentModel;
+
+namespace System.Configuration
+{
+ public sealed class CommaDelimitedStringCollectionConverter : ConfigurationConverterBase
+ {
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ ValidateType(value, typeof(CommaDelimitedStringCollection));
+ CommaDelimitedStringCollection internalValue = value as CommaDelimitedStringCollection;
+ return internalValue?.ToString();
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ CommaDelimitedStringCollection attributeCollection = new CommaDelimitedStringCollection();
+ attributeCollection.FromString((string)data);
+ return attributeCollection;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigDefinitionUpdates.cs b/src/System.Configuration/src/System/Configuration/ConfigDefinitionUpdates.cs
new file mode 100644
index 0000000000..8119e0d0f5
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigDefinitionUpdates.cs
@@ -0,0 +1,60 @@
+// 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.Configuration
+{
+ using Collections;
+
+ // Contains all the updates to section definitions across all location sections.
+ internal class ConfigDefinitionUpdates
+ {
+ internal ConfigDefinitionUpdates()
+ {
+ LocationUpdatesList = new ArrayList();
+ }
+
+ internal ArrayList LocationUpdatesList { get; }
+
+ internal bool RequireLocation { get; set; }
+
+ // Find the location update with a certain set of location attributes.
+ internal LocationUpdates FindLocationUpdates(OverrideModeSetting overrideMode, bool inheritInChildApps)
+ {
+ foreach (LocationUpdates locationUpdates in LocationUpdatesList)
+ if (OverrideModeSetting.CanUseSameLocationTag(locationUpdates.OverrideMode, overrideMode) &&
+ (locationUpdates.InheritInChildApps == inheritInChildApps))
+ return locationUpdates;
+
+ return null;
+ }
+
+ // Add a section definition update to the correct location update.
+ internal DefinitionUpdate AddUpdate(OverrideModeSetting overrideMode, bool inheritInChildApps, bool moved,
+ string updatedXml, SectionRecord sectionRecord)
+ {
+ LocationUpdates locationUpdates = FindLocationUpdates(overrideMode, inheritInChildApps);
+ if (locationUpdates == null)
+ {
+ locationUpdates = new LocationUpdates(overrideMode, inheritInChildApps);
+ LocationUpdatesList.Add(locationUpdates);
+ }
+
+ DefinitionUpdate definitionUpdate = new DefinitionUpdate(sectionRecord.ConfigKey, moved, updatedXml,
+ sectionRecord);
+ locationUpdates.SectionUpdates.AddSection(definitionUpdate);
+ return definitionUpdate;
+ }
+
+ // Determine which section definition updates are new.
+ internal void CompleteUpdates()
+ {
+ foreach (LocationUpdates locationUpdates in LocationUpdatesList) locationUpdates.CompleteUpdates();
+ }
+
+ internal void FlagLocationWritten()
+ {
+ RequireLocation = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigPathUtility.cs b/src/System.Configuration/src/System/Configuration/ConfigPathUtility.cs
new file mode 100644
index 0000000000..29b6470d2a
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigPathUtility.cs
@@ -0,0 +1,101 @@
+// 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;
+
+namespace System.Configuration
+{
+ internal static class ConfigPathUtility
+ {
+ private const char SeparatorChar = '/';
+
+ // A configPath is valid if
+ // * It does not start or end with a '/'
+ // * It is not null or empty, except in the case of the root configuration record
+ // * It does not contain '\'
+ // * It does not contain a path component equal to "." or ".."
+ //
+ // The checks for '\', ".", and ".." are not strictly necessary, but their presence
+ // could lead to problems for configuration hosts.
+ internal static bool IsValid(string configPath)
+ {
+ if (string.IsNullOrEmpty(configPath))
+ return false;
+
+ int start = -1;
+ for (int examine = 0; examine <= configPath.Length; examine++)
+ {
+ char ch;
+
+ ch = examine < configPath.Length ? configPath[examine] : SeparatorChar;
+
+ // backslash disallowed
+ if (ch == '\\')
+ return false;
+
+ if (ch == SeparatorChar)
+ {
+ // double slash disallowed
+ // note this check also purposefully catches starting and ending slash
+ if (examine == start + 1)
+ return false;
+
+ // "." disallowed
+ if ((examine == start + 2) && (configPath[start + 1] == '.'))
+ return false;
+
+ // ".." disallowed
+ if ((examine == start + 3) && (configPath[start + 1] == '.') && (configPath[start + 2] == '.'))
+ return false;
+
+ start = examine;
+ }
+ }
+
+ return true;
+ }
+
+ internal static string Combine(string parentConfigPath, string childConfigPath)
+ {
+ Debug.Assert(string.IsNullOrEmpty(parentConfigPath) || IsValid(parentConfigPath),
+ "String.IsNullOrEmpty(parentConfigPath) || IsValid(parentConfigPath)");
+ Debug.Assert(string.IsNullOrEmpty(childConfigPath) || IsValid(childConfigPath),
+ "String.IsNullOrEmpty(childConfigPath) || IsValid(childConfigPath)");
+
+ if (string.IsNullOrEmpty(parentConfigPath))
+ return childConfigPath;
+
+ if (string.IsNullOrEmpty(childConfigPath))
+ return parentConfigPath;
+
+ return parentConfigPath + SeparatorChar + childConfigPath;
+ }
+
+ internal static string[] GetParts(string configPath)
+ {
+ Debug.Assert(IsValid(configPath), "IsValid(configPath)");
+
+ string[] parts = configPath.Split(SeparatorChar);
+ return parts;
+ }
+
+ // Return the last part of a config path, e.g.
+ // GetName("MACHINE/WEBROOT/Default Web Site/app") == "app"
+ internal static string GetName(string configPath)
+ {
+ Debug.Assert(string.IsNullOrEmpty(configPath) || IsValid(configPath),
+ "String.IsNullOrEmpty(configPath) || IsValid(configPath)");
+
+ if (string.IsNullOrEmpty(configPath))
+ return configPath;
+
+ int index = configPath.LastIndexOf(SeparatorChar);
+ if (index == -1)
+ return configPath;
+
+ Debug.Assert(index != configPath.Length - 1);
+ return configPath.Substring(index + 1);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigXmlAttribute.cs b/src/System.Configuration/src/System/Configuration/ConfigXmlAttribute.cs
new file mode 100644
index 0000000000..2af7993c33
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigXmlAttribute.cs
@@ -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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class ConfigXmlAttribute : XmlAttribute, IConfigErrorInfo
+ {
+ private string _filename;
+ private int _line;
+
+ public ConfigXmlAttribute(string filename, int line, string prefix, string localName, string namespaceUri,
+ XmlDocument doc)
+ : base(prefix, localName, namespaceUri, doc)
+ {
+ _line = line;
+ _filename = filename;
+ }
+
+ int IConfigErrorInfo.LineNumber => _line;
+
+ string IConfigErrorInfo.Filename => _filename;
+
+ public override XmlNode CloneNode(bool deep)
+ {
+ XmlNode cloneNode = base.CloneNode(deep);
+ ConfigXmlAttribute clone = cloneNode as ConfigXmlAttribute;
+ if (clone != null)
+ {
+ clone._line = _line;
+ clone._filename = _filename;
+ }
+ return cloneNode;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigXmlCDataSection.cs b/src/System.Configuration/src/System/Configuration/ConfigXmlCDataSection.cs
new file mode 100644
index 0000000000..f7e6a05484
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigXmlCDataSection.cs
@@ -0,0 +1,38 @@
+// 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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class ConfigXmlCDataSection : XmlCDataSection, IConfigErrorInfo
+ {
+ private string _filename;
+ private int _line;
+
+ public ConfigXmlCDataSection(string filename, int line, string data, XmlDocument doc)
+ : base(data, doc)
+ {
+ _line = line;
+ _filename = filename;
+ }
+
+ int IConfigErrorInfo.LineNumber => _line;
+
+ string IConfigErrorInfo.Filename => _filename;
+
+ public override XmlNode CloneNode(bool deep)
+ {
+ XmlNode cloneNode = base.CloneNode(deep);
+ ConfigXmlCDataSection clone = cloneNode as ConfigXmlCDataSection;
+ if (clone != null)
+ {
+ clone._line = _line;
+ clone._filename = _filename;
+ }
+ return cloneNode;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigXmlComment.cs b/src/System.Configuration/src/System/Configuration/ConfigXmlComment.cs
new file mode 100644
index 0000000000..8090fc54da
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigXmlComment.cs
@@ -0,0 +1,38 @@
+// 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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class ConfigXmlComment : XmlComment, IConfigErrorInfo
+ {
+ private string _filename;
+ private int _line;
+
+ public ConfigXmlComment(string filename, int line, string comment, XmlDocument doc)
+ : base(comment, doc)
+ {
+ _line = line;
+ _filename = filename;
+ }
+
+ int IConfigErrorInfo.LineNumber => _line;
+
+ string IConfigErrorInfo.Filename => _filename;
+
+ public override XmlNode CloneNode(bool deep)
+ {
+ XmlNode cloneNode = base.CloneNode(deep);
+ ConfigXmlComment clone = cloneNode as ConfigXmlComment;
+ if (clone != null)
+ {
+ clone._line = _line;
+ clone._filename = _filename;
+ }
+ return cloneNode;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigXmlElement.cs b/src/System.Configuration/src/System/Configuration/ConfigXmlElement.cs
new file mode 100644
index 0000000000..7faed3bb89
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigXmlElement.cs
@@ -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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class ConfigXmlElement : XmlElement, IConfigErrorInfo
+ {
+ private string _filename;
+ private int _line;
+
+ public ConfigXmlElement(string filename, int line, string prefix, string localName, string namespaceUri,
+ XmlDocument doc)
+ : base(prefix, localName, namespaceUri, doc)
+ {
+ _line = line;
+ _filename = filename;
+ }
+
+ int IConfigErrorInfo.LineNumber => _line;
+
+ string IConfigErrorInfo.Filename => _filename;
+
+ public override XmlNode CloneNode(bool deep)
+ {
+ XmlNode cloneNode = base.CloneNode(deep);
+ ConfigXmlElement clone = cloneNode as ConfigXmlElement;
+ if (clone != null)
+ {
+ clone._line = _line;
+ clone._filename = _filename;
+ }
+ return cloneNode;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigXmlReader.cs b/src/System.Configuration/src/System/Configuration/ConfigXmlReader.cs
new file mode 100644
index 0000000000..8dcc205109
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigXmlReader.cs
@@ -0,0 +1,56 @@
+// 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.Configuration.Internal;
+using System.Diagnostics;
+using System.IO;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class ConfigXmlReader : XmlTextReader, IConfigErrorInfo
+ {
+ private readonly string _filename;
+
+ // Used in a decrypted configuration section to locate
+ // the line where the ecnrypted section begins.
+ private readonly bool _lineNumberIsConstant;
+ private readonly int _lineOffset;
+
+ internal ConfigXmlReader(string rawXml, string filename, int lineOffset) :
+ this(rawXml, filename, lineOffset, false)
+ { }
+
+ internal ConfigXmlReader(string rawXml, string filename, int lineOffset, bool lineNumberIsConstant) :
+ base(new StringReader(rawXml))
+ {
+ RawXml = rawXml;
+ _filename = filename;
+ _lineOffset = lineOffset;
+ _lineNumberIsConstant = lineNumberIsConstant;
+
+ Debug.Assert(!_lineNumberIsConstant || (_lineOffset > 0),
+ "!_lineNumberIsConstant || _lineOffset > 0");
+ }
+
+ internal string RawXml { get; }
+
+ int IConfigErrorInfo.LineNumber
+ {
+ get
+ {
+ if (_lineNumberIsConstant) return _lineOffset;
+ if (_lineOffset > 0) return LineNumber + (_lineOffset - 1);
+ return LineNumber;
+ }
+ }
+
+ string IConfigErrorInfo.Filename => _filename;
+
+ internal ConfigXmlReader Clone()
+ {
+ return new ConfigXmlReader(RawXml, _filename, _lineOffset, _lineNumberIsConstant);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigXmlSignificantWhitespace.cs b/src/System.Configuration/src/System/Configuration/ConfigXmlSignificantWhitespace.cs
new file mode 100644
index 0000000000..ba5a3f9a3e
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigXmlSignificantWhitespace.cs
@@ -0,0 +1,38 @@
+// 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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class ConfigXmlSignificantWhitespace : XmlSignificantWhitespace, IConfigErrorInfo
+ {
+ private string _filename;
+ private int _line;
+
+ public ConfigXmlSignificantWhitespace(string filename, int line, string strData, XmlDocument doc)
+ : base(strData, doc)
+ {
+ _line = line;
+ _filename = filename;
+ }
+
+ int IConfigErrorInfo.LineNumber => _line;
+
+ string IConfigErrorInfo.Filename => _filename;
+
+ public override XmlNode CloneNode(bool deep)
+ {
+ XmlNode cloneNode = base.CloneNode(deep);
+ ConfigXmlSignificantWhitespace clone = cloneNode as ConfigXmlSignificantWhitespace;
+ if (clone != null)
+ {
+ clone._line = _line;
+ clone._filename = _filename;
+ }
+ return cloneNode;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigXmlText.cs b/src/System.Configuration/src/System/Configuration/ConfigXmlText.cs
new file mode 100644
index 0000000000..d7130ebf1a
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigXmlText.cs
@@ -0,0 +1,38 @@
+// 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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class ConfigXmlText : XmlText, IConfigErrorInfo
+ {
+ private string _filename;
+ private int _line;
+
+ public ConfigXmlText(string filename, int line, string strData, XmlDocument doc)
+ : base(strData, doc)
+ {
+ _line = line;
+ _filename = filename;
+ }
+
+ int IConfigErrorInfo.LineNumber => _line;
+
+ string IConfigErrorInfo.Filename => _filename;
+
+ public override XmlNode CloneNode(bool deep)
+ {
+ XmlNode cloneNode = base.CloneNode(deep);
+ ConfigXmlText clone = cloneNode as ConfigXmlText;
+ if (clone != null)
+ {
+ clone._line = _line;
+ clone._filename = _filename;
+ }
+ return cloneNode;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigXmlWhitespace.cs b/src/System.Configuration/src/System/Configuration/ConfigXmlWhitespace.cs
new file mode 100644
index 0000000000..1d1b30a2f1
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigXmlWhitespace.cs
@@ -0,0 +1,38 @@
+// 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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class ConfigXmlWhitespace : XmlWhitespace, IConfigErrorInfo
+ {
+ private string _filename;
+ private int _line;
+
+ public ConfigXmlWhitespace(string filename, int line, string comment, XmlDocument doc)
+ : base(comment, doc)
+ {
+ _line = line;
+ _filename = filename;
+ }
+
+ int IConfigErrorInfo.LineNumber => _line;
+
+ string IConfigErrorInfo.Filename => _filename;
+
+ public override XmlNode CloneNode(bool deep)
+ {
+ XmlNode cloneNode = base.CloneNode(deep);
+ ConfigXmlWhitespace clone = cloneNode as ConfigXmlWhitespace;
+ if (clone != null)
+ {
+ clone._line = _line;
+ clone._filename = _filename;
+ }
+ return cloneNode;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Configuration.cs b/src/System.Configuration/src/System/Configuration/Configuration.cs
new file mode 100644
index 0000000000..9845e1beb2
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Configuration.cs
@@ -0,0 +1,233 @@
+// 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.Configuration.Internal;
+using System.IO;
+using System.Runtime.Versioning;
+
+namespace System.Configuration
+{
+ // An instance of the Configuration class represents a single level
+ // in the configuration hierarchy. Its contents can be edited and
+ // saved to disk.
+ //
+ // It is not thread safe for writing.
+ public sealed class Configuration
+ {
+ private readonly MgmtConfigurationRecord _configRecord;
+ private readonly object[] _hostInitConfigurationParams;
+ private readonly Type _typeConfigHost;
+ private Func<string, string> _assemblyStringTransformer;
+ private ContextInformation _evalContext;
+ private ConfigurationLocationCollection _locations;
+ private ConfigurationSectionGroup _rootSectionGroup;
+ private Stack _sectionsStack;
+ private Func<string, string> _typeStringTransformer;
+
+ internal Configuration(string locationSubPath, Type typeConfigHost, params object[] hostInitConfigurationParams)
+ {
+ _typeConfigHost = typeConfigHost;
+ _hostInitConfigurationParams = hostInitConfigurationParams;
+
+ IInternalConfigHost configHost = (IInternalConfigHost)TypeUtil.CreateInstance(typeConfigHost);
+
+ // Wrap the host with the UpdateConfigHost to support SaveAs.
+ UpdateConfigHost updateConfigHost = new UpdateConfigHost(configHost);
+
+ // Now wrap in ImplicitMachineConfigHost so we can stub in a simple machine.config if needed.
+ IInternalConfigHost implicitMachineConfigHost = new ImplicitMachineConfigHost(updateConfigHost);
+
+ InternalConfigRoot configRoot = new InternalConfigRoot(this, updateConfigHost);
+ ((IInternalConfigRoot)configRoot).Init(implicitMachineConfigHost, isDesignTime: true);
+
+ // Set the configuration paths for this Configuration.
+ //
+ // We do this in a separate step so that the WebConfigurationHost
+ // can use this object's _configRoot to get the <sites> section,
+ // which is used in it's MapPath implementation.
+ string configPath, locationConfigPath;
+ implicitMachineConfigHost.InitForConfiguration(
+ ref locationSubPath,
+ out configPath,
+ out locationConfigPath,
+ configRoot,
+ hostInitConfigurationParams);
+
+ if (!string.IsNullOrEmpty(locationSubPath) && !implicitMachineConfigHost.SupportsLocation)
+ throw ExceptionUtil.UnexpectedError("Configuration::ctor");
+
+ if (string.IsNullOrEmpty(locationSubPath) != string.IsNullOrEmpty(locationConfigPath))
+ throw ExceptionUtil.UnexpectedError("Configuration::ctor");
+
+ // Get the configuration record for this config file.
+ _configRecord = (MgmtConfigurationRecord)configRoot.GetConfigRecord(configPath);
+
+ // Create another MgmtConfigurationRecord for the location that is a child of the above record.
+ // Note that this does not match the resolution hiearchy that is used at runtime.
+ if (!string.IsNullOrEmpty(locationSubPath))
+ {
+ _configRecord = MgmtConfigurationRecord.Create(
+ configRoot, _configRecord, locationConfigPath, locationSubPath);
+ }
+
+ // Throw if the config record we created contains global errors.
+ _configRecord.ThrowIfInitErrors();
+ }
+
+ public AppSettingsSection AppSettings => (AppSettingsSection)GetSection("appSettings");
+
+ public ConnectionStringsSection ConnectionStrings => (ConnectionStringsSection)GetSection("connectionStrings");
+
+ public string FilePath => _configRecord.ConfigurationFilePath;
+
+ public bool HasFile => _configRecord.HasStream;
+
+ public ConfigurationLocationCollection Locations
+ => _locations ?? (_locations = _configRecord.GetLocationCollection(this));
+
+ public ContextInformation EvaluationContext
+ => _evalContext ?? (_evalContext = new ContextInformation(_configRecord));
+
+ public ConfigurationSectionGroup RootSectionGroup
+ {
+ get
+ {
+ if (_rootSectionGroup == null)
+ {
+ _rootSectionGroup = new ConfigurationSectionGroup();
+ _rootSectionGroup.RootAttachToConfigurationRecord(_configRecord);
+ }
+
+ return _rootSectionGroup;
+ }
+ }
+
+ public ConfigurationSectionCollection Sections => RootSectionGroup.Sections;
+
+ public ConfigurationSectionGroupCollection SectionGroups => RootSectionGroup.SectionGroups;
+
+ // Is the namespace declared in the file or not?
+ //
+ // ie. xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"
+ // (currently this is the only one we allow)
+ public bool NamespaceDeclared
+ {
+ get { return _configRecord.NamespacePresent; }
+ set { _configRecord.NamespacePresent = value; }
+ }
+
+ public Func<string, string> TypeStringTransformer
+ {
+ get { return _typeStringTransformer; }
+ set
+ {
+ if (_typeStringTransformer != value)
+ {
+ TypeStringTransformerIsSet = value != null;
+ _typeStringTransformer = value;
+ }
+ }
+ }
+
+ public Func<string, string> AssemblyStringTransformer
+ {
+ get { return _assemblyStringTransformer; }
+ set
+ {
+ if (_assemblyStringTransformer != value)
+ {
+ AssemblyStringTransformerIsSet = value != null;
+ _assemblyStringTransformer = value;
+ }
+ }
+ }
+
+ public FrameworkName TargetFramework
+ {
+ get; set;
+ } = null;
+
+ internal bool TypeStringTransformerIsSet { get; private set; }
+
+ internal bool AssemblyStringTransformerIsSet { get; private set; }
+
+ internal Stack SectionsStack => _sectionsStack ?? (_sectionsStack = new Stack());
+
+ // Create a new instance of Configuration for the locationSubPath,
+ // with the initialization parameters that were used to create this configuration.
+ internal Configuration OpenLocationConfiguration(string locationSubPath)
+ {
+ return new Configuration(locationSubPath, _typeConfigHost, _hostInitConfigurationParams);
+ }
+
+ // public methods
+ public ConfigurationSection GetSection(string sectionName)
+ {
+ ConfigurationSection section = (ConfigurationSection)_configRecord.GetSection(sectionName);
+
+ return section;
+ }
+
+ public ConfigurationSectionGroup GetSectionGroup(string sectionGroupName)
+ {
+ ConfigurationSectionGroup sectionGroup = _configRecord.GetSectionGroup(sectionGroupName);
+
+ return sectionGroup;
+ }
+
+ public void Save()
+ {
+ SaveAsImpl(null, ConfigurationSaveMode.Modified, false);
+ }
+
+ public void Save(ConfigurationSaveMode saveMode)
+ {
+ SaveAsImpl(null, saveMode, false);
+ }
+
+ public void Save(ConfigurationSaveMode saveMode, bool forceSaveAll)
+ {
+ SaveAsImpl(null, saveMode, forceSaveAll);
+ }
+
+ public void SaveAs(string filename)
+ {
+ SaveAs(filename, ConfigurationSaveMode.Modified, false);
+ }
+
+ public void SaveAs(string filename, ConfigurationSaveMode saveMode)
+ {
+ SaveAs(filename, saveMode, false);
+ }
+
+ public void SaveAs(string filename, ConfigurationSaveMode saveMode, bool forceSaveAll)
+ {
+ if (string.IsNullOrEmpty(filename)) throw ExceptionUtil.ParameterNullOrEmpty("filename");
+
+ SaveAsImpl(filename, saveMode, forceSaveAll);
+ }
+
+ private void SaveAsImpl(string filename, ConfigurationSaveMode saveMode, bool forceSaveAll)
+ {
+ filename = string.IsNullOrEmpty(filename) ? null : Path.GetFullPath(filename);
+
+ if (forceSaveAll) ForceGroupsRecursive(RootSectionGroup);
+ _configRecord.SaveAs(filename, saveMode, forceSaveAll);
+ }
+
+ // Force all sections and section groups to be instantiated.
+ private void ForceGroupsRecursive(ConfigurationSectionGroup group)
+ {
+ foreach (ConfigurationSection configSection in group.Sections)
+ {
+ // Force the section to be read into the cache
+ ConfigurationSection section = group.Sections[configSection.SectionInformation.Name];
+ }
+
+ foreach (ConfigurationSectionGroup sectionGroup in group.SectionGroups)
+ ForceGroupsRecursive(group.SectionGroups[sectionGroup.Name]);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationAllowDefinition.cs b/src/System.Configuration/src/System/Configuration/ConfigurationAllowDefinition.cs
new file mode 100644
index 0000000000..f47f22aff8
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationAllowDefinition.cs
@@ -0,0 +1,14 @@
+// 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.Configuration
+{
+ public enum ConfigurationAllowDefinition
+ {
+ MachineOnly = 0,
+ MachineToWebRoot = 100,
+ MachineToApplication = 200,
+ Everywhere = 300,
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationAllowExeDefinition.cs b/src/System.Configuration/src/System/Configuration/ConfigurationAllowExeDefinition.cs
new file mode 100644
index 0000000000..279f81078e
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationAllowExeDefinition.cs
@@ -0,0 +1,14 @@
+// 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.Configuration
+{
+ public enum ConfigurationAllowExeDefinition
+ {
+ MachineOnly = 0,
+ MachineToApplication = 100,
+ MachineToRoamingUser = 200,
+ MachineToLocalUser = 300
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationCollectionAttribute.cs b/src/System.Configuration/src/System/Configuration/ConfigurationCollectionAttribute.cs
new file mode 100644
index 0000000000..2725983341
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationCollectionAttribute.cs
@@ -0,0 +1,58 @@
+// 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.Configuration
+{
+ // This attribute is expected on section properties of type derivied from ConfigurationElementCollection
+ // or on the itself
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
+ public sealed class ConfigurationCollectionAttribute : Attribute
+ {
+ private string _addItemName;
+ private string _clearItemsName;
+ private string _removeItemName;
+
+ public ConfigurationCollectionAttribute(Type itemType)
+ {
+ if (itemType == null) throw new ArgumentNullException(nameof(itemType));
+
+ ItemType = itemType;
+ }
+
+ public Type ItemType { get; }
+
+ public string AddItemName
+ {
+ get { return _addItemName ?? ConfigurationElementCollection.DefaultAddItemName; }
+ set
+ {
+ if (string.IsNullOrEmpty(value)) value = null;
+ _addItemName = value;
+ }
+ }
+
+ public string RemoveItemName
+ {
+ get { return _removeItemName ?? ConfigurationElementCollection.DefaultRemoveItemName; }
+ set
+ {
+ if (string.IsNullOrEmpty(value)) value = null;
+ _removeItemName = value;
+ }
+ }
+
+ public string ClearItemsName
+ {
+ get { return _clearItemsName ?? ConfigurationElementCollection.DefaultClearItemsName; }
+ set
+ {
+ if (string.IsNullOrEmpty(value)) value = null;
+ _clearItemsName = value;
+ }
+ }
+
+ public ConfigurationElementCollectionType CollectionType { get; set; } =
+ ConfigurationElementCollectionType.AddRemoveClearMap;
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationConverterBase.cs b/src/System.Configuration/src/System/Configuration/ConfigurationConverterBase.cs
new file mode 100644
index 0000000000..251517bd1d
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationConverterBase.cs
@@ -0,0 +1,27 @@
+// 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.ComponentModel;
+
+namespace System.Configuration
+{
+ public abstract class ConfigurationConverterBase : TypeConverter
+ {
+ public override bool CanConvertTo(ITypeDescriptorContext ctx, Type type)
+ {
+ return type == typeof(string);
+ }
+
+ public override bool CanConvertFrom(ITypeDescriptorContext ctx, Type type)
+ {
+ return type == typeof(string);
+ }
+
+ internal void ValidateType(object value, Type expected)
+ {
+ if ((value != null) && (value.GetType() != expected))
+ throw new ArgumentException(string.Format(SR.Converter_unsupported_value_type, expected.Name));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationElement.cs b/src/System.Configuration/src/System/Configuration/ConfigurationElement.cs
new file mode 100644
index 0000000000..8f45464fa1
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationElement.cs
@@ -0,0 +1,2025 @@
+// 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.Collections.Specialized;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Xml;
+using System.Globalization;
+using System.Text;
+
+namespace System.Configuration
+{
+ // Methods that are called by the configuration system, and must be overridable
+ // by derived classes that wish to implement their own serialization/deserialization
+ // IsModified()
+ // ResetModified()
+ // Reset(ConfigurationElement parentSection, object context)
+ // DeserializeSection(object context, XmlNode xmlNode)
+ // SerializeSection(ConfigurationElement parentSection, object context, string name)
+ public abstract class ConfigurationElement
+ {
+ private const string LockAttributesKey = "lockAttributes";
+ private const string LockAllAttributesExceptKey = "lockAllAttributesExcept";
+ private const string LockElementsKey = "lockElements";
+ private const string LockAll = "*";
+ private const string LockAllElementsExceptKey = "lockAllElementsExcept";
+ private const string LockItemKey = "lockItem";
+ internal const string DefaultCollectionPropertyName = "";
+
+ private static readonly string[] s_lockAttributeNames =
+ {
+ LockAttributesKey,
+ LockAllAttributesExceptKey,
+ LockElementsKey,
+ LockAllElementsExceptKey,
+ LockItemKey,
+ };
+
+ private static readonly Hashtable s_propertyBags = new Hashtable();
+ private static volatile Dictionary<Type, ConfigurationValidatorBase> s_perTypeValidators;
+ internal static readonly object s_nullPropertyValue = new object();
+
+ private static readonly ConfigurationElementProperty s_elementProperty =
+ new ConfigurationElementProperty(new DefaultValidator());
+
+ private bool _bInited;
+ private bool _bModified;
+ private bool _bReadOnly;
+ internal BaseConfigurationRecord _configRecord;
+ private ConfigurationElementProperty _elementProperty = s_elementProperty;
+ internal ContextInformation _evalContext;
+ private volatile ElementInformation _evaluationElement;
+ internal ConfigurationValueFlags _fItemLocked;
+ internal ConfigurationLockCollection _lockedAllExceptAttributesList;
+ internal ConfigurationLockCollection _lockedAllExceptElementsList;
+ internal ConfigurationLockCollection _lockedAttributesList;
+ internal ConfigurationLockCollection _lockedElementsList;
+
+ protected ConfigurationElement()
+ {
+ Values = new ConfigurationValues();
+
+ // Set the per-type validator ( this will actually have an effect only for an attributed model elements )
+ // Note that in the case where the property bag fot this.GetType() has not yet been created
+ // the validator for this instance will get applied in ApplyValidatorsRecursive ( see this.get_Properties )
+ ApplyValidator(this);
+ }
+
+ internal bool DataToWriteInternal { get; set; }
+
+ internal bool ElementPresent { get; set; }
+
+ internal string ElementTagName { get; private set; }
+
+ internal ConfigurationLockCollection LockedAttributesList => _lockedAttributesList;
+
+ internal ConfigurationLockCollection LockedAllExceptAttributesList => _lockedAllExceptAttributesList;
+
+ internal ConfigurationValueFlags ItemLocked => _fItemLocked;
+
+ public ConfigurationLockCollection LockAttributes => _lockedAttributesList
+ ?? (_lockedAttributesList = new ConfigurationLockCollection(this, ConfigurationLockCollectionType.LockedAttributes));
+
+ public ConfigurationLockCollection LockAllAttributesExcept => _lockedAllExceptAttributesList
+ ?? (_lockedAllExceptAttributesList = new ConfigurationLockCollection(this, ConfigurationLockCollectionType.LockedExceptionList, ElementTagName));
+
+ public ConfigurationLockCollection LockElements => _lockedElementsList
+ ?? (_lockedElementsList = new ConfigurationLockCollection(this, ConfigurationLockCollectionType.LockedElements));
+
+ public ConfigurationLockCollection LockAllElementsExcept => _lockedAllExceptElementsList
+ ?? (_lockedAllExceptElementsList = new ConfigurationLockCollection(this, ConfigurationLockCollectionType.LockedElementsExceptionList, ElementTagName));
+
+ public bool LockItem
+ {
+ get { return (_fItemLocked & ConfigurationValueFlags.Locked) != 0; }
+ set
+ {
+ if ((_fItemLocked & ConfigurationValueFlags.Inherited) == 0)
+ {
+ _fItemLocked = value ? ConfigurationValueFlags.Locked : ConfigurationValueFlags.Default;
+ _fItemLocked |= ConfigurationValueFlags.Modified;
+ }
+ else throw new ConfigurationErrorsException(string.Format(SR.Config_base_attribute_locked, LockItemKey));
+ }
+ }
+
+ protected internal object this[ConfigurationProperty prop]
+ {
+ get
+ {
+ object o = Values[prop.Name];
+ if (o == null)
+ {
+ if (prop.IsConfigurationElementType)
+ {
+ lock (Values.SyncRoot)
+ {
+ o = Values[prop.Name];
+ if (o == null)
+ {
+ ConfigurationElement childElement = CreateElement(prop.Type);
+
+ if (_bReadOnly) childElement.SetReadOnly();
+
+ if (typeof(ConfigurationElementCollection).IsAssignableFrom(prop.Type))
+ {
+ ConfigurationElementCollection childElementCollection =
+ childElement as ConfigurationElementCollection;
+ if (prop.AddElementName != null)
+ childElementCollection.AddElementName = prop.AddElementName;
+ if (prop.RemoveElementName != null)
+ childElementCollection.RemoveElementName = prop.RemoveElementName;
+ if (prop.ClearElementName != null)
+ childElementCollection.ClearElementName = prop.ClearElementName;
+ }
+
+ //_values[prop.Name] = childElement;
+ Values.SetValue(prop.Name, childElement, ConfigurationValueFlags.Inherited, null);
+ o = childElement;
+ }
+ }
+ }
+ else o = prop.DefaultValue;
+ }
+ else
+ {
+ if (o == s_nullPropertyValue) o = null;
+ }
+
+ // If its an invalid value - throw the error now
+ if (o is InvalidPropValue) throw ((InvalidPropValue)o).Error;
+
+ return o;
+ }
+
+ set
+ {
+ SetPropertyValue(prop, value, false); // Do not ignore locks!!!
+ }
+ }
+
+ protected internal object this[string propertyName]
+ {
+ get
+ {
+ ConfigurationProperty prop = Properties[propertyName];
+ if (prop == null)
+ {
+ prop = Properties[DefaultCollectionPropertyName];
+ if (prop.ProvidedName != propertyName) return null;
+ }
+ return this[prop];
+ }
+ set
+ {
+ Debug.Assert(Properties.Contains(propertyName), "Properties.Contains(propertyName)");
+ SetPropertyValue(Properties[propertyName], value, false); // Do not ignore locks!!!
+ }
+ }
+
+ protected internal virtual ConfigurationPropertyCollection Properties
+ {
+ get
+ {
+ ConfigurationPropertyCollection result = null;
+
+ if (PropertiesFromType(GetType(), out result))
+ {
+ ApplyInstanceAttributes(this); // Redundant but preserved to minimize code changes for Whidbey RTM
+ ApplyValidatorsRecursive(this);
+ }
+ return result;
+ }
+ }
+
+ internal ConfigurationValues Values { get; }
+
+ public ElementInformation ElementInformation => _evaluationElement ?? (_evaluationElement = new ElementInformation(this));
+
+ protected ContextInformation EvaluationContext
+ {
+ get
+ {
+ if (_evalContext == null)
+ {
+ if (_configRecord == null)
+ {
+ // This is not associated with a context, so throw failure
+ throw new ConfigurationErrorsException(SR.Config_element_no_context);
+ }
+
+ _evalContext = new ContextInformation(_configRecord);
+ }
+
+ return _evalContext;
+ }
+ }
+
+ protected internal virtual ConfigurationElementProperty ElementProperty => _elementProperty;
+
+ protected bool HasContext => _configRecord != null;
+
+ public Configuration CurrentConfiguration => _configRecord?.CurrentConfiguration;
+
+ internal ConfigurationElement CreateElement(Type type)
+ {
+ ConfigurationElement element = (ConfigurationElement)TypeUtil.CreateInstance(type);
+ element.CallInit();
+ return element;
+ }
+
+ protected internal virtual void Init()
+ {
+ // If Init is called by the derived class, we may be able
+ // to set _bInited to true if the derived class properly
+ // calls Init on its base.
+ _bInited = true;
+ }
+
+ internal void CallInit()
+ {
+ // Ensure Init is called just once
+ if (!_bInited)
+ {
+ Init();
+ _bInited = true;
+ }
+ }
+
+ internal void MergeLocks(ConfigurationElement source)
+ {
+ if (source == null) return;
+
+ _fItemLocked = (source._fItemLocked & ConfigurationValueFlags.Locked) != 0
+ ? ConfigurationValueFlags.Inherited | source._fItemLocked
+ : _fItemLocked;
+
+ if (source._lockedAttributesList != null)
+ {
+ // Mark entry as from the parent - read only
+ if (_lockedAttributesList == null)
+ {
+ _lockedAttributesList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedAttributes);
+ }
+
+ foreach (string key in source._lockedAttributesList)
+ _lockedAttributesList.Add(key, ConfigurationValueFlags.Inherited);
+ }
+
+ if (source._lockedAllExceptAttributesList != null)
+ {
+ if (_lockedAllExceptAttributesList == null)
+ {
+ _lockedAllExceptAttributesList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedExceptionList, string.Empty,
+ source._lockedAllExceptAttributesList);
+ }
+
+ StringCollection intersectionCollection = IntersectLockCollections(_lockedAllExceptAttributesList,
+ source._lockedAllExceptAttributesList);
+
+ _lockedAllExceptAttributesList.ClearInternal(false);
+ foreach (string key in intersectionCollection)
+ _lockedAllExceptAttributesList.Add(key, ConfigurationValueFlags.Default);
+ }
+
+ if (source._lockedElementsList != null)
+ {
+ if (_lockedElementsList == null)
+ {
+ _lockedElementsList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedElements);
+ }
+
+ ConfigurationElementCollection collection = null;
+ if (Properties.DefaultCollectionProperty != null)
+ {
+ // this is not a collection but it may contain a default collection
+ collection = this[Properties.DefaultCollectionProperty] as ConfigurationElementCollection;
+ if (collection != null)
+ {
+ // Default collections don't know their tag name
+ collection.InternalElementTagName = source.ElementTagName;
+ //point to the same instance of the collection from parent
+ if (collection._lockedElementsList == null)
+ collection._lockedElementsList = _lockedElementsList;
+ }
+ }
+
+ foreach (string key in source._lockedElementsList)
+ {
+ // Mark entry as from the parent - read only
+ _lockedElementsList.Add(key, ConfigurationValueFlags.Inherited);
+ // add the local copy
+ collection?._lockedElementsList.Add(key, ConfigurationValueFlags.Inherited);
+ }
+ }
+
+ if (source._lockedAllExceptElementsList != null)
+ {
+ if ((_lockedAllExceptElementsList == null) || (_lockedAllExceptElementsList.Count == 0))
+ {
+ _lockedAllExceptElementsList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedElementsExceptionList, source.ElementTagName,
+ source._lockedAllExceptElementsList);
+ }
+
+ StringCollection intersectionCollection = IntersectLockCollections(_lockedAllExceptElementsList,
+ source._lockedAllExceptElementsList);
+
+ if (Properties.DefaultCollectionProperty != null)
+ {
+ // this is not a collection but it may contain a default collection
+ ConfigurationElementCollection collection = this[Properties.DefaultCollectionProperty] as ConfigurationElementCollection;
+ if ((collection != null) && (collection._lockedAllExceptElementsList == null))
+ {
+ // point default collection to the parent collection
+ collection._lockedAllExceptElementsList = _lockedAllExceptElementsList;
+ }
+ }
+
+ _lockedAllExceptElementsList.ClearInternal(false);
+ foreach (string key in intersectionCollection)
+ if (!_lockedAllExceptElementsList.Contains(key) || (key == ElementTagName))
+ _lockedAllExceptElementsList.Add(key, ConfigurationValueFlags.Default);
+
+ if (_lockedAllExceptElementsList.HasParentElements)
+ {
+ // add the local copy
+ foreach (ConfigurationProperty prop in Properties)
+ if (!_lockedAllExceptElementsList.Contains(prop.Name) &&
+ prop.IsConfigurationElementType)
+ ((ConfigurationElement)this[prop]).SetLocked();
+ }
+ }
+ }
+
+ internal void HandleLockedAttributes(ConfigurationElement source)
+ {
+ // if there are locked attributes on this collection element
+ if (source == null || (source._lockedAttributesList == null && source._lockedAllExceptAttributesList == null)) return;
+
+ // enumerate the possible locked properties
+ foreach (PropertyInformation propInfo in source.ElementInformation.Properties)
+ if (((source._lockedAttributesList != null) &&
+ (source._lockedAttributesList.Contains(propInfo.Name) ||
+ source._lockedAttributesList.Contains(LockAll))) ||
+ ((source._lockedAllExceptAttributesList != null) &&
+ !source._lockedAllExceptAttributesList.Contains(propInfo.Name))
+ )
+ {
+ if ((propInfo.Name == LockAttributesKey) || (propInfo.Name == LockAllAttributesExceptKey)) continue;
+
+ // if the attribute has been locked in the source then check to see
+ // if the local config is trying to override it
+ if (ElementInformation.Properties[propInfo.Name] == null)
+ {
+ // locked items are not defined
+
+ ConfigurationPropertyCollection props = Properties;
+ // so create the property based in the source item
+ ConfigurationProperty prop =
+ source.Properties[propInfo.Name];
+ props.Add(prop); // Add the property information to the property bag
+ _evaluationElement = null; // flush the cached element data
+
+ // Add the data from the source element but mark it as in herited
+ // This must use setvalue in order to set the lock and inherited flags
+ ConfigurationValueFlags flags = ConfigurationValueFlags.Inherited |
+ ConfigurationValueFlags.Locked;
+ Values.SetValue(propInfo.Name, propInfo.Value, flags,
+ source.PropertyInfoInternal(propInfo.Name));
+ }
+ else
+ {
+ // don't error when optional attibute are not defined yet
+ if (ElementInformation.Properties[propInfo.Name].ValueOrigin ==
+ PropertyValueOrigin.SetHere)
+ {
+ // Don't allow the override
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_attribute_locked, propInfo.Name));
+ }
+
+ // They did not override so we need to make sure the value comes from the locked one
+ ElementInformation.Properties[propInfo.Name].Value = propInfo.Value;
+ }
+ }
+ }
+
+ internal virtual void AssociateContext(BaseConfigurationRecord configRecord)
+ {
+ _configRecord = configRecord;
+ Values.AssociateContext(configRecord);
+ }
+
+ protected internal virtual bool IsModified()
+ {
+ if (_bModified)
+ return true;
+ if ((_lockedAttributesList != null) && _lockedAttributesList.IsModified)
+ return true;
+ if ((_lockedAllExceptAttributesList != null) && _lockedAllExceptAttributesList.IsModified)
+ return true;
+ if ((_lockedElementsList != null) && _lockedElementsList.IsModified)
+ return true;
+ if ((_lockedAllExceptElementsList != null) && _lockedAllExceptElementsList.IsModified)
+ return true;
+ if ((_fItemLocked & ConfigurationValueFlags.Modified) != 0)
+ return true;
+ foreach (ConfigurationElement elem in Values.ConfigurationElements)
+ if (elem.IsModified()) return true;
+ return false;
+ }
+
+ protected internal virtual void ResetModified()
+ {
+ _bModified = false;
+ _lockedAttributesList?.ResetModified();
+ _lockedAllExceptAttributesList?.ResetModified();
+ _lockedElementsList?.ResetModified();
+ _lockedAllExceptElementsList?.ResetModified();
+ foreach (ConfigurationElement elem in Values.ConfigurationElements)
+ elem.ResetModified();
+ }
+
+ public virtual bool IsReadOnly()
+ {
+ return _bReadOnly;
+ }
+
+ protected internal virtual void SetReadOnly()
+ {
+ _bReadOnly = true;
+ foreach (ConfigurationElement elem in Values.ConfigurationElements) elem.SetReadOnly();
+ }
+
+ internal void SetLocked()
+ {
+ _fItemLocked = ConfigurationValueFlags.Locked | ConfigurationValueFlags.XmlParentInherited;
+
+ foreach (ConfigurationProperty prop in Properties)
+ {
+ ConfigurationElement elem = this[prop] as ConfigurationElement;
+ if (elem != null)
+ {
+ if (elem.GetType() != GetType()) elem.SetLocked();
+
+ ConfigurationElementCollection collection = this[prop] as ConfigurationElementCollection;
+ if (collection != null)
+ {
+ foreach (object obj in collection)
+ {
+ ConfigurationElement element = obj as ConfigurationElement;
+ element?.SetLocked();
+ }
+ }
+ }
+ }
+ }
+
+ internal ArrayList GetErrorsList()
+ {
+ ArrayList errorList = new ArrayList();
+
+ ListErrors(errorList);
+
+ return errorList;
+ }
+
+ internal ConfigurationErrorsException GetErrors()
+ {
+ ArrayList errorsList = GetErrorsList();
+
+ if (errorsList.Count == 0) return null;
+
+ ConfigurationErrorsException e = new ConfigurationErrorsException(errorsList);
+ return e;
+ }
+
+ protected virtual void ListErrors(IList errorList)
+ {
+ // First list errors in this element, then in subelements
+ foreach (InvalidPropValue invalidValue in Values.InvalidValues) errorList.Add(invalidValue.Error);
+
+ foreach (ConfigurationElement elem in Values.ConfigurationElements)
+ {
+ elem.ListErrors(errorList);
+ ConfigurationElementCollection collection = elem as ConfigurationElementCollection;
+ if (collection != null) foreach (ConfigurationElement item in collection) item.ListErrors(errorList);
+ }
+ }
+
+ protected internal virtual void InitializeDefault() { }
+
+ internal void CheckLockedElement(string elementName, XmlReader reader)
+ {
+ // have to check if clear was locked!
+ if (elementName != null)
+ {
+ if (((_lockedElementsList != null) &&
+ (_lockedElementsList.DefinedInParent(LockAll) || _lockedElementsList.DefinedInParent(elementName))) ||
+ ((_lockedAllExceptElementsList != null) && (_lockedAllExceptElementsList.Count != 0) &&
+ _lockedAllExceptElementsList.HasParentElements &&
+ !_lockedAllExceptElementsList.DefinedInParent(elementName)) ||
+ ((_fItemLocked & ConfigurationValueFlags.Inherited) != 0)
+ )
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_element_locked, elementName),
+ reader);
+ }
+ }
+ }
+
+ internal void RemoveAllInheritedLocks()
+ {
+ _lockedAttributesList?.RemoveInheritedLocks();
+ _lockedElementsList?.RemoveInheritedLocks();
+ _lockedAllExceptAttributesList?.RemoveInheritedLocks();
+ _lockedAllExceptElementsList?.RemoveInheritedLocks();
+ }
+
+ internal void ResetLockLists(ConfigurationElement parentElement)
+ {
+ _lockedAttributesList = null;
+ _lockedAllExceptAttributesList = null;
+ _lockedElementsList = null;
+ _lockedAllExceptElementsList = null;
+
+ if (parentElement == null) return;
+
+ _fItemLocked = (parentElement._fItemLocked & ConfigurationValueFlags.Locked) != 0
+ ? ConfigurationValueFlags.Inherited | parentElement._fItemLocked
+ : ConfigurationValueFlags.Default;
+
+ if (parentElement._lockedAttributesList != null)
+ {
+ // Mark entry as from the parent - read only
+ _lockedAttributesList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedAttributes);
+ foreach (string key in parentElement._lockedAttributesList)
+ _lockedAttributesList.Add(key, ConfigurationValueFlags.Inherited);
+ }
+
+ if (parentElement._lockedAllExceptAttributesList != null)
+ {
+ _lockedAllExceptAttributesList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedExceptionList, string.Empty,
+ parentElement._lockedAllExceptAttributesList);
+ }
+
+ if (parentElement._lockedElementsList != null)
+ {
+ _lockedElementsList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedElements);
+
+ if (Properties.DefaultCollectionProperty != null)
+ {
+ // this is not a collection but it may contain a default collection
+ ConfigurationElementCollection collection = this[Properties.DefaultCollectionProperty] as ConfigurationElementCollection;
+ if (collection != null)
+ {
+ collection.InternalElementTagName = parentElement.ElementTagName;
+ // Default collections don't know there tag name
+ if (collection._lockedElementsList == null)
+ collection._lockedElementsList = _lockedElementsList;
+ }
+ }
+
+ // Mark entry as from the parent - read only
+ foreach (string key in parentElement._lockedElementsList)
+ _lockedElementsList.Add(key, ConfigurationValueFlags.Inherited);
+ }
+
+ if (parentElement._lockedAllExceptElementsList != null)
+ {
+ _lockedAllExceptElementsList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedElementsExceptionList, parentElement.ElementTagName,
+ parentElement._lockedAllExceptElementsList);
+
+ if (Properties.DefaultCollectionProperty != null)
+ {
+ // this is not a collection but it may contain a default collection
+ ConfigurationElementCollection collection = this[Properties.DefaultCollectionProperty] as ConfigurationElementCollection;
+ if ((collection != null) && (collection._lockedAllExceptElementsList == null))
+ collection._lockedAllExceptElementsList = _lockedAllExceptElementsList;
+ }
+ }
+ }
+
+ protected internal virtual void Reset(ConfigurationElement parentElement)
+ {
+ Values.Clear();
+ ResetLockLists(parentElement);
+ ConfigurationPropertyCollection props = Properties; // Force the bag to be up to date
+ ElementPresent = false;
+ if (parentElement == null) InitializeDefault();
+ else
+ {
+ bool hasAnyChildElements = false;
+
+ ConfigurationPropertyCollection collectionKeys = null;
+
+ for (int index = 0; index < parentElement.Values.Count; index++)
+ {
+ string key = parentElement.Values.GetKey(index);
+ ConfigurationValue configValue = parentElement.Values.GetConfigValue(index);
+ object value = configValue?.Value;
+ PropertySourceInfo sourceInfo = configValue?.SourceInfo;
+
+ ConfigurationProperty prop = parentElement.Properties[key];
+ if ((prop == null) || ((collectionKeys != null) && !collectionKeys.Contains(prop.Name))) continue;
+
+ if (prop.IsConfigurationElementType) hasAnyChildElements = true;
+ else
+ {
+ ConfigurationValueFlags flags = ConfigurationValueFlags.Inherited |
+ (((_lockedAttributesList != null) &&
+ (_lockedAttributesList.Contains(key) ||
+ _lockedAttributesList.Contains(LockAll))) ||
+ ((_lockedAllExceptAttributesList != null) &&
+ !_lockedAllExceptAttributesList.Contains(key))
+ ? ConfigurationValueFlags.Locked
+ : ConfigurationValueFlags.Default);
+
+ if (value != s_nullPropertyValue)
+ {
+ // _values[key] = value;
+ Values.SetValue(key, value, flags, sourceInfo);
+ }
+
+ if (!props.Contains(key)) // this is for optional provider models keys
+ {
+ props.Add(prop);
+ Values.SetValue(key, value, flags, sourceInfo);
+ }
+ }
+ }
+
+ if (hasAnyChildElements)
+ {
+ for (int index = 0; index < parentElement.Values.Count; index++)
+ {
+ string key = parentElement.Values.GetKey(index);
+ object value = parentElement.Values[index];
+
+ ConfigurationProperty prop = parentElement.Properties[key];
+ if ((prop != null) && prop.IsConfigurationElementType)
+ {
+ //((ConfigurationElement)value).SerializeToXmlElement(writer, prop.Name);
+ ConfigurationElement childElement = (ConfigurationElement)this[prop];
+ childElement.Reset((ConfigurationElement)value);
+ }
+ }
+ }
+ }
+ }
+
+ public override bool Equals(object compareTo)
+ {
+ ConfigurationElement compareToElem = compareTo as ConfigurationElement;
+
+ if ((compareToElem == null) ||
+ (compareTo.GetType() != GetType()) ||
+ (compareToElem.Properties.Count != Properties.Count))
+ return false;
+
+ foreach (ConfigurationProperty configProperty in Properties)
+ if (!Equals(Values[configProperty.Name], compareToElem.Values[configProperty.Name]))
+ {
+ if (!((((Values[configProperty.Name] == null) ||
+ (Values[configProperty.Name] == s_nullPropertyValue)) &&
+ Equals(compareToElem.Values[configProperty.Name], configProperty.DefaultValue)) ||
+ (((compareToElem.Values[configProperty.Name] == null) ||
+ (compareToElem.Values[configProperty.Name] == s_nullPropertyValue)) &&
+ Equals(Values[configProperty.Name], configProperty.DefaultValue))))
+ return false;
+ }
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ int hHashCode = 0;
+ foreach (ConfigurationProperty configProperty in Properties)
+ {
+ object o = this[configProperty];
+ if (o != null) hHashCode ^= this[configProperty].GetHashCode();
+ }
+ return hHashCode;
+ }
+
+ // Note: this method is completelly redundant ( the code is duplaicated in ConfigurationProperty( PropertyInfo ) )
+ // We do not remove the code now to minimize code changes for Whidbey RTM but this method and all calls leading to it should
+ // be removed post-Whidbey
+ private static void ApplyInstanceAttributes(object instance)
+ {
+ Debug.Assert(instance is ConfigurationElement, "instance is ConfigurationElement");
+ Type type = instance.GetType();
+
+ foreach (
+ PropertyInfo propertyInformation in
+ type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
+ {
+ ConfigurationPropertyAttribute attribProperty =
+ Attribute.GetCustomAttribute(propertyInformation,
+ typeof(ConfigurationPropertyAttribute)) as ConfigurationPropertyAttribute;
+
+ if (attribProperty == null) continue;
+
+ Type propertyType = propertyInformation.PropertyType;
+ if (typeof(ConfigurationElementCollection).IsAssignableFrom(propertyType))
+ {
+ // Collections need some customization when the collection attribute is present
+ ConfigurationCollectionAttribute attribCollection =
+ Attribute.GetCustomAttribute(propertyInformation,
+ typeof(ConfigurationCollectionAttribute)) as ConfigurationCollectionAttribute ??
+ Attribute.GetCustomAttribute(propertyType,
+ typeof(ConfigurationCollectionAttribute)) as ConfigurationCollectionAttribute;
+
+ ConfigurationElementCollection coll =
+ propertyInformation.GetValue(instance, null) as ConfigurationElementCollection;
+
+ if (coll == null)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_element_null_instance,
+ propertyInformation.Name, attribProperty.Name));
+ }
+
+ // If the attribute is found - get the collection instance and set the data from the attribute
+ if (attribCollection != null)
+ {
+ if (attribCollection.AddItemName.IndexOf(',') == -1)
+ coll.AddElementName = attribCollection.AddItemName;
+ coll.RemoveElementName = attribCollection.RemoveItemName;
+ coll.ClearElementName = attribCollection.ClearItemsName;
+ }
+ }
+ else
+ {
+ if (typeof(ConfigurationElement).IsAssignableFrom(propertyType))
+ {
+ // Nested configuration element - handle recursively
+ object element = propertyInformation.GetValue(instance, null);
+ if (element == null)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_element_null_instance,
+ propertyInformation.Name, attribProperty.Name));
+ }
+
+ ApplyInstanceAttributes(element);
+ }
+ }
+ }
+ }
+
+ private static bool PropertiesFromType(Type type, out ConfigurationPropertyCollection result)
+ {
+ ConfigurationPropertyCollection properties = (ConfigurationPropertyCollection)s_propertyBags[type];
+ bool firstTimeInit = false;
+ if (properties == null)
+ {
+ lock (s_propertyBags.SyncRoot)
+ {
+ properties = (ConfigurationPropertyCollection)s_propertyBags[type];
+ if (properties == null)
+ {
+ properties = CreatePropertyBagFromType(type);
+ s_propertyBags[type] = properties;
+ firstTimeInit = true;
+ }
+ }
+ }
+ result = properties;
+ return firstTimeInit;
+ }
+
+ private static ConfigurationPropertyCollection CreatePropertyBagFromType(Type type)
+ {
+ Debug.Assert(type != null, "type != null");
+
+ // For ConfigurationElement derived classes - get the per-type validator
+ if (typeof(ConfigurationElement).IsAssignableFrom(type))
+ {
+ ConfigurationValidatorAttribute attribValidator =
+ Attribute.GetCustomAttribute(type, typeof(ConfigurationValidatorAttribute)) as
+ ConfigurationValidatorAttribute;
+
+ if (attribValidator != null)
+ {
+ attribValidator.SetDeclaringType(type);
+ ConfigurationValidatorBase validator = attribValidator.ValidatorInstance;
+
+ if (validator != null) CachePerTypeValidator(type, validator);
+ }
+ }
+
+ ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection();
+
+ foreach (
+ PropertyInfo propertyInformation in
+ type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
+ {
+ ConfigurationProperty newProp = CreateConfigurationPropertyFromAttributes(propertyInformation);
+
+ if (newProp != null) properties.Add(newProp);
+ }
+
+ return properties;
+ }
+
+ private static ConfigurationProperty CreateConfigurationPropertyFromAttributes(PropertyInfo propertyInformation)
+ {
+ Debug.Assert(propertyInformation != null, "propertyInformation != null");
+
+ ConfigurationProperty result = null;
+
+ ConfigurationPropertyAttribute attribProperty =
+ Attribute.GetCustomAttribute(propertyInformation,
+ typeof(ConfigurationPropertyAttribute)) as ConfigurationPropertyAttribute;
+
+ // If there is no ConfigurationProperty attrib - this is not considered a property
+ if (attribProperty != null) result = new ConfigurationProperty(propertyInformation);
+
+ // Handle some special cases of property types
+ if ((result != null) && typeof(ConfigurationElement).IsAssignableFrom(result.Type))
+ {
+ ConfigurationPropertyCollection unused;
+ PropertiesFromType(result.Type, out unused);
+ }
+
+ return result;
+ }
+
+ private static void CachePerTypeValidator(Type type, ConfigurationValidatorBase validator)
+ {
+ Debug.Assert((type != null) && (validator != null));
+ Debug.Assert(typeof(ConfigurationElement).IsAssignableFrom(type));
+
+ // Use the same lock as the property bag lock since in the current implementation
+ // the only way to get to this method is through the code path that locks the property bag cache first ( see PropertiesFromType() )
+
+ // NOTE[ Thread Safety ]: Non-guarded access to static variable - since this code is called only from CreatePropertyBagFromType
+ // which in turn is done onle once per type and is guarded by the s_propertyBag.SyncRoot then this call is thread safe as well
+ if (s_perTypeValidators == null) s_perTypeValidators = new Dictionary<Type, ConfigurationValidatorBase>();
+
+ // A type validator should be cached only once. If it isn't then attribute parsing is done more then once which should be avoided
+ Debug.Assert(!s_perTypeValidators.ContainsKey(type));
+
+ // Make sure the supplied validator supports validating this object
+ if (!validator.CanValidate(type))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Validator_does_not_support_elem_type, type.Name));
+ }
+
+ s_perTypeValidators.Add(type, validator);
+ }
+
+ private static void ApplyValidatorsRecursive(ConfigurationElement root)
+ {
+ Debug.Assert(root != null);
+
+ // Apply the validator on 'root'
+ ApplyValidator(root);
+
+ // Apply validators on child elements ( note - we will do this only on already created child elements
+ // The non created ones will get their validators in the ctor
+ foreach (ConfigurationElement elem in root.Values.ConfigurationElements) ApplyValidatorsRecursive(elem);
+ }
+
+ private static void ApplyValidator(ConfigurationElement elem)
+ {
+ Debug.Assert(elem != null);
+
+ if ((s_perTypeValidators != null) && s_perTypeValidators.ContainsKey(elem.GetType()))
+ elem._elementProperty = new ConfigurationElementProperty(s_perTypeValidators[elem.GetType()]);
+ }
+
+ protected void SetPropertyValue(ConfigurationProperty prop, object value, bool ignoreLocks)
+ {
+ if (IsReadOnly()) throw new ConfigurationErrorsException(SR.Config_base_read_only);
+
+ if ((ignoreLocks == false) &&
+ (((_lockedAllExceptAttributesList != null) && _lockedAllExceptAttributesList.HasParentElements &&
+ !_lockedAllExceptAttributesList.DefinedInParent(prop.Name)) ||
+ ((_lockedAttributesList != null) &&
+ (_lockedAttributesList.DefinedInParent(prop.Name) || _lockedAttributesList.DefinedInParent(LockAll))) ||
+ (((_fItemLocked & ConfigurationValueFlags.Locked) != 0) &&
+ ((_fItemLocked & ConfigurationValueFlags.Inherited) != 0))))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_attribute_locked, prop.Name));
+
+ _bModified = true;
+
+ // Run the new value through the validator to make sure its ok to store it
+ if (value != null) prop.Validate(value);
+
+ Values[prop.Name] = value ?? s_nullPropertyValue;
+ }
+
+ internal PropertySourceInfo PropertyInfoInternal(string propertyName)
+ {
+ return Values.GetSourceInfo(propertyName);
+ }
+
+ internal string PropertyFileName(string propertyName)
+ {
+ // Get the filename of the parent if prop is not there
+ PropertySourceInfo p = PropertyInfoInternal(propertyName) ?? PropertyInfoInternal(string.Empty);
+ return p == null ? string.Empty : p.FileName;
+ }
+
+ internal int PropertyLineNumber(string propertyName)
+ {
+ PropertySourceInfo p = PropertyInfoInternal(propertyName) ?? PropertyInfoInternal(string.Empty);
+ return p?.LineNumber ?? 0;
+ }
+
+ internal virtual void Dump(TextWriter tw)
+ {
+ tw.WriteLine("Type: " + GetType().FullName);
+
+ foreach (PropertyInfo pi in GetType().GetProperties())
+ tw.WriteLine("{0}: {1}", pi.Name, pi.GetValue(this, null));
+ }
+
+ protected internal virtual void Unmerge(ConfigurationElement sourceElement,
+ ConfigurationElement parentElement,
+ ConfigurationSaveMode saveMode)
+ {
+ if (sourceElement == null) return;
+ bool hasAnyChildElements = false;
+
+ _lockedAllExceptAttributesList = sourceElement._lockedAllExceptAttributesList;
+ _lockedAllExceptElementsList = sourceElement._lockedAllExceptElementsList;
+ _fItemLocked = sourceElement._fItemLocked;
+ _lockedAttributesList = sourceElement._lockedAttributesList;
+ _lockedElementsList = sourceElement._lockedElementsList;
+ AssociateContext(sourceElement._configRecord);
+
+ if (parentElement != null)
+ {
+ if (parentElement._lockedAttributesList != null)
+ {
+ _lockedAttributesList = UnMergeLockList(sourceElement._lockedAttributesList,
+ parentElement._lockedAttributesList, saveMode);
+ }
+ if (parentElement._lockedElementsList != null)
+ {
+ _lockedElementsList = UnMergeLockList(sourceElement._lockedElementsList,
+ parentElement._lockedElementsList, saveMode);
+ }
+ if (parentElement._lockedAllExceptAttributesList != null)
+ {
+ _lockedAllExceptAttributesList = UnMergeLockList(sourceElement._lockedAllExceptAttributesList,
+ parentElement._lockedAllExceptAttributesList, saveMode);
+ }
+ if (parentElement._lockedAllExceptElementsList != null)
+ {
+ _lockedAllExceptElementsList = UnMergeLockList(sourceElement._lockedAllExceptElementsList,
+ parentElement._lockedAllExceptElementsList, saveMode);
+ }
+ }
+
+ ConfigurationPropertyCollection props = Properties;
+ ConfigurationPropertyCollection collectionKeys = null;
+
+ // check for props not in bag from source
+ for (int index = 0; index < sourceElement.Values.Count; index++)
+ {
+ string key = sourceElement.Values.GetKey(index);
+ object value = sourceElement.Values[index];
+ ConfigurationProperty prop = sourceElement.Properties[key];
+ if ((prop == null) || ((collectionKeys != null) && !collectionKeys.Contains(prop.Name)))
+ continue;
+
+ if (prop.IsConfigurationElementType)
+ {
+ hasAnyChildElements = true;
+ }
+ else if (value != s_nullPropertyValue && !props.Contains(key))
+ {
+ // this is for optional provider models keys
+ // _values[key] = value;
+ ConfigurationValueFlags valueFlags = sourceElement.Values.RetrieveFlags(key);
+ Values.SetValue(key, value, valueFlags, null);
+
+ props.Add(prop);
+ }
+ }
+
+ foreach (ConfigurationProperty prop in Properties)
+ {
+ if ((prop == null) || ((collectionKeys != null) && !collectionKeys.Contains(prop.Name))) continue;
+ if (prop.IsConfigurationElementType) hasAnyChildElements = true;
+ else
+ {
+ object value = sourceElement.Values[prop.Name];
+
+ // if the property is required or we are writing a full config make sure we have defaults
+ if ((prop.IsRequired || (saveMode == ConfigurationSaveMode.Full)) &&
+ ((value == null) || (value == s_nullPropertyValue)))
+ {
+ // If the default value is null, this means there wasnt a reasonable default for the value
+ // and there is nothing more we can do. Otherwise reset the value to the default
+
+ // Note: 'null' should be used as default for non-empty strings instead
+ // of the current practice to use String.Epmty
+ if (prop.DefaultValue != null)
+ value = prop.DefaultValue; // need to make sure required properties are persisted
+ }
+
+ if ((value == null) || (value == s_nullPropertyValue)) continue;
+
+ object value2 = null;
+ if (parentElement != null) // Is there a parent
+ value2 = parentElement.Values[prop.Name]; // if so get it's value
+
+ if (value2 == null) // no parent use default
+ value2 = prop.DefaultValue;
+
+ // If changed and not same as parent write or required
+ switch (saveMode)
+ {
+ case ConfigurationSaveMode.Minimal:
+ if (!Equals(value, value2) || prop.IsRequired)
+ Values[prop.Name] = value;
+ break;
+ case ConfigurationSaveMode.Modified:
+ bool modified = sourceElement.Values.IsModified(prop.Name);
+ bool inherited = sourceElement.Values.IsInherited(prop.Name);
+
+ // update the value if the property is required, modified or it was not inherited
+ // Also update properties that ARE inherited when we are resetting the object
+ // as long as the property is not the same as the default value for the property
+ if (prop.IsRequired || modified || !inherited ||
+ ((parentElement == null) && inherited && !Equals(value, value2)))
+ Values[prop.Name] = value;
+ break;
+ case ConfigurationSaveMode.Full:
+ if ((value != null) && (value != s_nullPropertyValue))
+ Values[prop.Name] = value;
+ else
+ Values[prop.Name] = value2;
+ break;
+ }
+ }
+ }
+
+ if (hasAnyChildElements)
+ {
+ foreach (ConfigurationProperty prop in Properties)
+ if (prop.IsConfigurationElementType)
+ {
+ ConfigurationElement pElem =
+ (ConfigurationElement)parentElement?[prop];
+ ConfigurationElement childElement = (ConfigurationElement)this[prop];
+ if ((ConfigurationElement)sourceElement[prop] != null)
+ {
+ childElement.Unmerge((ConfigurationElement)sourceElement[prop],
+ pElem, saveMode);
+ }
+ }
+ }
+ }
+
+ protected internal virtual bool SerializeToXmlElement(XmlWriter writer, string elementName)
+ {
+ if ((_configRecord != null) && (_configRecord.TargetFramework != null))
+ {
+ ConfigurationSection section = null;
+ if (_configRecord.SectionsStack.Count > 0)
+ section = _configRecord.SectionsStack.Peek() as ConfigurationSection;
+ if ((section != null) &&
+ !section.ShouldSerializeElementInTargetVersion(this, elementName, _configRecord.TargetFramework))
+ return false;
+ }
+
+ bool dataToWrite = DataToWriteInternal;
+
+ // Don't write elements that are locked in the parent
+ if (((_lockedElementsList != null) && _lockedElementsList.DefinedInParent(elementName)) ||
+ ((_lockedAllExceptElementsList != null) && _lockedAllExceptElementsList.HasParentElements &&
+ !_lockedAllExceptElementsList.DefinedInParent(elementName)))
+ return dataToWrite;
+
+ if (SerializeElement(null, false)) // check if there is anything to write...
+ {
+ writer?.WriteStartElement(elementName);
+ dataToWrite |= SerializeElement(writer, false);
+ writer?.WriteEndElement();
+ }
+ return dataToWrite;
+ }
+
+ protected internal virtual bool SerializeElement(XmlWriter writer, bool serializeCollectionKey)
+ {
+ PreSerialize(writer);
+
+ bool dataToWrite = DataToWriteInternal;
+ bool hasAnyChildElements = false;
+ bool foundDefaultElement = false;
+ ConfigurationPropertyCollection props = Properties;
+ ConfigurationPropertyCollection collectionKeys = null;
+
+ for (int index = 0; index < Values.Count; index++)
+ {
+ string key = Values.GetKey(index);
+ object value = Values[index];
+
+ ConfigurationProperty prop = props[key];
+ if ((prop == null) || ((collectionKeys != null) && !collectionKeys.Contains(prop.Name))) continue;
+
+ if (prop.IsVersionCheckRequired && (_configRecord != null) && (_configRecord.TargetFramework != null))
+ {
+ ConfigurationSection section = null;
+ if (_configRecord.SectionsStack.Count > 0)
+ section = _configRecord.SectionsStack.Peek() as ConfigurationSection;
+
+ if ((section != null) &&
+ !section.ShouldSerializePropertyInTargetVersion(prop, prop.Name, _configRecord.TargetFramework,
+ this))
+ continue;
+ }
+
+
+ if (prop.IsConfigurationElementType) hasAnyChildElements = true;
+ else
+ {
+ if (((_lockedAllExceptAttributesList != null) && _lockedAllExceptAttributesList.HasParentElements &&
+ !_lockedAllExceptAttributesList.DefinedInParent(prop.Name)) ||
+ ((_lockedAttributesList != null) && _lockedAttributesList.DefinedInParent(prop.Name)))
+ {
+ if (prop.IsRequired)
+ {
+ throw new ConfigurationErrorsException(string.Format(
+ SR.Config_base_required_attribute_locked, prop.Name));
+ }
+ value = s_nullPropertyValue;
+ }
+
+ if (value == s_nullPropertyValue || (serializeCollectionKey && !prop.IsKey)) continue;
+
+ string xmlValue;
+
+ // If this was an invalid string value and was cached - write it out as is
+ if (value is InvalidPropValue) xmlValue = ((InvalidPropValue)value).Value;
+ else
+ {
+ prop.Validate(value);
+ xmlValue = prop.ConvertToString(value);
+ }
+
+ if ((xmlValue != null) && (writer != null))
+ {
+ if (prop.IsTypeStringTransformationRequired)
+ xmlValue = GetTransformedTypeString(xmlValue);
+ if (prop.IsAssemblyStringTransformationRequired)
+ xmlValue = GetTransformedAssemblyString(xmlValue);
+
+ writer.WriteAttributeString(prop.Name, xmlValue);
+ }
+
+ dataToWrite = dataToWrite || (xmlValue != null);
+ }
+ }
+
+ if (serializeCollectionKey == false)
+ {
+ dataToWrite |= SerializeLockList(_lockedAttributesList, LockAttributesKey, writer);
+ dataToWrite |= SerializeLockList(_lockedAllExceptAttributesList, LockAllAttributesExceptKey, writer);
+ dataToWrite |= SerializeLockList(_lockedElementsList, LockElementsKey, writer);
+ dataToWrite |= SerializeLockList(_lockedAllExceptElementsList, LockAllElementsExceptKey, writer);
+ if (((_fItemLocked & ConfigurationValueFlags.Locked) != 0) &&
+ ((_fItemLocked & ConfigurationValueFlags.Inherited) == 0) &&
+ ((_fItemLocked & ConfigurationValueFlags.XmlParentInherited) == 0))
+ {
+ dataToWrite = true;
+ writer?.WriteAttributeString(LockItemKey, true.ToString().ToLower(CultureInfo.InvariantCulture));
+ }
+ }
+
+ if (hasAnyChildElements)
+ {
+ for (int index = 0; index < Values.Count; index++)
+ {
+ string key = Values.GetKey(index);
+ object value = Values[index];
+
+ ConfigurationProperty prop = props[key];
+
+ // if we are writing a remove and the sub element is not part of the key don't write it.
+ if ((serializeCollectionKey && !prop.IsKey) || !(value is ConfigurationElement))
+ continue;
+
+ if (((_lockedElementsList != null) && _lockedElementsList.DefinedInParent(key)) ||
+ ((_lockedAllExceptElementsList != null) &&
+ _lockedAllExceptElementsList.HasParentElements &&
+ !_lockedAllExceptElementsList.DefinedInParent(key)))
+ continue;
+
+ ConfigurationElement elem = (ConfigurationElement)value;
+
+ if (prop.Name != ConfigurationProperty.s_defaultCollectionPropertyName)
+ {
+ dataToWrite |= elem.SerializeToXmlElement(writer, prop.Name);
+ }
+ else
+ {
+ if (!foundDefaultElement)
+ {
+ // Prevent the locks from serializing a second time since locks
+ // on a default collection serialize with their parent node
+ elem._lockedAttributesList = null;
+ elem._lockedAllExceptAttributesList = null;
+ elem._lockedElementsList = null;
+ elem._lockedAllExceptElementsList = null;
+
+ dataToWrite |= elem.SerializeElement(writer, false);
+
+ foundDefaultElement = true;
+ }
+ else
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_element_cannot_have_multiple_child_elements, prop.Name));
+ }
+ }
+ }
+ }
+
+ return dataToWrite;
+ }
+
+ private bool SerializeLockList(ConfigurationLockCollection list, string elementKey, XmlWriter writer)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ if (list != null)
+ {
+ foreach (string key in list)
+ if (!list.DefinedInParent(key))
+ {
+ if (sb.Length != 0)
+ sb.Append(',');
+ sb.Append(key);
+ }
+ }
+
+ if ((writer != null) && (sb.Length != 0))
+ writer.WriteAttributeString(elementKey, sb.ToString());
+ return sb.Length != 0;
+ }
+
+ internal void ReportInvalidLock(string attribToLockTrim, ConfigurationLockCollectionType lockedType,
+ ConfigurationValue value, string collectionProperties)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ // Add the collection properties when locking elements
+ if (!string.IsNullOrEmpty(collectionProperties) &&
+ ((lockedType == ConfigurationLockCollectionType.LockedElements) ||
+ (lockedType == ConfigurationLockCollectionType.LockedElementsExceptionList)))
+ {
+ if (sb.Length != 0)
+ sb.Append(',');
+ sb.Append(collectionProperties);
+ }
+
+ // construct a list of valid lockable properties
+ foreach (object prop in Properties)
+ {
+ ConfigurationProperty validProp = (ConfigurationProperty)prop;
+ if ((validProp.Name != LockAttributesKey) &&
+ (validProp.Name != LockAllAttributesExceptKey) &&
+ (validProp.Name != LockElementsKey) &&
+ (validProp.Name != LockAllElementsExceptKey)
+ )
+ {
+ if ((lockedType == ConfigurationLockCollectionType.LockedElements) ||
+ (lockedType == ConfigurationLockCollectionType.LockedElementsExceptionList))
+ {
+ if (typeof(ConfigurationElement).IsAssignableFrom(validProp.Type))
+ {
+ if (sb.Length != 0)
+ sb.Append(", ");
+ sb.Append("'");
+ sb.Append(validProp.Name);
+ sb.Append("'");
+ }
+ }
+ else
+ {
+ if (!typeof(ConfigurationElement).IsAssignableFrom(validProp.Type))
+ {
+ if (sb.Length != 0)
+ sb.Append(", ");
+ sb.Append("'");
+ sb.Append(validProp.Name);
+ sb.Append("'");
+ }
+ }
+ }
+ }
+
+ string format;
+
+ if ((lockedType == ConfigurationLockCollectionType.LockedElements) ||
+ (lockedType == ConfigurationLockCollectionType.LockedElementsExceptionList))
+ {
+ format = value != null ? SR.Config_base_invalid_element_to_lock : SR.Config_base_invalid_element_to_lock_by_add;
+ }
+ else
+ {
+ format = value != null ? SR.Config_base_invalid_attribute_to_lock : SR.Config_base_invalid_attribute_to_lock_by_add;
+ }
+
+ if (value != null)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(CultureInfo.CurrentCulture, format, attribToLockTrim, sb.ToString()),
+ value.SourceInfo.FileName, value.SourceInfo.LineNumber);
+ }
+
+ throw new ConfigurationErrorsException(string.Format(CultureInfo.CurrentCulture, format,
+ attribToLockTrim, sb.ToString()));
+ }
+
+ private ConfigurationLockCollection ParseLockedAttributes(ConfigurationValue value,
+ ConfigurationLockCollectionType lockType)
+ {
+ // check that only actual properties are in the lock attribute
+ ConfigurationLockCollection localLockedAttributesList = new ConfigurationLockCollection(this, lockType);
+ string attributeList = (string)value.Value;
+
+ if (string.IsNullOrEmpty(attributeList))
+ {
+ switch (lockType)
+ {
+ case ConfigurationLockCollectionType.LockedAttributes:
+ throw new ConfigurationErrorsException(string.Format(SR.Empty_attribute, LockAttributesKey),
+ value.SourceInfo.FileName, value.SourceInfo.LineNumber);
+ case ConfigurationLockCollectionType.LockedElements:
+ throw new ConfigurationErrorsException(string.Format(SR.Empty_attribute, LockElementsKey),
+ value.SourceInfo.FileName, value.SourceInfo.LineNumber);
+ case ConfigurationLockCollectionType.LockedExceptionList:
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_empty_lock_attributes_except, LockAllAttributesExceptKey,
+ LockAttributesKey), value.SourceInfo.FileName, value.SourceInfo.LineNumber);
+ case ConfigurationLockCollectionType.LockedElementsExceptionList:
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_empty_lock_element_except, LockAllElementsExceptKey, LockElementsKey),
+ value.SourceInfo.FileName, value.SourceInfo.LineNumber);
+ }
+ }
+
+ string[] attribsToLock = attributeList.Split(',', ':', ';');
+ foreach (string attribToLock in attribsToLock)
+ {
+ string attribToLockTrim = attribToLock.Trim();
+ if (!string.IsNullOrEmpty(attribToLockTrim))
+ {
+ // validate that the locks are good
+ if (!(((lockType == ConfigurationLockCollectionType.LockedElements) ||
+ (lockType == ConfigurationLockCollectionType.LockedAttributes)) &&
+ (attribToLockTrim == LockAll)))
+ {
+ ConfigurationProperty propToLock = Properties[attribToLockTrim];
+
+ if ((propToLock == null) || // if the prop does not exist
+ (attribToLockTrim == LockAttributesKey) || // or it is the lockattributes keyword
+ (attribToLockTrim == LockAllAttributesExceptKey) || // or it is the lockattributes keyword
+ (attribToLockTrim == LockElementsKey) || // or it is the lockelements keyword
+ ((lockType != ConfigurationLockCollectionType.LockedElements) &&
+ (lockType != ConfigurationLockCollectionType.LockedElementsExceptionList) &&
+ typeof(ConfigurationElement).IsAssignableFrom(propToLock.Type)) ||
+ // or if not locking elements but the property is a element
+ (((lockType == ConfigurationLockCollectionType.LockedElements) ||
+ (lockType == ConfigurationLockCollectionType.LockedElementsExceptionList)) &&
+ !typeof(ConfigurationElement).IsAssignableFrom(propToLock.Type))
+ // or if locking elements but the property is not an element
+ )
+ {
+ // check to see if this is a collection and we are locking a collection element
+
+ ConfigurationElementCollection collection = this as ConfigurationElementCollection;
+ if ((collection == null) && (Properties.DefaultCollectionProperty != null))
+ // this is not a collection but it may contain a default collection
+ {
+ collection =
+ this[Properties.DefaultCollectionProperty] as ConfigurationElementCollection;
+ }
+ if ((collection == null) ||
+ (lockType == ConfigurationLockCollectionType.LockedAttributes) ||
+ // If the collection type is not element then the lock is bogus
+ (lockType == ConfigurationLockCollectionType.LockedExceptionList))
+ ReportInvalidLock(attribToLockTrim, lockType, value, null);
+ else
+ {
+ if (!collection.IsLockableElement(attribToLockTrim))
+ ReportInvalidLock(attribToLockTrim, lockType, value, collection.LockableElements);
+ }
+ }
+
+ if ((propToLock != null) && propToLock.IsRequired)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_required_attribute_lock_attempt, propToLock.Name));
+ }
+ }
+
+
+ // concatenate the new attribute.
+ localLockedAttributesList.Add(attribToLockTrim, ConfigurationValueFlags.Default); // Mark as local
+ }
+ }
+ return localLockedAttributesList;
+ }
+
+ private StringCollection IntersectLockCollections(ConfigurationLockCollection collection1,
+ ConfigurationLockCollection collection2)
+ {
+ ConfigurationLockCollection smallCollection = collection1.Count < collection2.Count
+ ? collection1
+ : collection2;
+ ConfigurationLockCollection largeCollection = collection1.Count >= collection2.Count
+ ? collection1
+ : collection2;
+ StringCollection intersectionCollection = new StringCollection();
+
+ foreach (string key in smallCollection)
+ if (largeCollection.Contains(key) || (key == ElementTagName))
+ intersectionCollection.Add(key); // add the local copy
+ return intersectionCollection;
+ }
+
+
+ protected internal virtual void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
+ {
+ ConfigurationPropertyCollection props = Properties;
+ ConfigurationValue lockedAttributesList = null;
+ ConfigurationValue lockedAllExceptList = null;
+ ConfigurationValue lockedElementList = null;
+ ConfigurationValue lockedAllElementsExceptList = null;
+ bool itemLockedLocally = false;
+
+ ElementPresent = true;
+
+ ConfigurationElement defaultCollection = null;
+ ConfigurationProperty defaultCollectionProperty = props?.DefaultCollectionProperty;
+ if (defaultCollectionProperty != null)
+ defaultCollection = (ConfigurationElement)this[defaultCollectionProperty];
+
+ // Process attributes
+ ElementTagName = reader.Name;
+ PropertySourceInfo rootInfo = new PropertySourceInfo(reader);
+ Values.SetValue(reader.Name, null, ConfigurationValueFlags.Modified, rootInfo);
+ Values.SetValue(DefaultCollectionPropertyName, defaultCollection, ConfigurationValueFlags.Modified,
+ rootInfo);
+
+ if (((_lockedElementsList != null) && (_lockedElementsList.Contains(reader.Name) ||
+ (_lockedElementsList.Contains(LockAll) && (reader.Name != ElementTagName)))) ||
+ ((_lockedAllExceptElementsList != null) && (_lockedAllExceptElementsList.Count != 0) &&
+ !_lockedAllExceptElementsList.Contains(reader.Name)) ||
+ (((_fItemLocked & ConfigurationValueFlags.Locked) != 0) &&
+ ((_fItemLocked & ConfigurationValueFlags.Inherited) != 0))
+ )
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_element_locked, reader.Name), reader);
+
+
+ if (reader.AttributeCount > 0)
+ {
+ while (reader.MoveToNextAttribute())
+ {
+ string propertyName = reader.Name;
+ if (((_lockedAttributesList != null) &&
+ (_lockedAttributesList.Contains(propertyName) || _lockedAttributesList.Contains(LockAll))) ||
+ ((_lockedAllExceptAttributesList != null) &&
+ !_lockedAllExceptAttributesList.Contains(propertyName))
+ )
+ {
+ if ((propertyName != LockAttributesKey) && (propertyName != LockAllAttributesExceptKey))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_attribute_locked, propertyName), reader);
+ }
+ }
+
+ ConfigurationProperty prop = props?[propertyName];
+ if (prop != null)
+ {
+ if (serializeCollectionKey && !prop.IsKey)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_unrecognized_attribute, propertyName), reader);
+ }
+
+ Values.SetValue(propertyName,
+ DeserializePropertyValue(prop, reader),
+ ConfigurationValueFlags.Modified,
+ new PropertySourceInfo(reader));
+ }
+ else
+ {
+ // if (deserializing a remove OR an add that does not handle optional attributes)
+ switch (propertyName)
+ {
+ case LockItemKey:
+ try
+ {
+ itemLockedLocally = bool.Parse(reader.Value);
+ }
+ catch
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_invalid_boolean_attribute, propertyName), reader);
+ }
+ break;
+ case LockAttributesKey:
+ lockedAttributesList = new ConfigurationValue(reader.Value,
+ ConfigurationValueFlags.Default, new PropertySourceInfo(reader));
+ break;
+ case LockAllAttributesExceptKey:
+ lockedAllExceptList = new ConfigurationValue(reader.Value,
+ ConfigurationValueFlags.Default, new PropertySourceInfo(reader));
+ break;
+ case LockElementsKey:
+ lockedElementList = new ConfigurationValue(reader.Value,
+ ConfigurationValueFlags.Default, new PropertySourceInfo(reader));
+ break;
+ case LockAllElementsExceptKey:
+ lockedAllElementsExceptList = new ConfigurationValue(reader.Value,
+ ConfigurationValueFlags.Default, new PropertySourceInfo(reader));
+ break;
+ default:
+ if (serializeCollectionKey ||
+ !OnDeserializeUnrecognizedAttribute(propertyName, reader.Value))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_unrecognized_attribute, propertyName),
+ reader);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ reader.MoveToElement();
+
+ // Check for nested elements.
+ try
+ {
+ HybridDictionary nodeFound = new HybridDictionary();
+ if (!reader.IsEmptyElement)
+ {
+ while (reader.Read())
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ string propertyName = reader.Name;
+
+ CheckLockedElement(propertyName, null);
+
+ ConfigurationProperty prop = props?[propertyName];
+ if (prop != null)
+ {
+ if (prop.IsConfigurationElementType)
+ {
+ // TODO: Check for duplicates.
+ if (nodeFound.Contains(propertyName))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_element_cannot_have_multiple_child_elements,
+ propertyName), reader);
+ }
+
+ nodeFound.Add(propertyName, propertyName);
+ ConfigurationElement childElement = (ConfigurationElement)this[prop];
+ childElement.DeserializeElement(reader, serializeCollectionKey);
+
+ // Validate the new element with the per-property Validator
+ // Note that the per-type validator for childElement has been already executed as part of Deserialize
+ ValidateElement(childElement, prop.Validator, false);
+ }
+ else
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_property_is_not_a_configuration_element,
+ propertyName), reader);
+ }
+ }
+ else
+ {
+ if (!OnDeserializeUnrecognizedElement(propertyName, reader))
+ {
+ // Let the default collection, if there is one, handle this node.
+ if ((defaultCollection == null) ||
+ !defaultCollection.OnDeserializeUnrecognizedElement(propertyName, reader))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_unrecognized_element_name, propertyName), reader);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (reader.NodeType == XmlNodeType.EndElement) break;
+
+ if ((reader.NodeType == XmlNodeType.CDATA) || (reader.NodeType == XmlNodeType.Text))
+ {
+ throw new ConfigurationErrorsException(
+ SR.Config_base_section_invalid_content, reader);
+ }
+ }
+ }
+
+ EnsureRequiredProperties(serializeCollectionKey);
+
+ // Call the per-type validator for this object
+ ValidateElement(this, null, false);
+ }
+ catch (ConfigurationException e)
+ {
+ // Catch the generic message from deserialization and include line info if necessary
+ if ((e.Filename == null) || (e.Filename.Length == 0))
+ throw new ConfigurationErrorsException(e.Message, reader); // give it some info
+
+ throw;
+ }
+
+ if (itemLockedLocally)
+ {
+ SetLocked();
+ _fItemLocked = ConfigurationValueFlags.Locked;
+ }
+
+ if (lockedAttributesList != null)
+ {
+ if (_lockedAttributesList == null)
+ {
+ _lockedAttributesList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedAttributes);
+ }
+ foreach (
+ string key in
+ ParseLockedAttributes(lockedAttributesList, ConfigurationLockCollectionType.LockedAttributes))
+ if (!_lockedAttributesList.Contains(key))
+ _lockedAttributesList.Add(key, ConfigurationValueFlags.Default); // add the local copy
+ else
+ {
+ _lockedAttributesList.Add(key,
+ ConfigurationValueFlags.Modified | ConfigurationValueFlags.Inherited); // add the local copy
+ }
+ }
+
+ if (lockedAllExceptList != null)
+ {
+ ConfigurationLockCollection newCollection = ParseLockedAttributes(lockedAllExceptList,
+ ConfigurationLockCollectionType.LockedExceptionList);
+ if (_lockedAllExceptAttributesList == null)
+ {
+ // Prevent the list from thinking this was set by a parent.
+ _lockedAllExceptAttributesList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedExceptionList, string.Empty, newCollection);
+ _lockedAllExceptAttributesList.ClearSeedList();
+ }
+
+ StringCollection intersectionCollection = IntersectLockCollections(_lockedAllExceptAttributesList,
+ newCollection);
+
+ _lockedAllExceptAttributesList.ClearInternal(false);
+ foreach (string key in intersectionCollection)
+ _lockedAllExceptAttributesList.Add(key, ConfigurationValueFlags.Default);
+ }
+
+ if (lockedElementList != null)
+ {
+ if (_lockedElementsList == null)
+ {
+ _lockedElementsList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedElements);
+ }
+
+ ConfigurationLockCollection localLockedElementList = ParseLockedAttributes(lockedElementList,
+ ConfigurationLockCollectionType.LockedElements);
+
+ if (props.DefaultCollectionProperty != null)
+ // this is not a collection but it may contain a default collection
+ {
+ ConfigurationElementCollection collection = this[props.DefaultCollectionProperty] as ConfigurationElementCollection;
+ if ((collection != null) && (collection._lockedElementsList == null))
+ collection._lockedElementsList = _lockedElementsList;
+ }
+
+ foreach (string key in localLockedElementList)
+ if (!_lockedElementsList.Contains(key))
+ {
+ _lockedElementsList.Add(key, ConfigurationValueFlags.Default); // add the local copy
+
+ ConfigurationProperty propToLock = Properties[key];
+ if ((propToLock != null) && typeof(ConfigurationElement).IsAssignableFrom(propToLock.Type))
+ ((ConfigurationElement)this[key]).SetLocked();
+ if (key == LockAll)
+ {
+ foreach (ConfigurationProperty prop in Properties)
+ if (!string.IsNullOrEmpty(prop.Name) &&
+ prop.IsConfigurationElementType)
+ ((ConfigurationElement)this[prop]).SetLocked();
+ }
+ }
+ }
+
+ if (lockedAllElementsExceptList != null)
+ {
+ ConfigurationLockCollection newCollection = ParseLockedAttributes(lockedAllElementsExceptList,
+ ConfigurationLockCollectionType.LockedElementsExceptionList);
+ if (_lockedAllExceptElementsList == null)
+ {
+ _lockedAllExceptElementsList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedElementsExceptionList, ElementTagName, newCollection);
+ _lockedAllExceptElementsList.ClearSeedList();
+ }
+
+ StringCollection intersectionCollection = IntersectLockCollections(_lockedAllExceptElementsList,
+ newCollection);
+
+ if (props.DefaultCollectionProperty != null)
+ {
+ // this is not a collection but it may contain a default collection
+ ConfigurationElementCollection collection = this[props.DefaultCollectionProperty] as ConfigurationElementCollection;
+ if ((collection != null) && (collection._lockedAllExceptElementsList == null))
+ collection._lockedAllExceptElementsList = _lockedAllExceptElementsList;
+ }
+
+ _lockedAllExceptElementsList.ClearInternal(false);
+ foreach (string key in intersectionCollection)
+ if (!_lockedAllExceptElementsList.Contains(key) || (key == ElementTagName))
+ _lockedAllExceptElementsList.Add(key, ConfigurationValueFlags.Default); // add the local copy
+
+ foreach (ConfigurationProperty prop in Properties)
+ if (!(string.IsNullOrEmpty(prop.Name) || _lockedAllExceptElementsList.Contains(prop.Name)) &&
+ prop.IsConfigurationElementType)
+ ((ConfigurationElement)this[prop]).SetLocked();
+ }
+
+ // Make sure default collections use the same lock element lists
+ if (defaultCollectionProperty != null)
+ {
+ defaultCollection = (ConfigurationElement)this[defaultCollectionProperty];
+ if (_lockedElementsList == null)
+ {
+ _lockedElementsList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedElements);
+ }
+ defaultCollection._lockedElementsList = _lockedElementsList;
+ if (_lockedAllExceptElementsList == null)
+ {
+ _lockedAllExceptElementsList = new ConfigurationLockCollection(this,
+ ConfigurationLockCollectionType.LockedElementsExceptionList, reader.Name);
+ _lockedAllExceptElementsList.ClearSeedList();
+ }
+ defaultCollection._lockedAllExceptElementsList = _lockedAllExceptElementsList;
+ }
+
+ // This has to be the last thing to execute
+ PostDeserialize();
+ }
+
+ private object DeserializePropertyValue(ConfigurationProperty prop, XmlReader reader)
+ {
+ Debug.Assert(prop != null, "prop != null");
+ Debug.Assert(reader != null, "reader != null");
+
+ // By default we try to load (i.e. parse/validate ) all properties
+ // If a property value is invalid ( cannot be parsed or is not valid ) we will keep the value
+ // as string ( from the xml ) and will write it out unchanged if needed
+ // If the property value is needed by users the actuall exception will be thrown
+
+ string xmlValue = reader.Value;
+ object propertyValue = null;
+
+ try
+ {
+ propertyValue = prop.ConvertFromString(xmlValue);
+
+ // Validate the loaded and converted value
+ prop.Validate(propertyValue);
+ }
+ catch (ConfigurationException ce)
+ {
+ // If the error is incomplete - complete it :)
+ if (string.IsNullOrEmpty(ce.Filename)) ce = new ConfigurationErrorsException(ce.Message, reader);
+
+ // Cannot parse/validate the value. Keep it as string
+ propertyValue = new InvalidPropValue(xmlValue, ce);
+ }
+ catch
+ {
+ // If this is an exception related to the parsing/validating the
+ // value ConfigurationErrorsException should be thrown instead.
+ // If not - the exception is ok to surface out of here
+ Debug.Fail("Unknown exception type thrown");
+ }
+
+ return propertyValue;
+ }
+
+ internal static void ValidateElement(ConfigurationElement elem, ConfigurationValidatorBase propValidator,
+ bool recursive)
+ {
+ // Validate a config element with the per-type validator when a per-property ( propValidator ) is not supplied
+ // or with the per-prop validator when the element ( elem ) is a child property of another configuration element
+
+ ConfigurationValidatorBase validator = propValidator;
+
+ if ((validator == null) && // Not a property - use the per-type validator
+ (elem.ElementProperty != null))
+ {
+ validator = elem.ElementProperty.Validator;
+
+ // Since ElementProperty can be overriden by derived classes we need to make sure that
+ // the validator supports the type of elem every time
+ if ((validator != null) && !validator.CanValidate(elem.GetType()))
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Validator_does_not_support_elem_type,
+ elem.GetType().Name));
+ }
+ }
+
+ try
+ {
+ validator?.Validate(elem);
+ }
+ catch (ConfigurationException)
+ {
+ // ConfigurationElement validators are allowed to throw ConfigurationErrorsException.
+ throw;
+ }
+ catch (Exception ex)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Validator_element_not_valid, elem.ElementTagName,
+ ex.Message));
+ }
+
+ if (recursive)
+ {
+ // Validate collection items:
+ // Note: this is a bit of a hack - we will exploit the fact that this method is called with recursive == true only when serializing the top level section
+ // At deserializtion time the per-element validator for collection items will get executed as part of their deserialization logic
+ // However we dont perform validation in the serialization logic ( because at that time the object is unmerged and not all data is present )
+ // so we have to do that validation here.
+ if (elem is ConfigurationElementCollection)
+ {
+ IEnumerator it = ((ConfigurationElementCollection)elem).GetElementsEnumerator();
+ while (it.MoveNext()) ValidateElement((ConfigurationElement)it.Current, null, true);
+ }
+
+ // Validate all child elements recursively
+ for (int index = 0; index < elem.Values.Count; index++)
+ {
+ ConfigurationElement value = elem.Values[index] as ConfigurationElement;
+
+ if (value != null)
+ {
+ // Run the per-type validator on the child element and proceed with validation in subelements
+ // Note we dont run the per-property validator here since we run those when the property value is set
+ ValidateElement(value, null, true); // per-type
+ }
+ }
+ }
+ }
+
+ private void EnsureRequiredProperties(bool ensureKeysOnly)
+ {
+ ConfigurationPropertyCollection props = Properties;
+
+ // Make sure all required properties are here
+ if (props != null)
+ {
+ foreach (ConfigurationProperty prop in props)
+ if (prop.IsRequired && !Values.Contains(prop.Name))
+ {
+ // Required properties can be ommited when we need only the keys to be there
+ if (!ensureKeysOnly || prop.IsKey) Values[prop.Name] = OnRequiredPropertyNotFound(prop.Name);
+ }
+ }
+ }
+
+ protected virtual object OnRequiredPropertyNotFound(string name)
+ {
+ // Derivied classes can override this to return a value for a required property that is missing
+ // Here we treat this as an error though
+
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_required_attribute_missing, name),
+ PropertyFileName(name),
+ PropertyLineNumber(name));
+ }
+
+ protected virtual void PostDeserialize()
+ {
+ // Please try to not add code in here
+ }
+
+ protected virtual void PreSerialize(XmlWriter writer)
+ {
+ // Please try to not add code in here
+ }
+
+ protected virtual bool OnDeserializeUnrecognizedAttribute(string name, string value)
+ {
+ return false;
+ }
+
+ protected virtual bool OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)
+ {
+ return false;
+ }
+
+ protected virtual string GetTransformedTypeString(string typeName)
+ {
+ if ((typeName == null) || (_configRecord == null) || !_configRecord.TypeStringTransformerIsSet)
+ return typeName;
+
+ return _configRecord.TypeStringTransformer(typeName);
+ }
+
+ protected virtual string GetTransformedAssemblyString(string assemblyName)
+ {
+ if ((assemblyName == null) || (_configRecord == null) || !_configRecord.AssemblyStringTransformerIsSet)
+ return assemblyName;
+
+ return _configRecord.AssemblyStringTransformer(assemblyName);
+ }
+
+ internal ConfigurationLockCollection UnMergeLockList(
+ ConfigurationLockCollection sourceLockList,
+ ConfigurationLockCollection parentLockList,
+ ConfigurationSaveMode saveMode)
+ {
+ if (sourceLockList.ExceptionList == false)
+ {
+ switch (saveMode)
+ {
+ case ConfigurationSaveMode.Modified:
+ {
+ ConfigurationLockCollection tempLockList = new ConfigurationLockCollection(this,
+ sourceLockList.LockType);
+ foreach (string lockedAttributeName in sourceLockList)
+ if (!parentLockList.Contains(lockedAttributeName) ||
+ sourceLockList.IsValueModified(lockedAttributeName))
+ tempLockList.Add(lockedAttributeName, ConfigurationValueFlags.Default);
+ return tempLockList;
+ }
+ case ConfigurationSaveMode.Minimal:
+ {
+ ConfigurationLockCollection tempLockList = new ConfigurationLockCollection(this,
+ sourceLockList.LockType);
+ foreach (string lockedAttributeName in sourceLockList)
+ if (!parentLockList.Contains(lockedAttributeName))
+ tempLockList.Add(lockedAttributeName, ConfigurationValueFlags.Default);
+ return tempLockList;
+ }
+ }
+ }
+ else
+ {
+ // exception list write out the entire collection unless the entire collection
+ // came from the parent.
+ if ((saveMode == ConfigurationSaveMode.Modified) || (saveMode == ConfigurationSaveMode.Minimal))
+ {
+ bool sameAsParent = false;
+ if (sourceLockList.Count == parentLockList.Count)
+ {
+ sameAsParent = true;
+ foreach (string lockedAttributeName in sourceLockList)
+ if (!parentLockList.Contains(lockedAttributeName) ||
+ (sourceLockList.IsValueModified(lockedAttributeName) &&
+ (saveMode == ConfigurationSaveMode.Modified)))
+ sameAsParent = false;
+ }
+ if (sameAsParent) return null;
+ }
+ }
+ return sourceLockList;
+ }
+
+ // Return true if an attribute is one of our reserved locking attributes,
+ // false otherwise.
+ internal static bool IsLockAttributeName(string name)
+ {
+ // optimize for common case that attribute name does not start with "lock"
+ if (!StringUtil.StartsWithOrdinal(name, "lock")) return false;
+
+ foreach (string lockAttributeName in s_lockAttributeNames) if (name == lockAttributeName) return true;
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationElementCollection.cs b/src/System.Configuration/src/System/Configuration/ConfigurationElementCollection.cs
new file mode 100644
index 0000000000..991dc0798e
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationElementCollection.cs
@@ -0,0 +1,1298 @@
+// 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.Xml;
+
+namespace System.Configuration
+{
+ [DebuggerDisplay("Count = {Count}")]
+ public abstract class ConfigurationElementCollection : ConfigurationElement, ICollection
+ {
+ internal const string DefaultAddItemName = "add";
+ internal const string DefaultRemoveItemName = "remove";
+ internal const string DefaultClearItemsName = "clear";
+ private readonly IComparer _comparer;
+ private string _addElement = DefaultAddItemName;
+ private string _clearElement = DefaultClearItemsName;
+ private bool _collectionCleared;
+ private bool _emitClearTag;
+ private int _inheritedCount; // Total number of inherited items
+ private bool _modified;
+ private bool _readOnly;
+
+ private int _removedItemCount; // Number of items removed for this collection (not including parent)
+ private string _removeElement = DefaultRemoveItemName;
+ internal bool InternalAddToEnd = false;
+ internal string InternalElementTagName = string.Empty;
+
+ protected ConfigurationElementCollection() { }
+
+ protected ConfigurationElementCollection(IComparer comparer)
+ {
+ if (comparer == null) throw new ArgumentNullException(nameof(comparer));
+
+ _comparer = comparer;
+ }
+
+ private ArrayList Items { get; } = new ArrayList();
+
+ protected internal string AddElementName
+ {
+ get { return _addElement; }
+ set
+ {
+ _addElement = value;
+ if (BaseConfigurationRecord.IsReservedAttributeName(value))
+ throw new ArgumentException(string.Format(SR.Item_name_reserved, DefaultAddItemName, value));
+ }
+ }
+
+ protected internal string RemoveElementName
+ {
+ get { return _removeElement; }
+ set
+ {
+ if (BaseConfigurationRecord.IsReservedAttributeName(value))
+ throw new ArgumentException(string.Format(SR.Item_name_reserved, DefaultRemoveItemName, value));
+ _removeElement = value;
+ }
+ }
+
+ protected internal string ClearElementName
+ {
+ get { return _clearElement; }
+ set
+ {
+ if (BaseConfigurationRecord.IsReservedAttributeName(value))
+ throw new ArgumentException(string.Format(SR.Item_name_reserved, DefaultClearItemsName, value));
+ _clearElement = value;
+ }
+ }
+
+ public bool EmitClear
+ {
+ get { return _emitClearTag; }
+ set
+ {
+ if (IsReadOnly()) throw new ConfigurationErrorsException(SR.Config_base_read_only);
+ if (value)
+ {
+ CheckLockedElement(_clearElement, null); // has clear been locked?
+ CheckLockedElement(_removeElement, null); // has remove been locked? Clear implies remove
+ }
+ _modified = true;
+ _emitClearTag = value;
+ }
+ }
+
+ protected virtual string ElementName => "";
+
+ internal string LockableElements
+ {
+ get
+ {
+ if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ string elementNames = "'" + AddElementName + "'"; // Must have an add
+ if (RemoveElementName.Length != 0)
+ elementNames += ", '" + RemoveElementName + "'";
+ if (ClearElementName.Length != 0)
+ elementNames += ", '" + ClearElementName + "'";
+ return elementNames;
+ }
+
+ if (!string.IsNullOrEmpty(ElementName)) return "'" + ElementName + "'";
+ return string.Empty;
+ }
+ }
+
+ protected virtual bool ThrowOnDuplicate
+ => (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate);
+
+ public virtual ConfigurationElementCollectionType CollectionType
+ => ConfigurationElementCollectionType.AddRemoveClearMap;
+
+ public int Count => Items.Count - _removedItemCount;
+
+ public bool IsSynchronized => false;
+
+ public object SyncRoot => null;
+
+ void ICollection.CopyTo(Array arr, int index)
+ {
+ foreach (Entry entry in Items)
+ if (entry.EntryType != EntryType.Removed) arr.SetValue(entry.Value, index++);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return GetEnumeratorImpl();
+ }
+
+ internal override void AssociateContext(BaseConfigurationRecord configRecord)
+ {
+ base.AssociateContext(configRecord);
+
+ foreach (Entry entry in Items)
+ entry.Value?.AssociateContext(configRecord);
+ }
+
+ protected internal override bool IsModified()
+ {
+ if (_modified) return true;
+
+ if (base.IsModified()) return true;
+
+ foreach (Entry entry in Items)
+ {
+ if (entry.EntryType == EntryType.Removed) continue;
+
+ ConfigurationElement elem = entry.Value;
+ if (elem.IsModified()) return true;
+ }
+
+ return false;
+ }
+
+ protected internal override void ResetModified()
+ {
+ _modified = false;
+ base.ResetModified();
+
+ foreach (Entry entry in Items)
+ {
+ if (entry.EntryType == EntryType.Removed) continue;
+
+ ConfigurationElement elem = entry.Value;
+ elem.ResetModified();
+ }
+ }
+
+ public override bool IsReadOnly()
+ {
+ return _readOnly;
+ }
+
+ protected internal override void SetReadOnly()
+ {
+ _readOnly = true;
+ foreach (Entry entry in Items)
+ {
+ if (entry.EntryType == EntryType.Removed) continue;
+
+ ConfigurationElement elem = entry.Value;
+ elem.SetReadOnly();
+ }
+ }
+
+ internal virtual IEnumerator GetEnumeratorImpl()
+ {
+ return new Enumerator(Items, this);
+ }
+
+ internal IEnumerator GetElementsEnumerator()
+ {
+ // Return an enumerator over the collection's config elements.
+ // This is different then the std GetEnumerator because the second one
+ // can return different set of items if overriden in a derived class
+
+ return new Enumerator(Items, this);
+ }
+
+ public override bool Equals(object compareTo)
+ {
+ if (compareTo.GetType() != GetType()) return false;
+
+ ConfigurationElementCollection compareToElem = (ConfigurationElementCollection)compareTo;
+ if (Count != compareToElem.Count) return false;
+
+ foreach (Entry thisEntry in Items)
+ {
+ bool found = false;
+ foreach (Entry compareEntry in compareToElem.Items)
+ {
+ if (!Equals(thisEntry.Value, compareEntry.Value)) continue;
+ found = true;
+ break;
+ }
+
+ if (found == false)
+ {
+ // not in the collection must be different
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ int hHashCode = 0;
+ foreach (Entry thisEntry in Items)
+ {
+ ConfigurationElement elem = thisEntry.Value;
+ hHashCode ^= elem.GetHashCode();
+ }
+ return hHashCode;
+ }
+
+
+ protected internal override void Unmerge(ConfigurationElement sourceElement,
+ ConfigurationElement parentElement,
+ ConfigurationSaveMode saveMode)
+ {
+ base.Unmerge(sourceElement, parentElement, saveMode);
+ if (sourceElement == null) return;
+
+ ConfigurationElementCollection parentCollection = parentElement as ConfigurationElementCollection;
+ ConfigurationElementCollection sourceCollection = sourceElement as ConfigurationElementCollection;
+ Hashtable inheritance = new Hashtable();
+ _lockedAllExceptAttributesList = sourceElement._lockedAllExceptAttributesList;
+ _lockedAllExceptElementsList = sourceElement._lockedAllExceptElementsList;
+ _fItemLocked = sourceElement._fItemLocked;
+ _lockedAttributesList = sourceElement._lockedAttributesList;
+ _lockedElementsList = sourceElement._lockedElementsList;
+
+ AssociateContext(sourceElement._configRecord);
+
+ if (parentElement != null)
+ {
+ if (parentElement._lockedAttributesList != null)
+ {
+ _lockedAttributesList = UnMergeLockList(sourceElement._lockedAttributesList,
+ parentElement._lockedAttributesList, saveMode);
+ }
+ if (parentElement._lockedElementsList != null)
+ {
+ _lockedElementsList = UnMergeLockList(sourceElement._lockedElementsList,
+ parentElement._lockedElementsList, saveMode);
+ }
+ if (parentElement._lockedAllExceptAttributesList != null)
+ {
+ _lockedAllExceptAttributesList = UnMergeLockList(sourceElement._lockedAllExceptAttributesList,
+ parentElement._lockedAllExceptAttributesList, saveMode);
+ }
+ if (parentElement._lockedAllExceptElementsList != null)
+ {
+ _lockedAllExceptElementsList = UnMergeLockList(sourceElement._lockedAllExceptElementsList,
+ parentElement._lockedAllExceptElementsList, saveMode);
+ }
+ }
+
+ if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ // When writing out portable configurations the <clear/> tag should be written
+ _collectionCleared = sourceCollection._collectionCleared;
+ EmitClear = ((saveMode == ConfigurationSaveMode.Full) && (_clearElement.Length != 0)) ||
+ ((saveMode == ConfigurationSaveMode.Modified) && _collectionCleared) || sourceCollection.EmitClear;
+
+ if ((parentCollection != null) && (EmitClear != true))
+ {
+ foreach (Entry entry in parentCollection.Items)
+ if (entry.EntryType != EntryType.Removed)
+ inheritance[entry.GetKey(this)] = InheritedType.InParent;
+ }
+
+ foreach (Entry entry in sourceCollection.Items)
+ {
+ if (entry.EntryType == EntryType.Removed) continue;
+
+ if (inheritance.Contains(entry.GetKey(this)))
+ {
+ Entry parentEntry =
+ (Entry)parentCollection.Items[parentCollection.RealIndexOf(entry.Value)];
+
+ ConfigurationElement elem = entry.Value;
+ if (elem.Equals(parentEntry.Value))
+ {
+ // in modified mode we consider any change to be different than the parent
+ inheritance[entry.GetKey(this)] = InheritedType.InBothSame;
+ if (saveMode != ConfigurationSaveMode.Modified) continue;
+
+ if (elem.IsModified())
+ inheritance[entry.GetKey(this)] = InheritedType.InBothDiff;
+ else
+ {
+ if (elem.ElementPresent)
+ {
+ // This is when the source file contained the entry but it was an
+ // exact copy. We don't want to emit a remove so we treat it as
+ // a special case.
+ inheritance[entry.GetKey(this)] = InheritedType.InBothCopyNoRemove;
+ }
+ }
+ }
+ else
+ {
+ inheritance[entry.GetKey(this)] = InheritedType.InBothDiff;
+ if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate)
+ && (entry.EntryType == EntryType.Added))
+ {
+ // this is a special case for deailing with defect number 529517
+ // this code allow the config to write out the same xml when no remove was
+ // present during deserialization.
+ inheritance[entry.GetKey(this)] = InheritedType.InBothCopyNoRemove;
+ }
+ }
+ }
+ else
+ {
+ // not in parent
+ inheritance[entry.GetKey(this)] = InheritedType.InSelf;
+ }
+ }
+
+ if ((parentCollection != null) && (EmitClear != true))
+ {
+ foreach (Entry entry in parentCollection.Items)
+ {
+ if (entry.EntryType == EntryType.Removed) continue;
+ InheritedType tp = (InheritedType)inheritance[entry.GetKey(this)];
+ if ((tp != InheritedType.InParent) && (tp != InheritedType.InBothDiff)) continue;
+ ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
+
+ elem.Reset(entry.Value); // copy this entry
+ BaseAdd(elem, ThrowOnDuplicate, true);
+ // Add it (so that is once existed in the temp
+ BaseRemove(entry.GetKey(this), false); // now remove it to for a remove instruction
+ }
+ }
+
+ foreach (Entry entry in sourceCollection.Items)
+ {
+ if (entry.EntryType == EntryType.Removed) continue;
+ InheritedType tp = (InheritedType)inheritance[entry.GetKey(this)];
+
+ if ((tp != InheritedType.InSelf) && (tp != InheritedType.InBothDiff) &&
+ (tp != InheritedType.InBothCopyNoRemove))
+ continue;
+ ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
+
+ elem.Unmerge(entry.Value, null, saveMode);
+
+ if (tp == InheritedType.InSelf)
+ elem.RemoveAllInheritedLocks(); // If the key changed only local locks are kept
+
+ BaseAdd(elem, ThrowOnDuplicate, true); // Add it
+ }
+ }
+ else
+ {
+ if ((CollectionType != ConfigurationElementCollectionType.BasicMap) &&
+ (CollectionType != ConfigurationElementCollectionType.BasicMapAlternate))
+ return;
+
+ foreach (Entry entry in sourceCollection.Items)
+ {
+ bool foundKeyInParent = false;
+ Entry parentEntrySaved = null;
+
+ if ((entry.EntryType != EntryType.Added) && (entry.EntryType != EntryType.Replaced)) continue;
+ bool inParent = false;
+
+ if (parentCollection != null)
+ {
+ foreach (Entry parentEntry in parentCollection.Items)
+ {
+ if (Equals(entry.GetKey(this), parentEntry.GetKey(this)))
+ {
+ // for basic map collection where the key is actually an element
+ // we do not want the merging behavior or data will not get written
+ // out for the properties if they match the first element deamed to be a parent
+ // For example <allow verbs="NewVerb" users="*"/> will loose the users because
+ // an entry exists in the root element.
+ if (!IsElementName(entry.GetKey(this).ToString()))
+ {
+ // For elements which are not keyed by the element name
+ // need to be unmerged
+ foundKeyInParent = true;
+ parentEntrySaved = parentEntry;
+ }
+ }
+
+ if (!Equals(entry.Value, parentEntry.Value)) continue;
+
+ foundKeyInParent = true;
+ inParent = true; // in parent and the same exact values
+ parentEntrySaved = parentEntry;
+ break;
+ }
+ }
+
+ ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
+
+ if (!foundKeyInParent)
+ {
+ // Unmerge is similar to a reset when used like this
+ // except that it handles the different update modes
+ // which Reset does not understand
+ elem.Unmerge(entry.Value, null, saveMode); // copy this entry
+ BaseAdd(-1, elem, true); // Add it
+ }
+ else
+ {
+ ConfigurationElement sourceItem = entry.Value;
+ if (inParent && ((saveMode != ConfigurationSaveMode.Modified) || !sourceItem.IsModified()) &&
+ (saveMode != ConfigurationSaveMode.Full))
+ continue;
+
+ elem.Unmerge(entry.Value, parentEntrySaved.Value, saveMode);
+ BaseAdd(-1, elem, true); // Add it
+ }
+ }
+ }
+ }
+
+ protected internal override void Reset(ConfigurationElement parentElement)
+ {
+ ConfigurationElementCollection parentCollection = parentElement as ConfigurationElementCollection;
+ ResetLockLists(parentElement);
+
+ if (parentCollection != null)
+ {
+ foreach (Entry entry in parentCollection.Items)
+ {
+ ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
+ elem.Reset(entry.Value);
+
+ if (((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate)) &&
+ ((entry.EntryType == EntryType.Added) ||
+ (entry.EntryType == EntryType.Replaced)))
+ {
+ // do not add removed items from the parent
+ BaseAdd(elem, true, true); // This version combines dups and throws (unless overridden)
+ }
+ else
+ {
+ if ((CollectionType == ConfigurationElementCollectionType.BasicMap) ||
+ (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate))
+ BaseAdd(-1, elem, true); // this version appends regardless of if it is a dup.
+ }
+ }
+ _inheritedCount = Count; // After reset the count is the number of items actually inherited.
+ }
+ }
+
+ public void CopyTo(ConfigurationElement[] array, int index)
+ {
+ ((ICollection)this).CopyTo(array, index);
+ }
+
+ protected virtual void BaseAdd(ConfigurationElement element)
+ {
+ BaseAdd(element, ThrowOnDuplicate);
+ }
+
+ protected internal void BaseAdd(ConfigurationElement element, bool throwIfExists)
+ {
+ BaseAdd(element, throwIfExists, false);
+ }
+
+ private void BaseAdd(ConfigurationElement element, bool throwIfExists, bool ignoreLocks)
+ {
+ bool flagAsReplaced = false;
+ bool localAddToEnd = InternalAddToEnd;
+
+ if (IsReadOnly()) throw new ConfigurationErrorsException(SR.Config_base_read_only);
+
+ if (LockItem && (ignoreLocks == false))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_element_locked, _addElement));
+
+ object key = GetElementKeyInternal(element);
+ int iFoundItem = -1;
+ for (int index = 0; index < Items.Count; index++)
+ {
+ Entry entry = (Entry)Items[index];
+ if (!CompareKeys(key, entry.GetKey(this))) continue;
+
+ if ((entry.Value != null) && entry.Value.LockItem && (ignoreLocks == false))
+ throw new ConfigurationErrorsException(SR.Config_base_collection_item_locked);
+
+ if ((entry.EntryType != EntryType.Removed) && throwIfExists)
+ {
+ if (!element.Equals(entry.Value))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_collection_entry_already_exists, key),
+ element.PropertyFileName(""), element.PropertyLineNumber(""));
+ }
+
+ entry.Value = element;
+ return;
+ }
+
+ if (entry.EntryType != EntryType.Added)
+ {
+ if (((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate)) &&
+ (entry.EntryType == EntryType.Removed) &&
+ (_removedItemCount > 0))
+ _removedItemCount--; // account for the value
+ entry.EntryType = EntryType.Replaced;
+ flagAsReplaced = true;
+ }
+
+ if (localAddToEnd ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ iFoundItem = index;
+ if (entry.EntryType == EntryType.Added)
+ {
+ // this is a special case for defect number 529517 to emulate everett behavior
+ localAddToEnd = true;
+ }
+ break;
+ }
+
+ // check to see if the element is trying to set a locked property.
+ if (ignoreLocks == false)
+ {
+ element.HandleLockedAttributes(entry.Value);
+ // copy the lock from the removed element before setting the new element
+ element.MergeLocks(entry.Value);
+ }
+
+ entry.Value = element;
+ _modified = true;
+ return;
+ }
+
+ // Brand new item.
+ if (iFoundItem >= 0)
+ {
+ Items.RemoveAt(iFoundItem);
+
+ // if the item being removed was inherited adjust the cout
+ if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) &&
+ (iFoundItem > Count + _removedItemCount - _inheritedCount))
+ _inheritedCount--;
+ }
+ BaseAddInternal(localAddToEnd ? -1 : iFoundItem, element, flagAsReplaced, ignoreLocks);
+ _modified = true;
+ }
+
+ protected int BaseIndexOf(ConfigurationElement element)
+ {
+ int index = 0;
+ object key = GetElementKeyInternal(element);
+ foreach (Entry entry in Items)
+ {
+ if (entry.EntryType == EntryType.Removed) continue;
+ if (CompareKeys(key, entry.GetKey(this))) return index;
+ index++;
+ }
+ return -1;
+ }
+
+ internal int RealIndexOf(ConfigurationElement element)
+ {
+ int index = 0;
+ object key = GetElementKeyInternal(element);
+ foreach (Entry entry in Items)
+ {
+ if (CompareKeys(key, entry.GetKey(this))) return index;
+ index++;
+ }
+ return -1;
+ }
+
+ private void BaseAddInternal(int index, ConfigurationElement element, bool flagAsReplaced, bool ignoreLocks)
+ {
+ // Allow the element to initialize itself after its
+ // constructor has been run so that it may access
+ // virtual methods.
+
+ element.AssociateContext(_configRecord);
+ element.CallInit();
+
+ if (IsReadOnly()) throw new ConfigurationErrorsException(SR.Config_base_read_only);
+
+ if (!ignoreLocks)
+ {
+ // during reset we ignore locks so we can copy the elements
+ if ((CollectionType == ConfigurationElementCollectionType.BasicMap) ||
+ (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate))
+ {
+ if (BaseConfigurationRecord.IsReservedAttributeName(ElementName))
+ throw new ArgumentException(string.Format(SR.Basicmap_item_name_reserved, ElementName));
+ CheckLockedElement(ElementName, null);
+ }
+
+ if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ CheckLockedElement(_addElement, null);
+ }
+
+ if ((CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ if (index == -1)
+ {
+ // insert before inherited, but after any removed
+ index = Count + _removedItemCount - _inheritedCount;
+ }
+ else
+ {
+ if ((index > Count + _removedItemCount - _inheritedCount) && (flagAsReplaced == false))
+ throw new ConfigurationErrorsException(SR.Config_base_cannot_add_items_below_inherited_items);
+ }
+ }
+
+ if ((CollectionType == ConfigurationElementCollectionType.BasicMap) &&
+ (index >= 0) &&
+ (index < _inheritedCount))
+ throw new ConfigurationErrorsException(SR.Config_base_cannot_add_items_above_inherited_items);
+
+ EntryType entryType = flagAsReplaced == false ? EntryType.Added : EntryType.Replaced;
+
+ object key = GetElementKeyInternal(element);
+
+ if (index >= 0)
+ {
+ if (index > Items.Count)
+ throw new ConfigurationErrorsException(string.Format(SR.IndexOutOfRange, index));
+ Items.Insert(index, new Entry(entryType, key, element));
+ }
+ else
+ Items.Add(new Entry(entryType, key, element));
+
+ _modified = true;
+ }
+
+
+ protected virtual void BaseAdd(int index, ConfigurationElement element)
+ {
+ BaseAdd(index, element, false);
+ }
+
+ private void BaseAdd(int index, ConfigurationElement element, bool ignoreLocks)
+ {
+ if (IsReadOnly()) throw new ConfigurationErrorsException(SR.Config_base_read_only);
+ if (index < -1) throw new ConfigurationErrorsException(string.Format(SR.IndexOutOfRange, index));
+
+ if ((index != -1) &&
+ ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate)))
+ {
+ // If it's an AddRemoveClearMap*** collection, turn the index passed into into a real internal index
+ int realIndex = 0;
+
+ if (index > 0)
+ {
+ foreach (Entry entryfound in Items)
+ {
+ if (entryfound.EntryType != EntryType.Removed) index--;
+ if (index == 0) break;
+ realIndex++;
+ }
+ index = ++realIndex;
+ }
+
+ // check for duplicates
+ object key = GetElementKeyInternal(element);
+ foreach (Entry entry in Items)
+ {
+ if (!CompareKeys(key, entry.GetKey(this))
+ || (entry.EntryType == EntryType.Removed))
+ continue;
+
+ if (!element.Equals(entry.Value))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_collection_entry_already_exists, key),
+ element.PropertyFileName(""), element.PropertyLineNumber(""));
+ }
+
+ return;
+ }
+ }
+
+ BaseAddInternal(index, element, false, ignoreLocks);
+ }
+
+ protected internal void BaseRemove(object key)
+ {
+ BaseRemove(key, false);
+ }
+
+ private void BaseRemove(object key, bool throwIfMissing)
+ {
+ if (IsReadOnly())
+ throw new ConfigurationErrorsException(SR.Config_base_read_only);
+
+ int index = 0;
+ foreach (Entry entry in Items)
+ {
+ if (CompareKeys(key, entry.GetKey(this)))
+ {
+ if (entry.Value == null) // A phoney delete is already present
+ {
+ if (throwIfMissing)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_collection_entry_not_found, key));
+ }
+ return;
+ }
+
+ if (entry.Value.LockItem)
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_attribute_locked, key));
+
+ if (entry.Value.ElementPresent == false)
+ CheckLockedElement(_removeElement, null); // has remove been locked?
+
+ switch (entry.EntryType)
+ {
+ case EntryType.Added:
+ if ((CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap) &&
+ (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate)
+ {
+ if (index >= Count - _inheritedCount)
+ {
+ throw new ConfigurationErrorsException(
+ SR.Config_base_cannot_remove_inherited_items);
+ }
+ }
+ if (CollectionType == ConfigurationElementCollectionType.BasicMap)
+ {
+ if (index < _inheritedCount)
+ {
+ throw new ConfigurationErrorsException(
+ SR.Config_base_cannot_remove_inherited_items);
+ }
+ }
+
+ Items.RemoveAt(index);
+ }
+ else
+ {
+ // don't really remove it from the collection just mark it removed
+ entry.EntryType = EntryType.Removed;
+ _removedItemCount++;
+ }
+ break;
+ case EntryType.Removed:
+ if (throwIfMissing)
+ throw new ConfigurationErrorsException(SR.Config_base_collection_entry_already_removed);
+ break;
+ default:
+ if ((CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap) &&
+ (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ throw new ConfigurationErrorsException(
+ SR.Config_base_collection_elements_may_not_be_removed);
+ }
+ entry.EntryType = EntryType.Removed;
+ _removedItemCount++;
+ break;
+ }
+ _modified = true;
+ return;
+ }
+ index++;
+ }
+
+ // Note because it is possible for removes to get orphaned by the API they will
+ // not cause a throw from the base classes. The scenerio is:
+ // Add an item in a parent level
+ // remove the item in a child level
+ // remove the item at the parent level.
+
+ if (throwIfMissing)
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_collection_entry_not_found, key));
+
+ if ((CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap) &&
+ (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ return;
+
+ if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate)
+ {
+ Items.Insert(Count + _removedItemCount - _inheritedCount,
+ new Entry(EntryType.Removed, key, null));
+ }
+ else
+ Items.Add(new Entry(EntryType.Removed, key, null));
+
+ _removedItemCount++;
+ }
+
+ protected internal ConfigurationElement BaseGet(object key)
+ {
+ foreach (Entry entry in Items)
+ if (entry.EntryType != EntryType.Removed)
+ if (CompareKeys(key, entry.GetKey(this))) return entry.Value;
+ return null;
+ }
+
+ protected internal bool BaseIsRemoved(object key)
+ {
+ foreach (Entry entry in Items)
+ if (CompareKeys(key, entry.GetKey(this)))
+ return entry.EntryType == EntryType.Removed;
+ return false;
+ }
+
+ protected internal ConfigurationElement BaseGet(int index)
+ {
+ if (index < 0) throw new ConfigurationErrorsException(string.Format(SR.IndexOutOfRange, index));
+
+ int virtualIndex = 0;
+ Entry entry = null;
+
+ foreach (Entry entryfound in Items)
+ {
+ if ((virtualIndex == index) && (entryfound.EntryType != EntryType.Removed))
+ {
+ entry = entryfound;
+ break;
+ }
+ if (entryfound.EntryType != EntryType.Removed) virtualIndex++;
+ }
+
+ if (entry != null)
+ return entry.Value;
+
+ throw new ConfigurationErrorsException(string.Format(SR.IndexOutOfRange, index));
+ }
+
+ protected internal object[] BaseGetAllKeys()
+ {
+ object[] keys = new object[Count];
+ int index = 0;
+ foreach (Entry entry in Items)
+ {
+ if (entry.EntryType == EntryType.Removed) continue;
+ keys[index] = entry.GetKey(this);
+ index++;
+ }
+ return keys;
+ }
+
+ protected internal object BaseGetKey(int index)
+ {
+ int virtualIndex = 0;
+ Entry entry = null;
+ if (index < 0) throw new ConfigurationErrorsException(string.Format(SR.IndexOutOfRange, index));
+
+ foreach (Entry entryfound in Items)
+ {
+ if ((virtualIndex == index) && (entryfound.EntryType != EntryType.Removed))
+ {
+ entry = entryfound;
+ break;
+ }
+
+ if (entryfound.EntryType != EntryType.Removed) virtualIndex++;
+ }
+
+ // Entry entry = (Entry)_items[index];
+ if (entry == null) throw new ConfigurationErrorsException(string.Format(SR.IndexOutOfRange, index));
+
+ return entry.GetKey(this);
+ }
+
+ protected internal void BaseClear()
+ {
+ if (IsReadOnly()) throw new ConfigurationErrorsException(SR.Config_base_read_only);
+
+ CheckLockedElement(_clearElement, null); // has clear been locked?
+ CheckLockedElement(_removeElement, null); // has remove been locked? Clear implies remove
+
+ _modified = true;
+ _collectionCleared = true;
+ if (((CollectionType == ConfigurationElementCollectionType.BasicMap) ||
+ (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate))
+ && (_inheritedCount > 0))
+ {
+ int removeIndex = 0;
+ if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate)
+ removeIndex = 0; // Inherited items are at the bottom and cannot be removed
+ if (CollectionType == ConfigurationElementCollectionType.BasicMap)
+ removeIndex = _inheritedCount; // inherited items are at the top and cannot be removed
+ while (Count - _inheritedCount > 0) Items.RemoveAt(removeIndex);
+ }
+ else
+ {
+ // do not clear any locked items
+ // _items.Clear();
+ int inheritedRemoved = 0;
+ int removedRemoved = 0;
+ int initialCount = Count;
+
+ // check for locks before removing any items from the collection
+ for (int checkIndex = 0; checkIndex < Items.Count; checkIndex++)
+ {
+ Entry entry = (Entry)Items[checkIndex];
+ if ((entry.Value != null) && entry.Value.LockItem)
+ throw new ConfigurationErrorsException(SR.Config_base_collection_item_locked_cannot_clear);
+ }
+
+ for (int removeIndex = Items.Count - 1; removeIndex >= 0; removeIndex--)
+ {
+ Entry entry = (Entry)Items[removeIndex];
+ if (((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) &&
+ (removeIndex < _inheritedCount)) ||
+ ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) &&
+ (removeIndex >= initialCount - _inheritedCount)))
+ inheritedRemoved++;
+ if (entry.EntryType == EntryType.Removed) removedRemoved++;
+
+ Items.RemoveAt(removeIndex);
+ }
+ _inheritedCount -= inheritedRemoved;
+ _removedItemCount -= removedRemoved;
+ }
+ }
+
+ protected internal void BaseRemoveAt(int index)
+ {
+ if (IsReadOnly()) throw new ConfigurationErrorsException(SR.Config_base_read_only);
+ int virtualIndex = 0;
+ Entry entry = null;
+
+ foreach (Entry entryfound in Items)
+ {
+ if ((virtualIndex == index) && (entryfound.EntryType != EntryType.Removed))
+ {
+ entry = entryfound;
+ break;
+ }
+
+ if (entryfound.EntryType != EntryType.Removed) virtualIndex++;
+ }
+
+ if (entry == null) throw new ConfigurationErrorsException(string.Format(SR.IndexOutOfRange, index));
+ if (entry.Value.LockItem)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_attribute_locked,
+ entry.GetKey(this)));
+ }
+
+ if (entry.Value.ElementPresent == false)
+ CheckLockedElement(_removeElement, null); // has remove been locked?
+
+ switch (entry.EntryType)
+ {
+ case EntryType.Added:
+ if ((CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap) &&
+ (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ if ((CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) &&
+ (index >= Count - _inheritedCount))
+ throw new ConfigurationErrorsException(SR.Config_base_cannot_remove_inherited_items);
+
+ if ((CollectionType == ConfigurationElementCollectionType.BasicMap) && (index < _inheritedCount))
+ throw new ConfigurationErrorsException(SR.Config_base_cannot_remove_inherited_items);
+
+ Items.RemoveAt(index);
+ }
+ else
+ {
+ // don't really remove it from the collection just mark it removed
+ if (entry.Value.ElementPresent == false)
+ CheckLockedElement(_removeElement, null); // has remove been locked?
+
+ entry.EntryType = EntryType.Removed;
+ _removedItemCount++;
+ }
+
+ break;
+
+ case EntryType.Removed:
+ throw new ConfigurationErrorsException(SR.Config_base_collection_entry_already_removed);
+
+ default:
+ if ((CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap) &&
+ (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ throw new ConfigurationErrorsException(SR.Config_base_collection_elements_may_not_be_removed);
+
+ entry.EntryType = EntryType.Removed;
+ _removedItemCount++;
+ break;
+ }
+ _modified = true;
+ }
+
+
+ protected internal override bool SerializeElement(XmlWriter writer, bool serializeCollectionKey)
+ {
+ ConfigurationElementCollectionType type = CollectionType;
+ bool dataToWrite = false;
+
+ dataToWrite |= base.SerializeElement(writer, serializeCollectionKey);
+
+ if ((type == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (type == ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ // it is possible that the collection only has to be cleared and contains
+ // no real elements
+ if (_emitClearTag && (_clearElement.Length != 0))
+ {
+ if (writer != null)
+ {
+ writer.WriteStartElement(_clearElement);
+ writer.WriteEndElement();
+ }
+ dataToWrite = true;
+ }
+ }
+
+ foreach (Entry entry in Items)
+ switch (type)
+ {
+ case ConfigurationElementCollectionType.BasicMap:
+ case ConfigurationElementCollectionType.BasicMapAlternate:
+ if ((entry.EntryType == EntryType.Added) || (entry.EntryType == EntryType.Replaced))
+ {
+ if (!string.IsNullOrEmpty(ElementName))
+ {
+ if (BaseConfigurationRecord.IsReservedAttributeName(ElementName))
+ {
+ throw new ArgumentException(string.Format(SR.Basicmap_item_name_reserved,
+ ElementName));
+ }
+
+ dataToWrite |= entry.Value.SerializeToXmlElement(writer, ElementName);
+ }
+ else dataToWrite |= entry.Value.SerializeElement(writer, false);
+ }
+ break;
+ case ConfigurationElementCollectionType.AddRemoveClearMap:
+ case ConfigurationElementCollectionType.AddRemoveClearMapAlternate:
+ if (((entry.EntryType == EntryType.Removed) ||
+ (entry.EntryType == EntryType.Replaced)) &&
+ (entry.Value != null))
+ {
+ writer?.WriteStartElement(_removeElement);
+ entry.Value.SerializeElement(writer, true);
+ writer?.WriteEndElement();
+ dataToWrite = true;
+ }
+
+ if ((entry.EntryType == EntryType.Added) || (entry.EntryType == EntryType.Replaced))
+ dataToWrite |= entry.Value.SerializeToXmlElement(writer, _addElement);
+
+ break;
+ }
+
+ return dataToWrite;
+ }
+
+ protected override bool OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)
+ {
+ if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ if (elementName == _addElement)
+ {
+ ConfigurationElement elem = CallCreateNewElement();
+ elem.ResetLockLists(this);
+ elem.DeserializeElement(reader, false);
+ BaseAdd(elem);
+ }
+ else
+ {
+ if (elementName == _removeElement)
+ {
+ ConfigurationElement elem = CallCreateNewElement();
+ elem.ResetLockLists(this);
+ elem.DeserializeElement(reader, true);
+ if (IsElementRemovable(elem)) BaseRemove(GetElementKeyInternal(elem), false);
+ }
+ else
+ {
+ if (elementName != _clearElement) return false;
+
+ if (reader.AttributeCount > 0)
+ {
+ while (reader.MoveToNextAttribute())
+ {
+ string propertyName = reader.Name;
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_base_unrecognized_attribute, propertyName), reader);
+ }
+ }
+
+ CheckLockedElement(elementName, reader);
+ reader.MoveToElement();
+ BaseClear(); //
+ _emitClearTag = true;
+ }
+ }
+ }
+ else
+ {
+ if (elementName == ElementName)
+ {
+ if (BaseConfigurationRecord.IsReservedAttributeName(elementName))
+ throw new ArgumentException(string.Format(SR.Basicmap_item_name_reserved, elementName));
+ ConfigurationElement elem = CallCreateNewElement();
+ elem.ResetLockLists(this);
+ elem.DeserializeElement(reader, false);
+ BaseAdd(elem);
+ }
+ else
+ {
+ if (!IsElementName(elementName)) return false;
+
+ // this section handle the collection like the allow deny senario which
+ if (BaseConfigurationRecord.IsReservedAttributeName(elementName))
+ throw new ArgumentException(string.Format(SR.Basicmap_item_name_reserved, elementName));
+
+ // have multiple tags for the collection
+ ConfigurationElement elem = CallCreateNewElement(elementName);
+ elem.ResetLockLists(this);
+ elem.DeserializeElement(reader, false);
+ BaseAdd(-1, elem);
+ }
+ }
+ return true;
+ }
+
+ private ConfigurationElement CallCreateNewElement(string elementName)
+ {
+ ConfigurationElement elem = CreateNewElement(elementName);
+ elem.AssociateContext(_configRecord);
+ elem.CallInit();
+ return elem;
+ }
+
+ private ConfigurationElement CallCreateNewElement()
+ {
+ ConfigurationElement elem = CreateNewElement();
+ elem.AssociateContext(_configRecord);
+ elem.CallInit();
+ return elem;
+ }
+
+ protected virtual ConfigurationElement CreateNewElement(string elementName)
+ {
+ return CreateNewElement();
+ }
+
+ protected abstract ConfigurationElement CreateNewElement();
+ protected abstract object GetElementKey(ConfigurationElement element);
+
+ internal object GetElementKeyInternal(ConfigurationElement element)
+ {
+ object key = GetElementKey(element);
+ if (key == null)
+ throw new ConfigurationErrorsException(SR.Config_base_invalid_element_key);
+ return key;
+ }
+
+ protected virtual bool IsElementRemovable(ConfigurationElement element)
+ {
+ return true;
+ }
+
+ private bool CompareKeys(object key1, object key2)
+ {
+ if (_comparer != null) return _comparer.Compare(key1, key2) == 0;
+ return key1.Equals(key2);
+ }
+
+ protected virtual bool IsElementName(string elementName)
+ {
+ return false;
+ }
+
+ internal bool IsLockableElement(string elementName)
+ {
+ if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap) ||
+ (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate))
+ {
+ return (elementName == AddElementName) ||
+ (elementName == RemoveElementName) ||
+ (elementName == ClearElementName);
+ }
+ return (elementName == ElementName) || IsElementName(elementName);
+ }
+
+ private enum InheritedType
+ {
+ InNeither = 0,
+ InParent = 1,
+ InSelf = 2,
+ InBothSame = 3,
+ InBothDiff = 4,
+ InBothCopyNoRemove = 5,
+ }
+
+ private enum EntryType
+ {
+ Inherited,
+ Replaced,
+ Removed,
+ Added,
+ }
+
+ private class Entry
+ {
+ private readonly object _key;
+ internal EntryType EntryType;
+ internal ConfigurationElement Value;
+
+ internal Entry(EntryType type, object key, ConfigurationElement value)
+ {
+ EntryType = type;
+ _key = key;
+ Value = value;
+ }
+
+ internal object GetKey(ConfigurationElementCollection thisCollection)
+ {
+ // For items that have been really inserted...
+ return Value != null ? thisCollection.GetElementKeyInternal(Value) : _key;
+ }
+ }
+
+ private class Enumerator : IDictionaryEnumerator
+ {
+ private readonly IEnumerator _itemsEnumerator;
+ private readonly ConfigurationElementCollection _thisCollection;
+ private DictionaryEntry _current;
+
+ internal Enumerator(ArrayList items, ConfigurationElementCollection collection)
+ {
+ _itemsEnumerator = items.GetEnumerator();
+ _thisCollection = collection;
+ }
+
+ bool IEnumerator.MoveNext()
+ {
+ while (_itemsEnumerator.MoveNext())
+ {
+ Entry entry = (Entry)_itemsEnumerator.Current;
+ if (entry.EntryType == EntryType.Removed) continue;
+ _current.Key = entry.GetKey(_thisCollection) != null ? entry.GetKey(_thisCollection) : "key";
+ _current.Value = entry.Value;
+ return true;
+ }
+ return false;
+ }
+
+ void IEnumerator.Reset()
+ {
+ _itemsEnumerator.Reset();
+ }
+
+ object IEnumerator.Current => _current.Value;
+
+ DictionaryEntry IDictionaryEnumerator.Entry => _current;
+
+ object IDictionaryEnumerator.Key => _current.Key;
+
+ object IDictionaryEnumerator.Value => _current.Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationElementCollectionType.cs b/src/System.Configuration/src/System/Configuration/ConfigurationElementCollectionType.cs
new file mode 100644
index 0000000000..8ea30d8819
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationElementCollectionType.cs
@@ -0,0 +1,58 @@
+// 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.Configuration
+{
+ public enum ConfigurationElementCollectionType
+ {
+ /**********************************************************************
+
+ This enum type specifies the behavior of the ConfigurationElementCollection.
+ Some of the behavior is changeable via other properties (i.e. throwing
+ on duplicate entries).
+
+ - BasicMap and BasicMapAlternate
+
+ This collection doesn't do any "clear" or "remove". Whatever the set
+ of entries is in the config file is given back to the user. An example
+ would be like Authentication Users, where each entry specifies a user.
+
+ The Alternate version of this collection simply changes the index location
+ of the items from the parent collection. For example, suppose you had
+ entries in machine and app level specified like this:
+
+ machine.config => A, B, C
+ web.config => D, E, F
+
+ For BasicMap, the collection at the app level would be:
+
+ A, B, C, D, E, F
+
+ With BasicMapAlternate, it'd be:
+
+ D, E, F, A, B, C
+
+ That means that the Alternate allows the "nearest" config file entries to
+ take precedence over the "parent" config file entries.
+
+ - AddRemoveClearMap and AddRemoveClearMapAlternate
+
+ This collection honors the "add, remove, clear" commands. Internally it
+ keeps track of each of them so that it knows whether it has to write out
+ an add/remove/clear at the appropriate levels, so it uses a concept of
+ "virtual index" and "real index" to keep track of stuff. The "virtual index"
+ is what the end user would see and use. The "real index" is just for us.
+ Any access via indexes have to go through some transformation step.
+
+ The Alternate version changes the inheritance stuff like the BasicMapAlternate,
+ where the "nearest" config file entries take precendence over the "parent"
+ config file entries (see example above).
+ **********************************************************************/
+
+ BasicMap,
+ AddRemoveClearMap,
+ BasicMapAlternate,
+ AddRemoveClearMapAlternate,
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationElementProperty.cs b/src/System.Configuration/src/System/Configuration/ConfigurationElementProperty.cs
new file mode 100644
index 0000000000..5adfc78d64
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationElementProperty.cs
@@ -0,0 +1,22 @@
+// 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.Configuration
+{
+ // Although in Whidbey this class contain just one property, but we still do this this way,
+ // instead of exposing a Validator property in ConfigurationElement, because if we need
+ // another property in the future we'll expand this ElementProperty class rather than adding a
+ // new overridable on ConfigurationElement
+ public sealed class ConfigurationElementProperty
+ {
+ public ConfigurationElementProperty(ConfigurationValidatorBase validator)
+ {
+ if (validator == null) throw new ArgumentNullException(nameof(validator));
+
+ Validator = validator;
+ }
+
+ public ConfigurationValidatorBase Validator { get; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationErrorsException.cs b/src/System.Configuration/src/System/Configuration/ConfigurationErrorsException.cs
new file mode 100644
index 0000000000..9cd5d1ca13
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationErrorsException.cs
@@ -0,0 +1,264 @@
+// 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.Collections.Generic;
+using System.Configuration.Internal;
+using System.Globalization;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Xml;
+
+namespace System.Configuration
+{
+ [Serializable]
+ public class ConfigurationErrorsException : ConfigurationException
+ {
+ // Constants
+ private const string HttpPrefix = "http:";
+ private const string SerializationParamFilename = "firstFilename";
+ private const string SerializationParamLine = "firstLine";
+ private const string SerializationParamErrorCount = "count";
+ private const string SerializationParamErrorData = "_errors";
+ private const string SerializationParamErrorType = "_errors_type";
+
+ private readonly ConfigurationException[] _errors;
+
+ private string _firstFilename;
+ private int _firstLine;
+
+ // The ConfigurationException class is obsolete, but we still need to derive from it and call the base ctor, so we
+ // just disable the obsoletion warning.
+#pragma warning disable 0618
+ public ConfigurationErrorsException(string message, Exception inner, string filename, int line)
+ : base(message, inner)
+ {
+#pragma warning restore 0618
+ Init(filename, line);
+ }
+
+ public ConfigurationErrorsException() :
+ this(null, null, null, 0)
+ { }
+
+ public ConfigurationErrorsException(string message) :
+ this(message, null, null, 0)
+ { }
+
+ public ConfigurationErrorsException(string message, Exception inner) :
+ this(message, inner, null, 0)
+ { }
+
+ public ConfigurationErrorsException(string message, string filename, int line) :
+ this(message, null, filename, line)
+ { }
+
+ public ConfigurationErrorsException(string message, XmlNode node) :
+ this(message, null, GetFilename(node), GetLineNumber(node))
+ { }
+
+ public ConfigurationErrorsException(string message, Exception inner, XmlNode node) :
+ this(message, inner, GetFilename(node), GetLineNumber(node))
+ { }
+
+ public ConfigurationErrorsException(string message, XmlReader reader) :
+ this(message, null, GetFilename(reader), GetLineNumber(reader))
+ { }
+
+ public ConfigurationErrorsException(string message, Exception inner, XmlReader reader) :
+ this(message, inner, GetFilename(reader), GetLineNumber(reader))
+ { }
+
+ internal ConfigurationErrorsException(string message, IConfigErrorInfo errorInfo) :
+ this(message, null, GetConfigErrorInfoFilename(errorInfo), GetConfigErrorInfoLineNumber(errorInfo))
+ { }
+
+ internal ConfigurationErrorsException(string message, Exception inner, IConfigErrorInfo errorInfo) :
+ this(message, inner, GetConfigErrorInfoFilename(errorInfo), GetConfigErrorInfoLineNumber(errorInfo))
+ { }
+
+ internal ConfigurationErrorsException(ConfigurationException e) :
+ this(e?.BareMessage, e?.InnerException, e?.Filename, e?.Line ?? 0)
+ { }
+
+ internal ConfigurationErrorsException(ICollection<ConfigurationException> coll) :
+ this(GetFirstException(coll))
+ {
+ if (coll.Count > 1)
+ {
+ _errors = new ConfigurationException[coll.Count];
+ coll.CopyTo(_errors, 0);
+ }
+ }
+
+ internal ConfigurationErrorsException(ArrayList coll) :
+ this((ConfigurationException)(coll.Count > 0 ? coll[0] : null))
+ {
+ if (coll.Count <= 1) return;
+ _errors = new ConfigurationException[coll.Count];
+ coll.CopyTo(_errors, 0);
+ }
+
+ protected ConfigurationErrorsException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ {
+ int firstLine;
+ int count;
+
+ // Retrieve out members
+ string firstFilename = info.GetString(SerializationParamFilename);
+ firstLine = info.GetInt32(SerializationParamLine);
+
+ Init(firstFilename, firstLine);
+
+ // Retrieve errors for _errors object
+ count = info.GetInt32(SerializationParamErrorCount);
+
+ if (count == 0) return;
+ _errors = new ConfigurationException[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ string numPrefix = i.ToString(CultureInfo.InvariantCulture);
+
+ string currentType = info.GetString(numPrefix + SerializationParamErrorType);
+ Type currentExceptionType = Type.GetType(currentType, true);
+
+ // Only allow our exception types
+ if ((currentExceptionType != typeof(ConfigurationException)) &&
+ (currentExceptionType != typeof(ConfigurationErrorsException)))
+ throw ExceptionUtil.UnexpectedError("ConfigurationErrorsException");
+
+ _errors[i] = (ConfigurationException)
+ info.GetValue(numPrefix + SerializationParamErrorData,
+ currentExceptionType);
+ }
+ }
+
+ // The message includes the file/line number information.
+ // To get the message without the extra information, use BareMessage.
+ public override string Message
+ {
+ get
+ {
+ string file = Filename;
+ if (!string.IsNullOrEmpty(file))
+ {
+ return Line != 0
+ ? BareMessage + " (" + file + " line " + Line.ToString(CultureInfo.CurrentCulture) + ")"
+ : BareMessage + " (" + file + ")";
+ }
+
+ return Line != 0
+ ? BareMessage + " (line " + Line.ToString("G", CultureInfo.CurrentCulture) + ")"
+ : BareMessage;
+ }
+ }
+
+ public override string Filename => _firstFilename;
+
+ public override int Line => _firstLine;
+
+ public ICollection Errors
+ {
+ get
+ {
+ if (_errors != null) return _errors;
+
+ ConfigurationErrorsException e = new ConfigurationErrorsException(BareMessage, InnerException,
+ _firstFilename, _firstLine);
+
+ ConfigurationException[] a = { e };
+ return a;
+ }
+ }
+
+ internal ICollection<ConfigurationException> ErrorsGeneric => (ICollection<ConfigurationException>)Errors;
+
+ private void Init(string filename, int line)
+ {
+ HResult = HResults.Configuration;
+
+ // BaseConfigurationRecord.cs uses -1 as uninitialized line number.
+ if (line == -1) line = 0;
+
+ _firstFilename = filename;
+ _firstLine = line;
+ }
+
+ private static ConfigurationException GetFirstException(ICollection<ConfigurationException> coll)
+ {
+ foreach (ConfigurationException e in coll) return e;
+
+ return null;
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ int subErrors = 0;
+
+ // call base implementation
+ base.GetObjectData(info, context);
+
+ // Serialize our members
+ info.AddValue(SerializationParamFilename, Filename);
+ info.AddValue(SerializationParamLine, Line);
+
+ // Serialize rest of errors, along with count
+ // (since first error duplicates this error, only worry if
+ // there is more than one)
+ if ((_errors != null) &&
+ (_errors.Length > 1))
+ {
+ subErrors = _errors.Length;
+
+ for (int i = 0; i < _errors.Length; i++)
+ {
+ string numPrefix = i.ToString(CultureInfo.InvariantCulture);
+
+ info.AddValue(numPrefix + SerializationParamErrorData,
+ _errors[i]);
+ info.AddValue(numPrefix + SerializationParamErrorType,
+ _errors[i].GetType());
+ }
+ }
+
+ info.AddValue(SerializationParamErrorCount, subErrors);
+ }
+
+ // Get file and linenumber from an XML Node in a DOM
+ public static int GetLineNumber(XmlNode node)
+ {
+ return GetConfigErrorInfoLineNumber(node as IConfigErrorInfo);
+ }
+
+ public static string GetFilename(XmlNode node)
+ {
+ return GetConfigErrorInfoFilename(node as IConfigErrorInfo);
+ }
+
+ // Get file and linenumber from an XML Reader
+ public static int GetLineNumber(XmlReader reader)
+ {
+ return GetConfigErrorInfoLineNumber(reader as IConfigErrorInfo);
+ }
+
+ public static string GetFilename(XmlReader reader)
+ {
+ return GetConfigErrorInfoFilename(reader as IConfigErrorInfo);
+ }
+
+ // Get file and linenumber from an IConfigErrorInfo
+ private static int GetConfigErrorInfoLineNumber(IConfigErrorInfo errorInfo)
+ {
+ return errorInfo?.LineNumber ?? 0;
+ }
+
+ private static string GetConfigErrorInfoFilename(IConfigErrorInfo errorInfo)
+ {
+ return errorInfo?.Filename;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationException.cs b/src/System.Configuration/src/System/Configuration/ConfigurationException.cs
new file mode 100644
index 0000000000..4e19a46473
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationException.cs
@@ -0,0 +1,106 @@
+// 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.Configuration.Internal;
+using System.Globalization;
+using System.Runtime.Serialization;
+using System.Xml;
+
+namespace System.Configuration
+{
+ /// <summary>
+ /// A config exception can contain a filename (of a config file) and a line number (of the location in the file in
+ /// which a
+ /// problem was encountered). Section handlers should throw this exception (or subclasses) together with filename and
+ /// line
+ /// number information where possible.
+ /// </summary>
+ [Serializable]
+ public class ConfigurationException : SystemException
+ {
+ private string _filename;
+ private int _line;
+
+ // Default ctor is required for serialization.
+ protected ConfigurationException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ Init(info.GetString("filename"), info.GetInt32("line"));
+ }
+
+ [Obsolete("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException() : this(null, null, null, 0) { }
+
+ [Obsolete("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message) : this(message, null, null, 0) { }
+
+ [Obsolete("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, Exception inner) : this(message, inner, null, 0) { }
+
+ [Obsolete("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, XmlNode node)
+ : this(message, null, GetXmlNodeFilename(node), GetXmlNodeLineNumber(node))
+ { }
+
+ [Obsolete("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, Exception inner, XmlNode node)
+ : this(message, inner, GetXmlNodeFilename(node), GetXmlNodeLineNumber(node))
+ { }
+
+ [Obsolete("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, string filename, int line) : this(message, null, filename, line) { }
+
+ [Obsolete("This class is obsolete, to create a new exception create a System.Configuration!System.Configuration.ConfigurationErrorsException")]
+ public ConfigurationException(string message, Exception inner, string filename, int line) : base(message, inner)
+ {
+ Init(filename, line);
+ }
+
+ // The message includes the file/line number information.
+ // To get the message without the extra information, use BareMessage.
+ public override string Message
+ {
+ get
+ {
+ string file = Filename;
+ if (!string.IsNullOrEmpty(file))
+ {
+ return Line != 0
+ ? BareMessage + " (" + file + " line " + Line.ToString(CultureInfo.InvariantCulture) + ")"
+ : BareMessage + " (" + file + ")";
+ }
+
+ return Line != 0
+ ? BareMessage + " (line " + Line.ToString("G", CultureInfo.InvariantCulture) + ")"
+ : BareMessage;
+ }
+ }
+
+ public virtual string BareMessage => base.Message;
+
+ public virtual string Filename => _filename;
+
+ public virtual int Line => _line;
+
+ private void Init(string filename, int line)
+ {
+ HResult = HResults.Configuration;
+ _filename = filename;
+ _line = line;
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("filename", _filename);
+ info.AddValue("line", _line);
+ }
+
+ [Obsolete("This class is obsolete, use System.Configuration!System.Configuration.ConfigurationErrorsException.GetFilename instead")]
+ public static string GetXmlNodeFilename(XmlNode node) => (node as IConfigErrorInfo)?.Filename ?? string.Empty;
+
+ [Obsolete("This class is obsolete, use System.Configuration!System.Configuration.ConfigurationErrorsException.GetFilename instead")]
+ public static int GetXmlNodeLineNumber(XmlNode node) => (node as IConfigErrorInfo)?.LineNumber ?? 0;
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationFileMap.cs b/src/System.Configuration/src/System/Configuration/ConfigurationFileMap.cs
new file mode 100644
index 0000000000..df4d12658b
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationFileMap.cs
@@ -0,0 +1,61 @@
+// 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.IO;
+
+namespace System.Configuration
+{
+ /// <summary>
+ /// Holds the configuration file mapping for machine.config. It is the base class for
+ /// ExeConfigurationFileMap and WebConfigurationFileMap.
+ /// </summary>
+ public class ConfigurationFileMap : ICloneable
+ {
+ // This used to be two fields: one containing the filename and the other containing
+ // a Boolean dictating whether a security check needed to take place. Such a pattern wasn't thread-safe
+ // and could be circumvented by malicious callers. Using a single reference field is guaranteed atomic
+ // read and write across all platforms, so the race condition is eliminated.
+ private Func<string> _getFilenameThunk;
+
+ public ConfigurationFileMap()
+ {
+ _getFilenameThunk = GetFilenameFromMachineConfigFilePath;
+ }
+
+ public ConfigurationFileMap(string machineConfigFilename)
+ {
+ if (string.IsNullOrEmpty(machineConfigFilename))
+ throw new ArgumentNullException(nameof(machineConfigFilename));
+ if (!File.Exists(machineConfigFilename))
+ {
+ throw new ArgumentException(string.Format(SR.Machine_config_file_not_found, machineConfigFilename),
+ nameof(machineConfigFilename));
+ }
+
+ MachineConfigFilename = machineConfigFilename;
+ }
+
+ // copy ctor used only for cloning
+ private ConfigurationFileMap(ConfigurationFileMap other)
+ {
+ _getFilenameThunk = other._getFilenameThunk;
+ }
+
+ public string MachineConfigFilename
+ {
+ get { return _getFilenameThunk(); }
+ set { _getFilenameThunk = () => value; }
+ }
+
+ public virtual object Clone()
+ {
+ return new ConfigurationFileMap(this);
+ }
+
+ private static string GetFilenameFromMachineConfigFilePath()
+ {
+ return ClientConfigurationHost.MachineConfigFilePath;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationLocation.cs b/src/System.Configuration/src/System/Configuration/ConfigurationLocation.cs
new file mode 100644
index 0000000000..7402dc5482
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationLocation.cs
@@ -0,0 +1,24 @@
+// 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.Configuration
+{
+ public class ConfigurationLocation
+ {
+ private readonly Configuration _config;
+
+ internal ConfigurationLocation(Configuration config, string locationSubPath)
+ {
+ _config = config;
+ Path = locationSubPath;
+ }
+
+ public string Path { get; }
+
+ public Configuration OpenConfiguration()
+ {
+ return _config.OpenLocationConfiguration(Path);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationLocationCollection.cs b/src/System.Configuration/src/System/Configuration/ConfigurationLocationCollection.cs
new file mode 100644
index 0000000000..10581d9ea0
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationLocationCollection.cs
@@ -0,0 +1,18 @@
+// 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.Configuration
+{
+ public class ConfigurationLocationCollection : ReadOnlyCollectionBase
+ {
+ internal ConfigurationLocationCollection(ICollection col)
+ {
+ InnerList.AddRange(col);
+ }
+
+ public ConfigurationLocation this[int index] => (ConfigurationLocation)InnerList[index];
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationLockCollection.cs b/src/System.Configuration/src/System/Configuration/ConfigurationLockCollection.cs
new file mode 100644
index 0000000000..d0bb431c0a
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationLockCollection.cs
@@ -0,0 +1,335 @@
+// 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.Collections.Specialized;
+using System.Text;
+
+namespace System.Configuration
+{
+ public sealed class ConfigurationLockCollection : ICollection
+ {
+ private const string LockAll = "*";
+ private readonly string _ignoreName;
+ private readonly ConfigurationElement _thisElement;
+ private readonly ArrayList _internalArraylist;
+ private readonly HybridDictionary _internalDictionary;
+ private string _seedList = string.Empty;
+
+ internal ConfigurationLockCollection(ConfigurationElement thisElement)
+ : this(thisElement, ConfigurationLockCollectionType.LockedAttributes)
+ { }
+
+ internal ConfigurationLockCollection(ConfigurationElement thisElement, ConfigurationLockCollectionType lockType)
+ : this(thisElement, lockType, string.Empty)
+ { }
+
+ internal ConfigurationLockCollection(ConfigurationElement thisElement, ConfigurationLockCollectionType lockType,
+ string ignoreName)
+ : this(thisElement, lockType, ignoreName, null)
+ { }
+
+ internal ConfigurationLockCollection(ConfigurationElement thisElement, ConfigurationLockCollectionType lockType,
+ string ignoreName, ConfigurationLockCollection parentCollection)
+ {
+ _thisElement = thisElement;
+ LockType = lockType;
+ _internalDictionary = new HybridDictionary();
+ _internalArraylist = new ArrayList();
+ IsModified = false;
+
+ ExceptionList = (LockType == ConfigurationLockCollectionType.LockedExceptionList) ||
+ (LockType == ConfigurationLockCollectionType.LockedElementsExceptionList);
+ _ignoreName = ignoreName;
+
+ if (parentCollection == null) return;
+
+ foreach (string key in parentCollection) // seed the new collection
+ {
+ Add(key, ConfigurationValueFlags.Inherited); // add the local copy
+ if (!ExceptionList) continue;
+
+ if (_seedList.Length != 0)
+ _seedList += ",";
+ _seedList += key;
+ }
+ }
+
+ internal ConfigurationLockCollectionType LockType { get; }
+
+ public bool IsModified { get; private set; }
+
+ internal bool ExceptionList { get; }
+
+ public string AttributeList
+ {
+ get
+ {
+ StringBuilder sb = new StringBuilder();
+
+ foreach (DictionaryEntry de in _internalDictionary)
+ {
+ if (sb.Length != 0) sb.Append(',');
+ sb.Append(de.Key);
+ }
+ return sb.ToString();
+ }
+ }
+
+ public bool HasParentElements
+ {
+ get
+ {
+ // return true if there is at least one element that was defined in the parent
+ bool result = false;
+ // Check to see if the exception list is empty as a result of a merge from config
+ // If so the there were some parent elements because empty string is invalid in config.
+ // and the only way to get an empty list is for the merged config to have no elements
+ // in common.
+ if (ExceptionList && (_internalDictionary.Count == 0) && !string.IsNullOrEmpty(_seedList))
+ return true;
+
+ foreach (DictionaryEntry de in _internalDictionary)
+ if (((ConfigurationValueFlags)de.Value & ConfigurationValueFlags.Inherited) != 0)
+ {
+ result = true;
+ break;
+ }
+
+ return result;
+ }
+ }
+
+ public int Count => _internalDictionary.Count;
+
+ public bool IsSynchronized => false;
+
+ public object SyncRoot => this;
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ _internalArraylist.CopyTo(array, index);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _internalArraylist.GetEnumerator();
+ }
+
+ internal void ClearSeedList()
+ {
+ _seedList = string.Empty;
+ }
+
+ public void Add(string name)
+ {
+ if (((_thisElement.ItemLocked & ConfigurationValueFlags.Locked) != 0) &&
+ ((_thisElement.ItemLocked & ConfigurationValueFlags.Inherited) != 0))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_attribute_locked, name));
+
+ ConfigurationValueFlags flags = ConfigurationValueFlags.Modified;
+
+ string attribToLockTrim = name.Trim();
+ ConfigurationProperty propToLock = _thisElement.Properties[attribToLockTrim];
+ if ((propToLock == null) && (attribToLockTrim != LockAll))
+ {
+ ConfigurationElementCollection collection = _thisElement as ConfigurationElementCollection;
+ if ((collection == null) && (_thisElement.Properties.DefaultCollectionProperty != null))
+ {
+ // this is not a collection but it may contain a default collection
+ collection =
+ _thisElement[_thisElement.Properties.DefaultCollectionProperty] as
+ ConfigurationElementCollection;
+ }
+
+ if ((collection == null) ||
+ (LockType == ConfigurationLockCollectionType.LockedAttributes) ||
+ // If the collection type is not element then the lock is bogus
+ (LockType == ConfigurationLockCollectionType.LockedExceptionList))
+ _thisElement.ReportInvalidLock(attribToLockTrim, LockType, null, null);
+ else
+ {
+ if (!collection.IsLockableElement(attribToLockTrim))
+ _thisElement.ReportInvalidLock(attribToLockTrim, LockType, null, collection.LockableElements);
+ }
+ }
+ else
+ {
+ // the lock is in the property bag but is it the correct type?
+ if ((propToLock != null) && propToLock.IsRequired)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_required_attribute_lock_attempt,
+ propToLock.Name));
+ }
+
+ if (attribToLockTrim != LockAll)
+ {
+ if ((LockType == ConfigurationLockCollectionType.LockedElements) ||
+ (LockType == ConfigurationLockCollectionType.LockedElementsExceptionList))
+ {
+ // If it is an element then it must be derived from ConfigurationElement
+ if (!typeof(ConfigurationElement).IsAssignableFrom(propToLock?.Type))
+ _thisElement.ReportInvalidLock(attribToLockTrim, LockType, null, null);
+ }
+ else
+ {
+ // if it is a property then it cannot be derived from ConfigurationElement
+ if (typeof(ConfigurationElement).IsAssignableFrom(propToLock?.Type))
+ _thisElement.ReportInvalidLock(attribToLockTrim, LockType, null, null);
+ }
+ }
+ }
+
+ if (_internalDictionary.Contains(name))
+ {
+ flags = ConfigurationValueFlags.Modified | (ConfigurationValueFlags)_internalDictionary[name];
+ _internalDictionary.Remove(name); // not from parent
+ _internalArraylist.Remove(name);
+ }
+ _internalDictionary.Add(name, flags); // not from parent
+ _internalArraylist.Add(name);
+ IsModified = true;
+ }
+
+ internal void Add(string name, ConfigurationValueFlags flags)
+ {
+ if ((flags != ConfigurationValueFlags.Inherited) && _internalDictionary.Contains(name))
+ {
+ // the user has an item declared as locked below a level where it is already locked
+ // keep enough info so we can write out the lock if they save in modified mode
+ flags = ConfigurationValueFlags.Modified | (ConfigurationValueFlags)_internalDictionary[name];
+ _internalDictionary.Remove(name);
+ _internalArraylist.Remove(name);
+ }
+
+ _internalDictionary.Add(name, flags); // not from parent
+ _internalArraylist.Add(name);
+ }
+
+ internal bool DefinedInParent(string name)
+ {
+ if (name == null)
+ return false;
+ if (!ExceptionList)
+ {
+ return _internalDictionary.Contains(name) &&
+ (((ConfigurationValueFlags)_internalDictionary[name] & ConfigurationValueFlags.Inherited) != 0);
+ }
+
+ string parentListEnclosed = "," + _seedList + ",";
+ if (name.Equals(_ignoreName) ||
+ (parentListEnclosed.IndexOf("," + name + ",", StringComparison.Ordinal) >= 0))
+ return true;
+ return _internalDictionary.Contains(name) &&
+ (((ConfigurationValueFlags)_internalDictionary[name] & ConfigurationValueFlags.Inherited) != 0);
+ }
+
+ internal bool IsValueModified(string name)
+ {
+ return _internalDictionary.Contains(name) &&
+ (((ConfigurationValueFlags)_internalDictionary[name] & ConfigurationValueFlags.Modified) != 0);
+ }
+
+ internal void RemoveInheritedLocks()
+ {
+ StringCollection removeList = new StringCollection();
+ foreach (string key in this) if (DefinedInParent(key)) removeList.Add(key);
+ foreach (string key in removeList)
+ {
+ _internalDictionary.Remove(key);
+ _internalArraylist.Remove(key);
+ }
+ }
+
+ public void Remove(string name)
+ {
+ if (!_internalDictionary.Contains(name))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_collection_entry_not_found, name));
+
+ // in a locked list you cannot remove items that were locked in the parent
+ // in an exception list this is legal because it makes the list more restrictive
+ if ((ExceptionList == false) &&
+ (((ConfigurationValueFlags)_internalDictionary[name] & ConfigurationValueFlags.Inherited) != 0))
+ {
+ if (((ConfigurationValueFlags)_internalDictionary[name] & ConfigurationValueFlags.Modified) == 0)
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_attribute_locked, name));
+
+ // allow the local one to be "removed" so it won't write out but throw if they try and remove
+ // one that is only inherited
+ ConfigurationValueFlags flags = (ConfigurationValueFlags)_internalDictionary[name];
+ flags &= ~ConfigurationValueFlags.Modified;
+ _internalDictionary[name] = flags;
+ IsModified = true;
+ return;
+ }
+
+ _internalDictionary.Remove(name);
+ _internalArraylist.Remove(name);
+ IsModified = true;
+ }
+
+ internal void ClearInternal(bool useSeedIfAvailble)
+ {
+ ArrayList removeList = new ArrayList();
+ foreach (DictionaryEntry de in _internalDictionary)
+ if ((((ConfigurationValueFlags)de.Value & ConfigurationValueFlags.Inherited) == 0)
+ || ExceptionList)
+ removeList.Add(de.Key);
+
+ foreach (object removeKey in removeList)
+ {
+ _internalDictionary.Remove(removeKey);
+ _internalArraylist.Remove(removeKey);
+ }
+
+ // Clearing an Exception list really means revert to parent
+ if (useSeedIfAvailble && !string.IsNullOrEmpty(_seedList))
+ {
+ string[] keys = _seedList.Split(',');
+ foreach (string key in keys) Add(key, ConfigurationValueFlags.Inherited);
+ }
+ IsModified = true;
+ }
+
+ public void Clear()
+ {
+ ClearInternal(true);
+ }
+
+ public bool Contains(string name)
+ {
+ if (ExceptionList && name.Equals(_ignoreName)) return true;
+ return _internalDictionary.Contains(name);
+ }
+
+ public void CopyTo(string[] array, int index)
+ {
+ ((ICollection)this).CopyTo(array, index);
+ }
+
+ internal void ResetModified()
+ {
+ IsModified = false;
+ }
+
+ public bool IsReadOnly(string name)
+ {
+ if (!_internalDictionary.Contains(name))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_collection_entry_not_found, name));
+ return
+ ((ConfigurationValueFlags)_internalDictionary[name] & ConfigurationValueFlags.Inherited) != 0;
+ }
+
+ public void SetFromList(string attributeList)
+ {
+ string[] splits = attributeList.Split(',', ';', ':');
+ Clear();
+ foreach (string name in splits)
+ {
+ string attribTrim = name.Trim();
+ if (!Contains(attribTrim)) Add(attribTrim);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationLockCollectionType.cs b/src/System.Configuration/src/System/Configuration/ConfigurationLockCollectionType.cs
new file mode 100644
index 0000000000..d56d039d21
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationLockCollectionType.cs
@@ -0,0 +1,14 @@
+// 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.Configuration
+{
+ internal enum ConfigurationLockCollectionType
+ {
+ LockedAttributes = 1,
+ LockedExceptionList = 2,
+ LockedElements = 3,
+ LockedElementsExceptionList = 4
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationManager.cs b/src/System.Configuration/src/System/Configuration/ConfigurationManager.cs
new file mode 100644
index 0000000000..33f779d1c1
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationManager.cs
@@ -0,0 +1,268 @@
+// 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.Specialized;
+using System.Configuration.Internal;
+
+namespace System.Configuration
+{
+ public static class ConfigurationManager
+ {
+ // The Configuration System
+ private static volatile IInternalConfigSystem s_configSystem;
+
+ // Initialization state
+ private static volatile InitState s_initState;
+ private static readonly object s_initLock;
+ private static volatile Exception s_initError;
+
+ static ConfigurationManager()
+ {
+ s_initState = InitState.NotStarted;
+ s_initLock = new object();
+ }
+
+ // to be used by System.Diagnostics to avoid false config results during config init
+ internal static bool SetConfigurationSystemInProgress
+ => (InitState.NotStarted < s_initState) && (s_initState < InitState.Completed);
+
+ internal static bool SupportsUserConfig
+ {
+ get
+ {
+ PrepareConfigSystem();
+
+ return s_configSystem.SupportsUserConfig;
+ }
+ }
+
+ public static NameValueCollection AppSettings
+ {
+ get
+ {
+ object section = GetSection("appSettings");
+ if (!(section is NameValueCollection))
+ {
+ // If config is null or not the type we expect, the declaration was changed.
+ // Treat it as a configuration error.
+ throw new ConfigurationErrorsException(SR.Config_appsettings_declaration_invalid);
+ }
+
+ return (NameValueCollection)section;
+ }
+ }
+
+ public static ConnectionStringSettingsCollection ConnectionStrings
+ {
+ get
+ {
+ object section = GetSection("connectionStrings");
+
+ // Verify type, and return the collection
+ if ((section == null) || (section.GetType() != typeof(ConnectionStringsSection)))
+ {
+ // If config is null or not the type we expect, the declaration was changed.
+ // Treat it as a configuration error.
+ throw new ConfigurationErrorsException(SR.Config_connectionstrings_declaration_invalid);
+ }
+
+ ConnectionStringsSection connectionStringsSection = (ConnectionStringsSection)section;
+ return connectionStringsSection.ConnectionStrings;
+ }
+ }
+
+ // Called by ASP.NET to allow hierarchical configuration settings and ASP.NET specific extenstions.
+ internal static void SetConfigurationSystem(IInternalConfigSystem configSystem, bool initComplete)
+ {
+ lock (s_initLock)
+ {
+ // It is an error if the configuration system has already been set.
+ if (s_initState != InitState.NotStarted)
+ throw new InvalidOperationException(SR.Config_system_already_set);
+
+ s_configSystem = configSystem;
+ s_initState = initComplete ? InitState.Completed : InitState.Usable;
+ }
+ }
+
+ private static void EnsureConfigurationSystem()
+ {
+ // If a configuration system has not yet been set,
+ // create the DefaultConfigurationSystem for exe's.
+ lock (s_initLock)
+ {
+ if (s_initState >= InitState.Usable) return;
+
+ s_initState = InitState.Started;
+ try
+ {
+ try
+ {
+ // Create the system, but let it initialize itself when GetConfig is called,
+ // so that it can handle its own re-entrancy issues during initialization.
+ //
+ // When initialization is complete, the DefaultConfigurationSystem will call
+ // CompleteConfigInit to mark initialization as having completed.
+ //
+ // Note: the ClientConfigurationSystem has a 2-stage initialization,
+ // and that's why s_initState isn't set to InitState.Completed yet.
+ s_configSystem = new ClientConfigurationSystem();
+ s_initState = InitState.Usable;
+ }
+ catch (Exception e)
+ {
+ s_initError =
+ new ConfigurationErrorsException(SR.Config_client_config_init_error, e);
+ throw s_initError;
+ }
+ }
+ catch
+ {
+ s_initState = InitState.Completed;
+ throw;
+ }
+ }
+ }
+
+ // Set the initialization error.
+ internal static void SetInitError(Exception initError)
+ {
+ s_initError = initError;
+ }
+
+ // Mark intiailization as having completed.
+ internal static void CompleteConfigInit()
+ {
+ lock (s_initLock)
+ {
+ s_initState = InitState.Completed;
+ }
+ }
+
+
+ private static void PrepareConfigSystem()
+ {
+ // Ensure the configuration system is usable.
+ if (s_initState < InitState.Usable) EnsureConfigurationSystem();
+
+ // If there was an initialization error, throw it.
+ if (s_initError != null) throw s_initError;
+ }
+
+ public static object GetSection(string sectionName)
+ {
+ // Avoid unintended AV's by ensuring sectionName is not empty.
+ // For compatibility, we cannot throw an InvalidArgumentException.
+ if (string.IsNullOrEmpty(sectionName)) return null;
+
+ PrepareConfigSystem();
+
+ object section = s_configSystem.GetSection(sectionName);
+ return section;
+ }
+
+ public static void RefreshSection(string sectionName)
+ {
+ // Avoid unintended AV's by ensuring sectionName is not empty.
+ // For consistency with GetSection, we should not throw an InvalidArgumentException.
+ if (string.IsNullOrEmpty(sectionName)) return;
+
+ PrepareConfigSystem();
+
+ s_configSystem.RefreshConfig(sectionName);
+ }
+
+ public static Configuration OpenMachineConfiguration()
+ {
+ return OpenExeConfigurationImpl(null, true, ConfigurationUserLevel.None, null);
+ }
+
+ public static Configuration OpenMappedMachineConfiguration(ConfigurationFileMap fileMap)
+ {
+ return OpenExeConfigurationImpl(fileMap, true, ConfigurationUserLevel.None, null);
+ }
+
+ public static Configuration OpenExeConfiguration(ConfigurationUserLevel userLevel)
+ {
+ return OpenExeConfigurationImpl(null, false, userLevel, null);
+ }
+
+ public static Configuration OpenExeConfiguration(string exePath)
+ {
+ return OpenExeConfigurationImpl(null, false, ConfigurationUserLevel.None, exePath);
+ }
+
+ public static Configuration OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap,
+ ConfigurationUserLevel userLevel)
+ {
+ return OpenExeConfigurationImpl(fileMap, false, userLevel, null);
+ }
+
+ public static Configuration OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap,
+ ConfigurationUserLevel userLevel, bool preLoad)
+ {
+ return OpenExeConfigurationImpl(fileMap, false, userLevel, null, preLoad);
+ }
+
+ private static Configuration OpenExeConfigurationImpl(ConfigurationFileMap fileMap, bool isMachine,
+ ConfigurationUserLevel userLevel, string exePath, bool preLoad = false)
+ {
+ // exePath must be specified if not running inside ClientConfigurationSystem
+ if (!isMachine &&
+ (((fileMap == null) && (exePath == null)) ||
+ ((fileMap != null) && (((ExeConfigurationFileMap)fileMap).ExeConfigFilename == null))))
+ {
+ if ((s_configSystem != null) &&
+ (s_configSystem.GetType() != typeof(ClientConfigurationSystem)))
+ throw new ArgumentException(SR.Config_configmanager_open_noexe);
+ }
+
+ Configuration config = ClientConfigurationHost.OpenExeConfiguration(fileMap, isMachine, userLevel, exePath);
+ if (preLoad) PreloadConfiguration(config);
+ return config;
+ }
+
+ /// <summary>
+ /// Recursively loads configuration section groups and sections belonging to a configuration object.
+ /// </summary>
+ private static void PreloadConfiguration(Configuration configuration)
+ {
+ if (null == configuration) return;
+
+ // Preload root-level sections.
+ foreach (ConfigurationSection section in configuration.Sections) { }
+
+ // Recursively preload all section groups and sections.
+ foreach (ConfigurationSectionGroup sectionGroup in configuration.SectionGroups)
+ PreloadConfigurationSectionGroup(sectionGroup);
+ }
+
+ private static void PreloadConfigurationSectionGroup(ConfigurationSectionGroup sectionGroup)
+ {
+ if (null == sectionGroup) return;
+
+ // Preload sections just by iterating.
+ foreach (ConfigurationSection section in sectionGroup.Sections) { }
+
+ // Load child section groups.
+ foreach (ConfigurationSectionGroup childSectionGroup in sectionGroup.SectionGroups)
+ PreloadConfigurationSectionGroup(childSectionGroup);
+ }
+
+ private enum InitState
+ {
+ // Initialization has not yet started.
+ NotStarted = 0,
+
+ // Initialization has started.
+ Started,
+
+ // The config system can be used, but initialization is not yet complete.
+ Usable,
+
+ // The config system has been completely initialized.
+ Completed
+ };
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationPermission.cs b/src/System.Configuration/src/System/Configuration/ConfigurationPermission.cs
new file mode 100644
index 0000000000..f05826dd61
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationPermission.cs
@@ -0,0 +1,151 @@
+// 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.Security;
+using System.Security.Permissions;
+
+namespace System.Configuration
+{
+ [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
+ [Serializable]
+ public sealed class ConfigurationPermissionAttribute : CodeAccessSecurityAttribute
+ {
+ public ConfigurationPermissionAttribute(SecurityAction action) : base(action) { }
+
+ public override IPermission CreatePermission()
+ {
+ PermissionState state = Unrestricted
+ ? PermissionState.Unrestricted
+ : PermissionState.None;
+
+ return new ConfigurationPermission(state);
+ }
+ }
+
+ //
+ // ConfigurationPermission is used to grant access to configuration sections that
+ // would not otherwise be available if the caller attempted to read the configuration
+ // files that make up configuration.
+ //
+ // The permission is a simple boolean one - it is either fully granted or denied.
+ // This boolean state is represented by using the PermissionState enumeration.
+ //
+ [Serializable]
+ public sealed class ConfigurationPermission : CodeAccessPermission, IUnrestrictedPermission
+ {
+ private PermissionState _permissionState; // Unrestricted or None
+
+ //
+ // Creates a new instance of ConfigurationPermission
+ // that passes all demands or that fails all demands.
+ //
+ public ConfigurationPermission(PermissionState state)
+ {
+ // validate state parameter
+ switch (state)
+ {
+ case PermissionState.Unrestricted:
+ case PermissionState.None:
+ _permissionState = state;
+ break;
+
+ default:
+ throw ExceptionUtil.ParameterInvalid("state");
+ }
+ }
+
+ public bool IsUnrestricted()
+ {
+ return _permissionState == PermissionState.Unrestricted;
+ }
+
+ public override IPermission Copy()
+ {
+ return new ConfigurationPermission(_permissionState);
+ }
+
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null) return Copy();
+
+ if (target.GetType() != typeof(ConfigurationPermission)) throw ExceptionUtil.ParameterInvalid("target");
+
+ // Create an Unrestricted permission if either this or other is unrestricted
+ if (_permissionState == PermissionState.Unrestricted)
+ return new ConfigurationPermission(PermissionState.Unrestricted);
+ ConfigurationPermission other = (ConfigurationPermission)target;
+ return new ConfigurationPermission(other._permissionState);
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null) return null;
+
+ if (target.GetType() != typeof(ConfigurationPermission)) throw ExceptionUtil.ParameterInvalid("target");
+
+ // Create an None permission if either this or other is None
+ if (_permissionState == PermissionState.None) return new ConfigurationPermission(PermissionState.None);
+ ConfigurationPermission other = (ConfigurationPermission)target;
+ return new ConfigurationPermission(other._permissionState);
+ }
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null) return _permissionState == PermissionState.None;
+
+ if (target.GetType() != typeof(ConfigurationPermission)) throw ExceptionUtil.ParameterInvalid("target");
+
+ ConfigurationPermission other = (ConfigurationPermission)target;
+ return (_permissionState == PermissionState.None) ||
+ (other._permissionState == PermissionState.Unrestricted);
+ }
+
+ public override void FromXml(SecurityElement securityElement)
+ {
+ if (securityElement == null)
+ throw new ArgumentNullException(string.Format(SR.ConfigurationPermissionBadXml, "securityElement"));
+
+ if (!securityElement.Tag.Equals("IPermission"))
+ throw new ArgumentException(string.Format(SR.ConfigurationPermissionBadXml, "securityElement"));
+
+ string className = securityElement.Attribute("class");
+ if (className == null)
+ throw new ArgumentException(string.Format(SR.ConfigurationPermissionBadXml, "securityElement"));
+
+ if (className.IndexOf(GetType().FullName, StringComparison.Ordinal) < 0)
+ throw new ArgumentException(string.Format(SR.ConfigurationPermissionBadXml, "securityElement"));
+
+ string version = securityElement.Attribute("version");
+ if (version != "1") throw new ArgumentException(string.Format(SR.ConfigurationPermissionBadXml, "version"));
+
+ string unrestricted = securityElement.Attribute("Unrestricted");
+ if (unrestricted == null) _permissionState = PermissionState.None;
+ else
+ {
+ switch (unrestricted)
+ {
+ case "true":
+ _permissionState = PermissionState.Unrestricted;
+ break;
+ case "false":
+ _permissionState = PermissionState.None;
+ break;
+ default:
+ throw new ArgumentException(string.Format(SR.ConfigurationPermissionBadXml, "Unrestricted"));
+ }
+ }
+ }
+
+ public override SecurityElement ToXml()
+ {
+ SecurityElement securityElement = new SecurityElement("IPermission");
+ securityElement.AddAttribute("class",
+ GetType().FullName + ", " + GetType().Module.Assembly.FullName.Replace('\"', '\''));
+ securityElement.AddAttribute("version", "1");
+ if (IsUnrestricted()) securityElement.AddAttribute("Unrestricted", "true");
+
+ return securityElement;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationProperty.cs b/src/System.Configuration/src/System/Configuration/ConfigurationProperty.cs
new file mode 100644
index 0000000000..f89c634f0c
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationProperty.cs
@@ -0,0 +1,379 @@
+// 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.ComponentModel;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace System.Configuration
+{
+ public sealed class ConfigurationProperty
+ {
+ internal static readonly ConfigurationValidatorBase s_nonEmptyStringValidator = new StringValidator(1);
+ private static readonly ConfigurationValidatorBase s_defaultValidatorInstance = new DefaultValidator();
+ internal static readonly string s_defaultCollectionPropertyName = "";
+ private TypeConverter _converter;
+ private volatile bool _isConfigurationElementType;
+ private volatile bool _isTypeInited;
+ private ConfigurationPropertyOptions _options;
+
+ public ConfigurationProperty(string name, Type type)
+ {
+ object defaultValue = null;
+
+ ConstructorInit(name, type, ConfigurationPropertyOptions.None, null, null);
+
+ if (type == typeof(string)) defaultValue = string.Empty;
+ else
+ {
+ if (type.IsValueType) defaultValue = TypeUtil.CreateInstance(type);
+ }
+ SetDefaultValue(defaultValue);
+ }
+
+ public ConfigurationProperty(string name, Type type, object defaultValue)
+ : this(name, type, defaultValue, ConfigurationPropertyOptions.None)
+ { }
+
+ public ConfigurationProperty(string name, Type type, object defaultValue, ConfigurationPropertyOptions options)
+ : this(name, type, defaultValue, null, null, options)
+ { }
+
+ public ConfigurationProperty(string name,
+ Type type,
+ object defaultValue,
+ TypeConverter typeConverter,
+ ConfigurationValidatorBase validator,
+ ConfigurationPropertyOptions options)
+ : this(name, type, defaultValue, typeConverter, validator, options, null)
+ { }
+
+ public ConfigurationProperty(string name,
+ Type type,
+ object defaultValue,
+ TypeConverter typeConverter,
+ ConfigurationValidatorBase validator,
+ ConfigurationPropertyOptions options,
+ string description)
+ {
+ ConstructorInit(name, type, options, validator, typeConverter);
+
+ SetDefaultValue(defaultValue);
+ }
+
+ internal ConfigurationProperty(PropertyInfo info)
+ {
+ Debug.Assert(info != null, "info != null");
+
+ // Bellow are the attributes we handle
+ ConfigurationPropertyAttribute attribProperty = null;
+
+ // Compatability attributes
+ // If the approprite data is provided in the ConfigPropAttribute then the one bellow will be ignored
+ DescriptionAttribute attribStdDescription = null;
+ DefaultValueAttribute attribStdDefault = null;
+
+ TypeConverter typeConverter = null;
+ ConfigurationValidatorBase validator = null;
+
+ // Find the interesting attributes in the collection
+ foreach (Attribute attribute in Attribute.GetCustomAttributes(info))
+ if (attribute is TypeConverterAttribute)
+ {
+ TypeConverterAttribute attribConverter = (TypeConverterAttribute)attribute;
+ typeConverter = TypeUtil.CreateInstance<TypeConverter>(attribConverter.ConverterTypeName);
+ }
+ else
+ {
+ if (attribute is ConfigurationPropertyAttribute)
+ attribProperty = (ConfigurationPropertyAttribute)attribute;
+ else
+ {
+ if (attribute is ConfigurationValidatorAttribute)
+ {
+ // There could be more then one validator attribute specified on a property
+ // Currently we consider this an error since it's too late to fix it for whidbey
+ // but the right thing to do is to introduce new validator type ( CompositeValidator ) that is a list of validators and executes
+ // them all
+
+ if (validator != null)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Validator_multiple_validator_attributes, info.Name));
+ }
+
+ ConfigurationValidatorAttribute attribValidator = (ConfigurationValidatorAttribute)attribute;
+ attribValidator.SetDeclaringType(info.DeclaringType);
+ validator = attribValidator.ValidatorInstance;
+ }
+ else
+ {
+ if (attribute is DescriptionAttribute)
+ attribStdDescription = (DescriptionAttribute)attribute;
+ else
+ {
+ if (attribute is DefaultValueAttribute)
+ attribStdDefault = (DefaultValueAttribute)attribute;
+ }
+ }
+ }
+ }
+
+ Type propertyType = info.PropertyType;
+ // Collections need some customization when the collection attribute is present
+ if (typeof(ConfigurationElementCollection).IsAssignableFrom(propertyType))
+ {
+ ConfigurationCollectionAttribute attribCollection =
+ Attribute.GetCustomAttribute(info,
+ typeof(ConfigurationCollectionAttribute)) as ConfigurationCollectionAttribute ??
+ Attribute.GetCustomAttribute(propertyType,
+ typeof(ConfigurationCollectionAttribute)) as ConfigurationCollectionAttribute;
+
+ // If none on the property - see if there is an attribute on the collection type itself
+ if (attribCollection != null)
+ {
+ if (attribCollection.AddItemName.IndexOf(',') == -1) AddElementName = attribCollection.AddItemName;
+ RemoveElementName = attribCollection.RemoveItemName;
+ ClearElementName = attribCollection.ClearItemsName;
+ }
+ }
+
+ // This constructor shouldnt be invoked if the reflection info is not for an actual config property
+ Debug.Assert(attribProperty != null, "attribProperty != null");
+
+ ConstructorInit(attribProperty.Name,
+ info.PropertyType,
+ attribProperty.Options,
+ validator,
+ typeConverter);
+
+ // Figure out the default value
+ InitDefaultValueFromTypeInfo(attribProperty, attribStdDefault);
+
+ // Get the description
+ if (!string.IsNullOrEmpty(attribStdDescription?.Description))
+ Description = attribStdDescription.Description;
+ }
+
+ public string Name { get; private set; }
+
+ public string Description { get; }
+
+ internal string ProvidedName { get; private set; }
+
+ internal bool IsConfigurationElementType
+ {
+ get
+ {
+ if (_isTypeInited) return _isConfigurationElementType;
+
+ _isConfigurationElementType = typeof(ConfigurationElement).IsAssignableFrom(Type);
+ _isTypeInited = true;
+ return _isConfigurationElementType;
+ }
+ }
+
+ public Type Type { get; private set; }
+
+ public object DefaultValue { get; private set; }
+
+ public bool IsRequired => (_options & ConfigurationPropertyOptions.IsRequired) != 0;
+
+ public bool IsKey => (_options & ConfigurationPropertyOptions.IsKey) != 0;
+
+ public bool IsDefaultCollection => (_options & ConfigurationPropertyOptions.IsDefaultCollection) != 0;
+
+ public bool IsTypeStringTransformationRequired
+ => (_options & ConfigurationPropertyOptions.IsTypeStringTransformationRequired) != 0;
+
+ public bool IsAssemblyStringTransformationRequired
+ => (_options & ConfigurationPropertyOptions.IsAssemblyStringTransformationRequired) != 0;
+
+ public bool IsVersionCheckRequired => (_options & ConfigurationPropertyOptions.IsVersionCheckRequired) != 0;
+
+ public TypeConverter Converter
+ {
+ get
+ {
+ CreateConverter();
+ return _converter;
+ }
+ }
+
+ public ConfigurationValidatorBase Validator { get; private set; }
+
+ internal string AddElementName { get; }
+
+ internal string RemoveElementName { get; }
+
+ internal string ClearElementName { get; }
+
+ private void ConstructorInit(string name,
+ Type type,
+ ConfigurationPropertyOptions options,
+ ConfigurationValidatorBase validator,
+ TypeConverter converter)
+ {
+ if (typeof(ConfigurationSection).IsAssignableFrom(type))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_properties_may_not_be_derived_from_configuration_section, name));
+ }
+
+ ProvidedName = name; // save the provided name so we can check for default collection names
+ if (((options & ConfigurationPropertyOptions.IsDefaultCollection) != 0) &&
+ string.IsNullOrEmpty(name))
+ name = s_defaultCollectionPropertyName;
+ else ValidatePropertyName(name);
+
+ Name = name;
+ Type = type;
+ _options = options;
+ Validator = validator;
+ _converter = converter;
+
+ // Use the default validator if none was supplied
+ if (Validator == null) Validator = s_defaultValidatorInstance;
+ else
+ {
+ // Make sure the supplied validator supports the type of this property
+ if (!Validator.CanValidate(Type))
+ throw new ConfigurationErrorsException(string.Format(SR.Validator_does_not_support_prop_type, Name));
+ }
+ }
+
+ private void ValidatePropertyName(string name)
+ {
+ if (string.IsNullOrEmpty(name)) throw new ArgumentException(SR.String_null_or_empty, nameof(name));
+
+ if (BaseConfigurationRecord.IsReservedAttributeName(name))
+ throw new ArgumentException(string.Format(SR.Property_name_reserved, name));
+ }
+
+ private void SetDefaultValue(object value)
+ {
+ // Validate the default value if any. This should make errors from invalid defaults easier to catch
+ if ((value == null) || (value == ConfigurationElement.s_nullPropertyValue)) return;
+
+ if (!Type.IsInstanceOfType(value))
+ {
+ if (Converter.CanConvertFrom(value.GetType()))
+ value = Converter.ConvertFrom(value);
+ else
+ throw new ConfigurationErrorsException(string.Format(SR.Default_value_wrong_type, Name));
+ }
+
+ Validate(value);
+ DefaultValue = value;
+ }
+
+ private void InitDefaultValueFromTypeInfo(ConfigurationPropertyAttribute attribProperty,
+ DefaultValueAttribute attribStdDefault)
+ {
+ object defaultValue = attribProperty.DefaultValue;
+
+ // If there is no default value there - try the other attribute ( the clr standard one )
+ if (((defaultValue == null) || (defaultValue == ConfigurationElement.s_nullPropertyValue)) &&
+ (attribStdDefault != null))
+ defaultValue = attribStdDefault.Value;
+
+ // If there was a default value in the prop attribute - check if we need to convert it from string
+ if (defaultValue is string && (Type != typeof(string)))
+ {
+ // Use the converter to parse this property default value
+ try
+ {
+ defaultValue = Converter.ConvertFromInvariantString((string)defaultValue);
+ }
+ catch (Exception ex)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Default_value_conversion_error_from_string,
+ Name, ex.Message));
+ }
+ }
+
+ if ((defaultValue == null) || (defaultValue == ConfigurationElement.s_nullPropertyValue))
+ {
+ if (Type == typeof(string)) defaultValue = string.Empty;
+ else
+ {
+ if (Type.IsValueType) defaultValue = TypeUtil.CreateInstance(Type);
+ }
+ }
+ SetDefaultValue(defaultValue);
+ }
+
+ internal object ConvertFromString(string value)
+ {
+ object result;
+
+ try
+ {
+ result = Converter.ConvertFromInvariantString(value);
+ }
+ catch (Exception ex)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Top_level_conversion_error_from_string, Name,
+ ex.Message));
+ }
+
+ return result;
+ }
+
+ internal string ConvertToString(object value)
+ {
+ string result;
+
+ try
+ {
+ if (Type == typeof(bool))
+ result = (bool)value ? "true" : "false"; // the converter will break 1.1 compat for bool
+ else result = Converter.ConvertToInvariantString(value);
+ }
+ catch (Exception ex)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Top_level_conversion_error_to_string, Name,
+ ex.Message));
+ }
+
+ return result;
+ }
+
+ internal void Validate(object value)
+ {
+ try
+ {
+ Validator.Validate(value);
+ }
+ catch (Exception ex)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Top_level_validation_error, Name, ex.Message),
+ ex);
+ }
+ }
+
+ private void CreateConverter()
+ {
+ // Some properties cannot have type converters.
+ // Such examples are properties that are ConfigurationElement ( derived classes )
+ // or properties which are user-defined and the user code handles serialization/desirialization so
+ // the property itself is never converted to/from string
+
+ if (_converter != null) return;
+
+ // Enums are exception. We use our custom converter for all enums
+ if (Type.IsEnum) _converter = new GenericEnumConverter(Type);
+ else
+ {
+ if (Type.IsSubclassOf(typeof(ConfigurationElement))) return;
+
+ _converter = TypeDescriptor.GetConverter(Type);
+ if ((_converter == null) ||
+ !_converter.CanConvertFrom(typeof(string)) ||
+ !_converter.CanConvertTo(typeof(string)))
+ throw new ConfigurationErrorsException(string.Format(SR.No_converter, Name, Type.Name));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationPropertyAttribute.cs b/src/System.Configuration/src/System/Configuration/ConfigurationPropertyAttribute.cs
new file mode 100644
index 0000000000..7bf8435ef3
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationPropertyAttribute.cs
@@ -0,0 +1,57 @@
+// 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.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class ConfigurationPropertyAttribute : Attribute
+ {
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ internal static readonly string s_defaultCollectionPropertyName = "";
+#pragma warning restore 0414
+
+ public ConfigurationPropertyAttribute(string name)
+ {
+ Name = name;
+ }
+
+ public string Name { get; }
+
+ public object DefaultValue { get; set; } = ConfigurationElement.s_nullPropertyValue;
+
+ public ConfigurationPropertyOptions Options { get; set; } = ConfigurationPropertyOptions.None;
+
+ public bool IsDefaultCollection
+ {
+ get { return (Options & ConfigurationPropertyOptions.IsDefaultCollection) != 0; }
+ set
+ {
+ if (value) Options |= ConfigurationPropertyOptions.IsDefaultCollection;
+ else
+ Options &= ~ConfigurationPropertyOptions.IsDefaultCollection;
+ }
+ }
+
+ public bool IsRequired
+ {
+ get { return (Options & ConfigurationPropertyOptions.IsRequired) != 0; }
+ set
+ {
+ if (value) Options |= ConfigurationPropertyOptions.IsRequired;
+ else Options &= ~ConfigurationPropertyOptions.IsRequired;
+ }
+ }
+
+ public bool IsKey
+ {
+ get { return (Options & ConfigurationPropertyOptions.IsKey) != 0; }
+ set
+ {
+ if (value) Options |= ConfigurationPropertyOptions.IsKey;
+ else Options &= ~ConfigurationPropertyOptions.IsKey;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationPropertyCollection.cs b/src/System.Configuration/src/System/Configuration/ConfigurationPropertyCollection.cs
new file mode 100644
index 0000000000..b4d4f525ae
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationPropertyCollection.cs
@@ -0,0 +1,83 @@
+// 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.Configuration
+{
+ public class ConfigurationPropertyCollection : ICollection
+ {
+ private readonly ArrayList _items = new ArrayList();
+
+ internal ConfigurationProperty DefaultCollectionProperty
+ => this[ConfigurationProperty.s_defaultCollectionPropertyName];
+
+ public ConfigurationProperty this[string name]
+ {
+ get
+ {
+ for (int index = 0; index < _items.Count; index++)
+ {
+ ConfigurationProperty cp = (ConfigurationProperty)_items[index];
+ if (cp.Name == name) return (ConfigurationProperty)_items[index];
+ }
+ return null;
+ }
+ }
+
+ public int Count => _items.Count;
+
+ public bool IsSynchronized => false;
+
+ public object SyncRoot => _items;
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ _items.CopyTo(array, index);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _items.GetEnumerator();
+ }
+
+ public void CopyTo(ConfigurationProperty[] array, int index)
+ {
+ ((ICollection)this).CopyTo(array, index);
+ }
+
+ public bool Contains(string name)
+ {
+ for (int index = 0; index < _items.Count; index++)
+ {
+ ConfigurationProperty cp = (ConfigurationProperty)_items[index];
+ if (cp.Name == name) return true;
+ }
+ return false;
+ }
+
+ public void Add(ConfigurationProperty property)
+ {
+ if (Contains(property.Name) != true) _items.Add(property);
+ }
+
+ public bool Remove(string name)
+ {
+ for (int index = 0; index < _items.Count; index++)
+ {
+ ConfigurationProperty cp = (ConfigurationProperty)_items[index];
+ if (cp.Name != name) continue;
+
+ _items.RemoveAt(index);
+ return true;
+ }
+ return false;
+ }
+
+ public void Clear()
+ {
+ _items.Clear();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationPropertyOptions.cs b/src/System.Configuration/src/System/Configuration/ConfigurationPropertyOptions.cs
new file mode 100644
index 0000000000..85fb56d189
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationPropertyOptions.cs
@@ -0,0 +1,18 @@
+// 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.Configuration
+{
+ [Flags]
+ public enum ConfigurationPropertyOptions
+ {
+ None = 0,
+ IsDefaultCollection = 0x00000001,
+ IsRequired = 0x00000002,
+ IsKey = 0x00000004,
+ IsTypeStringTransformationRequired = 0x00000008,
+ IsAssemblyStringTransformationRequired = 0x00000010,
+ IsVersionCheckRequired = 0x00000020,
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationSaveMode.cs b/src/System.Configuration/src/System/Configuration/ConfigurationSaveMode.cs
new file mode 100644
index 0000000000..e98212e3c6
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationSaveMode.cs
@@ -0,0 +1,22 @@
+// 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.Configuration
+{
+ // Determines how much of configuration is written out on save.
+ public enum ConfigurationSaveMode
+ {
+ // If a setting is modified, it'll get written no matter it's
+ // same as the parent or not.
+ Modified = 0,
+
+ // If a setting is the same as in its parent, it won't get written
+ Minimal = 1,
+
+ // It writes out all the properties in the configurationat that level,
+ // including the one from the parents. Used for writing out the
+ // full config settings at a file.
+ Full = 2,
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationSchemaErrors.cs b/src/System.Configuration/src/System/Configuration/ConfigurationSchemaErrors.cs
new file mode 100644
index 0000000000..e5c1c0f06f
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationSchemaErrors.cs
@@ -0,0 +1,99 @@
+// 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.Generic;
+
+namespace System.Configuration
+{
+ internal class ConfigurationSchemaErrors
+ {
+ // All errors related to a config file are logged to this list.
+ // This includes all global errors, all non-specific errors,
+ // and local errors for input that applies to this config file.
+ private List<ConfigurationException> _errorsAll;
+
+ // Errors with ExceptionAction.Global are logged to this list.
+ private List<ConfigurationException> _errorsGlobal;
+
+ // Errors with ExceptionAction.Local are logged to this list.
+ // This list is reset when processing of a section is complete.
+ // Errors on this list may be added to the _errorsAll list
+ // when RetrieveAndResetLocalErrors is called.
+ private List<ConfigurationException> _errorsLocal;
+
+ internal bool HasLocalErrors => ErrorsHelper.GetHasErrors(_errorsLocal);
+
+ internal bool HasGlobalErrors => ErrorsHelper.GetHasErrors(_errorsGlobal);
+
+ private bool HasAllErrors => ErrorsHelper.GetHasErrors(_errorsAll);
+
+ internal int GlobalErrorCount => ErrorsHelper.GetErrorCount(_errorsGlobal);
+
+ internal void AddError(ConfigurationException ce, ExceptionAction action)
+ {
+ switch (action)
+ {
+ case ExceptionAction.Global:
+ ErrorsHelper.AddError(ref _errorsAll, ce);
+ ErrorsHelper.AddError(ref _errorsGlobal, ce);
+ break;
+ case ExceptionAction.NonSpecific:
+ ErrorsHelper.AddError(ref _errorsAll, ce);
+ break;
+ case ExceptionAction.Local:
+ ErrorsHelper.AddError(ref _errorsLocal, ce);
+ break;
+ }
+ }
+
+ internal void SetSingleGlobalError(ConfigurationException ce)
+ {
+ _errorsAll = null;
+ _errorsLocal = null;
+ _errorsGlobal = null;
+
+ AddError(ce, ExceptionAction.Global);
+ }
+
+ internal bool HasErrors(bool ignoreLocal)
+ {
+ return ignoreLocal ? HasGlobalErrors : HasAllErrors;
+ }
+
+ internal void ThrowIfErrors(bool ignoreLocal)
+ {
+ if (!HasErrors(ignoreLocal)) return;
+
+ if (HasGlobalErrors)
+ {
+ // Throw just the global errors, as they invalidate
+ // all other config file parsing.
+ throw new ConfigurationErrorsException(_errorsGlobal);
+ }
+
+ // Throw all errors no matter what
+ throw new ConfigurationErrorsException(_errorsAll);
+ }
+
+ internal List<ConfigurationException> RetrieveAndResetLocalErrors(bool keepLocalErrors)
+ {
+ List<ConfigurationException> list = _errorsLocal;
+ _errorsLocal = null;
+
+ if (keepLocalErrors) ErrorsHelper.AddErrors(ref _errorsAll, list);
+
+ return list;
+ }
+
+ internal void AddSavedLocalErrors(ICollection<ConfigurationException> coll)
+ {
+ ErrorsHelper.AddErrors(ref _errorsAll, coll);
+ }
+
+ internal void ResetLocalErrors()
+ {
+ RetrieveAndResetLocalErrors(false);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationSection.cs b/src/System.Configuration/src/System/Configuration/ConfigurationSection.cs
new file mode 100644
index 0000000000..e2c83ef0f9
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationSection.cs
@@ -0,0 +1,98 @@
+// 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.Globalization;
+using System.IO;
+using System.Runtime.Versioning;
+using System.Xml;
+
+namespace System.Configuration
+{
+ public abstract class ConfigurationSection : ConfigurationElement
+ {
+ protected ConfigurationSection()
+ {
+ SectionInformation = new SectionInformation(this);
+ }
+
+ public SectionInformation SectionInformation { get; }
+
+ protected internal virtual object GetRuntimeObject()
+ {
+ return this;
+ }
+
+ protected internal override bool IsModified()
+ {
+ return SectionInformation.IsModifiedFlags() ||
+ base.IsModified();
+ }
+
+ protected internal override void ResetModified()
+ {
+ SectionInformation.ResetModifiedFlags();
+ base.ResetModified();
+ }
+
+ protected internal virtual void DeserializeSection(XmlReader reader)
+ {
+ if (!reader.Read() || (reader.NodeType != XmlNodeType.Element))
+ throw new ConfigurationErrorsException(SR.Config_base_expected_to_find_element, reader);
+
+ DeserializeElement(reader, false);
+ }
+
+ protected internal virtual string SerializeSection(ConfigurationElement parentElement, string name,
+ ConfigurationSaveMode saveMode)
+ {
+ if ((CurrentConfiguration != null) &&
+ (CurrentConfiguration.TargetFramework != null) &&
+ !ShouldSerializeSectionInTargetVersion(CurrentConfiguration.TargetFramework))
+ return string.Empty;
+
+ ValidateElement(this, null, true);
+
+ ConfigurationElement tempElement = CreateElement(GetType());
+ tempElement.Unmerge(this, parentElement, saveMode);
+
+ StringWriter strWriter = new StringWriter(CultureInfo.InvariantCulture);
+ XmlTextWriter writer = new XmlTextWriter(strWriter)
+ {
+ Formatting = Formatting.Indented,
+ Indentation = 4,
+ IndentChar = ' '
+ };
+
+ tempElement.DataToWriteInternal = saveMode != ConfigurationSaveMode.Minimal;
+
+ if ((CurrentConfiguration != null) && (CurrentConfiguration.TargetFramework != null))
+ _configRecord.SectionsStack.Push(this);
+
+ tempElement.SerializeToXmlElement(writer, name);
+
+ if ((CurrentConfiguration != null) && (CurrentConfiguration.TargetFramework != null))
+ _configRecord.SectionsStack.Pop();
+
+ writer.Flush();
+ return strWriter.ToString();
+ }
+
+ protected internal virtual bool ShouldSerializePropertyInTargetVersion(ConfigurationProperty property,
+ string propertyName, FrameworkName targetFramework, ConfigurationElement parentConfigurationElement)
+ {
+ return true;
+ }
+
+ protected internal virtual bool ShouldSerializeElementInTargetVersion(ConfigurationElement element,
+ string elementName, FrameworkName targetFramework)
+ {
+ return true;
+ }
+
+ protected internal virtual bool ShouldSerializeSectionInTargetVersion(FrameworkName targetFramework)
+ {
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationSectionCollection.cs b/src/System.Configuration/src/System/Configuration/ConfigurationSectionCollection.cs
new file mode 100644
index 0000000000..5523467023
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationSectionCollection.cs
@@ -0,0 +1,144 @@
+// 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.Collections.Specialized;
+using System.Runtime.Serialization;
+
+namespace System.Configuration
+{
+ [Serializable]
+ public sealed class ConfigurationSectionCollection : NameObjectCollectionBase
+ {
+ private readonly ConfigurationSectionGroup _configSectionGroup;
+ private MgmtConfigurationRecord _configRecord;
+
+ internal ConfigurationSectionCollection(MgmtConfigurationRecord configRecord,
+ ConfigurationSectionGroup configSectionGroup) :
+ base(StringComparer.Ordinal)
+ {
+ _configRecord = configRecord;
+ _configSectionGroup = configSectionGroup;
+
+ foreach (DictionaryEntry de in _configRecord.SectionFactories)
+ {
+ FactoryId factoryId = (FactoryId)de.Value;
+ if (factoryId.Group == _configSectionGroup.SectionGroupName) BaseAdd(factoryId.Name, factoryId.Name);
+ }
+ }
+
+ private ConfigurationSectionCollection(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ : base(serializationInfo, streamingContext)
+ {
+ }
+
+ public ConfigurationSection this[string name] => Get(name);
+
+ public ConfigurationSection this[int index] => Get(index);
+
+ // Remove the collection from configuration system, and remove all entries
+ // in the base collection so that enumeration will return an empty collection.
+ internal void DetachFromConfigurationRecord()
+ {
+ _configRecord = null;
+ BaseClear();
+ }
+
+ private void VerifyIsAttachedToConfigRecord()
+ {
+ if (_configRecord == null)
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsectiongroup_when_not_attached);
+ }
+
+ // Add a new section to the collection. This will result in a new declaration and definition.
+ // It is an error if the section already exists.
+ public void Add(string name, ConfigurationSection section)
+ {
+ VerifyIsAttachedToConfigRecord();
+
+ _configRecord.AddConfigurationSection(_configSectionGroup.SectionGroupName, name, section);
+ BaseAdd(name, name);
+ }
+
+ public void Clear()
+ {
+ VerifyIsAttachedToConfigRecord();
+
+ string[] allKeys = BaseGetAllKeys();
+ foreach (string key in allKeys) Remove(key);
+ }
+
+ public void CopyTo(ConfigurationSection[] array, int index)
+ {
+ if (array == null) throw new ArgumentNullException(nameof(array));
+
+ int c = Count;
+ if (array.Length < c + index) throw new ArgumentOutOfRangeException(nameof(index));
+
+ for (int i = 0, j = index; i < c; i++, j++) array[j] = Get(i);
+ }
+
+ public ConfigurationSection Get(int index)
+ {
+ return Get(GetKey(index));
+ }
+
+ public ConfigurationSection Get(string name)
+ {
+ VerifyIsAttachedToConfigRecord();
+
+ // validate name
+ if (string.IsNullOrEmpty(name))
+ throw ExceptionUtil.ParameterNullOrEmpty("name");
+
+ // prevent GetConfig from returning config not in this collection
+ if (name.IndexOf('/') >= 0)
+ return null;
+
+ // get the section from the config record
+ string configKey = BaseConfigurationRecord.CombineConfigKey(_configSectionGroup.SectionGroupName, name);
+ return (ConfigurationSection)_configRecord.GetSection(configKey);
+ }
+
+ // Get an enumerator
+ public override IEnumerator GetEnumerator()
+ {
+ int c = Count;
+ for (int i = 0; i < c; i++) yield return this[i];
+ }
+
+ // Get the string key at a given index.
+ public string GetKey(int index)
+ {
+ return BaseGetKey(index);
+ }
+
+ // Remove the declaration and definition of a section in this config file, including any
+ // location sections in the file.
+ //
+ // Note that if the section is declared in a parent, we still remove the declaration and
+ // definition, and the instance of ConfigurationSection will be detached from the collection.
+ // However, the collection will still have a ConfigurationSection of that name in the collection,
+ // only it will have the value of the immediate parent.
+ public void Remove(string name)
+ {
+ VerifyIsAttachedToConfigRecord();
+
+ // Remove the factory and section from this record, so that when config is written,
+ // it will contain neither a declaration or definition.
+ _configRecord.RemoveConfigurationSection(_configSectionGroup.SectionGroupName, name);
+
+ // Remove the section from the collection if it is no longer in the list of all SectionFactories.
+ string configKey = BaseConfigurationRecord.CombineConfigKey(_configSectionGroup.SectionGroupName, name);
+ if (!_configRecord.SectionFactories.Contains(configKey)) BaseRemove(name);
+ }
+
+ public void RemoveAt(int index)
+ {
+ VerifyIsAttachedToConfigRecord();
+
+ Remove(GetKey(index));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationSectionGroup.cs b/src/System.Configuration/src/System/Configuration/ConfigurationSectionGroup.cs
new file mode 100644
index 0000000000..7b904e2d27
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationSectionGroup.cs
@@ -0,0 +1,171 @@
+// 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.Versioning;
+
+namespace System.Configuration
+{
+ public class ConfigurationSectionGroup
+ {
+ private MgmtConfigurationRecord _configRecord;
+ private ConfigurationSectionGroupCollection _configSectionGroups;
+ private ConfigurationSectionCollection _configSections;
+ private string _typeName;
+
+ internal bool Attached => _configRecord != null;
+
+ public bool IsDeclared { get; private set; }
+
+ // Is the Declaration Required. It is required if it is not set
+ // int a parent, or the parent entry does not have the type
+ public bool IsDeclarationRequired { get; private set; }
+
+ public string SectionGroupName { get; private set; } = string.Empty;
+
+ public string Name { get; private set; } = string.Empty;
+
+ public string Type
+ {
+ get { return _typeName; }
+ set
+ {
+ if (IsRoot)
+ throw new InvalidOperationException(SR.Config_root_section_group_cannot_be_edited);
+
+ // Since type is optional for a section group, allow it to be removed.
+ // Note that a typename of "" is not permitted in the config file.
+ string typeName = value;
+ if (string.IsNullOrEmpty(typeName)) typeName = null;
+
+ if (_configRecord != null)
+ {
+ if (_configRecord.IsLocationConfig)
+ {
+ throw new InvalidOperationException(
+ SR.Config_cannot_edit_configurationsectiongroup_in_location_config);
+ }
+
+ // allow type to be different from current type,
+ // so long as it doesn't conflict with a type already defined
+ if (typeName != null)
+ {
+ FactoryRecord factoryRecord = FindParentFactoryRecord(false);
+ if ((factoryRecord != null) && !factoryRecord.IsEquivalentType(_configRecord.Host, typeName))
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined,
+ SectionGroupName));
+ }
+ }
+ }
+
+ _typeName = typeName;
+ }
+ }
+
+ public ConfigurationSectionCollection Sections
+ {
+ get
+ {
+ if (_configSections == null)
+ {
+ VerifyIsAttachedToConfigRecord();
+ _configSections = new ConfigurationSectionCollection(_configRecord, this);
+ }
+
+ return _configSections;
+ }
+ }
+
+ public ConfigurationSectionGroupCollection SectionGroups
+ {
+ get
+ {
+ if (_configSectionGroups == null)
+ {
+ VerifyIsAttachedToConfigRecord();
+ _configSectionGroups = new ConfigurationSectionGroupCollection(_configRecord, this);
+ }
+
+ return _configSectionGroups;
+ }
+ }
+
+ internal bool IsRoot { get; private set; }
+
+ internal void AttachToConfigurationRecord(MgmtConfigurationRecord configRecord, FactoryRecord factoryRecord)
+ {
+ _configRecord = configRecord;
+ SectionGroupName = factoryRecord.ConfigKey;
+ Name = factoryRecord.Name;
+ _typeName = factoryRecord.FactoryTypeName;
+
+ if (_typeName != null)
+ {
+ FactoryRecord parentFactoryRecord = null;
+ if (!configRecord.Parent.IsRootConfig)
+ parentFactoryRecord = configRecord.Parent.FindFactoryRecord(factoryRecord.ConfigKey, true);
+
+ IsDeclarationRequired = parentFactoryRecord?.FactoryTypeName == null;
+ IsDeclared = configRecord.GetFactoryRecord(factoryRecord.ConfigKey, true) != null;
+ }
+ }
+
+ internal void RootAttachToConfigurationRecord(MgmtConfigurationRecord configRecord)
+ {
+ _configRecord = configRecord;
+
+ IsRoot = true;
+ }
+
+ internal void DetachFromConfigurationRecord()
+ {
+ _configSections?.DetachFromConfigurationRecord();
+ _configSectionGroups?.DetachFromConfigurationRecord();
+ _configRecord = null;
+ }
+
+ private FactoryRecord FindParentFactoryRecord(bool permitErrors)
+ {
+ FactoryRecord factoryRecord = null;
+
+ if ((_configRecord != null) && !_configRecord.Parent.IsRootConfig)
+ factoryRecord = _configRecord.Parent.FindFactoryRecord(SectionGroupName, permitErrors);
+
+ return factoryRecord;
+ }
+
+ private void VerifyIsAttachedToConfigRecord()
+ {
+ if (_configRecord == null)
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsectiongroup_when_not_attached);
+ }
+
+ public void ForceDeclaration()
+ {
+ ForceDeclaration(true);
+ }
+
+ // Force the declaration to be written. If this is false, it
+ // may be ignored depending on if it is Required
+ public void ForceDeclaration(bool force)
+ {
+ if (IsRoot)
+ throw new InvalidOperationException(SR.Config_root_section_group_cannot_be_edited);
+
+ if ((_configRecord != null) && _configRecord.IsLocationConfig)
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsectiongroup_in_location_config);
+
+ if (!force && IsDeclarationRequired)
+ {
+ // Since it is required, we can not remove it
+ }
+ else IsDeclared = force;
+ }
+
+ protected internal virtual bool ShouldSerializeSectionGroupInTargetVersion(FrameworkName targetFramework)
+ {
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationSectionGroupCollection.cs b/src/System.Configuration/src/System/Configuration/ConfigurationSectionGroupCollection.cs
new file mode 100644
index 0000000000..c675bcb82c
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationSectionGroupCollection.cs
@@ -0,0 +1,144 @@
+// 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.Collections.Specialized;
+using System.Runtime.Serialization;
+
+namespace System.Configuration
+{
+ [Serializable]
+ public sealed class ConfigurationSectionGroupCollection : NameObjectCollectionBase
+ {
+ private readonly ConfigurationSectionGroup _configSectionGroup;
+ private MgmtConfigurationRecord _configRecord;
+
+ internal ConfigurationSectionGroupCollection(MgmtConfigurationRecord configRecord,
+ ConfigurationSectionGroup configSectionGroup) :
+ base(StringComparer.Ordinal)
+ {
+ _configRecord = configRecord;
+ _configSectionGroup = configSectionGroup;
+
+ foreach (DictionaryEntry de in _configRecord.SectionGroupFactories)
+ {
+ FactoryId factoryId = (FactoryId)de.Value;
+ if (factoryId.Group == _configSectionGroup.SectionGroupName) BaseAdd(factoryId.Name, factoryId.Name);
+ }
+ }
+
+ private ConfigurationSectionGroupCollection(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ : base(serializationInfo, streamingContext)
+ {
+ }
+
+ // Indexer via name
+ public ConfigurationSectionGroup this[string name] => Get(name);
+
+ // Indexer via integer index.
+ public ConfigurationSectionGroup this[int index] => Get(index);
+
+ // Remove the collection from configuration system, and remove all entries
+ // in the base collection so that enumeration will return an empty collection.
+ internal void DetachFromConfigurationRecord()
+ {
+ _configRecord = null;
+ BaseClear();
+ }
+
+ private void VerifyIsAttachedToConfigRecord()
+ {
+ if (_configRecord == null)
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsectiongroup_when_not_attached);
+ }
+
+ public void Add(string name, ConfigurationSectionGroup sectionGroup)
+ {
+ VerifyIsAttachedToConfigRecord();
+ _configRecord.AddConfigurationSectionGroup(_configSectionGroup.SectionGroupName, name, sectionGroup);
+ BaseAdd(name, name);
+ }
+
+ public void Clear()
+ {
+ VerifyIsAttachedToConfigRecord();
+
+ // If this is the root section group, do not require the location section to be written
+ // to the file.
+ if (_configSectionGroup.IsRoot) _configRecord.RemoveLocationWriteRequirement();
+
+ string[] allKeys = BaseGetAllKeys();
+ foreach (string key in allKeys) Remove(key);
+ }
+
+ public void CopyTo(ConfigurationSectionGroup[] array, int index)
+ {
+ if (array == null) throw new ArgumentNullException(nameof(array));
+
+ int c = Count;
+ if (array.Length < c + index) throw new ArgumentOutOfRangeException(nameof(index));
+
+ for (int i = 0, j = index; i < c; i++, j++) array[j] = Get(i);
+ }
+
+ public ConfigurationSectionGroup Get(int index)
+ {
+ return Get(GetKey(index));
+ }
+
+ public ConfigurationSectionGroup Get(string name)
+ {
+ VerifyIsAttachedToConfigRecord();
+
+ // validate name
+ if (string.IsNullOrEmpty(name))
+ throw ExceptionUtil.ParameterNullOrEmpty("name");
+
+ // prevent GetConfig from returning config not in this collection
+ if (name.IndexOf('/') >= 0)
+ return null;
+
+ // get the section group
+ string configKey = BaseConfigurationRecord.CombineConfigKey(_configSectionGroup.SectionGroupName, name);
+ return _configRecord.GetSectionGroup(configKey);
+ }
+
+ public override IEnumerator GetEnumerator()
+ {
+ int c = Count;
+ for (int i = 0; i < c; i++) yield return this[i];
+ }
+
+ public string GetKey(int index)
+ {
+ return BaseGetKey(index);
+ }
+
+ // Remove the declaration and definition of a section in this config file, including any
+ // location sections in the file. This will also remove any descendant sections and
+ // section groups.
+ //
+ // Note that if the section group is declared in a parent, we still remove the declaration and
+ // definition, and the instance of ConfigurationSectionGroup will be detached from the collection.
+ // However, the collection will still have a ConfigurationSectionGroup of that name in the collection,
+ // only it will have the value of the immediate parent.
+ public void Remove(string name)
+ {
+ VerifyIsAttachedToConfigRecord();
+
+ _configRecord.RemoveConfigurationSectionGroup(_configSectionGroup.SectionGroupName, name);
+
+ // Remove the section from the collection if it is no longer in the list of all SectionGroupFactories.
+ string configKey = BaseConfigurationRecord.CombineConfigKey(_configSectionGroup.SectionGroupName, name);
+ if (!_configRecord.SectionFactories.Contains(configKey)) BaseRemove(name);
+ }
+
+ public void RemoveAt(int index)
+ {
+ VerifyIsAttachedToConfigRecord();
+
+ Remove(GetKey(index));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationUserLevel.cs b/src/System.Configuration/src/System/Configuration/ConfigurationUserLevel.cs
new file mode 100644
index 0000000000..a93b00513f
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationUserLevel.cs
@@ -0,0 +1,14 @@
+// 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.Configuration
+{
+ // Represents which user.config files are included in the configuration.
+ public enum ConfigurationUserLevel
+ {
+ None = 0,
+ PerUserRoaming = 10,
+ PerUserRoamingAndLocal = 20,
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationValidatorAttribute.cs b/src/System.Configuration/src/System/Configuration/ConfigurationValidatorAttribute.cs
new file mode 100644
index 0000000000..04bd2356b2
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationValidatorAttribute.cs
@@ -0,0 +1,60 @@
+// 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;
+
+namespace System.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public class ConfigurationValidatorAttribute : Attribute
+ {
+ internal Type _declaringType;
+
+ protected ConfigurationValidatorAttribute() { }
+
+ public ConfigurationValidatorAttribute(Type validator)
+ {
+ if (validator == null) throw new ArgumentNullException(nameof(validator));
+
+ if (!typeof(ConfigurationValidatorBase).IsAssignableFrom(validator))
+ {
+ throw new ArgumentException(string.Format(SR.Validator_Attribute_param_not_validator,
+ "ConfigurationValidatorBase"));
+ }
+
+ ValidatorType = validator;
+ }
+
+ public virtual ConfigurationValidatorBase ValidatorInstance
+ => (ConfigurationValidatorBase)TypeUtil.CreateInstance(ValidatorType);
+
+ public Type ValidatorType { get; }
+
+ // Used for limiting the visibility of types that can be accessed in the reflection
+ // call made by the ValidatorInstance property getter. This will normally be the
+ // type that declared the attribute, but in certain cases it could be a subclass
+ // of the type that declared the attribute. This should be ok from a security
+ // perspective, as one wouldn't reasonably expect a derived type to have fewer
+ // security constraints than its base type.
+ internal void SetDeclaringType(Type declaringType)
+ {
+ if (declaringType == null)
+ {
+ Debug.Fail("Declaring type must not be null.");
+ return; // don't throw in an in-place update
+ }
+
+ if (_declaringType == null)
+ {
+ // First call to this method - allow any type to be set
+ _declaringType = declaringType;
+ }
+ else
+ {
+ Debug.Assert(_declaringType == declaringType,
+ "Subsequent calls cannot change the declaring type of the attribute.");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationValidatorBase.cs b/src/System.Configuration/src/System/Configuration/ConfigurationValidatorBase.cs
new file mode 100644
index 0000000000..faf5844d96
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationValidatorBase.cs
@@ -0,0 +1,16 @@
+// 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.Configuration
+{
+ public abstract class ConfigurationValidatorBase
+ {
+ public virtual bool CanValidate(Type type)
+ {
+ return false;
+ }
+
+ public abstract void Validate(object value);
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationValue.cs b/src/System.Configuration/src/System/Configuration/ConfigurationValue.cs
new file mode 100644
index 0000000000..a6f0e2ebaf
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationValue.cs
@@ -0,0 +1,21 @@
+// 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.Configuration
+{
+ internal class ConfigurationValue
+ {
+ internal PropertySourceInfo SourceInfo;
+ internal object Value;
+
+ internal ConfigurationValueFlags ValueFlags;
+
+ internal ConfigurationValue(object value, ConfigurationValueFlags valueFlags, PropertySourceInfo sourceInfo)
+ {
+ Value = value;
+ ValueFlags = valueFlags;
+ SourceInfo = sourceInfo;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationValueFlags.cs b/src/System.Configuration/src/System/Configuration/ConfigurationValueFlags.cs
new file mode 100644
index 0000000000..7b23630ec5
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationValueFlags.cs
@@ -0,0 +1,16 @@
+// 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.Configuration
+{
+ [Flags]
+ internal enum ConfigurationValueFlags
+ {
+ Default = 0,
+ Inherited = 1,
+ Modified = 2,
+ Locked = 4,
+ XmlParentInherited = 8,
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConfigurationValues.cs b/src/System.Configuration/src/System/Configuration/ConfigurationValues.cs
new file mode 100644
index 0000000000..e6d6047c1b
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConfigurationValues.cs
@@ -0,0 +1,215 @@
+// 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.Collections.Specialized;
+
+namespace System.Configuration
+{
+ internal class ConfigurationValues : NameObjectCollectionBase
+ {
+ private static volatile IEnumerable s_emptyCollection;
+ private BaseConfigurationRecord _configRecord;
+ private volatile bool _containsElement;
+ private volatile bool _containsInvalidValue;
+
+ internal ConfigurationValues() : base(StringComparer.Ordinal) { }
+
+ internal object this[string key]
+ {
+ get
+ {
+ ConfigurationValue configValue = GetConfigValue(key);
+ return configValue?.Value;
+ }
+ set { SetValue(key, value, ConfigurationValueFlags.Modified, null); }
+ }
+
+ internal object this[int index]
+ {
+ get
+ {
+ ConfigurationValue configValue = GetConfigValue(index);
+ return configValue?.Value;
+ }
+ }
+
+ internal object SyncRoot => this;
+
+ internal IEnumerable ConfigurationElements
+ => _containsElement ? new ConfigurationElementsCollection(this) : EmptyCollectionInstance;
+
+ internal IEnumerable InvalidValues
+ => _containsInvalidValue ? new InvalidValuesCollection(this) : EmptyCollectionInstance;
+
+ private static IEnumerable EmptyCollectionInstance
+ => s_emptyCollection ?? (s_emptyCollection = new EmptyCollection());
+
+ internal void AssociateContext(BaseConfigurationRecord configRecord)
+ {
+ _configRecord = configRecord;
+
+ // Associate with children
+ foreach (ConfigurationElement currentElement in ConfigurationElements)
+ currentElement.AssociateContext(_configRecord);
+ }
+
+ internal bool Contains(string key)
+ {
+ return BaseGet(key) != null;
+ }
+
+ internal string GetKey(int index)
+ {
+ return BaseGetKey(index);
+ }
+
+ internal ConfigurationValue GetConfigValue(string key)
+ {
+ return (ConfigurationValue)BaseGet(key);
+ }
+
+ internal ConfigurationValue GetConfigValue(int index)
+ {
+ return (ConfigurationValue)BaseGet(index);
+ }
+
+ internal PropertySourceInfo GetSourceInfo(string key)
+ {
+ ConfigurationValue configurationValue = GetConfigValue(key);
+ return configurationValue?.SourceInfo;
+ }
+
+ internal void ChangeSourceInfo(string key, PropertySourceInfo sourceInfo)
+ {
+ ConfigurationValue configurationValue = GetConfigValue(key);
+ if (configurationValue != null) configurationValue.SourceInfo = sourceInfo;
+ }
+
+ private ConfigurationValue CreateConfigValue(object value, ConfigurationValueFlags valueFlags,
+ PropertySourceInfo sourceInfo)
+ {
+ if (value != null)
+ {
+ if (value is ConfigurationElement)
+ {
+ _containsElement = true;
+ ((ConfigurationElement)value).AssociateContext(_configRecord);
+ }
+ else
+ {
+ if (value is InvalidPropValue) _containsInvalidValue = true;
+ }
+ }
+
+ ConfigurationValue configValue = new ConfigurationValue(value, valueFlags, sourceInfo);
+ return configValue;
+ }
+
+ internal void SetValue(string key, object value, ConfigurationValueFlags valueFlags,
+ PropertySourceInfo sourceInfo)
+ {
+ ConfigurationValue configValue = CreateConfigValue(value, valueFlags, sourceInfo);
+ BaseSet(key, configValue);
+ }
+
+ internal void Clear()
+ {
+ BaseClear();
+ }
+
+ internal ConfigurationValueFlags RetrieveFlags(string key)
+ {
+ ConfigurationValue configurationValue = (ConfigurationValue)BaseGet(key);
+ return configurationValue?.ValueFlags ?? ConfigurationValueFlags.Default;
+ }
+
+ internal bool IsModified(string key)
+ {
+ ConfigurationValue configurationValue = (ConfigurationValue)BaseGet(key);
+ if (configurationValue != null)
+ return (configurationValue.ValueFlags & ConfigurationValueFlags.Modified) != 0;
+ return false;
+ }
+
+ internal bool IsInherited(string key)
+ {
+ ConfigurationValue configurationValue = (ConfigurationValue)BaseGet(key);
+ if (configurationValue != null)
+ return (configurationValue.ValueFlags & ConfigurationValueFlags.Inherited) != 0;
+ return false;
+ }
+
+ private class EmptyCollection : IEnumerable
+ {
+ private readonly IEnumerator _emptyEnumerator;
+
+ internal EmptyCollection()
+ {
+ _emptyEnumerator = new EmptyCollectionEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _emptyEnumerator;
+ }
+
+ private class EmptyCollectionEnumerator : IEnumerator
+ {
+ bool IEnumerator.MoveNext()
+ {
+ return false;
+ }
+
+ object IEnumerator.Current => null;
+
+ void IEnumerator.Reset() { }
+ }
+ }
+
+ private class ConfigurationElementsCollection : IEnumerable
+ {
+ private readonly ConfigurationValues _values;
+
+ internal ConfigurationElementsCollection(ConfigurationValues values)
+ {
+ _values = values;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ if (_values._containsElement)
+ {
+ for (int index = 0; index < _values.Count; index++)
+ {
+ object value = _values[index];
+ if (value is ConfigurationElement) yield return value;
+ }
+ }
+ }
+ }
+
+ private class InvalidValuesCollection : IEnumerable
+ {
+ private readonly ConfigurationValues _values;
+
+ internal InvalidValuesCollection(ConfigurationValues values)
+ {
+ _values = values;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ if (_values._containsInvalidValue)
+ {
+ for (int index = 0; index < _values.Count; index++)
+ {
+ object value = _values[index];
+ if (value is InvalidPropValue) yield return value;
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConnectionStringSettings.cs b/src/System.Configuration/src/System/Configuration/ConnectionStringSettings.cs
new file mode 100644
index 0000000000..bf17013912
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConnectionStringSettings.cs
@@ -0,0 +1,76 @@
+// 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.Configuration
+{
+ public sealed class ConnectionStringSettings : ConfigurationElement
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ private static readonly ConfigurationProperty s_propName =
+ new ConfigurationProperty("name", typeof(string), null, null,
+ ConfigurationProperty.s_nonEmptyStringValidator,
+ ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);
+
+ private static readonly ConfigurationProperty s_propConnectionString =
+ new ConfigurationProperty("connectionString", typeof(string), "", ConfigurationPropertyOptions.IsRequired);
+
+ private static readonly ConfigurationProperty s_propProviderName =
+ new ConfigurationProperty("providerName", typeof(string), string.Empty, ConfigurationPropertyOptions.None);
+
+ static ConnectionStringSettings()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection { s_propName, s_propConnectionString, s_propProviderName };
+ }
+
+ public ConnectionStringSettings() { }
+
+ public ConnectionStringSettings(string name, string connectionString)
+ : this()
+ {
+ Name = name;
+ ConnectionString = connectionString;
+ }
+
+ public ConnectionStringSettings(string name, string connectionString, string providerName)
+ : this()
+ {
+ Name = name;
+ ConnectionString = connectionString;
+ ProviderName = providerName;
+ }
+
+ internal string Key => Name;
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ [ConfigurationProperty("name",
+ Options = ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey, DefaultValue = "")]
+ public string Name
+ {
+ get { return (string)base[s_propName]; }
+ set { base[s_propName] = value; }
+ }
+
+ [ConfigurationProperty("connectionString", Options = ConfigurationPropertyOptions.IsRequired, DefaultValue = "")]
+ public string ConnectionString
+ {
+ get { return (string)base[s_propConnectionString]; }
+ set { base[s_propConnectionString] = value; }
+ }
+
+ [ConfigurationProperty("providerName", DefaultValue = "System.Data.SqlClient")]
+ public string ProviderName
+ {
+ get { return (string)base[s_propProviderName]; }
+ set { base[s_propProviderName] = value; }
+ }
+
+ public override string ToString()
+ {
+ return ConnectionString;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConnectionStringSettingsCollection.cs b/src/System.Configuration/src/System/Configuration/ConnectionStringSettingsCollection.cs
new file mode 100644
index 0000000000..018aa2f4d4
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConnectionStringSettingsCollection.cs
@@ -0,0 +1,86 @@
+// 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.Configuration
+{
+ [ConfigurationCollection(typeof(ConnectionStringSettings))]
+ public sealed class ConnectionStringSettingsCollection : ConfigurationElementCollection
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ static ConnectionStringSettingsCollection()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection();
+ }
+
+ public ConnectionStringSettingsCollection()
+ : base(StringComparer.OrdinalIgnoreCase)
+ { }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ public ConnectionStringSettings this[int index]
+ {
+ get { return (ConnectionStringSettings)BaseGet(index); }
+ set
+ {
+ if (BaseGet(index) != null) BaseRemoveAt(index);
+ BaseAdd(index, value);
+ }
+ }
+
+ public new ConnectionStringSettings this[string name] => (ConnectionStringSettings)BaseGet(name);
+
+ public int IndexOf(ConnectionStringSettings settings)
+ {
+ return BaseIndexOf(settings);
+ }
+
+ // the connection string behavior is strange in that is acts kind of like a
+ // basic map and partially like a add remove clear collection
+ // Overriding these methods allows for the specific behaviors to be
+ // patterened
+ protected override void BaseAdd(int index, ConfigurationElement element)
+ {
+ if (index == -1) BaseAdd(element, false);
+ else base.BaseAdd(index, element);
+ }
+
+ public void Add(ConnectionStringSettings settings)
+ {
+ BaseAdd(settings);
+ }
+
+ public void Remove(ConnectionStringSettings settings)
+ {
+ if (BaseIndexOf(settings) >= 0) BaseRemove(settings.Key);
+ }
+
+ public void RemoveAt(int index)
+ {
+ BaseRemoveAt(index);
+ }
+
+ public void Remove(string name)
+ {
+ BaseRemove(name);
+ }
+
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new ConnectionStringSettings();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((ConnectionStringSettings)element).Key;
+ }
+
+ public void Clear()
+ {
+ BaseClear();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ConnectionStringsSection.cs b/src/System.Configuration/src/System/Configuration/ConnectionStringsSection.cs
new file mode 100644
index 0000000000..7f23566b16
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ConnectionStringsSection.cs
@@ -0,0 +1,33 @@
+// 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.Configuration
+{
+ public sealed class ConnectionStringsSection : ConfigurationSection
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ private static readonly ConfigurationProperty s_propConnectionStrings =
+ new ConfigurationProperty(null, typeof(ConnectionStringSettingsCollection), null,
+ ConfigurationPropertyOptions.IsDefaultCollection);
+
+ static ConnectionStringsSection()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection { s_propConnectionStrings };
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ [ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)]
+ public ConnectionStringSettingsCollection ConnectionStrings
+ => (ConnectionStringSettingsCollection)base[s_propConnectionStrings];
+
+ protected internal override object GetRuntimeObject()
+ {
+ SetReadOnly();
+ return this; // return the read only object
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ContextInformation.cs b/src/System.Configuration/src/System/Configuration/ContextInformation.cs
new file mode 100644
index 0000000000..2e28688ab8
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ContextInformation.cs
@@ -0,0 +1,56 @@
+// 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;
+
+namespace System.Configuration
+{
+ public sealed class ContextInformation
+ {
+ private readonly BaseConfigurationRecord _configRecord;
+ private object _hostingContext;
+ private bool _hostingContextEvaluated;
+
+ internal ContextInformation(BaseConfigurationRecord configRecord)
+ {
+ Debug.Assert(configRecord != null, "configRecord != null");
+
+ _hostingContextEvaluated = false;
+ _hostingContext = null;
+ _configRecord = configRecord;
+ }
+
+ public object HostingContext
+ {
+ get
+ {
+ if (!_hostingContextEvaluated)
+ {
+ // Retrieve Context
+ _hostingContext = _configRecord.ConfigContext;
+
+ _hostingContextEvaluated = true;
+ }
+
+ return _hostingContext;
+ }
+ }
+
+ // Is this the machine.config file or not? If it is not
+ // then use the Hosting Context to determine where you are
+ // and in what hierarchy you are in
+ public bool IsMachineLevel => _configRecord.IsMachineConfig;
+
+ // Get a Section within the context of where we are. What
+ // ever section you retrieve here will be at the same level
+ // in the hierarchy as we are.
+ //
+ // Note: Watch out for a situation where you request a section
+ // that will call you.
+ public object GetSection(string sectionName)
+ {
+ return _configRecord.GetSection(sectionName);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/DateTimeConfigurationCollection.cs b/src/System.Configuration/src/System/Configuration/DateTimeConfigurationCollection.cs
new file mode 100644
index 0000000000..8753785c1a
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/DateTimeConfigurationCollection.cs
@@ -0,0 +1,57 @@
+// 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.Configuration
+{
+ [ConfigurationCollection(typeof(DateTimeConfigurationElement))]
+ public sealed class DateTimeConfigurationCollection : ConfigurationElementCollection
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ static DateTimeConfigurationCollection()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection();
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ public DateTime this[int index]
+ {
+ get { return ((DateTimeConfigurationElement)BaseGet(index)).Value; }
+ set
+ {
+ if (BaseGet(index) != null) BaseRemoveAt(index);
+ BaseAdd(index, new DateTimeConfigurationElement(value));
+ }
+ }
+
+ public object[] AllKeys => BaseGetAllKeys();
+
+ public void Add(DateTime dateTime)
+ {
+ BaseAdd(new DateTimeConfigurationElement(dateTime));
+ }
+
+ public void Remove(DateTime dateTime)
+ {
+ BaseRemove(dateTime);
+ }
+
+ public void Clear()
+ {
+ BaseClear();
+ }
+
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new DateTimeConfigurationElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((DateTimeConfigurationElement)element).Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/DateTimeConfigurationElement.cs b/src/System.Configuration/src/System/Configuration/DateTimeConfigurationElement.cs
new file mode 100644
index 0000000000..6a64d094ec
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/DateTimeConfigurationElement.cs
@@ -0,0 +1,55 @@
+// 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.Configuration
+{
+ internal class DateTimeConfigurationElement : ConfigurationElement
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ private static readonly ConfigurationProperty s_propValue =
+ new ConfigurationProperty("value", typeof(DateTime), DateTime.MinValue, ConfigurationPropertyOptions.IsKey);
+
+ private readonly DateTime _initValue;
+
+ private bool _needsInit;
+
+ static DateTimeConfigurationElement()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection { s_propValue };
+ }
+
+ public DateTimeConfigurationElement() { }
+
+ public DateTimeConfigurationElement(DateTime value)
+ {
+ _needsInit = true;
+ _initValue = value;
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ [ConfigurationProperty("value", IsKey = true)]
+ public DateTime Value
+ {
+ get { return (DateTime)base[s_propValue]; }
+ set { base[s_propValue] = value; }
+ }
+
+ protected internal override void Init()
+ {
+ base.Init();
+
+ // We cannot initialize configuration properties in the constructor,
+ // because Properties is an overridable virtual property that
+ // hence may not be available in the constructor.
+ if (_needsInit)
+ {
+ _needsInit = false;
+ Value = _initValue;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/DeclarationUpdate.cs b/src/System.Configuration/src/System/Configuration/DeclarationUpdate.cs
new file mode 100644
index 0000000000..8ea6c7db0c
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/DeclarationUpdate.cs
@@ -0,0 +1,11 @@
+// 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.Configuration
+{
+ internal class DeclarationUpdate : Update
+ {
+ internal DeclarationUpdate(string configKey, bool moved, string updatedXml) : base(configKey, moved, updatedXml) { }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/DefaultSection.cs b/src/System.Configuration/src/System/Configuration/DefaultSection.cs
new file mode 100644
index 0000000000..315d3b810c
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/DefaultSection.cs
@@ -0,0 +1,64 @@
+// 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.Xml;
+
+namespace System.Configuration
+{
+ public sealed class DefaultSection : ConfigurationSection
+ {
+ private static volatile ConfigurationPropertyCollection s_properties;
+ private bool _isModified;
+
+ private string _rawXml = string.Empty;
+
+ public DefaultSection()
+ {
+ EnsureStaticPropertyBag();
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => EnsureStaticPropertyBag();
+
+ private static ConfigurationPropertyCollection EnsureStaticPropertyBag()
+ {
+ if (s_properties == null)
+ {
+ ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection();
+ s_properties = properties;
+ }
+
+ return s_properties;
+ }
+
+ protected internal override bool IsModified()
+ {
+ return _isModified;
+ }
+
+ protected internal override void ResetModified()
+ {
+ _isModified = false;
+ }
+
+ protected internal override void Reset(ConfigurationElement parentSection)
+ {
+ _rawXml = string.Empty;
+ _isModified = false;
+ }
+
+ protected internal override void DeserializeSection(XmlReader xmlReader)
+ {
+ if (!xmlReader.Read() || (xmlReader.NodeType != XmlNodeType.Element))
+ throw new ConfigurationErrorsException(SR.Config_base_expected_to_find_element, xmlReader);
+ _rawXml = xmlReader.ReadOuterXml();
+ _isModified = true;
+ }
+
+ protected internal override string SerializeSection(ConfigurationElement parentSection, string name,
+ ConfigurationSaveMode saveMode)
+ {
+ return _rawXml;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/DefaultValidator.cs b/src/System.Configuration/src/System/Configuration/DefaultValidator.cs
new file mode 100644
index 0000000000..205cb7496d
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/DefaultValidator.cs
@@ -0,0 +1,21 @@
+// 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.Configuration
+{
+ // Default configuration validator
+ // Can validate everything and never complains
+ public sealed class DefaultValidator : ConfigurationValidatorBase
+ {
+ public override bool CanValidate(Type type)
+ {
+ return true;
+ }
+
+ public override void Validate(object value)
+ {
+ // Everything is OK with this validator
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/DefinitionUpdate.cs b/src/System.Configuration/src/System/Configuration/DefinitionUpdate.cs
new file mode 100644
index 0000000000..937e3bfcb8
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/DefinitionUpdate.cs
@@ -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.Configuration
+{
+ internal class DefinitionUpdate : Update
+ {
+ internal DefinitionUpdate(string configKey, bool moved, string updatedXml, SectionRecord sectionRecord) :
+ base(configKey, moved, updatedXml)
+ {
+ SectionRecord = sectionRecord;
+ }
+
+ internal SectionRecord SectionRecord { get; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ElementInformation.cs b/src/System.Configuration/src/System/Configuration/ElementInformation.cs
new file mode 100644
index 0000000000..53eac1030f
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ElementInformation.cs
@@ -0,0 +1,84 @@
+// 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.Configuration
+{
+ public sealed class ElementInformation
+ {
+ private readonly ConfigurationElement _thisElement;
+ private ConfigurationException[] _errors;
+ private PropertyInformationCollection _internalProperties;
+
+ internal ElementInformation(ConfigurationElement thisElement)
+ {
+ _thisElement = thisElement;
+ }
+
+ public PropertyInformationCollection Properties
+ => _internalProperties ?? (_internalProperties = new PropertyInformationCollection(_thisElement));
+
+ public bool IsPresent => _thisElement.ElementPresent;
+
+ public bool IsLocked => ((_thisElement.ItemLocked & ConfigurationValueFlags.Locked) != 0) &&
+ ((_thisElement.ItemLocked & ConfigurationValueFlags.Inherited) != 0);
+
+ public bool IsCollection
+ {
+ get
+ {
+ ConfigurationElementCollection collection = _thisElement as ConfigurationElementCollection;
+ if ((collection == null) && (_thisElement.Properties.DefaultCollectionProperty != null))
+ {
+ // this is not a collection but it may contain a default collection
+ collection =
+ _thisElement[_thisElement.Properties.DefaultCollectionProperty] as
+ ConfigurationElementCollection;
+ }
+
+ return collection != null;
+ }
+ }
+
+ public string Source => _thisElement.Values.GetSourceInfo(_thisElement.ElementTagName)?.FileName;
+
+ /// <summary>
+ /// The line number or 0 if no source.
+ /// </summary>
+ public int LineNumber => _thisElement.Values.GetSourceInfo(_thisElement.ElementTagName)?.LineNumber ?? 0;
+
+ public Type Type => _thisElement.GetType();
+
+ public ConfigurationValidatorBase Validator => _thisElement.ElementProperty.Validator;
+
+ public ICollection Errors => _errors ?? (_errors = GetReadOnlyErrorsList());
+
+ // Internal method to fix SetRawXML defect...
+ internal PropertySourceInfo PropertyInfoInternal()
+ {
+ return _thisElement.PropertyInfoInternal(_thisElement.ElementTagName);
+ }
+
+ internal void ChangeSourceAndLineNumber(PropertySourceInfo sourceInformation)
+ {
+ _thisElement.Values.ChangeSourceInfo(_thisElement.ElementTagName, sourceInformation);
+ }
+
+ private ConfigurationException[] GetReadOnlyErrorsList()
+ {
+ int count;
+
+ ArrayList arrayList = _thisElement.GetErrorsList();
+ count = arrayList.Count;
+
+ // Create readonly array
+ ConfigurationException[] exceptionList = new ConfigurationException[arrayList.Count];
+
+ if (count != 0) arrayList.CopyTo(exceptionList, 0);
+
+ return exceptionList;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/EmptyImpersonationContext.cs b/src/System.Configuration/src/System/Configuration/EmptyImpersonationContext.cs
new file mode 100644
index 0000000000..5d3bfaac98
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/EmptyImpersonationContext.cs
@@ -0,0 +1,19 @@
+// 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.Configuration
+{
+ // Used in cases where the Host does not require impersonation.
+ internal class EmptyImpersonationContext : IDisposable
+ {
+ private static volatile IDisposable s_emptyImpersonationContext;
+
+ public void Dispose() { }
+
+ internal static IDisposable GetStaticInstance()
+ {
+ return s_emptyImpersonationContext ?? (s_emptyImpersonationContext = new EmptyImpersonationContext());
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ErrorInfoXmlDocument.cs b/src/System.Configuration/src/System/Configuration/ErrorInfoXmlDocument.cs
new file mode 100644
index 0000000000..180b02ae28
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ErrorInfoXmlDocument.cs
@@ -0,0 +1,122 @@
+// 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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ // ErrorInfoXmlDocument - the default Xml Document doesn't track line numbers, and line
+ // numbers are necessary to display source on config errors.
+ // These classes wrap corresponding System.Xml types and also carry
+ // the necessary information for reporting filename / line numbers.
+ // Note: these classes will go away if webdata ever decides to incorporate line numbers
+ // into the default XML classes. This class could also go away if webdata brings back
+ // the UserData property to hang any info off of any node.
+ internal sealed class ErrorInfoXmlDocument : XmlDocument, IConfigErrorInfo
+ {
+ private string _filename;
+ private int _lineOffset;
+ private XmlTextReader _reader;
+
+ internal int LineNumber => ((IConfigErrorInfo)this).LineNumber;
+
+ int IConfigErrorInfo.LineNumber
+ {
+ get
+ {
+ if (_reader == null) return 0;
+
+ if (_lineOffset > 0) return _reader.LineNumber + _lineOffset - 1;
+
+ return _reader.LineNumber;
+ }
+ }
+
+ string IConfigErrorInfo.Filename => _filename;
+
+ public override void Load(string filename)
+ {
+ _filename = filename;
+ try
+ {
+ _reader = new XmlTextReader(filename) { XmlResolver = null };
+ Load(_reader);
+ }
+ finally
+ {
+ if (_reader != null)
+ {
+ _reader.Close();
+ _reader = null;
+ }
+ }
+ }
+
+ private void LoadFromConfigXmlReader(ConfigXmlReader reader)
+ {
+ IConfigErrorInfo err = reader;
+ _filename = err.Filename;
+ _lineOffset = err.LineNumber + 1;
+
+ try
+ {
+ _reader = reader;
+ Load(_reader);
+ }
+ finally
+ {
+ if (_reader != null)
+ {
+ _reader.Close();
+ _reader = null;
+ }
+ }
+ }
+
+ internal static XmlNode CreateSectionXmlNode(ConfigXmlReader reader)
+ {
+ ErrorInfoXmlDocument doc = new ErrorInfoXmlDocument();
+ doc.LoadFromConfigXmlReader(reader);
+ XmlNode xmlNode = doc.DocumentElement;
+
+ return xmlNode;
+ }
+
+ public override XmlAttribute CreateAttribute(string prefix, string localName, string namespaceUri)
+ {
+ return new ConfigXmlAttribute(_filename, LineNumber, prefix, localName, namespaceUri, this);
+ }
+
+ public override XmlElement CreateElement(string prefix, string localName, string namespaceUri)
+ {
+ return new ConfigXmlElement(_filename, LineNumber, prefix, localName, namespaceUri, this);
+ }
+
+ public override XmlText CreateTextNode(string text)
+ {
+ return new ConfigXmlText(_filename, LineNumber, text, this);
+ }
+
+ public override XmlCDataSection CreateCDataSection(string data)
+ {
+ return new ConfigXmlCDataSection(_filename, LineNumber, data, this);
+ }
+
+ public override XmlComment CreateComment(string data)
+ {
+ return new ConfigXmlComment(_filename, LineNumber, data, this);
+ }
+
+ public override XmlSignificantWhitespace CreateSignificantWhitespace(string data)
+ {
+ return new ConfigXmlSignificantWhitespace(_filename, LineNumber, data, this);
+ }
+
+ public override XmlWhitespace CreateWhitespace(string data)
+ {
+ return new ConfigXmlWhitespace(_filename, LineNumber, data, this);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ErrorsHelper.cs b/src/System.Configuration/src/System/Configuration/ErrorsHelper.cs
new file mode 100644
index 0000000000..43b3794f07
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ErrorsHelper.cs
@@ -0,0 +1,64 @@
+// 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.Generic;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ internal static class ErrorsHelper
+ {
+ internal static int GetErrorCount(List<ConfigurationException> errors)
+ {
+ return errors?.Count ?? 0;
+ }
+
+ internal static bool GetHasErrors(List<ConfigurationException> errors)
+ {
+ return GetErrorCount(errors) > 0;
+ }
+
+ internal static void AddError(ref List<ConfigurationException> errors, ConfigurationException e)
+ {
+ Debug.Assert(e != null, "e != null");
+
+ // Create on demand
+ if (errors == null) errors = new List<ConfigurationException>();
+
+ ConfigurationErrorsException ce = e as ConfigurationErrorsException;
+ if (ce == null) errors.Add(e);
+ else
+ {
+ ICollection<ConfigurationException> col = ce.ErrorsGeneric;
+ if (col.Count == 1) errors.Add(e);
+ else errors.AddRange(col);
+ }
+ }
+
+ internal static void AddErrors(ref List<ConfigurationException> errors, ICollection<ConfigurationException> coll)
+ {
+ if ((coll == null) || (coll.Count == 0))
+ {
+ // Nothing to do here, bail
+ return;
+ }
+
+ foreach (ConfigurationException e in coll) AddError(ref errors, e);
+ }
+
+ internal static ConfigurationErrorsException GetErrorsException(List<ConfigurationException> errors)
+ {
+ if (errors == null) return null;
+
+ Debug.Assert(errors.Count != 0, "errors.Count != 0");
+ return new ConfigurationErrorsException(errors);
+ }
+
+ internal static void ThrowOnErrors(List<ConfigurationException> errors)
+ {
+ ConfigurationErrorsException e = GetErrorsException(errors);
+ if (e != null) throw e;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ExceptionAction.cs b/src/System.Configuration/src/System/Configuration/ExceptionAction.cs
new file mode 100644
index 0000000000..1a1f56197b
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ExceptionAction.cs
@@ -0,0 +1,24 @@
+// 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.Configuration
+{
+ internal enum ExceptionAction
+ {
+ /// <summary>
+ /// Not specific to a particular section, nor a global schema error
+ /// </summary>
+ NonSpecific,
+
+ /// <summary>
+ /// Error specific to a particular section
+ /// </summary>
+ Local,
+
+ /// <summary>
+ /// Error in the global (file) schema
+ /// </summary>
+ Global,
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ExceptionUtil.cs b/src/System.Configuration/src/System/Configuration/ExceptionUtil.cs
new file mode 100644
index 0000000000..50506ac6d8
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ExceptionUtil.cs
@@ -0,0 +1,89 @@
+// 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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal static class ExceptionUtil
+ {
+ internal static string NoExceptionInformation => SR.No_exception_information_available;
+
+ internal static ArgumentException ParameterInvalid(string parameter)
+ {
+ return new ArgumentException(string.Format(SR.Parameter_Invalid, parameter), parameter);
+ }
+
+ internal static ArgumentException ParameterNullOrEmpty(string parameter)
+ {
+ return new ArgumentException(string.Format(SR.Parameter_NullOrEmpty, parameter), parameter);
+ }
+
+ internal static ArgumentException PropertyInvalid(string property)
+ {
+ return new ArgumentException(string.Format(SR.Property_Invalid, property), property);
+ }
+
+ internal static ArgumentException PropertyNullOrEmpty(string property)
+ {
+ return new ArgumentException(string.Format(SR.Property_NullOrEmpty, property), property);
+ }
+
+ internal static InvalidOperationException UnexpectedError(string methodName)
+ {
+ return new InvalidOperationException(string.Format(SR.Unexpected_Error, methodName));
+ }
+
+ internal static ConfigurationErrorsException WrapAsConfigException(string outerMessage, Exception e,
+ IConfigErrorInfo errorInfo)
+ {
+ return errorInfo != null
+ ? WrapAsConfigException(outerMessage, e, errorInfo.Filename, errorInfo.LineNumber)
+ : WrapAsConfigException(outerMessage, e, null, 0);
+ }
+
+ internal static ConfigurationErrorsException WrapAsConfigException(string outerMessage, Exception e,
+ string filename, int line)
+ {
+ // Preserve ConfigurationErrorsException
+ ConfigurationErrorsException ce = e as ConfigurationErrorsException;
+ if (ce != null) return ce;
+
+ // Promote deprecated ConfigurationException to ConfigurationErrorsException
+ ConfigurationException deprecatedException = e as ConfigurationException;
+ if (deprecatedException != null)
+ return new ConfigurationErrorsException(
+ deprecatedException.BareMessage,
+ deprecatedException.InnerException,
+ deprecatedException.Filename,
+ deprecatedException.Line);
+
+ // For XML exceptions, preserve the text of the exception in the outer message.
+ XmlException xe = e as XmlException;
+ if (xe != null)
+ {
+ if (xe.LineNumber != 0) line = xe.LineNumber;
+
+ return new ConfigurationErrorsException(xe.Message, xe, filename, line);
+ }
+
+ // Wrap other exceptions in an inner exception, and give as much info as possible
+ if (e != null)
+ {
+ return new ConfigurationErrorsException(
+ string.Format(SR.Wrapped_exception_message, outerMessage, e.Message),
+ e,
+ filename,
+ line);
+ }
+
+ // If there is no exception, create a new exception with no further information.
+ return new ConfigurationErrorsException(
+ string.Format(SR.Wrapped_exception_message, outerMessage, NoExceptionInformation),
+ filename,
+ line);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ExeConfigurationFileMap.cs b/src/System.Configuration/src/System/Configuration/ExeConfigurationFileMap.cs
new file mode 100644
index 0000000000..07a7749296
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ExeConfigurationFileMap.cs
@@ -0,0 +1,45 @@
+// 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.Configuration
+{
+ public sealed class ExeConfigurationFileMap : ConfigurationFileMap
+ {
+ public ExeConfigurationFileMap()
+ {
+ ExeConfigFilename = string.Empty;
+ RoamingUserConfigFilename = string.Empty;
+ LocalUserConfigFilename = string.Empty;
+ }
+
+ public ExeConfigurationFileMap(string machineConfigFileName)
+ : base(machineConfigFileName)
+ {
+ ExeConfigFilename = string.Empty;
+ RoamingUserConfigFilename = string.Empty;
+ LocalUserConfigFilename = string.Empty;
+ }
+
+ private ExeConfigurationFileMap(string machineConfigFileName, string exeConfigFilename,
+ string roamingUserConfigFilename, string localUserConfigFilename)
+ : base(machineConfigFileName)
+ {
+ ExeConfigFilename = exeConfigFilename;
+ RoamingUserConfigFilename = roamingUserConfigFilename;
+ LocalUserConfigFilename = localUserConfigFilename;
+ }
+
+ public string ExeConfigFilename { get; set; }
+
+ public string RoamingUserConfigFilename { get; set; }
+
+ public string LocalUserConfigFilename { get; set; }
+
+ public override object Clone()
+ {
+ return new ExeConfigurationFileMap(MachineConfigFilename, ExeConfigFilename, RoamingUserConfigFilename,
+ LocalUserConfigFilename);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ExeContext.cs b/src/System.Configuration/src/System/Configuration/ExeContext.cs
new file mode 100644
index 0000000000..78f0482339
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ExeContext.cs
@@ -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.Configuration
+{
+ public sealed class ExeContext
+ {
+ internal ExeContext(ConfigurationUserLevel userContext,
+ string exePath)
+ {
+ UserLevel = userContext;
+ ExePath = exePath;
+ }
+
+ // The ConfigurationUserLevel that we are running within.
+ //
+ // Note: ConfigurationUserLevel.None will be set for machine.config
+ // and the applicationconfig file. Use IsMachineConfig in
+ // ConfigurationContext, to determine the difference.
+ public ConfigurationUserLevel UserLevel { get; }
+
+ public string ExePath { get; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/FactoryId.cs b/src/System.Configuration/src/System/Configuration/FactoryId.cs
new file mode 100644
index 0000000000..fd471e38f8
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/FactoryId.cs
@@ -0,0 +1,26 @@
+// 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;
+
+namespace System.Configuration
+{
+ // Identifies a factory
+ [DebuggerDisplay("FactoryId {ConfigKey}")]
+ internal class FactoryId
+ {
+ internal FactoryId(string configKey, string group, string name)
+ {
+ ConfigKey = configKey;
+ Group = group;
+ Name = name;
+ }
+
+ internal string ConfigKey { get; }
+
+ internal string Group { get; }
+
+ internal string Name { get; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/FactoryRecord.cs b/src/System.Configuration/src/System/Configuration/FactoryRecord.cs
new file mode 100644
index 0000000000..595d6194ca
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/FactoryRecord.cs
@@ -0,0 +1,275 @@
+// 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.Generic;
+using System.Configuration.Internal;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ [DebuggerDisplay("FactoryRecord {ConfigKey}")]
+ internal class FactoryRecord : IConfigErrorInfo
+ {
+ private const int FlagAllowLocation = 0x0001; // Does the factory allow location directives?
+ private const int FlagRestartOnExternalChanges = 0x0002; // Restart on external changes?
+
+ // Does access to the section require unrestricted ConfigurationPermission?
+ private const int FlagRequirePermission = 0x0004;
+
+ private const int FlagIsGroup = 0x0008; // factory represents a group
+ private const int FlagIsFromTrustedConfigRecord = 0x0010; // Factory is defined in trusted config record
+ private const int FlagIsUndeclared = 0x0040; // Factory is not declared - either implicit or unrecognized
+
+ private List<ConfigurationException> _errors; // errors
+ private SimpleBitVector32 _flags; // factory flags
+
+ // constructor used for Clone()
+ private FactoryRecord(
+ string configKey,
+ string group,
+ string name,
+ object factory,
+ string factoryTypeName,
+ SimpleBitVector32 flags,
+ ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition,
+ OverrideModeSetting overrideModeDefault,
+ string filename,
+ int lineNumber,
+ ICollection<ConfigurationException> errors)
+ {
+ ConfigKey = configKey;
+ Group = group;
+ Name = name;
+ Factory = factory;
+ FactoryTypeName = factoryTypeName;
+ _flags = flags;
+ AllowDefinition = allowDefinition;
+ AllowExeDefinition = allowExeDefinition;
+ OverrideModeDefault = overrideModeDefault;
+ Filename = filename;
+ LineNumber = lineNumber;
+
+ AddErrors(errors);
+ }
+
+ // constructor used for group
+ internal FactoryRecord(string configKey, string group, string name, string factoryTypeName, string filename,
+ int lineNumber)
+ {
+ ConfigKey = configKey;
+ Group = group;
+ Name = name;
+ FactoryTypeName = factoryTypeName;
+ IsGroup = true;
+ Filename = filename;
+ LineNumber = lineNumber;
+ }
+
+ // constructor used for a section
+ internal FactoryRecord(
+ string configKey,
+ string group,
+ string name,
+ string factoryTypeName,
+ bool allowLocation,
+ ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition,
+ OverrideModeSetting overrideModeDefault,
+ bool restartOnExternalChanges,
+ bool requirePermission,
+ bool isFromTrustedConfigRecord,
+ bool isUndeclared,
+ string filename,
+ int lineNumber)
+ {
+ ConfigKey = configKey;
+ Group = group;
+ Name = name;
+ FactoryTypeName = factoryTypeName;
+ AllowDefinition = allowDefinition;
+ AllowExeDefinition = allowExeDefinition;
+ OverrideModeDefault = overrideModeDefault;
+ AllowLocation = allowLocation;
+ RestartOnExternalChanges = restartOnExternalChanges;
+ RequirePermission = requirePermission;
+ IsFromTrustedConfigRecord = isFromTrustedConfigRecord;
+ IsUndeclared = isUndeclared;
+ Filename = filename;
+ LineNumber = lineNumber;
+ }
+
+ internal string ConfigKey { get; }
+
+ internal string Group { get; }
+
+ internal string Name { get; }
+
+ internal object Factory { get; set; }
+
+ internal string FactoryTypeName { get; set; }
+
+ internal ConfigurationAllowDefinition AllowDefinition { get; set; }
+
+ internal ConfigurationAllowExeDefinition AllowExeDefinition { get; set; }
+
+ internal OverrideModeSetting OverrideModeDefault { get; }
+
+ internal bool AllowLocation
+ {
+ get { return _flags[FlagAllowLocation]; }
+ set { _flags[FlagAllowLocation] = value; }
+ }
+
+ internal bool RestartOnExternalChanges
+ {
+ get { return _flags[FlagRestartOnExternalChanges]; }
+ set { _flags[FlagRestartOnExternalChanges] = value; }
+ }
+
+ internal bool RequirePermission
+ {
+ get { return _flags[FlagRequirePermission]; }
+ set { _flags[FlagRequirePermission] = value; }
+ }
+
+ internal bool IsGroup
+ {
+ get { return _flags[FlagIsGroup]; }
+ set { _flags[FlagIsGroup] = value; }
+ }
+
+ internal bool IsFromTrustedConfigRecord
+ {
+ get { return _flags[FlagIsFromTrustedConfigRecord]; }
+ set { _flags[FlagIsFromTrustedConfigRecord] = value; }
+ }
+
+ internal bool IsUndeclared
+ {
+ get { return _flags[FlagIsUndeclared]; }
+ set { _flags[FlagIsUndeclared] = value; }
+ }
+
+ internal bool HasFile => LineNumber >= 0;
+
+ internal List<ConfigurationException> Errors => _errors;
+
+ internal bool HasErrors => ErrorsHelper.GetHasErrors(_errors);
+
+ // This is used in HttpConfigurationRecord.EnsureSectionFactory() to give file and line source
+ // when a section handler type is invalid or cannot be loaded.
+ public string Filename { get; set; }
+
+ public int LineNumber { get; set; }
+
+ // by cloning we contain a single copy of the strings referred to in the factory and section records
+ internal FactoryRecord CloneSection(string filename, int lineNumber)
+ {
+ return new FactoryRecord(ConfigKey,
+ Group,
+ Name,
+ Factory,
+ FactoryTypeName,
+ _flags,
+ AllowDefinition,
+ AllowExeDefinition,
+ OverrideModeDefault,
+ filename,
+ lineNumber,
+ Errors);
+ }
+
+ // by cloning we contain a single copy of the strings referred to in the factory and section records
+ internal FactoryRecord CloneSectionGroup(string factoryTypeName, string filename, int lineNumber)
+ {
+ if (FactoryTypeName != null) factoryTypeName = FactoryTypeName;
+
+ return new FactoryRecord(ConfigKey,
+ Group,
+ Name,
+ Factory,
+ factoryTypeName,
+ _flags,
+ AllowDefinition,
+ AllowExeDefinition,
+ OverrideModeDefault,
+ filename,
+ lineNumber,
+ Errors);
+ }
+
+ internal bool IsEquivalentType(IInternalConfigHost host, string typeName)
+ {
+ try
+ {
+ if (FactoryTypeName == typeName)
+ return true;
+
+ Type t1, t2;
+
+ if (host != null)
+ {
+ t1 = TypeUtil.GetType(host, typeName, false);
+ t2 = TypeUtil.GetType(host, FactoryTypeName, false);
+ }
+ else
+ {
+ t1 = TypeUtil.GetType(typeName, false);
+ t2 = TypeUtil.GetType(FactoryTypeName, false);
+ }
+
+ return (t1 != null) && (t1 == t2);
+ }
+ catch { }
+
+ return false;
+ }
+
+ internal bool IsEquivalentSectionGroupFactory(IInternalConfigHost host, string typeName)
+ {
+ if ((typeName == null) || (FactoryTypeName == null))
+ return true;
+
+ return IsEquivalentType(host, typeName);
+ }
+
+ internal bool IsEquivalentSectionFactory(
+ IInternalConfigHost host,
+ string typeName,
+ bool allowLocation,
+ ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition,
+ bool restartOnExternalChanges,
+ bool requirePermission)
+ {
+ if ((allowLocation != AllowLocation) ||
+ (allowDefinition != AllowDefinition) ||
+ (allowExeDefinition != AllowExeDefinition) ||
+ (restartOnExternalChanges != RestartOnExternalChanges) ||
+ (requirePermission != RequirePermission))
+ return false;
+
+ return IsEquivalentType(host, typeName);
+ }
+
+ internal void AddErrors(ICollection<ConfigurationException> coll)
+ {
+ ErrorsHelper.AddErrors(ref _errors, coll);
+ }
+
+ internal void ThrowOnErrors()
+ {
+ ErrorsHelper.ThrowOnErrors(_errors);
+ }
+
+ internal bool IsIgnorable()
+ {
+ if (Factory != null)
+ return Factory is IgnoreSectionHandler;
+
+ return (FactoryTypeName != null) && FactoryTypeName.Contains("System.Configuration.IgnoreSection");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/GenericEnumConverter.cs b/src/System.Configuration/src/System/Configuration/GenericEnumConverter.cs
new file mode 100644
index 0000000000..ccdf42103f
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/GenericEnumConverter.cs
@@ -0,0 +1,69 @@
+// 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.Globalization;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Text;
+
+namespace System.Configuration
+{
+ public sealed class GenericEnumConverter : ConfigurationConverterBase
+ {
+ private readonly Type _enumType;
+
+ public GenericEnumConverter(Type typeEnum)
+ {
+ if (typeEnum == null) throw new ArgumentNullException(nameof(typeEnum));
+
+ _enumType = typeEnum;
+ }
+
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ Debug.Assert(value is Enum, "should be Enum type");
+
+ return value.ToString();
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ object result;
+
+ // For any error, throw the ArgumentException with SR.Invalid_enum_value
+ try
+ {
+ string value = (string)data;
+ if (string.IsNullOrEmpty(value)) throw new Exception();
+
+ // Disallow numeric values for enums.
+ if (!string.IsNullOrEmpty(value) &&
+ (char.IsDigit(value[0]) ||
+ (value[0] == '-') ||
+ (value[0] == '+')))
+ throw new Exception();
+
+ if (value != value.Trim())
+ {
+ // throw if the value has whitespace
+ throw new Exception();
+ }
+
+ result = Enum.Parse(_enumType, value);
+ }
+ catch
+ {
+ StringBuilder names = new StringBuilder();
+
+ foreach (string name in Enum.GetNames(_enumType))
+ {
+ if (names.Length != 0) names.Append(", ");
+ names.Append(name);
+ }
+ throw new ArgumentException(string.Format(SR.Invalid_enum_value, names.ToString()));
+ }
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/HResults.cs b/src/System.Configuration/src/System/Configuration/HResults.cs
new file mode 100644
index 0000000000..6ce9b52e16
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/HResults.cs
@@ -0,0 +1,11 @@
+// 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.Configuration
+{
+ internal static class HResults
+ {
+ internal const int Configuration = unchecked((int)0x80131902);
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/IConfigurationSectionHandler.cs b/src/System.Configuration/src/System/Configuration/IConfigurationSectionHandler.cs
new file mode 100644
index 0000000000..554c1489e6
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/IConfigurationSectionHandler.cs
@@ -0,0 +1,38 @@
+// 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.Xml;
+
+namespace System.Configuration
+{
+ /// <summary>
+ /// The IConfigSectionHandler interface defines the contract that all configuration section handlers
+ /// must implement in order to participate in the resolution of configuration settings.
+ /// Composes and creates config objects.
+ /// This interface is implemented by config providers. Classes implementing IConfigSectionHandler
+ /// define the rules for cooking XML config into usable objects. The cooked objects can be of arbitrary
+ /// type.
+ /// Configuration is composable (e.g., config in a child directory is layered over config in a parent
+ /// directory), so, IConfigSectionHandler is supplied with the parent config as well as any number of
+ /// XML fragments.
+ /// </summary>
+ public interface IConfigurationSectionHandler
+ {
+ /// <summary>
+ /// The function is responsible for inspecting "section", "context", and "parent", and creating
+ /// a config object.
+ /// Note that "parent" is guaranteed to be an object that was returned from a Create call on the
+ /// same IConfigSectionHandler implementation. (E.g., if Create returns a Hashtable, then "parent"
+ /// is always a Hashtable if it's non-null.)
+ /// Returned objects must be immutable. In particular, it's important that the "parent" object
+ /// being passed in is not altered: if a modification must be made, then it must be cloned before
+ /// it is modified.
+ /// </summary>
+ /// <param name="parent">the object inherited from parent path</param>
+ /// <param name="configContext">reserved, in ASP.NET used to convey virtual path of config being evaluated</param>
+ /// <param name="section">the xml node rooted at the section to handle</param>
+ /// <returns>a new config object</returns>
+ object Create(object parent, object configContext, XmlNode section);
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/IgnoreSection.cs b/src/System.Configuration/src/System/Configuration/IgnoreSection.cs
new file mode 100644
index 0000000000..db37a1be4f
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/IgnoreSection.cs
@@ -0,0 +1,64 @@
+// 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.Xml;
+
+namespace System.Configuration
+{
+ public sealed class IgnoreSection : ConfigurationSection
+ {
+ private static volatile ConfigurationPropertyCollection s_properties;
+ private bool _isModified;
+
+ private string _rawXml = string.Empty;
+
+ public IgnoreSection()
+ {
+ EnsureStaticPropertyBag();
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => EnsureStaticPropertyBag();
+
+ private static ConfigurationPropertyCollection EnsureStaticPropertyBag()
+ {
+ if (s_properties == null)
+ {
+ ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection();
+ s_properties = properties;
+ }
+
+ return s_properties;
+ }
+
+ protected internal override bool IsModified()
+ {
+ return _isModified;
+ }
+
+ protected internal override void ResetModified()
+ {
+ _isModified = false;
+ }
+
+ protected internal override void Reset(ConfigurationElement parentSection)
+ {
+ _rawXml = string.Empty;
+ _isModified = false;
+ }
+
+ protected internal override void DeserializeSection(XmlReader xmlReader)
+ {
+ if (!xmlReader.Read() || (xmlReader.NodeType != XmlNodeType.Element))
+ throw new ConfigurationErrorsException(SR.Config_base_expected_to_find_element, xmlReader);
+ _rawXml = xmlReader.ReadOuterXml();
+ _isModified = true;
+ }
+
+ protected internal override string SerializeSection(ConfigurationElement parentSection, string name,
+ ConfigurationSaveMode saveMode)
+ {
+ return _rawXml;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/IgnoreSectionHandler.cs b/src/System.Configuration/src/System/Configuration/IgnoreSectionHandler.cs
new file mode 100644
index 0000000000..c91a74edd3
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/IgnoreSectionHandler.cs
@@ -0,0 +1,20 @@
+// 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.Xml;
+
+namespace System.Configuration
+{
+ public class IgnoreSectionHandler : IConfigurationSectionHandler
+ {
+ /// <summary>
+ /// Given a partially composed config object (possibly null) and some input from the config system,
+ /// return a further partially composed config object.
+ /// </summary>
+ public virtual object Create(object parent, object configContext, XmlNode section)
+ {
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ImplicitMachineConfigHost.cs b/src/System.Configuration/src/System/Configuration/ImplicitMachineConfigHost.cs
new file mode 100644
index 0000000000..7cae79aad0
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ImplicitMachineConfigHost.cs
@@ -0,0 +1,72 @@
+// 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.Configuration.Internal;
+using System.IO;
+using System.Text;
+
+namespace System.Configuration
+{
+ internal class ImplicitMachineConfigHost : DelegatingConfigHost
+ {
+ private string _machineStreamName;
+ private ConfigurationFileMap _fileMap;
+
+ internal ImplicitMachineConfigHost(IInternalConfigHost host)
+ {
+ // Delegate to the host provided.
+ Host = host;
+ }
+
+ public override void InitForConfiguration(ref string locationSubPath, out string configPath,
+ out string locationConfigPath, IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams)
+ {
+ // Stash the filemap so we can see if the machine config was explicitly specified
+ _fileMap = (ConfigurationFileMap)hostInitConfigurationParams[0];
+ base.InitForConfiguration(ref locationSubPath, out configPath, out locationConfigPath, configRoot, hostInitConfigurationParams);
+ }
+
+ public override void Init(IInternalConfigRoot configRoot, params object[] hostInitParams)
+ {
+ // Stash the filemap so we can see if the machine config was explicitly specified
+ _fileMap = (ConfigurationFileMap)hostInitParams[0];
+ base.Init(configRoot, hostInitParams);
+ }
+
+ public override string GetStreamName(string configPath)
+ {
+ string name = base.GetStreamName(configPath);
+
+ if (ConfigPathUtility.GetName(configPath) == ClientConfigurationHost.MachineConfigName
+ && !string.Equals(_fileMap?.MachineConfigFilename, name))
+ {
+ // The machine config was asked for and wasn't explicitly
+ // specified, stash the "default" machine.config path
+ _machineStreamName = name;
+ }
+
+ return name;
+ }
+
+ public override Stream OpenStreamForRead(string streamName)
+ {
+ Stream stream = base.OpenStreamForRead(streamName);
+
+ if (stream == null && streamName == _machineStreamName)
+ {
+ // We only want to inject if we aren't able to load
+ stream = new MemoryStream(Encoding.UTF8.GetBytes(s_implicitMachineConfig));
+ }
+
+ return stream;
+ }
+
+ private static string s_implicitMachineConfig =
+@"<configuration>
+ <configSections>
+ <section name='appSettings' type='System.Configuration.AppSettingsSection, System.Configuration' restartOnExternalChanges='false' requirePermission='false'/>
+ </configSections>
+</configuration>";
+ }
+}
diff --git a/src/System.Configuration/src/System/Configuration/InfiniteIntConverter.cs b/src/System.Configuration/src/System/Configuration/InfiniteIntConverter.cs
new file mode 100644
index 0000000000..eb47cf905c
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/InfiniteIntConverter.cs
@@ -0,0 +1,27 @@
+// 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.Globalization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ public sealed class InfiniteIntConverter : ConfigurationConverterBase
+ {
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ ValidateType(value, typeof(int));
+
+ return (int)value == int.MaxValue ? "Infinite" : ((int)value).ToString(CultureInfo.InvariantCulture);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ Debug.Assert(data is string, "data is string");
+
+ return (string)data == "Infinite" ? int.MaxValue : Convert.ToInt32((string)data, 10);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/InfiniteTimeSpanConverter.cs b/src/System.Configuration/src/System/Configuration/InfiniteTimeSpanConverter.cs
new file mode 100644
index 0000000000..e6fb2c5bfb
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/InfiniteTimeSpanConverter.cs
@@ -0,0 +1,33 @@
+// 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.Globalization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ public sealed class InfiniteTimeSpanConverter : ConfigurationConverterBase
+ {
+ private static readonly TypeConverter s_timeSpanConverter = TypeDescriptor.GetConverter(typeof(TimeSpan));
+
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ ValidateType(value, typeof(TimeSpan));
+
+ return (TimeSpan)value == TimeSpan.MaxValue
+ ? "Infinite"
+ : s_timeSpanConverter.ConvertToInvariantString(value);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ Debug.Assert(data is string, "data is string");
+
+ return (string)data == "Infinite"
+ ? TimeSpan.MaxValue
+ : s_timeSpanConverter.ConvertFromInvariantString((string)data);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/IntegerValidator.cs b/src/System.Configuration/src/System/Configuration/IntegerValidator.cs
new file mode 100644
index 0000000000..328e97bbf7
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/IntegerValidator.cs
@@ -0,0 +1,58 @@
+// 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.Configuration
+{
+ public class IntegerValidator : ConfigurationValidatorBase
+ {
+ private readonly ValidationFlags _flags;
+ private readonly int _maxValue;
+ private readonly int _minValue;
+ private readonly int _resolution;
+
+ public IntegerValidator(int minValue, int maxValue) :
+ this(minValue, maxValue, false, 1)
+ { }
+
+ public IntegerValidator(int minValue, int maxValue, bool rangeIsExclusive) :
+ this(minValue, maxValue, rangeIsExclusive, 1)
+ { }
+
+ public IntegerValidator(int minValue, int maxValue, bool rangeIsExclusive, int resolution)
+ {
+ if (resolution <= 0) throw new ArgumentOutOfRangeException(nameof(resolution));
+
+ if (minValue > maxValue)
+ throw new ArgumentOutOfRangeException(nameof(minValue), SR.Validator_min_greater_than_max);
+
+ _minValue = minValue;
+ _maxValue = maxValue;
+ _resolution = resolution;
+
+ _flags = rangeIsExclusive ? ValidationFlags.ExclusiveRange : ValidationFlags.None;
+ }
+
+ public override bool CanValidate(Type type)
+ {
+ return type == typeof(int);
+ }
+
+ public override void Validate(object value)
+ {
+ ValidatorUtils.HelperParamValidation(value, typeof(int));
+
+ ValidatorUtils.ValidateScalar((int)value,
+ _minValue,
+ _maxValue,
+ _resolution,
+ _flags == ValidationFlags.ExclusiveRange);
+ }
+
+ private enum ValidationFlags
+ {
+ None = 0x0000,
+ ExclusiveRange = 0x0001, // If set the value must be outside of the range instead of inside
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/IntegerValidatorAttribute.cs b/src/System.Configuration/src/System/Configuration/IntegerValidatorAttribute.cs
new file mode 100644
index 0000000000..3c3069e47b
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/IntegerValidatorAttribute.cs
@@ -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.
+
+namespace System.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class IntegerValidatorAttribute : ConfigurationValidatorAttribute
+ {
+ private int _max = int.MaxValue;
+ private int _min = int.MinValue;
+
+ public override ConfigurationValidatorBase ValidatorInstance => new IntegerValidator(_min, _max, ExcludeRange);
+
+ public int MinValue
+ {
+ get { return _min; }
+ set
+ {
+ if (_max < value)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.Validator_min_greater_than_max);
+
+ _min = value;
+ }
+ }
+
+ public int MaxValue
+ {
+ get { return _max; }
+ set
+ {
+ if (_min > value)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.Validator_min_greater_than_max);
+
+ _max = value;
+ }
+ }
+
+ public bool ExcludeRange { get; set; } = false;
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/ConfigSystem.cs b/src/System.Configuration/src/System/Configuration/Internal/ConfigSystem.cs
new file mode 100644
index 0000000000..f39c49ce36
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/ConfigSystem.cs
@@ -0,0 +1,30 @@
+// 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.Configuration.Internal
+{
+ // The runtime config system
+ internal class ConfigSystem : IConfigSystem
+ {
+ private IInternalConfigHost _configHost;
+ private IInternalConfigRoot _configRoot;
+
+ void IConfigSystem.Init(Type typeConfigHost, params object[] hostInitParams)
+ {
+ _configRoot = new InternalConfigRoot();
+
+ // Create the requested host and wrap in ImplicitMachineConfigHost so we can
+ // stub in a simple machine.config if needed.
+ IInternalConfigHost host = (IInternalConfigHost)TypeUtil.CreateInstance(typeConfigHost);
+ _configHost = new ImplicitMachineConfigHost(host);
+
+ _configRoot.Init(_configHost, isDesignTime: false);
+ _configHost.Init(_configRoot, hostInitParams);
+ }
+
+ IInternalConfigHost IConfigSystem.Host => _configHost;
+
+ IInternalConfigRoot IConfigSystem.Root => _configRoot;
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/ConfigurationManagerInternal.cs b/src/System.Configuration/src/System/Configuration/Internal/ConfigurationManagerInternal.cs
new file mode 100644
index 0000000000..fa21776dbd
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/ConfigurationManagerInternal.cs
@@ -0,0 +1,36 @@
+// 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.Configuration.Internal
+{
+ internal sealed class ConfigurationManagerInternal : IConfigurationManagerInternal
+ {
+ // Created only through reflection
+ private ConfigurationManagerInternal() { }
+
+ bool IConfigurationManagerInternal.SupportsUserConfig => ConfigurationManager.SupportsUserConfig;
+
+ bool IConfigurationManagerInternal.SetConfigurationSystemInProgress
+ => ConfigurationManager.SetConfigurationSystemInProgress;
+
+ string IConfigurationManagerInternal.MachineConfigPath => ClientConfigurationHost.MachineConfigFilePath;
+
+ string IConfigurationManagerInternal.ApplicationConfigUri => ClientConfigPaths.Current.ApplicationConfigUri;
+
+ string IConfigurationManagerInternal.ExeProductName => ClientConfigPaths.Current.ProductName;
+
+ string IConfigurationManagerInternal.ExeProductVersion => ClientConfigPaths.Current.ProductVersion;
+
+ string IConfigurationManagerInternal.ExeRoamingConfigDirectory
+ => ClientConfigPaths.Current.RoamingConfigDirectory;
+
+ string IConfigurationManagerInternal.ExeRoamingConfigPath => ClientConfigPaths.Current.RoamingConfigFilename;
+
+ string IConfigurationManagerInternal.ExeLocalConfigDirectory => ClientConfigPaths.Current.LocalConfigDirectory;
+
+ string IConfigurationManagerInternal.ExeLocalConfigPath => ClientConfigPaths.Current.LocalConfigFilename;
+
+ string IConfigurationManagerInternal.UserConfigFilename => ClientConfigPaths.UserConfigFilename;
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/DelegatingConfigHost.cs b/src/System.Configuration/src/System/Configuration/Internal/DelegatingConfigHost.cs
new file mode 100644
index 0000000000..75c6ca5d0c
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/DelegatingConfigHost.cs
@@ -0,0 +1,228 @@
+// 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.IO;
+
+namespace System.Configuration.Internal
+{
+ // A public implementation of IInternalConfigHost that simply
+ // delegates all members of the IInternalConfigHost interface to
+ // another instance of a host. All interface members are marked virtual
+ // so that a derived class can override just the ones needed to
+ // implement that specific host, while all others are delegated to
+ // another implementation such as InternalConfigHost.
+ //
+ // The advantages of this arrangement are:
+ // * The IInternalConfigHost interface can be extended without
+ // requiring other hosts to be updated.
+ // * This class that we are making public has no implementation
+ // of its own that can be exploited. All the hosts with meaningful
+ // implementation can remain internal.
+ // * It allows straightforward chaining of host functionality,
+ // see UpdateConfigHost as an example.
+ public class DelegatingConfigHost : IInternalConfigHost, IInternalConfigHostPaths
+ {
+ protected DelegatingConfigHost() { }
+
+ // The host that is delegated to.
+ protected IInternalConfigHost Host { get; set; }
+
+ public virtual void Init(IInternalConfigRoot configRoot, params object[] hostInitParams)
+ {
+ Host.Init(configRoot, hostInitParams);
+ }
+
+ public virtual void InitForConfiguration(ref string locationSubPath, out string configPath,
+ out string locationConfigPath,
+ IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams)
+ {
+ Host.InitForConfiguration(ref locationSubPath, out configPath, out locationConfigPath, configRoot,
+ hostInitConfigurationParams);
+ }
+
+ public virtual bool IsConfigRecordRequired(string configPath)
+ {
+ return Host.IsConfigRecordRequired(configPath);
+ }
+
+ public virtual bool IsInitDelayed(IInternalConfigRecord configRecord)
+ {
+ return Host.IsInitDelayed(configRecord);
+ }
+
+ public virtual void RequireCompleteInit(IInternalConfigRecord configRecord)
+ {
+ Host.RequireCompleteInit(configRecord);
+ }
+
+ // Is this a secondary root. This means that it is a node in which
+ // everything that is defined in it should also be treated as a root.
+ // So...if a factory record is defined that was already defined above
+ // then throw since it is not allowed.
+ public virtual bool IsSecondaryRoot(string configPath)
+ {
+ return Host.IsSecondaryRoot(configPath);
+ }
+
+ public virtual string GetStreamName(string configPath)
+ {
+ return Host.GetStreamName(configPath);
+ }
+
+ public virtual string GetStreamNameForConfigSource(string streamName, string configSource)
+ {
+ return Host.GetStreamNameForConfigSource(streamName, configSource);
+ }
+
+ public virtual object GetStreamVersion(string streamName)
+ {
+ return Host.GetStreamVersion(streamName);
+ }
+
+ public virtual Stream OpenStreamForRead(string streamName)
+ {
+ return Host.OpenStreamForRead(streamName);
+ }
+
+ public virtual Stream OpenStreamForRead(string streamName, bool assertPermissions)
+ {
+ return Host.OpenStreamForRead(streamName, assertPermissions);
+ }
+
+ public virtual Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext)
+ {
+ return Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext);
+ }
+
+ public virtual Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext,
+ bool assertPermissions)
+ {
+ return Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext, assertPermissions);
+ }
+
+ public virtual void WriteCompleted(string streamName, bool success, object writeContext)
+ {
+ Host.WriteCompleted(streamName, success, writeContext);
+ }
+
+ public virtual void WriteCompleted(string streamName, bool success, object writeContext, bool assertPermissions)
+ {
+ Host.WriteCompleted(streamName, success, writeContext, assertPermissions);
+ }
+
+ public virtual void DeleteStream(string streamName)
+ {
+ Host.DeleteStream(streamName);
+ }
+
+ public virtual bool IsFile(string streamName)
+ {
+ return Host.IsFile(streamName);
+ }
+
+ public virtual bool SupportsChangeNotifications => Host.SupportsChangeNotifications;
+
+ public virtual object StartMonitoringStreamForChanges(string streamName, StreamChangeCallback callback)
+ {
+ return Host.StartMonitoringStreamForChanges(streamName, callback);
+ }
+
+ public virtual void StopMonitoringStreamForChanges(string streamName, StreamChangeCallback callback)
+ {
+ Host.StopMonitoringStreamForChanges(streamName, callback);
+ }
+
+ public virtual bool SupportsRefresh => Host.SupportsRefresh;
+
+ public virtual bool SupportsPath => Host.SupportsPath;
+
+ public virtual bool SupportsLocation => Host.SupportsLocation;
+
+ public virtual bool IsAboveApplication(string configPath)
+ {
+ return Host.IsAboveApplication(configPath);
+ }
+
+ public virtual bool IsDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition)
+ {
+ return Host.IsDefinitionAllowed(configPath, allowDefinition, allowExeDefinition);
+ }
+
+ public virtual void VerifyDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition, IConfigErrorInfo errorInfo)
+ {
+ Host.VerifyDefinitionAllowed(configPath, allowDefinition, allowExeDefinition, errorInfo);
+ }
+
+ public virtual string GetConfigPathFromLocationSubPath(string configPath, string locationSubPath)
+ {
+ return Host.GetConfigPathFromLocationSubPath(configPath, locationSubPath);
+ }
+
+ public virtual bool IsLocationApplicable(string configPath)
+ {
+ return Host.IsLocationApplicable(configPath);
+ }
+
+ public virtual bool PrefetchAll(string configPath, string streamName)
+ {
+ return Host.PrefetchAll(configPath, streamName);
+ }
+
+ public virtual bool PrefetchSection(string sectionGroupName, string sectionName)
+ {
+ return Host.PrefetchSection(sectionGroupName, sectionName);
+ }
+
+ public virtual object CreateDeprecatedConfigContext(string configPath)
+ {
+ return Host.CreateDeprecatedConfigContext(configPath);
+ }
+
+ public virtual object
+ CreateConfigurationContext(string configPath, string locationSubPath)
+ {
+ return Host.CreateConfigurationContext(configPath, locationSubPath);
+ }
+
+ public virtual string DecryptSection(string encryptedXml, ProtectedConfigurationProvider protectionProvider,
+ ProtectedConfigurationSection protectedConfigSection)
+ {
+ return Host.DecryptSection(encryptedXml, protectionProvider, protectedConfigSection);
+ }
+
+ public virtual string EncryptSection(string clearTextXml, ProtectedConfigurationProvider protectionProvider,
+ ProtectedConfigurationSection protectedConfigSection)
+ {
+ return Host.EncryptSection(clearTextXml, protectionProvider, protectedConfigSection);
+ }
+
+ public virtual Type GetConfigType(string typeName, bool throwOnError)
+ {
+ return Host.GetConfigType(typeName, throwOnError);
+ }
+
+ public virtual string GetConfigTypeName(Type t)
+ {
+ return Host.GetConfigTypeName(t);
+ }
+
+ public virtual bool IsRemote => Host.IsRemote;
+
+ // Want this to fail hard if we actually try and call where there is no implementation
+ private IInternalConfigHostPaths HostPaths => (IInternalConfigHostPaths)Host;
+
+ public virtual void RefreshConfigPaths()
+ {
+ HostPaths.RefreshConfigPaths();
+ }
+
+ public virtual bool HasLocalConfig => HostPaths.HasLocalConfig;
+
+ public virtual bool HasRoamingConfig => HostPaths.HasRoamingConfig;
+
+ public virtual bool IsAppConfigHttp => HostPaths.IsAppConfigHttp;
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/FileVersion.cs b/src/System.Configuration/src/System/Configuration/Internal/FileVersion.cs
new file mode 100644
index 0000000000..03e9c0d2e1
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/FileVersion.cs
@@ -0,0 +1,38 @@
+// 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.Configuration.Internal
+{
+ internal class FileVersion
+ {
+ private readonly bool _exists;
+ private readonly long _fileSize;
+ private readonly DateTime _utcCreationTime;
+ private readonly DateTime _utcLastWriteTime;
+
+ internal FileVersion(bool exists, long fileSize, DateTime utcCreationTime, DateTime utcLastWriteTime)
+ {
+ _exists = exists;
+ _fileSize = fileSize;
+ _utcCreationTime = utcCreationTime;
+ _utcLastWriteTime = utcLastWriteTime;
+ }
+
+ public override bool Equals(object obj)
+ {
+ FileVersion other = obj as FileVersion;
+ return
+ (other != null)
+ && (_exists == other._exists)
+ && (_fileSize == other._fileSize)
+ && (_utcCreationTime == other._utcCreationTime)
+ && (_utcLastWriteTime == other._utcLastWriteTime);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IConfigErrorInfo.cs b/src/System.Configuration/src/System/Configuration/Internal/IConfigErrorInfo.cs
new file mode 100644
index 0000000000..aca5afa133
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IConfigErrorInfo.cs
@@ -0,0 +1,12 @@
+// 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.Configuration.Internal
+{
+ public interface IConfigErrorInfo
+ {
+ string Filename { get; }
+ int LineNumber { get; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IConfigSystem.cs b/src/System.Configuration/src/System/Configuration/Internal/IConfigSystem.cs
new file mode 100644
index 0000000000..4b5bbadd6d
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IConfigSystem.cs
@@ -0,0 +1,13 @@
+// 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.Configuration.Internal
+{
+ public interface IConfigSystem
+ {
+ IInternalConfigHost Host { get; }
+ IInternalConfigRoot Root { get; }
+ void Init(Type typeConfigHost, params object[] hostInitParams);
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IConfigurationManagerHelper.cs b/src/System.Configuration/src/System/Configuration/Internal/IConfigurationManagerHelper.cs
new file mode 100644
index 0000000000..069e7bc477
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IConfigurationManagerHelper.cs
@@ -0,0 +1,16 @@
+// 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.Configuration.Internal
+{
+ // Exposes support in System.dll for functionality that has
+ // been moved to System.Configuration.dll
+
+ public interface IConfigurationManagerHelper
+ {
+ void EnsureNetConfigLoaded();
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IConfigurationManagerInternal.cs b/src/System.Configuration/src/System/Configuration/Internal/IConfigurationManagerInternal.cs
new file mode 100644
index 0000000000..4eb1a8e0fc
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IConfigurationManagerInternal.cs
@@ -0,0 +1,26 @@
+// 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.Configuration.Internal
+{
+ // Exposes support in System.Configuration for functions that were
+ // once available in System.dll
+
+ public interface IConfigurationManagerInternal
+ {
+ bool SupportsUserConfig { get; }
+ bool SetConfigurationSystemInProgress { get; }
+ string MachineConfigPath { get; }
+ string ApplicationConfigUri { get; }
+ string ExeProductName { get; }
+ string ExeProductVersion { get; }
+ string ExeRoamingConfigDirectory { get; }
+ string ExeRoamingConfigPath { get; }
+ string ExeLocalConfigDirectory { get; }
+ string ExeLocalConfigPath { get; }
+ string UserConfigFilename { get; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigClientHost.cs b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigClientHost.cs
new file mode 100644
index 0000000000..a2efb0dc95
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigClientHost.cs
@@ -0,0 +1,18 @@
+// 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.Configuration.Internal
+{
+ public interface IInternalConfigClientHost
+ {
+ bool IsExeConfig(string configPath);
+ bool IsRoamingUserConfig(string configPath);
+ bool IsLocalUserConfig(string configPath);
+ string GetExeConfigPath();
+ string GetRoamingUserConfigPath();
+ string GetLocalUserConfigPath();
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigConfigurationFactory.cs b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigConfigurationFactory.cs
new file mode 100644
index 0000000000..82be361666
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigConfigurationFactory.cs
@@ -0,0 +1,14 @@
+// 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.Configuration.Internal
+{
+ public interface IInternalConfigConfigurationFactory
+ {
+ Configuration Create(Type typeConfigHost, params object[] hostInitConfigurationParams);
+ string NormalizeLocationSubPath(string subPath, IConfigErrorInfo errorInfo);
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigHost.cs b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigHost.cs
new file mode 100644
index 0000000000..d5e356ddc4
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigHost.cs
@@ -0,0 +1,100 @@
+// 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.IO;
+using System.Runtime.InteropServices;
+
+namespace System.Configuration.Internal
+{
+ public interface IInternalConfigHost
+ {
+ // change notification support - runtime only
+ bool SupportsChangeNotifications { get; }
+
+ // RefreshConfig support - runtime only
+ bool SupportsRefresh { get; }
+
+ // Whether we support Path attribute in location.
+ bool SupportsPath { get; }
+
+ bool SupportsLocation { get; }
+
+ // Used by MgmtConfigurationRecord during SaveAs
+ bool IsRemote { get; }
+
+ void Init(IInternalConfigRoot configRoot, params object[] hostInitParams);
+
+ void InitForConfiguration(ref string locationSubPath, out string configPath, out string locationConfigPath,
+ IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams);
+
+ // To support creation of new config record - whether that path requires a configRecord.
+ bool IsConfigRecordRequired(string configPath);
+
+ bool IsInitDelayed(IInternalConfigRecord configRecord);
+
+ void RequireCompleteInit(IInternalConfigRecord configRecord);
+
+ bool IsSecondaryRoot(string configPath);
+
+ string GetStreamName(string configPath);
+
+ string GetStreamNameForConfigSource(string streamName, string configSource);
+
+ object GetStreamVersion(string streamName);
+
+ // default impl treats name as a file name
+ // null means stream doesn't exist for this name
+ Stream OpenStreamForRead(string streamName);
+
+ Stream OpenStreamForRead(string streamName, bool assertPermissions);
+
+ Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext);
+
+ Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext,
+ bool assertPermissions);
+
+ void WriteCompleted(string streamName, bool success, object writeContext);
+
+ void WriteCompleted(string streamName, bool success, object writeContext, bool assertPermissions);
+
+ void DeleteStream(string streamName);
+
+ bool IsFile(string streamName);
+
+ object StartMonitoringStreamForChanges(string streamName, StreamChangeCallback callback);
+
+ void StopMonitoringStreamForChanges(string streamName, StreamChangeCallback callback);
+
+ bool IsAboveApplication(string configPath);
+
+ string GetConfigPathFromLocationSubPath(string configPath, string locationSubPath);
+
+ bool IsLocationApplicable(string configPath);
+
+ bool IsDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition);
+
+ void VerifyDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition, IConfigErrorInfo errorInfo);
+
+ bool PrefetchAll(string configPath, string streamName);
+
+ // E.g. If the config file is downloaded from HTTP, we want to prefetch everything.
+ bool PrefetchSection(string sectionGroupName, string sectionName);
+
+ object CreateDeprecatedConfigContext(string configPath);
+
+ object CreateConfigurationContext(string configPath, string locationSubPath);
+
+ string DecryptSection(string encryptedXml, ProtectedConfigurationProvider protectionProvider,
+ ProtectedConfigurationSection protectedConfigSection);
+
+ string EncryptSection(string clearTextXml, ProtectedConfigurationProvider protectionProvider,
+ ProtectedConfigurationSection protectedConfigSection);
+
+ Type GetConfigType(string typeName, bool throwOnError);
+
+ string GetConfigTypeName(Type t);
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigHostPaths.cs b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigHostPaths.cs
new file mode 100644
index 0000000000..328a75de2c
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigHostPaths.cs
@@ -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.
+
+using System.Runtime.InteropServices;
+
+namespace System.Configuration.Internal
+{
+ [ComVisible(false)]
+ public interface IInternalConfigHostPaths
+ {
+ void RefreshConfigPaths();
+ bool HasLocalConfig { get; }
+ bool HasRoamingConfig { get; }
+ bool IsAppConfigHttp { get; }
+ }
+}
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigRecord.cs b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigRecord.cs
new file mode 100644
index 0000000000..7f224b44a3
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigRecord.cs
@@ -0,0 +1,27 @@
+// 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.Configuration.Internal
+{
+ public interface IInternalConfigRecord
+ {
+ string ConfigPath { get; }
+
+ string StreamName { get; }
+
+ bool HasInitErrors { get; }
+
+ void ThrowIfInitErrors();
+
+ object GetSection(string configKey);
+
+ object GetLkgSection(string configKey);
+
+ void RefreshSection(string configKey);
+
+ void Remove();
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigRoot.cs b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigRoot.cs
new file mode 100644
index 0000000000..f895b51576
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigRoot.cs
@@ -0,0 +1,30 @@
+// 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.Configuration.Internal
+{
+ public interface IInternalConfigRoot
+ {
+ bool IsDesignTime { get; }
+
+ void Init(IInternalConfigHost host, bool isDesignTime);
+
+ event InternalConfigEventHandler ConfigChanged;
+
+ event InternalConfigEventHandler ConfigRemoved;
+
+ object GetSection(string section, string configPath);
+
+ // Get the configPath of the nearest ancestor that has the config data
+ string GetUniqueConfigPath(string configPath);
+
+ IInternalConfigRecord GetUniqueConfigRecord(string configPath);
+
+ IInternalConfigRecord GetConfigRecord(string configPath);
+
+ void RemoveConfig(string configPath);
+ }
+} \ No newline at end of file
diff --git a/src/Common/src/Interop/Windows/kernel32/Interop.SetLastError.cs b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigSettingsFactory.cs
index d6e50d8509..592e8980f8 100644
--- a/src/Common/src/Interop/Windows/kernel32/Interop.SetLastError.cs
+++ b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigSettingsFactory.cs
@@ -4,11 +4,12 @@
using System.Runtime.InteropServices;
-internal partial class Interop
+namespace System.Configuration.Internal
{
- internal partial class Kernel32
+ public interface IInternalConfigSettingsFactory
{
- [DllImport(Libraries.Kernel32)]
- internal extern static void SetLastError(uint dwErrCode);
+ void SetConfigurationSystem(IInternalConfigSystem internalConfigSystem, bool initComplete);
+
+ void CompleteInit();
}
-}
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigSystem.cs b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigSystem.cs
new file mode 100644
index 0000000000..78d65f77d0
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/IInternalConfigSystem.cs
@@ -0,0 +1,19 @@
+// 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.Configuration.Internal
+{
+ public interface IInternalConfigSystem
+ {
+ bool SupportsUserConfig { get; }
+
+ // Returns the config object for the specified key.
+ object GetSection(string configKey);
+
+ // Refreshes the configuration section.
+ void RefreshConfig(string sectionName);
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/InternalConfigConfigurationFactory.cs b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigConfigurationFactory.cs
new file mode 100644
index 0000000000..6746a5de28
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigConfigurationFactory.cs
@@ -0,0 +1,22 @@
+// 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.Configuration.Internal
+{
+ internal sealed class InternalConfigConfigurationFactory : IInternalConfigConfigurationFactory
+ {
+ private InternalConfigConfigurationFactory() { }
+
+ Configuration IInternalConfigConfigurationFactory.Create(Type typeConfigHost,
+ params object[] hostInitConfigurationParams)
+ {
+ return new Configuration(null, typeConfigHost, hostInitConfigurationParams);
+ }
+
+ string IInternalConfigConfigurationFactory.NormalizeLocationSubPath(string subPath, IConfigErrorInfo errorInfo)
+ {
+ return BaseConfigurationRecord.NormalizeLocationSubPath(subPath, errorInfo);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/InternalConfigEventArgs.cs b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigEventArgs.cs
new file mode 100644
index 0000000000..1b857d6a68
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigEventArgs.cs
@@ -0,0 +1,16 @@
+// 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.Configuration.Internal
+{
+ public sealed class InternalConfigEventArgs : EventArgs
+ {
+ public InternalConfigEventArgs(string configPath)
+ {
+ ConfigPath = configPath;
+ }
+
+ public string ConfigPath { get; set; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/InternalConfigEventHandler.cs b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigEventHandler.cs
new file mode 100644
index 0000000000..b6645a3551
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigEventHandler.cs
@@ -0,0 +1,8 @@
+// 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.Configuration.Internal
+{
+ public delegate void InternalConfigEventHandler(object sender, InternalConfigEventArgs e);
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/InternalConfigHost.cs b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigHost.cs
new file mode 100644
index 0000000000..cb0bbb2597
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigHost.cs
@@ -0,0 +1,301 @@
+// 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.IO;
+
+namespace System.Configuration.Internal
+{
+ internal sealed class InternalConfigHost : IInternalConfigHost
+ {
+ private const FileAttributes InvalidAttributesForWrite = FileAttributes.ReadOnly | FileAttributes.Hidden;
+
+ void IInternalConfigHost.Init(IInternalConfigRoot configRoot, params object[] hostInitParams)
+ { }
+
+ void IInternalConfigHost.InitForConfiguration(ref string locationSubPath, out string configPath,
+ out string locationConfigPath,
+ IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams)
+ {
+ configPath = null;
+ locationConfigPath = null;
+ }
+
+ bool IInternalConfigHost.IsConfigRecordRequired(string configPath)
+ {
+ return true;
+ }
+
+ bool IInternalConfigHost.IsInitDelayed(IInternalConfigRecord configRecord)
+ {
+ return false;
+ }
+
+ void IInternalConfigHost.RequireCompleteInit(IInternalConfigRecord configRecord) { }
+
+ public bool IsSecondaryRoot(string configPath)
+ {
+ // In the default there are no secondary root's
+ return false;
+ }
+
+ string IInternalConfigHost.GetStreamName(string configPath)
+ {
+ throw ExceptionUtil.UnexpectedError("IInternalConfigHost.GetStreamName");
+ }
+
+ string IInternalConfigHost.GetStreamNameForConfigSource(string streamName, string configSource)
+ {
+ return StaticGetStreamNameForConfigSource(streamName, configSource);
+ }
+
+ object IInternalConfigHost.GetStreamVersion(string streamName)
+ {
+ return StaticGetStreamVersion(streamName);
+ }
+
+ Stream IInternalConfigHost.OpenStreamForRead(string streamName)
+ {
+ return StaticOpenStreamForRead(streamName);
+ }
+
+ Stream IInternalConfigHost.OpenStreamForRead(string streamName, bool assertPermissions)
+ {
+ return StaticOpenStreamForRead(streamName);
+ }
+
+ Stream IInternalConfigHost.OpenStreamForWrite(string streamName, string templateStreamName,
+ ref object writeContext)
+ {
+ return StaticOpenStreamForWrite(streamName, templateStreamName, ref writeContext);
+ }
+
+ Stream IInternalConfigHost.OpenStreamForWrite(string streamName, string templateStreamName,
+ ref object writeContext, bool assertPermissions)
+ {
+ return StaticOpenStreamForWrite(streamName, templateStreamName, ref writeContext);
+ }
+
+ void IInternalConfigHost.WriteCompleted(string streamName, bool success, object writeContext)
+ {
+ StaticWriteCompleted(streamName, success, writeContext);
+ }
+
+ void IInternalConfigHost.WriteCompleted(string streamName, bool success, object writeContext,
+ bool assertPermissions)
+ {
+ StaticWriteCompleted(streamName, success, writeContext);
+ }
+
+ void IInternalConfigHost.DeleteStream(string streamName)
+ {
+ StaticDeleteStream(streamName);
+ }
+
+ bool IInternalConfigHost.IsFile(string streamName)
+ {
+ return StaticIsFile(streamName);
+ }
+
+ bool IInternalConfigHost.SupportsChangeNotifications => false;
+
+ object IInternalConfigHost.StartMonitoringStreamForChanges(string streamName, StreamChangeCallback callback)
+ {
+ throw ExceptionUtil.UnexpectedError("IInternalConfigHost.StartMonitoringStreamForChanges");
+ }
+
+ void IInternalConfigHost.StopMonitoringStreamForChanges(string streamName, StreamChangeCallback callback)
+ {
+ throw ExceptionUtil.UnexpectedError("IInternalConfigHost.StopMonitoringStreamForChanges");
+ }
+
+ bool IInternalConfigHost.SupportsRefresh => false;
+
+ bool IInternalConfigHost.SupportsPath => false;
+
+ bool IInternalConfigHost.IsDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition)
+ {
+ return true;
+ }
+
+ void IInternalConfigHost.VerifyDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition,
+ ConfigurationAllowExeDefinition allowExeDefinition, IConfigErrorInfo errorInfo)
+ { }
+
+ bool IInternalConfigHost.SupportsLocation => false;
+
+ bool IInternalConfigHost.IsAboveApplication(string configPath)
+ {
+ throw ExceptionUtil.UnexpectedError("IInternalConfigHost.IsAboveApplication");
+ }
+
+ string IInternalConfigHost.GetConfigPathFromLocationSubPath(string configPath, string locationSubPath)
+ {
+ throw ExceptionUtil.UnexpectedError("IInternalConfigHost.GetConfigPathFromLocationSubPath");
+ }
+
+ bool IInternalConfigHost.IsLocationApplicable(string configPath)
+ {
+ throw ExceptionUtil.UnexpectedError("IInternalConfigHost.IsLocationApplicable");
+ }
+
+ bool IInternalConfigHost.PrefetchAll(string configPath, string streamName)
+ {
+ return false;
+ }
+
+ bool IInternalConfigHost.PrefetchSection(string sectionGroupName, string sectionName)
+ {
+ return false;
+ }
+
+ object IInternalConfigHost.CreateDeprecatedConfigContext(string configPath)
+ {
+ throw ExceptionUtil.UnexpectedError("IInternalConfigHost.CreateDeprecatedConfigContext");
+ }
+
+ object IInternalConfigHost.CreateConfigurationContext(string configPath, string locationSubPath)
+ {
+ throw ExceptionUtil.UnexpectedError("IInternalConfigHost.CreateConfigurationContext");
+ }
+
+ string IInternalConfigHost.DecryptSection(string encryptedXml, ProtectedConfigurationProvider protectionProvider,
+ ProtectedConfigurationSection protectedConfigSection)
+ {
+ return ProtectedConfigurationSection.DecryptSection(encryptedXml, protectionProvider);
+ }
+
+ string IInternalConfigHost.EncryptSection(string clearTextXml, ProtectedConfigurationProvider protectionProvider,
+ ProtectedConfigurationSection protectedConfigSection)
+ {
+ return ProtectedConfigurationSection.EncryptSection(clearTextXml, protectionProvider);
+ }
+
+ Type IInternalConfigHost.GetConfigType(string typeName, bool throwOnError)
+ {
+ return Type.GetType(typeName, throwOnError);
+ }
+
+ string IInternalConfigHost.GetConfigTypeName(Type t)
+ {
+ return t.AssemblyQualifiedName;
+ }
+
+ bool IInternalConfigHost.IsRemote => false;
+
+ internal static string StaticGetStreamNameForConfigSource(string streamName, string configSource)
+ {
+ // RemoteWebConfigurationHost also redirects GetStreamNameForConfigSource to this
+ // method, and that means streamName is referring to a path that's on the remote
+ // machine.
+
+ // don't allow relative paths for stream name
+ if (!Path.IsPathRooted(streamName)) throw ExceptionUtil.ParameterInvalid("streamName");
+
+ // get the path part of the original stream
+ streamName = Path.GetFullPath(streamName);
+ string dirStream = UrlPath.GetDirectoryOrRootName(streamName);
+
+ // combine with the new config source
+ string result = Path.Combine(dirStream, configSource);
+ result = Path.GetFullPath(result);
+
+ // ensure the result is in or under the directory of the original source
+ string dirResult = UrlPath.GetDirectoryOrRootName(result);
+ if (!UrlPath.IsEqualOrSubdirectory(dirStream, dirResult))
+ throw new ArgumentException(string.Format(SR.Config_source_not_under_config_dir, configSource));
+
+ return result;
+ }
+
+ internal static FileVersion StaticGetStreamVersion(string streamName)
+ {
+ FileInfo info = new FileInfo(streamName);
+ return info.Exists
+ ? new FileVersion(true, info.Length, info.CreationTimeUtc, info.LastWriteTimeUtc)
+ : new FileVersion(false, 0, DateTime.MinValue, DateTime.MinValue);
+ }
+
+ // default impl treats name as a file name
+ // null means stream doesn't exist for this name
+ internal static Stream StaticOpenStreamForRead(string streamName)
+ {
+ if (string.IsNullOrEmpty(streamName))
+ throw ExceptionUtil.UnexpectedError("InternalConfigHost::StaticOpenStreamForRead");
+
+ return !File.Exists(streamName)
+ ? null
+ : new FileStream(streamName, FileMode.Open, FileAccess.Read, FileShare.Read);
+ }
+
+ // This method doesn't really open the streamName for write. Instead, using WriteFileContext
+ // it opens a stream on a temporary file created in the same directory as streamName.
+ internal static Stream StaticOpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext)
+ {
+ if (string.IsNullOrEmpty(streamName))
+ throw new ConfigurationErrorsException(SR.Config_no_stream_to_write);
+
+ // Create directory if it does not exist.
+ // Ignore errors, allow any failure to come when trying to open the file.
+ string dir = Path.GetDirectoryName(streamName);
+
+ if (!Directory.Exists(dir))
+ Directory.CreateDirectory(dir);
+
+ Stream stream;
+ WriteFileContext writeFileContext = null;
+
+ try
+ {
+ writeFileContext = new WriteFileContext(streamName, templateStreamName);
+
+ if (File.Exists(streamName))
+ {
+ FileInfo fi = new FileInfo(streamName);
+ FileAttributes attrs = fi.Attributes;
+ if ((attrs & InvalidAttributesForWrite) != 0)
+ {
+ throw new IOException(string.Format(SR.Config_invalid_attributes_for_write, streamName));
+ }
+ }
+
+ try
+ {
+ stream = new FileStream(writeFileContext.TempNewFilename, FileMode.Create, FileAccess.Write, FileShare.Read);
+ }
+ catch (Exception e)
+ {
+ // Wrap all exceptions so that we provide a meaningful filename - otherwise the end user
+ // will just see the temporary file name, which is meaningless.
+
+ throw new ConfigurationErrorsException(string.Format(SR.Config_write_failed, streamName), e);
+ }
+ }
+ catch
+ {
+ writeFileContext?.Complete(streamName, false);
+ throw;
+ }
+
+ writeContext = writeFileContext;
+ return stream;
+
+ }
+
+ internal static void StaticWriteCompleted(string streamName, bool success, object writeContext)
+ {
+ ((WriteFileContext)writeContext).Complete(streamName, success);
+ }
+
+ internal static void StaticDeleteStream(string streamName)
+ {
+ File.Delete(streamName);
+ }
+
+ internal static bool StaticIsFile(string streamName)
+ {
+ return Path.IsPathRooted(streamName);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/InternalConfigRoot.cs b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigRoot.cs
new file mode 100644
index 0000000000..d72193a7c9
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigRoot.cs
@@ -0,0 +1,311 @@
+// 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.Threading;
+
+namespace System.Configuration.Internal
+{
+ // InternalConfigRoot holds the root of a configuration hierarchy.
+ // It managed creation, removal, and the search for BaseConfigurationRecord's.
+ // in a thread-safe manner.
+ //
+ // The BaseConfigurationRecord hierarchy is protected with the
+ // _hierarchyLock. Functions that assume that the lock as been
+ // taken begin with the prefix "hl", for example, "hlFindConfigRecord".
+ internal sealed class InternalConfigRoot : IInternalConfigRoot
+ {
+ private ReaderWriterLock _hierarchyLock;
+ private bool _isDesignTime;
+
+ internal InternalConfigRoot()
+ {
+ }
+
+ internal InternalConfigRoot(Configuration currentConfiguration, UpdateConfigHost host)
+ {
+ CurrentConfiguration = currentConfiguration;
+ UpdateConfigHost = host;
+ }
+
+ internal IInternalConfigHost Host { get; private set; }
+
+ internal UpdateConfigHost UpdateConfigHost { get; private set; }
+
+ internal BaseConfigurationRecord RootConfigRecord { get; private set; }
+
+ internal Configuration CurrentConfiguration { get; }
+
+ public event InternalConfigEventHandler ConfigChanged;
+ public event InternalConfigEventHandler ConfigRemoved;
+
+ void IInternalConfigRoot.Init(IInternalConfigHost host, bool isDesignTime)
+ {
+ Host = host;
+ _isDesignTime = isDesignTime;
+ _hierarchyLock = new ReaderWriterLock();
+
+ // Dummy record to hold _children for root
+ if (_isDesignTime) RootConfigRecord = MgmtConfigurationRecord.Create(this, null, string.Empty, null);
+ else
+ {
+ RootConfigRecord =
+ (BaseConfigurationRecord)RuntimeConfigurationRecord.Create(this, null, string.Empty);
+ }
+ }
+
+ bool IInternalConfigRoot.IsDesignTime => _isDesignTime;
+
+ public object GetSection(string section, string configPath)
+ {
+ BaseConfigurationRecord configRecord = (BaseConfigurationRecord)GetUniqueConfigRecord(configPath);
+ object result = configRecord.GetSection(section);
+ return result;
+ }
+
+ // Get the nearest ancestor path (including self) which contains unique configuration information.
+ public string GetUniqueConfigPath(string configPath)
+ {
+ IInternalConfigRecord configRecord = GetUniqueConfigRecord(configPath);
+
+ return configRecord?.ConfigPath;
+ }
+
+ // Get the nearest ancestor record (including self) which contains unique configuration information.
+ public IInternalConfigRecord GetUniqueConfigRecord(string configPath)
+ {
+ BaseConfigurationRecord configRecord = (BaseConfigurationRecord)GetConfigRecord(configPath);
+ while (configRecord.IsEmpty)
+ {
+ BaseConfigurationRecord parentConfigRecord = configRecord.Parent;
+
+ // If all config records are empty, return the immediate child of the
+ // root placeholder (e.g. machine.config)
+ if (parentConfigRecord.IsRootConfig) break;
+
+ configRecord = parentConfigRecord;
+ }
+
+ return configRecord;
+ }
+
+ // Get the config record for a path.
+ // If the record does not exist, create it if it is needed.
+ public IInternalConfigRecord GetConfigRecord(string configPath)
+ {
+ if (!ConfigPathUtility.IsValid(configPath)) throw ExceptionUtil.ParameterInvalid("configPath");
+
+ string[] parts = ConfigPathUtility.GetParts(configPath);
+
+ // First search under the reader lock, so that multiple searches
+ // can proceed in parallel.
+ try
+ {
+ int index;
+ BaseConfigurationRecord currentRecord;
+
+ AcquireHierarchyLockForRead();
+
+ HlFindConfigRecord(parts, out index, out currentRecord);
+
+ // check if found
+ if ((index == parts.Length) || !currentRecord.HlNeedsChildFor(parts[index])) return currentRecord;
+ }
+ finally
+ {
+ ReleaseHierarchyLockForRead();
+ }
+
+ // Not found, so search again under exclusive writer lock so that
+ // we can create the record.
+ try
+ {
+ int index;
+ BaseConfigurationRecord currentRecord;
+
+ AcquireHierarchyLockForWrite();
+
+ HlFindConfigRecord(parts, out index, out currentRecord);
+
+ if (index == parts.Length) return currentRecord;
+
+ string currentConfigPath = string.Join(BaseConfigurationRecord.ConfigPathSeparatorString, parts, 0,
+ index);
+
+ // Create new records
+ while ((index < parts.Length) && currentRecord.HlNeedsChildFor(parts[index]))
+ {
+ string configName = parts[index];
+ currentConfigPath = ConfigPathUtility.Combine(currentConfigPath, configName);
+ BaseConfigurationRecord childRecord;
+
+ childRecord = _isDesignTime
+ ? MgmtConfigurationRecord.Create(this, currentRecord, currentConfigPath, null)
+ : (BaseConfigurationRecord) RuntimeConfigurationRecord.Create(this, currentRecord, currentConfigPath);
+
+ currentRecord.HlAddChild(configName, childRecord);
+
+ index++;
+ currentRecord = childRecord;
+ }
+
+ return currentRecord;
+ }
+ finally
+ {
+ ReleaseHierarchyLockForWrite();
+ }
+ }
+
+ // Find and remove the config record and all its children for the config path.
+ public void RemoveConfig(string configPath)
+ {
+ RemoveConfigImpl(configPath, null);
+ }
+
+ private void AcquireHierarchyLockForRead()
+ {
+ // Protect against unexpected recursive entry on this thread.
+ // We do this in retail, too, because the results would be very bad if this were to fail,
+ // and the testing for this is not easy for all scenarios.
+ if (_hierarchyLock.IsReaderLockHeld)
+ throw ExceptionUtil.UnexpectedError(
+ "System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForRead - reader lock already held by this thread");
+
+ if (_hierarchyLock.IsWriterLockHeld)
+ throw ExceptionUtil.UnexpectedError(
+ "System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForRead - writer lock already held by this thread");
+
+ _hierarchyLock.AcquireReaderLock(-1);
+ }
+
+ private void ReleaseHierarchyLockForRead()
+ {
+ Debug.Assert(!_hierarchyLock.IsWriterLockHeld, "!_hierarchyLock.IsWriterLockHeld");
+
+ if (_hierarchyLock.IsReaderLockHeld) _hierarchyLock.ReleaseReaderLock();
+ }
+
+ private void AcquireHierarchyLockForWrite()
+ {
+ // Protect against unexpected recursive entry on this thread.
+ // We do this in retail, too, because the results would be very bad if this were to fail,
+ // and the testing for this is not easy for all scenarios.
+ if (_hierarchyLock.IsReaderLockHeld)
+ throw ExceptionUtil.UnexpectedError(
+ "System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForWrite - reader lock already held by this thread");
+
+ if (_hierarchyLock.IsWriterLockHeld)
+ throw ExceptionUtil.UnexpectedError(
+ "System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForWrite - writer lock already held by this thread");
+
+ _hierarchyLock.AcquireWriterLock(-1);
+ }
+
+ private void ReleaseHierarchyLockForWrite()
+ {
+ Debug.Assert(!_hierarchyLock.IsReaderLockHeld, "!_hierarchyLock.IsReaderLockHeld");
+
+ if (_hierarchyLock.IsWriterLockHeld)
+ _hierarchyLock.ReleaseWriterLock();
+ }
+
+ // Find a config record.
+ // If found, nextIndex == parts.Length and the resulting record is in currentRecord.
+ // If not found, nextIndex is the index of the part of the path not found, and currentRecord
+ // is the record that has been found so far (nexIndex - 1).
+ private void HlFindConfigRecord(string[] parts, out int nextIndex, out BaseConfigurationRecord currentRecord)
+ {
+ currentRecord = RootConfigRecord;
+ nextIndex = 0;
+ for (; nextIndex < parts.Length; nextIndex++)
+ {
+ BaseConfigurationRecord childRecord = currentRecord.HlGetChild(parts[nextIndex]);
+ if (childRecord == null)
+ break;
+
+ currentRecord = childRecord;
+ }
+ }
+
+ // Find and remove the config record and all its children for the config path.
+ // Optionally ensure the config record matches a desired config record.
+ private void RemoveConfigImpl(string configPath, BaseConfigurationRecord configRecord)
+ {
+ if (!ConfigPathUtility.IsValid(configPath)) throw ExceptionUtil.ParameterInvalid("configPath");
+
+ string[] parts = ConfigPathUtility.GetParts(configPath);
+
+ BaseConfigurationRecord currentRecord;
+
+ // search under exclusive writer lock
+ try
+ {
+ int index;
+ AcquireHierarchyLockForWrite();
+ HlFindConfigRecord(parts, out index, out currentRecord);
+
+ // Return if not found, or does not match the one we are trying to remove.
+ if ((index != parts.Length) || ((configRecord != null) && !ReferenceEquals(configRecord, currentRecord)))
+ return;
+
+ // Remove it from the hierarchy.
+ currentRecord.Parent.HlRemoveChild(parts[parts.Length - 1]);
+ }
+ finally
+ {
+ ReleaseHierarchyLockForWrite();
+ }
+
+ OnConfigRemoved(new InternalConfigEventArgs(configPath));
+
+ // Close the record. This is safe to do outside the lock.
+ currentRecord.CloseRecursive();
+ }
+
+ // Remove the config record and all its children for the config path.
+ public void RemoveConfigRecord(BaseConfigurationRecord configRecord)
+ {
+ RemoveConfigImpl(configRecord.ConfigPath, configRecord);
+ }
+
+ // Clear the result of a configSection evaluation at a particular point
+ // in the hierarchy.
+ public void ClearResult(BaseConfigurationRecord configRecord, string configKey, bool forceEvaluation)
+ {
+ string[] parts = ConfigPathUtility.GetParts(configRecord.ConfigPath);
+
+ try
+ {
+ int index;
+ BaseConfigurationRecord currentRecord;
+ AcquireHierarchyLockForRead();
+ HlFindConfigRecord(parts, out index, out currentRecord);
+
+ // clear result only if configRecord it is still in the hierarchy
+ if ((index == parts.Length) && ReferenceEquals(configRecord, currentRecord))
+ currentRecord.HlClearResultRecursive(configKey, forceEvaluation);
+ }
+ finally
+ {
+ ReleaseHierarchyLockForRead();
+ }
+ }
+
+ private void OnConfigRemoved(InternalConfigEventArgs e)
+ {
+ ConfigRemoved?.Invoke(this, e);
+ }
+
+ internal void FireConfigChanged(string configPath)
+ {
+ OnConfigChanged(new InternalConfigEventArgs(configPath));
+ }
+
+ private void OnConfigChanged(InternalConfigEventArgs e)
+ {
+ ConfigChanged?.Invoke(this, e);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/InternalConfigSettingsFactory.cs b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigSettingsFactory.cs
new file mode 100644
index 0000000000..63aa17456d
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/InternalConfigSettingsFactory.cs
@@ -0,0 +1,21 @@
+// 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.Configuration.Internal
+{
+ internal sealed class InternalConfigSettingsFactory : IInternalConfigSettingsFactory
+ {
+ private InternalConfigSettingsFactory() { }
+
+ void IInternalConfigSettingsFactory.SetConfigurationSystem(IInternalConfigSystem configSystem, bool initComplete)
+ {
+ ConfigurationManager.SetConfigurationSystem(configSystem, initComplete);
+ }
+
+ void IInternalConfigSettingsFactory.CompleteInit()
+ {
+ ConfigurationManager.CompleteConfigInit();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/CompressionMode.cs b/src/System.Configuration/src/System/Configuration/Internal/StreamChangeCallback.cs
index 2d641d50a9..7a625aa668 100644
--- a/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/CompressionMode.cs
+++ b/src/System.Configuration/src/System/Configuration/Internal/StreamChangeCallback.cs
@@ -2,12 +2,7 @@
// 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.IO.Compression
+namespace System.Configuration.Internal
{
- public enum CompressionMode
- {
- Decompress = 0,
- Compress = 1
- }
-}
-
+ public delegate void StreamChangeCallback(string streamName);
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Internal/WriteFileContext.cs b/src/System.Configuration/src/System/Configuration/Internal/WriteFileContext.cs
new file mode 100644
index 0000000000..f8c28dc691
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Internal/WriteFileContext.cs
@@ -0,0 +1,221 @@
+// 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.CodeDom.Compiler;
+using System.IO;
+using System.Threading;
+
+namespace System.Configuration.Internal
+{
+ internal class WriteFileContext
+ {
+ private const int SavingTimeout = 10000; // 10 seconds
+ private const int SavingRetryInterval = 100; // 100 milliseconds
+ private readonly string _templateFilename;
+
+ private TempFileCollection _tempFiles;
+
+ internal WriteFileContext(string filename, string templateFilename)
+ {
+ string directoryname = UrlPath.GetDirectoryOrRootName(filename);
+
+ _templateFilename = templateFilename;
+ _tempFiles = new TempFileCollection(directoryname);
+ try
+ {
+ TempNewFilename = _tempFiles.AddExtension("newcfg");
+ }
+ catch
+ {
+ ((IDisposable)_tempFiles).Dispose();
+ _tempFiles = null;
+ throw;
+ }
+ }
+
+ internal string TempNewFilename { get; }
+
+ // Cleanup the WriteFileContext object based on either success
+ // or failure
+ //
+ // Note: The current algorithm guarantess
+ // 1) The file we are saving to will always be present
+ // on the file system (ie. there will be no window
+ // during saving in which there won't be a file there)
+ // 2) It will always be available for reading from a
+ // client and it will be complete and accurate.
+ //
+ // ... This means that writing is a bit more complicated, and may
+ // have to be retried (because of reading lock), but I don't see
+ // anyway to get around this given 1 and 2.
+ internal void Complete(string filename, bool success)
+ {
+ try
+ {
+ if (!success) return;
+
+ if (File.Exists(filename))
+ {
+ // Test that we can write to the file
+ ValidateWriteAccess(filename);
+
+ // Copy Attributes from original
+ DuplicateFileAttributes(filename, TempNewFilename);
+ }
+ else
+ {
+ if (_templateFilename != null)
+ {
+ // Copy Acl from template file
+ DuplicateTemplateAttributes(_templateFilename, TempNewFilename);
+ }
+ }
+
+ ReplaceFile(TempNewFilename, filename);
+
+ // Don't delete, since we just moved it.
+ _tempFiles.KeepFiles = true;
+ }
+ finally
+ {
+ ((IDisposable)_tempFiles).Dispose();
+ _tempFiles = null;
+ }
+ }
+
+ // Copy all the files attributes that we care about from the source
+ // file to the destination file
+ private void DuplicateFileAttributes(string source, string destination)
+ {
+ DateTime creationTime;
+
+ // Copy File Attributes, ie. Hidden, Readonly, etc.
+ FileAttributes attributes = File.GetAttributes(source);
+ File.SetAttributes(destination, attributes);
+
+ // Copy Creation Time
+ creationTime = File.GetCreationTimeUtc(source);
+ File.SetCreationTimeUtc(destination, creationTime);
+
+ // Copy ACL's
+ DuplicateTemplateAttributes(source, destination);
+ }
+
+ // Copy over all the attributes you would want copied from a template file.
+ // As of right now this is just acl's
+ private void DuplicateTemplateAttributes(string source, string destination)
+ {
+ FileAttributes fileAttributes = File.GetAttributes(source);
+ File.SetAttributes(destination, fileAttributes);
+ }
+
+ // Validate that we can write to the file. This will enforce the ACL's
+ // on the file. Since we do our moving of files to replace, this is
+ // nice to ensure we are not by-passing some security permission
+ // that someone set (although that could bypass this via move themselves)
+ //
+ // Note: 1) This is really just a nice to have, since with directory permissions
+ // they could do the same thing we are doing
+ //
+ // 2) We are depending on the current behavior that if the file is locked
+ // and we can not open it, that we will get an UnauthorizedAccessException
+ // and not the IOException.
+ private void ValidateWriteAccess(string filename)
+ {
+ FileStream fs = null;
+
+ try
+ {
+ // Try to open file for write access
+ fs = new FileStream(filename,
+ FileMode.Open,
+ FileAccess.Write,
+ FileShare.ReadWrite);
+ }
+ catch (IOException)
+ {
+ // Someone else was using the file. Since we did not get
+ // the unauthorizedAccessException we have access to the file
+ }
+ finally
+ {
+ fs?.Close();
+ }
+ }
+
+ // Replace one file with another using MoveFileEx. This will
+ // retry the operation if the file is locked because someone
+ // is reading it
+ private void ReplaceFile(string source, string target)
+ {
+ bool writeSucceeded;
+ int duration = 0;
+
+ writeSucceeded = AttemptMove(source, target);
+
+ // The file may be open for read, if it is then
+ // lets try again because maybe they will finish
+ // soon, and we will be able to replace
+ while (!writeSucceeded &&
+ (duration < SavingTimeout) &&
+ File.Exists(target) &&
+ !FileIsWriteLocked(target))
+ {
+ Thread.Sleep(SavingRetryInterval);
+ duration += SavingRetryInterval;
+ writeSucceeded = AttemptMove(source, target);
+ }
+
+ if (!writeSucceeded)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_write_failed, target));
+ }
+ }
+
+ // Attempt to move a file from one location to another
+ private bool AttemptMove(string source, string target)
+ {
+ try
+ {
+ File.Replace(source, target, null);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ private static bool FileIsWriteLocked(string fileName)
+ {
+ Stream fileStream = null;
+
+ if (!File.Exists(fileName))
+ {
+ // It can't be locked if it doesn't exist
+ return false;
+ }
+
+ try
+ {
+ // Try to open for shared reading
+ fileStream = new FileStream(fileName,
+ FileMode.Open,
+ FileAccess.Read,
+ FileShare.Read | FileShare.Delete);
+
+ // If we can open it for shared reading, it is not write locked
+ return false;
+ }
+ catch
+ {
+ return true;
+ }
+ finally
+ {
+ fileStream?.Close();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/InvalidPropValue.cs b/src/System.Configuration/src/System/Configuration/InvalidPropValue.cs
new file mode 100644
index 0000000000..6a94e3e88a
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/InvalidPropValue.cs
@@ -0,0 +1,20 @@
+// 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.Configuration
+{
+ // Class to support caching of property values as string
+ internal sealed class InvalidPropValue
+ {
+ internal InvalidPropValue(string value, ConfigurationException error)
+ {
+ Value = value;
+ Error = error;
+ }
+
+ internal ConfigurationException Error { get; }
+
+ internal string Value { get; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/KeyValueConfigurationCollection.cs b/src/System.Configuration/src/System/Configuration/KeyValueConfigurationCollection.cs
new file mode 100644
index 0000000000..84ed668d00
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/KeyValueConfigurationCollection.cs
@@ -0,0 +1,77 @@
+// 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.Configuration
+{
+ [ConfigurationCollection(typeof(KeyValueConfigurationElement))]
+ public class KeyValueConfigurationCollection : ConfigurationElementCollection
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ static KeyValueConfigurationCollection()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection();
+ }
+
+ public KeyValueConfigurationCollection() :
+ base(StringComparer.OrdinalIgnoreCase)
+ {
+ InternalAddToEnd = true;
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ protected override bool ThrowOnDuplicate => false;
+
+ public new KeyValueConfigurationElement this[string key] => (KeyValueConfigurationElement)BaseGet(key);
+
+ public string[] AllKeys => StringUtil.ObjectArrayToStringArray(BaseGetAllKeys());
+
+ public void Add(KeyValueConfigurationElement keyValue)
+ {
+ // Need to initialize in order to get the key
+ keyValue.Init();
+
+ // the appsettings add works more like a namevalue collection add in that it appends values
+ // when add is called and teh key already exists.
+ KeyValueConfigurationElement oldValue = (KeyValueConfigurationElement)BaseGet(keyValue.Key);
+ if (oldValue == null)
+ BaseAdd(keyValue);
+ else
+ {
+ oldValue.Value += "," + keyValue.Value;
+ int index = BaseIndexOf(oldValue);
+ BaseRemoveAt(index);
+ BaseAdd(index, oldValue);
+ }
+ }
+
+ public void Add(string key, string value)
+ {
+ KeyValueConfigurationElement element = new KeyValueConfigurationElement(key, value);
+ Add(element);
+ }
+
+ public void Remove(string key)
+ {
+ BaseRemove(key);
+ }
+
+ public void Clear()
+ {
+ BaseClear();
+ }
+
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new KeyValueConfigurationElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((KeyValueConfigurationElement)element).Key;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/KeyValueConfigurationElement.cs b/src/System.Configuration/src/System/Configuration/KeyValueConfigurationElement.cs
new file mode 100644
index 0000000000..6afbf9087f
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/KeyValueConfigurationElement.cs
@@ -0,0 +1,64 @@
+// 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.Configuration
+{
+ public class KeyValueConfigurationElement : ConfigurationElement
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ private static readonly ConfigurationProperty s_propKey =
+ new ConfigurationProperty("key", typeof(string), string.Empty,
+ ConfigurationPropertyOptions.IsKey | ConfigurationPropertyOptions.IsRequired);
+
+ private static readonly ConfigurationProperty s_propValue =
+ new ConfigurationProperty("value", typeof(string), string.Empty, ConfigurationPropertyOptions.None);
+
+ private readonly string _initKey;
+ private readonly string _initValue;
+
+ private bool _needsInit;
+
+ static KeyValueConfigurationElement()
+ {
+ s_properties = new ConfigurationPropertyCollection { s_propKey, s_propValue };
+ }
+
+ internal KeyValueConfigurationElement() { }
+
+ public KeyValueConfigurationElement(string key, string value)
+ {
+ _needsInit = true;
+ _initKey = key;
+ _initValue = value;
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ [ConfigurationProperty("key", Options = ConfigurationPropertyOptions.IsKey, DefaultValue = "")]
+ public string Key => (string)base[s_propKey];
+
+ [ConfigurationProperty("value", DefaultValue = "")]
+ public string Value
+ {
+ get { return (string)base[s_propValue]; }
+ set { base[s_propValue] = value; }
+ }
+
+ protected internal override void Init()
+ {
+ base.Init();
+
+ // We cannot initialize configuration properties in the constructor,
+ // because Properties is an overridable virtual property that
+ // hence may not be available in the constructor.
+ if (_needsInit)
+ {
+ _needsInit = false;
+ base[s_propKey] = _initKey;
+ Value = _initValue;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/KeyValueInternalCollection.cs b/src/System.Configuration/src/System/Configuration/KeyValueInternalCollection.cs
new file mode 100644
index 0000000000..9763d2e1e2
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/KeyValueInternalCollection.cs
@@ -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.Collections.Specialized;
+
+namespace System.Configuration
+{
+ internal class KeyValueInternalCollection : NameValueCollection
+ {
+ private readonly AppSettingsSection _root;
+
+ public KeyValueInternalCollection(AppSettingsSection root)
+ {
+ _root = root;
+ foreach (KeyValueConfigurationElement element in _root.Settings) base.Add(element.Key, element.Value);
+ }
+
+ public override void Add(string key, string value)
+ {
+ _root.Settings.Add(new KeyValueConfigurationElement(key, value));
+ base.Add(key, value);
+ }
+
+ public override void Clear()
+ {
+ _root.Settings.Clear();
+ base.Clear();
+ }
+
+ public override void Remove(string key)
+ {
+ _root.Settings.Remove(key);
+ base.Remove(key);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/LocationSectionRecord.cs b/src/System.Configuration/src/System/Configuration/LocationSectionRecord.cs
new file mode 100644
index 0000000000..a55831eacc
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/LocationSectionRecord.cs
@@ -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.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ [DebuggerDisplay("LocationSectionRecord {ConfigKey}")]
+ internal class LocationSectionRecord
+ {
+ private List<ConfigurationException> _errors; // errors
+
+ internal LocationSectionRecord(SectionXmlInfo sectionXmlInfo, List<ConfigurationException> errors)
+ {
+ SectionXmlInfo = sectionXmlInfo;
+ _errors = errors;
+ }
+
+ internal string ConfigKey => SectionXmlInfo.ConfigKey;
+
+ internal SectionXmlInfo SectionXmlInfo { get; }
+
+ // Errors associated with the parse of a location section.
+ internal ICollection<ConfigurationException> Errors => _errors;
+
+ internal List<ConfigurationException> ErrorsList => _errors;
+
+ internal bool HasErrors => ErrorsHelper.GetHasErrors(_errors);
+
+ internal void AddError(ConfigurationException e)
+ {
+ ErrorsHelper.AddError(ref _errors, e);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/LocationUpdates.cs b/src/System.Configuration/src/System/Configuration/LocationUpdates.cs
new file mode 100644
index 0000000000..62e571771e
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/LocationUpdates.cs
@@ -0,0 +1,30 @@
+// 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.Configuration
+{
+ // LocationUpdates contains all the updates that share the same location characteristics.
+ internal class LocationUpdates
+ {
+ internal LocationUpdates(OverrideModeSetting overrideMode, bool inheritInChildApps)
+ {
+ OverrideMode = overrideMode;
+ InheritInChildApps = inheritInChildApps;
+ SectionUpdates = new SectionUpdates(string.Empty);
+ }
+
+ internal OverrideModeSetting OverrideMode { get; }
+
+ internal bool InheritInChildApps { get; }
+
+ internal SectionUpdates SectionUpdates { get; }
+
+ internal bool IsDefault => OverrideMode.IsDefaultForLocationTag && InheritInChildApps;
+
+ internal void CompleteUpdates()
+ {
+ SectionUpdates.CompleteUpdates();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/LongValidator.cs b/src/System.Configuration/src/System/Configuration/LongValidator.cs
new file mode 100644
index 0000000000..f9cda5dce0
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/LongValidator.cs
@@ -0,0 +1,58 @@
+// 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.Configuration
+{
+ public class LongValidator : ConfigurationValidatorBase
+ {
+ private readonly ValidationFlags _flags;
+ private readonly long _maxValue;
+ private readonly long _minValue;
+ private readonly long _resolution;
+
+ public LongValidator(long minValue, long maxValue)
+ : this(minValue, maxValue, false, 1)
+ { }
+
+ public LongValidator(long minValue, long maxValue, bool rangeIsExclusive)
+ : this(minValue, maxValue, rangeIsExclusive, 1)
+ { }
+
+ public LongValidator(long minValue, long maxValue, bool rangeIsExclusive, long resolution)
+ {
+ if (resolution <= 0) throw new ArgumentOutOfRangeException(nameof(resolution));
+
+ if (minValue > maxValue)
+ throw new ArgumentOutOfRangeException(nameof(minValue), SR.Validator_min_greater_than_max);
+
+ _minValue = minValue;
+ _maxValue = maxValue;
+ _resolution = resolution;
+
+ _flags = rangeIsExclusive ? ValidationFlags.ExclusiveRange : ValidationFlags.None;
+ }
+
+ public override bool CanValidate(Type type)
+ {
+ return type == typeof(long);
+ }
+
+ public override void Validate(object value)
+ {
+ ValidatorUtils.HelperParamValidation(value, typeof(long));
+
+ ValidatorUtils.ValidateScalar((long)value,
+ _minValue,
+ _maxValue,
+ _resolution,
+ _flags == ValidationFlags.ExclusiveRange);
+ }
+
+ private enum ValidationFlags
+ {
+ None = 0x0000,
+ ExclusiveRange = 0x0001, // If set the value must be outside of the range instead of inside
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/LongValidatorAttribute.cs b/src/System.Configuration/src/System/Configuration/LongValidatorAttribute.cs
new file mode 100644
index 0000000000..bee4661304
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/LongValidatorAttribute.cs
@@ -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.
+
+namespace System.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class LongValidatorAttribute : ConfigurationValidatorAttribute
+ {
+ private long _max = long.MaxValue;
+ private long _min = long.MinValue;
+
+ public override ConfigurationValidatorBase ValidatorInstance => new LongValidator(_min, _max, ExcludeRange);
+
+ public long MinValue
+ {
+ get { return _min; }
+ set
+ {
+ if (_max < value)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.Validator_min_greater_than_max);
+ _min = value;
+ }
+ }
+
+ public long MaxValue
+ {
+ get { return _max; }
+ set
+ {
+ if (_min > value)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.Validator_min_greater_than_max);
+ _max = value;
+ }
+ }
+
+ public bool ExcludeRange { get; set; } = false;
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/MgmtConfigurationRecord.cs b/src/System.Configuration/src/System/Configuration/MgmtConfigurationRecord.cs
new file mode 100644
index 0000000000..e9e0fabdb4
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/MgmtConfigurationRecord.cs
@@ -0,0 +1,3186 @@
+// 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.Collections.Generic;
+using System.Collections.Specialized;
+using System.Configuration.Internal;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class MgmtConfigurationRecord : BaseConfigurationRecord
+ {
+ private const int DefaultIndent = 4;
+ private const int MaxIndent = 10;
+
+ private static readonly SimpleBitVector32 s_mgmtClassFlags = new SimpleBitVector32(
+ ClassSupportsKeepInputs
+ | ClassIgnoreLocalErrors);
+
+ private Hashtable _locationTags;
+ private Hashtable _removedSectionGroups;
+ private Hashtable _removedSections;
+ private Hashtable _sectionFactories;
+ private Hashtable _sectionGroupFactories;
+ private Hashtable _sectionGroups;
+ private HybridDictionary _streamInfoUpdates;
+
+ // don't allow instantiation except by Create
+ private MgmtConfigurationRecord() { }
+
+ // The parent config record cast to this type
+ private MgmtConfigurationRecord MgmtParent => (MgmtConfigurationRecord)_parent;
+
+ // The IInternalConfigHost cast to UpdateConfigHost.
+ private UpdateConfigHost UpdateConfigHost => _configRoot.UpdateConfigHost;
+
+ protected override SimpleBitVector32 ClassFlags => s_mgmtClassFlags;
+
+ private Hashtable SectionGroups => _sectionGroups ?? (_sectionGroups = new Hashtable());
+
+ private Hashtable RemovedSections => _removedSections ?? (_removedSections = new Hashtable());
+
+ private Hashtable RemovedSectionGroups => _removedSectionGroups ?? (_removedSectionGroups = new Hashtable());
+
+ internal Hashtable SectionFactories => _sectionFactories ?? (_sectionFactories = GetAllFactories(false));
+
+ internal Hashtable SectionGroupFactories
+ => _sectionGroupFactories ?? (_sectionGroupFactories = GetAllFactories(true));
+
+ internal string ConfigurationFilePath => UpdateConfigHost.GetNewStreamname(ConfigStreamInfo.StreamName) ?? string.Empty;
+
+ private bool HasRemovedSectionsOrGroups => ((_removedSections != null) && (_removedSections.Count > 0))
+ || ((_removedSectionGroups != null) && (_removedSectionGroups.Count > 0));
+
+ private bool HasRemovedSections => (_removedSections != null) && (_removedSections.Count > 0);
+
+ internal bool NamespacePresent
+ {
+ get { return _flags[NamespacePresentCurrent]; }
+ set { _flags[NamespacePresentCurrent] = value; }
+ }
+
+ // On Update, do we need to add the namespace, remove it, or do nothing?
+ private NamespaceChange NamespaceChangeNeeded
+ {
+ get
+ {
+ if (_flags[NamespacePresentCurrent] == _flags[NamespacePresentInFile]) return NamespaceChange.None;
+ return _flags[NamespacePresentCurrent] ? NamespaceChange.Add : NamespaceChange.Remove;
+ }
+ }
+
+ // Outside the scope of the sections and there definitions, does
+ // the record itself require an update.
+ private bool RecordItselfRequiresUpdates => NamespaceChangeNeeded != NamespaceChange.None;
+
+ internal static MgmtConfigurationRecord Create(
+ IInternalConfigRoot configRoot,
+ IInternalConfigRecord parent,
+ string configPath,
+ string locationSubPath)
+ {
+ MgmtConfigurationRecord configRecord = new MgmtConfigurationRecord();
+ configRecord.Init(configRoot, parent, configPath, locationSubPath);
+ return configRecord;
+ }
+
+ private void Init(
+ IInternalConfigRoot configRoot,
+ IInternalConfigRecord parent,
+ string configPath,
+ string locationSubPath)
+ {
+ base.Init(configRoot, (BaseConfigurationRecord)parent, configPath, locationSubPath);
+
+ if (IsLocationConfig &&
+ ((MgmtParent._locationTags == null) || !MgmtParent._locationTags.Contains(_locationSubPath)))
+ {
+ // By instantiating a "new" LocationSubPath class, we have implicitly
+ // asked for one to be created
+ _flags[ForceLocationWritten] = true;
+ }
+
+ // Copy all stream information so that we can model changes to ConfigSource
+ InitStreamInfoUpdates();
+ }
+
+ private void InitStreamInfoUpdates()
+ {
+ _streamInfoUpdates = new HybridDictionary(true);
+ if (ConfigStreamInfo.HasStreamInfos)
+ {
+ foreach (StreamInfo streamInfo in ConfigStreamInfo.StreamInfos.Values)
+ _streamInfoUpdates.Add(streamInfo.StreamName, streamInfo.Clone());
+ }
+ }
+
+ protected override object CreateSectionFactory(FactoryRecord factoryRecord)
+ {
+ // Get the type of the factory
+ Type type = TypeUtil.GetType(Host, factoryRecord.FactoryTypeName, true);
+
+ // If the type is not a ConfigurationSection, use the DefaultSection if the type
+ // implements IConfigurationSectionHandler.
+ if (!typeof(ConfigurationSection).IsAssignableFrom(type))
+ {
+ TypeUtil.VerifyAssignableType(typeof(IConfigurationSectionHandler), type, true);
+ type = typeof(DefaultSection);
+ }
+
+ ConstructorInfo ctor = TypeUtil.GetConstructor(type, typeof(ConfigurationSection), true);
+
+ return ctor;
+ }
+
+ protected override object CreateSection(bool inputIsTrusted, FactoryRecord factoryRecord,
+ SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader)
+ {
+ // Create an instance of the ConfigurationSection
+ ConstructorInfo ctor = (ConstructorInfo)factoryRecord.Factory;
+ ConfigurationSection configSection =
+ (ConfigurationSection)ctor.Invoke(null);
+
+ // Attach the ConfigurationSection to this record
+ configSection.SectionInformation.AttachToConfigurationRecord(this, factoryRecord, sectionRecord);
+ configSection.CallInit();
+
+ // Initialize the ConfigurationSection with XML or just its parent.
+ ConfigurationSection parentConfigSection = (ConfigurationSection)parentConfig;
+ configSection.Reset(parentConfigSection);
+ if (reader != null) configSection.DeserializeSection(reader);
+
+ // Clear the modified bit.
+ configSection.ResetModified();
+
+ return configSection;
+ }
+
+ private ConstructorInfo CreateSectionGroupFactory(FactoryRecord factoryRecord)
+ {
+ Type type = string.IsNullOrEmpty(factoryRecord.FactoryTypeName)
+ ? typeof(ConfigurationSectionGroup)
+ : TypeUtil.GetType(Host, factoryRecord.FactoryTypeName, true);
+
+ ConstructorInfo ctor = TypeUtil.GetConstructor(type,
+ typeof(ConfigurationSectionGroup), true);
+
+ return ctor;
+ }
+
+ private ConstructorInfo EnsureSectionGroupFactory(FactoryRecord factoryRecord)
+ {
+ ConstructorInfo factory = (ConstructorInfo)factoryRecord.Factory;
+ if (factory == null)
+ {
+ factory = CreateSectionGroupFactory(factoryRecord);
+ factoryRecord.Factory = factory;
+ }
+
+ return factory;
+ }
+
+
+ // Create a new ConfigurationSection with the same values as the parent.
+ // We must use a different instance than the parent, as the parent is cached
+ // by the config system and the child ConfigurationSection may change due to
+ // user interaction.
+ protected override object UseParentResult(string configKey, object parentResult, SectionRecord sectionRecord)
+ {
+ FactoryRecord factoryRecord = FindFactoryRecord(configKey, false);
+ if (factoryRecord == null)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_unrecognized_configuration_section,
+ configKey));
+ }
+
+ object result = CallCreateSection(false, factoryRecord, sectionRecord, parentResult, null, null, -1);
+ return result;
+ }
+
+ // There is no runtime object at designtime - always return the result.
+ protected override object GetRuntimeObject(object result)
+ {
+ return result;
+ }
+
+ // Return the section result cast to a ConfigurationSection,
+ // or null if the section does not exist or has not been evaluated.
+ private ConfigurationSection GetConfigSection(string configKey)
+ {
+ SectionRecord sectionRecord = GetSectionRecord(configKey, false);
+ if ((sectionRecord != null) && sectionRecord.HasResult) return (ConfigurationSection)sectionRecord.Result;
+ return null;
+ }
+
+ // Lookup a section group. Return null if it doesn't exist or hasn't been evaluated.
+ internal ConfigurationSectionGroup LookupSectionGroup(string configKey)
+ {
+ ConfigurationSectionGroup configSectionGroup = null;
+ if (_sectionGroups != null) configSectionGroup = (ConfigurationSectionGroup)_sectionGroups[configKey];
+
+ return configSectionGroup;
+ }
+
+ // Returns the ConfigurationSectionGroup of the configKey.
+ // The ConfigurationSectionGroup is created if it doesn't exist.
+ // This method only returns null if a FactoryRecord does not exist for the
+ // desired configKey.
+ internal ConfigurationSectionGroup GetSectionGroup(string configKey)
+ {
+ ConfigurationSectionGroup configSectionGroup = LookupSectionGroup(configKey);
+ if (configSectionGroup != null) return configSectionGroup;
+
+ BaseConfigurationRecord configRecord;
+ FactoryRecord factoryRecord = FindFactoryRecord(configKey, false, out configRecord);
+ if (factoryRecord == null) return null;
+
+ if (!factoryRecord.IsGroup) throw ExceptionUtil.ParameterInvalid("sectionGroupName");
+
+ if (factoryRecord.FactoryTypeName == null)
+ {
+ // If no type is defined for the section group, return a base ConfigurationSectionGroup.
+ // For example:
+ // <configSections>
+ // <sectionGroup name="mySectionGroup" />
+ // </configSections>
+ configSectionGroup = new ConfigurationSectionGroup();
+ }
+ else
+ {
+ // Create the section group of the desired type.
+ // For example:
+ // <configSections>
+ // <sectionGroup name="mySectionGroup" type="MySectionGroupType, acme" />
+ // </configSections>
+ ConstructorInfo ctor = EnsureSectionGroupFactory(factoryRecord);
+
+ try
+ {
+ configSectionGroup =
+ (ConfigurationSectionGroup)ctor.Invoke(null);
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_exception_creating_section_handler, factoryRecord.ConfigKey),
+ e, factoryRecord);
+ }
+ }
+
+ configSectionGroup.AttachToConfigurationRecord(this, factoryRecord);
+
+ // Add it to the collection
+ SectionGroups[configKey] = configSectionGroup;
+
+ return configSectionGroup;
+ }
+
+ // Create a collection of all location tags encountered in the file.
+ internal ConfigurationLocationCollection GetLocationCollection(Configuration config)
+ {
+ ArrayList locations = new ArrayList();
+
+ // Now add the other empty location sections we recorded
+ if (_locationTags != null)
+ {
+ foreach (string subPath in _locationTags.Values)
+ locations.Add(new ConfigurationLocation(config, subPath));
+ }
+
+ return new ConfigurationLocationCollection(locations);
+ }
+
+ // Record all location tags in the config file, even if they are empty.
+ protected override void AddLocation(string locationSubPath)
+ {
+ if (_locationTags == null) _locationTags = new Hashtable(StringComparer.OrdinalIgnoreCase);
+
+ _locationTags[locationSubPath] = locationSubPath;
+ }
+
+ // Get all the factories available, both in this file and inherited.
+ private Hashtable GetAllFactories(bool isGroup)
+ {
+ Hashtable factories = new Hashtable();
+
+ MgmtConfigurationRecord configRecord = this;
+ do
+ {
+ if (configRecord._factoryRecords != null)
+ {
+ foreach (FactoryRecord factoryRecord in configRecord._factoryRecords.Values)
+ if (factoryRecord.IsGroup == isGroup)
+ {
+ string configKey = factoryRecord.ConfigKey;
+ factories[configKey] = new FactoryId(factoryRecord.ConfigKey, factoryRecord.Group,
+ factoryRecord.Name);
+ }
+ }
+
+ configRecord = configRecord.MgmtParent;
+ } while (!configRecord.IsRootConfig);
+
+ return factories;
+ }
+
+ internal ConfigurationSection FindImmediateParentSection(ConfigurationSection section)
+ {
+ ConfigurationSection result = null;
+
+ string configKey = section.SectionInformation.SectionName;
+ SectionRecord sectionRecord = GetSectionRecord(configKey, false);
+ if (sectionRecord.HasLocationInputs)
+ {
+ SectionInput input = sectionRecord.LastLocationInput;
+ Debug.Assert(input.HasResult, "input.HasResult");
+ result = (ConfigurationSection)input.Result;
+ }
+ else
+ {
+ if (sectionRecord.HasIndirectLocationInputs)
+ {
+ Debug.Assert(IsLocationConfig, "Indirect location inputs exist only in location config record");
+ SectionInput input = sectionRecord.LastIndirectLocationInput;
+ Debug.Assert(input != null);
+ Debug.Assert(input.HasResult, "input.HasResult");
+ result = (ConfigurationSection)input.Result;
+ }
+ else
+ {
+ if (IsRootDeclaration(configKey, true))
+ {
+ FactoryRecord factoryRecord = GetFactoryRecord(configKey, false);
+
+ object resultObject;
+ object resultRuntimeObject;
+ CreateSectionDefault(configKey, false, factoryRecord, null, out resultObject,
+ out resultRuntimeObject);
+ result = (ConfigurationSection)resultObject;
+ }
+ else
+ {
+ MgmtConfigurationRecord current = MgmtParent;
+ while (!current.IsRootConfig)
+ {
+ sectionRecord = current.GetSectionRecord(configKey, false);
+ if ((sectionRecord != null) && sectionRecord.HasResult)
+ {
+ result = (ConfigurationSection)sectionRecord.Result;
+ break;
+ }
+
+ current = current.MgmtParent;
+ }
+
+ Debug.Assert(!current.IsRootConfig, "An immediate parent result should have been found");
+ }
+ }
+ }
+
+ if (!result.IsReadOnly()) result.SetReadOnly();
+
+ return result;
+ }
+
+ internal ConfigurationSection FindAndCloneImmediateParentSection(ConfigurationSection configSection)
+ {
+ string configKey = configSection.SectionInformation.ConfigKey;
+ ConfigurationSection parentSection = FindImmediateParentSection(configSection);
+ SectionRecord sectionRecord = GetSectionRecord(configKey, false);
+ ConfigurationSection clone = (ConfigurationSection)UseParentResult(configKey, parentSection, sectionRecord);
+ return clone;
+ }
+
+ internal void RevertToParent(ConfigurationSection configSection)
+ {
+ // Remove any RawXml set by ConfigurationSection.SetRawXml
+ configSection.SectionInformation.RawXml = null;
+
+ try
+ {
+ // Reset to parent value
+ ConfigurationSection parentConfigSection = FindImmediateParentSection(configSection);
+ configSection.Reset(parentConfigSection);
+
+ // Consider it to be unmodified
+ configSection.ResetModified();
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_exception_in_config_section_handler,
+ configSection.SectionInformation.SectionName),
+ e, ConfigStreamInfo.StreamName, 0);
+ }
+
+ // Record that the section is to be removed.
+ configSection.SectionInformation.Removed = true;
+ }
+
+ // Return the outer XML of a section as a string.
+ // Return null if the section does not exist in the file.
+ internal string GetRawXml(string configKey)
+ {
+ // Get the section record created during Init
+ SectionRecord sectionRecord = GetSectionRecord(configKey, false);
+ if ((sectionRecord == null) || !sectionRecord.HasFileInput) return null;
+
+ // The section exists, so find and return its RawXml.
+ string[] keys = configKey.Split(s_configPathSeparatorParams);
+ ConfigXmlReader reader = GetSectionXmlReader(keys, sectionRecord.FileInput);
+
+ return reader.RawXml;
+ }
+
+ // Update the section with the XML provided.
+ //
+ // This method will throw out any changes made to the section up to this point.
+ //
+ // If xmlElement is null or empty, it is equivalent to calling RevertToParent
+ internal void SetRawXml(ConfigurationSection configSection, string xmlElement)
+ {
+ // Null or empty is equivalent to RevertToParent().
+ if (string.IsNullOrEmpty(xmlElement))
+ {
+ RevertToParent(configSection);
+ return;
+ }
+
+ ValidateSectionXml(xmlElement, configSection.SectionInformation.Name);
+
+ // Reset the ConfigurationSection with the XML.
+ ConfigurationSection parentConfigSection = FindImmediateParentSection(configSection);
+ ConfigXmlReader reader = new ConfigXmlReader(xmlElement, null, 0);
+
+ // Store the raw XML.
+ configSection.SectionInformation.RawXml = xmlElement;
+
+ // Update the section with the xml
+ try
+ {
+ try
+ {
+ bool wasPresent = configSection.ElementPresent;
+ PropertySourceInfo saveInfo = configSection.ElementInformation.PropertyInfoInternal();
+
+ configSection.Reset(parentConfigSection);
+ configSection.DeserializeSection(reader);
+ configSection.ResetModified();
+
+ configSection.ElementPresent = wasPresent;
+ configSection.ElementInformation.ChangeSourceAndLineNumber(saveInfo);
+ }
+ catch
+ {
+ configSection.SectionInformation.RawXml = null;
+ throw;
+ }
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_exception_in_config_section_handler,
+ configSection.SectionInformation.SectionName),
+ e, null, 0);
+ }
+
+ // Ignore previous attempts to remove the section.
+ configSection.SectionInformation.Removed = false;
+ }
+
+ // Return true if a stream is being used by a configSource directive in other input.
+ private bool IsStreamUsed(string oldStreamName)
+ {
+ MgmtConfigurationRecord current = this;
+ if (IsLocationConfig)
+ {
+ // For a location configuration, the input we need to check
+ // are the section records and location sections in the file,
+ // which are available in the parent record.
+ current = MgmtParent;
+
+ // Check whether a file section is using the configsource directive.
+ if (current._sectionRecords != null)
+ {
+ foreach (SectionRecord sectionRecord in current._sectionRecords.Values)
+ if (sectionRecord.HasFileInput &&
+ StringUtil.EqualsIgnoreCase(sectionRecord.FileInput.SectionXmlInfo.ConfigSourceStreamName,
+ oldStreamName))
+ return true;
+ }
+ }
+
+ // Check whether a location is using the configsource directive.
+ if (current._locationSections == null) return false;
+
+ foreach (LocationSectionRecord locationSectionRecord in current._locationSections)
+ if (StringUtil.EqualsIgnoreCase(locationSectionRecord.SectionXmlInfo.ConfigSourceStreamName,
+ oldStreamName))
+ return true;
+
+ return false;
+ }
+
+ // Set the configSource attribute on a ConfigurationSection
+ internal void ChangeConfigSource(
+ SectionInformation sectionInformation,
+ string oldConfigSource,
+ string oldConfigSourceStreamName,
+ string newConfigSource)
+ {
+ if (string.IsNullOrEmpty(oldConfigSource)) oldConfigSource = null;
+
+ if (string.IsNullOrEmpty(newConfigSource)) newConfigSource = null;
+
+ // Check if there is a change to config source
+ if (StringUtil.EqualsIgnoreCase(oldConfigSource, newConfigSource))
+ return;
+
+ if (string.IsNullOrEmpty(ConfigStreamInfo.StreamName))
+ throw new ConfigurationErrorsException(SR.Config_source_requires_file);
+
+ string newConfigSourceStreamName = null;
+ if (newConfigSource != null)
+ {
+ newConfigSourceStreamName = Host.GetStreamNameForConfigSource(ConfigStreamInfo.StreamName,
+ newConfigSource);
+ }
+
+ // Add the stream to the updates
+ if (newConfigSourceStreamName != null)
+ {
+ // Ensure that no parent is using the same config source stream
+ ValidateUniqueChildConfigSource(sectionInformation.ConfigKey, newConfigSourceStreamName, newConfigSource,
+ null);
+
+ StreamInfo streamInfo = (StreamInfo)_streamInfoUpdates[newConfigSourceStreamName];
+ if (streamInfo != null)
+ {
+ // Detect if another section in this file is using the same configSource
+ // with has a different section name.
+ if (streamInfo.SectionName != sectionInformation.ConfigKey)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_source_cannot_be_shared, newConfigSource));
+ }
+ }
+ else
+ {
+ // Add stream to updates
+ streamInfo = new StreamInfo(sectionInformation.ConfigKey, newConfigSource, newConfigSourceStreamName);
+ _streamInfoUpdates.Add(newConfigSourceStreamName, streamInfo);
+ }
+ }
+
+ // remove old streamname if no longer referenced
+ if ((oldConfigSourceStreamName != null) && !IsStreamUsed(oldConfigSourceStreamName))
+ _streamInfoUpdates.Remove(oldConfigSourceStreamName);
+
+ // update the configSourceStreamName
+ sectionInformation.ConfigSourceStreamName = newConfigSourceStreamName;
+ }
+
+ // Verify that the string is valid xml, begins with the expected section name,
+ // and contains no more or less than a single element.
+ //
+ // Throws a ConfigurationErrorsException if there is an error.
+ private void ValidateSectionXml(string xmlElement, string configKey)
+ {
+ if (string.IsNullOrEmpty(xmlElement))
+ return;
+
+ XmlTextReader reader = null;
+ try
+ {
+ XmlParserContext context = new XmlParserContext(null, null, null, XmlSpace.Default, Encoding.Unicode);
+ reader = new XmlTextReader(xmlElement, XmlNodeType.Element, context);
+
+ // Verify that the it is an element
+ reader.Read();
+ if (reader.NodeType != XmlNodeType.Element)
+ throw new ConfigurationErrorsException(string.Format(SR.Config_unexpected_node_type, reader.NodeType));
+
+ // Verify the name of the element is a section
+ string group, name;
+ SplitConfigKey(configKey, out group, out name);
+ if (reader.Name != name)
+ throw new ConfigurationErrorsException(string.Format(SR.Config_unexpected_element_name, reader.Name));
+
+ for (;;)
+ {
+ if (!reader.Read())
+ {
+ // ensure there is a matching end element
+ if (reader.Depth != 0)
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_unexpected_element_end),
+ reader);
+ }
+
+ break;
+ }
+
+ switch (reader.NodeType)
+ {
+ // disallowed node types within a section
+ case XmlNodeType.XmlDeclaration:
+ case XmlNodeType.DocumentType:
+ throw new ConfigurationErrorsException(SR.Config_invalid_node_type, reader);
+ }
+
+
+ // don't allow XML after the end element
+ if ((reader.Depth <= 0) && (reader.NodeType != XmlNodeType.EndElement))
+ throw new ConfigurationErrorsException(SR.Config_more_data_than_expected, reader);
+ }
+ }
+ finally
+ {
+ reader?.Close();
+ }
+ }
+
+ // Add a new configuration section to this config file.
+ // This adds both the section declaration and definition to the config file.
+ //
+ // Called from ConfigurationSectionCollection.Add().
+ // Note this method DOES NOT update the associated ConfigurationSectionCollection.
+ internal void AddConfigurationSection(string group, string name, ConfigurationSection configSection)
+ {
+ // <configSections> is not permitted within a <location> tag.
+ if (IsLocationConfig)
+ throw new InvalidOperationException(SR.Config_add_configurationsection_in_location_config);
+
+ VerifySectionName(name, null, false);
+
+ if (configSection == null) throw new ArgumentNullException(nameof(configSection));
+
+ // Ensure the section is not already part of the configuration hierarchy.
+ if (configSection.SectionInformation.Attached)
+ throw new InvalidOperationException(SR.Config_add_configurationsection_already_added);
+
+ string configKey = CombineConfigKey(group, name);
+
+ // Ensure the section is not already declared.
+ FactoryRecord factoryRecord = FindFactoryRecord(configKey, true);
+ if (factoryRecord != null)
+ throw new ArgumentException(SR.Config_add_configurationsection_already_exists);
+
+ // Add the configSource if needed.
+ if (!string.IsNullOrEmpty(configSection.SectionInformation.ConfigSource))
+ {
+ ChangeConfigSource(configSection.SectionInformation, null, null,
+ configSection.SectionInformation.ConfigSource);
+ }
+
+ // Add to list of all sections.
+ _sectionFactories?.Add(configKey, new FactoryId(configKey, group, name));
+
+ // Get the type name.
+ string typeName = configSection.SectionInformation.Type ?? Host.GetConfigTypeName(configSection.GetType());
+
+ // Add a factory record for the section.
+ factoryRecord = new FactoryRecord(configKey,
+ group,
+ name,
+ typeName,
+ configSection.SectionInformation.AllowLocation,
+ configSection.SectionInformation.AllowDefinition,
+ configSection.SectionInformation.AllowExeDefinition,
+ configSection.SectionInformation.OverrideModeDefaultSetting,
+ configSection.SectionInformation.RestartOnExternalChanges,
+ configSection.SectionInformation.RequirePermission,
+ _flags[IsTrusted],
+ false,
+ ConfigStreamInfo.StreamName,
+ -1)
+ {
+ Factory = TypeUtil.GetConstructor(
+ configSection.GetType(), typeof(ConfigurationSection), true),
+ };
+
+ // Construct a factory for the section
+ EnsureFactories()[configKey] = factoryRecord;
+
+ // Add a section record for the section.
+ // Since we are adding a new definition, it cannot be locked.
+ SectionRecord sectionRecord = EnsureSectionRecordUnsafe(configKey, false);
+ sectionRecord.Result = configSection;
+ sectionRecord.ResultRuntimeObject = configSection;
+
+ // Undo any previous removals of the section.
+ _removedSections?.Remove(configKey);
+
+ // Attach the section to the configuration record.
+ configSection.SectionInformation.AttachToConfigurationRecord(this, factoryRecord, sectionRecord);
+
+ // If there is rawXml, set it now. Note this will override any other changes to the section
+ // definition made after the call to SetXml.
+ string rawXml = configSection.SectionInformation.RawXml;
+ if (!string.IsNullOrEmpty(rawXml))
+ {
+ configSection.SectionInformation.RawXml = null;
+ configSection.SectionInformation.SetRawXml(rawXml);
+ }
+ }
+
+ // Remove a configuration section from this config file.
+ // This removes both the section declaration and definition from the config file.
+ // Note, however, that if a parent config file declares the section,
+ // a new instance of the section can be retrieved having the value of the
+ // immediate parent.
+ //
+ // Called from ConfigurationSectionCollection.Remove().
+ // Note this method DOES NOT update the associated ConfigurationSectionCollection.
+ internal void RemoveConfigurationSection(string group, string name)
+ {
+ bool sectionIsUsed = false; // Is section used in our record
+
+ VerifySectionName(name, null, true);
+
+ string configKey = CombineConfigKey(group, name);
+
+ // If it's already removed, don't try to remove it again.
+ if (RemovedSections.Contains(configKey)) return;
+
+ // If it's not a registered section, there's nothing to do.
+ if (FindFactoryRecord(configKey, true) == null) return;
+
+ // Detach from this record
+ ConfigurationSection configSection = GetConfigSection(configKey);
+ configSection?.SectionInformation.DetachFromConfigurationRecord();
+
+ // Remove from list of all sections if this is the root declaration.
+ bool isRootDeclaration = IsRootDeclaration(configKey, false);
+ if ((_sectionFactories != null) && isRootDeclaration) _sectionFactories.Remove(configKey);
+
+ // Remove from collection of factory records.
+ if (!IsLocationConfig && (_factoryRecords != null) && _factoryRecords.Contains(configKey))
+ {
+ sectionIsUsed = true;
+ _factoryRecords.Remove(configKey);
+ }
+
+ // Remove from collection of section records.
+ if ((_sectionRecords != null) && _sectionRecords.Contains(configKey))
+ {
+ sectionIsUsed = true;
+ _sectionRecords.Remove(configKey);
+ }
+
+ // Remove all location section records for this section in this file.
+ if (_locationSections != null)
+ {
+ int i = 0;
+ while (i < _locationSections.Count)
+ {
+ LocationSectionRecord locationSectionRecord = (LocationSectionRecord)_locationSections[i];
+ if (locationSectionRecord.ConfigKey != configKey) i++;
+ else
+ {
+ sectionIsUsed = true;
+ _locationSections.RemoveAt(i);
+ }
+ }
+ }
+
+ if (sectionIsUsed)
+ {
+ // Add to RemovedSections since we need to remove
+ // it from the file later.
+ RemovedSections.Add(configKey, configKey);
+ }
+
+ // Remove all references from configSource
+ // Note that we can't remove an item while enumerating it.
+ List<string> streamsToRemove = new List<string>();
+ foreach (StreamInfo streamInfo in _streamInfoUpdates.Values)
+ if (streamInfo.SectionName == configKey) streamsToRemove.Add(streamInfo.StreamName);
+
+ foreach (string stream in streamsToRemove) _streamInfoUpdates.Remove(stream);
+ }
+
+ // Add a new configuration section group to this config file.
+ //
+ // Called from ConfigurationSectionGroupCollection.Add().
+ // Note this method DOES NOT update the associated ConfigurationSectionGroupCollection.
+ internal void AddConfigurationSectionGroup(string group, string name,
+ ConfigurationSectionGroup configSectionGroup)
+ {
+ // <location> tags can't have a <configSections> declaration.
+ if (IsLocationConfig)
+ throw new InvalidOperationException(SR.Config_add_configurationsectiongroup_in_location_config);
+
+ // Validate name argument.
+ VerifySectionName(name, null, false);
+
+ // Validate configSectionGroup argument.
+ if (configSectionGroup == null) throw ExceptionUtil.ParameterInvalid("name");
+
+ // A section group can only belong to one section group collection.
+ if (configSectionGroup.Attached)
+ throw new InvalidOperationException(SR.Config_add_configurationsectiongroup_already_added);
+ string configKey = CombineConfigKey(group, name);
+
+ // Do not add if the section group already exists, even if it is of a different type.
+ FactoryRecord factoryRecord = FindFactoryRecord(configKey, true);
+ if (factoryRecord != null)
+ throw new ArgumentException(SR.Config_add_configurationsectiongroup_already_exists);
+
+ // Add to list of all section groups.
+ _sectionGroupFactories?.Add(configKey, new FactoryId(configKey, group, name));
+
+ // Get the type name - if it is not specified explicitly, get it from the type of the object.
+ string typeName = configSectionGroup.Type ?? Host.GetConfigTypeName(configSectionGroup.GetType());
+
+ // Create a factory record and add it to the collection of factory records.
+ factoryRecord = new FactoryRecord(configKey, group, name, typeName, ConfigStreamInfo.StreamName, -1);
+ EnsureFactories()[configKey] = factoryRecord;
+
+ // Add it to list of evaluated configuration section groups.
+ SectionGroups[configKey] = configSectionGroup;
+
+ // Remove it from RemovedSectionGroups if it was previously removed.
+ _removedSectionGroups?.Remove(configKey);
+
+ // Attach to the configuration record.
+ configSectionGroup.AttachToConfigurationRecord(this, factoryRecord);
+ }
+
+ // Return a list of all FactoryRecords of sections that are descendents of
+ // a section group.
+ private ArrayList GetDescendentSectionFactories(string configKey)
+ {
+ ArrayList sectionGroups = new ArrayList();
+
+ string configKeyAncestor;
+ if (configKey.Length == 0) configKeyAncestor = string.Empty;
+ else configKeyAncestor = configKey + "/";
+
+ foreach (FactoryId factoryId in SectionFactories.Values)
+ if ((factoryId.Group == configKey) || StringUtil.StartsWithOrdinal(factoryId.Group, configKeyAncestor))
+ sectionGroups.Add(factoryId);
+
+ return sectionGroups;
+ }
+
+ // Return a list of all FactoryRecords of section groups that are descendents of
+ // a section group, including the section group itself.
+ private ArrayList GetDescendentSectionGroupFactories(string configKey)
+ {
+ ArrayList sectionGroups = new ArrayList();
+
+ string configKeyAncestor;
+ if (configKey.Length == 0) configKeyAncestor = string.Empty;
+ else configKeyAncestor = configKey + "/";
+
+ foreach (FactoryId factoryId in SectionGroupFactories.Values)
+ if ((factoryId.ConfigKey == configKey) ||
+ StringUtil.StartsWithOrdinal(factoryId.ConfigKey, configKeyAncestor))
+ sectionGroups.Add(factoryId);
+
+ return sectionGroups;
+ }
+
+ // Remove a configuration section group from this config file.
+ // This removes both the section group declaration and definition from the config file,
+ // along with all descendent groups and sections.
+ //
+ // Note, however, that if a parent config file declares the section group,
+ // a new instance of the section can be retrieved having the value of the
+ // immediate parent.
+ //
+ // Called from ConfigurationSectionGroupCollection.Remove().
+ // Note this method DOES NOT update the associated ConfigurationSectionCollection.
+ internal void RemoveConfigurationSectionGroup(string group, string name)
+ {
+ // Validate arguments
+ VerifySectionName(name, null, false);
+
+ string configKey = CombineConfigKey(group, name);
+
+ // If it's not a registered section, there's nothing to do.
+ if (FindFactoryRecord(configKey, true) == null) return;
+
+ // Remove all descendent sections.
+ ArrayList sections = GetDescendentSectionFactories(configKey);
+ foreach (FactoryId descendent in sections) RemoveConfigurationSection(descendent.Group, descendent.Name);
+
+ // Remove all descendent sections groups, including the configKey group.
+ ArrayList sectionGroups = GetDescendentSectionGroupFactories(configKey);
+ foreach (FactoryId descendent in sectionGroups)
+ {
+ //
+ // If it's already removed, don't try to remove it again.
+ // We don't do this test above the loop for configKey, because
+ // the section groups contained within the section group may
+ // be changed by the user once added.
+ //
+ if (RemovedSectionGroups.Contains(descendent.ConfigKey)) continue;
+
+ // If the section group has been evaluated, detatch it.
+ ConfigurationSectionGroup sectionGroup = LookupSectionGroup(descendent.ConfigKey);
+ sectionGroup?.DetachFromConfigurationRecord();
+
+ // Remove from list of all section group factories if this is the root declaration.
+ bool isRootDeclaration = IsRootDeclaration(descendent.ConfigKey, false);
+ if ((_sectionGroupFactories != null) && isRootDeclaration)
+ _sectionGroupFactories.Remove(descendent.ConfigKey);
+
+ // Remove from list of factory records.
+ if (!IsLocationConfig) _factoryRecords?.Remove(descendent.ConfigKey);
+
+ // Remove from evaluated section groups.
+ _sectionGroups?.Remove(descendent.ConfigKey);
+
+ // Add to list of section groups that are removed
+ // Note that this will add section groups that might not be used
+ // in this config file. That just results in some extra work during
+ // save, it is not harmful.
+ RemovedSectionGroups.Add(descendent.ConfigKey, descendent.ConfigKey);
+ }
+ }
+
+ // Update the config file with the changes in each ConfigurationSection
+ internal void SaveAs(string filename, ConfigurationSaveMode saveMode, bool forceUpdateAll)
+ {
+ // Get the updates.
+ SectionUpdates declarationUpdates = GetConfigDeclarationUpdates(saveMode);
+
+ ConfigDefinitionUpdates definitionUpdates;
+ ArrayList configSourceUpdates;
+ bool checkedConfigForUpdates = false;
+ bool requireUpdates = filename != null;
+ GetConfigDefinitionUpdates(requireUpdates, saveMode, forceUpdateAll, out definitionUpdates,
+ out configSourceUpdates);
+
+ if (filename != null)
+ {
+ Debug.Assert(filename.Length > 0, "The caller should make sure that filename is not empty");
+
+ // Verify that the filename is not being used.
+ //
+ // Note that if we are using a remote host, all the streamName's in _streamInfoUpdates
+ // are actually fullpaths on the remote machine. In this case there is no way to
+ // detect if we have a conflict or not.
+ if (!Host.IsRemote && _streamInfoUpdates.Contains(filename))
+ throw new ArgumentException(string.Format(SR.Filename_in_SaveAs_is_used_already, filename));
+
+ // If there was no config file for this config record,
+ // record the new stream name and version.
+ if (string.IsNullOrEmpty(ConfigStreamInfo.StreamName))
+ {
+ StreamInfo streamInfo = new StreamInfo(null, null, filename);
+ _streamInfoUpdates.Add(filename, streamInfo);
+
+ ConfigStreamInfo.StreamName = filename;
+ ConfigStreamInfo.StreamVersion = MonitorStream(null, null, ConfigStreamInfo.StreamName);
+ }
+
+ // Update the host to redirect filenames
+ UpdateConfigHost.AddStreamname(ConfigStreamInfo.StreamName, filename, Host.IsRemote);
+
+ // Redirect also all configSource filenames
+ foreach (StreamInfo streamInfo in _streamInfoUpdates.Values)
+ if (!string.IsNullOrEmpty(streamInfo.SectionName))
+ {
+ // Get the new configSource streamName based on the new filename path
+ string newStreamName = InternalConfigHost.StaticGetStreamNameForConfigSource(
+ filename, streamInfo.ConfigSource);
+
+ // Ask UpdateConfigHost to intercept them.
+ UpdateConfigHost.AddStreamname(streamInfo.StreamName, newStreamName, Host.IsRemote);
+ }
+ }
+
+ if (!requireUpdates)
+ {
+ // Check if there are any updates needed for the
+ // configuration record itself.
+ requireUpdates = RecordItselfRequiresUpdates;
+ }
+
+ if ((declarationUpdates != null) || (definitionUpdates != null) || requireUpdates)
+ {
+ // Copy the input stream before opening the output stream.
+ byte[] readBuffer = null;
+ Encoding encoding = null;
+ if (ConfigStreamInfo.HasStream)
+ {
+ using (Stream streamRead = Host.OpenStreamForRead(ConfigStreamInfo.StreamName))
+ {
+ if (streamRead == null)
+ {
+ throw new ConfigurationErrorsException(SR.Config_file_has_changed,
+ ConfigStreamInfo.StreamName, 0);
+ }
+
+ readBuffer = new byte[streamRead.Length];
+ int count = streamRead.Read(readBuffer, 0, (int)streamRead.Length);
+ if (count != streamRead.Length)
+ throw new ConfigurationErrorsException(SR.Config_data_read_count_mismatch);
+ }
+
+ // Read the first byte so that we can determine the encoding.
+ try
+ {
+ using (StreamReader reader = new StreamReader(ConfigStreamInfo.StreamName))
+ {
+ if (reader.Peek() >= 0) reader.Read();
+
+ // Handle only UTF-16 explicitly, so that handling of other encodings are not affected.
+ if (reader.CurrentEncoding is UnicodeEncoding) encoding = reader.CurrentEncoding;
+ }
+ }
+ catch
+ {
+ // Ignore any errors, encoding will remain null.
+ }
+ }
+
+ string changedStreamName = FindChangedConfigurationStream();
+ if (changedStreamName != null)
+ throw new ConfigurationErrorsException(SR.Config_file_has_changed, changedStreamName, 0);
+
+ checkedConfigForUpdates = true;
+
+ // Write the changes to the output stream.
+ object writeContext = null;
+ bool streamOpened = false;
+ try
+ {
+ try
+ {
+ using (Stream streamWrite = Host.OpenStreamForWrite(ConfigStreamInfo.StreamName, null,
+ ref writeContext))
+ {
+ streamOpened = true;
+ // Use the default StreamWriter constructor if encoding is null,
+ // otherwise specify the encoding.
+ using (
+ StreamWriter streamWriter = encoding == null
+ ? new StreamWriter(streamWrite)
+ : new StreamWriter(streamWrite, encoding))
+ {
+ XmlUtilWriter utilWriter = new XmlUtilWriter(streamWriter, true);
+ if (ConfigStreamInfo.HasStream)
+ {
+ CopyConfig(declarationUpdates, definitionUpdates, readBuffer,
+ ConfigStreamInfo.StreamName, NamespaceChangeNeeded, utilWriter);
+ }
+ else
+ {
+ CreateNewConfig(declarationUpdates, definitionUpdates, NamespaceChangeNeeded,
+ utilWriter);
+ }
+ }
+ }
+ }
+ catch
+ {
+ if (streamOpened) Host.WriteCompleted(ConfigStreamInfo.StreamName, false, writeContext);
+
+ throw;
+ }
+ }
+ catch (Exception e)
+ {
+ // Guarantee that exceptions contain at least the name of the stream by wrapping them
+ // in a ConfigurationException.
+ throw ExceptionUtil.WrapAsConfigException(SR.Config_error_loading_XML_file, e,
+ ConfigStreamInfo.StreamName, 0);
+ }
+
+ Host.WriteCompleted(ConfigStreamInfo.StreamName, true, writeContext);
+
+ // Update stream information for the config file
+ ConfigStreamInfo.HasStream = true;
+ ConfigStreamInfo.ClearStreamInfos();
+ ConfigStreamInfo.StreamVersion = MonitorStream(null, null, ConfigStreamInfo.StreamName);
+ }
+
+ if (configSourceUpdates != null)
+ {
+ // If we haven't checked before, check now
+ if (!checkedConfigForUpdates)
+ {
+ string changedStreamName = FindChangedConfigurationStream();
+ if (changedStreamName != null)
+ {
+ throw new ConfigurationErrorsException(SR.Config_file_has_changed,
+ changedStreamName, 0);
+ }
+ }
+
+ // write updates
+ foreach (DefinitionUpdate update in configSourceUpdates) SaveConfigSource(update);
+ }
+
+ // Update state to reflect the changes to the config file
+ UpdateRecords();
+ }
+
+ private static bool AreDeclarationAttributesModified(FactoryRecord factoryRecord,
+ ConfigurationSection configSection)
+ {
+ return (factoryRecord.FactoryTypeName != configSection.SectionInformation.Type)
+ || (factoryRecord.AllowLocation != configSection.SectionInformation.AllowLocation)
+ || (factoryRecord.RestartOnExternalChanges != configSection.SectionInformation.RestartOnExternalChanges)
+ || (factoryRecord.RequirePermission != configSection.SectionInformation.RequirePermission)
+ || (factoryRecord.AllowDefinition != configSection.SectionInformation.AllowDefinition)
+ || (factoryRecord.AllowExeDefinition != configSection.SectionInformation.AllowExeDefinition)
+ ||
+ (factoryRecord.OverrideModeDefault.OverrideMode !=
+ configSection.SectionInformation.OverrideModeDefaultSetting.OverrideMode) // Compare the value only
+ || configSection.SectionInformation.IsModifiedFlags();
+ }
+
+ private static void AppendAttribute(StringBuilder sb, string key, string value)
+ {
+ sb.Append(key);
+ sb.Append("=\"");
+ sb.Append(value);
+ sb.Append("\" ");
+ }
+
+ private string GetUpdatedSectionDeclarationXml(FactoryRecord factoryRecord, ConfigurationSection configSection,
+ ConfigurationSaveMode saveMode)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append('<');
+ sb.Append(SectionTag);
+ sb.Append(' ');
+ string type = configSection.SectionInformation.Type ?? factoryRecord.FactoryTypeName;
+ if (TypeStringTransformerIsSet)
+ type = TypeStringTransformer(type);
+
+ AppendAttribute(sb, SectionNameAttribute, configSection.SectionInformation.Name);
+ AppendAttribute(sb, SectionTypeAttribute, type);
+
+ if (!configSection.SectionInformation.AllowLocation ||
+ (saveMode == ConfigurationSaveMode.Full) ||
+ ((saveMode == ConfigurationSaveMode.Modified) &&
+ configSection.SectionInformation.AllowLocationModified))
+ {
+ AppendAttribute(sb,
+ SectionAllowLocationAttribute,
+ configSection.SectionInformation.AllowLocation
+ ? KeywordTrue
+ : KeywordFalse);
+ }
+
+ if ((configSection.SectionInformation.AllowDefinition != ConfigurationAllowDefinition.Everywhere) ||
+ (saveMode == ConfigurationSaveMode.Full) ||
+ ((saveMode == ConfigurationSaveMode.Modified) &&
+ configSection.SectionInformation.AllowDefinitionModified))
+ {
+ string v = null;
+ switch (configSection.SectionInformation.AllowDefinition)
+ {
+ case ConfigurationAllowDefinition.Everywhere:
+ v = AllowDefinitionEverywhere;
+ break;
+ case ConfigurationAllowDefinition.MachineOnly:
+ v = AllowDefinitionMachineOnly;
+ break;
+ case ConfigurationAllowDefinition.MachineToWebRoot:
+ v = AllowDefinitionMachineToWebRoot;
+ break;
+ case ConfigurationAllowDefinition.MachineToApplication:
+ v = AllowDefinitionMachineToApplication;
+ break;
+ }
+
+ AppendAttribute(sb, SectionAllowDefinitionAttribute, v);
+ }
+
+ if ((configSection.SectionInformation.AllowExeDefinition !=
+ ConfigurationAllowExeDefinition.MachineToApplication) ||
+ (saveMode == ConfigurationSaveMode.Full) ||
+ ((saveMode == ConfigurationSaveMode.Modified) &&
+ configSection.SectionInformation.AllowExeDefinitionModified))
+ {
+ AppendAttribute(sb,
+ SectionAllowExeDefinitionAttribute,
+ ExeDefinitionToString(
+ configSection.SectionInformation.AllowExeDefinition)
+ );
+ }
+
+ if ((configSection.SectionInformation.OverrideModeDefaultSetting.IsDefaultForSection == false) ||
+ (saveMode == ConfigurationSaveMode.Full) ||
+ ((saveMode == ConfigurationSaveMode.Modified) &&
+ configSection.SectionInformation.OverrideModeDefaultModified))
+ {
+ AppendAttribute(sb,
+ SectionOverrideModeDefaultAttribute,
+ configSection.SectionInformation.OverrideModeDefaultSetting.OverrideModeXmlValue);
+ }
+
+ if (!configSection.SectionInformation.RestartOnExternalChanges)
+ AppendAttribute(sb, SectionRestartonExternalChangesAttribute, KeywordFalse);
+ else
+ {
+ if ((saveMode == ConfigurationSaveMode.Full) ||
+ ((saveMode == ConfigurationSaveMode.Modified) &&
+ configSection.SectionInformation.RestartOnExternalChangesModified))
+ AppendAttribute(sb, SectionRestartonExternalChangesAttribute, KeywordTrue);
+ }
+
+ if (!configSection.SectionInformation.RequirePermission)
+ {
+ AppendAttribute(sb, SectionRequirePermissionAttribute, KeywordFalse);
+ }
+ else
+ {
+ if ((saveMode == ConfigurationSaveMode.Full) ||
+ ((saveMode == ConfigurationSaveMode.Modified) &&
+ configSection.SectionInformation.RequirePermissionModified))
+ AppendAttribute(sb, SectionRequirePermissionAttribute, KeywordTrue);
+ }
+
+ sb.Append("/>");
+
+ return sb.ToString();
+ }
+
+ // ExeDefinitionToString
+ //
+ // Take an ExeDefinition and translate it to a string
+ //
+ private string ExeDefinitionToString(
+ ConfigurationAllowExeDefinition allowDefinition)
+ {
+ switch (allowDefinition)
+ {
+ case ConfigurationAllowExeDefinition.MachineOnly:
+ return AllowDefinitionMachineOnly;
+
+ case ConfigurationAllowExeDefinition.MachineToApplication:
+ return AllowDefinitionMachineToApplication;
+
+ case ConfigurationAllowExeDefinition.MachineToRoamingUser:
+ return AllowExeDefinitionMachineToRoaming;
+
+ case ConfigurationAllowExeDefinition.MachineToLocalUser:
+ return AllowExeDefinitionMachineToLocal;
+ }
+
+ throw ExceptionUtil.PropertyInvalid("AllowExeDefinition");
+ }
+
+ private string GetUpdatedSectionGroupDeclarationXml(FactoryRecord factoryRecord,
+ ConfigurationSectionGroup configSectionGroup)
+ {
+ if ((TargetFramework != null) &&
+ !configSectionGroup.ShouldSerializeSectionGroupInTargetVersion(TargetFramework))
+ return null;
+
+ StringBuilder sb = new StringBuilder();
+ sb.Append('<');
+ sb.Append(SectionGroupTag);
+ sb.Append(' ');
+ AppendAttribute(sb, SectionGroupNameAttribute, configSectionGroup.Name);
+ string type = configSectionGroup.Type ?? factoryRecord.FactoryTypeName;
+ if (TypeStringTransformerIsSet)
+ type = TypeStringTransformer(type);
+
+ AppendAttribute(sb, SectionGroupTypeAttribute, type);
+
+ sb.Append('>');
+
+ return sb.ToString();
+ }
+
+ // Gather all the updates to the configuration section declarations.
+ private SectionUpdates GetConfigDeclarationUpdates(ConfigurationSaveMode saveMode)
+ {
+ if (IsLocationConfig)
+ return null;
+
+ // hasChanged will be set to true if there is any change that will impact the current config file.
+ bool hasChanged = HasRemovedSectionsOrGroups;
+ SectionUpdates sectionUpdates = new SectionUpdates(string.Empty);
+
+ if (_factoryRecords != null)
+ {
+ foreach (FactoryRecord factoryRecord in _factoryRecords.Values)
+ if (!factoryRecord.IsGroup)
+ {
+ string updatedXml = null;
+
+ // Never write out an undeclared section.
+ if (factoryRecord.IsUndeclared) continue;
+
+ // Note that GetConfigSection will return only those sections that have a sectionRecord
+ // and has a result. In another word, only sections that have been accessed.
+ ConfigurationSection configSection = GetConfigSection(factoryRecord.ConfigKey);
+
+ if (configSection != null)
+ {
+ // We should skip this section declaration only if all below hold true:
+ // 1. The section should not be declared at this level. Reasons:
+ // i. The section is originally not declared at this level, or
+ // ii. The user calls SectionInformation.ForceDeclaration(false)
+ // 2. It's not machine.config. Otherwise we must declare it even if the user called ForceDeclaration(false)
+ // 3. It's already declared higher up.
+ // 4. It's not valid in the current Target Framework version
+ if (!configSection.SectionInformation.IsDeclared
+ && !MgmtParent.IsRootConfig
+ && (MgmtParent.FindFactoryRecord(factoryRecord.ConfigKey, false) != null))
+ {
+ if (factoryRecord.HasFile) hasChanged = true;
+
+ continue;
+ }
+ if ((TargetFramework != null) &&
+ !configSection.ShouldSerializeSectionInTargetVersion(TargetFramework))
+ continue;
+
+ if (AreDeclarationAttributesModified(factoryRecord, configSection) || !factoryRecord.HasFile)
+ {
+ updatedXml = GetUpdatedSectionDeclarationXml(factoryRecord, configSection, saveMode);
+ if (!string.IsNullOrEmpty(updatedXml))
+ hasChanged = true;
+ }
+ }
+
+ DeclarationUpdate update = new DeclarationUpdate(factoryRecord.ConfigKey, !factoryRecord.HasFile,
+ updatedXml);
+ sectionUpdates.AddSection(update);
+ }
+ else
+ {
+ bool addGroupUpdate = false;
+
+ // LookupSectionGroup will return an object only if the group has been accessed
+ ConfigurationSectionGroup configSectionGroup = LookupSectionGroup(factoryRecord.ConfigKey);
+
+ if (!factoryRecord.HasFile)
+ {
+ // Not in the file, so it means the group is added programmatically.
+ addGroupUpdate = true;
+ }
+ else
+ {
+ if ((configSectionGroup != null) && configSectionGroup.IsDeclarationRequired)
+ {
+ // The section group is declared in this config file
+ addGroupUpdate = true;
+ }
+ else
+ {
+ if ((factoryRecord.FactoryTypeName != null) || (configSectionGroup != null))
+ {
+ FactoryRecord parentFactoryRecord = null;
+ if (!MgmtParent.IsRootConfig)
+ {
+ parentFactoryRecord = MgmtParent.FindFactoryRecord(factoryRecord.ConfigKey,
+ false);
+ }
+
+ // Add it if declaration is required. Please note this check is identical to the check
+ // for _declarationRequired in ConfigurationSectionGroup.AttachToConfigurationRecord.
+ addGroupUpdate = parentFactoryRecord?.FactoryTypeName == null;
+ }
+ }
+ }
+
+ if (addGroupUpdate)
+ {
+ string updatedXml = null;
+
+ if (!factoryRecord.HasFile
+ ||
+ ((configSectionGroup != null) &&
+ (configSectionGroup.Type != factoryRecord.FactoryTypeName)))
+ {
+ updatedXml = GetUpdatedSectionGroupDeclarationXml(factoryRecord, configSectionGroup);
+ if (!string.IsNullOrEmpty(updatedXml)) hasChanged = true;
+ }
+
+ Debug.Assert(!factoryRecord.IsUndeclared, "!factoryRecord.IsUndeclared");
+ Debug.Assert(!IsImplicitSection(factoryRecord.ConfigKey),
+ "We should never write out an implicit section");
+
+ DeclarationUpdate update = new DeclarationUpdate(factoryRecord.ConfigKey,
+ !factoryRecord.HasFile, updatedXml);
+ sectionUpdates.AddSectionGroup(update);
+ }
+ }
+ }
+
+ if (_sectionRecords != null)
+ {
+ foreach (SectionRecord sectionRecord in _sectionRecords.Values)
+ {
+ if ((GetFactoryRecord(sectionRecord.ConfigKey, false) != null) || !sectionRecord.HasResult)
+ {
+ // Skip because this factory is defined locally ( in
+ // which case we handled above), or it was not used
+ continue;
+ }
+
+ ConfigurationSection configSection = (ConfigurationSection)sectionRecord.Result;
+ FactoryRecord factoryRecord = MgmtParent.FindFactoryRecord(sectionRecord.ConfigKey, false);
+
+ // Add this section declaration if:
+ // 1. The section is not declared locally (otherwise it's handled above)
+ // 2. SectionInformation.IsDeclared is true (i.e. user called SectionInformation.ForceDeclaration(true))
+ if (configSection.SectionInformation.IsDeclared)
+ {
+ Debug.Assert(!IsImplicitSection(sectionRecord.ConfigKey),
+ "We should never write out an implicit section");
+ Debug.Assert(!factoryRecord.IsUndeclared, "!factoryRecord.IsUndeclared");
+ string updatedXml = GetUpdatedSectionDeclarationXml(factoryRecord, configSection, saveMode);
+ if (!string.IsNullOrEmpty(updatedXml))
+ {
+ hasChanged = true;
+ DeclarationUpdate update = new DeclarationUpdate(factoryRecord.ConfigKey, true, updatedXml);
+ sectionUpdates.AddSection(update);
+ }
+ }
+ }
+ }
+
+ if (_sectionGroups != null)
+ {
+ foreach (ConfigurationSectionGroup configSectionGroup in _sectionGroups.Values)
+ {
+ if (GetFactoryRecord(configSectionGroup.SectionGroupName, false) != null) continue;
+
+ FactoryRecord factoryRecord = MgmtParent.FindFactoryRecord(configSectionGroup.SectionGroupName,
+ false);
+ if (configSectionGroup.IsDeclared ||
+ ((factoryRecord != null) && (configSectionGroup.Type != factoryRecord.FactoryTypeName)))
+ {
+ string updatedXml = GetUpdatedSectionGroupDeclarationXml(factoryRecord, configSectionGroup);
+ if (!string.IsNullOrEmpty(updatedXml))
+ {
+ hasChanged = true;
+ DeclarationUpdate update = new DeclarationUpdate(factoryRecord.ConfigKey, true, updatedXml);
+ sectionUpdates.AddSectionGroup(update);
+ }
+ }
+ }
+ }
+
+ if (hasChanged) return sectionUpdates;
+ else return null;
+ }
+
+ private bool AreLocationAttributesModified(SectionRecord sectionRecord, ConfigurationSection configSection)
+ {
+ OverrideModeSetting overrideMode = OverrideModeSetting.s_locationDefault;
+ bool inheritInChildApplications = true;
+
+ if (sectionRecord.HasFileInput)
+ {
+ SectionXmlInfo sectionXmlInfo = sectionRecord.FileInput.SectionXmlInfo;
+ overrideMode = sectionXmlInfo.OverrideModeSetting;
+ inheritInChildApplications = !sectionXmlInfo.SkipInChildApps;
+ }
+
+ // We will use IsSameForLocation tag so that we flag modes that cant go into the same location tag
+ // as different. If we don't do that it will appear like the mode was not changed which will
+ // case conflict later when determining if the section is moved ( when writing the new config updates )
+
+ return
+ !OverrideModeSetting.CanUseSameLocationTag(overrideMode,
+ configSection.SectionInformation.OverrideModeSetting)
+ || (inheritInChildApplications != configSection.SectionInformation.InheritInChildApplications);
+ }
+
+ private bool AreSectionAttributesModified(SectionRecord sectionRecord, ConfigurationSection configSection)
+ {
+ string configSource;
+ string protectionProviderName;
+
+ if (sectionRecord.HasFileInput)
+ {
+ SectionXmlInfo sectionXmlInfo = sectionRecord.FileInput.SectionXmlInfo;
+ configSource = sectionXmlInfo.ConfigSource;
+ protectionProviderName = sectionXmlInfo.ProtectionProviderName;
+ }
+ else
+ {
+ configSource = null;
+ protectionProviderName = null;
+ }
+
+ return
+ !StringUtil.EqualsOrBothNullOrEmpty(configSource, configSection.SectionInformation.ConfigSource)
+ ||
+ !StringUtil.EqualsOrBothNullOrEmpty(protectionProviderName,
+ configSection.SectionInformation.ProtectionProviderName)
+ || AreLocationAttributesModified(sectionRecord, configSection);
+ }
+
+ private bool IsConfigSectionMoved(SectionRecord sectionRecord, ConfigurationSection configSection)
+ {
+ if (!sectionRecord.HasFileInput)
+ return true;
+
+ return AreLocationAttributesModified(sectionRecord, configSection);
+ }
+
+ // Gather all the updates to the configuration section definitions.
+ private void GetConfigDefinitionUpdates(
+ bool requireUpdates, ConfigurationSaveMode saveMode, bool forceSaveAll,
+ out ConfigDefinitionUpdates definitionUpdates, out ArrayList configSourceUpdates)
+ {
+ definitionUpdates = new ConfigDefinitionUpdates();
+ configSourceUpdates = null;
+ bool hasChanged = HasRemovedSections;
+
+ // Loop through all the section records.
+ if (_sectionRecords != null)
+ {
+ InitProtectedConfigurationSection();
+ // Make sure we have the initialized the protected config section, otherwise the foreach loop may blow up
+ foreach (DictionaryEntry de in _sectionRecords)
+ {
+ string configKey = (string)de.Key;
+ SectionRecord sectionRecord = (SectionRecord)de.Value;
+ sectionRecord.AddUpdate = false;
+ bool addUpdate = sectionRecord.HasFileInput;
+ // If true, add this section to definitionUpdates, and optinally to configSourceUpdates
+ OverrideModeSetting overrideMode = OverrideModeSetting.s_locationDefault;
+ bool inheritInChildApplications = true;
+ bool moved = false;
+ string updatedXml = null;
+ bool addToConfigSourceUpdates = false;
+ // If true, we have to update the external config file for this section
+
+ if (!sectionRecord.HasResult)
+ {
+ if (sectionRecord.HasFileInput)
+ {
+ SectionXmlInfo sectionXmlInfo = sectionRecord.FileInput.SectionXmlInfo;
+ overrideMode = sectionXmlInfo.OverrideModeSetting;
+ inheritInChildApplications = !sectionXmlInfo.SkipInChildApps;
+ addToConfigSourceUpdates = requireUpdates &&
+ !string.IsNullOrEmpty(sectionXmlInfo.ConfigSource);
+ }
+ }
+ else
+ {
+ ConfigurationSection configSection = (ConfigurationSection)sectionRecord.Result;
+
+ if ((TargetFramework != null) &&
+ !configSection.ShouldSerializeSectionInTargetVersion(TargetFramework))
+ continue;
+
+ overrideMode = configSection.SectionInformation.OverrideModeSetting;
+ inheritInChildApplications = configSection.SectionInformation.InheritInChildApplications;
+
+ // it is an error to require a location section when the type doesn't allow locations.
+ if (!configSection.SectionInformation.AllowLocation &&
+ (!overrideMode.IsDefaultForLocationTag || !inheritInChildApplications))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_inconsistent_location_attributes, configKey));
+ }
+
+ addToConfigSourceUpdates = requireUpdates &&
+ !string.IsNullOrEmpty(configSection.SectionInformation.ConfigSource);
+ try
+ {
+ bool isModified = configSection.SectionInformation.ForceSave ||
+ configSection.IsModified() ||
+ (forceSaveAll && !configSection.SectionInformation.IsLocked);
+
+ bool sectionAttributesModified = AreSectionAttributesModified(sectionRecord, configSection);
+ bool sectionContentModified = isModified ||
+ (configSection.SectionInformation.RawXml != null);
+
+ // Get the updated XML if the section has been modified.
+ if (sectionContentModified || sectionAttributesModified)
+ {
+ configSection.SectionInformation.VerifyIsEditable();
+ configSection.SectionInformation.Removed = false;
+ addUpdate = true;
+ moved = IsConfigSectionMoved(sectionRecord, configSection);
+
+ if (!addToConfigSourceUpdates)
+ {
+ addToConfigSourceUpdates =
+ !string.IsNullOrEmpty(configSection.SectionInformation.ConfigSource)
+ &&
+ (sectionContentModified || configSection.SectionInformation.ConfigSourceModified);
+ }
+
+ if (isModified ||
+ (configSection.SectionInformation.RawXml == null) ||
+ (saveMode == ConfigurationSaveMode.Full))
+ {
+ // Note: we won't use RawXml if saveMode == Full because Full means we want to
+ // write all properties, and RawXml may not have all properties.
+ ConfigurationSection parentConfigSection = FindImmediateParentSection(configSection);
+ updatedXml = configSection.SerializeSection(parentConfigSection,
+ configSection.SectionInformation.Name, saveMode);
+ ValidateSectionXml(updatedXml, configKey);
+ }
+ else updatedXml = configSection.SectionInformation.RawXml;
+
+ if (string.IsNullOrEmpty(updatedXml))
+ {
+ // We always need to emit a section, even if empty, when:
+ // * The section has configSoure
+ // * The section is in a location section that has non-default attributes
+ // * The section is encrypted.
+ if (!string.IsNullOrEmpty(configSection.SectionInformation.ConfigSource) ||
+ !configSection.SectionInformation.LocationAttributesAreDefault ||
+ (configSection.SectionInformation.ProtectionProvider != null))
+ updatedXml = WriteEmptyElement(configSection.SectionInformation.Name);
+ }
+
+ if (string.IsNullOrEmpty(updatedXml))
+ {
+ configSection.SectionInformation.Removed = true;
+ updatedXml = null;
+ addUpdate = false;
+ if (sectionRecord.HasFileInput)
+ {
+ hasChanged = true;
+
+ // When a section is to be removed, its corresponding file
+ // input should be cleared as well so this section will be indicated as "moved"
+ // next time something is added back to the section. Without marking it as "moved",
+ // adding new content to a removed section fails.
+ sectionRecord.RemoveFileInput();
+ }
+ }
+ else
+ {
+ // configSection.ElementPresent = true;
+ if (sectionAttributesModified || moved ||
+ string.IsNullOrEmpty(configSection.SectionInformation.ConfigSource))
+ hasChanged = true;
+
+ // Encrypt if required.
+ if (configSection.SectionInformation.ProtectionProvider != null)
+ {
+ ProtectedConfigurationSection protectedConfig =
+ GetSection(ReservedSectionProtectedConfiguration) as
+ ProtectedConfigurationSection;
+ try
+ {
+ string encryptedSection = Host.EncryptSection(updatedXml,
+ configSection.SectionInformation.ProtectionProvider, protectedConfig);
+
+ // VsWhidbey 495120: The config host is responsible for encrypting a section, but it is the job of
+ // System.Configuration to format an encrypted section during write (and to detect an encrypted section during read.)
+ updatedXml =
+ ProtectedConfigurationSection.FormatEncryptedSection(encryptedSection,
+ configSection.SectionInformation.Name,
+ configSection.SectionInformation.ProtectionProvider.Name);
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Encryption_failed,
+ configSection.SectionInformation.SectionName,
+ configSection.SectionInformation.ProtectionProvider.Name, e.Message),
+ e);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (configSection.SectionInformation.Removed)
+ {
+ addUpdate = false;
+ if (sectionRecord.HasFileInput) hasChanged = true;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_exception_in_config_section_handler,
+ configSection.SectionInformation.SectionName), e);
+ }
+ }
+
+ if (!addUpdate) continue;
+
+ // Make sure we are not addingh a definition of a locked section
+ if (GetSectionLockedMode(sectionRecord.ConfigKey) == OverrideMode.Deny)
+ throw new ConfigurationErrorsException(SR.Config_section_locked, (IConfigErrorInfo)null);
+
+ sectionRecord.AddUpdate = true;
+ DefinitionUpdate definitionUpdate = definitionUpdates.AddUpdate(overrideMode,
+ inheritInChildApplications, moved, updatedXml, sectionRecord);
+
+ if (addToConfigSourceUpdates)
+ {
+ if (configSourceUpdates == null) configSourceUpdates = new ArrayList();
+ configSourceUpdates.Add(definitionUpdate);
+ }
+ }
+ }
+
+ if (_flags[ForceLocationWritten])
+ {
+ // We must write the location tag
+ hasChanged = true;
+ definitionUpdates.RequireLocation = true;
+ }
+
+ if (_flags[SuggestLocationRemoval])
+ {
+ // We should try to remove location
+ hasChanged = true;
+ }
+
+ if (hasChanged) definitionUpdates.CompleteUpdates();
+ else definitionUpdates = null;
+ }
+
+ // Take a element name, and create an xml string that contains
+ // that element in an empty state
+ private string WriteEmptyElement(string elementName)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ // Create element
+ sb.Append('<');
+ sb.Append(elementName);
+ sb.Append(" />");
+
+ return sb.ToString();
+ }
+
+ // After the config file has been written out, update the section records
+ // to reflect changes that were made in the config file.
+ private void UpdateRecords()
+ {
+ if (_factoryRecords != null)
+ {
+ foreach (FactoryRecord factoryRecord in _factoryRecords.Values)
+ {
+ // Update stream information
+ if (string.IsNullOrEmpty(factoryRecord.Filename))
+ factoryRecord.Filename = ConfigStreamInfo.StreamName;
+
+ factoryRecord.LineNumber = 0;
+
+ ConfigurationSection configSection = GetConfigSection(factoryRecord.ConfigKey);
+ if (configSection == null) continue;
+
+ if (configSection.SectionInformation.Type != null)
+ factoryRecord.FactoryTypeName = configSection.SectionInformation.Type;
+
+ factoryRecord.AllowLocation = configSection.SectionInformation.AllowLocation;
+ factoryRecord.RestartOnExternalChanges =
+ configSection.SectionInformation.RestartOnExternalChanges;
+ factoryRecord.RequirePermission = configSection.SectionInformation.RequirePermission;
+ factoryRecord.AllowDefinition = configSection.SectionInformation.AllowDefinition;
+ factoryRecord.AllowExeDefinition = configSection.SectionInformation.AllowExeDefinition;
+ }
+ }
+
+ if (_sectionRecords != null)
+ {
+ string definitionConfigPath = IsLocationConfig ? _parent.ConfigPath : ConfigPath;
+ foreach (SectionRecord sectionRecord in _sectionRecords.Values)
+ {
+ string configSource;
+ string configSourceStreamName;
+ object configSourceStreamVersion;
+ ConfigurationSection configSection;
+
+ if (sectionRecord.HasResult)
+ {
+ configSection = (ConfigurationSection)sectionRecord.Result;
+ configSource = configSection.SectionInformation.ConfigSource;
+ if (string.IsNullOrEmpty(configSource)) configSource = null;
+
+ configSourceStreamName = configSection.SectionInformation.ConfigSourceStreamName;
+ if (string.IsNullOrEmpty(configSourceStreamName)) configSourceStreamName = null;
+ }
+ else
+ {
+ configSection = null;
+ configSource = null;
+ configSourceStreamName = null;
+
+ // If there is no result, then the only way there could be a
+ // section record is:
+ // 1. For there to be input in the file.
+ // 2. A location tag applies to this record
+ Debug.Assert(sectionRecord.HasFileInput || sectionRecord.HasLocationInputs,
+ "sectionRecord.HasFileInput || sectionRecord.HasLocationInputs");
+
+ // Note that if it's a location input, we don't need to monitor the configSource because
+ // that stream is monitored by one of our parent's config record
+ if (sectionRecord.HasFileInput)
+ {
+ SectionXmlInfo sectionXmlInfo = sectionRecord.FileInput.SectionXmlInfo;
+ configSource = sectionXmlInfo.ConfigSource;
+ configSourceStreamName = sectionXmlInfo.ConfigSourceStreamName;
+ }
+ }
+
+ if (!string.IsNullOrEmpty(configSource))
+ {
+ configSourceStreamVersion = MonitorStream(sectionRecord.ConfigKey, configSource,
+ configSourceStreamName);
+ }
+ else configSourceStreamVersion = null;
+
+ if (!sectionRecord.HasResult)
+ {
+ Debug.Assert(sectionRecord.HasFileInput || sectionRecord.HasLocationInputs,
+ "sectionRecord.HasFileInput || sectionRecord.HasLocationInputs");
+
+ // Note that if it's a location input, we don't need to monitor the configSource because
+ // that stream is monitored by one of our parent's config record
+ if (sectionRecord.HasFileInput)
+ {
+ SectionXmlInfo sectionXmlInfo = sectionRecord.FileInput.SectionXmlInfo;
+ sectionXmlInfo.StreamVersion = ConfigStreamInfo.StreamVersion;
+ sectionXmlInfo.ConfigSourceStreamVersion = configSourceStreamVersion;
+ }
+ }
+ else
+ {
+ configSection.SectionInformation.RawXml = null;
+ bool addUpdate = sectionRecord.AddUpdate;
+ sectionRecord.AddUpdate = false;
+
+ if (addUpdate)
+ {
+ SectionInput fileInput = sectionRecord.FileInput;
+ if (fileInput == null)
+ {
+ SectionXmlInfo sectionXmlInfo = new SectionXmlInfo(
+ sectionRecord.ConfigKey, definitionConfigPath, _configPath, _locationSubPath,
+ ConfigStreamInfo.StreamName, 0, ConfigStreamInfo.StreamVersion, null,
+ configSource, configSourceStreamName, configSourceStreamVersion,
+ configSection.SectionInformation.ProtectionProviderName,
+ configSection.SectionInformation.OverrideModeSetting,
+ !configSection.SectionInformation.InheritInChildApplications);
+
+ fileInput = new SectionInput(sectionXmlInfo, null)
+ {
+ Result = configSection,
+ ResultRuntimeObject = configSection
+ };
+ sectionRecord.AddFileInput(fileInput);
+ }
+ else
+ {
+ SectionXmlInfo sectionXmlInfo = fileInput.SectionXmlInfo;
+ sectionXmlInfo.LineNumber = 0;
+ sectionXmlInfo.StreamVersion = ConfigStreamInfo.StreamVersion;
+
+ sectionXmlInfo.RawXml = null;
+ sectionXmlInfo.ConfigSource = configSource;
+ sectionXmlInfo.ConfigSourceStreamName = configSourceStreamName;
+ sectionXmlInfo.ConfigSourceStreamVersion = configSourceStreamVersion;
+ sectionXmlInfo.ProtectionProviderName =
+ configSection.SectionInformation.ProtectionProviderName;
+ sectionXmlInfo.OverrideModeSetting =
+ configSection.SectionInformation.OverrideModeSetting;
+ sectionXmlInfo.SkipInChildApps =
+ !configSection.SectionInformation.InheritInChildApplications;
+ }
+
+ fileInput.ProtectionProvider = configSection.SectionInformation.ProtectionProvider;
+ }
+
+ try
+ {
+ configSection.ResetModified();
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_exception_in_config_section_handler, sectionRecord.ConfigKey), e,
+ ConfigStreamInfo.StreamName, 0);
+ }
+ }
+ }
+ }
+
+ // Copy remaining stream updates, which correspond to streams used by location sections
+ foreach (StreamInfo streamInfo in _streamInfoUpdates.Values)
+ if (!ConfigStreamInfo.StreamInfos.Contains(streamInfo.StreamName))
+ MonitorStream(streamInfo.SectionName, streamInfo.ConfigSource, streamInfo.StreamName);
+
+ // reinitialize _streamInfoUpdates
+ InitStreamInfoUpdates();
+
+ // Update namespace value
+ _flags[NamespacePresentInFile] = _flags[NamespacePresentCurrent];
+
+ // You only have one chance to force the location config, now you
+ // will have to recreate the object
+ _flags[ForceLocationWritten] = false;
+ _flags[SuggestLocationRemoval] = false;
+
+ // Handle removed location sections
+ if (!IsLocationConfig && (_locationSections != null) && (_removedSections != null) &&
+ (_removedSections.Count > 0))
+ {
+ int i = 0;
+ while (i < _locationSections.Count)
+ {
+ LocationSectionRecord locationSectionRecord = (LocationSectionRecord)_locationSections[i];
+ if (_removedSections.Contains(locationSectionRecord.ConfigKey)) _locationSections.RemoveAt(i);
+ else i++;
+ }
+ }
+
+ _removedSections = null;
+ _removedSectionGroups = null;
+ }
+
+ // Create a new config file.
+ private void CreateNewConfig(
+ SectionUpdates declarationUpdates,
+ ConfigDefinitionUpdates definitionUpdates,
+ NamespaceChange namespaceChange,
+ XmlUtilWriter utilWriter)
+ {
+ // Write Header
+ utilWriter.Write(string.Format(CultureInfo.InvariantCulture,
+ FormatNewConfigFile,
+ ConfigStreamInfo.StreamEncoding.WebName));
+
+ // Write <configuration> tag
+ if (namespaceChange == NamespaceChange.Add)
+ {
+ utilWriter.Write(string.Format(CultureInfo.InvariantCulture,
+ FormatConfigurationNamespace,
+ ConfigurationNamespace));
+ }
+ else utilWriter.Write(FormatConfiguration);
+
+ const int LineIndent = DefaultIndent + 1;
+
+ if (declarationUpdates != null)
+ WriteNewConfigDeclarations(declarationUpdates, utilWriter, LineIndent, DefaultIndent, false);
+
+ WriteNewConfigDefinitions(definitionUpdates, utilWriter, LineIndent, DefaultIndent);
+
+ utilWriter.Write(FormatConfigurationEndElement);
+ }
+
+ private void WriteNewConfigDeclarations(SectionUpdates declarationUpdates, XmlUtilWriter utilWriter,
+ int linePosition, int indent, bool skipFirstIndent)
+ {
+ if (!skipFirstIndent) utilWriter.AppendSpacesToLinePosition(linePosition);
+
+ utilWriter.Write("<configSections>\r\n");
+ WriteUnwrittenConfigDeclarations(declarationUpdates, utilWriter, linePosition + indent, indent, false);
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ utilWriter.Write("</configSections>\r\n");
+
+ if (skipFirstIndent) utilWriter.AppendSpacesToLinePosition(linePosition);
+ }
+
+ private void WriteUnwrittenConfigDeclarations(SectionUpdates declarationUpdates, XmlUtilWriter utilWriter,
+ int linePosition, int indent, bool skipFirstIndent)
+ {
+ WriteUnwrittenConfigDeclarationsRecursive(declarationUpdates, utilWriter, linePosition, indent,
+ skipFirstIndent);
+ }
+
+ private void WriteUnwrittenConfigDeclarationsRecursive(SectionUpdates declarationUpdates,
+ XmlUtilWriter utilWriter, int linePosition, int indent, bool skipFirstIndent)
+ {
+ string[] unretrievedSectionNames = declarationUpdates.GetUnretrievedSectionNames();
+ if (unretrievedSectionNames != null)
+ {
+ foreach (string configKey in unretrievedSectionNames)
+ {
+ Debug.Assert(!IsImplicitSection(configKey), "We should never write out an implicit section");
+ if (!skipFirstIndent) utilWriter.AppendSpacesToLinePosition(linePosition);
+ skipFirstIndent = false;
+
+ DeclarationUpdate update = declarationUpdates.GetDeclarationUpdate(configKey);
+ if (!string.IsNullOrEmpty(update?.UpdatedXml))
+ {
+ utilWriter.Write(update.UpdatedXml);
+ utilWriter.AppendNewLine();
+ }
+ }
+ }
+
+ string[] unretrievedGroupNames = declarationUpdates.GetUnretrievedGroupNames();
+ if (unretrievedGroupNames == null) return;
+
+ foreach (string group in unretrievedGroupNames)
+ {
+ if (TargetFramework != null)
+ {
+ ConfigurationSectionGroup g = GetSectionGroup(group);
+ if ((g != null) && !g.ShouldSerializeSectionGroupInTargetVersion(TargetFramework))
+ {
+ declarationUpdates.MarkGroupAsRetrieved(group);
+ continue;
+ }
+ }
+ if (!skipFirstIndent) utilWriter.AppendSpacesToLinePosition(linePosition);
+ skipFirstIndent = false;
+
+ SectionUpdates declarationUpdatesChild = declarationUpdates.GetSectionUpdatesForGroup(group);
+ DeclarationUpdate groupUpdate = declarationUpdatesChild.GetSectionGroupUpdate();
+ if (groupUpdate == null) utilWriter.Write("<sectionGroup name=\"" + group + "\">");
+ else utilWriter.Write(groupUpdate.UpdatedXml);
+ utilWriter.AppendNewLine();
+
+ WriteUnwrittenConfigDeclarationsRecursive(declarationUpdatesChild, utilWriter, linePosition + indent,
+ indent, false);
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ utilWriter.Write("</sectionGroup>\r\n");
+ }
+ }
+
+ private void WriteNewConfigDefinitions(ConfigDefinitionUpdates configDefinitionUpdates, XmlUtilWriter utilWriter,
+ int linePosition, int indent)
+ {
+ if (configDefinitionUpdates == null)
+ return;
+
+ foreach (LocationUpdates locationUpdates in configDefinitionUpdates.LocationUpdatesList)
+ {
+ SectionUpdates sectionUpdates = locationUpdates.SectionUpdates;
+ if (sectionUpdates.IsEmpty || !sectionUpdates.IsNew)
+ continue;
+
+ configDefinitionUpdates.FlagLocationWritten();
+ bool writeLocationTag = (_locationSubPath != null) || !locationUpdates.IsDefault;
+ int recurseLinePosition = linePosition;
+
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+
+ if (writeLocationTag)
+ {
+ // write the <location> start tag
+ if (_locationSubPath == null)
+ {
+ utilWriter.Write(string.Format(CultureInfo.InvariantCulture, FormatLocationNoPath,
+ locationUpdates.OverrideMode.LocationTagXmlString,
+ BoolToString(locationUpdates.InheritInChildApps)));
+ }
+ else
+ {
+ utilWriter.Write(string.Format(CultureInfo.InvariantCulture, FormatLocationPath,
+ locationUpdates.OverrideMode.LocationTagXmlString,
+ BoolToString(locationUpdates.InheritInChildApps), _locationSubPath));
+ }
+
+ recurseLinePosition += indent;
+ utilWriter.AppendSpacesToLinePosition(recurseLinePosition);
+ }
+
+ // Invoke the recursive write.
+ WriteNewConfigDefinitionsRecursive(utilWriter, locationUpdates.SectionUpdates, recurseLinePosition,
+ indent, true);
+
+ if (writeLocationTag)
+ {
+ // Write the location end tag
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ utilWriter.Write(FormatLocationEndElement);
+ utilWriter.AppendNewLine();
+ }
+ }
+
+ if (configDefinitionUpdates.RequireLocation)
+ {
+ Debug.Assert(IsLocationConfig, "IsLocationConfig");
+
+ // If we still require this to be written, then we must write it out now
+ configDefinitionUpdates.FlagLocationWritten();
+
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+
+ utilWriter.Write(string.Format(CultureInfo.InvariantCulture, FormatLocationPath,
+ OverrideModeSetting.s_locationDefault.LocationTagXmlString, KeywordTrue, _locationSubPath));
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ utilWriter.Write(FormatLocationEndElement);
+ utilWriter.AppendNewLine();
+ }
+ }
+
+ // Recursively write new sections for each section group.
+ private bool WriteNewConfigDefinitionsRecursive(XmlUtilWriter utilWriter, SectionUpdates sectionUpdates,
+ int linePosition, int indent, bool skipFirstIndent)
+ {
+ bool wroteASection = false;
+
+ string[] movedSectionNames = sectionUpdates.GetMovedSectionNames();
+ if (movedSectionNames != null)
+ {
+ wroteASection = true;
+ foreach (string configKey in movedSectionNames)
+ {
+ DefinitionUpdate update = sectionUpdates.GetDefinitionUpdate(configKey);
+ WriteSectionUpdate(utilWriter, update, linePosition, indent, skipFirstIndent);
+ utilWriter.AppendNewLine();
+ skipFirstIndent = false;
+ }
+ }
+
+ string[] newGroupNames = sectionUpdates.GetNewGroupNames();
+ if (newGroupNames != null)
+ {
+ foreach (string group in newGroupNames)
+ {
+ if (TargetFramework != null)
+ {
+ ConfigurationSectionGroup g = GetSectionGroup(group);
+ if ((g != null) && !g.ShouldSerializeSectionGroupInTargetVersion(TargetFramework))
+ {
+ sectionUpdates.MarkGroupAsRetrieved(group);
+ continue;
+ }
+ }
+
+ if (!skipFirstIndent) utilWriter.AppendSpacesToLinePosition(linePosition);
+ skipFirstIndent = false;
+
+ utilWriter.Write("<" + group + ">\r\n");
+ bool recurseWroteASection = WriteNewConfigDefinitionsRecursive(
+ utilWriter, sectionUpdates.GetSectionUpdatesForGroup(group), linePosition + indent, indent,
+ false);
+
+ if (recurseWroteASection) wroteASection = true;
+
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ utilWriter.Write("</" + group + ">\r\n");
+ }
+ }
+
+ sectionUpdates.IsNew = false;
+
+ return wroteASection;
+ }
+
+ private void CheckPreamble(byte[] preamble, XmlUtilWriter utilWriter, byte[] buffer)
+ {
+ bool hasByteOrderMark = false;
+ using (Stream preambleStream = new MemoryStream(buffer))
+ {
+ byte[] streamStart = new byte[preamble.Length];
+ if (preambleStream.Read(streamStart, 0, streamStart.Length) == streamStart.Length)
+ {
+ hasByteOrderMark = true;
+ for (int i = 0; i < streamStart.Length; i++)
+ if (streamStart[i] != preamble[i])
+ {
+ hasByteOrderMark = false;
+ break;
+ }
+ }
+ }
+
+ if (!hasByteOrderMark)
+ {
+ // Force the writer to emit byte order mark, then reset the stream
+ // so that it is written over.
+ object checkpoint = utilWriter.CreateStreamCheckpoint();
+ utilWriter.Write('x');
+ utilWriter.RestoreStreamCheckpoint(checkpoint);
+ }
+ }
+
+ //
+ // Calculate a new indent based on the position of the parent element and the current node.
+ //
+ private int UpdateIndent(int oldIndent, XmlUtil xmlUtil, XmlUtilWriter utilWriter, int parentLinePosition)
+ {
+ int indent = oldIndent;
+ if ((xmlUtil.Reader.NodeType == XmlNodeType.Element) && utilWriter.IsLastLineBlank)
+ {
+ int childLinePosition = xmlUtil.TrueLinePosition;
+ if ((parentLinePosition < childLinePosition) && (childLinePosition <= parentLinePosition + MaxIndent))
+ indent = childLinePosition - parentLinePosition;
+ }
+
+ return indent;
+ }
+
+ // Copy a config file, replacing sections with updates.
+ private void CopyConfig(SectionUpdates declarationUpdates, ConfigDefinitionUpdates definitionUpdates,
+ byte[] buffer, string filename, NamespaceChange namespaceChange, XmlUtilWriter utilWriter)
+ {
+ CheckPreamble(ConfigStreamInfo.StreamEncoding.GetPreamble(), utilWriter, buffer);
+
+ using (Stream stream = new MemoryStream(buffer))
+ {
+ using (XmlUtil xmlUtil = new XmlUtil(stream, filename, false))
+ {
+ // copy up to the <configuration> node
+ XmlTextReader reader = xmlUtil.Reader;
+ reader.WhitespaceHandling = WhitespaceHandling.All;
+ reader.Read();
+ xmlUtil.CopyReaderToNextElement(utilWriter, false);
+
+ Debug.Assert((reader.NodeType == XmlNodeType.Element) && (reader.Name == ConfigurationTag),
+ "reader.NodeType == XmlNodeType.Element && reader.Name == KEYWORD_CONFIGURATION");
+
+ int indent = DefaultIndent;
+ int configurationElementLinePosition = xmlUtil.TrueLinePosition;
+ bool isEmptyConfigurationElement = reader.IsEmptyElement;
+
+ // copy <configuration> node
+ // if the node is an empty element, we may need to open it.
+ string configurationStartElement;
+ if (namespaceChange == NamespaceChange.Add)
+ {
+ configurationStartElement = string.Format(
+ CultureInfo.InvariantCulture, FormatConfigurationNamespace,
+ ConfigurationNamespace);
+ }
+ else
+ {
+ configurationStartElement = namespaceChange == NamespaceChange.Remove
+ ? FormatConfiguration
+ : null;
+ }
+
+ bool needsChildren = (declarationUpdates != null) || (definitionUpdates != null);
+ string configurationEndElement = xmlUtil.UpdateStartElement(utilWriter, configurationStartElement,
+ needsChildren, configurationElementLinePosition, indent);
+
+ bool foundConfigSectionsElement = false;
+ if (!isEmptyConfigurationElement)
+ {
+ // copy up to the first element under <configuration>
+ xmlUtil.CopyReaderToNextElement(utilWriter, true);
+
+ // updateIndent
+ indent = UpdateIndent(indent, xmlUtil, utilWriter, configurationElementLinePosition);
+
+ if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == ConfigSectionsTag))
+ {
+ foundConfigSectionsElement = true;
+
+ int configSectionsElementLinePosition = xmlUtil.TrueLinePosition;
+ bool isEmptyConfigSectionsElement = reader.IsEmptyElement;
+
+ // if no updates, copy the entire <configSections> element
+ if (declarationUpdates == null) xmlUtil.CopyOuterXmlToNextElement(utilWriter, true);
+ else
+ {
+ // copy <configSections>, and open it if it is an empty element
+ string configSectionsEndElement = xmlUtil.UpdateStartElement(
+ utilWriter, null, true, configSectionsElementLinePosition, indent);
+
+ if (!isEmptyConfigSectionsElement)
+ {
+ // copy to next element under <configSections>, or up to closing </configSections>
+ xmlUtil.CopyReaderToNextElement(utilWriter, true);
+
+ // copy config declarations
+ CopyConfigDeclarationsRecursive(declarationUpdates, xmlUtil, utilWriter,
+ string.Empty,
+ configSectionsElementLinePosition, indent);
+
+ Debug.Assert(
+ (reader.NodeType == XmlNodeType.EndElement) &&
+ (reader.Name == ConfigSectionsTag),
+ "reader.NodeType == XmlNodeType.EndElement && reader.Name == \"KEYWORD_CONFIGSECTIONS\"");
+ }
+
+ // write declarations not written by above copy
+ if (declarationUpdates.HasUnretrievedSections())
+ {
+ // determine the line position of the end element
+ int endElementLinePosition = 0;
+ if (configSectionsEndElement == null)
+ endElementLinePosition = xmlUtil.TrueLinePosition;
+
+ // indent a new line
+ if (!utilWriter.IsLastLineBlank) utilWriter.AppendNewLine();
+
+ WriteUnwrittenConfigDeclarations(declarationUpdates, utilWriter,
+ configSectionsElementLinePosition + indent, indent, false);
+
+ // restore spaces to end element
+ if (configSectionsEndElement == null)
+ utilWriter.AppendSpacesToLinePosition(endElementLinePosition);
+ }
+
+ // Copy the </configSections> element
+ if (configSectionsEndElement == null) xmlUtil.CopyXmlNode(utilWriter);
+ else
+ {
+ // note that configSectionsEndElement already contains the proper indenting
+ utilWriter.Write(configSectionsEndElement);
+ }
+
+ // copy up to the next element under <configuration>, or up to closing </configSections>
+ xmlUtil.CopyReaderToNextElement(utilWriter, true);
+ }
+ }
+ }
+
+ // Write new declarations
+ if (!foundConfigSectionsElement && (declarationUpdates != null))
+ {
+ bool skipFirstIndent = (reader.Depth > 0) && (reader.NodeType == XmlNodeType.Element);
+ int newConfigSectionsLinePosition;
+ if (skipFirstIndent) newConfigSectionsLinePosition = xmlUtil.TrueLinePosition;
+ else newConfigSectionsLinePosition = configurationElementLinePosition + indent;
+
+ WriteNewConfigDeclarations(declarationUpdates, utilWriter, newConfigSectionsLinePosition, indent,
+ skipFirstIndent);
+ }
+
+ if (definitionUpdates != null)
+ {
+ // Copy sections recursively. In the file we copy we start out at
+ // location path="." allowOverride="true" inheritInChildApps="true"
+ bool locationPathApplies = false;
+ LocationUpdates locationUpdates = null;
+ SectionUpdates sectionUpdates = null;
+ if (!IsLocationConfig)
+ {
+ locationPathApplies = true;
+ locationUpdates = definitionUpdates.FindLocationUpdates(
+ OverrideModeSetting.s_locationDefault, true);
+ if (locationUpdates != null) sectionUpdates = locationUpdates.SectionUpdates;
+ }
+
+ CopyConfigDefinitionsRecursive(definitionUpdates, xmlUtil, utilWriter, locationPathApplies,
+ locationUpdates, sectionUpdates, true, string.Empty, configurationElementLinePosition,
+ indent);
+
+ // Write new config sections from new groups.
+ WriteNewConfigDefinitions(definitionUpdates, utilWriter,
+ configurationElementLinePosition + indent, indent);
+
+#if DEBUG
+ Debug.Assert(
+ (configurationEndElement != null) ||
+ ((reader.NodeType == XmlNodeType.EndElement) && (reader.Name == ConfigurationTag)),
+ "configurationEndElement != null || (reader.NodeType == XmlNodeType.EndElement && reader.Name == KEYWORD_CONFIGURATION)");
+ foreach (LocationUpdates l in definitionUpdates.LocationUpdatesList)
+ Debug.Assert(!l.SectionUpdates.HasUnretrievedSections(),
+ "!l.SectionUpdates.HasUnretrievedSections()");
+#endif
+ }
+
+
+ if (configurationEndElement != null)
+ {
+ // If we have to add closing config tag, then do it now
+ // before copying extra whitespace/comments
+ if (!utilWriter.IsLastLineBlank) utilWriter.AppendNewLine();
+
+ utilWriter.Write(configurationEndElement);
+ }
+
+ // Copy the remainder of the file, the closing </configuration> node plus any whitespace
+ // and comments
+ while (xmlUtil.CopyXmlNode(utilWriter)) { }
+ }
+ }
+ }
+
+ private bool CopyConfigDeclarationsRecursive(
+ SectionUpdates declarationUpdates, XmlUtil xmlUtil, XmlUtilWriter utilWriter, string group,
+ int parentLinePosition, int parentIndent)
+ {
+ bool wroteASection = false;
+ XmlTextReader reader = xmlUtil.Reader;
+ int linePosition;
+ int indent;
+ int startingLinePosition;
+
+ indent = UpdateIndent(parentIndent, xmlUtil, utilWriter, parentLinePosition);
+
+ switch (reader.NodeType)
+ {
+ case XmlNodeType.Element:
+ linePosition = xmlUtil.TrueLinePosition;
+ startingLinePosition = linePosition;
+ break;
+ case XmlNodeType.EndElement:
+ linePosition = parentLinePosition + indent;
+ startingLinePosition = utilWriter.IsLastLineBlank ? xmlUtil.TrueLinePosition : parentLinePosition;
+ break;
+ default:
+ linePosition = parentLinePosition + indent;
+ startingLinePosition = 0;
+ break;
+ }
+
+ // Write any new section declarations that apply to this group
+ string[] movedSectionNames = declarationUpdates?.GetMovedSectionNames();
+
+ if (movedSectionNames != null)
+ {
+ if (!utilWriter.IsLastLineBlank) utilWriter.AppendNewLine();
+
+ foreach (string configKey in movedSectionNames)
+ {
+ DeclarationUpdate sectionUpdate = declarationUpdates.GetDeclarationUpdate(configKey);
+ Debug.Assert(!IsImplicitSection(configKey), "We should never write out an implicit section");
+
+ // Write the one line section declaration.
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ utilWriter.Write(sectionUpdate.UpdatedXml);
+ utilWriter.AppendNewLine();
+
+ wroteASection = true;
+ }
+
+ // Restore the whitespace we used for the first element, which is either a start or an end element.
+ utilWriter.AppendSpacesToLinePosition(startingLinePosition);
+ }
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ // For each element at this depth, either:
+ // - Write the element verbatim and recurse due to a group hierarchy element.
+ // - Write the element verbatim because it is unchanged
+ // - Write the updated XML for the section.
+ // - Skip it because the section has been removed.
+ int depth = reader.Depth;
+ while (reader.Depth == depth)
+ {
+ bool recurse = false;
+ DeclarationUpdate sectionUpdate = null;
+ DeclarationUpdate groupUpdate = null;
+ SectionUpdates declarationUpdatesChild = null;
+ SectionUpdates recurseDeclarationUpdates = declarationUpdates;
+ string recurseGroup = group;
+
+ // update the lineposition and indent for each element
+ indent = UpdateIndent(indent, xmlUtil, utilWriter, parentLinePosition);
+ linePosition = xmlUtil.TrueLinePosition;
+
+ string directive = reader.Name;
+ string name = reader.GetAttribute(SectionGroupNameAttribute);
+ string configKey = CombineConfigKey(group, name);
+ if (directive == SectionGroupTag)
+ {
+ // it's a group - get the updates for children
+ declarationUpdatesChild = declarationUpdates.GetSectionUpdatesForGroup(name);
+ if (declarationUpdatesChild != null)
+ {
+ // get the group update
+ groupUpdate = declarationUpdatesChild.GetSectionGroupUpdate();
+
+ // recurse if there are more sections to copy
+ if (declarationUpdatesChild.HasUnretrievedSections())
+ {
+ recurse = true;
+ recurseGroup = configKey;
+ recurseDeclarationUpdates = declarationUpdatesChild;
+ }
+ }
+ }
+ else
+ {
+ // it is a section - get the update
+ Debug.Assert(!IsImplicitSection(configKey), "We should never write out an implicit section");
+ sectionUpdate = declarationUpdates.GetDeclarationUpdate(configKey);
+ }
+
+ bool writeGroupUpdate = groupUpdate?.UpdatedXml != null;
+ if (recurse)
+ {
+ // create a checkpoint that we can revert to if no children are written
+ object checkpoint = utilWriter.CreateStreamCheckpoint();
+ string closingElement = null;
+
+ // Copy this element node and up to the first subelement
+ if (writeGroupUpdate)
+ {
+ // replace the element with the updated xml
+ utilWriter.Write(groupUpdate.UpdatedXml);
+
+ // skip over the start element
+ reader.Read();
+ }
+ else closingElement = xmlUtil.UpdateStartElement(utilWriter, null, true, linePosition, indent);
+
+ if (closingElement == null)
+ {
+ // Only if there is a closing element should
+ // we move to it
+ xmlUtil.CopyReaderToNextElement(utilWriter, true);
+ }
+
+ // Recurse
+ bool recurseWroteASection = CopyConfigDeclarationsRecursive(
+ recurseDeclarationUpdates, xmlUtil, utilWriter, recurseGroup, linePosition, indent);
+
+ if (closingElement != null)
+ {
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ utilWriter.Write(closingElement);
+
+ // Since we already got to </configSections> in reader, lets
+ // indent so we can copy the element in the right place
+ utilWriter.AppendSpacesToLinePosition(parentLinePosition);
+ }
+ else
+ {
+ // Copy the end element
+ xmlUtil.CopyXmlNode(utilWriter);
+ }
+
+ if (recurseWroteASection || writeGroupUpdate) wroteASection = true;
+ else
+ {
+ // back out the change
+ utilWriter.RestoreStreamCheckpoint(checkpoint);
+ }
+
+ // Copy up to the next element, or exit this level.
+ xmlUtil.CopyReaderToNextElement(utilWriter, true);
+ }
+ else
+ {
+ bool skip;
+ bool skipChildElements = false;
+ if (sectionUpdate == null)
+ {
+ skip = true;
+ if (writeGroupUpdate)
+ {
+ // Insert an empty <sectionGroup type="typename" > node, to introduce the type
+ wroteASection = true;
+ utilWriter.Write(groupUpdate.UpdatedXml);
+ utilWriter.AppendNewLine();
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ utilWriter.Write(FormatSectionGroupEndElement);
+ utilWriter.AppendNewLine();
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ }
+ else
+ {
+ if (groupUpdate != null)
+ {
+ // If groupUpdate exists, that means we've decided in GetConfigDeclarationUpdates
+ // that the section group should stay in the file.
+ Debug.Assert(groupUpdate.UpdatedXml == null, "groupUpdate.UpdatedXml == null");
+ Debug.Assert(!declarationUpdatesChild.HasUnretrievedSections(),
+ "If the group has any unretrieved section, we should have chosen the recursive code path above.");
+
+ wroteASection = true;
+ skip = false;
+
+ // We should skip all the child sections. If we indeed need to keep any child
+ // section, we should have chosen the recursive code path above.
+ skipChildElements = true;
+ }
+ }
+ }
+ else
+ {
+ wroteASection = true;
+ if (sectionUpdate.UpdatedXml == null) skip = false;
+ else
+ {
+ skip = true;
+
+ // Write the updated XML on a single line
+ utilWriter.Write(sectionUpdate.UpdatedXml);
+ }
+ }
+
+ if (skip)
+ {
+ // Skip over the existing element, then
+ // copy up to the next element, or exit this level.
+ xmlUtil.SkipAndCopyReaderToNextElement(utilWriter, true);
+ }
+ else
+ {
+ if (skipChildElements) xmlUtil.SkipChildElementsAndCopyOuterXmlToNextElement(utilWriter);
+ else
+ {
+ // Copy this entire contents of this element and then to the next element, or exit this level.
+ xmlUtil.CopyOuterXmlToNextElement(utilWriter, true);
+ }
+ }
+ }
+ }
+ }
+
+ return wroteASection;
+ }
+
+ // Copy configuration sections from the original configuration file.
+ private bool CopyConfigDefinitionsRecursive(
+ ConfigDefinitionUpdates configDefinitionUpdates, XmlUtil xmlUtil, XmlUtilWriter utilWriter,
+ bool locationPathApplies, LocationUpdates locationUpdates, SectionUpdates sectionUpdates,
+ bool addNewSections, string group, int parentLinePosition, int parentIndent)
+ {
+ bool wroteASection = false;
+ XmlTextReader reader = xmlUtil.Reader;
+ int linePosition;
+ int indent;
+ int startingLinePosition;
+
+ indent = UpdateIndent(parentIndent, xmlUtil, utilWriter, parentLinePosition);
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ linePosition = xmlUtil.TrueLinePosition;
+ startingLinePosition = linePosition;
+ }
+ else
+ {
+ if (reader.NodeType == XmlNodeType.EndElement)
+ {
+ linePosition = parentLinePosition + indent;
+ startingLinePosition = utilWriter.IsLastLineBlank ? xmlUtil.TrueLinePosition : parentLinePosition;
+ }
+ else
+ {
+ linePosition = parentLinePosition + indent;
+ startingLinePosition = 0;
+ }
+ }
+
+ // Write any new sections that apply to this group
+ if ((sectionUpdates != null) && addNewSections)
+ {
+ // Remove newness, so we won't write again
+ sectionUpdates.IsNew = false;
+
+ Debug.Assert(locationPathApplies, "locationPathApplies");
+ string[] movedSectionNames = sectionUpdates.GetMovedSectionNames();
+ if (movedSectionNames != null)
+ {
+ if (!utilWriter.IsLastLineBlank) utilWriter.AppendNewLine();
+
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+ bool skipFirstIndent = true;
+
+ foreach (string configKey in movedSectionNames)
+ {
+ DefinitionUpdate update = sectionUpdates.GetDefinitionUpdate(configKey);
+
+ WriteSectionUpdate(utilWriter, update, linePosition, indent, skipFirstIndent);
+ skipFirstIndent = false;
+ utilWriter.AppendNewLine();
+ wroteASection = true;
+ }
+
+ // Restore the whitespace we used for the first element, which is either a start or an end element.
+ utilWriter.AppendSpacesToLinePosition(startingLinePosition);
+ }
+ }
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ // For each element at this depth, either:
+ // - Write the element verbatim and recurse due to a location section or group hierarchy element.
+ // - Write the element verbatim because it is unchanged, or because the current location does
+ // not apply.
+ // - Write the updated XML for the section.
+ // - Skip it because the section has been removed.
+ int depth = reader.Depth;
+ while (reader.Depth == depth)
+ {
+ bool recurse = false;
+ DefinitionUpdate update = null;
+ bool elementLocationPathApplies = locationPathApplies;
+ LocationUpdates recurseLocationUpdates = locationUpdates;
+ SectionUpdates recurseSectionUpdates = sectionUpdates;
+ bool recurseAddNewSections = addNewSections;
+ string recurseGroup = group;
+ bool removedSectionOrGroup = false;
+
+ // update the lineposition and indent for each element
+ indent = UpdateIndent(indent, xmlUtil, utilWriter, parentLinePosition);
+ linePosition = xmlUtil.TrueLinePosition;
+
+ string elementName = reader.Name;
+ if (elementName == LocationTag)
+ {
+ string locationSubPathAttribute = reader.GetAttribute(LocationPathAttribute);
+ locationSubPathAttribute = NormalizeLocationSubPath(locationSubPathAttribute, xmlUtil);
+ OverrideModeSetting overrideMode = OverrideModeSetting.s_locationDefault;
+ bool inheritInChildApps = true;
+
+ if (IsLocationConfig)
+ {
+ // For location config we will compare config paths instead of location strings
+ // so that we dont end up comparing "1" with "Default Web Site" and ending up with the wrong result
+ if (locationSubPathAttribute == null) elementLocationPathApplies = false;
+ else
+ {
+ elementLocationPathApplies = StringUtil.EqualsIgnoreCase(ConfigPath,
+ Host.GetConfigPathFromLocationSubPath(Parent.ConfigPath, locationSubPathAttribute));
+ }
+ }
+ else
+ {
+ Debug.Assert(LocationSubPath == null);
+
+ // This is the same as doing StringUtil.EqualsIgnoreCase(_locationSubPath, locationSubPathAttribute)
+ // but remember the first one is null. Also remember locationSubPathAttribute is already normalized
+ elementLocationPathApplies = locationSubPathAttribute == null;
+ }
+
+ if (elementLocationPathApplies)
+ {
+ // Retrieve overrideMode and InheritInChildApps
+ string allowOverrideAttribute = reader.GetAttribute(LocationAllowOverrideAttribute);
+ if (allowOverrideAttribute != null)
+ {
+ overrideMode =
+ OverrideModeSetting.CreateFromXmlReadValue(bool.Parse(allowOverrideAttribute));
+ }
+
+ string overrideModeAttribute = reader.GetAttribute(LocationOverrideModeAttribute);
+ if (overrideModeAttribute != null)
+ {
+ overrideMode =
+ OverrideModeSetting.CreateFromXmlReadValue(
+ OverrideModeSetting.ParseOverrideModeXmlValue(overrideModeAttribute, null));
+
+ Debug.Assert(allowOverrideAttribute == null,
+ "allowOverride and overrideMode both detected in a <location> tag");
+ }
+
+ string inheritInChildAppsAttribute =
+ reader.GetAttribute(LocationInheritInChildApplicationsAttribute);
+ if (inheritInChildAppsAttribute != null)
+ inheritInChildApps = bool.Parse(inheritInChildAppsAttribute);
+
+ // Flag that we already have one of these locations
+ configDefinitionUpdates.FlagLocationWritten();
+ }
+
+ if (reader.IsEmptyElement)
+ {
+ if (elementLocationPathApplies &&
+ (configDefinitionUpdates.FindLocationUpdates(overrideMode,
+ inheritInChildApps) != null))
+ {
+ // If we are going to make updates here, then
+ // delete the one that is here (so we can update later)
+ elementLocationPathApplies = true;
+ }
+ else
+ {
+ // If not lets leave it
+ elementLocationPathApplies = false;
+ }
+ }
+ else
+ {
+ // recurse if this location applies to us
+ if (elementLocationPathApplies)
+ {
+ if (configDefinitionUpdates != null)
+ {
+ recurseLocationUpdates = configDefinitionUpdates.FindLocationUpdates(overrideMode,
+ inheritInChildApps);
+ if (recurseLocationUpdates != null)
+ {
+ recurse = true;
+ recurseSectionUpdates = recurseLocationUpdates.SectionUpdates;
+
+ // If this is <location path=".">, we don't want to add moved sections
+ // to it.
+ if ((_locationSubPath == null) && recurseLocationUpdates.IsDefault)
+ recurseAddNewSections = false;
+ }
+ }
+ }
+ else
+ {
+ // recurse if necessary to remove items in _removedSections and _removedGroups
+ if (HasRemovedSectionsOrGroups && !IsLocationConfig && Host.SupportsLocation)
+ {
+ recurse = true;
+ recurseLocationUpdates = null;
+ recurseSectionUpdates = null;
+ recurseAddNewSections = false;
+ }
+ }
+ }
+ }
+ else
+ {
+ string configKey = CombineConfigKey(group, elementName);
+ FactoryRecord factoryRecord = FindFactoryRecord(configKey, false);
+ if (factoryRecord == null)
+ {
+ // The factory was deleted, so regardless of whether this is a
+ // section or sectionGroup, it can be skipped.
+ if (!elementLocationPathApplies && !IsLocationConfig) removedSectionOrGroup = true;
+ }
+ else
+ {
+ if (factoryRecord.IsGroup)
+ {
+ if (reader.IsEmptyElement)
+ {
+ if (!elementLocationPathApplies && !IsLocationConfig) removedSectionOrGroup = true;
+ }
+ else
+ {
+ // if the location path applies, recurse if there are updates
+ if (sectionUpdates != null)
+ {
+ SectionUpdates sectionUpdatesChild =
+ sectionUpdates.GetSectionUpdatesForGroup(elementName);
+ if (sectionUpdatesChild != null)
+ {
+ recurse = true;
+ recurseGroup = configKey;
+ recurseSectionUpdates = sectionUpdatesChild;
+ }
+ }
+ else
+ {
+ if (!elementLocationPathApplies && !IsLocationConfig)
+ {
+ if ((_removedSectionGroups != null) &&
+ _removedSectionGroups.Contains(configKey))
+ removedSectionOrGroup = true;
+ else
+ {
+ recurse = true;
+ recurseGroup = configKey;
+ recurseLocationUpdates = null;
+ recurseSectionUpdates = null;
+ recurseAddNewSections = false;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // it is a section - get the update
+ if (sectionUpdates != null) update = sectionUpdates.GetDefinitionUpdate(configKey);
+ else
+ {
+ if (!elementLocationPathApplies && !IsLocationConfig)
+ {
+ if ((_removedSections != null) && _removedSections.Contains(configKey))
+ removedSectionOrGroup = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (recurse)
+ {
+ // flush, and get length of underlying stream
+ object checkpoint = utilWriter.CreateStreamCheckpoint();
+
+ // Copy this element node and up to the first subelement
+ xmlUtil.CopyXmlNode(utilWriter);
+ xmlUtil.CopyReaderToNextElement(utilWriter, true);
+
+ // Recurse
+ bool recurseWroteASection = CopyConfigDefinitionsRecursive(
+ configDefinitionUpdates, xmlUtil, utilWriter, elementLocationPathApplies,
+ recurseLocationUpdates, recurseSectionUpdates,
+ recurseAddNewSections, recurseGroup, linePosition, indent);
+
+ // Copy the end element
+ xmlUtil.CopyXmlNode(utilWriter);
+
+ if (recurseWroteASection) wroteASection = true;
+ else
+ {
+ // back out the change
+ utilWriter.RestoreStreamCheckpoint(checkpoint);
+ }
+
+ // Copy up to the next element, or exit this level.
+ xmlUtil.CopyReaderToNextElement(utilWriter, true);
+ }
+ else
+ {
+ bool skip;
+ if (update == null)
+ {
+ // remove the section from the file if we're in the correct location,
+ // or if the section or group should be removed from all locations
+ skip = elementLocationPathApplies || removedSectionOrGroup;
+ }
+ else
+ {
+ // replace the section if the xml for it has been updated
+ // if it is a configSource, don't write it unless the configSource parameters have changed
+ skip = false;
+ if (update.UpdatedXml != null)
+ {
+ ConfigurationSection configSection = (ConfigurationSection)update.SectionRecord.Result;
+ if (string.IsNullOrEmpty(configSection.SectionInformation.ConfigSource) ||
+ configSection.SectionInformation.ConfigSourceModified)
+ {
+ skip = true;
+ WriteSectionUpdate(utilWriter, update, linePosition, indent, true);
+ wroteASection = true;
+ }
+ }
+ }
+
+ if (skip)
+ {
+ // Skip over the existing element, then
+ // copy up to the next element, or exit this level.
+ xmlUtil.SkipAndCopyReaderToNextElement(utilWriter, true);
+ }
+ else
+ {
+ // Copy this entire contents of this element and then to the next element, or exit this level.
+ xmlUtil.CopyOuterXmlToNextElement(utilWriter, true);
+ wroteASection = true;
+ }
+ }
+ }
+ }
+
+ // Write new section groups
+ if ((sectionUpdates != null) && addNewSections && sectionUpdates.HasNewSectionGroups())
+ {
+ // Add whitespace to align us with the other elements in this group
+ linePosition = parentLinePosition + indent;
+ if (reader.NodeType == XmlNodeType.EndElement)
+ startingLinePosition = utilWriter.IsLastLineBlank ? xmlUtil.TrueLinePosition : parentLinePosition;
+ else startingLinePosition = 0;
+
+ utilWriter.AppendSpacesToLinePosition(linePosition);
+
+ bool wroteNewSection = WriteNewConfigDefinitionsRecursive(utilWriter, sectionUpdates, linePosition,
+ indent, true);
+ if (wroteNewSection) wroteASection = true;
+
+ // Restore the whitespace of the end element
+ utilWriter.AppendSpacesToLinePosition(startingLinePosition);
+ }
+
+ return wroteASection;
+ }
+
+ private void WriteSectionUpdate(XmlUtilWriter utilWriter, DefinitionUpdate update, int linePosition, int indent,
+ bool skipFirstIndent)
+ {
+ ConfigurationSection configSection = (ConfigurationSection)update.SectionRecord.Result;
+ string updatedXml;
+
+ if (!string.IsNullOrEmpty(configSection.SectionInformation.ConfigSource))
+ {
+ updatedXml = string.Format(CultureInfo.InvariantCulture, FormatSectionConfigSource,
+ configSection.SectionInformation.Name, configSection.SectionInformation.ConfigSource);
+ }
+ else updatedXml = update.UpdatedXml;
+
+ string formattedXml = XmlUtil.FormatXmlElement(updatedXml, linePosition, indent, skipFirstIndent);
+ utilWriter.Write(formattedXml);
+ }
+
+ // SaveConfigSource
+ private void SaveConfigSource(DefinitionUpdate update)
+ {
+ string configSourceStreamName;
+
+ if (update.SectionRecord.HasResult)
+ {
+ ConfigurationSection configSection = (ConfigurationSection)update.SectionRecord.Result;
+ configSourceStreamName = configSection.SectionInformation.ConfigSourceStreamName;
+ }
+ else
+ {
+ Debug.Assert(update.SectionRecord.HasFileInput, "update.SectionRecord.HasFileInput");
+ SectionInput fileInput = update.SectionRecord.FileInput;
+ configSourceStreamName = fileInput.SectionXmlInfo.ConfigSourceStreamName;
+ }
+
+ // Copy the input stream before opening the output stream.
+ byte[] readBuffer = null;
+ using (Stream streamRead = Host.OpenStreamForRead(configSourceStreamName))
+ {
+ if (streamRead != null)
+ {
+ readBuffer = new byte[streamRead.Length];
+ int count = streamRead.Read(readBuffer, 0, (int)streamRead.Length);
+ if (count != streamRead.Length) throw new ConfigurationErrorsException();
+ }
+ }
+
+ // Write the changes to the output stream.
+ bool hasFile = readBuffer != null;
+ object writeContext = null;
+ bool streamOpened = false;
+
+ try
+ {
+ try
+ {
+ // templateStreamName is used by OpenStreamForWrite for copying file attributes during saving.
+ // (for details, see WriteFileContext.Complete.)
+ //
+ // If we're using a remote host, then ConfigStreamInfo.StreamName is actually pointing to a
+ // full filepath on a remote machine. In this case, it's impossible to copy the attributes
+ // over, and thus we won't do it.
+ string templateStreamName = Host.IsRemote ? null : ConfigStreamInfo.StreamName;
+
+ using (
+ Stream streamWrite = Host.OpenStreamForWrite(configSourceStreamName, templateStreamName,
+ ref writeContext))
+ {
+ streamOpened = true;
+ if (update.UpdatedXml == null)
+ {
+ Debug.Assert(hasFile, "hasFile");
+ if (hasFile) streamWrite.Write(readBuffer, 0, readBuffer.Length);
+ }
+ else
+ {
+ using (StreamWriter streamWriter = new StreamWriter(streamWrite))
+ {
+ XmlUtilWriter utilWriter = new XmlUtilWriter(streamWriter, true);
+ if (hasFile)
+ CopyConfigSource(utilWriter, update.UpdatedXml, configSourceStreamName, readBuffer);
+ else CreateNewConfigSource(utilWriter, update.UpdatedXml, DefaultIndent);
+ }
+ }
+ }
+ }
+ catch
+ {
+ if (streamOpened) Host.WriteCompleted(configSourceStreamName, false, writeContext);
+ throw;
+ }
+ }
+ catch (Exception e)
+ {
+ // Guarantee that exceptions contain at least the name of the stream by wrapping them
+ // in a ConfigurationException.
+ throw ExceptionUtil.WrapAsConfigException(SR.Config_error_loading_XML_file, e, configSourceStreamName, 0);
+ }
+
+ Host.WriteCompleted(configSourceStreamName, true, writeContext);
+ }
+
+ private void CopyConfigSource(XmlUtilWriter utilWriter, string updatedXml, string configSourceStreamName,
+ byte[] buffer)
+ {
+ // only copy the byte order mark if it exists in the current web.config
+ byte[] preamble;
+ using (Stream stream = new MemoryStream(buffer))
+ {
+ using (new XmlUtil(stream, configSourceStreamName, true))
+ {
+ preamble = ConfigStreamInfo.StreamEncoding.GetPreamble();
+ }
+ }
+
+ CheckPreamble(preamble, utilWriter, buffer);
+
+ using (Stream stream = new MemoryStream(buffer))
+ {
+ using (XmlUtil xmlUtil = new XmlUtil(stream, configSourceStreamName, false))
+ {
+ XmlTextReader reader = xmlUtil.Reader;
+
+ // copy up to the first element
+ reader.WhitespaceHandling = WhitespaceHandling.All;
+ reader.Read();
+
+ // determine the indent to use for the element
+ int indent = DefaultIndent;
+ int linePosition = 1;
+ bool hasElement = xmlUtil.CopyReaderToNextElement(utilWriter, false);
+ if (hasElement)
+ {
+ // find the indent of the first attribute, if any
+ int lineNumber = reader.LineNumber;
+ linePosition = reader.LinePosition - 1;
+ int attributeIndent = 0;
+ while (reader.MoveToNextAttribute())
+ if (reader.LineNumber > lineNumber)
+ {
+ attributeIndent = reader.LinePosition - linePosition;
+ break;
+ }
+
+ // find the indent of the first sub element, if any
+ int elementIndent = 0;
+ reader.Read();
+ while (reader.Depth >= 1)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ elementIndent = reader.LinePosition - 1 - linePosition;
+ break;
+ }
+
+ reader.Read();
+ }
+
+ if (elementIndent > 0) indent = elementIndent;
+ else
+ {
+ if (attributeIndent > 0) indent = attributeIndent;
+ }
+ }
+
+ // Write the config source
+ string formattedXml = XmlUtil.FormatXmlElement(updatedXml, linePosition, indent, true);
+ utilWriter.Write(formattedXml);
+
+ // Copy remaining contents
+ if (hasElement)
+ {
+ // Skip over the existing element
+ while (reader.Depth > 0) reader.Read();
+
+ if (reader.IsEmptyElement || (reader.NodeType == XmlNodeType.EndElement)) reader.Read();
+
+ // Copy remainder of file
+ while (xmlUtil.CopyXmlNode(utilWriter)) { }
+ }
+ }
+ }
+ }
+
+ private void CreateNewConfigSource(XmlUtilWriter utilWriter, string updatedXml, int indent)
+ {
+ string formattedXml = XmlUtil.FormatXmlElement(updatedXml, 0, indent, true);
+ utilWriter.Write(string.Format(CultureInfo.InvariantCulture, FormatConfigSourceFile,
+ ConfigStreamInfo.StreamEncoding.WebName));
+ utilWriter.Write(formattedXml + NewLine);
+ }
+
+ private static string BoolToString(bool v)
+ {
+ return v ? KeywordTrue : KeywordFalse;
+ }
+
+ // It is possible that we have set the flag to force this location
+ // to be written out. Allow a way to remove that
+ internal void RemoveLocationWriteRequirement()
+ {
+ if (IsLocationConfig)
+ {
+ _flags[ForceLocationWritten] = false;
+ _flags[SuggestLocationRemoval] = true;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/NameValueConfigurationCollection.cs b/src/System.Configuration/src/System/Configuration/NameValueConfigurationCollection.cs
new file mode 100644
index 0000000000..6ca14ca013
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/NameValueConfigurationCollection.cs
@@ -0,0 +1,69 @@
+// 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.Configuration
+{
+ [ConfigurationCollection(typeof(NameValueConfigurationElement))]
+ public sealed class NameValueConfigurationCollection : ConfigurationElementCollection
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ static NameValueConfigurationCollection()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection();
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ public new NameValueConfigurationElement this[string name]
+ {
+ get { return (NameValueConfigurationElement)BaseGet(name); }
+ set
+ {
+ int index = -1; // append by default
+ NameValueConfigurationElement tempElement = (NameValueConfigurationElement)BaseGet(name);
+ if (tempElement != null)
+ {
+ index = BaseIndexOf(tempElement);
+ BaseRemoveAt(index);
+ }
+ BaseAdd(index, value);
+ }
+ }
+
+ public string[] AllKeys => StringUtil.ObjectArrayToStringArray(BaseGetAllKeys());
+
+ public void Add(NameValueConfigurationElement nameValue)
+ {
+ BaseAdd(nameValue);
+ }
+
+ public void Remove(NameValueConfigurationElement nameValue)
+ {
+ if (BaseIndexOf(nameValue) >= 0)
+ BaseRemove(nameValue.Name);
+ }
+
+ public void Remove(string name)
+ {
+ BaseRemove(name);
+ }
+
+ public void Clear()
+ {
+ BaseClear();
+ }
+
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new NameValueConfigurationElement();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((NameValueConfigurationElement)element).Name;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/NameValueConfigurationElement.cs b/src/System.Configuration/src/System/Configuration/NameValueConfigurationElement.cs
new file mode 100644
index 0000000000..e958ffb7a0
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/NameValueConfigurationElement.cs
@@ -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.
+
+namespace System.Configuration
+{
+ public sealed class NameValueConfigurationElement : ConfigurationElement
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ private static readonly ConfigurationProperty s_propName =
+ new ConfigurationProperty("name", typeof(string), string.Empty, ConfigurationPropertyOptions.IsKey);
+
+ private static readonly ConfigurationProperty s_propValue =
+ new ConfigurationProperty("value", typeof(string), string.Empty, ConfigurationPropertyOptions.None);
+
+ static NameValueConfigurationElement()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection { s_propName, s_propValue };
+ }
+
+ internal NameValueConfigurationElement() { }
+
+ public NameValueConfigurationElement(string name, string value)
+ {
+ base[s_propName] = name;
+ base[s_propValue] = value;
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ [ConfigurationProperty("name", IsKey = true, DefaultValue = "")]
+ public string Name => (string)base[s_propName];
+
+ [ConfigurationProperty("value", DefaultValue = "")]
+ public string Value
+ {
+ get { return (string)base[s_propValue]; }
+ set { base[s_propValue] = value; }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Net.HttpListener/src/System/Net/NTAuthentication.cs b/src/System.Configuration/src/System/Configuration/NamespaceChange.cs
index ed464c2f4f..9a6fa8cb0d 100644
--- a/src/System.Net.HttpListener/src/System/Net/NTAuthentication.cs
+++ b/src/System.Configuration/src/System/Configuration/NamespaceChange.cs
@@ -2,12 +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.
-namespace System.Net
+namespace System.Configuration
{
- internal class NTAuthentication
+ internal enum NamespaceChange
{
- internal void CloseContext()
- {
- }
+ None = 0,
+ Add = 1,
+ Remove = 2,
}
-}
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/OverrideMode.cs b/src/System.Configuration/src/System/Configuration/OverrideMode.cs
new file mode 100644
index 0000000000..65ccceaf5e
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/OverrideMode.cs
@@ -0,0 +1,23 @@
+// 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.Configuration
+{
+ // This is the public type of the override mode enum visible to the API users
+ // The override mode is an attribute of a <location> tag and controls if the sections inside this tag
+ // can be defined in child web.config files
+ public enum OverrideMode
+ {
+ // Default ( aka Indiferent ) - When specified on a location tag means the location tag will not alter
+ // the locking mode ( locked or unlocked ). Rather, the locking mode should be picked
+ // from the <location> tag with the closest parent path in the current file, or the parent file if no such location in the current one,
+ // or the default for the specific section ( section.OverrideModeDefault )
+ Inherit = 0,
+ // Allow overriding in child config files. I.e. unlock the settings for overridiing
+ Allow = 1,
+ // Deny overriding of the settings defined in the <location> tag. It is an error for the sections in the <location> tag
+ // to appear in a child config file. It is not an error for them to appear in another <lcoation> tag in the current file
+ Deny = 2,
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/OverrideModeSetting.cs b/src/System.Configuration/src/System/Configuration/OverrideModeSetting.cs
new file mode 100644
index 0000000000..792357c8bc
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/OverrideModeSetting.cs
@@ -0,0 +1,353 @@
+// 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.Globalization;
+
+namespace System.Configuration
+{
+ // This is a class that abstracts the usage of the override mode setting
+ internal struct OverrideModeSetting
+ {
+ private const byte ApiDefinedLegacy = 0x10; // allowOverride was set through the API
+ private const byte ApiDefinedNewMode = 0x20; // overrideMode was set through the API
+
+ // allowOverride or overrideMode was set through the API
+ private const byte ApiDefinedAny = ApiDefinedLegacy | ApiDefinedNewMode;
+ private const byte XmlDefinedLegacy = 0x40; // allowOverride was defined in the XML
+ private const byte XmlDefinedNewMode = 0x80; // overrideMode was defined in the XML
+
+ // overrideMode or allowOverride was defined in the XML
+ private const byte XmlDefinedAny = XmlDefinedLegacy | XmlDefinedNewMode;
+
+ private const byte ModeMask = 0x0f; // logical AND this with the current value to get the mode part only
+
+ private byte _mode;
+
+ internal static OverrideModeSetting s_sectionDefault;
+ internal static OverrideModeSetting s_locationDefault;
+
+ static OverrideModeSetting()
+ {
+ // Default for section is ALLOW
+ s_sectionDefault = new OverrideModeSetting { _mode = (byte)OverrideMode.Allow };
+
+ // Default for location tags is INHERIT. Note that we do not make the value as existant in the XML or specified by the API
+ s_locationDefault = new OverrideModeSetting { _mode = (byte)OverrideMode.Inherit };
+ }
+
+ internal static OverrideModeSetting CreateFromXmlReadValue(bool allowOverride)
+ {
+ // Create a mode from the old "allowOverride" attribute in the xml
+
+ // The conversion is true -> OverrideMode.Inherit
+ // The conversion is false -> OverrideMode.Deny
+ // This is consistent with Whidbey where true means true unless there is a false somewhere above
+ OverrideModeSetting result = new OverrideModeSetting();
+
+ result.SetMode(allowOverride ? OverrideMode.Inherit : OverrideMode.Deny);
+ result._mode |= XmlDefinedLegacy;
+
+ return result;
+ }
+
+ internal static OverrideModeSetting CreateFromXmlReadValue(OverrideMode mode)
+ {
+ OverrideModeSetting result = new OverrideModeSetting();
+
+ result.SetMode(mode);
+ result._mode |= XmlDefinedNewMode;
+
+ return result;
+ }
+
+ internal static OverrideMode ParseOverrideModeXmlValue(string value, XmlUtil xmlUtil)
+ {
+ // 'value' is the string representation of OverrideMode enum
+ // Try to parse the string to the enum and generate errors if not possible
+
+ switch (value)
+ {
+ case BaseConfigurationRecord.OverrideModeInherit:
+ return OverrideMode.Inherit;
+
+ case BaseConfigurationRecord.OverrideModeAllow:
+ return OverrideMode.Allow;
+
+ case BaseConfigurationRecord.OverrideModeDeny:
+ return OverrideMode.Deny;
+
+ default:
+ throw new ConfigurationErrorsException(
+ SR.Config_section_override_mode_attribute_invalid,
+ xmlUtil);
+ }
+ }
+
+ internal static bool CanUseSameLocationTag(OverrideModeSetting x, OverrideModeSetting y)
+ {
+ // This function tells if the two OverrideModeSettings are compatible enough to be used in only one location tag
+ // or each of them should go to a separate one
+
+ // The rules here are ( in order of importance )
+ // 1. The effective mode is the same ( we will use only the new OverrideMode to compare )
+ // 2. When the mode was changed( i.e. API change ) - both must be changed the same way ( i.e. using either allowOverride or OverrideMode )
+ // 3. When mode was not changed the XML - they must've been the same in the xml ( i.e. allowOverride specified on both, or overrideMode or neither of them )
+
+ bool result = x.OverrideMode == y.OverrideMode;
+ if (!result) return false;
+
+ // Check for an API change for each setting first
+ // If one mode was set through the API - the other mode has to be set in the same way through the API or has to be using the same type in the xml
+
+ // Handle case where "x" was API modified
+ if ((x._mode & ApiDefinedAny) != 0) result = IsMatchingApiChangedLocationTag(x, y);
+ // Handle case where "y" was API modified
+ else
+ {
+ if ((y._mode & ApiDefinedAny) != 0) result = IsMatchingApiChangedLocationTag(y, x);
+ // Handle case where neither "x" nor "y" was API modified
+ else
+ {
+ // If one of the settings was XML defined - they are a match only if both were XML defined in the same way
+ if (((x._mode & XmlDefinedAny) != 0) ||
+ ((y._mode & XmlDefinedAny) != 0))
+ result = (x._mode & XmlDefinedAny) == (y._mode & XmlDefinedAny);
+
+ // Neither "x" nor "y" was XML defined - they are a match since they can both go
+ // to a default <location> with no explicit mode setting written out
+ }
+ }
+
+ return result;
+ }
+
+ private static bool IsMatchingApiChangedLocationTag(OverrideModeSetting x, OverrideModeSetting y)
+ {
+ // x must be a changed through the API setting
+ // Returns true if x and y can share the same location tag
+
+ Debug.Assert((x._mode & ApiDefinedAny) != 0);
+
+ bool result = false;
+
+ if ((y._mode & ApiDefinedAny) != 0)
+ {
+ // If "y" was modified through the API as well - the modified setting must be the same ( i.e. allowOvverride or overrideMode must be modified in both settings )
+ result = (x._mode & ApiDefinedAny) == (y._mode & ApiDefinedAny);
+ }
+ else
+ {
+ // "y" was not API modified - they are still a match if "y" was a XML setting from the same mode
+ if ((y._mode & XmlDefinedAny) != 0)
+ {
+ // "x" was API changed in Legacy and "y" was XML defined in Legacy
+ result = (((x._mode & ApiDefinedLegacy) != 0) && ((y._mode & XmlDefinedLegacy) != 0)) ||
+ // "x" was API changed in New and "y" was XML defined in New
+ (((x._mode & ApiDefinedNewMode) != 0) && ((y._mode & XmlDefinedNewMode) != 0));
+ }
+ // "y" was not API or XML modified - since "x" was API modified - they are not a match ( i.e. "y" should go to an <location> with no explicit mode written out )
+ }
+
+ return result;
+ }
+
+ internal bool IsDefaultForSection
+ {
+ get
+ {
+ // Returns true if the current value of the overrideMode setting is the default one on a section declaration
+
+ // The current default value for a section's overrideMode ( i.e. overrideModeDefault ) is Allow ( see CreateDefaultForSection )
+ // It would've been nice not to repeat that rule here but since OverrideMode.Inherited means the same in this specific context we have to
+ // I.e. the default for a section is both Allow and Inherited. In this case they mean the same
+
+ OverrideMode mode = OverrideMode;
+
+ // Return true if mode is Allow or Inherit
+ return (mode == OverrideMode.Allow) || (mode == OverrideMode.Inherit);
+ }
+ }
+
+ internal bool IsDefaultForLocationTag
+ {
+ get
+ {
+ // Returns true if the current setting is the same as the default value for a location tag
+ // Note that if the setting was an API modified or XmlDefined it is not a default since it
+ // cannot go to the default <location> tag which does not explicitlly specify a mode
+
+ OverrideModeSetting defaultSetting = s_locationDefault;
+
+ return (defaultSetting.OverrideMode == OverrideMode) &&
+ ((_mode & ApiDefinedAny) == 0) &&
+ ((_mode & XmlDefinedAny) == 0);
+ }
+ }
+
+ internal bool IsLocked => OverrideMode == OverrideMode.Deny;
+
+ internal string LocationTagXmlString
+ {
+ get
+ {
+ // Returns the string for this setting which is to be written in the xml <location> tag
+
+ string result = string.Empty;
+
+ bool needToWrite = false;
+ bool useLegacy = false;
+
+ // If there was an API change - it has highest priority
+ if ((_mode & ApiDefinedAny) != 0)
+ {
+ // Whichever was changed by the API dictates what is to be written
+ useLegacy = (_mode & ApiDefinedLegacy) != 0;
+ needToWrite = true;
+
+ Debug.Assert(useLegacy || ((_mode & ApiDefinedNewMode) != 0));
+ }
+ // It wasn't changed through the API - check if it was read originally from the XML
+ else
+ {
+ if ((_mode & XmlDefinedAny) != 0)
+ {
+ // Whatever was defined in the XML is to be written out
+
+ useLegacy = (_mode & XmlDefinedLegacy) != 0;
+ needToWrite = true;
+
+ Debug.Assert(useLegacy || ((_mode & XmlDefinedNewMode) != 0));
+ }
+ }
+
+ if (needToWrite)
+ {
+ string value;
+ string attrib;
+
+ if (useLegacy)
+ {
+ // Legacy - allowOverride
+ attrib = BaseConfigurationRecord.LocationAllowOverrideAttribute;
+ value = AllowOverride
+ ? BaseConfigurationRecord.KeywordTrue
+ : BaseConfigurationRecord.KeywordFalse;
+ }
+ else
+ {
+ attrib = BaseConfigurationRecord.LocationOverrideModeAttribute;
+ value = OverrideModeXmlValue;
+ }
+
+ result = string.Format(CultureInfo.InvariantCulture,
+ BaseConfigurationRecord.KeywordLocationOverrideModeString, attrib, value);
+ }
+
+ return result;
+ }
+ }
+
+ internal string OverrideModeXmlValue
+ {
+ get
+ {
+ // Returns the xml (string) value of the current setting for override mode
+ switch (OverrideMode)
+ {
+ case OverrideMode.Inherit:
+ return BaseConfigurationRecord.OverrideModeInherit;
+ case OverrideMode.Allow:
+ return BaseConfigurationRecord.OverrideModeAllow;
+ case OverrideMode.Deny:
+ return BaseConfigurationRecord.OverrideModeDeny;
+ default:
+ Debug.Fail("Missing xml keyword for OverrideMode enum value");
+ break;
+ }
+
+ return null;
+ }
+ }
+
+ // Use this method to change only the value of the setting when not done through the public API
+ internal void ChangeModeInternal(OverrideMode mode)
+ {
+ SetMode(mode);
+ }
+
+ // Properties to enable external chnages to the mode.
+ // Note that those changes will be tracked as made by the public API
+ // There shouldn't be a reason for those to be used except in this specific case
+ internal OverrideMode OverrideMode
+ {
+ get { return (OverrideMode)(_mode & ModeMask); }
+ set
+ {
+ // Note that changing the mode through the API ( which is the purpose of this setter )
+ // overrides the setting in the XML ( if any )
+ // and hence we dont keep a track of it anymore
+
+ // Error condition: We do not allow changes to the mode through both AllowOverride and OverrideMode
+ // If one was changed first we require that API users stick with it
+ VerifyConsistentChangeModel(ApiDefinedNewMode);
+
+ SetMode(value);
+ _mode |= ApiDefinedNewMode;
+ }
+ }
+
+ internal bool AllowOverride
+ {
+ get
+ {
+ bool result = true;
+
+ switch (OverrideMode)
+ {
+ case OverrideMode.Inherit:
+ case OverrideMode.Allow:
+ break;
+ case OverrideMode.Deny:
+ result = false;
+ break;
+ default:
+ Debug.Assert(false, "Unrecognized OverrideMode");
+ break;
+ }
+
+ return result;
+ }
+ set
+ {
+ // Note that changing the mode through the API ( which is the purpose of this setter )
+ // overrides the setting in the XML ( if any )
+ // and hence we dont keep a track of it anymore
+
+ // Error condition: We do not allow changes to the mode through both AllowOverride and OverrideMode
+ // If one was changed first we require that API users stick with it
+ VerifyConsistentChangeModel(ApiDefinedLegacy);
+
+ SetMode(value ? OverrideMode.Inherit : OverrideMode.Deny);
+ _mode |= ApiDefinedLegacy;
+ }
+ }
+
+ private void SetMode(OverrideMode mode)
+ {
+ _mode = (byte)mode;
+ }
+
+ private void VerifyConsistentChangeModel(byte required)
+ {
+ // The required API change model ( i.e. was allowOverride used or OverrideMode ) should be consistent
+ // I.e. its not possible to change both on the same OverrideModeSetting object
+ byte current = (byte)(_mode & ApiDefinedAny);
+
+ // Shows whats the current setting: 0 ( none ), ApiDefinedLegacy or ApiDefinedNew
+ if ((current != 0) && (current != required))
+ throw new ConfigurationErrorsException(SR.Cannot_change_both_AllowOverride_and_OverrideMode);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/PositiveTimeSpanValidator.cs b/src/System.Configuration/src/System/Configuration/PositiveTimeSpanValidator.cs
new file mode 100644
index 0000000000..a92bc93390
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/PositiveTimeSpanValidator.cs
@@ -0,0 +1,22 @@
+// 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.Configuration
+{
+ public class PositiveTimeSpanValidator : ConfigurationValidatorBase
+ {
+ public override bool CanValidate(Type type)
+ {
+ return type == typeof(TimeSpan);
+ }
+
+ public override void Validate(object value)
+ {
+ if (value == null) throw new ArgumentNullException(nameof(value));
+
+ if ((TimeSpan)value <= TimeSpan.Zero)
+ throw new ArgumentException(SR.Validator_timespan_value_must_be_positive);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/PositiveTimeSpanValidatorAttribute.cs b/src/System.Configuration/src/System/Configuration/PositiveTimeSpanValidatorAttribute.cs
new file mode 100644
index 0000000000..0fa51568eb
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/PositiveTimeSpanValidatorAttribute.cs
@@ -0,0 +1,12 @@
+// 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.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class PositiveTimeSpanValidatorAttribute : ConfigurationValidatorAttribute
+ {
+ public override ConfigurationValidatorBase ValidatorInstance => new PositiveTimeSpanValidator();
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/PrivilegedConfigurationManager.cs b/src/System.Configuration/src/System/Configuration/PrivilegedConfigurationManager.cs
new file mode 100644
index 0000000000..0bd3bf9edb
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/PrivilegedConfigurationManager.cs
@@ -0,0 +1,16 @@
+// 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.Configuration
+{
+ internal static class PrivilegedConfigurationManager
+ {
+ internal static ConnectionStringSettingsCollection ConnectionStrings => ConfigurationManager.ConnectionStrings;
+
+ internal static object GetSection(string sectionName)
+ {
+ return ConfigurationManager.GetSection(sectionName);
+ }
+ }
+}
diff --git a/src/System.Configuration/src/System/Configuration/PropertyInformation.cs b/src/System.Configuration/src/System/Configuration/PropertyInformation.cs
new file mode 100644
index 0000000000..fd45344b80
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/PropertyInformation.cs
@@ -0,0 +1,95 @@
+// 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.ComponentModel;
+
+namespace System.Configuration
+{
+ public sealed class PropertyInformation
+ {
+ private const string LockAll = "*";
+ private ConfigurationProperty _prop;
+
+ private readonly ConfigurationElement _thisElement;
+
+ internal PropertyInformation(ConfigurationElement thisElement, string propertyName)
+ {
+ Name = propertyName;
+ _thisElement = thisElement;
+ }
+
+ private ConfigurationProperty Prop => _prop ?? (_prop = _thisElement.Properties[Name]);
+
+
+ public string Name { get; }
+
+
+ internal string ProvidedName => Prop.ProvidedName;
+
+
+ public object Value
+ {
+ get { return _thisElement[Name]; }
+ set { _thisElement[Name] = value; }
+ }
+
+ public object DefaultValue => Prop.DefaultValue;
+
+ public PropertyValueOrigin ValueOrigin
+ {
+ get
+ {
+ if (_thisElement.Values[Name] == null) return PropertyValueOrigin.Default;
+ return _thisElement.Values.IsInherited(Name) ? PropertyValueOrigin.Inherited : PropertyValueOrigin.SetHere;
+ }
+ }
+
+ public bool IsModified => _thisElement.Values[Name] != null && _thisElement.Values.IsModified(Name);
+
+ public bool IsKey => Prop.IsKey;
+
+ public bool IsRequired => Prop.IsRequired;
+
+ public bool IsLocked =>
+ ((_thisElement.LockedAllExceptAttributesList != null) &&
+ !_thisElement.LockedAllExceptAttributesList.DefinedInParent(Name)) ||
+ ((_thisElement.LockedAttributesList != null) &&
+ (_thisElement.LockedAttributesList.DefinedInParent(Name) ||
+ _thisElement.LockedAttributesList.DefinedInParent(LockAll))) ||
+ (((_thisElement.ItemLocked & ConfigurationValueFlags.Locked) != 0) &&
+ ((_thisElement.ItemLocked & ConfigurationValueFlags.Inherited) != 0));
+
+
+ public string Source
+ {
+ get
+ {
+ PropertySourceInfo psi = _thisElement.Values.GetSourceInfo(Name) ??
+ _thisElement.Values.GetSourceInfo(string.Empty);
+ return psi == null ? string.Empty : psi.FileName;
+ }
+ }
+
+ /// <summary>
+ /// Line number or 0 if there is no source.
+ /// </summary>
+ public int LineNumber
+ {
+ get
+ {
+ PropertySourceInfo psi = _thisElement.Values.GetSourceInfo(Name) ??
+ _thisElement.Values.GetSourceInfo(string.Empty);
+ return psi?.LineNumber ?? 0;
+ }
+ }
+
+ public Type Type => Prop.Type;
+
+ public ConfigurationValidatorBase Validator => Prop.Validator;
+
+ public TypeConverter Converter => Prop.Converter;
+
+ public string Description => Prop.Description;
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/PropertyInformationCollection.cs b/src/System.Configuration/src/System/Configuration/PropertyInformationCollection.cs
new file mode 100644
index 0000000000..9ba20a1245
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/PropertyInformationCollection.cs
@@ -0,0 +1,65 @@
+// 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.Specialized;
+using System.Collections;
+using System.Runtime.Serialization;
+
+namespace System.Configuration
+{
+ [Serializable]
+ public sealed class PropertyInformationCollection : NameObjectCollectionBase
+ {
+ internal PropertyInformationCollection(ConfigurationElement thisElement) : base(StringComparer.Ordinal)
+ {
+ ConfigurationElement thisElement1 = thisElement;
+ foreach (ConfigurationProperty prop in thisElement1.Properties)
+ if (prop.Name != thisElement1.ElementTagName)
+ BaseAdd(prop.Name, new PropertyInformation(thisElement, prop.Name));
+ IsReadOnly = true;
+ }
+
+ private PropertyInformationCollection(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ : base(serializationInfo, streamingContext)
+ {
+ }
+
+ public PropertyInformation this[string propertyName]
+ {
+ get
+ {
+ PropertyInformation result = (PropertyInformation)BaseGet(propertyName);
+
+ // check for default collection name
+ if (result == null)
+ {
+ PropertyInformation defaultColl =
+ (PropertyInformation)BaseGet(ConfigurationProperty.s_defaultCollectionPropertyName);
+
+ if ((defaultColl != null) && (defaultColl.ProvidedName == propertyName)) result = defaultColl;
+ }
+ return result;
+ }
+ }
+
+ internal PropertyInformation this[int index] => (PropertyInformation)BaseGet(BaseGetKey(index));
+
+
+ public void CopyTo(PropertyInformation[] array, int index)
+ {
+ if (array == null) throw new ArgumentNullException(nameof(array));
+
+ if (array.Length < Count + index) throw new ArgumentOutOfRangeException(nameof(index));
+
+ foreach (PropertyInformation pi in this) array[index++] = pi;
+ }
+
+
+ public override IEnumerator GetEnumerator()
+ {
+ int c = Count;
+ for (int i = 0; i < c; i++) yield return this[i];
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/PropertySourceInfo.cs b/src/System.Configuration/src/System/Configuration/PropertySourceInfo.cs
new file mode 100644
index 0000000000..db249b7d50
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/PropertySourceInfo.cs
@@ -0,0 +1,36 @@
+// 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.Configuration.Internal;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal class PropertySourceInfo
+ {
+ internal PropertySourceInfo(XmlReader reader)
+ {
+ FileName = GetFilename(reader);
+ LineNumber = GetLineNumber(reader);
+ }
+
+ internal string FileName { get; }
+
+ internal int LineNumber { get; }
+
+ private string GetFilename(XmlReader reader)
+ {
+ IConfigErrorInfo err = reader as IConfigErrorInfo;
+
+ return err != null ? err.Filename : "";
+ }
+
+ private int GetLineNumber(XmlReader reader)
+ {
+ IConfigErrorInfo err = reader as IConfigErrorInfo;
+
+ return err?.LineNumber ?? 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/PropertyValueOrigin.cs b/src/System.Configuration/src/System/Configuration/PropertyValueOrigin.cs
new file mode 100644
index 0000000000..4decf7f4bb
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/PropertyValueOrigin.cs
@@ -0,0 +1,13 @@
+// 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.Configuration
+{
+ public enum PropertyValueOrigin
+ {
+ Default = 0, // Default is retrieved
+ Inherited = 1, // It is inherited
+ SetHere = 2 // It was set here
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ProtectedConfiguration.cs b/src/System.Configuration/src/System/Configuration/ProtectedConfiguration.cs
new file mode 100644
index 0000000000..86a5b62202
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ProtectedConfiguration.cs
@@ -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.
+
+namespace System.Configuration
+{
+ public static class ProtectedConfiguration
+ {
+ public static ProtectedConfigurationProviderCollection Providers
+ {
+ get
+ {
+ ProtectedConfigurationSection config =
+ PrivilegedConfigurationManager.GetSection(
+ BaseConfigurationRecord.ReservedSectionProtectedConfiguration) as
+ ProtectedConfigurationSection;
+ return config == null ? new ProtectedConfigurationProviderCollection() : config.GetAllProviders();
+ }
+ }
+
+ public const string RsaProviderName = "RsaProtectedConfigurationProvider";
+ public const string DataProtectionProviderName = "DataProtectionConfigurationProvider";
+ public const string ProtectedDataSectionName = BaseConfigurationRecord.ReservedSectionProtectedConfiguration;
+
+ public static string DefaultProvider
+ {
+ get
+ {
+ ProtectedConfigurationSection config =
+ PrivilegedConfigurationManager.GetSection(
+ BaseConfigurationRecord.ReservedSectionProtectedConfiguration) as
+ ProtectedConfigurationSection;
+ return config != null ? config.DefaultProvider : "";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ProtectedConfigurationProvider.cs b/src/System.Configuration/src/System/Configuration/ProtectedConfigurationProvider.cs
new file mode 100644
index 0000000000..f9c6263ed0
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ProtectedConfigurationProvider.cs
@@ -0,0 +1,15 @@
+// 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.Configuration.Provider;
+using System.Xml;
+
+namespace System.Configuration
+{
+ public abstract class ProtectedConfigurationProvider : ProviderBase
+ {
+ public abstract XmlNode Encrypt(XmlNode node);
+ public abstract XmlNode Decrypt(XmlNode encryptedNode);
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ProtectedConfigurationProviderCollection.cs b/src/System.Configuration/src/System/Configuration/ProtectedConfigurationProviderCollection.cs
new file mode 100644
index 0000000000..23cb626e7e
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ProtectedConfigurationProviderCollection.cs
@@ -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.Configuration.Provider;
+
+namespace System.Configuration
+{
+ public class ProtectedConfigurationProviderCollection : ProviderCollection
+ {
+ public new ProtectedConfigurationProvider this[string name] => (ProtectedConfigurationProvider)base[name];
+
+ public override void Add(ProviderBase provider)
+ {
+ if (provider == null)
+ throw new ArgumentNullException(nameof(provider));
+
+ if (!(provider is ProtectedConfigurationProvider))
+ {
+ throw new ArgumentException(
+ string.Format(SR.Config_provider_must_implement_type,
+ typeof(ProtectedConfigurationProvider).ToString()), nameof(provider));
+ }
+
+ base.Add(provider);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ProtectedConfigurationSection.cs b/src/System.Configuration/src/System/Configuration/ProtectedConfigurationSection.cs
new file mode 100644
index 0000000000..068de115d5
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ProtectedConfigurationSection.cs
@@ -0,0 +1,117 @@
+// 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.Specialized;
+using System.Globalization;
+using System.Xml;
+
+namespace System.Configuration
+{
+ public sealed class ProtectedConfigurationSection : ConfigurationSection
+ {
+ private const string EncryptedSectionTemplate = "<{0} {1}=\"{2}\"> {3} </{0}>";
+
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ private static readonly ConfigurationProperty s_propProviders =
+ new ConfigurationProperty("providers",
+ typeof(ProtectedProviderSettings),
+ new ProtectedProviderSettings(),
+ ConfigurationPropertyOptions.None);
+
+ private static readonly ConfigurationProperty s_propDefaultProvider =
+ new ConfigurationProperty("defaultProvider",
+ type: typeof(string),
+ defaultValue: "RsaProtectedConfigurationProvider",
+ typeConverter: null,
+ validator: ConfigurationProperty.s_nonEmptyStringValidator,
+ options: ConfigurationPropertyOptions.None);
+
+ static ProtectedConfigurationSection()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection { s_propProviders, s_propDefaultProvider };
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ private ProtectedProviderSettings ProtectedProviders => (ProtectedProviderSettings)base[s_propProviders];
+
+ [ConfigurationProperty("providers")]
+ public ProviderSettingsCollection Providers => ProtectedProviders.Providers;
+
+ [ConfigurationProperty("defaultProvider", DefaultValue = "RsaProtectedConfigurationProvider")]
+ public string DefaultProvider
+ {
+ get { return (string)base[s_propDefaultProvider]; }
+ set { base[s_propDefaultProvider] = value; }
+ }
+
+ internal ProtectedConfigurationProvider GetProviderFromName(string providerName)
+ {
+ ProviderSettings ps = Providers[providerName];
+
+ if (ps == null)
+ throw new Exception(string.Format(SR.ProtectedConfigurationProvider_not_found, providerName));
+
+ return InstantiateProvider(ps);
+ }
+
+ internal ProtectedConfigurationProviderCollection GetAllProviders()
+ {
+ ProtectedConfigurationProviderCollection coll = new ProtectedConfigurationProviderCollection();
+ foreach (ProviderSettings ps in Providers)
+ coll.Add(InstantiateProvider(ps));
+ return coll;
+ }
+
+ private ProtectedConfigurationProvider CreateAndInitializeProviderWithAssert(Type t, ProviderSettings pn)
+ {
+ ProtectedConfigurationProvider provider =
+ (ProtectedConfigurationProvider)TypeUtil.CreateInstance(t);
+ NameValueCollection pars = pn.Parameters;
+ NameValueCollection cloneParams = new NameValueCollection(pars.Count);
+
+ foreach (string key in pars) cloneParams[key] = pars[key];
+
+ provider.Initialize(pn.Name, cloneParams);
+ return provider;
+ }
+
+ private ProtectedConfigurationProvider InstantiateProvider(ProviderSettings pn)
+ {
+ Type t = TypeUtil.GetType(pn.Type, true);
+ if (!typeof(ProtectedConfigurationProvider).IsAssignableFrom(t))
+ throw new Exception(SR.WrongType_of_Protected_provider);
+
+ return CreateAndInitializeProviderWithAssert(t, pn);
+ }
+
+ internal static string DecryptSection(string encryptedXml, ProtectedConfigurationProvider provider)
+ {
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(encryptedXml);
+ XmlNode resultNode = provider.Decrypt(doc.DocumentElement);
+ return resultNode.OuterXml;
+ }
+
+ internal static string FormatEncryptedSection(string encryptedXml, string sectionName, string providerName)
+ {
+ return string.Format(CultureInfo.InvariantCulture, EncryptedSectionTemplate,
+ sectionName, // The section to encrypt
+ BaseConfigurationRecord.ProtectionProviderAttibute, // protectionProvider keyword
+ providerName, // The provider name
+ encryptedXml // the encrypted xml
+ );
+ }
+
+ internal static string EncryptSection(string clearXml, ProtectedConfigurationProvider provider)
+ {
+ XmlDocument xmlDocument = new XmlDocument { PreserveWhitespace = true };
+ xmlDocument.LoadXml(clearXml);
+ XmlNode encNode = provider.Encrypt(xmlDocument.DocumentElement);
+ return encNode.OuterXml;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ProtectedProviderSettings.cs b/src/System.Configuration/src/System/Configuration/ProtectedProviderSettings.cs
new file mode 100644
index 0000000000..bc409f584a
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ProtectedProviderSettings.cs
@@ -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.
+
+namespace System.Configuration
+{
+ public class ProtectedProviderSettings : ConfigurationElement
+ {
+ private readonly ConfigurationProperty _propProviders =
+ new ConfigurationProperty(null, typeof(ProviderSettingsCollection), null,
+ ConfigurationPropertyOptions.IsDefaultCollection);
+
+ private readonly ConfigurationPropertyCollection _properties;
+
+ public ProtectedProviderSettings()
+ {
+ // Property initialization
+ _properties = new ConfigurationPropertyCollection { _propProviders };
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties => _properties;
+
+
+ [ConfigurationProperty("", IsDefaultCollection = true,
+ Options = ConfigurationPropertyOptions.IsDefaultCollection)]
+ public ProviderSettingsCollection Providers => (ProviderSettingsCollection)base[_propProviders];
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Provider/ProviderBase.cs b/src/System.Configuration/src/System/Configuration/Provider/ProviderBase.cs
new file mode 100644
index 0000000000..d9434230cc
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Provider/ProviderBase.cs
@@ -0,0 +1,42 @@
+// 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.Specialized;
+
+namespace System.Configuration.Provider
+{
+ public abstract class ProviderBase
+ {
+ private string _description;
+ private bool _initialized;
+
+ private string _name;
+
+ public virtual string Name => _name;
+
+ public virtual string Description => string.IsNullOrEmpty(_description) ? Name : _description;
+
+ public virtual void Initialize(string name, NameValueCollection config)
+ {
+ lock (this)
+ {
+ if (_initialized)
+ throw new InvalidOperationException(SR.Provider_Already_Initialized);
+ _initialized = true;
+ }
+
+ if (name == null)
+ throw new ArgumentNullException(nameof(name));
+ if (name.Length == 0)
+ throw new ArgumentException(SR.Config_provider_name_null_or_empty, nameof(name));
+
+ _name = name;
+ if (config != null)
+ {
+ _description = config["description"];
+ config.Remove("description");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Provider/ProviderCollection.cs b/src/System.Configuration/src/System/Configuration/Provider/ProviderCollection.cs
new file mode 100644
index 0000000000..75808d487f
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Provider/ProviderCollection.cs
@@ -0,0 +1,77 @@
+// 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.Configuration.Provider
+{
+ public class ProviderCollection : ICollection
+ {
+ private readonly Hashtable _hashtable;
+ private bool _readOnly;
+
+ public ProviderCollection()
+ {
+ _hashtable = new Hashtable(10, StringComparer.OrdinalIgnoreCase);
+ }
+
+ public ProviderBase this[string name] => _hashtable[name] as ProviderBase;
+
+ public IEnumerator GetEnumerator()
+ {
+ return _hashtable.Values.GetEnumerator();
+ }
+
+ public int Count => _hashtable.Count;
+
+ public bool IsSynchronized => false;
+
+ public object SyncRoot => this;
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ _hashtable.Values.CopyTo(array, index);
+ }
+
+ public virtual void Add(ProviderBase provider)
+ {
+ if (_readOnly)
+ throw new NotSupportedException(SR.CollectionReadOnly);
+
+ if (provider == null)
+ throw new ArgumentNullException(nameof(provider));
+
+ if ((provider.Name == null) || (provider.Name.Length < 1))
+ throw new ArgumentException(SR.Config_provider_name_null_or_empty);
+
+ _hashtable.Add(provider.Name, provider);
+ }
+
+ public void Remove(string name)
+ {
+ if (_readOnly)
+ throw new NotSupportedException(SR.CollectionReadOnly);
+ _hashtable.Remove(name);
+ }
+
+ public void SetReadOnly()
+ {
+ if (_readOnly)
+ return;
+ _readOnly = true;
+ }
+
+ public void Clear()
+ {
+ if (_readOnly)
+ throw new NotSupportedException(SR.CollectionReadOnly);
+ _hashtable.Clear();
+ }
+
+ public void CopyTo(ProviderBase[] array, int index)
+ {
+ ((ICollection)this).CopyTo(array, index);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Provider/ProviderException.cs b/src/System.Configuration/src/System/Configuration/Provider/ProviderException.cs
new file mode 100644
index 0000000000..e595fe7499
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Provider/ProviderException.cs
@@ -0,0 +1,26 @@
+// 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.Serialization;
+
+namespace System.Configuration.Provider
+{
+ [Serializable]
+ public class ProviderException : Exception
+ {
+ public ProviderException() { }
+
+ public ProviderException(string message)
+ : base(message)
+ { }
+
+ public ProviderException(string message, Exception innerException)
+ : base(message, innerException)
+ { }
+
+ protected ProviderException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ProviderSettings.cs b/src/System.Configuration/src/System/Configuration/ProviderSettings.cs
new file mode 100644
index 0000000000..9ad2a20805
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ProviderSettings.cs
@@ -0,0 +1,190 @@
+// 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.Collections.Specialized;
+
+namespace System.Configuration
+{
+ public sealed class ProviderSettings : ConfigurationElement
+ {
+ private readonly ConfigurationPropertyCollection _properties;
+
+ private readonly ConfigurationProperty _propName =
+ new ConfigurationProperty("name",
+ typeof(string),
+ null, // no reasonable default
+ null, // use default converter
+ ConfigurationProperty.s_nonEmptyStringValidator,
+ ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);
+
+ private readonly ConfigurationProperty _propType = new ConfigurationProperty("type", typeof(string), "",
+ ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsTypeStringTransformationRequired);
+
+ private NameValueCollection _propertyNameCollection;
+
+ public ProviderSettings()
+ {
+ _properties = new ConfigurationPropertyCollection { _propName, _propType };
+ _propertyNameCollection = null;
+ }
+
+ public ProviderSettings(string name, string type) : this()
+ {
+ Name = name;
+ Type = type;
+ }
+
+ protected internal override ConfigurationPropertyCollection Properties
+ {
+ get
+ {
+ UpdatePropertyCollection();
+ return _properties;
+ }
+ }
+
+ [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
+ public string Name
+ {
+ get { return (string)base[_propName]; }
+ set { base[_propName] = value; }
+ }
+
+ [ConfigurationProperty("type", IsRequired = true)]
+ public string Type
+ {
+ get { return (string)base[_propType]; }
+ set { base[_propType] = value; }
+ }
+
+ public NameValueCollection Parameters
+ {
+ get
+ {
+ if (_propertyNameCollection != null) return _propertyNameCollection;
+
+ lock (this)
+ {
+ _propertyNameCollection = new NameValueCollection(StringComparer.Ordinal);
+
+ foreach (object de in _properties)
+ {
+ ConfigurationProperty prop = (ConfigurationProperty)de;
+ if ((prop.Name != "name") && (prop.Name != "type"))
+ _propertyNameCollection.Add(prop.Name, (string)base[prop]);
+ }
+ }
+ return _propertyNameCollection;
+ }
+ }
+
+ protected internal override void Unmerge(ConfigurationElement sourceElement,
+ ConfigurationElement parentElement,
+ ConfigurationSaveMode saveMode)
+ {
+ ProviderSettings parentProviders = parentElement as ProviderSettings;
+ parentProviders?.UpdatePropertyCollection(); // before reseting make sure the bag is filled in
+
+ ProviderSettings sourceProviders = sourceElement as ProviderSettings;
+ sourceProviders?.UpdatePropertyCollection(); // before reseting make sure the bag is filled in
+
+ base.Unmerge(sourceElement, parentElement, saveMode);
+ UpdatePropertyCollection();
+ }
+
+ protected internal override void Reset(ConfigurationElement parentElement)
+ {
+ ProviderSettings parentProviders = parentElement as ProviderSettings;
+ parentProviders?.UpdatePropertyCollection(); // before reseting make sure the bag is filled in
+
+ base.Reset(parentElement);
+ }
+
+ internal bool UpdatePropertyCollection()
+ {
+ bool bIsModified = false;
+ ArrayList removeList = null;
+
+ if (_propertyNameCollection != null)
+ {
+ // remove any data that has been delete from the collection
+ foreach (ConfigurationProperty prop in _properties)
+ if ((prop.Name != "name") && (prop.Name != "type"))
+ {
+ if (_propertyNameCollection.Get(prop.Name) != null) continue;
+ if (removeList == null)
+ removeList = new ArrayList();
+
+ if ((Values.GetConfigValue(prop.Name).ValueFlags & ConfigurationValueFlags.Locked) != 0)
+ continue;
+ removeList.Add(prop.Name);
+ bIsModified = true;
+ }
+
+ if (removeList != null)
+ {
+ foreach (string propName in removeList)
+ _properties.Remove(propName);
+ }
+
+ // then copy any data that has been changed in the collection
+ foreach (string key in _propertyNameCollection)
+ {
+ string valueInCollection = _propertyNameCollection[key];
+ string valueInBag = GetProperty(key);
+
+ if ((valueInBag == null) || (valueInCollection != valueInBag)) // add new property
+ {
+ SetProperty(key, valueInCollection);
+ bIsModified = true;
+ }
+ }
+ }
+ _propertyNameCollection = null;
+ return bIsModified;
+ }
+
+ protected internal override bool IsModified()
+ {
+ return UpdatePropertyCollection() || base.IsModified();
+ }
+
+
+ private string GetProperty(string propName)
+ {
+ if (_properties.Contains(propName))
+ {
+ ConfigurationProperty prop = _properties[propName];
+ if (prop != null)
+ return (string)base[prop];
+ }
+ return null;
+ }
+
+ private void SetProperty(string propName, string value)
+ {
+ ConfigurationProperty setPropName;
+ if (_properties.Contains(propName))
+ setPropName = _properties[propName];
+ else
+ {
+ setPropName = new ConfigurationProperty(propName, typeof(string), null);
+ _properties.Add(setPropName);
+ }
+
+ if (setPropName == null) return;
+ base[setPropName] = value;
+ }
+
+ protected override bool OnDeserializeUnrecognizedAttribute(string name, string value)
+ {
+ ConfigurationProperty propName = new ConfigurationProperty(name, typeof(string), value);
+ _properties.Add(propName);
+ base[propName] = value; // Add them to the property bag
+ Parameters[name] = value;
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ProviderSettingsCollection.cs b/src/System.Configuration/src/System/Configuration/ProviderSettingsCollection.cs
new file mode 100644
index 0000000000..ac37635c80
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ProviderSettingsCollection.cs
@@ -0,0 +1,67 @@
+// 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.Configuration
+{
+ [ConfigurationCollection(typeof(ProviderSettings))]
+ public sealed class ProviderSettingsCollection : ConfigurationElementCollection
+ {
+ private static readonly ConfigurationPropertyCollection s_properties;
+
+ static ProviderSettingsCollection()
+ {
+ // Property initialization
+ s_properties = new ConfigurationPropertyCollection();
+ }
+
+ public ProviderSettingsCollection() :
+ base(StringComparer.OrdinalIgnoreCase)
+ { }
+
+ protected internal override ConfigurationPropertyCollection Properties => s_properties;
+
+ public new ProviderSettings this[string key] => (ProviderSettings)BaseGet(key);
+
+ public ProviderSettings this[int index]
+ {
+ get { return (ProviderSettings)BaseGet(index); }
+ set
+ {
+ if (BaseGet(index) != null)
+ BaseRemoveAt(index);
+
+ BaseAdd(index, value);
+ }
+ }
+
+ public void Add(ProviderSettings provider)
+ {
+ if (provider != null)
+ {
+ provider.UpdatePropertyCollection();
+ BaseAdd(provider);
+ }
+ }
+
+ public void Remove(string name)
+ {
+ BaseRemove(name);
+ }
+
+ public void Clear()
+ {
+ BaseClear();
+ }
+
+ protected override ConfigurationElement CreateNewElement()
+ {
+ return new ProviderSettings();
+ }
+
+ protected override object GetElementKey(ConfigurationElement element)
+ {
+ return ((ProviderSettings)element).Name;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/RegexStringValidator.cs b/src/System.Configuration/src/System/Configuration/RegexStringValidator.cs
new file mode 100644
index 0000000000..e5afe8df8d
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/RegexStringValidator.cs
@@ -0,0 +1,38 @@
+// 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.Text.RegularExpressions;
+
+namespace System.Configuration
+{
+ public class RegexStringValidator : ConfigurationValidatorBase
+ {
+ private readonly string _expression;
+ private readonly Regex _regex;
+
+ public RegexStringValidator(string regex)
+ {
+ if (string.IsNullOrEmpty(regex)) throw ExceptionUtil.ParameterNullOrEmpty("regex");
+
+ _expression = regex;
+ _regex = new Regex(regex, RegexOptions.Compiled);
+ }
+
+ public override bool CanValidate(Type type)
+ {
+ return type == typeof(string);
+ }
+
+ public override void Validate(object value)
+ {
+ ValidatorUtils.HelperParamValidation(value, typeof(string));
+
+ if (value == null) return;
+
+ Match match = _regex.Match((string)value);
+
+ if (!match.Success) throw new ArgumentException(string.Format(SR.Regex_validator_error, _expression));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/RegexStringValidatorAttribute.cs b/src/System.Configuration/src/System/Configuration/RegexStringValidatorAttribute.cs
new file mode 100644
index 0000000000..695dc370a6
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/RegexStringValidatorAttribute.cs
@@ -0,0 +1,19 @@
+// 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.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class RegexStringValidatorAttribute : ConfigurationValidatorAttribute
+ {
+ public RegexStringValidatorAttribute(string regex)
+ {
+ Regex = regex;
+ }
+
+ public override ConfigurationValidatorBase ValidatorInstance => new RegexStringValidator(Regex);
+
+ public string Regex { get; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/RuntimeConfigurationRecord.cs b/src/System.Configuration/src/System/Configuration/RuntimeConfigurationRecord.cs
new file mode 100644
index 0000000000..a19a971a92
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/RuntimeConfigurationRecord.cs
@@ -0,0 +1,191 @@
+// 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.Configuration.Internal;
+using System.Reflection;
+using System.Xml;
+
+namespace System.Configuration
+{
+ internal sealed class RuntimeConfigurationRecord : BaseConfigurationRecord
+ {
+ private static readonly SimpleBitVector32 s_runtimeClassFlags = new SimpleBitVector32(
+ ClassSupportsChangeNotifications
+ | ClassSupportsRefresh
+ | ClassSupportsImpersonation
+ | ClassSupportsRestrictedPermissions
+ | ClassSupportsDelayedInit);
+
+ private RuntimeConfigurationRecord() { }
+
+ protected override SimpleBitVector32 ClassFlags => s_runtimeClassFlags;
+
+ internal static IInternalConfigRecord Create(
+ InternalConfigRoot configRoot,
+ IInternalConfigRecord parent,
+ string configPath)
+ {
+ RuntimeConfigurationRecord configRecord = new RuntimeConfigurationRecord();
+ configRecord.Init(configRoot, (BaseConfigurationRecord)parent, configPath, null);
+ return configRecord;
+ }
+
+ // Create the factory that will evaluate configuration
+ protected override object CreateSectionFactory(FactoryRecord factoryRecord)
+ {
+ return new RuntimeConfigurationFactory(this, factoryRecord);
+ }
+
+ // parentConfig contains the config that we'd merge with.
+ protected override object CreateSection(bool inputIsTrusted, FactoryRecord factoryRecord,
+ SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader)
+ {
+ // Get the factory used to create a section.
+ RuntimeConfigurationFactory factory = (RuntimeConfigurationFactory)factoryRecord.Factory;
+
+ // Use the factory to create a section.
+ object config = factory.CreateSection(inputIsTrusted, this, factoryRecord, sectionRecord, parentConfig,
+ reader);
+
+ return config;
+ }
+
+ protected override object UseParentResult(string configKey, object parentResult, SectionRecord sectionRecord)
+ {
+ return parentResult;
+ }
+
+ protected override object GetRuntimeObject(object result)
+ {
+ object runtimeObject;
+ ConfigurationSection section = result as ConfigurationSection;
+ if (section == null) runtimeObject = result;
+ else
+ {
+ // Call into config section while impersonating process or UNC identity
+ // so that the section could read files from disk if needed
+ try
+ {
+ runtimeObject = section.GetRuntimeObject();
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_exception_in_config_section_handler,
+ section.SectionInformation.SectionName), e);
+ }
+ }
+
+ return runtimeObject;
+ }
+
+ private class RuntimeConfigurationFactory
+ {
+ private ConstructorInfo _sectionCtor;
+ private IConfigurationSectionHandler _sectionHandler;
+
+ internal RuntimeConfigurationFactory(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
+ {
+ Init(configRecord, factoryRecord);
+ }
+
+ private void Init(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
+ {
+ // Get the type of the factory
+ Type type = TypeUtil.GetType(configRecord.Host, factoryRecord.FactoryTypeName,
+ true);
+
+ // If the type is a ConfigurationSection, that's the type.
+ if (typeof(ConfigurationSection).IsAssignableFrom(type))
+ {
+ _sectionCtor = TypeUtil.GetConstructor(type, typeof(ConfigurationSection),
+ true);
+ }
+ else
+ {
+ // Note: in v1, IConfigurationSectionHandler is in effect a factory that has a Create method
+ // that creates the real section object.
+
+ // throws if type does not implement IConfigurationSectionHandler
+ TypeUtil.VerifyAssignableType(typeof(IConfigurationSectionHandler), type, true);
+
+ // Create an instance of the handler
+ _sectionHandler =
+ (IConfigurationSectionHandler)TypeUtil.CreateInstance(type);
+ }
+ }
+
+ // Throw an exception if an attribute within a legacy section is one of our
+ // reserved locking attributes. We do not want admins to think they can lock
+ // an attribute or element within a legacy section.
+ private static void CheckForLockAttributes(string sectionName, XmlNode xmlNode)
+ {
+ XmlAttributeCollection attributes = xmlNode.Attributes;
+ if (attributes != null)
+ {
+ foreach (XmlAttribute attribute in attributes)
+ if (ConfigurationElement.IsLockAttributeName(attribute.Name))
+ {
+ throw new ConfigurationErrorsException(
+ string.Format(SR.Config_element_locking_not_supported, sectionName), attribute);
+ }
+ }
+
+ foreach (XmlNode child in xmlNode.ChildNodes)
+ if (xmlNode.NodeType == XmlNodeType.Element) CheckForLockAttributes(sectionName, child);
+ }
+
+ internal object CreateSection(bool inputIsTrusted, RuntimeConfigurationRecord configRecord,
+ FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader)
+ {
+ object config;
+
+ if (_sectionCtor != null)
+ {
+ ConfigurationSection configSection =
+ (ConfigurationSection)_sectionCtor.Invoke(null);
+
+ configSection.SectionInformation.SetRuntimeConfigurationInformation(configRecord, factoryRecord,
+ sectionRecord);
+
+ configSection.CallInit();
+
+ ConfigurationSection parentSection = (ConfigurationSection)parentConfig;
+ configSection.Reset(parentSection);
+
+ if (reader != null) configSection.DeserializeSection(reader);
+
+ // throw if there are any cached errors
+ ConfigurationErrorsException errors = configSection.GetErrors();
+ if (errors != null) throw errors;
+
+ // don't allow changes to sections at runtime
+ configSection.SetReadOnly();
+
+ // reset the modified bit
+ configSection.ResetModified();
+
+ config = configSection;
+ }
+ else
+ {
+ if (reader != null)
+ {
+ XmlNode xmlNode = ErrorInfoXmlDocument.CreateSectionXmlNode(reader);
+
+ CheckForLockAttributes(factoryRecord.ConfigKey, xmlNode);
+
+ // In v1, our old section handler expects a context that contains the virtualPath from the configPath
+ object configContext = configRecord.Host.CreateDeprecatedConfigContext(configRecord.ConfigPath);
+
+ config = _sectionHandler.Create(parentConfig, configContext, xmlNode);
+ }
+ else config = null;
+ }
+
+ return config;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/SafeBitVector32.cs b/src/System.Configuration/src/System/Configuration/SafeBitVector32.cs
new file mode 100644
index 0000000000..6d8e9b1b1f
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/SafeBitVector32.cs
@@ -0,0 +1,45 @@
+// 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.Threading;
+
+namespace System.Configuration
+{
+ // This is a multithreadsafe version of System.Collections.Specialized.BitVector32.
+ [Serializable]
+ internal struct SafeBitVector32
+ {
+ private volatile int _data;
+
+ internal SafeBitVector32(int data)
+ {
+ _data = data;
+ }
+
+ internal bool this[int bit]
+ {
+ get
+ {
+ int data = _data;
+ return (data & bit) == bit;
+ }
+ set
+ {
+ for (;;)
+ {
+ int oldData = _data;
+ int newData;
+ if (value) newData = oldData | bit;
+ else newData = oldData & ~bit;
+
+#pragma warning disable 0420
+ int result = Interlocked.CompareExchange(ref _data, newData, oldData);
+#pragma warning restore 0420
+
+ if (result == oldData) break;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/SectionInformation.cs b/src/System.Configuration/src/System/Configuration/SectionInformation.cs
new file mode 100644
index 0000000000..de92ab6637
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/SectionInformation.cs
@@ -0,0 +1,684 @@
+// 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.Configuration.Internal;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ public sealed class SectionInformation
+ {
+ // Flags
+ private const int FlagAttached = 0x00000001;
+ private const int FlagDeclared = 0x00000002;
+ private const int FlagDeclarationRequired = 0x00000004;
+ private const int FlagAllowLocation = 0x00000008;
+ private const int FlagRestartOnExternalChanges = 0x00000010;
+ private const int FlagRequirePermission = 0x00000020;
+ private const int FlagLocationLocked = 0x00000040;
+ private const int FlagChildrenLocked = 0x00000080;
+ private const int FlagInheritInChildApps = 0x00000100;
+ private const int FlagIsParentSection = 0x00000200;
+ private const int FlagRemoved = 0x00000400;
+ private const int FlagProtectionProviderDetermined = 0x00000800;
+ private const int FlagForceSave = 0x00001000;
+ private const int FlagIsUndeclared = 0x00002000;
+ private const int FlagChildrenLockWithoutFileInput = 0x00004000;
+
+ private const int FlagAllowExeDefinitionModified = 0x00010000;
+ private const int FlagAllowDefinitionModified = 0x00020000;
+ private const int FlagConfigSourceModified = 0x00040000;
+ private const int FlagProtectionProviderModified = 0x00080000;
+ private const int FlagOverrideModeDefaultModified = 0x00100000;
+ private const int FlagOverrideModeModified = 0x00200000; // Used only for modified tracking
+
+ private readonly ConfigurationSection _configurationSection;
+ private ConfigurationAllowDefinition _allowDefinition;
+ private ConfigurationAllowExeDefinition _allowExeDefinition;
+ private MgmtConfigurationRecord _configRecord;
+ private string _configSource;
+ private SafeBitVector32 _flags;
+ private SimpleBitVector32 _modifiedFlags;
+ private OverrideModeSetting _overrideMode; // The override mode at the current config path
+ private OverrideModeSetting _overrideModeDefault; // The default mode for the section in _configurationSection
+ private ProtectedConfigurationProvider _protectionProvider;
+ private string _typeName;
+
+ internal SectionInformation(ConfigurationSection associatedConfigurationSection)
+ {
+ ConfigKey = string.Empty;
+ Name = string.Empty;
+
+ _configurationSection = associatedConfigurationSection;
+ _allowDefinition = ConfigurationAllowDefinition.Everywhere;
+ _allowExeDefinition = ConfigurationAllowExeDefinition.MachineToApplication;
+ _overrideModeDefault = OverrideModeSetting.s_sectionDefault;
+ _overrideMode = OverrideModeSetting.s_locationDefault;
+
+ _flags[FlagAllowLocation] = true;
+ _flags[FlagRestartOnExternalChanges] = true;
+ _flags[FlagRequirePermission] = true;
+ _flags[FlagInheritInChildApps] = true;
+ _flags[FlagForceSave] = false;
+
+ _modifiedFlags = new SimpleBitVector32();
+ }
+
+ private bool IsRuntime => _flags[FlagAttached] &&
+ (_configRecord == null);
+
+ internal bool Attached => _flags[FlagAttached];
+
+ internal string ConfigKey { get; private set; }
+
+ internal bool Removed
+ {
+ get { return _flags[FlagRemoved]; }
+ set { _flags[FlagRemoved] = value; }
+ }
+
+ public string SectionName => ConfigKey;
+
+ public string Name { get; private set; }
+
+ public ConfigurationAllowDefinition AllowDefinition
+ {
+ get { return _allowDefinition; }
+ set
+ {
+ VerifyIsEditable();
+ VerifyIsEditableFactory();
+
+ // allow AllowDefinition to be different from current type,
+ // so long as it doesn't conflict with a type already defined
+ FactoryRecord factoryRecord = FindParentFactoryRecord(false);
+ if ((factoryRecord != null) && (factoryRecord.AllowDefinition != value))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
+
+ _allowDefinition = value;
+ _modifiedFlags[FlagAllowDefinitionModified] = true;
+ }
+ }
+
+ internal bool AllowDefinitionModified => _modifiedFlags[FlagAllowDefinitionModified];
+
+ public ConfigurationAllowExeDefinition AllowExeDefinition
+ {
+ get { return _allowExeDefinition; }
+ set
+ {
+ VerifyIsEditable();
+ VerifyIsEditableFactory();
+
+ // allow AllowDefinition to be different from current type,
+ // so long as it doesn't conflict with a type already defined
+ FactoryRecord factoryRecord = FindParentFactoryRecord(false);
+ if ((factoryRecord != null) && (factoryRecord.AllowExeDefinition != value))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
+
+ _allowExeDefinition = value;
+ _modifiedFlags[FlagAllowExeDefinitionModified] = true;
+ }
+ }
+
+ internal bool AllowExeDefinitionModified => _modifiedFlags[FlagAllowExeDefinitionModified];
+
+ public OverrideMode OverrideModeDefault
+ {
+ get { return _overrideModeDefault.OverrideMode; }
+ set
+ {
+ VerifyIsEditable();
+ VerifyIsEditableFactory();
+
+ // allow OverrideModeDefault to be different from current value,
+ // so long as it doesn't conflict with a type already defined
+ FactoryRecord factoryRecord = FindParentFactoryRecord(false);
+ if ((factoryRecord != null) && (factoryRecord.OverrideModeDefault.OverrideMode != value))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
+
+ // Threat "Inherit" as "Allow" as "Inherit" does not make sense as a default
+ if (value == OverrideMode.Inherit) value = OverrideMode.Allow;
+
+ _overrideModeDefault.OverrideMode = value;
+ _modifiedFlags[FlagOverrideModeDefaultModified] = true;
+ }
+ }
+
+ internal OverrideModeSetting OverrideModeDefaultSetting => _overrideModeDefault;
+
+ internal bool OverrideModeDefaultModified => _modifiedFlags[FlagOverrideModeDefaultModified];
+
+ public bool AllowLocation
+ {
+ get { return _flags[FlagAllowLocation]; }
+ set
+ {
+ VerifyIsEditable();
+ VerifyIsEditableFactory();
+
+ // allow AllowLocation to be different from current type,
+ // so long as it doesn't conflict with a type already defined
+ FactoryRecord factoryRecord = FindParentFactoryRecord(false);
+ if ((factoryRecord != null) && (factoryRecord.AllowLocation != value))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
+
+ _flags[FlagAllowLocation] = value;
+ _modifiedFlags[FlagAllowLocation] = true;
+ }
+ }
+
+ internal bool AllowLocationModified => _modifiedFlags[FlagAllowLocation];
+
+ public bool AllowOverride
+ {
+ get { return _overrideMode.AllowOverride; }
+ set
+ {
+ VerifyIsEditable();
+ VerifySupportsLocation();
+ _overrideMode.AllowOverride = value;
+ _modifiedFlags[FlagOverrideModeModified] = true;
+ }
+ }
+
+ public OverrideMode OverrideMode
+ {
+ get { return _overrideMode.OverrideMode; }
+ set
+ {
+ VerifyIsEditable();
+ VerifySupportsLocation();
+ _overrideMode.OverrideMode = value;
+ _modifiedFlags[FlagOverrideModeModified] = true;
+
+ // Modify the state of OverrideModeEffective according to the changes to the current mode
+ switch (value)
+ {
+ case OverrideMode.Inherit:
+ // Wehen the state is changing to inherit - apply the value from parent which does not
+ // include the file input lock mode
+ _flags[FlagChildrenLocked] = _flags[FlagChildrenLockWithoutFileInput];
+ break;
+ case OverrideMode.Allow:
+ _flags[FlagChildrenLocked] = false;
+ break;
+ case OverrideMode.Deny:
+ _flags[FlagChildrenLocked] = true;
+ break;
+ default:
+ Debug.Assert(false, "Unexpected value for OverrideMode");
+ break;
+ }
+ }
+ }
+
+ public OverrideMode OverrideModeEffective => _flags[FlagChildrenLocked] ? OverrideMode.Deny : OverrideMode.Allow
+ ;
+
+ internal OverrideModeSetting OverrideModeSetting => _overrideMode;
+
+
+ // LocationAttributesAreDefault
+ //
+ // Are the location attributes for this section set to the
+ // default settings?
+ internal bool LocationAttributesAreDefault => _overrideMode.IsDefaultForLocationTag &&
+ _flags[FlagInheritInChildApps];
+
+ public string ConfigSource
+ {
+ get { return _configSource ?? string.Empty; }
+ set
+ {
+ VerifyIsEditable();
+
+ string configSource = !string.IsNullOrEmpty(value)
+ ? BaseConfigurationRecord.NormalizeConfigSource(value, null)
+ : null;
+
+ // return early if there is no change
+ if (configSource == _configSource)
+ return;
+
+ _configRecord?.ChangeConfigSource(this, _configSource, ConfigSourceStreamName, configSource);
+
+ _configSource = configSource;
+ _modifiedFlags[FlagConfigSourceModified] = true;
+ }
+ }
+
+ internal bool ConfigSourceModified => _modifiedFlags[FlagConfigSourceModified];
+
+ internal string ConfigSourceStreamName { get; set; }
+
+ public bool InheritInChildApplications
+ {
+ get { return _flags[FlagInheritInChildApps]; }
+ set
+ {
+ VerifyIsEditable();
+ VerifySupportsLocation();
+ _flags[FlagInheritInChildApps] = value;
+ }
+ }
+
+ // True if the section is declared at the current level
+ public bool IsDeclared
+ {
+ get
+ {
+ VerifyNotParentSection();
+
+ return _flags[FlagDeclared];
+ }
+ }
+
+ // Is the Declaration Required. It is required if it is not set
+ // in a parent, or the parent entry does not have the type
+ public bool IsDeclarationRequired
+ {
+ get
+ {
+ VerifyNotParentSection();
+
+ return _flags[FlagDeclarationRequired];
+ }
+ }
+
+ // Is the Definition Allowed at this point. This is all depending
+ // on the Definition that is allowed, and what context we are
+ // writing the file
+ private bool IsDefinitionAllowed
+ => (_configRecord == null) || _configRecord.IsDefinitionAllowed(_allowDefinition, _allowExeDefinition);
+
+ public bool IsLocked => _flags[FlagLocationLocked] || !IsDefinitionAllowed ||
+ _configurationSection.ElementInformation.IsLocked;
+
+ public bool IsProtected => ProtectionProvider != null;
+
+ public ProtectedConfigurationProvider ProtectionProvider
+ {
+ get
+ {
+ if (!_flags[FlagProtectionProviderDetermined] && (_configRecord != null))
+ {
+ _protectionProvider = _configRecord.GetProtectionProviderFromName(ProtectionProviderName, false);
+ _flags[FlagProtectionProviderDetermined] = true;
+ }
+
+ return _protectionProvider;
+ }
+ }
+
+ internal string ProtectionProviderName { get; private set; }
+
+ public bool RestartOnExternalChanges
+ {
+ get { return _flags[FlagRestartOnExternalChanges]; }
+ set
+ {
+ VerifyIsEditable();
+ VerifyIsEditableFactory();
+
+ // allow RestartOnExternalChanges to be different from current type,
+ // so long as it doesn't conflict with a type already defined
+ FactoryRecord factoryRecord = FindParentFactoryRecord(false);
+ if ((factoryRecord != null) && (factoryRecord.RestartOnExternalChanges != value))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
+
+ _flags[FlagRestartOnExternalChanges] = value;
+ _modifiedFlags[FlagRestartOnExternalChanges] = true;
+ }
+ }
+
+ internal bool RestartOnExternalChangesModified => _modifiedFlags[FlagRestartOnExternalChanges];
+
+ public bool RequirePermission
+ {
+ get { return _flags[FlagRequirePermission]; }
+ set
+ {
+ VerifyIsEditable();
+ VerifyIsEditableFactory();
+
+ // allow RequirePermission to be different from current type,
+ // so long as it doesn't conflict with a type already defined
+ FactoryRecord factoryRecord = FindParentFactoryRecord(false);
+ if ((factoryRecord != null) && (factoryRecord.RequirePermission != value))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
+
+ _flags[FlagRequirePermission] = value;
+ _modifiedFlags[FlagRequirePermission] = true;
+ }
+ }
+
+ internal bool RequirePermissionModified => _modifiedFlags[FlagRequirePermission];
+
+
+ public string Type
+ {
+ get { return _typeName; }
+ set
+ {
+ if (string.IsNullOrEmpty(value)) throw ExceptionUtil.PropertyNullOrEmpty("Type");
+
+ VerifyIsEditable();
+ VerifyIsEditableFactory();
+
+ // allow type to be different from current type,
+ // so long as it doesn't conflict with a type already defined
+ FactoryRecord factoryRecord = FindParentFactoryRecord(false);
+ if (factoryRecord != null)
+ {
+ IInternalConfigHost host = null;
+ if (_configRecord != null) host = _configRecord.Host;
+
+ if (!factoryRecord.IsEquivalentType(host, value))
+ {
+ throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined,
+ ConfigKey));
+ }
+ }
+
+ _typeName = value;
+ }
+ }
+
+ internal string RawXml { get; set; }
+
+ // True if the section will be serialized to the current hierarchy level, regardless of
+ // ConfigurationSaveMode.
+ public bool ForceSave
+ {
+ get { return _flags[FlagForceSave]; }
+ set
+ {
+ VerifyIsEditable();
+
+ _flags[FlagForceSave] = value;
+ }
+ }
+
+ internal void ResetModifiedFlags()
+ {
+ _modifiedFlags = new SimpleBitVector32();
+ }
+
+ internal bool IsModifiedFlags()
+ {
+ return _modifiedFlags.Data != 0;
+ }
+
+ // for instantiation of a ConfigurationSection from GetConfig
+ internal void AttachToConfigurationRecord(MgmtConfigurationRecord configRecord, FactoryRecord factoryRecord,
+ SectionRecord sectionRecord)
+ {
+ SetRuntimeConfigurationInformation(configRecord, factoryRecord, sectionRecord);
+ _configRecord = configRecord;
+ }
+
+ internal void SetRuntimeConfigurationInformation(BaseConfigurationRecord configRecord,
+ FactoryRecord factoryRecord, SectionRecord sectionRecord)
+ {
+ _flags[FlagAttached] = true;
+
+ // factory info
+ ConfigKey = factoryRecord.ConfigKey;
+ Name = factoryRecord.Name;
+ _typeName = factoryRecord.FactoryTypeName;
+ _allowDefinition = factoryRecord.AllowDefinition;
+ _allowExeDefinition = factoryRecord.AllowExeDefinition;
+ _flags[FlagAllowLocation] = factoryRecord.AllowLocation;
+ _flags[FlagRestartOnExternalChanges] = factoryRecord.RestartOnExternalChanges;
+ _flags[FlagRequirePermission] = factoryRecord.RequirePermission;
+ _overrideModeDefault = factoryRecord.OverrideModeDefault;
+
+ if (factoryRecord.IsUndeclared)
+ {
+ _flags[FlagIsUndeclared] = true;
+ _flags[FlagDeclared] = false;
+ _flags[FlagDeclarationRequired] = false;
+ }
+ else
+ {
+ _flags[FlagIsUndeclared] = false;
+ _flags[FlagDeclared] = configRecord.GetFactoryRecord(factoryRecord.ConfigKey, false) != null;
+ _flags[FlagDeclarationRequired] = configRecord.IsRootDeclaration(factoryRecord.ConfigKey, false);
+ }
+
+ // section info
+ _flags[FlagLocationLocked] = sectionRecord.Locked;
+ _flags[FlagChildrenLocked] = sectionRecord.LockChildren;
+ _flags[FlagChildrenLockWithoutFileInput] = sectionRecord.LockChildrenWithoutFileInput;
+
+ if (sectionRecord.HasFileInput)
+ {
+ SectionInput fileInput = sectionRecord.FileInput;
+
+ _flags[FlagProtectionProviderDetermined] = fileInput.IsProtectionProviderDetermined;
+ _protectionProvider = fileInput.ProtectionProvider;
+
+ SectionXmlInfo sectionXmlInfo = fileInput.SectionXmlInfo;
+
+ _configSource = sectionXmlInfo.ConfigSource;
+ ConfigSourceStreamName = sectionXmlInfo.ConfigSourceStreamName;
+ _overrideMode = sectionXmlInfo.OverrideModeSetting;
+ _flags[FlagInheritInChildApps] = !sectionXmlInfo.SkipInChildApps;
+ ProtectionProviderName = sectionXmlInfo.ProtectionProviderName;
+ }
+ else
+ {
+ _flags[FlagProtectionProviderDetermined] = false;
+ _protectionProvider = null;
+ }
+
+ // element context information
+ _configurationSection.AssociateContext(configRecord);
+ }
+
+ internal void DetachFromConfigurationRecord()
+ {
+ RevertToParent();
+ _flags[FlagAttached] = false;
+ _configRecord = null;
+ }
+
+ private void VerifyDesigntime()
+ {
+ if (IsRuntime) throw new InvalidOperationException(SR.Config_operation_not_runtime);
+ }
+
+ private void VerifyIsAttachedToConfigRecord()
+ {
+ if (_configRecord == null)
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_not_attached);
+ }
+
+ // VerifyIsEditable
+ //
+ // Verify the section is Editable.
+ // It may not be editable for the following reasons:
+ // - We are in Runtime mode, not Design time
+ // - The section is not attached to a _configRecord.
+ // - We are locked (ie. allowOveride = false )
+ // - We are a parent section (ie. Retrieved from GetParentSection)
+ //
+ internal void VerifyIsEditable()
+ {
+ VerifyDesigntime();
+
+ if (IsLocked)
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_locked);
+
+ if (_flags[FlagIsParentSection])
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_parentsection);
+
+ if (!_flags[FlagAllowLocation] &&
+ (_configRecord != null) &&
+ _configRecord.IsLocationConfig)
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_location_locked);
+ }
+
+ private void VerifyNotParentSection()
+ {
+ if (_flags[FlagIsParentSection])
+ throw new InvalidOperationException(SR.Config_configsection_parentnotvalid);
+ }
+
+ // Verify that we support the location tag. This is true either
+ // in machine.config, or in any place for the web config system
+ private void VerifySupportsLocation()
+ {
+ if ((_configRecord != null) &&
+ !_configRecord.RecordSupportsLocation)
+ throw new InvalidOperationException(SR.Config_cannot_edit_locationattriubtes);
+ }
+
+ internal void VerifyIsEditableFactory()
+ {
+ if ((_configRecord != null) && _configRecord.IsLocationConfig)
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_in_location_config);
+
+ // Can't edit factory if the section is built-in
+ if (BaseConfigurationRecord.IsImplicitSection(ConfigKey))
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_it_is_implicit);
+
+ // Can't edit undeclared section
+ if (_flags[FlagIsUndeclared])
+ throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_it_is_undeclared);
+ }
+
+ private FactoryRecord FindParentFactoryRecord(bool permitErrors)
+ {
+ FactoryRecord factoryRecord = null;
+
+ if ((_configRecord != null) && !_configRecord.Parent.IsRootConfig)
+ factoryRecord = _configRecord.Parent.FindFactoryRecord(ConfigKey, permitErrors);
+
+ return factoryRecord;
+ }
+
+ // Force the section declaration to be written out during Save.
+ public void ForceDeclaration()
+ {
+ ForceDeclaration(true);
+ }
+
+ // If force==false, it actually means don't declare it at
+ // the current level.
+ public void ForceDeclaration(bool force)
+ {
+ VerifyIsEditable();
+
+ if ((force == false) &&
+ _flags[FlagDeclarationRequired])
+ {
+ // Since it is required, we can not remove it
+ }
+ else
+ {
+ // CONSIDER: There is no apriori way to determine if a section
+ // is implicit or undeclared. Would it be better to simply
+ // fail silently so that app code can easily loop through sections
+ // and declare all of them?
+ if (force && BaseConfigurationRecord.IsImplicitSection(SectionName))
+ throw new ConfigurationErrorsException(SR.Cannot_declare_or_remove_implicit_section);
+
+ if (force && _flags[FlagIsUndeclared])
+ {
+ throw new ConfigurationErrorsException(
+ SR.Config_cannot_edit_configurationsection_when_it_is_undeclared);
+ }
+
+ _flags[FlagDeclared] = force;
+ }
+ }
+
+ // method to cause a section to be protected using the specified provider
+ public void ProtectSection(string protectionProvider)
+ {
+ ProtectedConfigurationProvider protectedConfigurationProvider;
+
+ VerifyIsEditable();
+
+ // Do not encrypt sections that will be read by a native reader.
+ // These sections are be marked with allowLocation=false.
+ // Also, the configProtectedData section cannot be encrypted!
+ if (!AllowLocation || (ConfigKey == BaseConfigurationRecord.ReservedSectionProtectedConfiguration))
+ throw new InvalidOperationException(SR.Config_not_allowed_to_encrypt_this_section);
+
+ if (_configRecord != null)
+ {
+ if (string.IsNullOrEmpty(protectionProvider)) protectionProvider = _configRecord.DefaultProviderName;
+
+ protectedConfigurationProvider = _configRecord.GetProtectionProviderFromName(protectionProvider, true);
+ }
+ else throw new InvalidOperationException(SR.Must_add_to_config_before_protecting_it);
+
+ ProtectionProviderName = protectionProvider;
+ _protectionProvider = protectedConfigurationProvider;
+
+ _flags[FlagProtectionProviderDetermined] = true;
+ _modifiedFlags[FlagProtectionProviderModified] = true;
+ }
+
+ public void UnprotectSection()
+ {
+ VerifyIsEditable();
+
+ _protectionProvider = null;
+ ProtectionProviderName = null;
+ _flags[FlagProtectionProviderDetermined] = true;
+ _modifiedFlags[FlagProtectionProviderModified] = true;
+ }
+
+ public ConfigurationSection GetParentSection()
+ {
+ VerifyDesigntime();
+
+ if (_flags[FlagIsParentSection])
+ throw new InvalidOperationException(SR.Config_getparentconfigurationsection_first_instance);
+
+ // if a users create a configsection with : sectionType sec = new sectionType();
+ // the config record will be null. Return null for the parent in this case.
+ ConfigurationSection ancestor = null;
+ if (_configRecord != null)
+ {
+ ancestor = _configRecord.FindAndCloneImmediateParentSection(_configurationSection);
+ if (ancestor != null)
+ {
+ ancestor.SectionInformation._flags[FlagIsParentSection] = true;
+ ancestor.SetReadOnly();
+ }
+ }
+
+ return ancestor;
+ }
+
+ public string GetRawXml()
+ {
+ VerifyDesigntime();
+ VerifyNotParentSection();
+
+ return RawXml ?? _configRecord?.GetRawXml(ConfigKey);
+ }
+
+ public void SetRawXml(string rawXml)
+ {
+ VerifyIsEditable();
+
+ if (_configRecord != null) _configRecord.SetRawXml(_configurationSection, rawXml);
+ else RawXml = string.IsNullOrEmpty(rawXml) ? null : rawXml;
+ }
+
+ public void RevertToParent()
+ {
+ VerifyIsEditable();
+ VerifyIsAttachedToConfigRecord();
+
+ _configRecord.RevertToParent(_configurationSection);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/SectionInput.cs b/src/System.Configuration/src/System/Configuration/SectionInput.cs
new file mode 100644
index 0000000000..98c1bf9276
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/SectionInput.cs
@@ -0,0 +1,69 @@
+// 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.Generic;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ [DebuggerDisplay("SectionInput {SectionXmlInfo.ConfigKey}")]
+ internal class SectionInput
+ {
+ // result can be null, so we use this object to indicate whether it has been evaluated
+ private static readonly object s_unevaluated = new object();
+
+ // accummulated errors related to this input
+ private readonly List<ConfigurationException> _errors;
+
+ // Provider to use for encryption
+ private ProtectedConfigurationProvider _protectionProvider;
+
+ internal SectionInput(SectionXmlInfo sectionXmlInfo, List<ConfigurationException> errors)
+ {
+ SectionXmlInfo = sectionXmlInfo;
+ _errors = errors;
+
+ Result = s_unevaluated;
+ ResultRuntimeObject = s_unevaluated;
+ }
+
+ internal SectionXmlInfo SectionXmlInfo { get; }
+
+ internal bool HasResult => Result != s_unevaluated;
+
+ internal bool HasResultRuntimeObject => ResultRuntimeObject != s_unevaluated;
+
+ internal object Result { get; set; }
+
+ internal object ResultRuntimeObject { get; set; }
+
+ internal bool IsProtectionProviderDetermined { get; private set; }
+
+ internal ProtectedConfigurationProvider ProtectionProvider
+ {
+ get { return _protectionProvider; }
+ set
+ {
+ _protectionProvider = value;
+ IsProtectionProviderDetermined = true;
+ }
+ }
+
+ // Errors associated with a section input.
+ internal ICollection<ConfigurationException> Errors => _errors;
+
+ internal bool HasErrors => ErrorsHelper.GetHasErrors(_errors);
+
+ internal void ClearResult()
+ {
+ Result = s_unevaluated;
+ ResultRuntimeObject = s_unevaluated;
+ }
+
+ internal void ThrowOnErrors()
+ {
+ ErrorsHelper.ThrowOnErrors(_errors);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/SectionRecord.cs b/src/System.Configuration/src/System/Configuration/SectionRecord.cs
new file mode 100644
index 0000000000..1b7fa5fb1a
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/SectionRecord.cs
@@ -0,0 +1,298 @@
+// 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.Generic;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ [DebuggerDisplay("SectionRecord {ConfigKey}")]
+ internal class SectionRecord
+ {
+ //
+ // Runtime flags below 0x10000
+ //
+
+ // locked by parent input, either because a parent section is locked,
+ // a parent section locks all children, or a location input for this
+ // configPath has allowOverride=false.
+ private const int FlagLocked = 0x00000001;
+
+ // lock children of this section
+ private const int FlagLockChildren = 0x00000002;
+
+ // propagation of FactoryRecord.RequirePermission
+ private const int FlagRequirePermission = 0x00000008;
+
+ // Look at AddLocationInput for explanation of this flag's purpose
+ private const int FlagLocationInputLockApplied = 0x00000010;
+
+ // Look at AddIndirectLocationInput for explanation of this flag's purpose
+ private const int FlagIndirectLocationInputLockApplied = 0x00000020;
+
+ // The flag gives us the inherited lock mode for this section record without the file input
+ // We need this to support SectionInformation.OverrideModeEffective.
+ private const int FlagChildrenLockWithoutFileInput = 0x00000040;
+
+ //
+ // Designtime flags at or above 0x00010000
+ //
+
+ // the section has been added to the update list
+ private const int FlagAddUpdate = 0x00010000;
+
+ // result can be null, so we use this object to indicate whether it has been evaluated
+ private static readonly object s_unevaluated = new object();
+
+ // config key
+
+ // The input from this file
+
+ private SafeBitVector32 _flags;
+
+ // This special input is used only when creating a location config record.
+ // The inputs are from location tags which are found in the same config file as the
+ // location config configPath, but point to the parent paths of the location config
+ // configPath. See the comment for VSWhidbey 540184 in Init() in
+ // BaseConfigurationRecord.cs for more details.
+
+ // The input from location sections
+ // This list is ordered to keep oldest ancestors at the front
+
+ // the cached result of evaluating this section
+
+ // the cached result of evaluating this section after GetRuntimeObject is called
+
+
+ internal SectionRecord(string configKey)
+ {
+ ConfigKey = configKey;
+ Result = s_unevaluated;
+ ResultRuntimeObject = s_unevaluated;
+ }
+
+ internal string ConfigKey { get; }
+
+ internal bool Locked => _flags[FlagLocked];
+
+ internal bool LockChildren => _flags[FlagLockChildren];
+
+ internal bool LockChildrenWithoutFileInput
+ {
+ get
+ {
+ // Start assuming we dont have a file input
+ // When we don't have file input the lock mode for children is the same for LockChildren and LockChildrenWithoutFileInput
+ bool result = LockChildren;
+
+ if (HasFileInput) result = _flags[FlagChildrenLockWithoutFileInput];
+
+ return result;
+ }
+ }
+
+ internal bool RequirePermission
+ {
+ get { return _flags[FlagRequirePermission]; }
+ set { _flags[FlagRequirePermission] = value; }
+ }
+
+ internal bool AddUpdate
+ {
+ get { return _flags[FlagAddUpdate]; }
+ set { _flags[FlagAddUpdate] = value; }
+ }
+
+ internal bool HasLocationInputs => (LocationInputs != null) && (LocationInputs.Count > 0);
+
+ internal List<SectionInput> LocationInputs { get; private set; }
+
+ internal SectionInput LastLocationInput => HasLocationInputs ? LocationInputs[LocationInputs.Count - 1] : null;
+
+ internal bool HasFileInput => FileInput != null;
+
+ internal SectionInput FileInput { get; private set; }
+
+ internal bool HasIndirectLocationInputs
+ => (IndirectLocationInputs != null) && (IndirectLocationInputs.Count > 0);
+
+ internal List<SectionInput> IndirectLocationInputs { get; private set; }
+
+ internal SectionInput LastIndirectLocationInput
+ => HasIndirectLocationInputs ? IndirectLocationInputs[IndirectLocationInputs.Count - 1] : null;
+
+ internal bool HasInput => HasLocationInputs || HasFileInput || HasIndirectLocationInputs;
+
+ internal bool HasResult => Result != s_unevaluated;
+
+ internal bool HasResultRuntimeObject => ResultRuntimeObject != s_unevaluated;
+
+ internal object Result { get; set; }
+
+ internal object ResultRuntimeObject { get; set; }
+
+ internal bool HasErrors
+ {
+ get
+ {
+ if (HasLocationInputs) foreach (SectionInput input in LocationInputs) if (input.HasErrors) return true;
+
+ if (HasIndirectLocationInputs)
+ foreach (SectionInput input in IndirectLocationInputs) if (input.HasErrors) return true;
+
+ return HasFileInput && FileInput.HasErrors;
+ }
+ }
+
+ internal void
+ AddLocationInput(SectionInput sectionInput)
+ {
+ AddLocationInputImpl(sectionInput, false);
+ }
+
+ internal void ChangeLockSettings(OverrideMode forSelf, OverrideMode forChildren)
+ {
+ if (forSelf != OverrideMode.Inherit)
+ {
+ _flags[FlagLocked] = forSelf == OverrideMode.Deny;
+ _flags[FlagLockChildren] = forSelf == OverrideMode.Deny;
+ }
+
+ if (forChildren != OverrideMode.Inherit)
+ _flags[FlagLockChildren] = (forSelf == OverrideMode.Deny) || (forChildren == OverrideMode.Deny);
+ }
+
+ // AddFileInput
+ internal void AddFileInput(SectionInput sectionInput)
+ {
+ Debug.Assert(sectionInput != null);
+
+ FileInput = sectionInput;
+
+ // If the file input has an explicit value for its children locking - use it
+ // Note we dont change the current lock setting
+ if (!sectionInput.HasErrors &&
+ (sectionInput.SectionXmlInfo.OverrideModeSetting.OverrideMode != OverrideMode.Inherit))
+ {
+ // Store the current setting before applying the lock from the file input
+ // So that if the user changes the current OverrideMode on this configKey to "Inherit"
+ // we will know what we are going to inherit ( used in SectionInformation.OverrideModeEffective )
+ // Note that we cannot use BaseConfigurationRecord.ResolveOverrideModeFromParent as it gives us only the lock
+ // resolved up to our immediate parent which does not inlcude normal and indirect location imputs
+ _flags[FlagChildrenLockWithoutFileInput] = LockChildren;
+
+ ChangeLockSettings(OverrideMode.Inherit,
+ sectionInput.SectionXmlInfo.OverrideModeSetting.OverrideMode);
+ }
+ }
+
+ internal void RemoveFileInput()
+ {
+ if (FileInput != null)
+ {
+ FileInput = null;
+
+ // Reset LockChildren flag to the value provided by
+ // location input or inherited sections.
+ _flags[FlagLockChildren] = Locked;
+ }
+ }
+
+ internal void
+ AddIndirectLocationInput(SectionInput sectionInput)
+ {
+ AddLocationInputImpl(sectionInput, true);
+ }
+
+ private void
+ AddLocationInputImpl(SectionInput sectionInput, bool isIndirectLocation)
+ {
+ List<SectionInput> inputs = isIndirectLocation
+ ? IndirectLocationInputs
+ : LocationInputs;
+
+ int flag = isIndirectLocation
+ ? FlagIndirectLocationInputLockApplied
+ : FlagLocationInputLockApplied;
+
+ if (inputs == null)
+ {
+ inputs = new List<SectionInput>(1);
+
+ if (isIndirectLocation) IndirectLocationInputs = inputs;
+ else LocationInputs = inputs;
+ }
+
+ // The list of locationSections is traversed from child to parent,
+ // so insert at the beginning of the list.
+ inputs.Insert(0, sectionInput);
+
+ // Only the overrideMode from the parent thats closest to the SectionRecord has effect
+ //
+ // For location input:
+ // Remember that this method will be called for location inputs comming from the immediate parent first
+ // and then walking the hierarchy up to the root level
+ //
+ // For indirect location input:
+ // This method will be first called for indirect input closest to the location config
+ if (!sectionInput.HasErrors && !_flags[flag])
+ {
+ OverrideMode modeLocation = sectionInput.SectionXmlInfo.OverrideModeSetting.OverrideMode;
+
+ if (modeLocation != OverrideMode.Inherit)
+ {
+ ChangeLockSettings(modeLocation, modeLocation);
+ _flags[flag] = true;
+ }
+ }
+ }
+
+ internal void ClearRawXml()
+ {
+ if (HasLocationInputs)
+ foreach (SectionInput locationInput in LocationInputs) locationInput.SectionXmlInfo.RawXml = null;
+
+ if (HasIndirectLocationInputs)
+ {
+ foreach (SectionInput indirectLocationInput in IndirectLocationInputs)
+ indirectLocationInput.SectionXmlInfo.RawXml = null;
+ }
+
+ if (HasFileInput) FileInput.SectionXmlInfo.RawXml = null;
+ }
+
+ internal void ClearResult()
+ {
+ FileInput?.ClearResult();
+
+ if (LocationInputs != null) foreach (SectionInput input in LocationInputs) input.ClearResult();
+
+ Result = s_unevaluated;
+ ResultRuntimeObject = s_unevaluated;
+ }
+
+ private List<ConfigurationException> GetAllErrors()
+ {
+ List<ConfigurationException> allErrors = null;
+
+ if (HasLocationInputs)
+ foreach (SectionInput input in LocationInputs) ErrorsHelper.AddErrors(ref allErrors, input.Errors);
+
+ if (HasIndirectLocationInputs)
+ {
+ foreach (SectionInput input in IndirectLocationInputs)
+ ErrorsHelper.AddErrors(ref allErrors, input.Errors);
+ }
+
+ if (HasFileInput) ErrorsHelper.AddErrors(ref allErrors, FileInput.Errors);
+
+ return allErrors;
+ }
+
+ internal void ThrowOnErrors()
+ {
+ if (HasErrors) throw new ConfigurationErrorsException(GetAllErrors());
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/SectionUpdates.cs b/src/System.Configuration/src/System/Configuration/SectionUpdates.cs
new file mode 100644
index 0000000000..147f86e981
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/SectionUpdates.cs
@@ -0,0 +1,248 @@
+// 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;
+
+namespace System.Configuration
+{
+ internal class SectionUpdates
+ {
+ private readonly Hashtable _groups;
+ private readonly string _name;
+ private readonly Hashtable _sections;
+ private int _cMoved;
+ private int _cUnretrieved;
+ private Update _sectionGroupUpdate;
+
+ internal SectionUpdates(string name)
+ {
+ _name = name;
+ _groups = new Hashtable();
+ _sections = new Hashtable();
+ }
+
+ internal bool IsNew { get; set; }
+
+ internal bool IsEmpty => (_groups.Count == 0) && (_sections.Count == 0);
+
+ // Find the SectionUpdates for a configKey, and create it if it does not exist.
+ private SectionUpdates FindSectionUpdates(string configKey, bool isGroup)
+ {
+ string group, dummy;
+
+ if (isGroup) group = configKey;
+ else BaseConfigurationRecord.SplitConfigKey(configKey, out group, out dummy);
+
+ Debug.Assert(string.IsNullOrEmpty(_name), "FindSectionUpdates assumes search is from root record");
+ SectionUpdates sectionUpdates = this;
+ if (group.Length != 0)
+ {
+ // find the SectionUpdates for the group
+ string[] groups = group.Split(BaseConfigurationRecord.s_configPathSeparatorParams);
+ foreach (string groupPart in groups)
+ {
+ SectionUpdates sectionUpdatesChild = (SectionUpdates)sectionUpdates._groups[groupPart];
+ if (sectionUpdatesChild == null)
+ {
+ sectionUpdatesChild = new SectionUpdates(groupPart);
+ sectionUpdates._groups[groupPart] = sectionUpdatesChild;
+ }
+
+ sectionUpdates = sectionUpdatesChild;
+ }
+ }
+
+ return sectionUpdates;
+ }
+
+ // Recursively check whether this group has all new updates.
+ // An update is new if all sections are new and all subgroups are new.
+ internal void CompleteUpdates()
+ {
+ bool allSubgroupsAreNew = true;
+
+ // call CompleteUpdates() for all children
+ foreach (SectionUpdates sectionUpdates in _groups.Values)
+ {
+ sectionUpdates.CompleteUpdates();
+ if (!sectionUpdates.IsNew) allSubgroupsAreNew = false;
+ }
+
+ IsNew = allSubgroupsAreNew && (_cMoved == _sections.Count);
+ }
+
+ internal void AddSection(Update update)
+ {
+ SectionUpdates sectionUpdates = FindSectionUpdates(update.ConfigKey, false);
+ sectionUpdates._sections.Add(update.ConfigKey, update);
+
+ // Maintain counts.
+ sectionUpdates._cUnretrieved++;
+ if (update.Moved) sectionUpdates._cMoved++;
+ }
+
+ internal void AddSectionGroup(Update update)
+ {
+ SectionUpdates sectionUpdates = FindSectionUpdates(update.ConfigKey, true);
+ sectionUpdates._sectionGroupUpdate = update;
+ }
+
+ private Update GetUpdate(string configKey)
+ {
+ Update update = (Update)_sections[configKey];
+ if (update != null)
+ {
+ if (update.Retrieved) update = null;
+ else
+ {
+ update.Retrieved = true;
+ _cUnretrieved--;
+ if (update.Moved) _cMoved--;
+ }
+ }
+
+ return update;
+ }
+
+ internal DeclarationUpdate GetSectionGroupUpdate()
+ {
+ if ((_sectionGroupUpdate != null) && !_sectionGroupUpdate.Retrieved)
+ {
+ _sectionGroupUpdate.Retrieved = true;
+ return (DeclarationUpdate)_sectionGroupUpdate;
+ }
+
+ return null;
+ }
+
+ internal DefinitionUpdate GetDefinitionUpdate(string configKey)
+ {
+ return (DefinitionUpdate)GetUpdate(configKey);
+ }
+
+ internal DeclarationUpdate GetDeclarationUpdate(string configKey)
+ {
+ return (DeclarationUpdate)GetUpdate(configKey);
+ }
+
+ internal SectionUpdates GetSectionUpdatesForGroup(string group)
+ {
+ return (SectionUpdates)_groups[group];
+ }
+
+ // Return true if this section group or any of its children have unretrieved sections.
+ internal bool HasUnretrievedSections()
+ {
+ if ((_cUnretrieved > 0) || ((_sectionGroupUpdate != null) && !_sectionGroupUpdate.Retrieved)) return true;
+
+ foreach (SectionUpdates sectionUpdates in _groups.Values)
+ if (sectionUpdates.HasUnretrievedSections()) return true;
+
+ return false;
+ }
+
+ internal void MarkAsRetrieved()
+ {
+ _cUnretrieved = 0;
+ foreach (SectionUpdates sectionUpdates in _groups.Values) sectionUpdates.MarkAsRetrieved();
+ if (_sectionGroupUpdate != null) _sectionGroupUpdate.Retrieved = true;
+ }
+
+ internal void MarkGroupAsRetrieved(string groupName)
+ {
+ SectionUpdates sectionUpdates = _groups[groupName] as SectionUpdates;
+ sectionUpdates?.MarkAsRetrieved();
+ }
+
+ internal bool HasNewSectionGroups()
+ {
+ foreach (SectionUpdates sectionUpdates in _groups.Values)
+ if (sectionUpdates.IsNew)
+ return true;
+
+ return false;
+ }
+
+ // Return a sorted list of the names of unretrieved sections in this group.
+ internal string[] GetUnretrievedSectionNames()
+ {
+ if (_cUnretrieved == 0)
+ return null;
+
+ string[] sectionNames = new string[_cUnretrieved];
+ int i = 0;
+ foreach (Update update in _sections.Values)
+ if (!update.Retrieved)
+ {
+ sectionNames[i] = update.ConfigKey;
+ i++;
+ }
+
+ Array.Sort(sectionNames);
+ return sectionNames;
+ }
+
+ // Return a sorted list of the names of moved and unretrieved sections in this group.
+ internal string[] GetMovedSectionNames()
+ {
+ if (_cMoved == 0)
+ return null;
+
+ string[] sectionNames = new string[_cMoved];
+ int i = 0;
+ foreach (Update update in _sections.Values)
+ if (update.Moved && !update.Retrieved)
+ {
+ sectionNames[i] = update.ConfigKey;
+ i++;
+ }
+
+ Array.Sort(sectionNames);
+ return sectionNames;
+ }
+
+ // Return a sorted list of the names of groups with unretrieved sections.
+ internal string[] GetUnretrievedGroupNames()
+ {
+ ArrayList unretrievedGroups = new ArrayList();
+
+ foreach (DictionaryEntry de in _groups)
+ {
+ string group = (string)de.Key;
+ SectionUpdates sectionUpdates = (SectionUpdates)de.Value;
+ if (sectionUpdates.HasUnretrievedSections()) unretrievedGroups.Add(group);
+ }
+
+ if (unretrievedGroups.Count == 0)
+ return null;
+
+ string[] groupNames = new string[unretrievedGroups.Count];
+ unretrievedGroups.CopyTo(groupNames);
+ Array.Sort(groupNames);
+ return groupNames;
+ }
+
+ // Return a sorted list of the names of new section groups with unretrieved sections.
+ internal string[] GetNewGroupNames()
+ {
+ ArrayList newsGroups = new ArrayList();
+
+ foreach (DictionaryEntry de in _groups)
+ {
+ string group = (string)de.Key;
+ SectionUpdates sectionUpdates = (SectionUpdates)de.Value;
+ if (sectionUpdates.IsNew && sectionUpdates.HasUnretrievedSections()) newsGroups.Add(group);
+ }
+
+ if (newsGroups.Count == 0)
+ return null;
+
+ string[] groupNames = new string[newsGroups.Count];
+ newsGroups.CopyTo(groupNames);
+ Array.Sort(groupNames);
+ return groupNames;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/SectionXmlInfo.cs b/src/System.Configuration/src/System/Configuration/SectionXmlInfo.cs
new file mode 100644
index 0000000000..6f5d7cb5d2
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/SectionXmlInfo.cs
@@ -0,0 +1,66 @@
+// 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.Configuration.Internal;
+
+namespace System.Configuration
+{
+ internal sealed class SectionXmlInfo : IConfigErrorInfo
+ {
+ // the config path of the configuration record where this directive was defined
+
+ internal SectionXmlInfo(
+ string configKey, string definitionConfigPath, string targetConfigPath, string subPath,
+ string filename, int lineNumber, object streamVersion,
+ string rawXml, string configSource, string configSourceStreamName, object configSourceStreamVersion,
+ string protectionProviderName, OverrideModeSetting overrideMode, bool skipInChildApps)
+ {
+ ConfigKey = configKey;
+ DefinitionConfigPath = definitionConfigPath;
+ TargetConfigPath = targetConfigPath;
+ SubPath = subPath;
+ Filename = filename;
+ LineNumber = lineNumber;
+ StreamVersion = streamVersion;
+ RawXml = rawXml;
+ ConfigSource = configSource;
+ ConfigSourceStreamName = configSourceStreamName;
+ ProtectionProviderName = protectionProviderName;
+ OverrideModeSetting = overrideMode;
+ SkipInChildApps = skipInChildApps;
+ }
+
+ // other access methods
+ internal object StreamVersion { get; set; }
+
+ internal string ConfigSource { get; set; }
+
+ internal string ConfigSourceStreamName { get; set; }
+
+ internal object ConfigSourceStreamVersion
+ {
+ set { }
+ }
+
+ internal string ConfigKey { get; }
+
+ internal string DefinitionConfigPath { get; }
+
+ internal string TargetConfigPath { get; set; }
+
+ internal string SubPath { get; }
+
+ internal string RawXml { get; set; }
+
+ internal string ProtectionProviderName { get; set; }
+
+ internal OverrideModeSetting OverrideModeSetting { get; set; }
+
+ internal bool SkipInChildApps { get; set; }
+
+ public string Filename { get; }
+
+ public int LineNumber { get; set; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/SimpleBitVector32.cs b/src/System.Configuration/src/System/Configuration/SimpleBitVector32.cs
new file mode 100644
index 0000000000..a7c76e41d7
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/SimpleBitVector32.cs
@@ -0,0 +1,32 @@
+// 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.Configuration
+{
+ // This is a cut down copy of System.Collections.Specialized.BitVector32. The
+ // reason this is here is because it is used rather intensively by Control and
+ // WebControl. As a result, being able to inline this operations results in a
+ // measurable performance gain, at the expense of some maintainability.
+ [Serializable]
+ internal struct SimpleBitVector32
+ {
+ internal SimpleBitVector32(int data)
+ {
+ Data = data;
+ }
+
+ internal int Data { get; private set; }
+
+ internal bool this[int bit]
+ {
+ get { return (Data & bit) == bit; }
+ set
+ {
+ int data = Data;
+ if (value) Data = data | bit;
+ else Data = data & ~bit;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/StreamInfo.cs b/src/System.Configuration/src/System/Configuration/StreamInfo.cs
new file mode 100644
index 0000000000..70706bd9f5
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/StreamInfo.cs
@@ -0,0 +1,46 @@
+// 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.Configuration
+{
+ // Information about a stream used in configuration
+ internal class StreamInfo
+ {
+ // the configSource directive that generated this stream, null for a full config file
+
+ internal StreamInfo(string sectionName, string configSource, string streamName)
+ {
+ SectionName = sectionName;
+ ConfigSource = configSource;
+ StreamName = streamName;
+ }
+
+ private StreamInfo() { }
+
+ internal string SectionName { get; private set; }
+
+ internal string ConfigSource { get; private set; }
+
+ internal string StreamName { get; private set; }
+
+ internal bool IsMonitored { get; set; }
+
+ internal object Version { get; set; }
+
+ internal StreamInfo Clone()
+ {
+ StreamInfo clone = new StreamInfo
+ {
+ SectionName = SectionName,
+ ConfigSource = ConfigSource,
+ StreamName = StreamName,
+ IsMonitored = IsMonitored,
+ Version = Version
+ };
+
+
+ return clone;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/StreamUpdate.cs b/src/System.Configuration/src/System/Configuration/StreamUpdate.cs
new file mode 100644
index 0000000000..4bf52aa937
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/StreamUpdate.cs
@@ -0,0 +1,21 @@
+// 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.Configuration
+{
+ internal class StreamUpdate
+ {
+ internal StreamUpdate(string newStreamname)
+ {
+ NewStreamname = newStreamname;
+ }
+
+ // desired new stream name
+ internal string NewStreamname { get; }
+
+ // indicates whether the change from the old stream name
+ // to the new stream name has been completed.
+ internal bool WriteCompleted { get; set; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/StringAttributeCollection.cs b/src/System.Configuration/src/System/Configuration/StringAttributeCollection.cs
new file mode 100644
index 0000000000..0aa56440e6
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/StringAttributeCollection.cs
@@ -0,0 +1,147 @@
+// 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.Specialized;
+using System.Text;
+
+namespace System.Configuration
+{
+ public sealed class CommaDelimitedStringCollection : StringCollection
+ {
+ private bool _modified;
+ private string _originalString;
+
+ public CommaDelimitedStringCollection()
+ {
+ IsReadOnly = false;
+ _modified = false;
+ _originalString = ToString();
+ }
+
+ public bool IsModified => _modified || (ToString() != _originalString);
+
+ public new bool IsReadOnly { get; private set; }
+
+ public new string this[int index]
+ {
+ get { return base[index]; }
+ set
+ {
+ ThrowIfReadOnly();
+ ThrowIfContainsDelimiter(value);
+ _modified = true;
+ base[index] = value.Trim();
+ }
+ }
+
+ internal void FromString(string list)
+ {
+ char[] delimiters = { ',' };
+ if (list != null)
+ {
+ string[] items = list.Split(delimiters);
+ foreach (string item in items)
+ {
+ string trimmedItem = item.Trim();
+ if (trimmedItem.Length != 0) Add(item.Trim());
+ }
+ }
+ _originalString = ToString();
+ IsReadOnly = false;
+ _modified = false;
+ }
+
+ public override string ToString()
+ {
+ if (Count <= 0) return null;
+
+ StringBuilder sb = new StringBuilder();
+ foreach (string str in this)
+ {
+ ThrowIfContainsDelimiter(str);
+ // Since the add methods are not virtual they could still add bad data
+ // by casting the collection to a string collection. This check will catch
+ // it before serialization, late is better than never.
+ sb.Append(str.Trim());
+ sb.Append(',');
+ }
+
+ if (sb.Length > 0) sb.Length = sb.Length - 1;
+ return sb.Length == 0 ? null : sb.ToString();
+ }
+
+ private void ThrowIfReadOnly()
+ {
+ if (IsReadOnly) throw new ConfigurationErrorsException(SR.Config_base_read_only);
+ }
+
+ private static void ThrowIfContainsDelimiter(string value)
+ {
+ if (value.Contains(","))
+ throw new ConfigurationErrorsException(string.Format(SR.Config_base_value_cannot_contain, ","));
+ }
+
+ public void SetReadOnly()
+ {
+ IsReadOnly = true;
+ }
+
+ public new void Add(string value)
+ {
+ ThrowIfReadOnly();
+ ThrowIfContainsDelimiter(value);
+ _modified = true;
+ base.Add(value.Trim());
+ }
+
+ public new void AddRange(string[] range)
+ {
+ ThrowIfReadOnly();
+ _modified = true;
+ foreach (string str in range)
+ {
+ ThrowIfContainsDelimiter(str);
+ base.Add(str.Trim());
+ }
+ }
+
+ public new void Clear()
+ {
+ ThrowIfReadOnly();
+ _modified = true;
+ base.Clear();
+ }
+
+ public new void Insert(int index, string value)
+ {
+ ThrowIfReadOnly();
+ ThrowIfContainsDelimiter(value);
+ _modified = true;
+ base.Insert(index, value.Trim());
+ }
+
+ public new void Remove(string value)
+ {
+ ThrowIfReadOnly();
+ ThrowIfContainsDelimiter(value);
+ _modified = true;
+ base.Remove(value.Trim());
+ }
+
+ public CommaDelimitedStringCollection Clone()
+ {
+ CommaDelimitedStringCollection copy = new CommaDelimitedStringCollection();
+
+ // Copy all values
+ foreach (string str in this) copy.Add(str);
+
+ // Copy Attributes
+ copy._modified = false;
+ copy.IsReadOnly = IsReadOnly;
+ copy._originalString = _originalString;
+
+ return copy;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/StringUtil.cs b/src/System.Configuration/src/System/Configuration/StringUtil.cs
new file mode 100644
index 0000000000..e0ffdc3b09
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/StringUtil.cs
@@ -0,0 +1,38 @@
+// 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.Configuration
+{
+ internal static class StringUtil
+ {
+ internal static bool EqualsOrBothNullOrEmpty(string s1, string s2)
+ {
+ return string.Equals(s1 ?? string.Empty, s2 ?? string.Empty, StringComparison.Ordinal);
+ }
+
+ internal static bool EqualsIgnoreCase(string s1, string s2)
+ {
+ return string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase);
+ }
+
+ internal static bool StartsWithOrdinal(string s1, string s2)
+ {
+ if (s2 == null) return false;
+ return 0 == string.Compare(s1, 0, s2, 0, s2.Length, StringComparison.Ordinal);
+ }
+
+ internal static bool StartsWithOrdinalIgnoreCase(string s1, string s2)
+ {
+ if (s2 == null) return false;
+ return 0 == string.Compare(s1, 0, s2, 0, s2.Length, StringComparison.OrdinalIgnoreCase);
+ }
+
+ internal static string[] ObjectArrayToStringArray(object[] objectArray)
+ {
+ string[] stringKeys = new string[objectArray.Length];
+ objectArray.CopyTo(stringKeys, 0);
+ return stringKeys;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/StringValidator.cs b/src/System.Configuration/src/System/Configuration/StringValidator.cs
new file mode 100644
index 0000000000..05b0506524
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/StringValidator.cs
@@ -0,0 +1,57 @@
+// 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.Configuration
+{
+ public class StringValidator : ConfigurationValidatorBase
+ {
+ private readonly string _invalidChars;
+ private readonly int _maxLength;
+ private readonly int _minLength;
+
+ public StringValidator(int minLength)
+ : this(minLength, int.MaxValue, null)
+ { }
+
+ public StringValidator(int minLength, int maxLength)
+ : this(minLength, maxLength, null)
+ { }
+
+ public StringValidator(int minLength, int maxLength, string invalidCharacters)
+ {
+ _minLength = minLength;
+ _maxLength = maxLength;
+ _invalidChars = invalidCharacters;
+ }
+
+ public override bool CanValidate(Type type)
+ {
+ return type == typeof(string);
+ }
+
+ public override void Validate(object value)
+ {
+ ValidatorUtils.HelperParamValidation(value, typeof(string));
+
+ string data = value as string;
+ int len = data?.Length ?? 0;
+
+ if (len < _minLength)
+ throw new ArgumentException(string.Format(SR.Validator_string_min_length, _minLength));
+ if (len > _maxLength)
+ throw new ArgumentException(string.Format(SR.Validator_string_max_length, _maxLength));
+
+ // Check if the string contains any invalid characters
+ if ((len > 0) && !string.IsNullOrEmpty(_invalidChars))
+ {
+ char[] array = new char[_invalidChars.Length];
+
+ _invalidChars.CopyTo(0, array, 0, _invalidChars.Length);
+
+ if (data.IndexOfAny(array) != -1)
+ throw new ArgumentException(string.Format(SR.Validator_string_invalid_chars, _invalidChars));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/StringValidatorAttribute.cs b/src/System.Configuration/src/System/Configuration/StringValidatorAttribute.cs
new file mode 100644
index 0000000000..abdc502bb2
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/StringValidatorAttribute.cs
@@ -0,0 +1,42 @@
+// 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.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class StringValidatorAttribute : ConfigurationValidatorAttribute
+ {
+ private int _maxLength = int.MaxValue;
+ private int _minLength;
+
+ public override ConfigurationValidatorBase ValidatorInstance
+ => new StringValidator(_minLength, _maxLength, InvalidCharacters);
+
+ public int MinLength
+ {
+ get { return _minLength; }
+ set
+ {
+ if (_maxLength < value)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.Validator_min_greater_than_max);
+
+ _minLength = value;
+ }
+ }
+
+ public int MaxLength
+ {
+ get { return _maxLength; }
+ set
+ {
+ if (_minLength > value)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.Validator_min_greater_than_max);
+
+ _maxLength = value;
+ }
+ }
+
+ public string InvalidCharacters { get; set; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/SubclassTypeValidator.cs b/src/System.Configuration/src/System/Configuration/SubclassTypeValidator.cs
new file mode 100644
index 0000000000..f1e907c0f5
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/SubclassTypeValidator.cs
@@ -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.
+
+namespace System.Configuration
+{
+ // This class validates that the value is a subclass of a specified type
+ public sealed class SubclassTypeValidator : ConfigurationValidatorBase
+ {
+ private readonly Type _base;
+
+ public SubclassTypeValidator(Type baseClass)
+ {
+ if (baseClass == null)
+ throw new ArgumentNullException(nameof(baseClass));
+
+ _base = baseClass;
+ }
+
+ public override bool CanValidate(Type type)
+ {
+ return type == typeof(Type);
+ }
+
+ public override void Validate(object value)
+ {
+ if (value == null) return;
+
+ // Make a check here since value.GetType() returns RuntimeType rather then Type
+ if (!(value is Type)) ValidatorUtils.HelperParamValidation(value, typeof(Type));
+
+ if (!_base.IsAssignableFrom((Type)value))
+ {
+ throw new ArgumentException(string.Format(SR.Subclass_validator_error, ((Type)value).FullName,
+ _base.FullName));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/SubclassTypeValidatorAttribute.cs b/src/System.Configuration/src/System/Configuration/SubclassTypeValidatorAttribute.cs
new file mode 100644
index 0000000000..5a1613822d
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/SubclassTypeValidatorAttribute.cs
@@ -0,0 +1,19 @@
+// 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.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class SubclassTypeValidatorAttribute : ConfigurationValidatorAttribute
+ {
+ public SubclassTypeValidatorAttribute(Type baseClass)
+ {
+ BaseClass = baseClass;
+ }
+
+ public override ConfigurationValidatorBase ValidatorInstance => new SubclassTypeValidator(BaseClass);
+
+ public Type BaseClass { get; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/TimeSpanMinutesConverter.cs b/src/System.Configuration/src/System/Configuration/TimeSpanMinutesConverter.cs
new file mode 100644
index 0000000000..52cc93d6c6
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/TimeSpanMinutesConverter.cs
@@ -0,0 +1,29 @@
+// 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.Globalization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ public class TimeSpanMinutesConverter : ConfigurationConverterBase
+ {
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ ValidateType(value, typeof(TimeSpan));
+
+ long data = (long)((TimeSpan)value).TotalMinutes;
+ return data.ToString(CultureInfo.InvariantCulture);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ Debug.Assert(data is string, "data is string");
+
+ long min = long.Parse((string)data, CultureInfo.InvariantCulture);
+ return TimeSpan.FromMinutes(min);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/TimeSpanMinutesOrInfiniteConverter.cs b/src/System.Configuration/src/System/Configuration/TimeSpanMinutesOrInfiniteConverter.cs
new file mode 100644
index 0000000000..fce43e156d
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/TimeSpanMinutesOrInfiniteConverter.cs
@@ -0,0 +1,27 @@
+// 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.Globalization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ public sealed class TimeSpanMinutesOrInfiniteConverter : TimeSpanMinutesConverter
+ {
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ ValidateType(value, typeof(TimeSpan));
+
+ return (TimeSpan)value == TimeSpan.MaxValue ? "Infinite" : base.ConvertTo(ctx, ci, value, type);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ Debug.Assert(data is string, "data is string");
+
+ return (string)data == "Infinite" ? TimeSpan.MaxValue : base.ConvertFrom(ctx, ci, data);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/TimeSpanSecondsConverter.cs b/src/System.Configuration/src/System/Configuration/TimeSpanSecondsConverter.cs
new file mode 100644
index 0000000000..d28c83d27c
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/TimeSpanSecondsConverter.cs
@@ -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.Globalization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ public class TimeSpanSecondsConverter : ConfigurationConverterBase
+ {
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ ValidateType(value, typeof(TimeSpan));
+
+ long data = (long)((TimeSpan)value).TotalSeconds;
+
+ return data.ToString(CultureInfo.InvariantCulture);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ Debug.Assert(data is string, "data is string");
+ long min;
+ try
+ {
+ min = long.Parse((string)data, CultureInfo.InvariantCulture);
+ }
+ catch
+ {
+ throw new ArgumentException(SR.Converter_timespan_not_in_second);
+ }
+ return TimeSpan.FromSeconds(min);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/TimeSpanSecondsOrInfiniteConverter.cs b/src/System.Configuration/src/System/Configuration/TimeSpanSecondsOrInfiniteConverter.cs
new file mode 100644
index 0000000000..17b46b825e
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/TimeSpanSecondsOrInfiniteConverter.cs
@@ -0,0 +1,27 @@
+// 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.Globalization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ public sealed class TimeSpanSecondsOrInfiniteConverter : TimeSpanSecondsConverter
+ {
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ ValidateType(value, typeof(TimeSpan));
+
+ return (TimeSpan)value == TimeSpan.MaxValue ? "Infinite" : base.ConvertTo(ctx, ci, value, type);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ Debug.Assert(data is string, "data is string");
+
+ return (string)data == "Infinite" ? TimeSpan.MaxValue : base.ConvertFrom(ctx, ci, data);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/TimeSpanValidator.cs b/src/System.Configuration/src/System/Configuration/TimeSpanValidator.cs
new file mode 100644
index 0000000000..e5bef4a00a
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/TimeSpanValidator.cs
@@ -0,0 +1,58 @@
+// 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.Configuration
+{
+ public class TimeSpanValidator : ConfigurationValidatorBase
+ {
+ private readonly ValidationFlags _flags;
+ private readonly TimeSpan _maxValue;
+ private readonly TimeSpan _minValue;
+ private readonly long _resolution;
+
+ public TimeSpanValidator(TimeSpan minValue, TimeSpan maxValue)
+ : this(minValue, maxValue, false, 0)
+ { }
+
+ public TimeSpanValidator(TimeSpan minValue, TimeSpan maxValue, bool rangeIsExclusive)
+ : this(minValue, maxValue, rangeIsExclusive, 0)
+ { }
+
+ public TimeSpanValidator(TimeSpan minValue, TimeSpan maxValue, bool rangeIsExclusive, long resolutionInSeconds)
+ {
+ if (resolutionInSeconds < 0) throw new ArgumentOutOfRangeException(nameof(resolutionInSeconds));
+
+ if (minValue > maxValue)
+ throw new ArgumentOutOfRangeException(nameof(minValue), SR.Validator_min_greater_than_max);
+
+ _minValue = minValue;
+ _maxValue = maxValue;
+ _resolution = resolutionInSeconds;
+
+ _flags = rangeIsExclusive ? ValidationFlags.ExclusiveRange : ValidationFlags.None;
+ }
+
+ public override bool CanValidate(Type type)
+ {
+ return type == typeof(TimeSpan);
+ }
+
+ public override void Validate(object value)
+ {
+ ValidatorUtils.HelperParamValidation(value, typeof(TimeSpan));
+
+ ValidatorUtils.ValidateScalar((TimeSpan)value,
+ _minValue,
+ _maxValue,
+ _resolution,
+ _flags == ValidationFlags.ExclusiveRange);
+ }
+
+ private enum ValidationFlags
+ {
+ None = 0x0000,
+ ExclusiveRange = 0x0001, // If set the value must be outside of the range instead of inside
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/TimeSpanValidatorAttribute.cs b/src/System.Configuration/src/System/Configuration/TimeSpanValidatorAttribute.cs
new file mode 100644
index 0000000000..48d6118643
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/TimeSpanValidatorAttribute.cs
@@ -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.Globalization;
+
+namespace System.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class TimeSpanValidatorAttribute : ConfigurationValidatorAttribute
+ {
+ public const string TimeSpanMinValue = "-10675199.02:48:05.4775808";
+ public const string TimeSpanMaxValue = "10675199.02:48:05.4775807";
+
+ public override ConfigurationValidatorBase ValidatorInstance
+ => new TimeSpanValidator(MinValue, MaxValue, ExcludeRange);
+
+ public TimeSpan MinValue { get; private set; } = TimeSpan.MinValue;
+
+ public TimeSpan MaxValue { get; private set; } = TimeSpan.MaxValue;
+
+ public string MinValueString
+ {
+ get { return MinValue.ToString(); }
+ set
+ {
+ TimeSpan timeValue = TimeSpan.Parse(value, CultureInfo.InvariantCulture);
+
+ if (MaxValue < timeValue)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.Validator_min_greater_than_max);
+
+ MinValue = timeValue;
+ }
+ }
+
+ public string MaxValueString
+ {
+ get { return MaxValue.ToString(); }
+ set
+ {
+ TimeSpan timeValue = TimeSpan.Parse(value, CultureInfo.InvariantCulture);
+
+ if (MinValue > timeValue)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.Validator_min_greater_than_max);
+
+ MaxValue = timeValue;
+ }
+ }
+
+ public bool ExcludeRange { get; set; } = false;
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/TypeNameConverter.cs b/src/System.Configuration/src/System/Configuration/TypeNameConverter.cs
new file mode 100644
index 0000000000..42dc47b5e5
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/TypeNameConverter.cs
@@ -0,0 +1,33 @@
+// 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.Globalization;
+using System.ComponentModel;
+
+namespace System.Configuration
+{
+ public sealed class TypeNameConverter : ConfigurationConverterBase
+ {
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ // Make the check here since for some reason value.GetType is not System.Type but RuntimeType
+ if (!(value is Type)) ValidateType(value, typeof(Type));
+
+ string result = null;
+
+ if (value != null) result = ((Type)value).AssemblyQualifiedName;
+
+ return result;
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ Type result = TypeUtil.GetType((string)data, false);
+
+ if (result == null) throw new ArgumentException(string.Format(SR.Type_cannot_be_resolved, (string)data));
+
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/TypeUtil.cs b/src/System.Configuration/src/System/Configuration/TypeUtil.cs
new file mode 100644
index 0000000000..7d46bd4ba1
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/TypeUtil.cs
@@ -0,0 +1,188 @@
+// 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.Configuration.Internal;
+using System.Reflection;
+
+namespace System.Configuration
+{
+ internal static class TypeUtil
+ {
+ // Deliberately not being explicit about the versions to make
+ // things simpler for consumers of System.Configuration.
+ private static string[] s_implicitAssemblies =
+ {
+ // Historically we would find types in System.dll here.
+ // This is because Configuration used to live in System.dll
+ // and by resolution rules, typenames without an assembly
+ // specifier would be found there:
+ //
+ // (current executing assembly -> mscorlib / now s.p.c.l)
+ //
+ // When Configuration types moved to System.Configuration
+ // the implicit lookup for System had to be added to keep
+ // existing configuration files working.
+
+ // We also need to find types in mscorlib.dll as currently
+ // only types found in System.Private.CoreLib.dll are
+ // implicitly resolved. If this changes we can remove the
+ // explicit mscorlib lookup.
+
+ "mscorlib",
+ "System",
+
+ // TODO: ISSUE #14528
+ // System facade isn't currently part of the framework
+ // package. Once it is added the following locations can
+ // be removed. There are tests for types from each of
+ // these locations.
+ "System.Runtime",
+ "System.Collections",
+ "System.Collections.Concurrent",
+ "System.Collections.Specialized",
+ };
+
+ /// <summary>
+ /// Find type references that used to be found without assembly names
+ /// </summary>
+ private static Type GetImplicitType(string typeString)
+ {
+ // Since the config APIs were originally implemented in System.dll,
+ // references to types without assembly names could be resolved if
+ // they lived in System.dll.
+ //
+ // On NetFX we would try to emulate that behavior by looking in
+ // System. As types have moved around in CoreFX- we'll try to load
+ // from the a variety of assemblies to mimick the old behavior.
+
+ // Don't bother to look around if we've already got something that
+ // is clearly not a simple type name.
+ if (string.IsNullOrEmpty(typeString) || typeString.IndexOf(',') != -1)
+ return null;
+
+ // Ignore all exceptions, otherwise callers will get unexpected
+ // exceptions not related to the original failure to load the
+ // desired type.
+
+ // First attempt is against our own System.Configuration types
+ try
+ {
+ Assembly configurationAssembly = typeof(ConfigurationException).Assembly;
+ Type type = configurationAssembly.GetType(typeString, false);
+ if (type != null)
+ return type;
+ }
+ catch { }
+
+ foreach (string assembly in s_implicitAssemblies)
+ {
+ try
+ {
+ Type type = Type.GetType($"{typeString}, {assembly}");
+ if (type != null)
+ return type;
+ }
+ catch { }
+ }
+
+ return null;
+ }
+
+ // Get the type specified by typeString. If it fails, try to retrieve it
+ // as a type from System.dll. If that fails, return null or throw the original
+ // exception as indicated by throwOnError.
+ internal static Type GetType(string typeString, bool throwOnError)
+ {
+ Type type = null;
+ Exception originalException = null;
+
+ try
+ {
+ type = Type.GetType(typeString, throwOnError);
+ }
+ catch (Exception e)
+ {
+ originalException = e;
+ }
+
+ if (type == null)
+ {
+ type = GetImplicitType(typeString);
+ if ((type == null) && (originalException != null))
+ throw originalException;
+ }
+
+ return type;
+ }
+
+ // Ask the host to get the type specified by typeString. If it fails, try to retrieve it
+ // as a type from System.dll. If that fails, return null or throw the original
+ // exception as indicated by throwOnError.
+ internal static Type GetType(IInternalConfigHost host, string typeString, bool throwOnError)
+ {
+ Type type = null;
+ Exception originalException = null;
+
+ try
+ {
+ type = host.GetConfigType(typeString, throwOnError);
+ }
+ catch (Exception e)
+ {
+ originalException = e;
+ }
+
+ if (type == null)
+ {
+ type = GetImplicitType(typeString);
+ if ((type == null) && (originalException != null))
+ throw originalException;
+ }
+
+ return type;
+ }
+
+ internal static T CreateInstance<T>(string typeString)
+ {
+ Type type = GetType(typeString, true);
+ VerifyAssignableType(typeof(T), type, true);
+ return (T)Activator.CreateInstance(type, true);
+ }
+
+ internal static object CreateInstance(Type type)
+ {
+ return Activator.CreateInstance(type, true);
+ }
+
+ internal static ConstructorInfo GetConstructor(Type type, Type baseType, bool throwOnError)
+ {
+ type = VerifyAssignableType(baseType, type, throwOnError);
+ if (type == null)
+ return null;
+
+ const BindingFlags BindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
+
+ ConstructorInfo ctor = type.GetConstructor(BindingFlags, null, CallingConventions.HasThis, Type.EmptyTypes,
+ null);
+ if ((ctor == null) && throwOnError)
+ throw new TypeLoadException(string.Format(SR.TypeNotPublic, type.AssemblyQualifiedName));
+
+ return ctor;
+ }
+
+ internal static Type VerifyAssignableType(Type baseType, Type type, bool throwOnError)
+ {
+ if (baseType.IsAssignableFrom(type))
+ return type;
+
+ if (throwOnError)
+ {
+ throw new TypeLoadException(
+ string.Format(SR.Config_type_doesnt_inherit_from_type, type.FullName, baseType.FullName));
+ }
+
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/Update.cs b/src/System.Configuration/src/System/Configuration/Update.cs
new file mode 100644
index 0000000000..49d16a634d
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/Update.cs
@@ -0,0 +1,26 @@
+// 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.Configuration
+{
+ // Represents an update to a configuration section, either in its
+ // declaration or its definition.
+ internal abstract class Update
+ {
+ internal Update(string configKey, bool moved, string updatedXml)
+ {
+ ConfigKey = configKey;
+ Moved = moved;
+ UpdatedXml = updatedXml;
+ }
+
+ internal string ConfigKey { get; }
+
+ internal bool Moved { get; }
+
+ internal string UpdatedXml { get; }
+
+ internal bool Retrieved { get; set; }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/UpdateConfigHost.cs b/src/System.Configuration/src/System/Configuration/UpdateConfigHost.cs
new file mode 100644
index 0000000000..9a634db3a6
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/UpdateConfigHost.cs
@@ -0,0 +1,134 @@
+// 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.Specialized;
+using System.Configuration.Internal;
+using System.Diagnostics;
+using System.IO;
+
+namespace System.Configuration
+{
+ // Configuration host that intercepts calls to filename functions
+ // to support SaveAs to an alternate file stream.
+ internal class UpdateConfigHost : DelegatingConfigHost
+ {
+ private HybridDictionary _streams; // oldStreamname -> StreamUpdate
+
+ internal UpdateConfigHost(IInternalConfigHost host)
+ {
+ // Delegate to the host provided.
+ Host = host;
+ }
+
+ // Add a stream to the list of streams to intercept.
+ //
+ // Parameters:
+ // alwaysIntercept - If true, then don't check whether the old stream and the new stream are the same.
+ // SaveAs() will set this to true if oldStreamname is actually referring to a stream
+ // on a remote machine.
+ internal void AddStreamname(string oldStreamname, string newStreamname, bool alwaysIntercept)
+ {
+ // After reviewing all the code paths, oldStreamname shouldn't be Null or Empty.
+ // It actually doesn't make much sense if we're asked to intercept an null or empty stream.
+ Debug.Assert(!string.IsNullOrEmpty(oldStreamname));
+
+ if (string.IsNullOrEmpty(oldStreamname)) return;
+
+ if (!alwaysIntercept && StringUtil.EqualsIgnoreCase(oldStreamname, newStreamname)) return;
+
+ if (_streams == null) _streams = new HybridDictionary(true);
+
+ _streams[oldStreamname] = new StreamUpdate(newStreamname);
+ }
+
+ // Get the new stream name for a stream if a new name exists, otherwise
+ // return the original stream name.
+ internal string GetNewStreamname(string oldStreamname)
+ {
+ StreamUpdate streamUpdate = GetStreamUpdate(oldStreamname, false);
+ return streamUpdate != null ? streamUpdate.NewStreamname : oldStreamname;
+ }
+
+ // Get the StreamUpdate for a stream.
+ // If alwaysIntercept is true, then the StreamUpdate is
+ // always returned if it exists.
+ // If alwaysIntercept is false, then only return the StreamUpdate
+ // if the new stream has been successfully written to.
+ private StreamUpdate GetStreamUpdate(string oldStreamname, bool alwaysIntercept)
+ {
+ if (_streams == null)
+ return null;
+
+ StreamUpdate streamUpdate = (StreamUpdate)_streams[oldStreamname];
+ if ((streamUpdate != null) && !alwaysIntercept && !streamUpdate.WriteCompleted) streamUpdate = null;
+
+ return streamUpdate;
+ }
+
+ public override object GetStreamVersion(string streamName)
+ {
+ StreamUpdate streamUpdate = GetStreamUpdate(streamName, false);
+ return streamUpdate != null
+ ? InternalConfigHost.StaticGetStreamVersion(streamUpdate.NewStreamname)
+ : Host.GetStreamVersion(streamName);
+ }
+
+ public override Stream OpenStreamForRead(string streamName)
+ {
+ StreamUpdate streamUpdate = GetStreamUpdate(streamName, false);
+ return streamUpdate != null
+ ? InternalConfigHost.StaticOpenStreamForRead(streamUpdate.NewStreamname)
+ : Host.OpenStreamForRead(streamName);
+ }
+
+ public override Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext)
+ {
+ // Always attempt to write to the new stream name if it exists.
+ StreamUpdate streamUpdate = GetStreamUpdate(streamName, true);
+ if (streamUpdate != null)
+ {
+ return InternalConfigHost.StaticOpenStreamForWrite(
+ streamUpdate.NewStreamname, templateStreamName, ref writeContext);
+ }
+ return Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext);
+ }
+
+ public override void WriteCompleted(string streamName, bool success, object writeContext)
+ {
+ StreamUpdate streamUpdate = GetStreamUpdate(streamName, true);
+ if (streamUpdate != null)
+ {
+ InternalConfigHost.StaticWriteCompleted(streamUpdate.NewStreamname, success, writeContext);
+
+ // Mark the write as having successfully completed, so that subsequent calls
+ // to Read() will use the new stream name.
+ if (success) streamUpdate.WriteCompleted = true;
+ }
+ else
+ {
+ Host.WriteCompleted(streamName, success, writeContext);
+ }
+ }
+
+ public override bool IsConfigRecordRequired(string configPath)
+ {
+ return true;
+ }
+
+ public override void DeleteStream(string streamName)
+ {
+ StreamUpdate streamUpdate = GetStreamUpdate(streamName, false);
+ if (streamUpdate != null) InternalConfigHost.StaticDeleteStream(streamUpdate.NewStreamname);
+ else Host.DeleteStream(streamName);
+ }
+
+ public override bool IsFile(string streamName)
+ {
+ StreamUpdate streamUpdate = GetStreamUpdate(streamName, false);
+ return streamUpdate != null
+ ? InternalConfigHost.StaticIsFile(streamUpdate.NewStreamname)
+ : Host.IsFile(streamName);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/UrlPath.cs b/src/System.Configuration/src/System/Configuration/UrlPath.cs
new file mode 100644
index 0000000000..94856b7c55
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/UrlPath.cs
@@ -0,0 +1,139 @@
+// 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.IO;
+
+namespace System.Configuration
+{
+ internal static class UrlPath
+ {
+ private const string FileUrlLocal = "file:///";
+ private const string FileUrlUnc = "file:";
+
+ internal static string GetDirectoryOrRootName(string path)
+ {
+ return Path.GetDirectoryName(path) ?? Path.GetPathRoot(path);
+ }
+
+ // Determine if subdir is equal to or a subdirectory of dir.
+ // For example, c:\mydir\subdir is a subdirectory of c:\mydir
+ // Account for optional trailing backslashes.
+ internal static bool IsEqualOrSubdirectory(string dir, string subdir)
+ {
+ if (string.IsNullOrEmpty(dir))
+ return true;
+
+ if (string.IsNullOrEmpty(subdir))
+ return false;
+
+ // Compare up to but not including trailing backslash
+ int lDir = dir.Length;
+ if (dir[lDir - 1] == '\\') lDir -= 1;
+
+ int lSubdir = subdir.Length;
+ if (subdir[lSubdir - 1] == '\\') lSubdir -= 1;
+
+ if (lSubdir < lDir)
+ return false;
+
+ if (string.Compare(dir, 0, subdir, 0, lDir, StringComparison.OrdinalIgnoreCase) != 0)
+ return false;
+
+ // Check subdir that character following length of dir is a backslash
+ return (lSubdir <= lDir) || (subdir[lDir] == '\\');
+ }
+
+ // NOTE: This function is also present in fx\src\xsp\system\web\util\urlpath.cs
+ // Please propagate any changes to that file.
+ //
+ // Determine if subpath is equal to or a subpath of path.
+ // For example, /myapp/foo.aspx is a subpath of /myapp
+ // Account for optional trailing slashes.
+ internal static bool IsEqualOrSubpath(string path, string subpath)
+ {
+ return IsEqualOrSubpathImpl(path, subpath, false);
+ }
+
+ // Determine if subpath is a subpath of path, but return
+ // false if subpath & path are the same.
+ // For example, /myapp/foo.aspx is a subpath of /myapp
+ // Account for optional trailing slashes.
+ internal static bool IsSubpath(string path, string subpath)
+ {
+ return IsEqualOrSubpathImpl(path, subpath, true);
+ }
+
+ private static bool IsEqualOrSubpathImpl(string path, string subpath, bool excludeEqual)
+ {
+ if (string.IsNullOrEmpty(path))
+ return true;
+
+ if (string.IsNullOrEmpty(subpath))
+ return false;
+
+ // Compare up to but not including trailing slash
+ int lPath = path.Length;
+ if (path[lPath - 1] == '/') lPath -= 1;
+
+ int lSubpath = subpath.Length;
+ if (subpath[lSubpath - 1] == '/') lSubpath -= 1;
+
+ if (lSubpath < lPath)
+ return false;
+
+ if (excludeEqual && (lSubpath == lPath))
+ return false;
+
+ if (string.Compare(path, 0, subpath, 0, lPath, StringComparison.OrdinalIgnoreCase) != 0)
+ return false;
+
+ // Check subpath that character following length of path is a slash
+ return (lSubpath <= lPath) || (subpath[lPath] == '/');
+ }
+
+ private static bool IsDirectorySeparatorChar(char ch)
+ {
+ return (ch == '\\') || (ch == '/');
+ }
+
+ private static bool IsAbsoluteLocalPhysicalPath(string path)
+ {
+ if ((path == null) || (path.Length < 3))
+ return false;
+
+ // e.g c:\foo
+ return (path[1] == ':') && IsDirectorySeparatorChar(path[2]);
+ }
+
+ private static bool IsAbsoluteUncPhysicalPath(string path)
+ {
+ if ((path == null) || (path.Length < 3))
+ return false;
+
+ // e.g \\server\share\foo or //server/share/foo
+ return IsDirectorySeparatorChar(path[0]) && IsDirectorySeparatorChar(path[1]);
+ }
+
+ internal static string ConvertFileNameToUrl(string fileName)
+ {
+ string prefix;
+
+ if (IsAbsoluteLocalPhysicalPath(fileName)) prefix = FileUrlLocal;
+ else
+ {
+ if (IsAbsoluteUncPhysicalPath(fileName)) prefix = FileUrlUnc;
+ else
+ {
+ // We should never get here, but if we do we are likely to have
+ // serious security problems, so throw an exception rather than simply
+ // asserting.
+ throw ExceptionUtil.ParameterInvalid("filename");
+ }
+ }
+
+ string newFileName = prefix + fileName.Replace('\\', '/');
+ return newFileName;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ValidatorCallback.cs b/src/System.Configuration/src/System/Configuration/ValidatorCallback.cs
new file mode 100644
index 0000000000..20445d3c4d
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ValidatorCallback.cs
@@ -0,0 +1,9 @@
+// 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.Configuration
+{
+ // Call back validator. Uses a validation callback to avoid creation of new types
+ public delegate void ValidatorCallback(object value);
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/ValidatorUtils.cs b/src/System.Configuration/src/System/Configuration/ValidatorUtils.cs
new file mode 100644
index 0000000000..3ebccbb4f2
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/ValidatorUtils.cs
@@ -0,0 +1,89 @@
+// 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.Globalization;
+
+namespace System.Configuration
+{
+ internal static class ValidatorUtils
+ {
+ public static void HelperParamValidation(object value, Type allowedType)
+ {
+ if (value == null) return;
+
+ if (value.GetType() != allowedType)
+ throw new ArgumentException(SR.Validator_value_type_invalid, string.Empty);
+ }
+
+ public static void ValidateScalar<T>(T value, T min, T max, T resolution, bool exclusiveRange)
+ where T : IComparable<T>
+ {
+ ValidateRangeImpl(value, min, max, exclusiveRange);
+
+ // Validate the resolution
+ ValidateResolution(resolution.ToString(), Convert.ToInt64(value, CultureInfo.InvariantCulture),
+ Convert.ToInt64(resolution, CultureInfo.InvariantCulture));
+ }
+
+ private static void ValidateRangeImpl<T>(T value, T min, T max, bool exclusiveRange) where T : IComparable<T>
+ {
+ IComparable<T> itfValue = value;
+
+ bool valueIsInRange = itfValue.CompareTo(min) >= 0;
+
+ if (valueIsInRange && (itfValue.CompareTo(max) > 0))
+ {
+ // TRUE: value > max
+ valueIsInRange = false;
+ }
+
+ if (valueIsInRange ^ exclusiveRange) return;
+
+ // Throw range validation error
+ string error;
+
+ if (min.Equals(max))
+ {
+ // First group of errors - the min and max range are the same. i.e. the valid value must be the same/equal to the min(max)
+ error = exclusiveRange
+ ? SR.Validation_scalar_range_violation_not_different
+ : SR.Validation_scalar_range_violation_not_equal;
+ }
+ else
+ {
+ // Second group of errors: min != max. I.e. its a range
+ error = exclusiveRange
+ ? SR.Validation_scalar_range_violation_not_outside_range
+ : SR.Validation_scalar_range_violation_not_in_range;
+ }
+
+ throw new ArgumentException(string.Format(CultureInfo.InvariantCulture,
+ error,
+ min.ToString(),
+ max.ToString()));
+ }
+
+ private static void ValidateResolution(string resolutionAsString, long value, long resolution)
+ {
+ Debug.Assert(resolution > 0, "resolution > 0");
+
+ if (value % resolution != 0)
+ throw new ArgumentException(string.Format(SR.Validator_scalar_resolution_violation, resolutionAsString));
+ }
+
+ public static void ValidateScalar(TimeSpan value, TimeSpan min, TimeSpan max, long resolutionInSeconds,
+ bool exclusiveRange)
+ {
+ ValidateRangeImpl(value, min, max, exclusiveRange);
+
+ // Validate the resolution
+ if (resolutionInSeconds > 0)
+ {
+ ValidateResolution(TimeSpan.FromSeconds(resolutionInSeconds).ToString(), value.Ticks,
+ resolutionInSeconds * TimeSpan.TicksPerSecond);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/WhiteSpaceTrimStringConverter.cs b/src/System.Configuration/src/System/Configuration/WhiteSpaceTrimStringConverter.cs
new file mode 100644
index 0000000000..0d03bdc765
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/WhiteSpaceTrimStringConverter.cs
@@ -0,0 +1,26 @@
+// 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.Globalization;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace System.Configuration
+{
+ public sealed class WhiteSpaceTrimStringConverter : ConfigurationConverterBase
+ {
+ public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)
+ {
+ ValidateType(value, typeof(string));
+
+ return value == null ? string.Empty : ((string)value).Trim();
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
+ {
+ Debug.Assert(data is string, "data is string");
+ return ((string)data).Trim();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/XmlUtil.cs b/src/System.Configuration/src/System/Configuration/XmlUtil.cs
new file mode 100644
index 0000000000..999a99f2db
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/XmlUtil.cs
@@ -0,0 +1,1110 @@
+// 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.Configuration.Internal;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Xml;
+
+namespace System.Configuration
+{
+ // XmlTextReader Helper class.
+ //
+ // Provides the following services:
+ //
+ // * Reader methods that verify restrictions on the XML that can be contained in a config file.
+ // * Methods to copy the reader stream to a writer stream.
+ // * Method to copy a configuration section to a string.
+ // * Methods to format a string of XML.
+ //
+ // Errors found during read are accumlated in a ConfigurationSchemaErrors object.
+ internal sealed class XmlUtil : IDisposable, IConfigErrorInfo
+ {
+ private const int MaxLineWidth = 60;
+
+ // Offset from where the reader reports the LinePosition of an Xml Node to
+ // the start of that representation in text.
+ private static readonly int[] s_positionOffset =
+ {
+ 0, // None,
+ 1, // Element, <elem
+ -1, // Attribute, N/A
+ 0, // Text,
+ 9, // CDATA, <![CDATA[
+ 1, // EntityReference, &lt
+ -1, // Entity, N/A
+ 2, // ProcessingInstruction, <?pi
+ 4, // Comment, <!--
+ -1, // Document, N/A
+ 10, // DocumentType, <!DOCTYPE
+ -1, // DocumentFragment, N/A
+ -1, // Notation, N/A
+ 0, // Whitespace,
+ 0, // SignificantWhitespace,
+ 2, // EndElement, />
+ -1, // EndEntity, N/A
+ 2, // XmlDeclaration <?xml
+ };
+
+ private StringWriter _cachedStringWriter;
+ private int _lastLineNumber;
+ private int _lastLinePosition;
+
+ private Stream _stream;
+
+ internal XmlUtil(Stream stream, string name, bool readToFirstElement) :
+ this(stream, name, readToFirstElement, new ConfigurationSchemaErrors())
+ { }
+
+ internal XmlUtil(Stream stream, string name, bool readToFirstElement, ConfigurationSchemaErrors schemaErrors)
+ {
+ try
+ {
+ Filename = name;
+ _stream = stream;
+ Reader = new XmlTextReader(_stream) { XmlResolver = null };
+
+ // config reads never require a resolver
+
+ SchemaErrors = schemaErrors;
+ _lastLineNumber = 1;
+ _lastLinePosition = 1;
+
+ // When parsing config that we don't intend to copy, skip all content
+ // before the first element.
+ if (!readToFirstElement) return;
+ Reader.WhitespaceHandling = WhitespaceHandling.None;
+
+ bool done = false;
+ while (!done && Reader.Read())
+ switch (Reader.NodeType)
+ {
+ case XmlNodeType.XmlDeclaration:
+ case XmlNodeType.Comment:
+ case XmlNodeType.DocumentType:
+ break;
+ case XmlNodeType.Element:
+ done = true;
+ break;
+ default:
+ throw new ConfigurationErrorsException(SR.Config_base_unrecognized_element, this);
+ }
+ }
+ catch
+ {
+ ReleaseResources();
+ throw;
+ }
+ }
+
+ // Return the line position of the reader, compensating for the reader's offset
+ // for nodes such as an XmlElement.
+ internal int TrueLinePosition
+ {
+ get
+ {
+ int trueLinePosition = Reader.LinePosition - GetPositionOffset(Reader.NodeType);
+ Debug.Assert(trueLinePosition > 0, "trueLinePosition > 0");
+ return trueLinePosition;
+ }
+ }
+
+ internal XmlTextReader Reader { get; private set; }
+
+ internal ConfigurationSchemaErrors SchemaErrors { get; }
+
+ public string Filename { get; }
+
+ public int LineNumber => Reader.LineNumber;
+
+ public void Dispose()
+ {
+ ReleaseResources();
+ }
+
+ private static int GetPositionOffset(XmlNodeType nodeType)
+ {
+ return s_positionOffset[(int)nodeType];
+ }
+
+ private void ReleaseResources()
+ {
+ if (Reader != null)
+ {
+ // closing _reader will also close underlying _stream
+ Reader.Close();
+ Reader = null;
+ }
+ else
+ _stream?.Close();
+
+ _stream = null;
+
+ if (_cachedStringWriter != null)
+ {
+ _cachedStringWriter.Close();
+ _cachedStringWriter = null;
+ }
+ }
+
+ // Read until the Next Element element, or we hit
+ // the end of the file.
+ internal void ReadToNextElement()
+ {
+ while (Reader.Read())
+ if (Reader.MoveToContent() == XmlNodeType.Element)
+ {
+ // We found an element, so return
+ return;
+ }
+ // We must of hit end of file
+ }
+
+ /// <summary>
+ /// Skip this element and its children, then read to next start element,
+ /// or until we hit end of file.
+ /// </summary>
+ internal void SkipToNextElement()
+ {
+ Reader.Skip();
+ Reader.MoveToContent();
+
+ while (!Reader.EOF && (Reader.NodeType != XmlNodeType.Element))
+ {
+ Reader.Read();
+ Reader.MoveToContent();
+ }
+ }
+
+ /// <summary>
+ /// Read to the next start element, and verify that all XML nodes read are permissible.
+ /// </summary>
+ internal void StrictReadToNextElement(ExceptionAction action)
+ {
+ while (Reader.Read())
+ {
+ // optimize for the common case
+ if (Reader.NodeType == XmlNodeType.Element) return;
+
+ VerifyIgnorableNodeType(action);
+ }
+ }
+
+ /// <summary>
+ /// Skip this element and its children, then read to next start element, or until we hit
+ /// end of file. Verify that nodes that are read after the skipped element are permissible.
+ /// </summary>
+ internal void StrictSkipToNextElement(ExceptionAction action)
+ {
+ Reader.Skip();
+
+ while (!Reader.EOF && (Reader.NodeType != XmlNodeType.Element))
+ {
+ VerifyIgnorableNodeType(action);
+ Reader.Read();
+ }
+ }
+
+ /// <summary>
+ /// Skip until we hit the end element for our parent, and verify that nodes at the
+ /// parent level are permissible.
+ /// </summary>
+ internal void StrictSkipToOurParentsEndElement(ExceptionAction action)
+ {
+ int currentDepth = Reader.Depth;
+
+ // Skip everything at out current level
+ while (Reader.Depth >= currentDepth) Reader.Skip();
+
+ while (!Reader.EOF && (Reader.NodeType != XmlNodeType.EndElement))
+ {
+ VerifyIgnorableNodeType(action);
+ Reader.Read();
+ }
+ }
+
+ /// <summary>
+ /// Add an error if the node type is not permitted by the configuration schema.
+ /// </summary>
+ internal void VerifyIgnorableNodeType(ExceptionAction action)
+ {
+ XmlNodeType nodeType = Reader.NodeType;
+
+ if ((nodeType != XmlNodeType.Comment) && (nodeType != XmlNodeType.EndElement))
+ {
+ ConfigurationException ex = new ConfigurationErrorsException(
+ SR.Config_base_unrecognized_element,
+ this);
+
+ SchemaErrors.AddError(ex, action);
+ }
+ }
+
+ /// <summary>
+ /// Add an error if there are attributes that have not been examined, and are therefore unrecognized.
+ /// </summary>
+ internal void VerifyNoUnrecognizedAttributes(ExceptionAction action)
+ {
+ if (Reader.MoveToNextAttribute())
+ AddErrorUnrecognizedAttribute(action);
+ }
+
+ /// <summary>
+ /// Add an error if the retrieved attribute is null, and therefore not present.
+ /// </summary>
+ internal bool VerifyRequiredAttribute(object requiredAttribute, string attrName, ExceptionAction action)
+ {
+ if (requiredAttribute == null)
+ {
+ AddErrorRequiredAttribute(attrName, action);
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ internal void AddErrorUnrecognizedAttribute(ExceptionAction action)
+ {
+ ConfigurationErrorsException ex = new ConfigurationErrorsException(
+ string.Format(SR.Config_base_unrecognized_attribute, Reader.Name),
+ this);
+
+ SchemaErrors.AddError(ex, action);
+ }
+
+ internal void AddErrorRequiredAttribute(string attrib, ExceptionAction action)
+ {
+ ConfigurationErrorsException ex = new ConfigurationErrorsException(
+ string.Format(SR.Config_missing_required_attribute, attrib, Reader.Name),
+ this);
+
+ SchemaErrors.AddError(ex, action);
+ }
+
+ internal void AddErrorReservedAttribute(ExceptionAction action)
+ {
+ ConfigurationErrorsException ex = new ConfigurationErrorsException(
+ string.Format(SR.Config_reserved_attribute, Reader.Name),
+ this);
+
+ SchemaErrors.AddError(ex, action);
+ }
+
+ internal void AddErrorUnrecognizedElement(ExceptionAction action)
+ {
+ ConfigurationErrorsException ex = new ConfigurationErrorsException(
+ SR.Config_base_unrecognized_element,
+ this);
+
+ SchemaErrors.AddError(ex, action);
+ }
+
+ internal void VerifyAndGetNonEmptyStringAttribute(ExceptionAction action, out string newValue)
+ {
+ if (!string.IsNullOrEmpty(Reader.Value)) newValue = Reader.Value;
+ else
+ {
+ newValue = null;
+
+ ConfigurationException ex = new ConfigurationErrorsException(
+ string.Format(SR.Empty_attribute, Reader.Name),
+ this);
+
+ SchemaErrors.AddError(ex, action);
+ }
+ }
+
+ /// <summary>
+ /// Verify and Retrieve the Boolean Attribute. If it is not
+ /// a valid value then log an error and set the value to a given default.
+ /// </summary>
+ internal void VerifyAndGetBooleanAttribute(
+ ExceptionAction action, bool defaultValue, out bool newValue)
+ {
+ switch (Reader.Value)
+ {
+ case "true":
+ newValue = true;
+ break;
+ case "false":
+ newValue = false;
+ break;
+ default:
+ newValue = defaultValue;
+ SchemaErrors.AddError(
+ new ConfigurationErrorsException(string.Format(SR.Config_invalid_boolean_attribute, Reader.Name), this),
+ action);
+ break;
+ }
+ }
+
+ // Copy an XML element, then continue copying until we've hit the next element
+ // or exited this depth.
+ internal bool CopyOuterXmlToNextElement(XmlUtilWriter utilWriter, bool limitDepth)
+ {
+ CopyElement(utilWriter);
+
+ // Copy until reaching the next element, or if limitDepth == true until we've exited this depth.
+ return CopyReaderToNextElement(utilWriter, limitDepth);
+ }
+
+ // Copy an XML element but skip all its child elements, then continue copying until we've hit the next element.
+ internal bool SkipChildElementsAndCopyOuterXmlToNextElement(XmlUtilWriter utilWriter)
+ {
+ bool isEmptyElement = Reader.IsEmptyElement;
+ int startingLine = Reader.LineNumber;
+#if DEBUG
+ int depth = Reader.Depth;
+#endif
+
+ Debug.Assert(Reader.NodeType == XmlNodeType.Element, "Reader.NodeType == XmlNodeType.Element");
+
+ CopyXmlNode(utilWriter);
+
+ // See if we need to skip any child element
+ if (!isEmptyElement)
+ {
+ while (Reader.NodeType != XmlNodeType.EndElement)
+ if (Reader.NodeType == XmlNodeType.Element)
+ {
+ Reader.Skip();
+
+ // We need to skip all the whitespaces following a skipped element.
+ // - If the whitespaces don't contain /r/n, then it's okay to skip them
+ // as part of the element.
+ // - If the whitespaces contain /r/n, not skipping them will result
+ // in a redundant emtpy line being copied.
+ if (Reader.NodeType == XmlNodeType.Whitespace) Reader.Skip();
+ }
+ else
+ {
+ // We want to preserve other content, e.g. comments.
+ CopyXmlNode(utilWriter);
+ }
+
+ if (Reader.LineNumber != startingLine)
+ {
+ // The whitespace in front of the EndElement was skipped above.
+ // We need to append spaces to compensate for that.
+ utilWriter.AppendSpacesToLinePosition(TrueLinePosition);
+ }
+
+#if DEBUG
+ Debug.Assert(Reader.Depth == depth, "We should be at the same depth as the opening Element");
+#endif
+
+ // Copy the end element.
+ CopyXmlNode(utilWriter);
+ }
+
+ return CopyReaderToNextElement(utilWriter, true);
+ }
+
+ // Copy the reader until we hit an element, or we've exited the current depth.
+ internal bool CopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth)
+ {
+ bool moreToRead = true;
+
+ // Set the depth if we limit copying to this depth
+ int depth;
+ if (limitDepth)
+ {
+ // there is nothing in the element
+ if (Reader.NodeType == XmlNodeType.EndElement)
+ return true;
+
+ depth = Reader.Depth;
+ }
+ else depth = 0;
+
+ // Copy nodes until we've reached the desired depth, or until we hit an element.
+ do
+ {
+ if (Reader.NodeType == XmlNodeType.Element)
+ break;
+
+ if (Reader.Depth < depth) break;
+
+ moreToRead = CopyXmlNode(utilWriter);
+ } while (moreToRead);
+
+ return moreToRead;
+ }
+
+ // Skip over the current element and copy until the next element.
+ // This function removes the one blank line that would otherwise
+ // be inserted by simply skipping and copying to the next element
+ // in a situation like this:
+ //
+ // <!-- end of previous configSection -->
+ // <configSectionToDelete>
+ // <content />
+ // <moreContent />
+ // </configSectionToDelete>
+ // <!-- end of configSectionToDelete -->
+ // <nextConfigSection />
+ internal bool SkipAndCopyReaderToNextElement(XmlUtilWriter utilWriter, bool limitDepth)
+ {
+ Debug.Assert(Reader.NodeType == XmlNodeType.Element, "_reader.NodeType == XmlNodeType.Element");
+
+ // If the last line before the element is not blank, then we do not have to
+ // remove the blank line.
+ if (!utilWriter.IsLastLineBlank)
+ {
+ Reader.Skip();
+ return CopyReaderToNextElement(utilWriter, limitDepth);
+ }
+
+ // Set the depth if we limit copying to this depth
+ int depth = limitDepth ? Reader.Depth : 0;
+
+ // Skip over the element
+ Reader.Skip();
+
+ int lineNumberOfEndElement = Reader.LineNumber;
+
+ // Read until we hit a a non-whitespace node or reach the end
+ while (!Reader.EOF)
+ {
+ if (Reader.NodeType != XmlNodeType.Whitespace)
+ {
+ // If the next non-whitepace node is on another line,
+ // seek back to the beginning of the current blank line,
+ // skip a blank line of whitespace, and copy the remaining whitespace.
+ if (Reader.LineNumber > lineNumberOfEndElement)
+ {
+ utilWriter.SeekToLineStart();
+ utilWriter.AppendWhiteSpace(lineNumberOfEndElement + 1, 1, LineNumber, TrueLinePosition);
+ }
+
+ break;
+ }
+
+ Reader.Read();
+ }
+
+ // Copy nodes until we've reached the desired depth, or until we hit an element.
+ while (!Reader.EOF)
+ {
+ if (Reader.NodeType == XmlNodeType.Element)
+ break;
+
+ if (Reader.Depth < depth) break;
+
+ CopyXmlNode(utilWriter);
+ }
+
+ return !Reader.EOF;
+ }
+
+ // Copy an XML element and its children, up to and including the end element.
+ private void CopyElement(XmlUtilWriter utilWriter)
+ {
+ Debug.Assert(Reader.NodeType == XmlNodeType.Element, "_reader.NodeType== XmlNodeType.Element");
+
+ int depth = Reader.Depth;
+ bool isEmptyElement = Reader.IsEmptyElement;
+
+ // Copy current node
+ CopyXmlNode(utilWriter);
+
+ // Copy nodes while the depth is greater than the current depth.
+ while (Reader.Depth > depth) CopyXmlNode(utilWriter);
+
+ // Copy the end element.
+ if (!isEmptyElement) CopyXmlNode(utilWriter);
+ }
+
+ // Copy a single XML node, attempting to preserve whitespace.
+ // A side effect of this method is to advance the reader to the next node.
+ //
+ // PERFORMANCE NOTE: this function is used at runtime to copy a configuration section,
+ // and at designtime to copy an entire XML document.
+ //
+ // At designtime, this function needs to be able to copy a <!DOCTYPE declaration.
+ // Copying a <!DOCTYPE declaration is expensive, because due to limitations of the
+ // XmlReader API, we must track the position of the writer to accurately format it.
+ // Tracking the position of the writer is expensive, as it requires examining every
+ // character that is written for newline characters, and maintaining the seek position
+ // of the underlying stream at each new line, which in turn requires a stream flush.
+ //
+ // This function must NEVER require tracking the writer position to copy the Xml nodes
+ // that are used in a configuration section.
+ internal bool CopyXmlNode(XmlUtilWriter utilWriter)
+ {
+ // For nodes that have a closing string, such as "<element >"
+ // the XmlReader API does not give us the location of the closing string, e.g. ">".
+ // To correctly determine the location of the closing part, we advance the reader,
+ // determine the position of the next node, then work backwards to add whitespace
+ // and add the closing string.
+ string close = null;
+ int lineNumber = -1;
+ int linePosition = -1;
+
+ int readerLineNumber = 0;
+ int readerLinePosition = 0;
+ int writerLineNumber = 0;
+ int writerLinePosition = 0;
+ if (utilWriter.TrackPosition)
+ {
+ readerLineNumber = Reader.LineNumber;
+ readerLinePosition = Reader.LinePosition;
+ writerLineNumber = utilWriter.LineNumber;
+ writerLinePosition = utilWriter.LinePosition;
+ }
+
+ // We test the node type in the likely order of decreasing occurrence.
+ XmlNodeType nodeType = Reader.NodeType;
+ if (nodeType == XmlNodeType.Whitespace) utilWriter.Write(Reader.Value);
+ else
+ {
+ if (nodeType == XmlNodeType.Element)
+ {
+ close = Reader.IsEmptyElement ? "/>" : ">";
+
+ // get the line position after the element declaration:
+ // <element attr="value"
+ // ^
+ // linePosition
+ lineNumber = Reader.LineNumber;
+ linePosition = Reader.LinePosition + Reader.Name.Length;
+
+ utilWriter.Write('<');
+ utilWriter.Write(Reader.Name);
+
+ // Note that there is no way to get spacing between attribute name and value
+ // For example:
+ //
+ // <elem attr="value" />
+ //
+ // is reported with the same position as
+ //
+ // <elem attr = "value" />
+ //
+ // The first example has no spaces around '=', the second example does.
+ while (Reader.MoveToNextAttribute())
+ {
+ // get line position of the attribute declaration
+ // <element attr="value"
+ // ^
+ // attrLinePosition
+ int attrLineNumber = Reader.LineNumber;
+ int attrLinePosition = Reader.LinePosition;
+
+ // Write the whitespace before the attribute
+ utilWriter.AppendRequiredWhiteSpace(lineNumber, linePosition, attrLineNumber, attrLinePosition);
+
+ // Write the attribute and value
+ int charactersWritten = utilWriter.Write(Reader.Name);
+ charactersWritten += utilWriter.Write('=');
+ charactersWritten += utilWriter.AppendAttributeValue(Reader);
+
+ // Update position. Note that the attribute value is escaped to always be on a single line.
+ lineNumber = attrLineNumber;
+ linePosition = attrLinePosition + charactersWritten;
+ }
+ }
+ else
+ {
+ if (nodeType == XmlNodeType.EndElement)
+ {
+ close = ">";
+
+ // get line position after the end element declaration:
+ // </element >
+ // ^
+ // linePosition
+ lineNumber = Reader.LineNumber;
+ linePosition = Reader.LinePosition + Reader.Name.Length;
+
+ utilWriter.Write("</");
+ utilWriter.Write(Reader.Name);
+ }
+ else
+ {
+ if (nodeType == XmlNodeType.Comment) utilWriter.AppendComment(Reader.Value);
+ else
+ {
+ if (nodeType == XmlNodeType.Text) utilWriter.AppendEscapeTextString(Reader.Value);
+ else
+ {
+ if (nodeType == XmlNodeType.XmlDeclaration)
+ {
+ close = "?>";
+
+ // get line position after the xml declaration:
+ // <?xml version="1.0"
+ // ^
+ // linePosition
+ lineNumber = Reader.LineNumber;
+ linePosition = Reader.LinePosition + 3;
+
+ utilWriter.Write("<?xml");
+
+ // Note that there is no way to get spacing between attribute name and value
+ // For example:
+ //
+ // <?xml attr="value" ?>
+ //
+ // is reported with the same position as
+ //
+ // <?xml attr = "value" ?>
+ //
+ // The first example has no spaces around '=', the second example does.
+ while (Reader.MoveToNextAttribute())
+ {
+ // get line position of the attribute declaration
+ // <?xml version="1.0"
+ // ^
+ // attrLinePosition
+ int attrLineNumber = Reader.LineNumber;
+ int attrLinePosition = Reader.LinePosition;
+
+ // Write the whitespace before the attribute
+ utilWriter.AppendRequiredWhiteSpace(lineNumber, linePosition, attrLineNumber,
+ attrLinePosition);
+
+ // Write the attribute and value
+ int charactersWritten = utilWriter.Write(Reader.Name);
+ charactersWritten += utilWriter.Write('=');
+ charactersWritten += utilWriter.AppendAttributeValue(Reader);
+
+ // Update position. Note that the attribute value is escaped to always be on a single line.
+ lineNumber = attrLineNumber;
+ linePosition = attrLinePosition + charactersWritten;
+ }
+
+ // Position reader at beginning of node
+ Reader.MoveToElement();
+ }
+ else
+ {
+ if (nodeType == XmlNodeType.SignificantWhitespace) utilWriter.Write(Reader.Value);
+ else
+ {
+ if (nodeType == XmlNodeType.ProcessingInstruction)
+ {
+ // Note that there is no way to get spacing between attribute name and value
+ // For example:
+ //
+ // <?pi "value" ?>
+ //
+ // is reported with the same position as
+ //
+ // <?pi "value" ?>
+ //
+ // The first example has one space between 'pi' and "value", the second has multiple spaces.
+ utilWriter.AppendProcessingInstruction(Reader.Name, Reader.Value);
+ }
+ else
+ {
+ if (nodeType == XmlNodeType.EntityReference)
+ utilWriter.AppendEntityRef(Reader.Name);
+ else
+ {
+ if (nodeType == XmlNodeType.CDATA)
+ utilWriter.AppendCData(Reader.Value);
+ else
+ {
+ if (nodeType == XmlNodeType.DocumentType)
+ {
+ // XmlNodeType.DocumentType has the following format:
+ //
+ // <!DOCTYPE rootElementName {(SYSTEM uriRef)|(PUBLIC id uriRef)} {[ dtdDecls ]} >
+ //
+ // The reader only gives us the position of 'rootElementName', so we must track what was
+ // written before "<!DOCTYPE" in order to correctly determine the position of the
+ // <!DOCTYPE tag
+ Debug.Assert(utilWriter.TrackPosition,
+ "utilWriter.TrackPosition");
+ int c = utilWriter.Write("<!DOCTYPE");
+
+ // Write the space between <!DOCTYPE and the rootElementName
+ utilWriter.AppendRequiredWhiteSpace(_lastLineNumber,
+ _lastLinePosition + c, Reader.LineNumber,
+ Reader.LinePosition);
+
+ // Write the rootElementName
+ utilWriter.Write(Reader.Name);
+
+ // Get the dtd declarations, if any
+ string dtdValue = null;
+ if (Reader.HasValue) dtdValue = Reader.Value;
+
+ // get line position after the !DOCTYPE declaration:
+ // <!DOCTYPE rootElement SYSTEM rootElementDtdUri >
+ // ^
+ // linePosition
+ lineNumber = Reader.LineNumber;
+ linePosition = Reader.LinePosition + Reader.Name.Length;
+
+ // Note that there is no way to get the spacing after PUBLIC or SYSTEM attributes and their values
+ if (Reader.MoveToFirstAttribute())
+ {
+ // Write the space before SYSTEM or PUBLIC
+ utilWriter.AppendRequiredWhiteSpace(lineNumber, linePosition,
+ Reader.LineNumber, Reader.LinePosition);
+
+ // Write SYSTEM or PUBLIC and the 1st value of the attribute
+ string attrName = Reader.Name;
+ utilWriter.Write(attrName);
+ utilWriter.AppendSpace();
+ utilWriter.AppendAttributeValue(Reader);
+ Reader.MoveToAttribute(0);
+
+ // If PUBLIC, write the second value of the attribute
+ if (attrName == "PUBLIC")
+ {
+ Reader.MoveToAttribute(1);
+ utilWriter.AppendSpace();
+ utilWriter.AppendAttributeValue(Reader);
+ Reader.MoveToAttribute(1);
+ }
+ }
+
+ // If there is a dtd, write it
+ if (!string.IsNullOrEmpty(dtdValue))
+ {
+ utilWriter.Write(" [");
+ utilWriter.Write(dtdValue);
+ utilWriter.Write(']');
+ }
+
+ utilWriter.Write('>');
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Advance the _reader so we can get the position of the next node.
+ bool moreToRead = Reader.Read();
+ nodeType = Reader.NodeType;
+
+ // Close the node we are copying.
+ if (close != null)
+ {
+ // Find the position of the close string, for example:
+ // <element > <subElement />
+ // ^
+ // closeLinePosition
+ int startOffset = GetPositionOffset(nodeType);
+ int closeLineNumber = Reader.LineNumber;
+ int closeLinePosition = Reader.LinePosition - startOffset - close.Length;
+
+ // Add whitespace up to the position of the close string
+ utilWriter.AppendWhiteSpace(lineNumber, linePosition, closeLineNumber, closeLinePosition);
+
+ // Write the close string
+ utilWriter.Write(close);
+ }
+
+ // Track the position of the reader based on the position of the reader
+ // before we copied this node and what we have written in copying the node.
+ // This allows us to determine the position of the <!DOCTYPE tag.
+ if (utilWriter.TrackPosition)
+ {
+ _lastLineNumber = readerLineNumber - writerLineNumber + utilWriter.LineNumber;
+
+ if (writerLineNumber == utilWriter.LineNumber)
+ _lastLinePosition = readerLinePosition - writerLinePosition + utilWriter.LinePosition;
+ else _lastLinePosition = utilWriter.LinePosition;
+ }
+
+ return moreToRead;
+ }
+
+ // Asuming that we are at an element, retrieve the text for that element
+ // and attributes that can be serialized to an xml file.
+ private string RetrieveFullOpenElementTag()
+ {
+ Debug.Assert(Reader.NodeType == XmlNodeType.Element,
+ "_reader.NodeType == NodeType.Element");
+
+ // Start with element tag name
+ StringBuilder element = new StringBuilder(64);
+ element.Append("<");
+ element.Append(Reader.Name);
+
+ // Add attributes
+ while (Reader.MoveToNextAttribute())
+ {
+ element.Append(" ");
+ element.Append(Reader.Name);
+ element.Append("=");
+ element.Append('\"');
+ element.Append(Reader.Value);
+ element.Append('\"');
+ }
+
+ // Now close the element tag
+ element.Append(">");
+
+ return element.ToString();
+ }
+
+ // Copy or replace an element node.
+ // If the element is an empty element, replace it with a formatted start element if either:
+ // * The contents of the start element string need updating.
+ // * The element needs to contain child elements.
+ //
+ // If the element is empty and is replaced with a start/end element pair, return a
+ // end element string with whitespace formatting; otherwise return null.
+ internal string UpdateStartElement(XmlUtilWriter utilWriter, string updatedStartElement, bool needsChildren,
+ int linePosition, int indent)
+ {
+ Debug.Assert(Reader.NodeType == XmlNodeType.Element, "_reader.NodeType == NodeType.Element");
+
+ string endElement = null;
+ bool needsEndElement = false;
+
+ string elementName = Reader.Name;
+
+ // If the element is empty, determine if a new end element is needed.
+ if (Reader.IsEmptyElement)
+ {
+ if ((updatedStartElement == null) && needsChildren) updatedStartElement = RetrieveFullOpenElementTag();
+
+ needsEndElement = updatedStartElement != null;
+ }
+
+ if (updatedStartElement == null)
+ {
+ // If no changes to the start element are required, just copy it.
+ CopyXmlNode(utilWriter);
+ }
+ else
+ {
+ // Format a new start element/end element pair
+ string updatedEndElement = "</" + elementName + ">";
+ string updatedElement = updatedStartElement + updatedEndElement;
+ string formattedElement = FormatXmlElement(updatedElement, linePosition, indent, true);
+
+ // Get the start and end element strings from the formatted element.
+ int iEndElement = formattedElement.LastIndexOf('\n') + 1;
+ string startElement;
+ if (needsEndElement)
+ {
+ endElement = formattedElement.Substring(iEndElement);
+
+ // Include a newline in the start element as we are expanding an empty element.
+ startElement = formattedElement.Substring(0, iEndElement);
+ }
+ else
+ {
+ // Omit the newline from the start element.
+ startElement = formattedElement.Substring(0, iEndElement - 2);
+ }
+
+ // Write the new start element.
+ utilWriter.Write(startElement);
+
+ // Skip over the existing start element.
+ Reader.Read();
+ }
+
+ return endElement;
+ }
+
+ // Create the cached string writer if it does not exist,
+ // otherwise reuse the existing buffer.
+ private void ResetCachedStringWriter()
+ {
+ if (_cachedStringWriter == null)
+ _cachedStringWriter = new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture);
+ else _cachedStringWriter.GetStringBuilder().Length = 0;
+ }
+
+ // Copy a configuration section to a string, and advance the reader.
+ internal string CopySection()
+ {
+ ResetCachedStringWriter();
+
+ // Preserve whitespace for sections for backcompat
+ WhitespaceHandling originalHandling = Reader.WhitespaceHandling;
+ Reader.WhitespaceHandling = WhitespaceHandling.All;
+
+ // Create string writer to write to
+ XmlUtilWriter utilWriter = new XmlUtilWriter(_cachedStringWriter, false);
+
+ // Copy the element
+ CopyElement(utilWriter);
+
+ // Reset whitespace handling
+ Reader.WhitespaceHandling = originalHandling;
+
+ if ((originalHandling == WhitespaceHandling.None) &&
+ (Reader.NodeType == XmlNodeType.Whitespace))
+ {
+ // If we were previously suppose to skip whitespace, and now we
+ // are at it, then lets jump to the next item
+ Reader.Read();
+ }
+
+ utilWriter.Flush();
+ string s = ((StringWriter)utilWriter.Writer).ToString();
+ return s;
+ }
+
+ /// <summary>
+ /// Format an Xml element to be written to the config file.
+ /// </summary>
+ /// <param name="xmlElement">the element</param>
+ /// <param name="linePosition">start position of the element</param>
+ /// <param name="indent">indent for each depth</param>
+ /// <param name="skipFirstIndent">skip indent for the first element?</param>
+ /// <returns></returns>
+ internal static string FormatXmlElement(string xmlElement, int linePosition, int indent, bool skipFirstIndent)
+ {
+ XmlParserContext context = new XmlParserContext(null, null, null, XmlSpace.Default, Encoding.Unicode);
+ XmlTextReader reader = new XmlTextReader(xmlElement, XmlNodeType.Element, context);
+
+ StringWriter stringWriter = new StringWriter(new StringBuilder(64), CultureInfo.InvariantCulture);
+ XmlUtilWriter utilWriter = new XmlUtilWriter(stringWriter, false);
+
+ // append newline before indent?
+ bool newLine = false;
+
+ // last node visited was text?
+ bool lastWasText = false;
+
+ // length of the stringbuilder after last indent with newline
+ int sbLengthLastNewLine = 0;
+
+ while (reader.Read())
+ {
+ XmlNodeType nodeType = reader.NodeType;
+
+ int lineWidth;
+ if (lastWasText)
+ {
+ utilWriter.Flush();
+ lineWidth = sbLengthLastNewLine - ((StringWriter)utilWriter.Writer).GetStringBuilder().Length;
+ }
+ else lineWidth = 0;
+
+ switch (nodeType)
+ {
+ case XmlNodeType.CDATA:
+ case XmlNodeType.Element:
+ case XmlNodeType.EndElement:
+ case XmlNodeType.Comment:
+ // Do not indent if the last node was text - doing so would add whitespace
+ // that is included as part of the text.
+ if (!skipFirstIndent && !lastWasText)
+ {
+ utilWriter.AppendIndent(linePosition, indent, reader.Depth, newLine);
+
+ if (newLine)
+ {
+ utilWriter.Flush();
+ sbLengthLastNewLine = ((StringWriter)utilWriter.Writer).GetStringBuilder().Length;
+ }
+ }
+ break;
+ }
+
+ lastWasText = false;
+ switch (nodeType)
+ {
+ case XmlNodeType.Whitespace:
+ break;
+ case XmlNodeType.SignificantWhitespace:
+ utilWriter.Write(reader.Value);
+ break;
+ case XmlNodeType.CDATA:
+ utilWriter.AppendCData(reader.Value);
+ break;
+ case XmlNodeType.ProcessingInstruction:
+ utilWriter.AppendProcessingInstruction(reader.Name, reader.Value);
+ break;
+ case XmlNodeType.Comment:
+ utilWriter.AppendComment(reader.Value);
+ break;
+ case XmlNodeType.Text:
+ utilWriter.AppendEscapeTextString(reader.Value);
+ lastWasText = true;
+ break;
+ case XmlNodeType.Element:
+ {
+ // Write "<elem"
+ utilWriter.Write('<');
+ utilWriter.Write(reader.Name);
+
+ lineWidth += reader.Name.Length + 2;
+
+ int c = reader.AttributeCount;
+ for (int i = 0; i < c; i++)
+ {
+ // Add new line if we've exceeded the line width
+ bool writeSpace;
+ if (lineWidth > MaxLineWidth)
+ {
+ utilWriter.AppendIndent(linePosition, indent, reader.Depth - 1, true);
+ lineWidth = indent;
+ writeSpace = false;
+ utilWriter.Flush();
+ sbLengthLastNewLine = ((StringWriter)utilWriter.Writer).GetStringBuilder().Length;
+ }
+ else writeSpace = true;
+
+ // Write the attribute
+ reader.MoveToNextAttribute();
+ utilWriter.Flush();
+ int startLength = ((StringWriter)utilWriter.Writer).GetStringBuilder().Length;
+ if (writeSpace) utilWriter.AppendSpace();
+
+ utilWriter.Write(reader.Name);
+ utilWriter.Write('=');
+ utilWriter.AppendAttributeValue(reader);
+ utilWriter.Flush();
+ lineWidth += ((StringWriter)utilWriter.Writer).GetStringBuilder().Length - startLength;
+ }
+ }
+
+ // position reader back on element
+ reader.MoveToElement();
+
+ // write closing tag
+ if (reader.IsEmptyElement) utilWriter.Write(" />");
+ else utilWriter.Write('>');
+
+ break;
+ case XmlNodeType.EndElement:
+ utilWriter.Write("</");
+ utilWriter.Write(reader.Name);
+ utilWriter.Write('>');
+ break;
+ case XmlNodeType.EntityReference:
+ utilWriter.AppendEntityRef(reader.Name);
+ break;
+
+ // Ignore <?xml and <!DOCTYPE nodes
+ // case XmlNodeType.XmlDeclaration:
+ // case XmlNodeType.DocumentType:
+ }
+
+ // put each new element on a new line
+ newLine = true;
+
+ // do not skip any more indents
+ skipFirstIndent = false;
+ }
+
+ utilWriter.Flush();
+ string s = ((StringWriter)utilWriter.Writer).ToString();
+ return s;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/src/System/Configuration/XmlUtilWriter.cs b/src/System.Configuration/src/System/Configuration/XmlUtilWriter.cs
new file mode 100644
index 0000000000..65d8fb9969
--- /dev/null
+++ b/src/System.Configuration/src/System/Configuration/XmlUtilWriter.cs
@@ -0,0 +1,388 @@
+// 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.Globalization;
+using System.IO;
+using System.Xml;
+
+namespace System.Configuration
+{
+ // A utility class for writing XML to a TextWriter.
+ //
+ // When this class is used to copy an XML document that may include a "<!DOCTYPE" directive,
+ // we must track what is written until the "<!DOCTYPE" or first document element is found.
+ // This is needed because the XML reader does not give us accurate spacing information
+ // for the beginning of the "<!DOCTYPE" element.
+ //
+ // Note that tracking this information is expensive, as it requires a scan of everything that is written
+ // until "<!DOCTYPE" or the first element is found.
+ //
+ // Note also that this class is used at runtime to copy sections, so performance of all
+ // writing functions directly affects application startup time.
+ internal class XmlUtilWriter
+ {
+ private const char Space = ' ';
+ private const string NewLine = "\r\n";
+
+ private static readonly string s_spaces8;
+ private static readonly string s_spaces4;
+ private static readonly string s_spaces2;
+ private readonly Stream _baseStream; // stream under TextWriter when tracking position
+ private object _lineStartCheckpoint; // checkpoint taken at the start of each line
+
+ static XmlUtilWriter()
+ {
+ s_spaces8 = new string(Space, 8);
+ s_spaces4 = new string(Space, 4);
+ s_spaces2 = new string(Space, 2);
+ }
+
+ internal XmlUtilWriter(TextWriter writer, bool trackPosition)
+ {
+ Writer = writer;
+ TrackPosition = trackPosition;
+ LineNumber = 1;
+ LinePosition = 1;
+ IsLastLineBlank = true;
+
+ if (TrackPosition)
+ {
+ _baseStream = ((StreamWriter)Writer).BaseStream;
+ _lineStartCheckpoint = CreateStreamCheckpoint();
+ }
+ }
+
+ internal TextWriter Writer { get; }
+
+ internal bool TrackPosition { get; }
+
+ internal int LineNumber { get; private set; }
+
+ internal int LinePosition { get; private set; }
+
+ internal bool IsLastLineBlank { get; private set; }
+
+ // Update the position after the character is written to the stream.
+ private void UpdatePosition(char ch)
+ {
+ switch (ch)
+ {
+ case '\r':
+ LineNumber++;
+ LinePosition = 1;
+ IsLastLineBlank = true;
+ break;
+ case '\n':
+ _lineStartCheckpoint = CreateStreamCheckpoint();
+ break;
+ case Space:
+ case '\t':
+ LinePosition++;
+ break;
+ default:
+ LinePosition++;
+ IsLastLineBlank = false;
+ break;
+ }
+ }
+
+ // Write a string to _writer.
+ // If we are tracking position, determine the line number and position
+ internal int Write(string s)
+ {
+ if (TrackPosition)
+ {
+ for (int i = 0; i < s.Length; i++)
+ {
+ char ch = s[i];
+ Writer.Write(ch);
+ UpdatePosition(ch);
+ }
+ }
+ else Writer.Write(s);
+
+ return s.Length;
+ }
+
+ // Write a character to _writer.
+ // If we are tracking position, determine the line number and position
+ internal int Write(char ch)
+ {
+ Writer.Write(ch);
+ if (TrackPosition) UpdatePosition(ch);
+ return 1;
+ }
+
+ internal void Flush()
+ {
+ Writer.Flush();
+ }
+
+ // Escape a text string
+ internal int AppendEscapeTextString(string s)
+ {
+ return AppendEscapeXmlString(s, false, 'A');
+ }
+
+ // Escape a XML string to preserve XML markup.
+ internal int AppendEscapeXmlString(string s, bool inAttribute, char quoteChar)
+ {
+ int charactersWritten = 0;
+ for (int i = 0; i < s.Length; i++)
+ {
+ char ch = s[i];
+
+ bool appendCharEntity = false;
+ string entityRef = null;
+ if (((ch < 32) && (ch != '\t') && (ch != '\r') && (ch != '\n')) || (ch > 0xFFFD))
+ appendCharEntity = true;
+ else
+ {
+ switch (ch)
+ {
+ case '<':
+ entityRef = "lt";
+ break;
+ case '>':
+ entityRef = "gt";
+ break;
+ case '&':
+ entityRef = "amp";
+ break;
+ case '\'':
+ if (inAttribute && (quoteChar == ch)) entityRef = "apos";
+ break;
+ case '"':
+ if (inAttribute && (quoteChar == ch)) entityRef = "quot";
+ break;
+ case '\n':
+ case '\r':
+ appendCharEntity = inAttribute;
+ break;
+ }
+ }
+
+ if (appendCharEntity) charactersWritten += AppendCharEntity(ch);
+ else
+ {
+ if (entityRef != null) charactersWritten += AppendEntityRef(entityRef);
+ else charactersWritten += Write(ch);
+ }
+ }
+
+ return charactersWritten;
+ }
+
+ internal int AppendEntityRef(string entityRef)
+ {
+ Write('&');
+ Write(entityRef);
+ Write(';');
+ return entityRef.Length + 2;
+ }
+
+ internal int AppendCharEntity(char ch)
+ {
+ string numberToWrite = ((int)ch).ToString("X", CultureInfo.InvariantCulture);
+ Write('&');
+ Write('#');
+ Write('x');
+ Write(numberToWrite);
+ Write(';');
+ return numberToWrite.Length + 4;
+ }
+
+ internal int AppendCData(string cdata)
+ {
+ Write("<![CDATA[");
+ Write(cdata);
+ Write("]]>");
+ return cdata.Length + 12;
+ }
+
+ internal int AppendProcessingInstruction(string name, string value)
+ {
+ Write("<?");
+ Write(name);
+ AppendSpace();
+ Write(value);
+ Write("?>");
+ return name.Length + value.Length + 5;
+ }
+
+ internal int AppendComment(string comment)
+ {
+ Write("<!--");
+ Write(comment);
+ Write("-->");
+ return comment.Length + 7;
+ }
+
+ internal int AppendAttributeValue(XmlTextReader reader)
+ {
+ int charactersWritten = 0;
+ char quote = reader.QuoteChar;
+
+ // In !DOCTYPE, quote is '\0' for second public attribute.
+ // Protect ourselves from writing invalid XML by always
+ // supplying a valid quote char.
+ if ((quote != '"') && (quote != '\'')) quote = '"';
+
+ charactersWritten += Write(quote);
+ while (reader.ReadAttributeValue())
+ if (reader.NodeType == XmlNodeType.Text)
+ charactersWritten += AppendEscapeXmlString(reader.Value, true, quote);
+ else charactersWritten += AppendEntityRef(reader.Name);
+
+ charactersWritten += Write(quote);
+ return charactersWritten;
+ }
+
+ // Append whitespace, ensuring there is at least one space.
+ internal int AppendRequiredWhiteSpace(int fromLineNumber, int fromLinePosition, int toLineNumber,
+ int toLinePosition)
+ {
+ int charactersWritten = AppendWhiteSpace(fromLineNumber, fromLinePosition, toLineNumber, toLinePosition);
+ if (charactersWritten == 0) charactersWritten += AppendSpace();
+
+ return charactersWritten;
+ }
+
+ internal int AppendWhiteSpace(int fromLineNumber, int fromLinePosition, int toLineNumber, int toLinePosition)
+ {
+ int charactersWritten = 0;
+ while (fromLineNumber++ < toLineNumber)
+ {
+ charactersWritten += AppendNewLine();
+ fromLinePosition = 1;
+ }
+
+ charactersWritten += AppendSpaces(toLinePosition - fromLinePosition);
+ return charactersWritten;
+ }
+
+ // Append indent
+ // linePosition - starting line position
+ // indent - number of spaces to indent each unit of depth
+ // depth - depth to indent
+ // newLine - insert new line before indent?
+ internal int AppendIndent(int linePosition, int indent, int depth, bool newLine)
+ {
+ int charactersWritten = 0;
+ if (newLine) charactersWritten += AppendNewLine();
+
+ int c = linePosition - 1 + indent * depth;
+ charactersWritten += AppendSpaces(c);
+ return charactersWritten;
+ }
+
+ // Write spaces up to the line position, taking into account the
+ // current line position of the writer.
+ internal int AppendSpacesToLinePosition(int linePosition)
+ {
+ if (linePosition <= 0) return 0;
+
+ int delta = linePosition - LinePosition;
+ if ((delta < 0) && IsLastLineBlank) SeekToLineStart();
+
+ return AppendSpaces(linePosition - LinePosition);
+ }
+
+ internal int AppendNewLine()
+ {
+ return Write(NewLine);
+ }
+
+ // Write spaces to the writer provided. Since we do not want waste
+ // memory by allocating do not use "new String(' ', count)".
+ internal int AppendSpaces(int count)
+ {
+ int c = count;
+ while (c > 0)
+ if (c >= 8)
+ {
+ Write(s_spaces8);
+ c -= 8;
+ }
+ else
+ {
+ if (c >= 4)
+ {
+ Write(s_spaces4);
+ c -= 4;
+ }
+ else
+ {
+ if (c >= 2)
+ {
+ Write(s_spaces2);
+ c -= 2;
+ }
+ else
+ {
+ Write(Space);
+ break;
+ }
+ }
+ }
+
+ return count > 0 ? count : 0;
+ }
+
+ internal int AppendSpace()
+ {
+ return Write(Space);
+ }
+
+ // Reset the stream to the beginning of the current blank line.
+ internal void SeekToLineStart()
+ {
+ RestoreStreamCheckpoint(_lineStartCheckpoint);
+ }
+
+ // Create a checkpoint that can be restored with RestoreStreamCheckpoint().
+ internal object CreateStreamCheckpoint()
+ {
+ return new StreamWriterCheckpoint(this);
+ }
+
+ // Restore the writer state that was recorded with CreateStreamCheckpoint().
+ internal void RestoreStreamCheckpoint(object o)
+ {
+ StreamWriterCheckpoint checkpoint = (StreamWriterCheckpoint)o;
+
+ Flush();
+
+ LineNumber = checkpoint._lineNumber;
+ LinePosition = checkpoint._linePosition;
+ IsLastLineBlank = checkpoint._isLastLineBlank;
+
+ _baseStream.Seek(checkpoint._streamPosition, SeekOrigin.Begin);
+ _baseStream.SetLength(checkpoint._streamLength);
+ _baseStream.Flush();
+ }
+
+ // Class that contains the state of the writer and its underlying stream.
+ private class StreamWriterCheckpoint
+ {
+ internal readonly bool _isLastLineBlank;
+ internal readonly int _lineNumber;
+ internal readonly int _linePosition;
+ internal readonly long _streamLength;
+ internal readonly long _streamPosition;
+
+ internal StreamWriterCheckpoint(XmlUtilWriter writer)
+ {
+ writer.Flush();
+ _lineNumber = writer.LineNumber;
+ _linePosition = writer.LinePosition;
+ _isLastLineBlank = writer.IsLastLineBlank;
+
+ writer._baseStream.Flush();
+ _streamPosition = writer._baseStream.Position;
+ _streamLength = writer._baseStream.Length;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Configuration/tests/Resources/Strings.Designer.cs b/src/System.Configuration/tests/Resources/Strings.Designer.cs
new file mode 100644
index 0000000000..9681c7f3ed
--- /dev/null
+++ b/src/System.Configuration/tests/Resources/Strings.Designer.cs
@@ -0,0 +1,226 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Resources {
+ using System;
+ using System.Reflection;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Strings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Strings() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Resources.Strings", typeof(Strings).GetTypeInfo().Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to No information about the exception is available..
+ /// </summary>
+ internal static string No_exception_information_available {
+ get {
+ return ResourceManager.GetString("No_exception_information_available", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The value must be different than {0}..
+ /// </summary>
+ internal static string Validation_scalar_range_violation_not_different {
+ get {
+ return ResourceManager.GetString("Validation_scalar_range_violation_not_different", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The value must be equal to {0}..
+ /// </summary>
+ internal static string Validation_scalar_range_violation_not_equal {
+ get {
+ return ResourceManager.GetString("Validation_scalar_range_violation_not_equal", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The value must be inside the range {0}-{1}..
+ /// </summary>
+ internal static string Validation_scalar_range_violation_not_in_range {
+ get {
+ return ResourceManager.GetString("Validation_scalar_range_violation_not_in_range", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The value must not be in the range {0}-{1}..
+ /// </summary>
+ internal static string Validation_scalar_range_violation_not_outside_range {
+ get {
+ return ResourceManager.GetString("Validation_scalar_range_violation_not_outside_range", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Only types derived from {0} are valid validator types..
+ /// </summary>
+ internal static string Validator_Attribute_param_not_validator {
+ get {
+ return ResourceManager.GetString("Validator_Attribute_param_not_validator", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The supplied validator does not support validating the configuration element type {0}..
+ /// </summary>
+ internal static string Validator_does_not_support_elem_type {
+ get {
+ return ResourceManager.GetString("Validator_does_not_support_elem_type", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The supplied validator does not support the type of the property &apos;{0}&apos;..
+ /// </summary>
+ internal static string Validator_does_not_support_prop_type {
+ get {
+ return ResourceManager.GetString("Validator_does_not_support_prop_type", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The configuration element &apos;{0}&apos; is not valid. The error is: {1}.
+ /// </summary>
+ internal static string Validator_element_not_valid {
+ get {
+ return ResourceManager.GetString("Validator_element_not_valid", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The supplied method name &apos;{0}&apos; was not found. The callback method must be a public static void method with one object parameter..
+ /// </summary>
+ internal static string Validator_method_not_found {
+ get {
+ return ResourceManager.GetString("Validator_method_not_found", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The upper range limit value must be greater than the lower range limit value..
+ /// </summary>
+ internal static string Validator_min_greater_than_max {
+ get {
+ return ResourceManager.GetString("Validator_min_greater_than_max", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Multiple validator attributes are not currently supported. The property &apos;{0}&apos; has more than one validator attribute associated with it..
+ /// </summary>
+ internal static string Validator_multiple_validator_attributes {
+ get {
+ return ResourceManager.GetString("Validator_multiple_validator_attributes", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The value must have a resolution of {0}..
+ /// </summary>
+ internal static string Validator_scalar_resolution_violation {
+ get {
+ return ResourceManager.GetString("Validator_scalar_resolution_violation", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The string cannot contain any of the following characters: &apos;{0}&apos;..
+ /// </summary>
+ internal static string Validator_string_invalid_chars {
+ get {
+ return ResourceManager.GetString("Validator_string_invalid_chars", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The string must be no more than {0} characters long..
+ /// </summary>
+ internal static string Validator_string_max_length {
+ get {
+ return ResourceManager.GetString("Validator_string_max_length", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The string must be at least {0} characters long..
+ /// </summary>
+ internal static string Validator_string_min_length {
+ get {
+ return ResourceManager.GetString("Validator_string_min_length", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The time span value must be positive..
+ /// </summary>
+ internal static string Validator_timespan_value_must_be_positive {
+ get {
+ return ResourceManager.GetString("Validator_timespan_value_must_be_positive", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The supplied value is not of type which the validator can process..
+ /// </summary>
+ internal static string Validator_value_type_invalid {
+ get {
+ return ResourceManager.GetString("Validator_value_type_invalid", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/System.Configuration/tests/Resources/Strings.resx b/src/System.Configuration/tests/Resources/Strings.resx
new file mode 100644
index 0000000000..822bc4e700
--- /dev/null
+++ b/src/System.Configuration/tests/Resources/Strings.resx
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 1.3
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">1.3</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1">this is my long string</data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ [base64 mime encoded serialized .NET Framework object]
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ [base64 mime encoded string representing a byte array form of the .NET Framework object]
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>1.3</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Validation_scalar_range_violation_not_different" xml:space="preserve">
+ <value>The value must be different than {0}.</value>
+ </data>
+ <data name="Validation_scalar_range_violation_not_equal" xml:space="preserve">
+ <value>The value must be equal to {0}.</value>
+ </data>
+ <data name="Validation_scalar_range_violation_not_in_range" xml:space="preserve">
+ <value>The value must be inside the range {0}-{1}.</value>
+ </data>
+ <data name="Validation_scalar_range_violation_not_outside_range" xml:space="preserve">
+ <value>The value must not be in the range {0}-{1}.</value>
+ </data>
+ <data name="Validator_Attribute_param_not_validator" xml:space="preserve">
+ <value>Only types derived from {0} are valid validator types.</value>
+ </data>
+ <data name="Validator_does_not_support_elem_type" xml:space="preserve">
+ <value>The supplied validator does not support validating the configuration element type {0}.</value>
+ </data>
+ <data name="Validator_does_not_support_prop_type" xml:space="preserve">
+ <value>The supplied validator does not support the type of the property '{0}'.</value>
+ </data>
+ <data name="Validator_element_not_valid" xml:space="preserve">
+ <value>The configuration element '{0}' is not valid. The error is: {1}</value>
+ </data>
+ <data name="Validator_method_not_found" xml:space="preserve">
+ <value>The supplied method name '{0}' was not found. The callback method must be a public static void method with one object parameter.</value>
+ </data>
+ <data name="Validator_min_greater_than_max" xml:space="preserve">
+ <value>The upper range limit value must be greater than the lower range limit value.</value>
+ </data>
+ <data name="Validator_scalar_resolution_violation" xml:space="preserve">
+ <value>The value must have a resolution of {0}.</value>
+ </data>
+ <data name="Validator_string_invalid_chars" xml:space="preserve">
+ <value>The string cannot contain any of the following characters: '{0}'.</value>
+ </data>
+ <data name="Validator_string_max_length" xml:space="preserve">
+ <value>The string must be no more than {0} characters long.</value>
+ </data>
+ <data name="Validator_string_min_length" xml:space="preserve">
+ <value>The string must be at least {0} characters long.</value>
+ </data>
+ <data name="Validator_value_type_invalid" xml:space="preserve">
+ <value>The supplied value is not of type which the validator can process.</value>
+ </data>
+ <data name="Validator_multiple_validator_attributes" xml:space="preserve">
+ <value>Multiple validator attributes are not currently supported. The property '{0}' has more than one validator attribute associated with it.</value>
+ </data>
+ <data name="Validator_timespan_value_must_be_positive" xml:space="preserve">
+ <value>The time span value must be positive.</value>
+ </data>
+ <data name="No_exception_information_available" xml:space="preserve">
+ <value>No information about the exception is available.</value>
+ </data>
+ <data name="Parameter_Invalid" xml:space="preserve">
+ <value>The parameter '{0}' is invalid.</value>
+ </data>
+ <data name="Parameter_NullOrEmpty" xml:space="preserve">
+ <value>The string parameter '{0}' cannot be null or empty.</value>
+ </data>
+ <data name="Property_NullOrEmpty" xml:space="preserve">
+ <value>The value assigned to property '{0}' cannot be null or empty.</value>
+ </data>
+ <data name="Property_Invalid" xml:space="preserve">
+ <value>The value assigned to property '{0}' is invalid.</value>
+ </data>
+ <data name="Unexpected_Error" xml:space="preserve">
+ <value>An unexpected error occurred in '{0}'.</value>
+ </data>
+ <data name="Wrapped_exception_message" xml:space="preserve">
+ <value>{0}: {1}</value>
+ </data>
+ <data name="TypeNotPublic" xml:space="preserve">
+ <value>Unable to load type '{0}' because it is not public.</value>
+ </data>
+ <data name="Config_type_doesnt_inherit_from_type" xml:space="preserve">
+ <value>Type '{0}' does not inherit from '{1}'.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/System.Configuration/tests/System.Configuration.Tests.builds b/src/System.Configuration/tests/System.Configuration.Tests.builds
new file mode 100644
index 0000000000..114e4b3a04
--- /dev/null
+++ b/src/System.Configuration/tests/System.Configuration.Tests.builds
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <Project Include="System.Configuration.Tests.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.Configuration/tests/System.Configuration.Tests.csproj b/src/System.Configuration/tests/System.Configuration.Tests.csproj
new file mode 100644
index 0000000000..5db4c6a502
--- /dev/null
+++ b/src/System.Configuration/tests/System.Configuration.Tests.csproj
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition="'$(Configuration)'==''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
+ <ProjectGuid>{7669C397-C21C-4C08-83F1-BE6691911E88}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AssemblyName>System.Configuration.Tests</AssemblyName>
+ <TestCategories>InnerLoop;OuterLoop</TestCategories>
+ <NugetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.7</NugetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the options -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\pkg\System.Configuration.pkgproj">
+ <Name>System.Configuration</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="$(CommonTestPath)\System\IO\TempDirectory.cs">
+ <Link>Common\System\IO\TempDirectory.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonTestPath)\System\IO\TempFile.cs">
+ <Link>Common\System\IO\TempFile.cs</Link>
+ </Compile>
+ <Compile Include="..\src\System\Configuration\ConfigPathUtility.cs">
+ <Link>Source\ConfigPathUtility.cs</Link>
+ </Compile>
+ <Compile Include="..\src\System\Configuration\ExceptionUtil.cs">
+ <Link>Source\ExceptionUtil.cs</Link>
+ </Compile>
+ <Compile Include="..\src\System\Configuration\StringUtil.cs">
+ <Link>Source\StringUtil.cs</Link>
+ </Compile>
+ <Compile Include="..\src\System\Configuration\TypeUtil.cs">
+ <Link>Source\TypeUtil.cs</Link>
+ </Compile>
+ <Compile Include="..\src\System\Configuration\UrlPath.cs">
+ <Link>Source\UrlPath.cs</Link>
+ </Compile>
+ <Compile Include="..\src\System\Configuration\ValidatorUtils.cs">
+ <Link>Source\ValidatorUtils.cs</Link>
+ </Compile>
+ <Compile Include="Resources\Strings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Strings.resx</DependentUpon>
+ </Compile>
+ <Compile Include="System\Configuration\AppSettingsTests.cs" />
+ <Compile Include="System\Configuration\ConfigPathUtilityTests.cs" />
+ <Compile Include="System\Configuration\ExceptionUtilTests.cs" />
+ <Compile Include="System\Configuration\ImplicitMachineConfigTests.cs" />
+ <Compile Include="System\Configuration\SmokeTest.cs" />
+ <Compile Include="System\Configuration\StringUtilTests.cs" />
+ <Compile Include="System\Configuration\TempConfig.cs" />
+ <Compile Include="System\Configuration\TestData.cs" />
+ <Compile Include="System\Configuration\TypeUtilTests.cs" />
+ <Compile Include="System\Configuration\ValidatiorUtilsTests.cs" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.Configuration/tests/System/Configuration/AppSettingsTests.cs b/src/System.Configuration/tests/System/Configuration/AppSettingsTests.cs
new file mode 100644
index 0000000000..5aaf0a6349
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/AppSettingsTests.cs
@@ -0,0 +1,87 @@
+// 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.Configuration;
+using System.IO;
+using Xunit;
+
+namespace System.ConfigurationTests
+{
+ public class AppSettingsTests
+ {
+ [Fact]
+ public void EmptyRuntimeAppSettings()
+ {
+ var appSettings = ConfigurationManager.AppSettings;
+ Assert.NotNull(appSettings);
+ Assert.Empty(appSettings);
+ }
+
+ [Fact]
+ public void EmptyDesignTimeAppSettings()
+ {
+ using (var temp = new TempConfig(TestData.EmptyConfig))
+ {
+ var config = ConfigurationManager.OpenExeConfiguration(temp.ExePath);
+ Assert.NotNull(config.AppSettings);
+ Assert.Empty(config.AppSettings.Settings);
+ }
+ }
+
+ [Fact]
+ public void SimpleAppSettings()
+ {
+ using (var temp = new TempConfig(TestData.SimpleConfig))
+ {
+ var config = ConfigurationManager.OpenExeConfiguration(temp.ExePath);
+ Assert.NotNull(config.AppSettings);
+ Assert.Equal(2, config.AppSettings.Settings.Count);
+ Assert.Equal("FooValue", config.AppSettings.Settings["FooKey"].Value);
+ Assert.Equal("BarValue", config.AppSettings.Settings["BarKey"].Value);
+ }
+ }
+
+ [Fact]
+ public void AddToAppSettings_NoSave()
+ {
+ using (var temp = new TempConfig(TestData.EmptyConfig))
+ {
+ var config = ConfigurationManager.OpenExeConfiguration(temp.ExePath);
+ Assert.NotNull(config.AppSettings);
+ Assert.Empty(config.AppSettings.Settings);
+
+ config.AppSettings.Settings.Add("NewKey", "NewValue");
+ Assert.NotEmpty(config.AppSettings.Settings);
+ Assert.Equal("NewValue", config.AppSettings.Settings["NewKey"].Value);
+
+ config = ConfigurationManager.OpenExeConfiguration(temp.ExePath);
+ Assert.Empty(config.AppSettings.Settings);
+ }
+ }
+
+ [Fact]
+ public void AddToAppSettings_Save()
+ {
+ using (var temp = new TempConfig(TestData.EmptyConfig))
+ {
+ var config = ConfigurationManager.OpenExeConfiguration(temp.ExePath);
+ Assert.NotNull(config.AppSettings);
+ Assert.Empty(config.AppSettings.Settings);
+
+ config.AppSettings.Settings.Add("NewKey", "NewValue");
+ Assert.NotEmpty(config.AppSettings.Settings);
+ Assert.Equal("NewValue", config.AppSettings.Settings["NewKey"].Value);
+
+ config.Save();
+
+ // Make sure we didn't serialize the implicit machine.config
+ Assert.False(File.Exists(new ConfigurationFileMap().MachineConfigFilename));
+
+ config = ConfigurationManager.OpenExeConfiguration(temp.ExePath);
+ Assert.NotEmpty(config.AppSettings.Settings);
+ Assert.Equal("NewValue", config.AppSettings.Settings["NewKey"].Value);
+ }
+ }
+ }
+}
diff --git a/src/System.Configuration/tests/System/Configuration/ConfigPathUtilityTests.cs b/src/System.Configuration/tests/System/Configuration/ConfigPathUtilityTests.cs
new file mode 100644
index 0000000000..cdbb02ba6d
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/ConfigPathUtilityTests.cs
@@ -0,0 +1,66 @@
+// 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.Configuration;
+using Xunit;
+
+namespace System.ConfigurationTests
+{
+ public class ConfigPathUtilityTests
+ {
+ [Theory
+ InlineData(null, false)
+ InlineData(@"", false)
+ InlineData(@"\", false)
+ InlineData(@"/", false)
+ InlineData(@".", false)
+ InlineData(@"..", false)
+ InlineData(@"a", true)
+ InlineData(@"a\", false)
+ InlineData(@"\a", false)
+ InlineData(@"/a", false)
+ InlineData(@"a/", false)
+ InlineData(@"a/b", true)
+ InlineData(@"a//c", false)
+ InlineData(@"a\b", false)
+ InlineData(@"a/b/c", true)
+ InlineData(@"a/b./c", true)
+ InlineData(@"a/b../c", true)
+ InlineData(@"a/../c", false)
+ InlineData(@"a/./c", false)
+ ]
+ public void IsValid(string configPath, bool expected)
+ {
+ Assert.Equal(expected, ConfigPathUtility.IsValid(configPath));
+ }
+
+ [Theory
+ InlineData(@"a", @"b", @"a/b")
+ ]
+ public void Combine(string parentConfigPath, string childConfigPath, string expected)
+ {
+ Assert.Equal(expected, ConfigPathUtility.Combine(parentConfigPath, childConfigPath));
+ }
+
+ [Theory
+ InlineData(@"a", new string[] { "a" })
+ InlineData(@"a/b", new string[] { "a", "b" })
+ ]
+ public void GetParts(string configPath, string[] expected)
+ {
+ Assert.Equal(expected, ConfigPathUtility.GetParts(configPath));
+ }
+
+ [Theory
+ InlineData(@"a", @"a")
+ InlineData(@"ab", @"ab")
+ InlineData(@"a/b", @"b")
+ InlineData(@"a/b/c", @"c")
+ ]
+ public void GetName(string configPath, string expected)
+ {
+ Assert.Equal(expected, ConfigPathUtility.GetName(configPath));
+ }
+ }
+}
diff --git a/src/System.Configuration/tests/System/Configuration/ExceptionUtilTests.cs b/src/System.Configuration/tests/System/Configuration/ExceptionUtilTests.cs
new file mode 100644
index 0000000000..f67b4087a3
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/ExceptionUtilTests.cs
@@ -0,0 +1,130 @@
+// 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.Configuration;
+using System.Xml;
+using Xunit;
+
+namespace System.ConfigurationTests
+{
+ public class ExceptionUtilTests
+ {
+ [Fact]
+ public void WrapAsConfigException_ConfigurationErrorsException()
+ {
+ ConfigurationErrorsException e = new ConfigurationErrorsException();
+ Assert.Same(e, ExceptionUtil.WrapAsConfigException(null, e, null));
+ }
+
+ [Fact]
+ public void WrapAsConfigException_ConfigurationException()
+ {
+ Exception inner = new Exception();
+#pragma warning disable CS0618
+ ConfigurationException obsolete = new ConfigurationException("mymessage", inner, "myfilename", 42);
+#pragma warning restore CS0618
+ var result = ExceptionUtil.WrapAsConfigException(null, obsolete, null);
+ Assert.NotNull(result);
+ Assert.Same(inner, result.InnerException);
+ Assert.Equal("mymessage", result.BareMessage);
+ Assert.Equal("myfilename", result.Filename);
+ Assert.Equal(42, result.Line);
+ }
+
+ [Fact]
+ public void WrapAsConfigException_XmlExceptionWithLine()
+ {
+ XmlException xml = new XmlException("xmlmessage", null, 42, 0);
+ var result = ExceptionUtil.WrapAsConfigException(null, xml, null, 99);
+ Assert.NotNull(result);
+ Assert.Same(xml, result.InnerException);
+ Assert.Equal(xml.Message, result.BareMessage);
+ Assert.Equal(xml.LineNumber, result.Line);
+ Assert.Null(result.Filename);
+ }
+
+ [Fact]
+ public void WrapAsConfigException_XmlExceptionWithNoLine()
+ {
+ XmlException xml = new XmlException("xmlmessage", null, 0, 0);
+ var result = ExceptionUtil.WrapAsConfigException(null, xml, "myfilename", 99);
+ Assert.NotNull(result);
+ Assert.Same(xml, result.InnerException);
+ Assert.Equal(xml.Message, result.BareMessage);
+ Assert.Equal(99, result.Line);
+ Assert.Equal("myfilename", result.Filename);
+ }
+
+ [Fact]
+ public void WrapAsConfigException_OtherException()
+ {
+ Exception e = new Exception();
+ var result = ExceptionUtil.WrapAsConfigException("mymessage", e, "myfilename", 55);
+ Assert.NotNull(result);
+ Assert.Same(e, result.InnerException);
+
+ // The "bare" message is whatever the base class returns
+ Assert.StartsWith("mymessage:", result.BareMessage);
+ Assert.Equal("myfilename", result.Filename);
+ Assert.Equal(55, result.Line);
+ }
+
+ [Fact]
+ public void WrapAsConfigException_Null()
+ {
+ var result = ExceptionUtil.WrapAsConfigException("mymessage", null, "myfilename", 55);
+ Assert.NotNull(result);
+ Assert.Null(result.InnerException);
+
+ // The "bare" message is whatever the base class returns
+ Assert.StartsWith("mymessage:", result.BareMessage);
+ Assert.Equal("myfilename", result.Filename);
+ Assert.Equal(55, result.Line);
+ }
+
+ [Fact]
+ public void ParameterInvalid()
+ {
+ ArgumentException e = ExceptionUtil.ParameterInvalid("foo");
+ Assert.NotNull(e);
+ Assert.Equal("foo", e.ParamName);
+ Assert.StartsWith(string.Format(SR.GetResourceString("Parameter_Invalid", null), "foo"), e.Message);
+ }
+
+ [Fact]
+ public void ParameterNullOrEmpty()
+ {
+ ArgumentException e = ExceptionUtil.ParameterNullOrEmpty("foo");
+ Assert.NotNull(e);
+ Assert.Equal("foo", e.ParamName);
+ Assert.StartsWith(string.Format(SR.GetResourceString("Parameter_NullOrEmpty", null), "foo"), e.Message);
+ }
+
+ [Fact]
+ public void PropertyInvalid()
+ {
+ ArgumentException e = ExceptionUtil.PropertyInvalid("foo");
+ Assert.NotNull(e);
+ Assert.Equal("foo", e.ParamName);
+ Assert.StartsWith(string.Format(SR.GetResourceString("Property_Invalid", null), "foo"), e.Message);
+ }
+
+ [Fact]
+ public void PropertyNullOrEmpty()
+ {
+ ArgumentException e = ExceptionUtil.PropertyNullOrEmpty("foo");
+ Assert.NotNull(e);
+ Assert.Equal("foo", e.ParamName);
+ Assert.StartsWith(string.Format(SR.GetResourceString("Property_NullOrEmpty", null), "foo"), e.Message);
+ }
+
+ [Fact]
+ public void UnexpectedError()
+ {
+ InvalidOperationException e = ExceptionUtil.UnexpectedError("foo");
+ Assert.NotNull(e);
+ Assert.StartsWith(string.Format(SR.GetResourceString("Unexpected_Error", null), "foo"), e.Message);
+ }
+ }
+}
diff --git a/src/System.Configuration/tests/System/Configuration/ImplicitMachineConfigTests.cs b/src/System.Configuration/tests/System/Configuration/ImplicitMachineConfigTests.cs
new file mode 100644
index 0000000000..6671d8a0fc
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/ImplicitMachineConfigTests.cs
@@ -0,0 +1,65 @@
+// 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.Configuration;
+using System.IO;
+using Xunit;
+
+namespace System.ConfigurationTests
+{
+ public class ImplicitMachineConfigTests
+ {
+ [Fact]
+ public void RuntimeAppSettingsAccessible()
+ {
+ var appSettings = ConfigurationManager.AppSettings;
+ Assert.NotNull(appSettings);
+ }
+
+ [Fact]
+ public void DesignTimeAppSettingsAccessible()
+ {
+ using (var temp = new TempConfig(TestData.EmptyConfig))
+ {
+ var config = ConfigurationManager.OpenExeConfiguration(temp.ExePath);
+ Assert.NotNull(config);
+ Assert.NotNull(config.AppSettings);
+ }
+ }
+
+ [Fact]
+ public void DesignTimeAppSettingsFailWithMissingMachineConfig_1()
+ {
+ // ConfigurationFileMap checks for existence in the constructor
+ string missingFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".config");
+ Assert.Throws<ArgumentException>(() => new ConfigurationFileMap(missingFile));
+ }
+
+ [Fact]
+ public void DesignTimeAppSettingsFailWithMissingMachineConfig_2()
+ {
+ // Get around the existence check by using the default constructor
+ string missingFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".config");
+ ConfigurationFileMap map = new ConfigurationFileMap();
+ map.MachineConfigFilename = missingFile;
+ var config = ConfigurationManager.OpenMappedMachineConfiguration(map);
+ Assert.NotNull(config);
+ Assert.Null(config.AppSettings);
+ }
+
+ [Fact]
+ public void DesignTimeAppSettingsFailWithEmptyMachineConfig()
+ {
+ // If we've explicitly specified a machine config and it doesn't define the AppSettingsType we shouldn't be able
+ // to get it (e.g. we haven't stubbed in overtop).
+ using (var temp = new TempConfig(TestData.EmptyConfig))
+ {
+ var config = ConfigurationManager.OpenMappedMachineConfiguration(new ConfigurationFileMap(temp.ConfigPath));
+ Assert.NotNull(config);
+
+ Assert.Null(config.AppSettings);
+ }
+ }
+ }
+}
diff --git a/src/System.Configuration/tests/System/Configuration/SmokeTest.cs b/src/System.Configuration/tests/System/Configuration/SmokeTest.cs
new file mode 100644
index 0000000000..2eb1f0d97c
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/SmokeTest.cs
@@ -0,0 +1,23 @@
+// 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.Configuration;
+using Xunit;
+
+namespace System.ConfigurationTests
+{
+ public class SmokeTest
+ {
+ [Fact]
+ public void CreateExe()
+ {
+ using (var temp = new TempConfig(TestData.SimpleConfig))
+ {
+ var config = ConfigurationManager.OpenExeConfiguration(temp.ExePath);
+ Assert.NotNull(config);
+ Assert.Equal(2, config.AppSettings.Settings.Count);
+ }
+ }
+ }
+}
diff --git a/src/System.Configuration/tests/System/Configuration/StringUtilTests.cs b/src/System.Configuration/tests/System/Configuration/StringUtilTests.cs
new file mode 100644
index 0000000000..311d2005d4
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/StringUtilTests.cs
@@ -0,0 +1,96 @@
+// 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.Configuration;
+using Xunit;
+
+namespace System.ConfigurationTests
+{
+ public class StringUtilTests
+ {
+ [Theory
+ InlineData(null, null, true)
+ InlineData(@"", null, true)
+ InlineData(null, @"", true)
+ InlineData(@"", @"", true)
+ InlineData(@"a", null, false)
+ InlineData(null, @"a", false)
+ InlineData(@"a", @"", false)
+ InlineData(@"", @"a", false)
+ InlineData(@"A", @"a", false)
+ InlineData(@"a", @"a", true)
+ ]
+ public void EqualsOrBothNullOrEmpty(string s1, string s2, bool expected)
+ {
+ Assert.Equal(expected, StringUtil.EqualsOrBothNullOrEmpty(s1, s2));
+ }
+
+ [Theory
+ InlineData(null, null, true)
+ InlineData(@"", null, false)
+ InlineData(null, @"", false)
+ InlineData(@"", @"", true)
+ InlineData(@"a", null, false)
+ InlineData(null, @"a", false)
+ InlineData(@"a", @"", false)
+ InlineData(@"", @"a", false)
+ InlineData(@"A", @"a", true)
+ InlineData(@"a", @"a", true)
+ ]
+ public void EqualsIgnoreCase(string s1, string s2, bool expected)
+ {
+ Assert.Equal(expected, StringUtil.EqualsIgnoreCase(s1, s2));
+ }
+
+ [Theory
+ InlineData(null, null, false)
+ InlineData(@"", null, false)
+ InlineData(null, @"", false)
+ InlineData(@"", @"", true)
+ InlineData(@"a", null, false)
+ InlineData(null, @"a", false)
+ InlineData(@"a", @"", true)
+ InlineData(@"", @"a", false)
+ InlineData(@"A", @"a", false)
+ InlineData(@"a", @"a", true)
+ InlineData(@"a", @"abba", false)
+ InlineData(@"abba", @"ab", true)
+ InlineData(@"abba", @"abba", true)
+ InlineData(@"ABBA", @"abba", false)
+ ]
+ public void StartsWithOrdinal(string s1, string s2, bool expected)
+ {
+ Assert.Equal(expected, StringUtil.StartsWithOrdinal(s1, s2));
+ }
+
+ [Theory
+ InlineData(null, null, false)
+ InlineData(@"", null, false)
+ InlineData(null, @"", false)
+ InlineData(@"", @"", true)
+ InlineData(@"a", null, false)
+ InlineData(null, @"a", false)
+ InlineData(@"a", @"", true)
+ InlineData(@"", @"a", false)
+ InlineData(@"A", @"a", true)
+ InlineData(@"a", @"a", true)
+ InlineData(@"a", @"abba", false)
+ InlineData(@"abba", @"ab", true)
+ InlineData(@"abba", @"abba", true)
+ InlineData(@"ABBA", @"abba", true)
+ ]
+ public void StartsWithOrdinalIgnoreCase(string s1, string s2, bool expected)
+ {
+ Assert.Equal(expected, StringUtil.StartsWithOrdinalIgnoreCase(s1, s2));
+ }
+
+ [Theory
+ InlineData(new object[] { "1", "2", "3" }, new string[] { "1", "2", "3" } )
+ ]
+ public void ObjectArrayToStringArray(object[] objectArray, string[] expected)
+ {
+ Assert.Equal(expected, StringUtil.ObjectArrayToStringArray(objectArray));
+ }
+ }
+}
diff --git a/src/System.Configuration/tests/System/Configuration/TempConfig.cs b/src/System.Configuration/tests/System/Configuration/TempConfig.cs
new file mode 100644
index 0000000000..141f2d0cbe
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/TempConfig.cs
@@ -0,0 +1,30 @@
+// 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.IO;
+
+namespace System.Configuration
+{
+ public class TempConfig : IDisposable
+ {
+ private readonly TempDirectory _directory;
+
+ public TempConfig(string contents)
+ {
+ _directory = new TempDirectory();
+ ExePath = Path.Combine(_directory.Path, Path.GetRandomFileName() + ".exe");
+ File.WriteAllText(ExePath, "dummy exe");
+ ConfigPath = ExePath + ".config";
+ File.WriteAllText(ConfigPath, contents);
+ }
+
+ public string ConfigPath { get; }
+ public string ExePath { get; }
+
+ public void Dispose()
+ {
+ _directory?.Dispose();
+ }
+ }
+}
diff --git a/src/System.Configuration/tests/System/Configuration/TestData.cs b/src/System.Configuration/tests/System/Configuration/TestData.cs
new file mode 100644
index 0000000000..625ce91fab
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/TestData.cs
@@ -0,0 +1,23 @@
+// 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.ConfigurationTests
+{
+ public static class TestData
+ {
+ public static string EmptyConfig =
+@"<?xml version='1.0' encoding='utf-8' ?>
+<configuration>
+</configuration>";
+
+ public static string SimpleConfig =
+@"<?xml version='1.0' encoding='utf-8' ?>
+<configuration>
+ <appSettings>
+ <add key='FooKey' value='FooValue'/>
+ <add key='BarKey' value='BarValue'/>
+ </appSettings>
+</configuration>";
+ }
+}
diff --git a/src/System.Configuration/tests/System/Configuration/TypeUtilTests.cs b/src/System.Configuration/tests/System/Configuration/TypeUtilTests.cs
new file mode 100644
index 0000000000..62fb2d86c1
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/TypeUtilTests.cs
@@ -0,0 +1,288 @@
+// 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.Concurrent;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Configuration;
+using System.Configuration.Internal;
+using System.IO;
+using Xunit;
+
+namespace System.ConfigurationTests
+{
+ public class TypeUtilTests
+ {
+ [Theory
+ // CoreLib
+ InlineData("System.String", typeof(string))
+ InlineData("System.Int32", typeof(int))
+ // System.Configuration
+ InlineData("System.Configuration.PropertyInformation", typeof(PropertyInformation))
+ // System.Runtime, previously System
+ InlineData("System.Uri", typeof(Uri))
+ // System.Collections, previously System
+ InlineData("System.Collections.Generic.LinkedList`1", typeof(LinkedList<>))
+ InlineData("System.Collections.Generic.Queue`1", typeof(Queue<>))
+ InlineData("System.Collections.Generic.Stack`1", typeof(Stack<>))
+ // System.Collections.Concurrent, previously System
+ InlineData("System.Collections.Concurrent.ConcurrentBag`1", typeof(ConcurrentBag<>))
+ InlineData("System.Collections.Concurrent.BlockingCollection`1", typeof(BlockingCollection<>))
+ // System.Collections.Specialized, previously System
+ InlineData("System.Collections.Specialized.HybridDictionary", typeof(HybridDictionary))
+ InlineData("System.Collections.Specialized.ListDictionary", typeof(ListDictionary))
+ InlineData("System.Collections.Specialized.StringDictionary", typeof(StringDictionary))
+ InlineData("System.Collections.Specialized.OrderedDictionary", typeof(OrderedDictionary))
+ InlineData("System.Collections.Specialized.StringCollection", typeof(StringCollection))
+ InlineData("System.Collections.Specialized.NameValueCollection", typeof(NameValueCollection))
+ ]
+ public void GetType_NoAssemblyQualifcation(string typeString, Type expectedType)
+ {
+ Assert.Equal(expectedType, TypeUtil.GetType(typeString, throwOnError: false));
+ }
+
+ [Fact]
+ public void GetType_ThrowOnError()
+ {
+ Assert.Throws<TypeLoadException>(() => TypeUtil.GetType("Mxyzptlk", throwOnError: true));
+ }
+
+ [Fact]
+ public void GetType_NoThrowOnError()
+ {
+ Assert.Null(TypeUtil.GetType("Mxyzptlk", throwOnError: false));
+ }
+
+ [Fact]
+ public void GetTypeConfigHost()
+ {
+ TestHost host = new TestHost((s, b) => { return typeof(string); });
+ Assert.Equal(typeof(string), TypeUtil.GetType(host, "Mxyzptlk", throwOnError: false));
+ }
+
+ [Fact]
+ public void GetTypeConfigHost_ThrowOnError()
+ {
+ TestHost host = new TestHost((s, b) => { if (b) throw new ArgumentException(); return null; });
+ Assert.Throws<ArgumentException>(() => TypeUtil.GetType(host, "Mxyzptlk", throwOnError: true));
+ }
+
+ [Fact]
+ public void GetTypeConfigHost_NoThrowOnError()
+ {
+ TestHost host = new TestHost((s, b) => { if (b) throw new ArgumentException(); return null; });
+ Assert.Null(TypeUtil.GetType(host, "Mxyzptlk", throwOnError: false));
+ }
+
+ private class TestHost : IInternalConfigHost
+ {
+ Func<string, bool, Type> _configTypeFunc;
+
+ public TestHost(Func<string, bool, Type> configTypeFunc)
+ {
+ _configTypeFunc = configTypeFunc;
+ }
+
+ Type IInternalConfigHost.GetConfigType(string typeName, bool throwOnError)
+ {
+ return _configTypeFunc(typeName, throwOnError);
+ }
+
+ bool IInternalConfigHost.IsRemote
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ bool IInternalConfigHost.SupportsChangeNotifications
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ bool IInternalConfigHost.SupportsLocation
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ bool IInternalConfigHost.SupportsPath
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ bool IInternalConfigHost.SupportsRefresh
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ object IInternalConfigHost.CreateConfigurationContext(string configPath, string locationSubPath)
+ {
+ throw new NotImplementedException();
+ }
+
+ object IInternalConfigHost.CreateDeprecatedConfigContext(string configPath)
+ {
+ throw new NotImplementedException();
+ }
+
+ string IInternalConfigHost.DecryptSection(string encryptedXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfigSection)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IInternalConfigHost.DeleteStream(string streamName)
+ {
+ throw new NotImplementedException();
+ }
+
+ string IInternalConfigHost.EncryptSection(string clearTextXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfigSection)
+ {
+ throw new NotImplementedException();
+ }
+
+ string IInternalConfigHost.GetConfigPathFromLocationSubPath(string configPath, string locationSubPath)
+ {
+ throw new NotImplementedException();
+ }
+
+ string IInternalConfigHost.GetConfigTypeName(Type t)
+ {
+ throw new NotImplementedException();
+ }
+
+ string IInternalConfigHost.GetStreamName(string configPath)
+ {
+ throw new NotImplementedException();
+ }
+
+ string IInternalConfigHost.GetStreamNameForConfigSource(string streamName, string configSource)
+ {
+ throw new NotImplementedException();
+ }
+
+ object IInternalConfigHost.GetStreamVersion(string streamName)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IInternalConfigHost.Init(IInternalConfigRoot configRoot, params object[] hostInitParams)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IInternalConfigHost.InitForConfiguration(ref string locationSubPath, out string configPath, out string locationConfigPath, IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IInternalConfigHost.IsAboveApplication(string configPath)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IInternalConfigHost.IsConfigRecordRequired(string configPath)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IInternalConfigHost.IsDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition, ConfigurationAllowExeDefinition allowExeDefinition)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IInternalConfigHost.IsFile(string streamName)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IInternalConfigHost.IsInitDelayed(IInternalConfigRecord configRecord)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IInternalConfigHost.IsLocationApplicable(string configPath)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IInternalConfigHost.IsSecondaryRoot(string configPath)
+ {
+ throw new NotImplementedException();
+ }
+
+ Stream IInternalConfigHost.OpenStreamForRead(string streamName)
+ {
+ throw new NotImplementedException();
+ }
+
+ Stream IInternalConfigHost.OpenStreamForRead(string streamName, bool assertPermissions)
+ {
+ throw new NotImplementedException();
+ }
+
+ Stream IInternalConfigHost.OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext)
+ {
+ throw new NotImplementedException();
+ }
+
+ Stream IInternalConfigHost.OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext, bool assertPermissions)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IInternalConfigHost.PrefetchAll(string configPath, string streamName)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool IInternalConfigHost.PrefetchSection(string sectionGroupName, string sectionName)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IInternalConfigHost.RequireCompleteInit(IInternalConfigRecord configRecord)
+ {
+ throw new NotImplementedException();
+ }
+
+ object IInternalConfigHost.StartMonitoringStreamForChanges(string streamName, StreamChangeCallback callback)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IInternalConfigHost.StopMonitoringStreamForChanges(string streamName, StreamChangeCallback callback)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IInternalConfigHost.VerifyDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition, ConfigurationAllowExeDefinition allowExeDefinition, IConfigErrorInfo errorInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IInternalConfigHost.WriteCompleted(string streamName, bool success, object writeContext)
+ {
+ throw new NotImplementedException();
+ }
+
+ void IInternalConfigHost.WriteCompleted(string streamName, bool success, object writeContext, bool assertPermissions)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/src/System.Configuration/tests/System/Configuration/ValidatiorUtilsTests.cs b/src/System.Configuration/tests/System/Configuration/ValidatiorUtilsTests.cs
new file mode 100644
index 0000000000..0634a10502
--- /dev/null
+++ b/src/System.Configuration/tests/System/Configuration/ValidatiorUtilsTests.cs
@@ -0,0 +1,83 @@
+// 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.Configuration;
+using Xunit;
+
+namespace System.ConfigurationTests
+{
+ public class ValidatiorUtilsTests
+ {
+ [Theory
+ InlineData(@"a", typeof(string), false)
+ InlineData(null, typeof(string), false)
+ InlineData(@"a", typeof(int), true)
+ InlineData(1, typeof(string), true)
+ ]
+ public void HelperParamValidation(object value, Type allowedType, bool shouldThrow)
+ {
+ Action action = () => ValidatorUtils.HelperParamValidation(value, allowedType);
+ if (!shouldThrow)
+ {
+ action();
+ }
+ else
+ {
+ Assert.Throws<ArgumentException>(action);
+ }
+ }
+
+ [Theory
+ // Exclusive in range
+ InlineData(1, 1, 1, 1, true, true, "Validation_scalar_range_violation_not_different")
+ InlineData(1, 1, 2, 1, true, true, "Validation_scalar_range_violation_not_outside_range")
+ InlineData(2, 1, 2, 1, true, true, "Validation_scalar_range_violation_not_outside_range")
+ // Not exclusive in range
+ InlineData(1, 1, 1, 1, false, false, null)
+ InlineData(1, 1, 2, 1, false, false, null)
+ InlineData(2, 1, 2, 1, false, false, null)
+ // Exclusive out of range
+ InlineData(2, 1, 1, 1, true, false, null)
+ InlineData(3, 1, 2, 1, true, false, null)
+ InlineData(3, 1, 2, 1, true, false, null)
+ // Not exclusive out of range
+ InlineData(2, 1, 1, 1, false, true, "Validation_scalar_range_violation_not_equal")
+ InlineData(3, 1, 2, 1, false, true, "Validation_scalar_range_violation_not_in_range")
+ InlineData(3, 1, 2, 1, false, true, "Validation_scalar_range_violation_not_in_range")
+ ]
+ public void ValidateIntScalar(int value, int min, int max, int resolution, bool exclusiveRange, bool shouldThrow, string message)
+ {
+ Action action = () => ValidatorUtils.ValidateScalar(value, min, max, resolution, exclusiveRange);
+ if (!shouldThrow)
+ {
+ action();
+ }
+ else
+ {
+ Assert.Equal(
+ string.Format(SR.GetResourceString(message, null), min, max),
+ Assert.Throws<ArgumentException>(action).Message);
+ }
+ }
+
+ [Theory
+ InlineData(1, 1, 1, 1, false, false, null)
+ InlineData(1, 1, 1, 2, false, true, "Validator_scalar_resolution_violation")
+ ]
+ public void ValidateIntBadResolution(int value, int min, int max, int resolution, bool exclusiveRange, bool shouldThrow, string message)
+ {
+ Action action = () => ValidatorUtils.ValidateScalar(value, min, max, resolution, exclusiveRange);
+ if (!shouldThrow)
+ {
+ action();
+ }
+ else
+ {
+ Assert.Equal(
+ string.Format(SR.GetResourceString(message, null), resolution),
+ Assert.Throws<ArgumentException>(action).Message);
+ }
+ }
+ }
+}
diff --git a/src/System.Console/src/FxCopBaseline.cs b/src/System.Console/src/FxCopBaseline.cs
new file mode 100644
index 0000000000..be75298ec3
--- /dev/null
+++ b/src/System.Console/src/FxCopBaseline.cs
@@ -0,0 +1,49 @@
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#Dispose(System.Boolean)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#Peek():System.Int32")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#Read():System.Int32")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#Read(System.Char[],System.Int32,System.Int32):System.Int32")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#ReadBlock(System.Char[],System.Int32,System.Int32):System.Int32")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#ReadLine():System.String")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#ReadToEnd():System.String")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#ReadKey(System.Boolean&):System.ConsoleKeyInfo")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextReader.#get_KeyAvailable():System.Boolean")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#get_NewLine():System.String")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#set_NewLine(System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Dispose(System.Boolean)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Flush()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Char)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Char[])")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Char[],System.Int32,System.Int32)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Boolean)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Int32)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.UInt32)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Int64)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.UInt64)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Single)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Double)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Decimal)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.Object)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#Write(System.String,System.Object[])")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Char)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Char[])")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Char[],System.Int32,System.Int32)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Boolean)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Int32)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.UInt32)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Int64)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.UInt64)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Single)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Double)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Decimal)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.Object)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.IO.SyncTextWriter.#WriteLine(System.String,System.Object[])")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.ConsolePal.#ResetColor()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.ConsolePal.#GetCursorPosition(System.Int32&,System.Int32&)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.ConsolePal.#RefreshColors(System.ConsoleColor&,System.ConsoleColor)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.ConsolePal.#EnsureInitializedCore()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.ConsolePal.#WriteStdoutAnsiString(System.String)")]
diff --git a/src/System.Console/src/Resources/Strings.resx b/src/System.Console/src/Resources/Strings.resx
index 4568eb3f4c..f5ac1eebb2 100644
--- a/src/System.Console/src/Resources/Strings.resx
+++ b/src/System.Console/src/Resources/Strings.resx
@@ -234,4 +234,31 @@
<data name="ArgumentOutOfRange_BeepFrequency" xml:space="preserve">
<value>The frequency must be between {0} and {1}.</value>
</data>
+ <data name="ArgumentNull_Array" xml:space="preserve">
+ <value>Array cannot be null.</value>
+ </data>
+ <data name="ArgumentOutOfRange_IndexCountBuffer" xml:space="preserve">
+ <value>Index and count must refer to a location within the buffer.</value>
+ </data>
+ <data name="ArgumentOutOfRange_IndexCount" xml:space="preserve">
+ <value>Index and count must refer to a location within the string.</value>
+ </data>
+ <data name="ArgumentOutOfRange_Index" xml:space="preserve">
+ <value>Index was out of range. Must be non-negative and less than the size of the collection.</value>
+ </data>
+ <data name="Argument_EncodingConversionOverflowBytes" xml:space="preserve">
+ <value>The output byte buffer is too small to contain the encoded data, encoding '{0}' fallback '{1}'.</value>
+ </data>
+ <data name="Argument_EncodingConversionOverflowChars" xml:space="preserve">
+ <value>The output char buffer is too small to contain the decoded characters, encoding '{0}' fallback '{1}'.</value>
+ </data>
+ <data name="ArgumentOutOfRange_GetByteCountOverflow" xml:space="preserve">
+ <value>Too many characters. The resulting number of bytes is larger than what can be returned as an int.</value>
+ </data>
+ <data name="ArgumentOutOfRange_GetCharCountOverflow" xml:space="preserve">
+ <value>Too many bytes. The resulting number of chars is larger than what can be returned as an int.</value>
+ </data>
+ <data name="Argument_InvalidCharSequenceNoIndex" xml:space="preserve">
+ <value>String contains invalid Unicode code points.</value>
+ </data>
</root>
diff --git a/src/System.Console/src/System.Console.csproj b/src/System.Console/src/System.Console.csproj
index 52ec97d919..f4f188cf4c 100644
--- a/src/System.Console/src/System.Console.csproj
+++ b/src/System.Console/src/System.Console.csproj
@@ -15,6 +15,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <ItemGroup>
+ <Compile Include="FxCopBaseline.cs"/>
+ </ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\Console.cs" />
<Compile Include="System\ConsoleCancelEventArgs.cs" />
@@ -30,9 +33,6 @@
<Compile Include="$(CommonPath)\System\Text\ConsoleEncoding.cs">
<Link>Common\System\Text\ConsoleEncoding.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Text\EncodingHelper.cs">
- <Link>Common\System\IO\EncodingHelper.cs</Link>
- </Compile>
</ItemGroup>
<!-- Windows : UAP
<ItemGroup Condition="'$(TargetsWindows)' == 'true' And '$(TargetGroup)' == 'uap101aot' ">
@@ -42,6 +42,21 @@
<!-- Windows : Win32 -->
<ItemGroup Condition="'$(TargetsWindows)' == 'true' And '$(TargetGroup)' == 'netstandard'">
<Compile Include="System\ConsolePal.Windows.cs" />
+ <Compile Include="$(CommonPath)\System\Text\OSEncoding.Windows.cs">
+ <Link>Common\System\Text\OSEncoding.Windows.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Text\OSEncoder.cs">
+ <Link>Common\System\Text\OSEncoder.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Text\DBCSDecoder.cs">
+ <Link>Common\System\Text\DBCSDecoder.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.Encoding.Constants.cs">
+ <Link>Common\Interop\Windows\kernel32\Interop.Encoding.Constants.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetCPInfoEx.cs">
+ <Link>Common\Interop\Windows\kernel32\Interop.GetCPInfoEx.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs">
<Link>Common\Interop\Windows\Interop.Libraries.cs</Link>
</Compile>
@@ -99,6 +114,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.HandleTypes.cs">
<Link>Common\Interop\Windows\Interop.HandleTypes.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.MultiByteToWideChar.cs">
+ <Link>Common\Interop\Windows\Interop.MultiByteToWideChar.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.PeekConsoleInput.cs">
<Link>Common\Interop\Windows\Interop.PeekConsoleInput.cs</Link>
</Compile>
@@ -138,6 +156,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetConsoleWindowInfo.cs">
<Link>Common\Interop\Windows\Interop.SetConsoleWindowInfo.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.WideCharToMultiByte.cs">
+ <Link>Common\Interop\Windows\Interop.WideCharToMultiByte.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.WriteFile_IntPtr.cs">
<Link>Common\Interop\Windows\Interop.WriteFile.cs</Link>
</Compile>
@@ -147,6 +168,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.WriteConsoleOutput.cs">
<Link>Common\Interop\Windows\Interop.WriteConsoleOutput.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\System\Text\EncodingHelper.Windows.cs">
+ <Link>Common\System\IO\EncodingHelper.Windows.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\System\IO\Win32Marshal.cs">
<Link>Common\System\IO\Win32Marshal.cs</Link>
</Compile>
diff --git a/src/System.Console/src/System/ConsolePal.Unix.cs b/src/System.Console/src/System/ConsolePal.Unix.cs
index b33245460c..60adb519cd 100644
--- a/src/System.Console/src/System/ConsolePal.Unix.cs
+++ b/src/System.Console/src/System/ConsolePal.Unix.cs
@@ -708,7 +708,7 @@ namespace System
{
/// <summary>Gets the lazily-initialized terminal information for the terminal.</summary>
public static TerminalFormatStrings Instance { get { return s_instance.Value; } }
- private readonly static Lazy<TerminalFormatStrings> s_instance = new Lazy<TerminalFormatStrings>(() => new TerminalFormatStrings(TermInfo.Database.ReadActiveDatabase()));
+ private static readonly Lazy<TerminalFormatStrings> s_instance = new Lazy<TerminalFormatStrings>(() => new TerminalFormatStrings(TermInfo.Database.ReadActiveDatabase()));
/// <summary>The format string to use to change the foreground color.</summary>
public readonly string Foreground;
diff --git a/src/System.Console/src/System/ConsolePal.Windows.cs b/src/System.Console/src/System/ConsolePal.Windows.cs
index 08017ec58e..ee6c10ab4f 100644
--- a/src/System.Console/src/System/ConsolePal.Windows.cs
+++ b/src/System.Console/src/System/ConsolePal.Windows.cs
@@ -668,7 +668,7 @@ namespace System
Interop.Kernel32.Beep(frequency, duration);
}
- public unsafe static void MoveBufferArea(int sourceLeft, int sourceTop,
+ public static unsafe void MoveBufferArea(int sourceLeft, int sourceTop,
int sourceWidth, int sourceHeight, int targetLeft, int targetTop,
char sourceChar, ConsoleColor sourceForeColor,
ConsoleColor sourceBackColor)
@@ -1170,7 +1170,7 @@ namespace System
// world working set and to avoid requiring a reference to the
// System.IO.FileSystem contract.
- private unsafe static int ReadFileNative(IntPtr hFile, byte[] bytes, int offset, int count, bool isPipe, out int bytesRead, bool useFileAPIs)
+ private static unsafe int ReadFileNative(IntPtr hFile, byte[] bytes, int offset, int count, bool isPipe, out int bytesRead, bool useFileAPIs)
{
Debug.Assert(offset >= 0, "offset >= 0");
Debug.Assert(count >= 0, "count >= 0");
diff --git a/src/System.Console/tests/ConsoleEncoding.cs b/src/System.Console/tests/ConsoleEncoding.cs
new file mode 100644
index 0000000000..66fd95d17a
--- /dev/null
+++ b/src/System.Console/tests/ConsoleEncoding.cs
@@ -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 System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using Xunit;
+
+public class ConsoleEncoding
+{
+ public static IEnumerable<object[]> InputData()
+ {
+ yield return new object[] { "This is Ascii string" };
+ yield return new object[] { "This is string have surrogates \uD800\uDC00" };
+ yield return new object[] { "This string has non ascii charaters \u03b1\u00df\u0393\u03c0\u03a3\u03c3\u00b5" };
+ yield return new object[] { "This string has invalid surrogates \uD800\uD800\uD800\uD800\uD800\uD800" };
+ yield return new object[] { "\uD800" };
+ }
+
+ [Theory]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ [MemberData(nameof(InputData))]
+ public void TestEncoding(string inputString)
+ {
+ var outConsoleStream = Console.Out;
+ var inConsoleStream = Console.In;
+
+ try
+ {
+ byte [] inputBytes;
+ byte [] inputBytesNoBom = Console.OutputEncoding.GetBytes(inputString);
+ byte [] bom = Console.OutputEncoding.GetPreamble();
+
+ if (bom.Length > 0)
+ {
+ inputBytes = new byte[inputBytesNoBom.Length + bom.Length];
+ Array.Copy(bom, inputBytes, bom.Length);
+ Array.Copy(inputBytesNoBom, 0, inputBytes, bom.Length, inputBytesNoBom.Length);
+ }
+ else
+ {
+ inputBytes = inputBytesNoBom;
+ }
+
+ byte[] outBytes = new byte[inputBytes.Length];
+ using (MemoryStream ms = new MemoryStream(outBytes, true))
+ {
+ using (StreamWriter sw = new StreamWriter(ms, Console.OutputEncoding))
+ {
+ Console.SetOut(sw);
+ Console.Write(inputString);
+ }
+ }
+
+ Assert.Equal(inputBytes, outBytes);
+
+ string inString = new String(Console.InputEncoding.GetChars(inputBytesNoBom));
+
+ string outString;
+ using (MemoryStream ms = new MemoryStream(inputBytes, false))
+ {
+ using (StreamReader sr = new StreamReader(ms, Console.InputEncoding))
+ {
+ Console.SetIn(sr);
+ outString = Console.In.ReadToEnd();
+ }
+ }
+
+ Assert.Equal(inString, outString);
+ }
+ finally
+ {
+ Console.SetOut(outConsoleStream);
+ Console.SetIn(inConsoleStream);
+ }
+ }
+}
diff --git a/src/System.Console/tests/ManualTests/ManualTests.cs b/src/System.Console/tests/ManualTests/ManualTests.cs
index f713f94ba6..a54ed02e26 100644
--- a/src/System.Console/tests/ManualTests/ManualTests.cs
+++ b/src/System.Console/tests/ManualTests/ManualTests.cs
@@ -145,6 +145,14 @@ namespace System
AssertUserExpectedResults("the arrow keys move around the screen as expected with no other bad artificts");
}
+ [ConditionalFact(nameof(ManualTestsEnabled))]
+ public static void EncodingTest()
+ {
+ Console.WriteLine(Console.OutputEncoding);
+ Console.WriteLine("'\u03A0\u03A3'.");
+ AssertUserExpectedResults("Pi and Segma or question marks");
+ }
+
private static void AssertUserExpectedResults(string expected)
{
Console.Write($"Did you see {expected}? [y/n] ");
diff --git a/src/System.Console/tests/System.Console.Tests.csproj b/src/System.Console/tests/System.Console.Tests.csproj
index 7199d674b1..d2764a428f 100644
--- a/src/System.Console/tests/System.Console.Tests.csproj
+++ b/src/System.Console/tests/System.Console.Tests.csproj
@@ -9,6 +9,9 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
<ItemGroup>
+ <Compile Include="$(CommonTestPath)\System\PlatformDetection.cs">
+ <Link>Common\tests\System\PlatformDetection.cs</Link>
+ </Compile>
<Compile Include="CancelKeyPress.cs" />
<Compile Include="Helpers.cs" />
<Compile Include="ReadAndWrite.cs" />
@@ -18,6 +21,7 @@
<Compile Include="Color.cs" />
<Compile Include="SetOut.cs" />
<Compile Include="NegativeTesting.cs" />
+ <Compile Include="ConsoleEncoding.cs" />
<Compile Include="SyncTextReader.cs" />
<Compile Include="SyncTextWriter.cs" />
<Compile Include="Timeout.cs" />
diff --git a/src/System.Console/tests/WindowAndCursorProps.cs b/src/System.Console/tests/WindowAndCursorProps.cs
index 9a41d606b5..20eb258d6a 100644
--- a/src/System.Console/tests/WindowAndCursorProps.cs
+++ b/src/System.Console/tests/WindowAndCursorProps.cs
@@ -305,7 +305,7 @@ public class WindowAndCursorProps : RemoteExecutorTestBase
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
- if (!Console.IsInputRedirected && !Console.IsOutputRedirected)
+ if (PlatformDetection.IsNotWindowsNanoServer && !Console.IsInputRedirected && !Console.IsOutputRedirected)
{
Assert.Throws<ArgumentOutOfRangeException>(() => Console.SetWindowSize(-1, Console.WindowHeight));
Assert.Throws<ArgumentOutOfRangeException>(() => Console.SetWindowSize(Console.WindowWidth, -1));
diff --git a/src/System.Data.Common/src/System/Data/Common/DBSchemaTable.cs b/src/System.Data.Common/src/System/Data/Common/DBSchemaTable.cs
index 3e690e11ab..39e1a97aae 100644
--- a/src/System.Data.Common/src/System/Data/Common/DBSchemaTable.cs
+++ b/src/System.Data.Common/src/System/Data/Common/DBSchemaTable.cs
@@ -31,7 +31,7 @@ namespace System.Data.Common
SchemaMappingUnsortedIndex,
}
- static readonly private string[] s_DBCOLUMN_NAME = new string[] {
+ private static readonly string[] s_DBCOLUMN_NAME = new string[] {
SchemaTableColumn.ColumnName,
SchemaTableColumn.ColumnOrdinal,
SchemaTableColumn.ColumnSize,
diff --git a/src/System.Data.Common/src/System/Data/Common/DataStorage.cs b/src/System.Data.Common/src/System/Data/Common/DataStorage.cs
index 2cc5f7523b..bc574a3b19 100644
--- a/src/System.Data.Common/src/System/Data/Common/DataStorage.cs
+++ b/src/System.Data.Common/src/System/Data/Common/DataStorage.cs
@@ -124,8 +124,8 @@ namespace System.Data.Common
internal readonly bool _isStringType;
internal readonly bool _isValueType;
- private readonly static Func<Type, Tuple<bool, bool, bool, bool>> s_inspectTypeForInterfaces = InspectTypeForInterfaces;
- private readonly static ConcurrentDictionary<Type, Tuple<bool, bool, bool, bool>> s_typeImplementsInterface = new ConcurrentDictionary<Type, Tuple<bool, bool, bool, bool>>();
+ private static readonly Func<Type, Tuple<bool, bool, bool, bool>> s_inspectTypeForInterfaces = InspectTypeForInterfaces;
+ private static readonly ConcurrentDictionary<Type, Tuple<bool, bool, bool, bool>> s_typeImplementsInterface = new ConcurrentDictionary<Type, Tuple<bool, bool, bool, bool>>();
protected DataStorage(DataColumn column, Type type, object defaultValue, StorageType storageType)
: this(column, type, defaultValue, DBNull.Value, false, storageType)
diff --git a/src/System.Data.Common/src/System/Data/DataColumn.cs b/src/System.Data.Common/src/System/Data/DataColumn.cs
index 14d0a2d49d..eddc9c027c 100644
--- a/src/System.Data.Common/src/System/Data/DataColumn.cs
+++ b/src/System.Data.Common/src/System/Data/DataColumn.cs
@@ -1398,7 +1398,7 @@ namespace System.Data
}
}
- internal protected void CheckNotAllowNull()
+ protected internal void CheckNotAllowNull()
{
if (_storage == null)
{
diff --git a/src/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs b/src/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs
index 1b3ffa6924..673b97c111 100644
--- a/src/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs
+++ b/src/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs
@@ -16,9 +16,9 @@ namespace System.Data.SqlTypes
[Serializable, XmlSchemaProvider("GetXsdType")]
public sealed class SqlXml : INullable, IXmlSerializable
{
- private readonly static Func<Stream, XmlReaderSettings, XmlParserContext, XmlReader> s_sqlReaderDelegate = CreateSqlReaderDelegate();
- private readonly static XmlReaderSettings s_defaultXmlReaderSettings = new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment };
- private readonly static XmlReaderSettings s_defaultXmlReaderSettingsCloseInput = new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment, CloseInput = true };
+ private static readonly Func<Stream, XmlReaderSettings, XmlParserContext, XmlReader> s_sqlReaderDelegate = CreateSqlReaderDelegate();
+ private static readonly XmlReaderSettings s_defaultXmlReaderSettings = new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment };
+ private static readonly XmlReaderSettings s_defaultXmlReaderSettingsCloseInput = new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment, CloseInput = true };
private static MethodInfo s_createSqlReaderMethodInfo;
private bool _fNotNull; // false if null, the default ctor (plain 0) will make it Null
diff --git a/src/System.Data.SqlClient/src/Interop/SNINativeMethodWrapper.Windows.cs b/src/System.Data.SqlClient/src/Interop/SNINativeMethodWrapper.Windows.cs
index 103e3015a7..23cd8aa548 100644
--- a/src/System.Data.SqlClient/src/Interop/SNINativeMethodWrapper.Windows.cs
+++ b/src/System.Data.SqlClient/src/Interop/SNINativeMethodWrapper.Windows.cs
@@ -268,10 +268,10 @@ namespace System.Data.SqlClient
private static extern uint SNIPacketGetDataWrapper([In] IntPtr packet, [In, Out] byte[] readBuffer, uint readBufferLength, out uint dataSize);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
- private static unsafe extern void SNIPacketSetData(SNIPacket pPacket, [In] byte* pbBuf, uint cbBuf);
+ private static extern unsafe void SNIPacketSetData(SNIPacket pPacket, [In] byte* pbBuf, uint cbBuf);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
- private static unsafe extern uint SNISecGenClientContextWrapper(
+ private static extern unsafe uint SNISecGenClientContextWrapper(
[In] SNIHandle pConn,
[In, Out] byte[] pIn,
uint cbIn,
diff --git a/src/System.Data.SqlClient/src/Microsoft/SqlServer/Server/MetadataUtilsSmi.cs b/src/System.Data.SqlClient/src/Microsoft/SqlServer/Server/MetadataUtilsSmi.cs
index 9fa6cb0030..0040eb78f5 100644
--- a/src/System.Data.SqlClient/src/Microsoft/SqlServer/Server/MetadataUtilsSmi.cs
+++ b/src/System.Data.SqlClient/src/Microsoft/SqlServer/Server/MetadataUtilsSmi.cs
@@ -355,7 +355,7 @@ namespace Microsoft.SqlServer.Server
}
// Method to map from Type to ExtendedTypeCode
- static internal ExtendedClrTypeCode DetermineExtendedTypeCodeFromType(Type clrType)
+ internal static ExtendedClrTypeCode DetermineExtendedTypeCodeFromType(Type clrType)
{
ExtendedClrTypeCode resultCode;
return s_typeToExtendedTypeCodeMap.TryGetValue(clrType, out resultCode) ?
@@ -364,7 +364,7 @@ namespace Microsoft.SqlServer.Server
}
// Returns the ExtendedClrTypeCode that describes the given value
- static internal ExtendedClrTypeCode DetermineExtendedTypeCode(object value)
+ internal static ExtendedClrTypeCode DetermineExtendedTypeCode(object value)
{
return value != null ?
DetermineExtendedTypeCodeFromType(value.GetType()) :
@@ -372,7 +372,7 @@ namespace Microsoft.SqlServer.Server
}
// returns a sqldbtype for the given type code
- static internal SqlDbType InferSqlDbTypeFromTypeCode(ExtendedClrTypeCode typeCode)
+ internal static SqlDbType InferSqlDbTypeFromTypeCode(ExtendedClrTypeCode typeCode)
{
Debug.Assert(typeCode >= ExtendedClrTypeCode.Invalid && typeCode <= ExtendedClrTypeCode.Last, "Someone added a typecode without adding support here!");
@@ -381,7 +381,7 @@ namespace Microsoft.SqlServer.Server
// Infer SqlDbType from Type in the general case. Katmai-only (or later) features that need to
// infer types should use InferSqlDbTypeFromType_Katmai.
- static internal SqlDbType InferSqlDbTypeFromType(Type type)
+ internal static SqlDbType InferSqlDbTypeFromType(Type type)
{
ExtendedClrTypeCode typeCode = DetermineExtendedTypeCodeFromType(type);
SqlDbType returnType;
@@ -402,7 +402,7 @@ namespace Microsoft.SqlServer.Server
// example: TVP's are a new Katmai feature (no back compat issues) so can infer DATETIME2
// when mapping System.DateTime from DateTable or DbDataReader. DATETIME2 is better because
// of greater range that can handle all DateTime values.
- static internal SqlDbType InferSqlDbTypeFromType_Katmai(Type type)
+ internal static SqlDbType InferSqlDbTypeFromType_Katmai(Type type)
{
SqlDbType returnType = InferSqlDbTypeFromType(type);
if (SqlDbType.DateTime == returnType)
@@ -413,7 +413,7 @@ namespace Microsoft.SqlServer.Server
}
- static internal SqlMetaData SmiExtendedMetaDataToSqlMetaData(SmiExtendedMetaData source)
+ internal static SqlMetaData SmiExtendedMetaDataToSqlMetaData(SmiExtendedMetaData source)
{
if (SqlDbType.Xml == source.SqlDbType)
{
@@ -475,7 +475,7 @@ namespace Microsoft.SqlServer.Server
// compare SmiMetaData to SqlMetaData and determine if they are compatible.
- static internal bool IsCompatible(SmiMetaData firstMd, SqlMetaData secondMd)
+ internal static bool IsCompatible(SmiMetaData firstMd, SqlMetaData secondMd)
{
return firstMd.SqlDbType == secondMd.SqlDbType &&
firstMd.MaxLength == secondMd.MaxLength &&
@@ -489,7 +489,7 @@ namespace Microsoft.SqlServer.Server
// This is a modified version of SmiMetaDataFromSchemaTableRow above
// Since CoreCLR doesn't have GetSchema, we need to infer the MetaData from the CLR Type alone
- static internal SmiExtendedMetaData SmiMetaDataFromType(string colName, Type colType)
+ internal static SmiExtendedMetaData SmiMetaDataFromType(string colName, Type colType)
{
// Determine correct SqlDbType.
SqlDbType colDbType = InferSqlDbTypeFromType_Katmai(colType);
diff --git a/src/System.Data.SqlClient/src/System/Data/Common/AdapterUtil.cs b/src/System.Data.SqlClient/src/System/Data/Common/AdapterUtil.cs
index 77992b1963..e4c11fb003 100644
--- a/src/System.Data.SqlClient/src/System/Data/Common/AdapterUtil.cs
+++ b/src/System.Data.SqlClient/src/System/Data/Common/AdapterUtil.cs
@@ -43,7 +43,7 @@ namespace System.Data.Common
// location so that the catcher of the exception will have the appropriate call stack.
// This class is used so that there will be compile time checking of error messages.
- static internal Exception ExceptionWithStackTrace(Exception e)
+ internal static Exception ExceptionWithStackTrace(Exception e)
{
try
{
@@ -57,8 +57,8 @@ namespace System.Data.Common
// NOTE: Initializing a Task in SQL CLR requires the "UNSAFE" permission set (http://msdn.microsoft.com/en-us/library/ms172338.aspx)
// Therefore we are lazily initializing these Tasks to avoid forcing customers to use the "UNSAFE" set when they are actually using no Async features
- static private Task<bool> s_trueTask = null;
- static internal Task<bool> TrueTask
+ private static Task<bool> s_trueTask = null;
+ internal static Task<bool> TrueTask
{
get
{
@@ -70,8 +70,8 @@ namespace System.Data.Common
}
}
- static private Task<bool> s_falseTask = null;
- static internal Task<bool> FalseTask
+ private static Task<bool> s_falseTask = null;
+ internal static Task<bool> FalseTask
{
get
{
@@ -83,9 +83,9 @@ namespace System.Data.Common
}
}
- static private readonly bool s_isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+ private static readonly bool s_isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
- static internal bool IsWindows
+ internal static bool IsWindows
{
get
{
@@ -97,160 +97,160 @@ namespace System.Data.Common
//
// COM+ exceptions
//
- static internal ArgumentException Argument(string error)
+ internal static ArgumentException Argument(string error)
{
ArgumentException e = new ArgumentException(error);
return e;
}
- static internal ArgumentException Argument(string error, Exception inner)
+ internal static ArgumentException Argument(string error, Exception inner)
{
ArgumentException e = new ArgumentException(error, inner);
return e;
}
- static internal ArgumentException Argument(string error, string parameter)
+ internal static ArgumentException Argument(string error, string parameter)
{
ArgumentException e = new ArgumentException(error, parameter);
return e;
}
- static internal ArgumentNullException ArgumentNull(string parameter)
+ internal static ArgumentNullException ArgumentNull(string parameter)
{
ArgumentNullException e = new ArgumentNullException(parameter);
return e;
}
- static internal ArgumentNullException ArgumentNull(string parameter, string error)
+ internal static ArgumentNullException ArgumentNull(string parameter, string error)
{
ArgumentNullException e = new ArgumentNullException(parameter, error);
return e;
}
- static internal ArgumentOutOfRangeException ArgumentOutOfRange(string parameterName)
+ internal static ArgumentOutOfRangeException ArgumentOutOfRange(string parameterName)
{
ArgumentOutOfRangeException e = new ArgumentOutOfRangeException(parameterName);
return e;
}
- static internal ArgumentOutOfRangeException ArgumentOutOfRange(string message, string parameterName)
+ internal static ArgumentOutOfRangeException ArgumentOutOfRange(string message, string parameterName)
{
ArgumentOutOfRangeException e = new ArgumentOutOfRangeException(parameterName, message);
return e;
}
- static internal IndexOutOfRangeException IndexOutOfRange(int value)
+ internal static IndexOutOfRangeException IndexOutOfRange(int value)
{
IndexOutOfRangeException e = new IndexOutOfRangeException(value.ToString(CultureInfo.InvariantCulture));
return e;
}
- static internal IndexOutOfRangeException IndexOutOfRange(string error)
+ internal static IndexOutOfRangeException IndexOutOfRange(string error)
{
IndexOutOfRangeException e = new IndexOutOfRangeException(error);
return e;
}
- static internal IndexOutOfRangeException IndexOutOfRange()
+ internal static IndexOutOfRangeException IndexOutOfRange()
{
IndexOutOfRangeException e = new IndexOutOfRangeException();
return e;
}
- static internal InvalidCastException InvalidCast(string error)
+ internal static InvalidCastException InvalidCast(string error)
{
return InvalidCast(error, null);
}
- static internal InvalidCastException InvalidCast(string error, Exception inner)
+ internal static InvalidCastException InvalidCast(string error, Exception inner)
{
InvalidCastException e = new InvalidCastException(error, inner);
return e;
}
- static internal InvalidOperationException InvalidOperation(string error)
+ internal static InvalidOperationException InvalidOperation(string error)
{
InvalidOperationException e = new InvalidOperationException(error);
return e;
}
- static internal TimeoutException TimeoutException(string error)
+ internal static TimeoutException TimeoutException(string error)
{
TimeoutException e = new TimeoutException(error);
return e;
}
- static internal InvalidOperationException InvalidOperation(string error, Exception inner)
+ internal static InvalidOperationException InvalidOperation(string error, Exception inner)
{
InvalidOperationException e = new InvalidOperationException(error, inner);
return e;
}
- static internal NotSupportedException NotSupported()
+ internal static NotSupportedException NotSupported()
{
NotSupportedException e = new NotSupportedException();
return e;
}
- static internal NotSupportedException NotSupported(string error)
+ internal static NotSupportedException NotSupported(string error)
{
NotSupportedException e = new NotSupportedException(error);
return e;
}
- static internal OverflowException Overflow(string error)
+ internal static OverflowException Overflow(string error)
{
return Overflow(error, null);
}
- static internal OverflowException Overflow(string error, Exception inner)
+ internal static OverflowException Overflow(string error, Exception inner)
{
OverflowException e = new OverflowException(error, inner);
return e;
}
- static internal PlatformNotSupportedException DbTypeNotSupported(string dbType)
+ internal static PlatformNotSupportedException DbTypeNotSupported(string dbType)
{
PlatformNotSupportedException e = new PlatformNotSupportedException(Res.GetString(Res.SQL_DbTypeNotSupportedOnThisPlatform, dbType));
return e;
}
- static internal InvalidCastException InvalidCast()
+ internal static InvalidCastException InvalidCast()
{
InvalidCastException e = new InvalidCastException();
return e;
}
- static internal IOException IO(string error)
+ internal static IOException IO(string error)
{
IOException e = new IOException(error);
return e;
}
- static internal IOException IO(string error, Exception inner)
+ internal static IOException IO(string error, Exception inner)
{
IOException e = new IOException(error, inner);
return e;
}
- static internal InvalidOperationException DataAdapter(string error)
+ internal static InvalidOperationException DataAdapter(string error)
{
return InvalidOperation(error);
}
- static private InvalidOperationException Provider(string error)
+ private static InvalidOperationException Provider(string error)
{
return InvalidOperation(error);
}
- static internal ObjectDisposedException ObjectDisposed(object instance)
+ internal static ObjectDisposedException ObjectDisposed(object instance)
{
ObjectDisposedException e = new ObjectDisposedException(instance.GetType().Name);
return e;
}
- static internal InvalidOperationException MethodCalledTwice(string method)
+ internal static InvalidOperationException MethodCalledTwice(string method)
{
InvalidOperationException e = new InvalidOperationException(Res.GetString(Res.ADP_CalledTwice, method));
return e;
}
- static internal ArgumentException InvalidMultipartName(string property, string value)
+ internal static ArgumentException InvalidMultipartName(string property, string value)
{
ArgumentException e = new ArgumentException(Res.GetString(Res.ADP_InvalidMultipartName, Res.GetString(property), value));
return e;
}
- static internal ArgumentException InvalidMultipartNameIncorrectUsageOfQuotes(string property, string value)
+ internal static ArgumentException InvalidMultipartNameIncorrectUsageOfQuotes(string property, string value)
{
ArgumentException e = new ArgumentException(Res.GetString(Res.ADP_InvalidMultipartNameQuoteUsage, Res.GetString(property), value));
return e;
}
- static internal ArgumentException InvalidMultipartNameToManyParts(string property, string value, int limit)
+ internal static ArgumentException InvalidMultipartNameToManyParts(string property, string value, int limit)
{
ArgumentException e = new ArgumentException(Res.GetString(Res.ADP_InvalidMultipartNameToManyParts, Res.GetString(property), value, limit));
return e;
}
- static internal void CheckArgumentNull(object value, string parameterName)
+ internal static void CheckArgumentNull(object value, string parameterName)
{
if (null == value)
{
@@ -260,13 +260,13 @@ namespace System.Data.Common
- static internal bool IsCatchableExceptionType(Exception e)
+ internal static bool IsCatchableExceptionType(Exception e)
{
return !((e is NullReferenceException) ||
(e is SecurityException));
}
- static internal bool IsCatchableOrSecurityExceptionType(Exception e)
+ internal static bool IsCatchableOrSecurityExceptionType(Exception e)
{
// a 'catchable' exception is defined by what it is not.
// since IsCatchableExceptionType defined SecurityException as not 'catchable'
@@ -283,14 +283,14 @@ namespace System.Data.Common
// Invalid Enumeration
- static internal ArgumentOutOfRangeException InvalidEnumerationValue(Type type, int value)
+ internal static ArgumentOutOfRangeException InvalidEnumerationValue(Type type, int value)
{
return ADP.ArgumentOutOfRange(Res.GetString(Res.ADP_InvalidEnumerationValue, type.Name, value.ToString(System.Globalization.CultureInfo.InvariantCulture)), type.Name);
}
// IDbCommand.CommandType
- static internal ArgumentOutOfRangeException InvalidCommandType(CommandType value)
+ internal static ArgumentOutOfRangeException InvalidCommandType(CommandType value)
{
#if DEBUG
switch (value)
@@ -307,7 +307,7 @@ namespace System.Data.Common
// IDbConnection.BeginTransaction, OleDbTransaction.Begin
- static internal ArgumentOutOfRangeException InvalidIsolationLevel(IsolationLevel value)
+ internal static ArgumentOutOfRangeException InvalidIsolationLevel(IsolationLevel value)
{
#if DEBUG
switch (value)
@@ -328,7 +328,7 @@ namespace System.Data.Common
// IDataParameter.Direction
- static internal ArgumentOutOfRangeException InvalidParameterDirection(ParameterDirection value)
+ internal static ArgumentOutOfRangeException InvalidParameterDirection(ParameterDirection value)
{
#if DEBUG
switch (value)
@@ -346,7 +346,7 @@ namespace System.Data.Common
// IDbCommand.UpdateRowSource
- static internal ArgumentOutOfRangeException InvalidUpdateRowSource(UpdateRowSource value)
+ internal static ArgumentOutOfRangeException InvalidUpdateRowSource(UpdateRowSource value)
{
#if DEBUG
switch (value)
@@ -366,19 +366,19 @@ namespace System.Data.Common
//
// DbConnectionOptions, DataAccess
//
- static internal ArgumentException ConnectionStringSyntax(int index)
+ internal static ArgumentException ConnectionStringSyntax(int index)
{
return Argument(Res.GetString(Res.ADP_ConnectionStringSyntax, index));
}
- static internal ArgumentException KeywordNotSupported(string keyword)
+ internal static ArgumentException KeywordNotSupported(string keyword)
{
return Argument(Res.GetString(Res.ADP_KeywordNotSupported, keyword));
}
- static internal ArgumentException InvalidMinMaxPoolSizeValues()
+ internal static ArgumentException InvalidMinMaxPoolSizeValues()
{
return ADP.Argument(Res.GetString(Res.ADP_InvalidMinMaxPoolSizeValues));
}
- static internal ArgumentException ConvertFailed(Type fromType, Type toType, Exception innerException)
+ internal static ArgumentException ConvertFailed(Type fromType, Type toType, Exception innerException)
{
return ADP.Argument(Res.GetString(Res.SqlConvert_ConvertFailed, fromType.FullName, toType.FullName), innerException);
}
@@ -387,17 +387,17 @@ namespace System.Data.Common
//
// DbConnection
//
- static internal InvalidOperationException NoConnectionString()
+ internal static InvalidOperationException NoConnectionString()
{
return InvalidOperation(Res.GetString(Res.ADP_NoConnectionString));
}
- static internal Exception MethodNotImplemented([CallerMemberName] string methodName = "")
+ internal static Exception MethodNotImplemented([CallerMemberName] string methodName = "")
{
return NotImplemented.ByDesignWithMessage(methodName);
}
- static private string ConnectionStateMsg(ConnectionState state)
+ private static string ConnectionStateMsg(ConnectionState state)
{
switch (state)
{
@@ -421,25 +421,25 @@ namespace System.Data.Common
//
// : DbConnectionOptions, DataAccess, SqlClient
//
- static internal Exception InvalidConnectionOptionValue(string key)
+ internal static Exception InvalidConnectionOptionValue(string key)
{
return InvalidConnectionOptionValue(key, null);
}
- static internal Exception InvalidConnectionOptionValueLength(string key, int limit)
+ internal static Exception InvalidConnectionOptionValueLength(string key, int limit)
{
return Argument(Res.GetString(Res.ADP_InvalidConnectionOptionValueLength, key, limit));
}
- static internal Exception InvalidConnectionOptionValue(string key, Exception inner)
+ internal static Exception InvalidConnectionOptionValue(string key, Exception inner)
{
return Argument(Res.GetString(Res.ADP_InvalidConnectionOptionValue, key), inner);
}
- static internal Exception MissingConnectionOptionValue(string key, string requiredAdditionalKey)
+ internal static Exception MissingConnectionOptionValue(string key, string requiredAdditionalKey)
{
return Argument(Res.GetString(Res.ADP_MissingConnectionOptionValue, key, requiredAdditionalKey));
}
- static internal Exception WrongType(Type got, Type expected)
+ internal static Exception WrongType(Type got, Type expected)
{
return Argument(Res.GetString(Res.SQL_WrongType, got.ToString(), expected.ToString()));
}
@@ -448,12 +448,12 @@ namespace System.Data.Common
//
// DbConnectionPool and related
//
- static internal Exception PooledOpenTimeout()
+ internal static Exception PooledOpenTimeout()
{
return ADP.InvalidOperation(Res.GetString(Res.ADP_PooledOpenTimeout));
}
- static internal Exception NonPooledOpenTimeout()
+ internal static Exception NonPooledOpenTimeout()
{
return ADP.TimeoutException(Res.GetString(Res.ADP_NonPooledOpenTimeout));
}
@@ -461,31 +461,31 @@ namespace System.Data.Common
//
// Generic Data Provider Collection
//
- static internal ArgumentException CollectionRemoveInvalidObject(Type itemType, ICollection collection)
+ internal static ArgumentException CollectionRemoveInvalidObject(Type itemType, ICollection collection)
{
return Argument(Res.GetString(Res.ADP_CollectionRemoveInvalidObject, itemType.Name, collection.GetType().Name));
}
- static internal ArgumentNullException CollectionNullValue(string parameter, Type collection, Type itemType)
+ internal static ArgumentNullException CollectionNullValue(string parameter, Type collection, Type itemType)
{
return ArgumentNull(parameter, Res.GetString(Res.ADP_CollectionNullValue, collection.Name, itemType.Name));
}
- static internal IndexOutOfRangeException CollectionIndexInt32(int index, Type collection, int count)
+ internal static IndexOutOfRangeException CollectionIndexInt32(int index, Type collection, int count)
{
return IndexOutOfRange(Res.GetString(Res.ADP_CollectionIndexInt32, index.ToString(CultureInfo.InvariantCulture), collection.Name, count.ToString(CultureInfo.InvariantCulture)));
}
- static internal IndexOutOfRangeException CollectionIndexString(Type itemType, string propertyName, string propertyValue, Type collection)
+ internal static IndexOutOfRangeException CollectionIndexString(Type itemType, string propertyName, string propertyValue, Type collection)
{
return IndexOutOfRange(Res.GetString(Res.ADP_CollectionIndexString, itemType.Name, propertyName, propertyValue, collection.Name));
}
- static internal InvalidCastException CollectionInvalidType(Type collection, Type itemType, object invalidValue)
+ internal static InvalidCastException CollectionInvalidType(Type collection, Type itemType, object invalidValue)
{
return InvalidCast(Res.GetString(Res.ADP_CollectionInvalidType, collection.Name, itemType.Name, invalidValue.GetType().Name));
}
- static internal ArgumentException ParametersIsNotParent(Type parameterType, ICollection collection)
+ internal static ArgumentException ParametersIsNotParent(Type parameterType, ICollection collection)
{
return Argument(Res.GetString(Res.ADP_CollectionIsNotParent, parameterType.Name, collection.GetType().Name));
}
- static internal ArgumentException ParametersIsParent(Type parameterType, ICollection collection)
+ internal static ArgumentException ParametersIsParent(Type parameterType, ICollection collection)
{
return Argument(Res.GetString(Res.ADP_CollectionIsNotParent, parameterType.Name, collection.GetType().Name));
}
@@ -493,36 +493,36 @@ namespace System.Data.Common
//
// DbProviderException
//
- static internal InvalidOperationException TransactionConnectionMismatch()
+ internal static InvalidOperationException TransactionConnectionMismatch()
{
return Provider(Res.GetString(Res.ADP_TransactionConnectionMismatch));
}
- static internal InvalidOperationException TransactionRequired(string method)
+ internal static InvalidOperationException TransactionRequired(string method)
{
return Provider(Res.GetString(Res.ADP_TransactionRequired, method));
}
- static internal Exception CommandTextRequired(string method)
+ internal static Exception CommandTextRequired(string method)
{
return InvalidOperation(Res.GetString(Res.ADP_CommandTextRequired, method));
}
- static internal InvalidOperationException ConnectionRequired(string method)
+ internal static InvalidOperationException ConnectionRequired(string method)
{
return InvalidOperation(Res.GetString(Res.ADP_ConnectionRequired, method));
}
- static internal InvalidOperationException OpenConnectionRequired(string method, ConnectionState state)
+ internal static InvalidOperationException OpenConnectionRequired(string method, ConnectionState state)
{
return InvalidOperation(Res.GetString(Res.ADP_OpenConnectionRequired, method, ADP.ConnectionStateMsg(state)));
}
- static internal Exception OpenReaderExists()
+ internal static Exception OpenReaderExists()
{
return OpenReaderExists(null);
}
- static internal Exception OpenReaderExists(Exception e)
+ internal static Exception OpenReaderExists(Exception e)
{
return InvalidOperation(Res.GetString(Res.ADP_OpenReaderExists), e);
}
@@ -531,18 +531,18 @@ namespace System.Data.Common
//
// DbDataReader
//
- static internal Exception NonSeqByteAccess(long badIndex, long currIndex, string method)
+ internal static Exception NonSeqByteAccess(long badIndex, long currIndex, string method)
{
return InvalidOperation(Res.GetString(Res.ADP_NonSeqByteAccess, badIndex.ToString(CultureInfo.InvariantCulture), currIndex.ToString(CultureInfo.InvariantCulture), method));
}
- static internal Exception NegativeParameter(string parameterName)
+ internal static Exception NegativeParameter(string parameterName)
{
return InvalidOperation(Res.GetString(Res.ADP_NegativeParameter, parameterName));
}
- static internal Exception InvalidSeekOrigin(string parameterName)
+ internal static Exception InvalidSeekOrigin(string parameterName)
{
return ArgumentOutOfRange(Res.GetString(Res.ADP_InvalidSeekOrigin), parameterName);
}
@@ -550,12 +550,12 @@ namespace System.Data.Common
//
// SqlMetaData, SqlTypes, SqlClient
//
- static internal Exception InvalidMetaDataValue()
+ internal static Exception InvalidMetaDataValue()
{
return ADP.Argument(Res.GetString(Res.ADP_InvalidMetaDataValue));
}
- static internal InvalidOperationException NonSequentialColumnAccess(int badCol, int currCol)
+ internal static InvalidOperationException NonSequentialColumnAccess(int badCol, int currCol)
{
return InvalidOperation(Res.GetString(Res.ADP_NonSequentialColumnAccess, badCol.ToString(CultureInfo.InvariantCulture), currCol.ToString(CultureInfo.InvariantCulture)));
}
@@ -564,27 +564,27 @@ namespace System.Data.Common
//
// : IDbCommand
//
- static internal Exception InvalidCommandTimeout(int value, [CallerMemberName] string property = "")
+ internal static Exception InvalidCommandTimeout(int value, [CallerMemberName] string property = "")
{
return Argument(Res.GetString(Res.ADP_InvalidCommandTimeout, value.ToString(CultureInfo.InvariantCulture)), property);
}
- static internal Exception UninitializedParameterSize(int index, Type dataType)
+ internal static Exception UninitializedParameterSize(int index, Type dataType)
{
return InvalidOperation(Res.GetString(Res.ADP_UninitializedParameterSize, index.ToString(CultureInfo.InvariantCulture), dataType.Name));
}
- static internal Exception PrepareParameterType(DbCommand cmd)
+ internal static Exception PrepareParameterType(DbCommand cmd)
{
return InvalidOperation(Res.GetString(Res.ADP_PrepareParameterType, cmd.GetType().Name));
}
- static internal Exception PrepareParameterSize(DbCommand cmd)
+ internal static Exception PrepareParameterSize(DbCommand cmd)
{
return InvalidOperation(Res.GetString(Res.ADP_PrepareParameterSize, cmd.GetType().Name));
}
- static internal Exception PrepareParameterScale(DbCommand cmd, string type)
+ internal static Exception PrepareParameterScale(DbCommand cmd, string type)
{
return InvalidOperation(Res.GetString(Res.ADP_PrepareParameterScale, cmd.GetType().Name, type));
}
- static internal Exception MismatchedAsyncResult(string expectedMethod, string gotMethod)
+ internal static Exception MismatchedAsyncResult(string expectedMethod, string gotMethod)
{
return InvalidOperation(Res.GetString(Res.ADP_MismatchedAsyncResult, expectedMethod, gotMethod));
}
@@ -592,23 +592,23 @@ namespace System.Data.Common
//
// : ConnectionUtil
//
- static internal Exception ConnectionIsDisabled(Exception InnerException)
+ internal static Exception ConnectionIsDisabled(Exception InnerException)
{
return InvalidOperation(Res.GetString(Res.ADP_ConnectionIsDisabled), InnerException);
}
- static internal Exception ClosedConnectionError()
+ internal static Exception ClosedConnectionError()
{
return InvalidOperation(Res.GetString(Res.ADP_ClosedConnectionError));
}
- static internal Exception ConnectionAlreadyOpen(ConnectionState state)
+ internal static Exception ConnectionAlreadyOpen(ConnectionState state)
{
return InvalidOperation(Res.GetString(Res.ADP_ConnectionAlreadyOpen, ADP.ConnectionStateMsg(state)));
}
- static internal Exception OpenConnectionPropertySet(string property, ConnectionState state)
+ internal static Exception OpenConnectionPropertySet(string property, ConnectionState state)
{
return InvalidOperation(Res.GetString(Res.ADP_OpenConnectionPropertySet, property, ADP.ConnectionStateMsg(state)));
}
- static internal Exception EmptyDatabaseName()
+ internal static Exception EmptyDatabaseName()
{
return Argument(Res.GetString(Res.ADP_EmptyDatabaseName));
}
@@ -620,7 +620,7 @@ namespace System.Data.Common
ConnectionOptionsMissing,
CouldNotSwitchToClosedPreviouslyOpenedState,
}
- static internal Exception InternalConnectionError(ConnectionError internalError)
+ internal static Exception InternalConnectionError(ConnectionError internalError)
{
return InvalidOperation(Res.GetString(Res.ADP_InternalConnectionError, (int)internalError));
}
@@ -664,17 +664,17 @@ namespace System.Data.Common
UnknownTransactionFailure = 60,
}
- static internal Exception InternalError(InternalErrorCode internalError)
+ internal static Exception InternalError(InternalErrorCode internalError)
{
return InvalidOperation(Res.GetString(Res.ADP_InternalProviderError, (int)internalError));
}
- static internal Exception InvalidConnectRetryCountValue()
+ internal static Exception InvalidConnectRetryCountValue()
{
return Argument(Res.GetString(Res.SQLCR_InvalidConnectRetryCountValue));
}
- static internal Exception InvalidConnectRetryIntervalValue()
+ internal static Exception InvalidConnectRetryIntervalValue()
{
return Argument(Res.GetString(Res.SQLCR_InvalidConnectRetryIntervalValue));
}
@@ -682,27 +682,27 @@ namespace System.Data.Common
//
// : DbDataReader
//
- static internal Exception DataReaderClosed([CallerMemberName] string method = "")
+ internal static Exception DataReaderClosed([CallerMemberName] string method = "")
{
return InvalidOperation(Res.GetString(Res.ADP_DataReaderClosed, method));
}
- static internal ArgumentOutOfRangeException InvalidSourceBufferIndex(int maxLen, long srcOffset, string parameterName)
+ internal static ArgumentOutOfRangeException InvalidSourceBufferIndex(int maxLen, long srcOffset, string parameterName)
{
return ArgumentOutOfRange(Res.GetString(Res.ADP_InvalidSourceBufferIndex, maxLen.ToString(CultureInfo.InvariantCulture), srcOffset.ToString(CultureInfo.InvariantCulture)), parameterName);
}
- static internal ArgumentOutOfRangeException InvalidDestinationBufferIndex(int maxLen, int dstOffset, string parameterName)
+ internal static ArgumentOutOfRangeException InvalidDestinationBufferIndex(int maxLen, int dstOffset, string parameterName)
{
return ArgumentOutOfRange(Res.GetString(Res.ADP_InvalidDestinationBufferIndex, maxLen.ToString(CultureInfo.InvariantCulture), dstOffset.ToString(CultureInfo.InvariantCulture)), parameterName);
}
- static internal IndexOutOfRangeException InvalidBufferSizeOrIndex(int numBytes, int bufferIndex)
+ internal static IndexOutOfRangeException InvalidBufferSizeOrIndex(int numBytes, int bufferIndex)
{
return IndexOutOfRange(Res.GetString(Res.SQL_InvalidBufferSizeOrIndex, numBytes.ToString(CultureInfo.InvariantCulture), bufferIndex.ToString(CultureInfo.InvariantCulture)));
}
- static internal Exception InvalidDataLength(long length)
+ internal static Exception InvalidDataLength(long length)
{
return IndexOutOfRange(Res.GetString(Res.SQL_InvalidDataLength, length.ToString(CultureInfo.InvariantCulture)));
}
- static internal InvalidOperationException AsyncOperationPending()
+ internal static InvalidOperationException AsyncOperationPending()
{
return InvalidOperation(Res.GetString(Res.ADP_PendingAsyncOperation));
}
@@ -710,49 +710,49 @@ namespace System.Data.Common
//
// : Stream
//
- static internal Exception StreamClosed([CallerMemberName] string method = "")
+ internal static Exception StreamClosed([CallerMemberName] string method = "")
{
return InvalidOperation(Res.GetString(Res.ADP_StreamClosed, method));
}
- static internal IOException ErrorReadingFromStream(Exception internalException)
+ internal static IOException ErrorReadingFromStream(Exception internalException)
{
return IO(Res.GetString(Res.SqlMisc_StreamErrorMessage), internalException);
}
- static internal ArgumentException InvalidDataType(string typeName)
+ internal static ArgumentException InvalidDataType(string typeName)
{
return Argument(Res.GetString(Res.ADP_InvalidDataType, typeName));
}
- static internal ArgumentException UnknownDataType(Type dataType)
+ internal static ArgumentException UnknownDataType(Type dataType)
{
return Argument(Res.GetString(Res.ADP_UnknownDataType, dataType.FullName));
}
- static internal ArgumentException DbTypeNotSupported(System.Data.DbType type, Type enumtype)
+ internal static ArgumentException DbTypeNotSupported(System.Data.DbType type, Type enumtype)
{
return Argument(Res.GetString(Res.ADP_DbTypeNotSupported, type.ToString(), enumtype.Name));
}
- static internal ArgumentException InvalidOffsetValue(int value)
+ internal static ArgumentException InvalidOffsetValue(int value)
{
return Argument(Res.GetString(Res.ADP_InvalidOffsetValue, value.ToString(CultureInfo.InvariantCulture)));
}
- static internal ArgumentException InvalidSizeValue(int value)
+ internal static ArgumentException InvalidSizeValue(int value)
{
return Argument(Res.GetString(Res.ADP_InvalidSizeValue, value.ToString(CultureInfo.InvariantCulture)));
}
- static internal ArgumentException ParameterValueOutOfRange(Decimal value)
+ internal static ArgumentException ParameterValueOutOfRange(Decimal value)
{
return ADP.Argument(Res.GetString(Res.ADP_ParameterValueOutOfRange, value.ToString((IFormatProvider)null)));
}
- static internal ArgumentException ParameterValueOutOfRange(SqlDecimal value)
+ internal static ArgumentException ParameterValueOutOfRange(SqlDecimal value)
{
return ADP.Argument(Res.GetString(Res.ADP_ParameterValueOutOfRange, value.ToString()));
}
- static internal ArgumentException VersionDoesNotSupportDataType(string typeName)
+ internal static ArgumentException VersionDoesNotSupportDataType(string typeName)
{
return Argument(Res.GetString(Res.ADP_VersionDoesNotSupportDataType, typeName));
}
- static internal Exception ParameterConversionFailed(object value, Type destType, Exception inner)
+ internal static Exception ParameterConversionFailed(object value, Type destType, Exception inner)
{
Debug.Assert(null != value, "null value on conversion failure");
Debug.Assert(null != inner, "null inner on conversion failure");
@@ -785,19 +785,19 @@ namespace System.Data.Common
//
// : IDataParameterCollection
//
- static internal Exception ParametersMappingIndex(int index, DbParameterCollection collection)
+ internal static Exception ParametersMappingIndex(int index, DbParameterCollection collection)
{
return CollectionIndexInt32(index, collection.GetType(), collection.Count);
}
- static internal Exception ParametersSourceIndex(string parameterName, DbParameterCollection collection, Type parameterType)
+ internal static Exception ParametersSourceIndex(string parameterName, DbParameterCollection collection, Type parameterType)
{
return CollectionIndexString(parameterType, ADP.ParameterName, parameterName, collection.GetType());
}
- static internal Exception ParameterNull(string parameter, DbParameterCollection collection, Type parameterType)
+ internal static Exception ParameterNull(string parameter, DbParameterCollection collection, Type parameterType)
{
return CollectionNullValue(parameter, collection.GetType(), parameterType);
}
- static internal Exception InvalidParameterType(DbParameterCollection collection, Type parameterType, object invalidValue)
+ internal static Exception InvalidParameterType(DbParameterCollection collection, Type parameterType, object invalidValue)
{
return CollectionInvalidType(collection.GetType(), parameterType, invalidValue);
}
@@ -805,11 +805,11 @@ namespace System.Data.Common
//
// : IDbTransaction
//
- static internal Exception ParallelTransactionsNotSupported(DbConnection obj)
+ internal static Exception ParallelTransactionsNotSupported(DbConnection obj)
{
return InvalidOperation(Res.GetString(Res.ADP_ParallelTransactionsNotSupported, obj.GetType().Name));
}
- static internal Exception TransactionZombied(DbTransaction obj)
+ internal static Exception TransactionZombied(DbTransaction obj)
{
return InvalidOperation(Res.GetString(Res.ADP_TransactionZombied, obj.GetType().Name));
}
@@ -827,77 +827,77 @@ namespace System.Data.Common
internal const int DefaultConnectionTimeout = DbConnectionStringDefaults.ConnectTimeout;
internal const float FailoverTimeoutStep = 0.08F; // fraction of timeout to use for fast failover connections
- // security issue, don't rely upon static public readonly values - AS/URT 109635
- static internal readonly String StrEmpty = ""; // String.Empty
+ // security issue, don't rely upon public static readonly values - AS/URT 109635
+ internal static readonly String StrEmpty = ""; // String.Empty
internal const int CharSize = sizeof(char);
- static internal void TimerCurrent(out long ticks)
+ internal static void TimerCurrent(out long ticks)
{
ticks = DateTime.UtcNow.ToFileTimeUtc();
}
- static internal long TimerCurrent()
+ internal static long TimerCurrent()
{
return DateTime.UtcNow.ToFileTimeUtc();
}
- static internal long TimerFromSeconds(int seconds)
+ internal static long TimerFromSeconds(int seconds)
{
long result = checked((long)seconds * TimeSpan.TicksPerSecond);
return result;
}
- static internal long TimerFromMilliseconds(long milliseconds)
+ internal static long TimerFromMilliseconds(long milliseconds)
{
long result = checked(milliseconds * TimeSpan.TicksPerMillisecond);
return result;
}
- static internal bool TimerHasExpired(long timerExpire)
+ internal static bool TimerHasExpired(long timerExpire)
{
bool result = TimerCurrent() > timerExpire;
return result;
}
- static internal long TimerRemaining(long timerExpire)
+ internal static long TimerRemaining(long timerExpire)
{
long timerNow = TimerCurrent();
long result = checked(timerExpire - timerNow);
return result;
}
- static internal long TimerRemainingMilliseconds(long timerExpire)
+ internal static long TimerRemainingMilliseconds(long timerExpire)
{
long result = TimerToMilliseconds(TimerRemaining(timerExpire));
return result;
}
- static internal long TimerRemainingSeconds(long timerExpire)
+ internal static long TimerRemainingSeconds(long timerExpire)
{
long result = TimerToSeconds(TimerRemaining(timerExpire));
return result;
}
- static internal long TimerToMilliseconds(long timerValue)
+ internal static long TimerToMilliseconds(long timerValue)
{
long result = timerValue / TimeSpan.TicksPerMillisecond;
return result;
}
- static private long TimerToSeconds(long timerValue)
+ private static long TimerToSeconds(long timerValue)
{
long result = timerValue / TimeSpan.TicksPerSecond;
return result;
}
- static internal string MachineName()
+ internal static string MachineName()
{
return Environment.MachineName;
}
- static internal string BuildQuotedString(string quotePrefix, string quoteSuffix, string unQuotedString)
+ internal static string BuildQuotedString(string quotePrefix, string quoteSuffix, string unQuotedString)
{
StringBuilder resultString = new StringBuilder();
if (string.IsNullOrEmpty(quotePrefix) == false)
@@ -924,7 +924,7 @@ namespace System.Data.Common
// { "a", "a", "a1" } -> { "a", "a2", "a1" }
// { "a", "A", "a" } -> { "a", "A1", "a2" }
// { "a", "A", "a1" } -> { "a", "A2", "a1" }
- static internal void BuildSchemaTableInfoTableNames(string[] columnNameArray)
+ internal static void BuildSchemaTableInfoTableNames(string[] columnNameArray)
{
Dictionary<string, int> hash = new Dictionary<string, int>(columnNameArray.Length);
@@ -968,7 +968,7 @@ namespace System.Data.Common
}
}
- static private int GenerateUniqueName(Dictionary<string, int> hash, ref string columnName, int index, int uniqueIndex)
+ private static int GenerateUniqueName(Dictionary<string, int> hash, ref string columnName, int index, int uniqueIndex)
{
for (; ; ++uniqueIndex)
{
@@ -985,12 +985,12 @@ namespace System.Data.Common
}
- static internal int DstCompare(string strA, string strB)
+ internal static int DstCompare(string strA, string strB)
{ // this is null safe
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, ADP.compareOptions);
}
- static internal bool IsDirection(DbParameter value, ParameterDirection condition)
+ internal static bool IsDirection(DbParameter value, ParameterDirection condition)
{
#if DEBUG
IsDirectionValid(condition);
@@ -998,7 +998,7 @@ namespace System.Data.Common
return (condition == (condition & value.Direction));
}
#if DEBUG
- static private void IsDirectionValid(ParameterDirection value)
+ private static void IsDirectionValid(ParameterDirection value)
{
switch (value)
{ // @perfnote: Enum.IsDefined
@@ -1013,7 +1013,7 @@ namespace System.Data.Common
}
#endif
- static internal bool IsNull(object value)
+ internal static bool IsNull(object value)
{
if ((null == value) || (DBNull.Value == value))
{
@@ -1023,7 +1023,7 @@ namespace System.Data.Common
return ((null != nullable) && nullable.IsNull);
}
- static internal void IsNullOrSqlType(object value, out bool isNull, out bool isSqlType)
+ internal static void IsNullOrSqlType(object value, out bool isNull, out bool isSqlType)
{
if ((value == null) || (value == DBNull.Value))
{
@@ -1065,7 +1065,7 @@ namespace System.Data.Common
private static Version s_systemDataVersion;
- static internal Version GetAssemblyVersion()
+ internal static Version GetAssemblyVersion()
{
// NOTE: Using lazy thread-safety since we don't care if two threads both happen to update the value at the same time
if (s_systemDataVersion == null)
@@ -1077,13 +1077,13 @@ namespace System.Data.Common
}
- static internal readonly string[] AzureSqlServerEndpoints = {Res.GetString(Res.AZURESQL_GenericEndpoint),
+ internal static readonly string[] AzureSqlServerEndpoints = {Res.GetString(Res.AZURESQL_GenericEndpoint),
Res.GetString(Res.AZURESQL_GermanEndpoint),
Res.GetString(Res.AZURESQL_UsGovEndpoint),
Res.GetString(Res.AZURESQL_ChinaEndpoint)};
// This method assumes dataSource parameter is in TCP connection string format.
- static internal bool IsAzureSqlServerEndpoint(string dataSource)
+ internal static bool IsAzureSqlServerEndpoint(string dataSource)
{
// remove server port
int i = dataSource.LastIndexOf(',');
diff --git a/src/System.Data.SqlClient/src/System/Data/Common/DbConnectionOptions.cs b/src/System.Data.SqlClient/src/System/Data/Common/DbConnectionOptions.cs
index 40becfe473..a18d22542e 100644
--- a/src/System.Data.SqlClient/src/System/Data/Common/DbConnectionOptions.cs
+++ b/src/System.Data.SqlClient/src/System/Data/Common/DbConnectionOptions.cs
@@ -226,7 +226,7 @@ namespace System.Data.Common
return _parsetable.TryGetValue(keyName, out value) && value != null ? value : defaultValue;
}
- static private bool CompareInsensitiveInvariant(string strvalue, string strconst)
+ private static bool CompareInsensitiveInvariant(string strvalue, string strconst)
{
return (0 == StringComparer.OrdinalIgnoreCase.Compare(strvalue, strconst));
}
@@ -244,7 +244,7 @@ namespace System.Data.Common
}
#endif
- static private string GetKeyName(StringBuilder buffer)
+ private static string GetKeyName(StringBuilder buffer)
{
int count = buffer.Length;
while ((0 < count) && Char.IsWhiteSpace(buffer[count - 1]))
@@ -254,7 +254,7 @@ namespace System.Data.Common
return buffer.ToString(0, count).ToLowerInvariant();
}
- static private string GetKeyValue(StringBuilder buffer, bool trimWhitespace)
+ private static string GetKeyValue(StringBuilder buffer, bool trimWhitespace)
{
int count = buffer.Length;
int index = 0;
@@ -290,7 +290,7 @@ namespace System.Data.Common
NullTermination,
};
- static internal int GetKeyValuePair(string connectionString, int currentPosition, StringBuilder buffer, out string keyname, out string keyvalue)
+ internal static int GetKeyValuePair(string connectionString, int currentPosition, StringBuilder buffer, out string keyname, out string keyvalue)
{
int startposition = currentPosition;
@@ -458,7 +458,7 @@ namespace System.Data.Common
return currentPosition;
}
- static private bool IsValueValidInternal(string keyvalue)
+ private static bool IsValueValidInternal(string keyvalue)
{
if (null != keyvalue)
{
@@ -471,7 +471,7 @@ namespace System.Data.Common
return true;
}
- static private bool IsKeyNameValid(string keyname)
+ private static bool IsKeyNameValid(string keyname)
{
if (null != keyname)
{
diff --git a/src/System.Data.SqlClient/src/System/Data/DataException.cs b/src/System.Data.SqlClient/src/System/Data/DataException.cs
index 5584381e70..76e9b82bfe 100644
--- a/src/System.Data.SqlClient/src/System/Data/DataException.cs
+++ b/src/System.Data.SqlClient/src/System/Data/DataException.cs
@@ -29,20 +29,20 @@ namespace System.Data
// The resource Data.txt will ensure proper string text based on the appropriate
// locale.
- static internal void TraceExceptionAsReturnValue(Exception e)
+ internal static void TraceExceptionAsReturnValue(Exception e)
{
}
//
// COM+ exceptions
//
- static internal ArgumentException _Argument(string error)
+ internal static ArgumentException _Argument(string error)
{
ArgumentException e = new ArgumentException(error);
ExceptionBuilder.TraceExceptionAsReturnValue(e);
return e;
}
- static public Exception InvalidOffsetLength()
+ public static Exception InvalidOffsetLength()
{
return _Argument(Res.GetString(Res.Data_InvalidOffsetLength));
}
diff --git a/src/System.Data.SqlClient/src/System/Data/OperationAbortedException.cs b/src/System.Data.SqlClient/src/System/Data/OperationAbortedException.cs
index afe6ba3cb0..7cb8448a53 100644
--- a/src/System.Data.SqlClient/src/System/Data/OperationAbortedException.cs
+++ b/src/System.Data.SqlClient/src/System/Data/OperationAbortedException.cs
@@ -23,7 +23,7 @@ namespace System.Data
{
}
- static internal OperationAbortedException Aborted(Exception inner)
+ internal static OperationAbortedException Aborted(Exception inner)
{
OperationAbortedException e;
if (inner == null)
diff --git a/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs b/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs
index 5ccd706cdd..ddb76a8732 100644
--- a/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs
+++ b/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs
@@ -12,7 +12,7 @@ namespace System.Data.ProviderBase
{
partial class DbConnectionPoolIdentity
{
- static internal DbConnectionPoolIdentity GetCurrent()
+ internal static DbConnectionPoolIdentity GetCurrent()
{
throw new PlatformNotSupportedException();
}
diff --git a/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs b/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs
index a114a58982..42040d5c5e 100644
--- a/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs
+++ b/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs
@@ -12,9 +12,9 @@ namespace System.Data.ProviderBase
{
partial class DbConnectionPoolIdentity
{
- static private DbConnectionPoolIdentity s_lastIdentity = null;
+ private static DbConnectionPoolIdentity s_lastIdentity = null;
- static internal DbConnectionPoolIdentity GetCurrent()
+ internal static DbConnectionPoolIdentity GetCurrent()
{
DbConnectionPoolIdentity current;
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
diff --git a/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.cs b/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.cs
index 4e521c1968..1134619a88 100644
--- a/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.cs
+++ b/src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolIdentity.cs
@@ -13,7 +13,7 @@ namespace System.Data.ProviderBase
[Serializable]
sealed internal partial class DbConnectionPoolIdentity
{
- static public readonly DbConnectionPoolIdentity NoIdentity = new DbConnectionPoolIdentity(String.Empty, false, true);
+ public static readonly DbConnectionPoolIdentity NoIdentity = new DbConnectionPoolIdentity(String.Empty, false, true);
private readonly string _sidString;
private readonly bool _isRestricted;
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCachedBuffer.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCachedBuffer.cs
index 05033d2fa6..213a19a6d3 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCachedBuffer.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCachedBuffer.cs
@@ -40,7 +40,7 @@ namespace System.Data.SqlClient
}
// Reads off from the network buffer and caches bytes. Only reads one column value in the current row.
- static internal bool TryCreate(SqlMetaDataPriv metadata, TdsParser parser, TdsParserStateObject stateObj, out SqlCachedBuffer buffer)
+ internal static bool TryCreate(SqlMetaDataPriv metadata, TdsParser parser, TdsParserStateObject stateObj, out SqlCachedBuffer buffer)
{
int cb = 0;
ulong plplength;
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs
index c0cc1b5dec..3e3eecea6f 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs
@@ -23,7 +23,7 @@ namespace System.Data.SqlClient
private UpdateRowSource _updatedRowSource = UpdateRowSource.Both;
private bool _designTimeInvisible;
- private readonly static DiagnosticListener _diagnosticListener = new DiagnosticListener(SqlClientDiagnosticListenerExtensions.DiagnosticListenerName);
+ private static readonly DiagnosticListener _diagnosticListener = new DiagnosticListener(SqlClientDiagnosticListenerExtensions.DiagnosticListenerName);
private bool _parentOperationStarted = false;
// Prepare
@@ -67,7 +67,7 @@ namespace System.Data.SqlClient
private TaskCompletionSource<object> _reconnectionCompletionSource = null;
#if DEBUG
- static internal int DebugForceAsyncWriteDelay { get; set; }
+ internal static int DebugForceAsyncWriteDelay { get; set; }
#endif
internal bool InPrepare
{
@@ -1792,7 +1792,7 @@ namespace System.Data.SqlClient
}
// Yukon- column ordinals (this array indexed by ProcParamsColIndex
- static readonly internal string[] PreKatmaiProcParamsNames = new string[] {
+ internal static readonly string[] PreKatmaiProcParamsNames = new string[] {
"PARAMETER_NAME", // ParameterName,
"PARAMETER_TYPE", // ParameterType,
"DATA_TYPE", // DataType
@@ -1811,7 +1811,7 @@ namespace System.Data.SqlClient
};
// Katmai+ column ordinals (this array indexed by ProcParamsColIndex
- static readonly internal string[] KatmaiProcParamsNames = new string[] {
+ internal static readonly string[] KatmaiProcParamsNames = new string[] {
"PARAMETER_NAME", // ParameterName,
"PARAMETER_TYPE", // ParameterType,
null, // DataType, removed from Katmai+
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnection.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnection.cs
index 41e29f5c51..d60d326522 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnection.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnection.cs
@@ -41,7 +41,7 @@ namespace System.Data.SqlClient
private int _reconnectCount;
// diagnostics listener
- private readonly static DiagnosticListener s_diagnosticListener = new DiagnosticListener(SqlClientDiagnosticListenerExtensions.DiagnosticListenerName);
+ private static readonly DiagnosticListener s_diagnosticListener = new DiagnosticListener(SqlClientDiagnosticListenerExtensions.DiagnosticListenerName);
// Transient Fault handling flag. This is needed to convey to the downstream mechanism of connection establishment, if Transient Fault handling should be used or not
// The downstream handling of Connection open is the same for idle connection resiliency. Currently we want to apply transient fault handling only to the connections opened
@@ -433,12 +433,12 @@ namespace System.Data.SqlClient
}
}
- static public void ClearAllPools()
+ public static void ClearAllPools()
{
SqlConnectionFactory.SingletonInstance.ClearAllPools();
}
- static public void ClearPool(SqlConnection connection)
+ public static void ClearPool(SqlConnection connection)
{
ADP.CheckArgumentNull(connection, nameof(connection));
@@ -1102,7 +1102,7 @@ namespace System.Data.SqlClient
// Surround name in brackets and then escape any end bracket to protect against SQL Injection.
// NOTE: if the user escapes it themselves it will not work, but this was the case in V1 as well
// as native OleDb and Odbc.
- static internal string FixupDatabaseTransactionName(string name)
+ internal static string FixupDatabaseTransactionName(string name)
{
if (!string.IsNullOrEmpty(name))
{
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnectionString.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnectionString.cs
index bf2c9523c1..9485c713ae 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnectionString.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlConnectionString.cs
@@ -153,7 +153,7 @@ namespace System.Data.SqlClient
}
- static private Dictionary<string, string> s_sqlClientSynonyms;
+ private static Dictionary<string, string> s_sqlClientSynonyms;
private readonly bool _integratedSecurity;
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs
index 0275fe4327..2131a21ba2 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs
@@ -70,7 +70,7 @@ namespace System.Data.SqlClient
private CommandBehavior _commandBehavior;
private static int s_objectTypeCount; // Bid counter
- private readonly static ReadOnlyCollection<DbColumn> s_emptySchema = new ReadOnlyCollection<DbColumn>(Array.Empty<DbColumn>());
+ private static readonly ReadOnlyCollection<DbColumn> s_emptySchema = new ReadOnlyCollection<DbColumn>(Array.Empty<DbColumn>());
internal readonly int ObjectID = System.Threading.Interlocked.Increment(ref s_objectTypeCount);
// metadata (no explicit table, use 'Table')
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlEnums.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlEnums.cs
index fea5b9b4b4..aa4374c7f3 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlEnums.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlEnums.cs
@@ -290,7 +290,7 @@ namespace System.Data.SqlClient
//
// map COM+ Type to MetaType class
//
- static internal MetaType GetMetaTypeFromType(Type dataType, bool streamAllowed = true)
+ internal static MetaType GetMetaTypeFromType(Type dataType, bool streamAllowed = true)
{
if (dataType == typeof(System.Byte[]))
return MetaVarBinary;
@@ -372,7 +372,7 @@ namespace System.Data.SqlClient
throw ADP.UnknownDataType(dataType);
}
- static internal MetaType GetMetaTypeFromValue(object value, bool inferLen = true, bool streamAllowed = true)
+ internal static MetaType GetMetaTypeFromValue(object value, bool inferLen = true, bool streamAllowed = true)
{
if (value == null)
{
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlException.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlException.cs
index c303b54612..df453fe2a4 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlException.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlException.cs
@@ -139,12 +139,12 @@ namespace System.Data.SqlClient
return sb.ToString();
}
- static internal SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion)
+ internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion)
{
return CreateException(errorCollection, serverVersion, Guid.Empty);
}
- static internal SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, SqlInternalConnectionTds internalConnection, Exception innerException = null)
+ internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, SqlInternalConnectionTds internalConnection, Exception innerException = null)
{
Guid connectionId = (internalConnection == null) ? Guid.Empty : internalConnection._clientConnectionId;
var exception = CreateException(errorCollection, serverVersion, connectionId, innerException);
@@ -165,7 +165,7 @@ namespace System.Data.SqlClient
return exception;
}
- static internal SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, Guid conId, Exception innerException = null)
+ internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, Guid conId, Exception innerException = null)
{
Debug.Assert(null != errorCollection && errorCollection.Count > 0, "no errorCollection?");
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlStatistics.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlStatistics.cs
index a993ceccda..b1ac40d50a 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlStatistics.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlStatistics.cs
@@ -15,7 +15,7 @@ namespace System.Data.SqlClient
{
internal sealed class SqlStatistics
{
- static internal SqlStatistics StartTimer(SqlStatistics statistics)
+ internal static SqlStatistics StartTimer(SqlStatistics statistics)
{
if ((null != statistics) && !statistics.RequestExecutionTimer())
{
@@ -25,7 +25,7 @@ namespace System.Data.SqlClient
return statistics;
}
- static internal void StopTimer(SqlStatistics statistics)
+ internal static void StopTimer(SqlStatistics statistics)
{
if (null != statistics)
{
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlUtil.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlUtil.cs
index 9c24b23902..7774995a45 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlUtil.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlUtil.cs
@@ -19,7 +19,7 @@ namespace System.Data.SqlClient
{
using Res = System.SR;
- static internal class AsyncHelper
+ internal static class AsyncHelper
{
internal static Task CreateContinuationTask(Task task, Action onSuccess, SqlInternalConnectionTds connectionToDoom = null, Action<Exception> onFailure = null)
{
@@ -145,7 +145,7 @@ namespace System.Data.SqlClient
}
- static internal class SQL
+ internal static class SQL
{
// The class SQL defines the exceptions that are specific to the SQL Adapter.
// The class contains functions that take the proper informational variables and then construct
@@ -164,60 +164,60 @@ namespace System.Data.SqlClient
// SQL.Connection
//
- static internal Exception InvalidInternalPacketSize(string str)
+ internal static Exception InvalidInternalPacketSize(string str)
{
return ADP.ArgumentOutOfRange(str);
}
- static internal Exception InvalidPacketSize()
+ internal static Exception InvalidPacketSize()
{
return ADP.ArgumentOutOfRange(Res.GetString(Res.SQL_InvalidTDSPacketSize));
}
- static internal Exception InvalidPacketSizeValue()
+ internal static Exception InvalidPacketSizeValue()
{
return ADP.Argument(Res.GetString(Res.SQL_InvalidPacketSizeValue));
}
- static internal Exception InvalidSSPIPacketSize()
+ internal static Exception InvalidSSPIPacketSize()
{
return ADP.Argument(Res.GetString(Res.SQL_InvalidSSPIPacketSize));
}
- static internal Exception NullEmptyTransactionName()
+ internal static Exception NullEmptyTransactionName()
{
return ADP.Argument(Res.GetString(Res.SQL_NullEmptyTransactionName));
}
- static internal Exception UserInstanceFailoverNotCompatible()
+ internal static Exception UserInstanceFailoverNotCompatible()
{
return ADP.Argument(Res.GetString(Res.SQL_UserInstanceFailoverNotCompatible));
}
- static internal Exception InvalidSQLServerVersionUnknown()
+ internal static Exception InvalidSQLServerVersionUnknown()
{
return ADP.DataAdapter(Res.GetString(Res.SQL_InvalidSQLServerVersionUnknown));
}
- static internal Exception SynchronousCallMayNotPend()
+ internal static Exception SynchronousCallMayNotPend()
{
return new Exception(Res.GetString(Res.Sql_InternalError));
}
- static internal Exception ConnectionLockedForBcpEvent()
+ internal static Exception ConnectionLockedForBcpEvent()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_ConnectionLockedForBcpEvent));
}
- static internal Exception InstanceFailure()
+ internal static Exception InstanceFailure()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_InstanceFailure));
}
- static internal Exception InvalidPartnerConfiguration(string server, string database)
+ internal static Exception InvalidPartnerConfiguration(string server, string database)
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_InvalidPartnerConfiguration, server, database));
}
- static internal Exception MARSUnspportedOnConnection()
+ internal static Exception MARSUnspportedOnConnection()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_MarsUnsupportedOnConnection));
}
- static internal Exception CannotModifyPropertyAsyncOperationInProgress([CallerMemberName] string property = "")
+ internal static Exception CannotModifyPropertyAsyncOperationInProgress([CallerMemberName] string property = "")
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_CannotModifyPropertyAsyncOperationInProgress, property));
}
- static internal Exception NonLocalSSEInstance()
+ internal static Exception NonLocalSSEInstance()
{
return ADP.NotSupported(Res.GetString(Res.SQL_NonLocalSSEInstance));
}
@@ -225,12 +225,12 @@ namespace System.Data.SqlClient
// SQL.DataCommand
//
- static internal ArgumentOutOfRangeException NotSupportedEnumerationValue(Type type, int value)
+ internal static ArgumentOutOfRangeException NotSupportedEnumerationValue(Type type, int value)
{
return ADP.ArgumentOutOfRange(Res.GetString(Res.SQL_NotSupportedEnumerationValue, type.Name, value.ToString(System.Globalization.CultureInfo.InvariantCulture)), type.Name);
}
- static internal ArgumentOutOfRangeException NotSupportedCommandType(CommandType value)
+ internal static ArgumentOutOfRangeException NotSupportedCommandType(CommandType value)
{
#if DEBUG
switch (value)
@@ -248,7 +248,7 @@ namespace System.Data.SqlClient
#endif
return NotSupportedEnumerationValue(typeof(CommandType), (int)value);
}
- static internal ArgumentOutOfRangeException NotSupportedIsolationLevel(IsolationLevel value)
+ internal static ArgumentOutOfRangeException NotSupportedIsolationLevel(IsolationLevel value)
{
#if DEBUG
switch (value)
@@ -271,19 +271,19 @@ namespace System.Data.SqlClient
return NotSupportedEnumerationValue(typeof(IsolationLevel), (int)value);
}
- static internal Exception OperationCancelled()
+ internal static Exception OperationCancelled()
{
Exception exception = ADP.InvalidOperation(Res.GetString(Res.SQL_OperationCancelled));
return exception;
}
- static internal Exception PendingBeginXXXExists()
+ internal static Exception PendingBeginXXXExists()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_PendingBeginXXXExists));
}
- static internal Exception NonXmlResult()
+ internal static Exception NonXmlResult()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_NonXmlResult));
}
@@ -291,57 +291,57 @@ namespace System.Data.SqlClient
//
// SQL.DataParameter
//
- static internal Exception InvalidParameterTypeNameFormat()
+ internal static Exception InvalidParameterTypeNameFormat()
{
return ADP.Argument(Res.GetString(Res.SQL_InvalidParameterTypeNameFormat));
}
- static internal Exception InvalidParameterNameLength(string value)
+ internal static Exception InvalidParameterNameLength(string value)
{
return ADP.Argument(Res.GetString(Res.SQL_InvalidParameterNameLength, value));
}
- static internal Exception PrecisionValueOutOfRange(byte precision)
+ internal static Exception PrecisionValueOutOfRange(byte precision)
{
return ADP.Argument(Res.GetString(Res.SQL_PrecisionValueOutOfRange, precision.ToString(CultureInfo.InvariantCulture)));
}
- static internal Exception ScaleValueOutOfRange(byte scale)
+ internal static Exception ScaleValueOutOfRange(byte scale)
{
return ADP.Argument(Res.GetString(Res.SQL_ScaleValueOutOfRange, scale.ToString(CultureInfo.InvariantCulture)));
}
- static internal Exception TimeScaleValueOutOfRange(byte scale)
+ internal static Exception TimeScaleValueOutOfRange(byte scale)
{
return ADP.Argument(Res.GetString(Res.SQL_TimeScaleValueOutOfRange, scale.ToString(CultureInfo.InvariantCulture)));
}
- static internal Exception InvalidSqlDbType(SqlDbType value)
+ internal static Exception InvalidSqlDbType(SqlDbType value)
{
return ADP.InvalidEnumerationValue(typeof(SqlDbType), (int)value);
}
- static internal Exception UnsupportedTVPOutputParameter(ParameterDirection direction, string paramName)
+ internal static Exception UnsupportedTVPOutputParameter(ParameterDirection direction, string paramName)
{
return ADP.NotSupported(Res.GetString(Res.SqlParameter_UnsupportedTVPOutputParameter,
direction.ToString(), paramName));
}
- static internal Exception DBNullNotSupportedForTVPValues(string paramName)
+ internal static Exception DBNullNotSupportedForTVPValues(string paramName)
{
return ADP.NotSupported(Res.GetString(Res.SqlParameter_DBNullNotSupportedForTVP, paramName));
}
- static internal Exception UnexpectedTypeNameForNonStructParams(string paramName)
+ internal static Exception UnexpectedTypeNameForNonStructParams(string paramName)
{
return ADP.NotSupported(Res.GetString(Res.SqlParameter_UnexpectedTypeNameForNonStruct, paramName));
}
- static internal Exception ParameterInvalidVariant(string paramName)
+ internal static Exception ParameterInvalidVariant(string paramName)
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_ParameterInvalidVariant, paramName));
}
- static internal Exception MustSetTypeNameForParam(string paramType, string paramName)
+ internal static Exception MustSetTypeNameForParam(string paramType, string paramName)
{
return ADP.Argument(Res.GetString(Res.SQL_ParameterTypeNameRequired, paramType, paramName));
}
- static internal Exception EnumeratedRecordMetaDataChanged(string fieldName, int recordNumber)
+ internal static Exception EnumeratedRecordMetaDataChanged(string fieldName, int recordNumber)
{
return ADP.Argument(Res.GetString(Res.SQL_EnumeratedRecordMetaDataChanged, fieldName, recordNumber));
}
- static internal Exception EnumeratedRecordFieldCountChanged(int recordNumber)
+ internal static Exception EnumeratedRecordFieldCountChanged(int recordNumber)
{
return ADP.Argument(Res.GetString(Res.SQL_EnumeratedRecordFieldCountChanged, recordNumber));
}
@@ -353,27 +353,27 @@ namespace System.Data.SqlClient
//
// SQL.TDSParser
//
- static internal Exception InvalidTDSVersion()
+ internal static Exception InvalidTDSVersion()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_InvalidTDSVersion));
}
- static internal Exception ParsingError()
+ internal static Exception ParsingError()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_ParsingError));
}
- static internal Exception MoneyOverflow(string moneyValue)
+ internal static Exception MoneyOverflow(string moneyValue)
{
return ADP.Overflow(Res.GetString(Res.SQL_MoneyOverflow, moneyValue));
}
- static internal Exception SmallDateTimeOverflow(string datetime)
+ internal static Exception SmallDateTimeOverflow(string datetime)
{
return ADP.Overflow(Res.GetString(Res.SQL_SmallDateTimeOverflow, datetime));
}
- static internal Exception SNIPacketAllocationFailure()
+ internal static Exception SNIPacketAllocationFailure()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_SNIPacketAllocationFailure));
}
- static internal Exception TimeOverflow(string time)
+ internal static Exception TimeOverflow(string time)
{
return ADP.Overflow(Res.GetString(Res.SQL_TimeOverflow, time));
}
@@ -381,78 +381,78 @@ namespace System.Data.SqlClient
//
// SQL.SqlDataReader
//
- static internal Exception InvalidRead()
+ internal static Exception InvalidRead()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_InvalidRead));
}
- static internal Exception NonBlobColumn(string columnName)
+ internal static Exception NonBlobColumn(string columnName)
{
return ADP.InvalidCast(Res.GetString(Res.SQL_NonBlobColumn, columnName));
}
- static internal Exception NonCharColumn(string columnName)
+ internal static Exception NonCharColumn(string columnName)
{
return ADP.InvalidCast(Res.GetString(Res.SQL_NonCharColumn, columnName));
}
- static internal Exception StreamNotSupportOnColumnType(string columnName)
+ internal static Exception StreamNotSupportOnColumnType(string columnName)
{
return ADP.InvalidCast(Res.GetString(Res.SQL_StreamNotSupportOnColumnType, columnName));
}
- static internal Exception TextReaderNotSupportOnColumnType(string columnName)
+ internal static Exception TextReaderNotSupportOnColumnType(string columnName)
{
return ADP.InvalidCast(Res.GetString(Res.SQL_TextReaderNotSupportOnColumnType, columnName));
}
- static internal Exception XmlReaderNotSupportOnColumnType(string columnName)
+ internal static Exception XmlReaderNotSupportOnColumnType(string columnName)
{
return ADP.InvalidCast(Res.GetString(Res.SQL_XmlReaderNotSupportOnColumnType, columnName));
}
- static internal Exception InvalidSqlDbTypeForConstructor(SqlDbType type)
+ internal static Exception InvalidSqlDbTypeForConstructor(SqlDbType type)
{
return ADP.Argument(Res.GetString(Res.SqlMetaData_InvalidSqlDbTypeForConstructorFormat, type.ToString()));
}
- static internal Exception NameTooLong(string parameterName)
+ internal static Exception NameTooLong(string parameterName)
{
return ADP.Argument(Res.GetString(Res.SqlMetaData_NameTooLong), parameterName);
}
- static internal Exception InvalidSortOrder(SortOrder order)
+ internal static Exception InvalidSortOrder(SortOrder order)
{
return ADP.InvalidEnumerationValue(typeof(SortOrder), (int)order);
}
- static internal Exception MustSpecifyBothSortOrderAndOrdinal(SortOrder order, int ordinal)
+ internal static Exception MustSpecifyBothSortOrderAndOrdinal(SortOrder order, int ordinal)
{
return ADP.InvalidOperation(Res.GetString(Res.SqlMetaData_SpecifyBothSortOrderAndOrdinal, order.ToString(), ordinal));
}
- static internal Exception UnsupportedColumnTypeForSqlProvider(string columnName, string typeName)
+ internal static Exception UnsupportedColumnTypeForSqlProvider(string columnName, string typeName)
{
return ADP.Argument(Res.GetString(Res.SqlProvider_InvalidDataColumnType, columnName, typeName));
}
- static internal Exception NotEnoughColumnsInStructuredType()
+ internal static Exception NotEnoughColumnsInStructuredType()
{
return ADP.Argument(Res.GetString(Res.SqlProvider_NotEnoughColumnsInStructuredType));
}
- static internal Exception DuplicateSortOrdinal(int sortOrdinal)
+ internal static Exception DuplicateSortOrdinal(int sortOrdinal)
{
return ADP.InvalidOperation(Res.GetString(Res.SqlProvider_DuplicateSortOrdinal, sortOrdinal));
}
- static internal Exception MissingSortOrdinal(int sortOrdinal)
+ internal static Exception MissingSortOrdinal(int sortOrdinal)
{
return ADP.InvalidOperation(Res.GetString(Res.SqlProvider_MissingSortOrdinal, sortOrdinal));
}
- static internal Exception SortOrdinalGreaterThanFieldCount(int columnOrdinal, int sortOrdinal)
+ internal static Exception SortOrdinalGreaterThanFieldCount(int columnOrdinal, int sortOrdinal)
{
return ADP.InvalidOperation(Res.GetString(Res.SqlProvider_SortOrdinalGreaterThanFieldCount, sortOrdinal, columnOrdinal));
}
- static internal Exception IEnumerableOfSqlDataRecordHasNoRows()
+ internal static Exception IEnumerableOfSqlDataRecordHasNoRows()
{
return ADP.Argument(Res.GetString(Res.IEnumerableOfSqlDataRecordHasNoRows));
}
@@ -463,75 +463,75 @@ namespace System.Data.SqlClient
//
// SQL.BulkLoad
//
- static internal Exception BulkLoadMappingInaccessible()
+ internal static Exception BulkLoadMappingInaccessible()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadMappingInaccessible));
}
- static internal Exception BulkLoadMappingsNamesOrOrdinalsOnly()
+ internal static Exception BulkLoadMappingsNamesOrOrdinalsOnly()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadMappingsNamesOrOrdinalsOnly));
}
- static internal Exception BulkLoadCannotConvertValue(Type sourcetype, MetaType metatype, Exception e)
+ internal static Exception BulkLoadCannotConvertValue(Type sourcetype, MetaType metatype, Exception e)
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadCannotConvertValue, sourcetype.Name, metatype.TypeName), e);
}
- static internal Exception BulkLoadNonMatchingColumnMapping()
+ internal static Exception BulkLoadNonMatchingColumnMapping()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadNonMatchingColumnMapping));
}
- static internal Exception BulkLoadNonMatchingColumnName(string columnName)
+ internal static Exception BulkLoadNonMatchingColumnName(string columnName)
{
return BulkLoadNonMatchingColumnName(columnName, null);
}
- static internal Exception BulkLoadNonMatchingColumnName(string columnName, Exception e)
+ internal static Exception BulkLoadNonMatchingColumnName(string columnName, Exception e)
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadNonMatchingColumnName, columnName), e);
}
- static internal Exception BulkLoadStringTooLong()
+ internal static Exception BulkLoadStringTooLong()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadStringTooLong));
}
- static internal Exception BulkLoadInvalidVariantValue()
+ internal static Exception BulkLoadInvalidVariantValue()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadInvalidVariantValue));
}
- static internal Exception BulkLoadInvalidTimeout(int timeout)
+ internal static Exception BulkLoadInvalidTimeout(int timeout)
{
return ADP.Argument(Res.GetString(Res.SQL_BulkLoadInvalidTimeout, timeout.ToString(CultureInfo.InvariantCulture)));
}
- static internal Exception BulkLoadExistingTransaction()
+ internal static Exception BulkLoadExistingTransaction()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadExistingTransaction));
}
- static internal Exception BulkLoadNoCollation()
+ internal static Exception BulkLoadNoCollation()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadNoCollation));
}
- static internal Exception BulkLoadConflictingTransactionOption()
+ internal static Exception BulkLoadConflictingTransactionOption()
{
return ADP.Argument(Res.GetString(Res.SQL_BulkLoadConflictingTransactionOption));
}
- static internal Exception BulkLoadLcidMismatch(int sourceLcid, string sourceColumnName, int destinationLcid, string destinationColumnName)
+ internal static Exception BulkLoadLcidMismatch(int sourceLcid, string sourceColumnName, int destinationLcid, string destinationColumnName)
{
return ADP.InvalidOperation(Res.GetString(Res.Sql_BulkLoadLcidMismatch, sourceLcid, sourceColumnName, destinationLcid, destinationColumnName));
}
- static internal Exception InvalidOperationInsideEvent()
+ internal static Exception InvalidOperationInsideEvent()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadInvalidOperationInsideEvent));
}
- static internal Exception BulkLoadMissingDestinationTable()
+ internal static Exception BulkLoadMissingDestinationTable()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadMissingDestinationTable));
}
- static internal Exception BulkLoadInvalidDestinationTable(string tableName, Exception inner)
+ internal static Exception BulkLoadInvalidDestinationTable(string tableName, Exception inner)
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadInvalidDestinationTable, tableName), inner);
}
- static internal Exception BulkLoadBulkLoadNotAllowDBNull(string columnName)
+ internal static Exception BulkLoadBulkLoadNotAllowDBNull(string columnName)
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadNotAllowDBNull, columnName));
}
- static internal Exception BulkLoadPendingOperation()
+ internal static Exception BulkLoadPendingOperation()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_BulkLoadPendingOperation));
}
@@ -539,17 +539,17 @@ namespace System.Data.SqlClient
//
// transactions.
//
- static internal Exception ConnectionDoomed()
+ internal static Exception ConnectionDoomed()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_ConnectionDoomed));
}
- static internal Exception OpenResultCountExceeded()
+ internal static Exception OpenResultCountExceeded()
{
return ADP.InvalidOperation(Res.GetString(Res.SQL_OpenResultCountExceeded));
}
- static internal readonly byte[] AttentionHeader = new byte[] {
+ internal static readonly byte[] AttentionHeader = new byte[] {
TdsEnums.MT_ATTN, // Message Type
TdsEnums.ST_EOM, // Status
TdsEnums.HEADER_LEN >> 8, // length - upper byte
@@ -569,7 +569,7 @@ namespace System.Data.SqlClient
/// * server-provided failover partner - raising SqlException in this case
/// * connection string with failover partner and MultiSubnetFailover=true - raising argument one in this case with the same message
/// </summary>
- static internal Exception MultiSubnetFailoverWithFailoverPartner(bool serverProvidedFailoverPartner, SqlInternalConnectionTds internalConnection)
+ internal static Exception MultiSubnetFailoverWithFailoverPartner(bool serverProvidedFailoverPartner, SqlInternalConnectionTds internalConnection)
{
string msg = Res.GetString(Res.SQLMSF_FailoverPartnerNotSupported);
if (serverProvidedFailoverPartner)
@@ -587,19 +587,19 @@ namespace System.Data.SqlClient
}
}
- static internal Exception MultiSubnetFailoverWithMoreThan64IPs()
+ internal static Exception MultiSubnetFailoverWithMoreThan64IPs()
{
string msg = GetSNIErrorMessage((int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithMoreThan64IPs);
return ADP.InvalidOperation(msg);
}
- static internal Exception MultiSubnetFailoverWithInstanceSpecified()
+ internal static Exception MultiSubnetFailoverWithInstanceSpecified()
{
string msg = GetSNIErrorMessage((int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithInstanceSpecified);
return ADP.Argument(msg);
}
- static internal Exception MultiSubnetFailoverWithNonTcpProtocol()
+ internal static Exception MultiSubnetFailoverWithNonTcpProtocol()
{
string msg = GetSNIErrorMessage((int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithNonTcpProtocol);
return ADP.Argument(msg);
@@ -609,12 +609,12 @@ namespace System.Data.SqlClient
// Read-only routing
//
- static internal Exception ROR_FailoverNotSupportedConnString()
+ internal static Exception ROR_FailoverNotSupportedConnString()
{
return ADP.Argument(Res.GetString(Res.SQLROR_FailoverNotSupported));
}
- static internal Exception ROR_FailoverNotSupportedServer(SqlInternalConnectionTds internalConnection)
+ internal static Exception ROR_FailoverNotSupportedServer(SqlInternalConnectionTds internalConnection)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (Res.GetString(Res.SQLROR_FailoverNotSupported)), "", 0));
@@ -623,7 +623,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal Exception ROR_RecursiveRoutingNotSupported(SqlInternalConnectionTds internalConnection)
+ internal static Exception ROR_RecursiveRoutingNotSupported(SqlInternalConnectionTds internalConnection)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (Res.GetString(Res.SQLROR_RecursiveRoutingNotSupported)), "", 0));
@@ -632,7 +632,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal Exception ROR_UnexpectedRoutingInfo(SqlInternalConnectionTds internalConnection)
+ internal static Exception ROR_UnexpectedRoutingInfo(SqlInternalConnectionTds internalConnection)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (Res.GetString(Res.SQLROR_UnexpectedRoutingInfo)), "", 0));
@@ -641,7 +641,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal Exception ROR_InvalidRoutingInfo(SqlInternalConnectionTds internalConnection)
+ internal static Exception ROR_InvalidRoutingInfo(SqlInternalConnectionTds internalConnection)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (Res.GetString(Res.SQLROR_InvalidRoutingInfo)), "", 0));
@@ -650,7 +650,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal Exception ROR_TimeoutAfterRoutingInfo(SqlInternalConnectionTds internalConnection)
+ internal static Exception ROR_TimeoutAfterRoutingInfo(SqlInternalConnectionTds internalConnection)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, null, (Res.GetString(Res.SQLROR_TimeoutAfterRoutingInfo)), "", 0));
@@ -662,7 +662,7 @@ namespace System.Data.SqlClient
//
// Connection resiliency
//
- static internal SqlException CR_ReconnectTimeout()
+ internal static SqlException CR_ReconnectTimeout()
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(TdsEnums.TIMEOUT_EXPIRED, (byte)0x00, TdsEnums.MIN_ERROR_CLASS, null, SQLMessage.Timeout(), "", 0, TdsEnums.SNI_WAIT_TIMEOUT));
@@ -670,7 +670,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal SqlException CR_ReconnectionCancelled()
+ internal static SqlException CR_ReconnectionCancelled()
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, null, SQLMessage.OperationCancelled(), "", 0));
@@ -678,7 +678,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal Exception CR_NextAttemptWillExceedQueryTimeout(SqlException innerException, Guid connectionId)
+ internal static Exception CR_NextAttemptWillExceedQueryTimeout(SqlException innerException, Guid connectionId)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, null, Res.GetString(Res.SQLCR_NextAttemptWillExceedQueryTimeout), "", 0));
@@ -686,7 +686,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal Exception CR_EncryptionChanged(SqlInternalConnectionTds internalConnection)
+ internal static Exception CR_EncryptionChanged(SqlInternalConnectionTds internalConnection)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, Res.GetString(Res.SQLCR_EncryptionChanged), "", 0));
@@ -694,7 +694,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal SqlException CR_AllAttemptsFailed(SqlException innerException, Guid connectionId)
+ internal static SqlException CR_AllAttemptsFailed(SqlException innerException, Guid connectionId)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, null, Res.GetString(Res.SQLCR_AllAttemptsFailed), "", 0));
@@ -702,7 +702,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal SqlException CR_NoCRAckAtReconnection(SqlInternalConnectionTds internalConnection)
+ internal static SqlException CR_NoCRAckAtReconnection(SqlInternalConnectionTds internalConnection)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, Res.GetString(Res.SQLCR_NoCRAckAtReconnection), "", 0));
@@ -710,7 +710,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal SqlException CR_TDSVersionNotPreserved(SqlInternalConnectionTds internalConnection)
+ internal static SqlException CR_TDSVersionNotPreserved(SqlInternalConnectionTds internalConnection)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, Res.GetString(Res.SQLCR_TDSVestionNotPreserved), "", 0));
@@ -718,7 +718,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal SqlException CR_UnrecoverableServer(Guid connectionId)
+ internal static SqlException CR_UnrecoverableServer(Guid connectionId)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, Res.GetString(Res.SQLCR_UnrecoverableServer), "", 0));
@@ -726,7 +726,7 @@ namespace System.Data.SqlClient
return exc;
}
- static internal SqlException CR_UnrecoverableClient(Guid connectionId)
+ internal static SqlException CR_UnrecoverableClient(Guid connectionId)
{
SqlErrorCollection errors = new SqlErrorCollection();
errors.Add(new SqlError(0, 0, TdsEnums.FATAL_ERROR_CLASS, null, Res.GetString(Res.SQLCR_UnrecoverableClient), "", 0));
@@ -734,38 +734,38 @@ namespace System.Data.SqlClient
return exc;
}
- static internal Exception StreamWriteNotSupported()
+ internal static Exception StreamWriteNotSupported()
{
return ADP.NotSupported(Res.GetString(Res.SQL_StreamWriteNotSupported));
}
- static internal Exception StreamReadNotSupported()
+ internal static Exception StreamReadNotSupported()
{
return ADP.NotSupported(Res.GetString(Res.SQL_StreamReadNotSupported));
}
- static internal Exception StreamSeekNotSupported()
+ internal static Exception StreamSeekNotSupported()
{
return ADP.NotSupported(Res.GetString(Res.SQL_StreamSeekNotSupported));
}
- static internal System.Data.SqlTypes.SqlNullValueException SqlNullValue()
+ internal static System.Data.SqlTypes.SqlNullValueException SqlNullValue()
{
System.Data.SqlTypes.SqlNullValueException e = new System.Data.SqlTypes.SqlNullValueException();
return e;
}
- static internal Exception SubclassMustOverride()
+ internal static Exception SubclassMustOverride()
{
return ADP.InvalidOperation(Res.GetString(Res.SqlMisc_SubclassMustOverride));
}
// ProjectK\CoreCLR specific errors
- static internal Exception UnsupportedKeyword(string keyword)
+ internal static Exception UnsupportedKeyword(string keyword)
{
return ADP.NotSupported(Res.GetString(Res.SQL_UnsupportedKeyword, keyword));
}
- static internal Exception NetworkLibraryKeywordNotSupported()
+ internal static Exception NetworkLibraryKeywordNotSupported()
{
return ADP.NotSupported(Res.GetString(Res.SQL_NetworkLibraryNotSupported));
}
- static internal Exception UnsupportedFeatureAndToken(SqlInternalConnectionTds internalConnection, string token)
+ internal static Exception UnsupportedFeatureAndToken(SqlInternalConnectionTds internalConnection, string token)
{
var innerException = ADP.NotSupported(Res.GetString(Res.SQL_UnsupportedToken, token));
@@ -778,7 +778,7 @@ namespace System.Data.SqlClient
/// <summary>
/// gets a message for SNI error (sniError must be valid, non-zero error code)
/// </summary>
- static internal string GetSNIErrorMessage(int sniError)
+ internal static string GetSNIErrorMessage(int sniError)
{
Debug.Assert(sniError > 0 && sniError <= (int)SNINativeMethodWrapper.SniSpecialErrors.MaxErrorValue, "SNI error is out of range");
@@ -800,115 +800,115 @@ namespace System.Data.SqlClient
// messages. The resource Framework.txt will ensure proper string text based on the appropriate
// locale.
- static internal string CultureIdError()
+ internal static string CultureIdError()
{
return Res.GetString(Res.SQL_CultureIdError);
}
- static internal string EncryptionNotSupportedByClient()
+ internal static string EncryptionNotSupportedByClient()
{
return Res.GetString(Res.SQL_EncryptionNotSupportedByClient);
}
- static internal string EncryptionNotSupportedByServer()
+ internal static string EncryptionNotSupportedByServer()
{
return Res.GetString(Res.SQL_EncryptionNotSupportedByServer);
}
- static internal string OperationCancelled()
+ internal static string OperationCancelled()
{
return Res.GetString(Res.SQL_OperationCancelled);
}
- static internal string SevereError()
+ internal static string SevereError()
{
return Res.GetString(Res.SQL_SevereError);
}
- static internal string SSPIInitializeError()
+ internal static string SSPIInitializeError()
{
return Res.GetString(Res.SQL_SSPIInitializeError);
}
- static internal string SSPIGenerateError()
+ internal static string SSPIGenerateError()
{
return Res.GetString(Res.SQL_SSPIGenerateError);
}
- static internal string Timeout()
+ internal static string Timeout()
{
return Res.GetString(Res.SQL_Timeout);
}
- static internal string Timeout_PreLogin_Begin()
+ internal static string Timeout_PreLogin_Begin()
{
return Res.GetString(Res.SQL_Timeout_PreLogin_Begin);
}
- static internal string Timeout_PreLogin_InitializeConnection()
+ internal static string Timeout_PreLogin_InitializeConnection()
{
return Res.GetString(Res.SQL_Timeout_PreLogin_InitializeConnection);
}
- static internal string Timeout_PreLogin_SendHandshake()
+ internal static string Timeout_PreLogin_SendHandshake()
{
return Res.GetString(Res.SQL_Timeout_PreLogin_SendHandshake);
}
- static internal string Timeout_PreLogin_ConsumeHandshake()
+ internal static string Timeout_PreLogin_ConsumeHandshake()
{
return Res.GetString(Res.SQL_Timeout_PreLogin_ConsumeHandshake);
}
- static internal string Timeout_Login_Begin()
+ internal static string Timeout_Login_Begin()
{
return Res.GetString(Res.SQL_Timeout_Login_Begin);
}
- static internal string Timeout_Login_ProcessConnectionAuth()
+ internal static string Timeout_Login_ProcessConnectionAuth()
{
return Res.GetString(Res.SQL_Timeout_Login_ProcessConnectionAuth);
}
- static internal string Timeout_PostLogin()
+ internal static string Timeout_PostLogin()
{
return Res.GetString(Res.SQL_Timeout_PostLogin);
}
- static internal string Timeout_FailoverInfo()
+ internal static string Timeout_FailoverInfo()
{
return Res.GetString(Res.SQL_Timeout_FailoverInfo);
}
- static internal string Timeout_RoutingDestination()
+ internal static string Timeout_RoutingDestination()
{
return Res.GetString(Res.SQL_Timeout_RoutingDestinationInfo);
}
- static internal string Duration_PreLogin_Begin(long PreLoginBeginDuration)
+ internal static string Duration_PreLogin_Begin(long PreLoginBeginDuration)
{
return Res.GetString(Res.SQL_Duration_PreLogin_Begin, PreLoginBeginDuration);
}
- static internal string Duration_PreLoginHandshake(long PreLoginBeginDuration, long PreLoginHandshakeDuration)
+ internal static string Duration_PreLoginHandshake(long PreLoginBeginDuration, long PreLoginHandshakeDuration)
{
return Res.GetString(Res.SQL_Duration_PreLoginHandshake, PreLoginBeginDuration, PreLoginHandshakeDuration);
}
- static internal string Duration_Login_Begin(long PreLoginBeginDuration, long PreLoginHandshakeDuration, long LoginBeginDuration)
+ internal static string Duration_Login_Begin(long PreLoginBeginDuration, long PreLoginHandshakeDuration, long LoginBeginDuration)
{
return Res.GetString(Res.SQL_Duration_Login_Begin, PreLoginBeginDuration, PreLoginHandshakeDuration, LoginBeginDuration);
}
- static internal string Duration_Login_ProcessConnectionAuth(long PreLoginBeginDuration, long PreLoginHandshakeDuration, long LoginBeginDuration, long LoginAuthDuration)
+ internal static string Duration_Login_ProcessConnectionAuth(long PreLoginBeginDuration, long PreLoginHandshakeDuration, long LoginBeginDuration, long LoginAuthDuration)
{
return Res.GetString(Res.SQL_Duration_Login_ProcessConnectionAuth, PreLoginBeginDuration, PreLoginHandshakeDuration, LoginBeginDuration, LoginAuthDuration);
}
- static internal string Duration_PostLogin(long PreLoginBeginDuration, long PreLoginHandshakeDuration, long LoginBeginDuration, long LoginAuthDuration, long PostLoginDuration)
+ internal static string Duration_PostLogin(long PreLoginBeginDuration, long PreLoginHandshakeDuration, long LoginBeginDuration, long LoginAuthDuration, long PostLoginDuration)
{
return Res.GetString(Res.SQL_Duration_PostLogin, PreLoginBeginDuration, PreLoginHandshakeDuration, LoginBeginDuration, LoginAuthDuration, PostLoginDuration);
}
- static internal string UserInstanceFailure()
+ internal static string UserInstanceFailure()
{
return Res.GetString(Res.SQL_UserInstanceFailure);
}
- static internal string PreloginError()
+ internal static string PreloginError()
{
return Res.GetString(Res.Snix_PreLogin);
}
- static internal string ExClientConnectionId()
+ internal static string ExClientConnectionId()
{
return Res.GetString(Res.SQL_ExClientConnectionId);
}
- static internal string ExErrorNumberStateClass()
+ internal static string ExErrorNumberStateClass()
{
return Res.GetString(Res.SQL_ExErrorNumberStateClass);
}
- static internal string ExOriginalClientConnectionId()
+ internal static string ExOriginalClientConnectionId()
{
return Res.GetString(Res.SQL_ExOriginalClientConnectionId);
}
- static internal string ExRoutingDestination()
+ internal static string ExRoutingDestination()
{
return Res.GetString(Res.SQL_ExRoutingDestination);
}
@@ -917,14 +917,14 @@ namespace System.Data.SqlClient
/// <summary>
/// This class holds helper methods to escape Microsoft SQL Server identifiers, such as table, schema, database or other names
/// </summary>
- static internal class SqlServerEscapeHelper
+ internal static class SqlServerEscapeHelper
{
/// <summary>
/// Escapes the identifier with square brackets. The input has to be in unescaped form, like the parts received from MultipartIdentifier.ParseMultipartIdentifier.
/// </summary>
/// <param name="name">name of the identifier, in unescaped form</param>
/// <returns>escapes the name with [], also escapes the last close bracket with double-bracket</returns>
- static internal string EscapeIdentifier(string name)
+ internal static string EscapeIdentifier(string name)
{
Debug.Assert(!string.IsNullOrEmpty(name), "null or empty identifiers are not allowed");
return "[" + name.Replace("]", "]]") + "]";
@@ -933,7 +933,7 @@ namespace System.Data.SqlClient
/// <summary>
/// Same as above EscapeIdentifier, except that output is written into StringBuilder
/// </summary>
- static internal void EscapeIdentifier(StringBuilder builder, string name)
+ internal static void EscapeIdentifier(StringBuilder builder, string name)
{
Debug.Assert(builder != null, "builder cannot be null");
Debug.Assert(!string.IsNullOrEmpty(name), "null or empty identifiers are not allowed");
@@ -946,7 +946,7 @@ namespace System.Data.SqlClient
/// <summary>
/// Escape a string to be used inside TSQL literal, such as N'somename' or 'somename'
/// </summary>
- static internal string EscapeStringAsLiteral(string input)
+ internal static string EscapeStringAsLiteral(string input)
{
Debug.Assert(input != null, "input string cannot be null");
return input.Replace("'", "''");
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs
index 459efc4314..0c5404e70f 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs
@@ -5456,7 +5456,7 @@ namespace System.Data.SqlClient
return true;
}
- static internal SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale)
+ internal static SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale)
{
if (d.Scale != newScale)
{
@@ -5466,7 +5466,7 @@ namespace System.Data.SqlClient
return d;
}
- static internal decimal AdjustDecimalScale(decimal value, int newScale)
+ internal static decimal AdjustDecimalScale(decimal value, int newScale)
{
int oldScale = (Decimal.GetBits(value)[3] & 0x00ff0000) >> 0x10;
@@ -5843,7 +5843,7 @@ namespace System.Data.SqlClient
Debug.Assert(!stateObj._attentionSent, "Invalid attentionSent state at end of ProcessAttention");
}
- static private int StateValueLength(int dataLen)
+ private static int StateValueLength(int dataLen)
{
return dataLen < 0xFF ? (dataLen + 1) : (dataLen + 5);
}
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserHelperClasses.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserHelperClasses.cs
index 3647a8f73e..6331b515cd 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserHelperClasses.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserHelperClasses.cs
@@ -195,7 +195,7 @@ namespace System.Data.SqlClient
}
- static internal bool AreSame(SqlCollation a, SqlCollation b)
+ internal static bool AreSame(SqlCollation a, SqlCollation b)
{
if (a == null || b == null)
{
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserSafeHandles.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserSafeHandles.cs
index a5e895b40d..5beb6ddd92 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserSafeHandles.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserSafeHandles.cs
@@ -88,7 +88,7 @@ namespace System.Data.SqlClient
}
}
- static private void ReadDispatcher(IntPtr key, IntPtr packet, UInt32 error)
+ private static void ReadDispatcher(IntPtr key, IntPtr packet, UInt32 error)
{
// This is the app-domain dispatcher for all async read callbacks, It
// simply gets the state object from the key that it is passed, and
@@ -109,7 +109,7 @@ namespace System.Data.SqlClient
}
}
- static private void WriteDispatcher(IntPtr key, IntPtr packet, UInt32 error)
+ private static void WriteDispatcher(IntPtr key, IntPtr packet, UInt32 error)
{
// This is the app-domain dispatcher for all async write callbacks, It
// simply gets the state object from the key that it is passed, and
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStaticMethods.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStaticMethods.cs
index 010fa0de3e..2c760dc18d 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStaticMethods.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStaticMethods.cs
@@ -16,7 +16,7 @@ namespace System.Data.SqlClient
// Encrypt password to be sent to SQL Server
// Note: The same logic is used in SNIPacketSetData (SniManagedWrapper) to encrypt passwords stored in SecureString
// If this logic changed, SNIPacketSetData needs to be changed as well
- static internal Byte[] EncryptPassword(string password)
+ internal static Byte[] EncryptPassword(string password)
{
Byte[] bEnc = new Byte[password.Length << 1];
int s;
@@ -36,7 +36,7 @@ namespace System.Data.SqlClient
private const int NoProcessId = -1;
private static int s_currentProcessId = NoProcessId;
- static internal int GetCurrentProcessIdForTdsLoginOnly()
+ internal static int GetCurrentProcessIdForTdsLoginOnly()
{
if (s_currentProcessId == NoProcessId)
{
@@ -51,14 +51,14 @@ namespace System.Data.SqlClient
}
- static internal Int32 GetCurrentThreadIdForTdsLoginOnly()
+ internal static Int32 GetCurrentThreadIdForTdsLoginOnly()
{
return Environment.CurrentManagedThreadId;
}
private static byte[] s_nicAddress = null;
- static internal byte[] GetNetworkPhysicalAddressForTdsLoginOnly()
+ internal static byte[] GetNetworkPhysicalAddressForTdsLoginOnly()
{
// For ProjectK\CoreCLR we don't want to take a dependency on the registry to try to read a value
// that isn't usually set, so we'll just use a random value each time instead
@@ -74,7 +74,7 @@ namespace System.Data.SqlClient
}
// translates remaining time in stateObj (from user specified timeout) to timeout value for SNI
- static internal Int32 GetTimeoutMilliseconds(long timeoutTime)
+ internal static Int32 GetTimeoutMilliseconds(long timeoutTime)
{
// User provided timeout t | timeout value for SNI | meaning
// ------------------------+-----------------------+------------------------------
@@ -101,7 +101,7 @@ namespace System.Data.SqlClient
}
- static internal long GetTimeout(long timeoutMilliseconds)
+ internal static long GetTimeout(long timeoutMilliseconds)
{
long result;
if (timeoutMilliseconds <= 0)
@@ -123,7 +123,7 @@ namespace System.Data.SqlClient
return result;
}
- static internal bool TimeoutHasExpired(long timeoutTime)
+ internal static bool TimeoutHasExpired(long timeoutTime)
{
bool result = false;
@@ -134,7 +134,7 @@ namespace System.Data.SqlClient
return result;
}
- static internal int NullAwareStringLength(string str)
+ internal static int NullAwareStringLength(string str)
{
if (str == null)
{
@@ -146,7 +146,7 @@ namespace System.Data.SqlClient
}
}
- static internal int GetRemainingTimeout(int timeout, long start)
+ internal static int GetRemainingTimeout(int timeout, long start)
{
if (timeout <= 0)
{
diff --git a/src/System.Data.SqlClient/tests/FunctionalTests/SqlConnectionTest.cs b/src/System.Data.SqlClient/tests/FunctionalTests/SqlConnectionTest.cs
index bd6b1becb4..7749103b47 100644
--- a/src/System.Data.SqlClient/tests/FunctionalTests/SqlConnectionTest.cs
+++ b/src/System.Data.SqlClient/tests/FunctionalTests/SqlConnectionTest.cs
@@ -57,10 +57,10 @@ namespace System.Data.SqlClient.Tests
}
TestTdsServer server = new TestTdsServer(args);
- server._endpoint = new TDSServerEndPoint(server) { ServerEndPoint = new IPEndPoint(IPAddress.Any, 12345) };
+ server._endpoint = new TDSServerEndPoint(server) { ServerEndPoint = new IPEndPoint(IPAddress.Any, 0) };
server._endpoint.Start();
-
- server.connectionStringBuilder = new SqlConnectionStringBuilder() { DataSource = "localhost,12345", ConnectTimeout = 30, Encrypt = false };
+ int port = server._endpoint.ServerEndPoint.Port;
+ server.connectionStringBuilder = new SqlConnectionStringBuilder() { DataSource = "localhost,"+port, ConnectTimeout = 30, Encrypt = false };
server.ConnectionString = server.connectionStringBuilder.ConnectionString;
return server;
}
diff --git a/src/System.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/System.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
index 0b60ec9128..76555154b7 100644
--- a/src/System.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
+++ b/src/System.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
@@ -10,8 +10,8 @@ namespace System.Data.SqlClient.ManualTesting.Tests
{
public static class DataTestUtility
{
- public readonly static string NpConnStr = null;
- public readonly static string TcpConnStr = null;
+ public static readonly string NpConnStr = null;
+ public static readonly string TcpConnStr = null;
static DataTestUtility()
{
diff --git a/src/System.Data.SqlClient/tests/StressTests/System.Data.StressRunner/Program.cs b/src/System.Data.SqlClient/tests/StressTests/System.Data.StressRunner/Program.cs
index aadb7ddf91..64230b56e9 100644
--- a/src/System.Data.SqlClient/tests/StressTests/System.Data.StressRunner/Program.cs
+++ b/src/System.Data.SqlClient/tests/StressTests/System.Data.StressRunner/Program.cs
@@ -217,7 +217,7 @@ namespace DPStressHarness
}
}
- static private void PrintHelp()
+ private static void PrintHelp()
{
Console.WriteLine("stresstest.exe [-a <module name>] <arguments>");
Console.WriteLine();
@@ -256,18 +256,18 @@ namespace DPStressHarness
Console.WriteLine();
}
- static private int ExitWithError()
+ private static int ExitWithError()
{
Environment.FailFast("Exit with error(s).");
return 1;
}
- static private int RunVerify()
+ private static int RunVerify()
{
throw new NotImplementedException();
}
- static private int RunStress()
+ private static int RunStress()
{
return s_eng.Run();
}
diff --git a/src/System.Data.SqlClient/tests/Tools/TDS/TDS.EndPoint/SSPI/SecurityWrapper.cs b/src/System.Data.SqlClient/tests/Tools/TDS/TDS.EndPoint/SSPI/SecurityWrapper.cs
index cb75484080..7e54ff5259 100644
--- a/src/System.Data.SqlClient/tests/Tools/TDS/TDS.EndPoint/SSPI/SecurityWrapper.cs
+++ b/src/System.Data.SqlClient/tests/Tools/TDS/TDS.EndPoint/SSPI/SecurityWrapper.cs
@@ -25,7 +25,7 @@ namespace Microsoft.SqlServer.TDS.EndPoint.SSPI
/// <param name="phCredential">A pointer to a CredHandle structure to receive the credential handle</param>
/// <param name="ptsExpiry">A pointer to a TimeStamp structure that receives the time at which the returned credentials expire</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto)]
- static internal extern int AcquireCredentialsHandle(
+ internal static extern int AcquireCredentialsHandle(
string pszPrincipal,
string pszPackage,
int fCredentialUse,
@@ -52,7 +52,7 @@ namespace Microsoft.SqlServer.TDS.EndPoint.SSPI
/// <param name="pfContextAttr">A pointer to a variable that receives a set of bit flags that indicate the attributes of the established context</param>
/// <param name="ptsTimeStamp">A pointer to a TimeStamp structure that receives the expiration time of the context</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto, SetLastError = false)]
- static internal extern int InitializeSecurityContext(ref SecurityHandle phCredential,
+ internal static extern int InitializeSecurityContext(ref SecurityHandle phCredential,
IntPtr phContext,
string pszTargetName,
uint fContextReq,
@@ -81,7 +81,7 @@ namespace Microsoft.SqlServer.TDS.EndPoint.SSPI
/// <param name="pfContextAttr">A pointer to a variable that receives a set of bit flags that indicate the attributes of the established context</param>
/// <param name="ptsTimeStamp">A pointer to a TimeStamp structure that receives the expiration time of the context</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto, SetLastError = false)]
- static internal extern int InitializeSecurityContext(ref SecurityHandle phCredential,
+ internal static extern int InitializeSecurityContext(ref SecurityHandle phCredential,
ref SecurityHandle phContext,
string pszTargetName,
uint fContextReq,
@@ -100,7 +100,7 @@ namespace Microsoft.SqlServer.TDS.EndPoint.SSPI
/// <param name="phContext">A handle of the context that needs to be completed</param>
/// <param name="pOutput">A pointer to a SecBufferDesc structure that contains the buffer descriptor for the entire message.</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto)]
- static internal extern int CompleteAuthToken(ref SecurityHandle phContext, out SecBufferDesc pOutput);
+ internal static extern int CompleteAuthToken(ref SecurityHandle phContext, out SecBufferDesc pOutput);
/// <summary>
/// The AcceptSecurityContext (Negotiate) function enables the server component of a transport application to establish a security context between the server and a remote client
@@ -115,7 +115,7 @@ namespace Microsoft.SqlServer.TDS.EndPoint.SSPI
/// <param name="pfContextAttr">A pointer to a variable that receives a set of bit flags that indicate the attributes of the established context</param>
/// <param name="ptsTimeStamp">A pointer to a TimeStamp structure that receives the expiration time of the context</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto, SetLastError = false)]
- static internal extern int AcceptSecurityContext(ref SecurityHandle phCredential,
+ internal static extern int AcceptSecurityContext(ref SecurityHandle phCredential,
IntPtr phContext,
ref SecBufferDesc pInput,
uint fContextReq,
@@ -138,7 +138,7 @@ namespace Microsoft.SqlServer.TDS.EndPoint.SSPI
/// <param name="pfContextAttr">A pointer to a variable that receives a set of bit flags that indicate the attributes of the established context</param>
/// <param name="ptsTimeStamp">A pointer to a TimeStamp structure that receives the expiration time of the context</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto, SetLastError = false)]
- static internal extern int AcceptSecurityContext(ref SecurityHandle phCredential,
+ internal static extern int AcceptSecurityContext(ref SecurityHandle phCredential,
ref SecurityHandle phContext,
ref SecBufferDesc pInput,
uint fContextReq,
@@ -153,7 +153,7 @@ namespace Microsoft.SqlServer.TDS.EndPoint.SSPI
/// </summary>
/// <param name="phCredential">A pointer to the CredHandle handle obtained by using the AcquireCredentialsHandle (General) function</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto)]
- static internal extern int FreeCredentialsHandle(ref SecurityHandle phCredential);
+ internal static extern int FreeCredentialsHandle(ref SecurityHandle phCredential);
/// <summary>
/// The FreeCredentialsHandle function notifies the security system that the credentials are no longer needed
@@ -161,7 +161,7 @@ namespace Microsoft.SqlServer.TDS.EndPoint.SSPI
/// <param name="phContext">Handle of the context to query</param>
/// <param name="phToken">Returned handle to the access token</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto)]
- static internal extern int QuerySecurityContextToken(ref SecurityHandle phContext, ref IntPtr phToken);
+ internal static extern int QuerySecurityContextToken(ref SecurityHandle phContext, ref IntPtr phToken);
/// <summary>
/// Retrieves information about a specified security package
@@ -169,13 +169,13 @@ namespace Microsoft.SqlServer.TDS.EndPoint.SSPI
/// <param name="packageName">Pointer to a null-terminated string that specifies the name of the security package</param>
/// <param name="ppPackageInfo">Pointer to a variable that receives a pointer to a SecPkgInfo structure containing information about the specified security package</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto)]
- static internal extern int QuerySecurityPackageInfo([MarshalAs(UnmanagedType.LPTStr)] string packageName, ref IntPtr ppPackageInfo);
+ internal static extern int QuerySecurityPackageInfo([MarshalAs(UnmanagedType.LPTStr)] string packageName, ref IntPtr ppPackageInfo);
/// <summary>
/// The FreeContextBuffer function enables callers of security package functions to free memory buffers allocated by the security package.
/// </summary>
/// <param name="pvContextBuffer">A pointer to memory to be freed</param>
[DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Auto)]
- static internal extern int FreeContextBuffer(IntPtr pvContextBuffer);
+ internal static extern int FreeContextBuffer(IntPtr pvContextBuffer);
}
}
diff --git a/src/System.Diagnostics.Debug/tests/DebugTests.cs b/src/System.Diagnostics.Debug/tests/DebugTests.cs
index 2296586ca2..b1def81cd4 100644
--- a/src/System.Diagnostics.Debug/tests/DebugTests.cs
+++ b/src/System.Diagnostics.Debug/tests/DebugTests.cs
@@ -188,7 +188,7 @@ namespace System.Diagnostics.Tests
class WriteLogger : Debug.IDebugLogger
{
- public readonly static WriteLogger Instance = new WriteLogger();
+ public static readonly WriteLogger Instance = new WriteLogger();
private WriteLogger()
{
diff --git a/src/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md b/src/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md
index 87c712a9dd..6af22eb8f0 100644
--- a/src/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md
+++ b/src/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md
@@ -99,7 +99,7 @@ Already some of the architectural elements are being exposed, namely
### Creating DiagnosticSources (Actually DiagnosticListeners)
-Perhaps confusingly you make a DiagnosticSource by creating DiagnosticListener
+Perhaps confusingly you make a DiagnosticSource by creating a DiagnosticListener
static DiagnosticSource mySource = new DiagnosticListener("System.Net.Http");
@@ -196,7 +196,7 @@ is typically not flexible enough.
Instead DiagnosticListener supports a way of discovering DiagnosticListener that is
active in the system at runtime. The API to accomplish this is the 'AllListeners'
-IObservable<DiagnosticListener>.
+IObservable\<DiagnosticListener>.
The IObservable interface is the 'callback' version of the IEnumerable interface. You can learn
more about it at the [Reactive Extensions Site](https://msdn.microsoft.com/en-us/data/gg577609.aspx).
@@ -240,19 +240,19 @@ to subscribe to.
Finally, note that the code above is taking advantage of convenience functionality in the System.Reactive.Core
library. The DiagnosticListener.AllListeners.Subscribe method actually requires that it be passed
-an IObserver<DiagnosticListener>, which is a class that has three callbacks (OnNext, OnError, OnComplete),
-but we passed it a Action<DiagnosticListener>. The magic that makes this work is an extension method
-in System.Reactive.Core that takes the Action and from it makes a IObserver (called AnonymousObserver)
+an IObserver\<DiagnosticListener>, which is a class that has three callbacks (OnNext, OnError, OnComplete),
+but we passed it an Action\<DiagnosticListener>. The magic that makes this work is an extension method
+in System.Reactive.Core that takes the Action and from it makes an IObserver (called AnonymousObserver)
which calls the Action on its OnNext callback. This glue is what makes the code concise.
#### Subscribing to DiagnosticListeners
-A DiagnosticListener implements the IObservable<KeyValuePair<string, object>> interface, so you can
+A DiagnosticListener implements the IObservable\<KeyValuePair\<string, object>> interface, so you can
call 'Subscribe' on it as well. Thus we can fill out the previous example a bit
```C#
- static IDisposable listenerSubscription = DiagnosticListener.AllListeners.Subscribe(delegate (DiagnosticListener listener)
static IDisposable networkSubscription = null;
+ static IDisposable listenerSubscription = DiagnosticListener.AllListeners.Subscribe(delegate (DiagnosticListener listener)
{
if (listener.Name == "System.Net.Http")
{
@@ -274,7 +274,7 @@ call 'Subscribe' on it as well. Thus we can fill out the previous example a bit
In this example after finding the 'System.Net.Http' DiagnosticListener, we create an action that
prints out the name of the listener, event, and payload.ToString(). Notice a few things:
- 1. DiagnosticListener implement IObservable<KeyValuePair<string, object>>. This means
+ 1. DiagnosticListener implement IObservable\<KeyValuePair\<string, object>>. This means
on each callback we get a KeyValuePair. The key of this pair is the name of the event
and the value is the payload object. In the code above we simply log this information
to the Console.
diff --git a/src/System.Diagnostics.Process/src/FxCopBaseline.cs b/src/System.Diagnostics.Process/src/FxCopBaseline.cs
new file mode 100644
index 0000000000..2fed8d3a21
--- /dev/null
+++ b/src/System.Diagnostics.Process/src/FxCopBaseline.cs
@@ -0,0 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.Process.#EnsureWatchingForExit()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.Process.#RaiseOnExited()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.Process.#StopWatchingForExit()")]
diff --git a/src/System.Diagnostics.Process/src/Resources/Strings.resx b/src/System.Diagnostics.Process/src/Resources/Strings.resx
index 2a84cc275c..87bfba788f 100644
--- a/src/System.Diagnostics.Process/src/Resources/Strings.resx
+++ b/src/System.Diagnostics.Process/src/Resources/Strings.resx
@@ -282,4 +282,34 @@
<data name="CantSetDuplicatePassword" xml:space="preserve">
<value>ProcessStartInfo.Password and ProcessStartInfo.PasswordInClearText cannot both be set. Use only one of them.</value>
</data>
+ <data name="ArgumentNull_Array" xml:space="preserve">
+ <value>Array cannot be null.</value>
+ </data>
+ <data name="ArgumentOutOfRange_IndexCountBuffer" xml:space="preserve">
+ <value>Index and count must refer to a location within the buffer.</value>
+ </data>
+ <data name="ArgumentOutOfRange_IndexCount" xml:space="preserve">
+ <value>Index and count must refer to a location within the string.</value>
+ </data>
+ <data name="ArgumentOutOfRange_Index" xml:space="preserve">
+ <value>Index was out of range. Must be non-negative and less than the size of the collection.</value>
+ </data>
+ <data name="Argument_EncodingConversionOverflowBytes" xml:space="preserve">
+ <value>The output byte buffer is too small to contain the encoded data, encoding '{0}' fallback '{1}'.</value>
+ </data>
+ <data name="Argument_EncodingConversionOverflowChars" xml:space="preserve">
+ <value>The output char buffer is too small to contain the decoded characters, encoding '{0}' fallback '{1}'.</value>
+ </data>
+ <data name="ArgumentOutOfRange_GetByteCountOverflow" xml:space="preserve">
+ <value>Too many characters. The resulting number of bytes is larger than what can be returned as an int.</value>
+ </data>
+ <data name="ArgumentOutOfRange_GetCharCountOverflow" xml:space="preserve">
+ <value>Too many bytes. The resulting number of chars is larger than what can be returned as an int.</value>
+ </data>
+ <data name="Argument_InvalidCharSequenceNoIndex" xml:space="preserve">
+ <value>String contains invalid Unicode code points.</value>
+ </data>
+ <data name="ArgumentOutOfRange_NeedNonNegNum" xml:space="preserve">
+ <value>Non-negative number required.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj b/src/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj
index 37f3103948..dac54e23a2 100644
--- a/src/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj
+++ b/src/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj
@@ -24,6 +24,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net46_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
+ <ItemGroup>
+ <Compile Include="FxCopBaseline.cs" />
+ </ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)'!='true'">
<Compile Include="Microsoft\Win32\SafeHandles\SafeProcessHandle.cs" />
<Compile Include="System\Diagnostics\AsyncStreamReader.cs" />
@@ -195,6 +198,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetCurrentProcessId.cs">
<Link>Common\Interop\Windows\Interop.GetCurrentProcessId.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.Encoding.Constants.cs">
+ <Link>Common\Interop\Windows\kernel32\Interop.Encoding.Constants.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetConsoleCP.cs">
<Link>Common\Interop\Windows\Interop.GetConsoleCP.cs</Link>
</Compile>
@@ -231,11 +237,29 @@
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.HandleOptions.cs">
<Link>Common\Interop\Windows\Interop.ProcessOptions.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.MultiByteToWideChar.cs">
+ <Link>Common\Interop\Windows\Interop.MultiByteToWideChar.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.WideCharToMultiByte.cs">
+ <Link>Common\Interop\Windows\Interop.WideCharToMultiByte.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\System\Text\ConsoleEncoding.cs">
<Link>Common\System\Text\ConsoleEncoding.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Text\EncodingHelper.cs">
- <Link>Common\System\Text\EncodingHelper.cs</Link>
+ <Compile Include="$(CommonPath)\System\Text\EncodingHelper.Windows.cs">
+ <Link>Common\System\Text\EncodingHelper.Windows.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Text\OSEncoding.Windows.cs">
+ <Link>Common\System\Text\OSEncoding.Windows.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Text\OSEncoder.cs">
+ <Link>Common\System\Text\OSEncoder.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Text\DBCSDecoder.cs">
+ <Link>Common\System\Text\DBCSDecoder.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetCPInfoEx.cs">
+ <Link>Common\Interop\Windows\kernel32\Interop.GetCPInfoEx.cs</Link>
</Compile>
<Compile Include="Microsoft\Win32\SafeHandles\SafeProcessHandle.Windows.cs" />
<Compile Include="Microsoft\Win32\SafeHandles\SafeThreadHandle.cs" />
diff --git a/src/System.Diagnostics.Process/tests/ProcessStandardConsoleTests.cs b/src/System.Diagnostics.Process/tests/ProcessStandardConsoleTests.cs
index 1731846e87..95e46e1f88 100644
--- a/src/System.Diagnostics.Process/tests/ProcessStandardConsoleTests.cs
+++ b/src/System.Diagnostics.Process/tests/ProcessStandardConsoleTests.cs
@@ -43,22 +43,12 @@ namespace System.Diagnostics.Tests
try
{
- {
- Interop.SetConsoleCP(s_ConsoleEncoding);
- Interop.SetConsoleOutputCP(s_ConsoleEncoding);
-
- run(Encoding.UTF8.CodePage);
- }
-
// Don't test this on Windows Nano, Windows Nano only supports UTF8.
if (File.Exists(Path.Combine(Environment.GetEnvironmentVariable("windir"), "regedit.exe")))
{
Interop.SetConsoleCP(s_ConsoleEncoding);
Interop.SetConsoleOutputCP(s_ConsoleEncoding);
- // Register the codeprovider which will ensure 437 is enabled.
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
-
run(s_ConsoleEncoding);
}
}
diff --git a/src/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs b/src/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs
index 5ac85165d0..7ba123d542 100644
--- a/src/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs
+++ b/src/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs
@@ -183,6 +183,7 @@ namespace System.Diagnostics.Tests
});
}
+ [ActiveIssue(14417)]
[Fact]
public void TestEnvironmentOfChildProcess()
{
diff --git a/src/System.Diagnostics.Process/tests/ProcessStartInfoTests.netstandard1.7.cs b/src/System.Diagnostics.Process/tests/ProcessStartInfoTests.netstandard1.7.cs
index 4c8c3331c6..cc26795971 100644
--- a/src/System.Diagnostics.Process/tests/ProcessStartInfoTests.netstandard1.7.cs
+++ b/src/System.Diagnostics.Process/tests/ProcessStartInfoTests.netstandard1.7.cs
@@ -79,8 +79,11 @@ namespace System.Diagnostics.Tests
psi.FileName = $"{Process.GetCurrentProcess().ProcessName}.exe";
Assert.Contains("open", psi.Verbs, StringComparer.OrdinalIgnoreCase);
- Assert.Contains("runas", psi.Verbs, StringComparer.OrdinalIgnoreCase);
- Assert.Contains("runasuser", psi.Verbs, StringComparer.OrdinalIgnoreCase);
+ if (PlatformDetection.IsNotWindowsNanoServer)
+ {
+ Assert.Contains("runas", psi.Verbs, StringComparer.OrdinalIgnoreCase);
+ Assert.Contains("runasuser", psi.Verbs, StringComparer.OrdinalIgnoreCase);
+ }
Assert.DoesNotContain("printto", psi.Verbs, StringComparer.OrdinalIgnoreCase);
Assert.DoesNotContain("closed", psi.Verbs, StringComparer.OrdinalIgnoreCase);
}
diff --git a/src/System.Diagnostics.Process/tests/ProcessTests.cs b/src/System.Diagnostics.Process/tests/ProcessTests.cs
index df6b85869d..a583dffd9d 100644
--- a/src/System.Diagnostics.Process/tests/ProcessTests.cs
+++ b/src/System.Diagnostics.Process/tests/ProcessTests.cs
@@ -595,8 +595,13 @@ namespace System.Diagnostics.Tests
{
try
{
- int? value = (int?)Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PerfProc\Performance", "Disable Performance Counters", null);
- return !value.HasValue || value.Value == 0;
+ using (Microsoft.Win32.RegistryKey perfKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\PerfProc\Performance"))
+ {
+ if (perfKey == null)
+ return false;
+ int? value = (int?)perfKey.GetValue("Disable Performance Counters", null);
+ return !value.HasValue || value.Value == 0;
+ }
}
catch (Exception)
{
diff --git a/src/System.Diagnostics.StackTrace/src/System/Diagnostics/StackTraceSymbols.CoreCLR.cs b/src/System.Diagnostics.StackTrace/src/System/Diagnostics/StackTraceSymbols.CoreCLR.cs
index afaed63fcc..6f6686300c 100644
--- a/src/System.Diagnostics.StackTrace/src/System/Diagnostics/StackTraceSymbols.CoreCLR.cs
+++ b/src/System.Diagnostics.StackTrace/src/System/Diagnostics/StackTraceSymbols.CoreCLR.cs
@@ -141,7 +141,7 @@ namespace System.Diagnostics
return provider.GetMetadataReader();
}
- private unsafe static MetadataReaderProvider TryOpenReaderForInMemoryPdb(IntPtr inMemoryPdbAddress, int inMemoryPdbSize)
+ private static unsafe MetadataReaderProvider TryOpenReaderForInMemoryPdb(IntPtr inMemoryPdbAddress, int inMemoryPdbSize)
{
Debug.Assert(inMemoryPdbAddress != IntPtr.Zero);
@@ -167,7 +167,7 @@ namespace System.Diagnostics
}
}
- private unsafe static PEReader TryGetPEReader(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize)
+ private static unsafe PEReader TryGetPEReader(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize)
{
// TODO: https://github.com/dotnet/corefx/issues/11406
//if (loadedPeAddress != IntPtr.Zero && loadedPeSize > 0)
diff --git a/src/System.Diagnostics.TextWriterTraceListener/src/FxCopBaseline.cs b/src/System.Diagnostics.TextWriterTraceListener/src/FxCopBaseline.cs
new file mode 100644
index 0000000000..9be0eb534a
--- /dev/null
+++ b/src/System.Diagnostics.TextWriterTraceListener/src/FxCopBaseline.cs
@@ -0,0 +1,3 @@
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.DelimitedListTraceListener.#set_Delimiter(System.String)")]
diff --git a/src/System.Diagnostics.TextWriterTraceListener/src/System.Diagnostics.TextWriterTraceListener.csproj b/src/System.Diagnostics.TextWriterTraceListener/src/System.Diagnostics.TextWriterTraceListener.csproj
index 324329ee60..42653528ff 100644
--- a/src/System.Diagnostics.TextWriterTraceListener/src/System.Diagnostics.TextWriterTraceListener.csproj
+++ b/src/System.Diagnostics.TextWriterTraceListener/src/System.Diagnostics.TextWriterTraceListener.csproj
@@ -12,6 +12,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <ItemGroup>
+ <Compile Include="FxCopBaseline.cs" />
+ </ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\Diagnostics\DelimitedListTraceListener.cs" />
<Compile Include="System\Diagnostics\TextWriterTraceListener.cs" />
diff --git a/src/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs b/src/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs
index 2a35b019fa..b072d3d80e 100644
--- a/src/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs
+++ b/src/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs
@@ -78,7 +78,7 @@ namespace System.Diagnostics
protected virtual void OnSwitchSettingChanged() { }
protected virtual void OnValueChanged() { }
public System.Collections.Specialized.StringDictionary Attributes { get { throw null; } }
- protected internal virtual string[] GetSupportedAttributes() { throw null; }
+ protected virtual string[] GetSupportedAttributes() { throw null; }
}
public sealed partial class Trace
{
@@ -221,7 +221,7 @@ namespace System.Diagnostics
public virtual void WriteLine(string message, string category) { }
public System.Collections.Specialized.StringDictionary Attributes { get { throw null; } }
public virtual void Close() { }
- protected internal virtual string[] GetSupportedAttributes() { throw null; }
+ protected virtual string[] GetSupportedAttributes() { throw null; }
public virtual void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId) { throw null; }
}
public partial class TraceListenerCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList
@@ -289,7 +289,7 @@ namespace System.Diagnostics
[System.Diagnostics.ConditionalAttribute("TRACE")]
public void TraceInformation(string format, params object[] args) { }
public System.Collections.Specialized.StringDictionary Attributes { get { throw null; } }
- protected internal virtual string[] GetSupportedAttributes() { throw null; }
+ protected virtual string[] GetSupportedAttributes() { throw null; }
public void TraceTransfer(int id, string message, System.Guid relatedActivityId) { }
}
public partial class TraceSwitch : System.Diagnostics.Switch
diff --git a/src/System.Diagnostics.TraceSource/src/FxCopBaseline.cs b/src/System.Diagnostics.TraceSource/src/FxCopBaseline.cs
new file mode 100644
index 0000000000..8a2b79b4a3
--- /dev/null
+++ b/src/System.Diagnostics.TraceSource/src/FxCopBaseline.cs
@@ -0,0 +1,21 @@
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#Flush()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#Fail(System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#Fail(System.String,System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#TraceEvent(System.Diagnostics.TraceEventType,System.Int32,System.String,System.Object[])")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#Write(System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#Write(System.String,System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#Write(System.Object)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#Write(System.Object,System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#WriteLine(System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#WriteLine(System.String,System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#WriteLine(System.Object)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceInternal.#WriteLine(System.Object,System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceSource.#Flush()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceSource.#TraceEvent(System.Diagnostics.TraceEventType,System.Int32)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceSource.#TraceEvent(System.Diagnostics.TraceEventType,System.Int32,System.String)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceSource.#TraceEvent(System.Diagnostics.TraceEventType,System.Int32,System.String,System.Object[])")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceSource.#TraceData(System.Diagnostics.TraceEventType,System.Int32,System.Object)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceSource.#TraceData(System.Diagnostics.TraceEventType,System.Int32,System.Object[])")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.TraceSource.#TraceTransfer(System.Int32,System.String,System.Guid)")]
diff --git a/src/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj b/src/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj
index 12d4d34cc0..13a7d2c84f 100644
--- a/src/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj
+++ b/src/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj
@@ -16,6 +16,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <ItemGroup>
+ <Compile Include="FxCopBaseline.cs" />
+ </ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\Diagnostics\BooleanSwitch.cs" />
<Compile Include="System\Diagnostics\CorrelationManager.cs" />
diff --git a/src/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceInternal.cs b/src/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceInternal.cs
index 23d80a2ecf..423c5e3a7c 100644
--- a/src/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceInternal.cs
+++ b/src/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceInternal.cs
@@ -349,7 +349,7 @@ namespace System.Diagnostics
// This method refreshes all the data from the configuration file, so that updated to the configuration file are mirrored
// in the System.Diagnostics.Trace class
- static internal void Refresh()
+ internal static void Refresh()
{
lock (critSec)
{
diff --git a/src/System.Diagnostics.Tracing/pkg/System.Diagnostics.Tracing.pkgproj b/src/System.Diagnostics.Tracing/pkg/System.Diagnostics.Tracing.pkgproj
index 15bdce64d9..ad6b0250ea 100644
--- a/src/System.Diagnostics.Tracing/pkg/System.Diagnostics.Tracing.pkgproj
+++ b/src/System.Diagnostics.Tracing/pkg/System.Diagnostics.Tracing.pkgproj
@@ -3,10 +3,10 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Diagnostics.Tracing.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Diagnostics.Tracing.csproj">
- <TargetGroup>net463</TargetGroup>
+ <TargetGroup>net461</TargetGroup>
</ProjectReference>
<ProjectReference Include="any\System.Diagnostics.Tracing.pkgproj" />
<ProjectReference Include="aot\System.Diagnostics.Tracing.pkgproj" />
@@ -20,6 +20,10 @@
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
+ <!-- the previous version of this package supported a different API version for
+ net462, but since netstandard2.0 supports the latest and net461 supports
+ netstandard2.0 we need to suppress the old net462 assembly. -->
+ <HarvestSuppressPaths Include="ref/net462;lib/net462" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Diagnostics.Tracing/src/ApiCompatBaseline.net461.txt b/src/System.Diagnostics.Tracing/src/ApiCompatBaseline.net461.txt
new file mode 100644
index 0000000000..3bd98c7d6d
--- /dev/null
+++ b/src/System.Diagnostics.Tracing/src/ApiCompatBaseline.net461.txt
@@ -0,0 +1,3 @@
+TypesMustExist : Type 'System.Diagnostics.Tracing.EventCounter' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Diagnostics.Tracing.EventSource.add_EventCommandExecuted(System.EventHandler<System.Diagnostics.Tracing.EventCommandEventArgs>)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Diagnostics.Tracing.EventSource.remove_EventCommandExecuted(System.EventHandler<System.Diagnostics.Tracing.EventCommandEventArgs>)' does not exist in the implementation but it does exist in the contract.
diff --git a/src/System.Diagnostics.Tracing/src/Configurations.props b/src/System.Diagnostics.Tracing/src/Configurations.props
index 9c336c0be9..53b62c64fe 100644
--- a/src/System.Diagnostics.Tracing/src/Configurations.props
+++ b/src/System.Diagnostics.Tracing/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Diagnostics.Tracing/src/FxCopBaseline.cs b/src/System.Diagnostics.Tracing/src/FxCopBaseline.cs
new file mode 100644
index 0000000000..d0542e737b
--- /dev/null
+++ b/src/System.Diagnostics.Tracing/src/FxCopBaseline.cs
@@ -0,0 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.Tracing.EventCounter.#Enqueue(System.Single)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.Tracing.EventCounter.#GetEventCounterPayload():System.Diagnostics.Tracing.EventCounterPayload")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Diagnostics.Tracing.EventCounterGroup.#OnTimer(System.Object)")]
diff --git a/src/System.Diagnostics.Tracing/src/System.Diagnostics.Tracing.csproj b/src/System.Diagnostics.Tracing/src/System.Diagnostics.Tracing.csproj
index 3a0510bbb4..723b63d398 100644
--- a/src/System.Diagnostics.Tracing/src/System.Diagnostics.Tracing.csproj
+++ b/src/System.Diagnostics.Tracing/src/System.Diagnostics.Tracing.csproj
@@ -10,14 +10,17 @@
<!-- Default configurations to help VS understand the options -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup>
+ <Compile Include="FxCopBaseline.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(TargetGroup)'=='' OR '$(TargetGroup)'=='netcore50aot'">
<ProjectReference Include="..\..\System.Runtime\src\System.Runtime.csproj" />
<Compile Include="System\Diagnostics\Tracing\EventCounter.cs" />
</ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)'=='true'">
- <TargetingPackReference Include="mscorlib" Condition="'$(TargetGroup)' == 'net463'" />
+ <TargetingPackReference Include="mscorlib" Condition="'$(TargetGroup)' == 'net461'" />
<TargetingPackReference Include="System.Private.CoreLib" Condition="'$(TargetGroup)' == 'netstandard'" />
</ItemGroup>
<ItemGroup>
diff --git a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventProvider.cs b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventProvider.cs
index 6ea8d98d92..ce12178b35 100644
--- a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventProvider.cs
+++ b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventProvider.cs
@@ -331,7 +331,7 @@ namespace System.Diagnostics.Tracing
protected EventKeywords MatchAnyKeyword { get { return (EventKeywords)m_anyKeywordMask; } set { m_anyKeywordMask = unchecked((long)value); } }
protected EventKeywords MatchAllKeyword { get { return (EventKeywords)m_allKeywordMask; } set { m_allKeywordMask = unchecked((long)value); } }
- static private int FindNull(byte[] buffer, int idx)
+ private static int FindNull(byte[] buffer, int idx)
{
while (idx < buffer.Length && buffer[idx] != 0)
idx++;
@@ -1132,7 +1132,7 @@ namespace System.Diagnostics.Tracing
// </SecurityKernel>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
[System.Security.SecurityCritical]
- internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
+ protected internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
{
if (childActivityID != null)
{
diff --git a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventSource.cs b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventSource.cs
index 836232a7ba..f5e8059137 100644
--- a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventSource.cs
+++ b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/EventSource.cs
@@ -2060,7 +2060,7 @@ namespace System.Diagnostics.Tracing
}
[SecurityCritical]
- unsafe private object[] SerializeEventArgs(int eventId, object[] args)
+ private unsafe object[] SerializeEventArgs(int eventId, object[] args)
{
TraceLoggingEventTypes eventTypes = m_eventData[eventId].TraceLoggingEventTypes;
if (eventTypes == null)
@@ -2136,7 +2136,7 @@ namespace System.Diagnostics.Tracing
}
[SecurityCritical]
- unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
+ private unsafe void WriteToAllListeners(int eventId, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
{
// We represent a byte[] as a integer denoting the length and then a blob of bytes in the data pointer. This causes a spurious
// warning because eventDataCount is off by one for the byte[] case since a byte[] has 2 items associated it. So we want to check
@@ -2160,7 +2160,7 @@ namespace System.Diagnostics.Tracing
// helper for writing to all EventListeners attached the current eventSource.
[SecurityCritical]
- unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, params object[] args)
+ private unsafe void WriteToAllListeners(int eventId, Guid* childActivityID, params object[] args)
{
EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
eventCallbackArgs.EventId = eventId;
@@ -2311,7 +2311,7 @@ namespace System.Diagnostics.Tracing
#if FEATURE_ACTIVITYSAMPLING
[SecurityCritical]
- unsafe private SessionMask GetEtwSessionMask(int eventId, Guid* childActivityID)
+ private unsafe SessionMask GetEtwSessionMask(int eventId, Guid* childActivityID)
{
SessionMask etwSessions = new SessionMask();
@@ -3823,7 +3823,7 @@ namespace System.Diagnostics.Tracing
/// <returns>The literal value or -1 if the value could not be determined. </returns>
[SecuritySafeCritical]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Switch statement is clearer than alternatives")]
- static private int GetHelperCallFirstArg(MethodInfo method)
+ private static int GetHelperCallFirstArg(MethodInfo method)
{
#if (!ES_BUILD_PCL && !PROJECTN)
// Currently searches for the following pattern
@@ -4125,7 +4125,7 @@ namespace System.Diagnostics.Tracing
private List<EtwSession> m_legacySessions; // the legacy ETW sessions listening to this source
internal long m_keywordTriggers; // a bit is set if it corresponds to a keyword that's part of an enabled triggering event
internal SessionMask m_activityFilteringForETWEnabled; // does THIS EventSource have activity filtering turned on for each ETW session
- static internal Action<Guid> s_activityDying; // Fires when something calls SetCurrentThreadToActivity()
+ internal static Action<Guid> s_activityDying; // Fires when something calls SetCurrentThreadToActivity()
// Also used to mark that activity tracing is on for some case
#endif // FEATURE_ACTIVITYSAMPLING
@@ -4395,7 +4395,7 @@ namespace System.Diagnostics.Tracing
/// for a particular eventSource to occur BEFORE the OnEventSourceCreated is issued.
/// </summary>
/// <param name="eventSource"></param>
- internal protected virtual void OnEventSourceCreated(EventSource eventSource)
+ protected internal virtual void OnEventSourceCreated(EventSource eventSource)
{
EventHandler<EventSourceCreatedEventArgs> callBack = this._EventSourceCreated;
if(callBack != null)
@@ -4411,7 +4411,7 @@ namespace System.Diagnostics.Tracing
/// the EventListener has enabled events.
/// </summary>
/// <param name="eventData"></param>
- internal protected virtual void OnEventWritten(EventWrittenEventArgs eventData)
+ protected internal virtual void OnEventWritten(EventWrittenEventArgs eventData)
{
EventHandler<EventWrittenEventArgs> callBack = this.EventWritten;
if (callBack != null)
@@ -5434,7 +5434,7 @@ namespace System.Diagnostics.Tracing
/// current activity is active.
/// </summary>
[SecurityCritical]
- unsafe public static bool PassesActivityFilter(
+ public static unsafe bool PassesActivityFilter(
ActivityFilter filterList,
Guid* childActivityID,
bool triggeringEvent,
@@ -5532,7 +5532,7 @@ namespace System.Diagnostics.Tracing
/// that the current activity is active.
/// </summary>
[SecurityCritical]
- unsafe public static void FlowActivityIfNeeded(ActivityFilter filterList, Guid* currentActivityId, Guid* childActivityID)
+ public static unsafe void FlowActivityIfNeeded(ActivityFilter filterList, Guid* currentActivityId, Guid* childActivityID)
{
Contract.Assert(childActivityID != null);
diff --git a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
index 38c1767462..1a599238fe 100644
--- a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
+++ b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
@@ -315,7 +315,7 @@ namespace System.Diagnostics.Tracing
private State state;
private string eventName;
- static internal Guid s_empty;
+ internal static Guid s_empty;
#endregion
}
}
diff --git a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs
index e51aff0380..24d7c100ed 100644
--- a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs
+++ b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs
@@ -135,7 +135,7 @@ namespace System.Diagnostics.Tracing
public static TraceLoggingTypeInfo UIntPtr() { return new ScalarArrayTypeInfo(typeof(UIntPtr[]), Statics.FormatPtr, Statics.UIntPtrType, System.IntPtr.Size); }
public static TraceLoggingTypeInfo Single() { return new ScalarArrayTypeInfo(typeof(Single[]), Statics.Format32, TraceLoggingDataType.Float, sizeof(Single)); }
public static TraceLoggingTypeInfo Double() { return new ScalarArrayTypeInfo(typeof(Double[]), Statics.Format64, TraceLoggingDataType.Double, sizeof(Double)); }
- public unsafe static TraceLoggingTypeInfo Guid() { return new ScalarArrayTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid, sizeof(Guid)); }
+ public static unsafe TraceLoggingTypeInfo Guid() { return new ScalarArrayTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid, sizeof(Guid)); }
}
/// <summary>
diff --git a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs
index 83a51f545e..fe3ae9d854 100644
--- a/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs
+++ b/src/System.Diagnostics.Tracing/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs
@@ -100,7 +100,7 @@ namespace Microsoft.Win32
[StructLayout(LayoutKind.Sequential)]
- unsafe internal struct EVENT_FILTER_DESCRIPTOR
+ internal unsafe struct EVENT_FILTER_DESCRIPTOR
{
public long Ptr;
public int Size;
diff --git a/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/EventSourceTestParser.cs b/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/EventSourceTestParser.cs
index 95e3dade96..57b27fba8c 100644
--- a/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/EventSourceTestParser.cs
+++ b/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/EventSourceTestParser.cs
@@ -428,148 +428,148 @@ using Address = System.UInt64;
// #region private
// protected override string GetProviderName() { return ProviderName; }
-// static private EmptyTraceData Event0Template(Action<EmptyTraceData> action)
+// private static EmptyTraceData Event0Template(Action<EmptyTraceData> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EmptyTraceData(action, 1, 65533, "Event0", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventEnumArgs EventEnumTemplate(Action<EventEnumArgs> action)
+// private static EventEnumArgs EventEnumTemplate(Action<EventEnumArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventEnumArgs(action, 19, 65515, "EventEnum", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventEnum1Args EventEnum1Template(Action<EventEnum1Args> action)
+// private static EventEnum1Args EventEnum1Template(Action<EventEnum1Args> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventEnum1Args(action, 20, 65514, "EventEnum1", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventFlagsArgs EventFlagsTemplate(Action<EventFlagsArgs> action)
+// private static EventFlagsArgs EventFlagsTemplate(Action<EventFlagsArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventFlagsArgs(action, 21, 65513, "EventFlags", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventFlags1Args EventFlags1Template(Action<EventFlags1Args> action)
+// private static EventFlags1Args EventFlags1Template(Action<EventFlags1Args> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventFlags1Args(action, 22, 65512, "EventFlags1", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventIArgs EventITemplate(Action<EventIArgs> action)
+// private static EventIArgs EventITemplate(Action<EventIArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventIArgs(action, 2, 65532, "EventI", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventIIArgs EventIITemplate(Action<EventIIArgs> action)
+// private static EventIIArgs EventIITemplate(Action<EventIIArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventIIArgs(action, 3, 65531, "EventII", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventIIIArgs EventIIITemplate(Action<EventIIIArgs> action)
+// private static EventIIIArgs EventIIITemplate(Action<EventIIIArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventIIIArgs(action, 4, 65530, "EventIII", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventLArgs EventLTemplate(Action<EventLArgs> action)
+// private static EventLArgs EventLTemplate(Action<EventLArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventLArgs(action, 5, 65529, "EventL", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventLLArgs EventLLTemplate(Action<EventLLArgs> action)
+// private static EventLLArgs EventLLTemplate(Action<EventLLArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventLLArgs(action, 6, 65528, "EventLL", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventLLLArgs EventLLLTemplate(Action<EventLLLArgs> action)
+// private static EventLLLArgs EventLLLTemplate(Action<EventLLLArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventLLLArgs(action, 7, 65527, "EventLLL", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventNoAttributesArgs EventNoAttributesTemplate(Action<EventNoAttributesArgs> action)
+// private static EventNoAttributesArgs EventNoAttributesTemplate(Action<EventNoAttributesArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventNoAttributesArgs(action, 16, 65518, "EventNoAttributes", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventSArgs EventSTemplate(Action<EventSArgs> action)
+// private static EventSArgs EventSTemplate(Action<EventSArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventSArgs(action, 8, 65526, "EventS", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventSIArgs EventSITemplate(Action<EventSIArgs> action)
+// private static EventSIArgs EventSITemplate(Action<EventSIArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventSIArgs(action, 11, 65523, "EventSI", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventSIIArgs EventSIITemplate(Action<EventSIIArgs> action)
+// private static EventSIIArgs EventSIITemplate(Action<EventSIIArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventSIIArgs(action, 13, 65521, "EventSII", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventSLArgs EventSLTemplate(Action<EventSLArgs> action)
+// private static EventSLArgs EventSLTemplate(Action<EventSLArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventSLArgs(action, 12, 65522, "EventSL", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventSSArgs EventSSTemplate(Action<EventSSArgs> action)
+// private static EventSSArgs EventSSTemplate(Action<EventSSArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventSSArgs(action, 9, 65525, "EventSS", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventSSSArgs EventSSSTemplate(Action<EventSSSArgs> action)
+// private static EventSSSArgs EventSSSTemplate(Action<EventSSSArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventSSSArgs(action, 10, 65524, "EventSSS", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventWith7StringsArgs EventWith7StringsTemplate(Action<EventWith7StringsArgs> action)
+// private static EventWith7StringsArgs EventWith7StringsTemplate(Action<EventWith7StringsArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWith7StringsArgs(action, 26, 65508, "EventWith7Strings", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventWith9StringsArgs EventWith9StringsTemplate(Action<EventWith9StringsArgs> action)
+// private static EventWith9StringsArgs EventWith9StringsTemplate(Action<EventWith9StringsArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWith9StringsArgs(action, 27, 65507, "EventWith9Strings", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventWithByteArrArgArgs EventWithByteArrArgTemplate(Action<EventWithByteArrArgArgs> action)
+// private static EventWithByteArrArgArgs EventWithByteArrArgTemplate(Action<EventWithByteArrArgArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWithByteArrArgArgs(action, 34, 65500, "EventWithByteArrArg", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventWithBytePtrArgArgs EventWithBytePtrArgTemplate(Action<EventWithBytePtrArgArgs> action)
+// private static EventWithBytePtrArgArgs EventWithBytePtrArgTemplate(Action<EventWithBytePtrArgArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWithBytePtrArgArgs(action, 35, 65499, "EventWithBytePtrArg", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventWithEscapingMessageArgs EventWithEscapingMessageTemplate(Action<EventWithEscapingMessageArgs> action)
+// private static EventWithEscapingMessageArgs EventWithEscapingMessageTemplate(Action<EventWithEscapingMessageArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWithEscapingMessageArgs(action, 32, 65502, "EventWithEscapingMessage", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventWithManyTypeArgsArgs EventWithManyTypeArgsTemplate(Action<EventWithManyTypeArgsArgs> action)
+// private static EventWithManyTypeArgsArgs EventWithManyTypeArgsTemplate(Action<EventWithManyTypeArgsArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWithManyTypeArgsArgs(action, 25, 65509, "EventWithManyTypeArgs", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventWithMoreEscapingMessageArgs EventWithMoreEscapingMessageTemplate(Action<EventWithMoreEscapingMessageArgs> action)
+// private static EventWithMoreEscapingMessageArgs EventWithMoreEscapingMessageTemplate(Action<EventWithMoreEscapingMessageArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWithMoreEscapingMessageArgs(action, 33, 65501, "EventWithMoreEscapingMessage", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventWithWeirdArgsArgs EventWithWeirdArgsTemplate(Action<EventWithWeirdArgsArgs> action)
+// private static EventWithWeirdArgsArgs EventWithWeirdArgsTemplate(Action<EventWithWeirdArgsArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWithWeirdArgsArgs(action, 30, 65504, "EventWithWeirdArgs", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EmptyTraceData LogTransferNoOpcodeTemplate(Action<EmptyTraceData> action)
+// private static EmptyTraceData LogTransferNoOpcodeTemplate(Action<EmptyTraceData> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EmptyTraceData(action, 28, 65506, "LogTransferNoOpcode", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private MessageArgs MessageTemplate(Action<MessageArgs> action)
+// private static MessageArgs MessageTemplate(Action<MessageArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new MessageArgs(action, 14, 65520, "Message", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private SlowerHelperArgs SlowerHelperTemplate(Action<SlowerHelperArgs> action)
+// private static SlowerHelperArgs SlowerHelperTemplate(Action<SlowerHelperArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new SlowerHelperArgs(action, 18, 65516, "SlowerHelper", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private EventDateTimeArgs WorkDateTimeOpcode1Template(Action<EventDateTimeArgs> action)
+// private static EventDateTimeArgs WorkDateTimeOpcode1Template(Action<EventDateTimeArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventDateTimeArgs(action, 24, 5, "WorkDateTime", Guid.Empty, 11, "Opcode1", ProviderGuid, ProviderName);
// }
-// static private EmptyTraceData WorkItemTemplate(Action<EmptyTraceData> action)
+// private static EmptyTraceData WorkItemTemplate(Action<EmptyTraceData> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EmptyTraceData(action, 15, 1, "WorkItem", Guid.Empty, 0, "", ProviderGuid, ProviderName);
// }
-// static private LogTaskScheduledBadArgs WorkItemBadSendTemplate(Action<LogTaskScheduledBadArgs> action)
+// private static LogTaskScheduledBadArgs WorkItemBadSendTemplate(Action<LogTaskScheduledBadArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new LogTaskScheduledBadArgs(action, 23, 2, "WorkItemBad", Guid.Empty, 9, "Send", ProviderGuid, ProviderName);
// }
-// static private LogTaskScheduledArgs WorkItemSendTemplate(Action<LogTaskScheduledArgs> action)
+// private static LogTaskScheduledArgs WorkItemSendTemplate(Action<LogTaskScheduledArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new LogTaskScheduledArgs(action, 17, 1, "WorkItem", Guid.Empty, 9, "Send", ProviderGuid, ProviderName);
// }
-// static private EventWithXferManyTypeArgsArgs WorkManyArgsSendTemplate(Action<EventWithXferManyTypeArgsArgs> action)
+// private static EventWithXferManyTypeArgsArgs WorkManyArgsSendTemplate(Action<EventWithXferManyTypeArgsArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWithXferManyTypeArgsArgs(action, 29, 3, "WorkManyArgs", Guid.Empty, 9, "Send", ProviderGuid, ProviderName);
// }
-// static private EventWithXferWeirdArgsArgs WorkWeirdArgsSendTemplate(Action<EventWithXferWeirdArgsArgs> action)
+// private static EventWithXferWeirdArgsArgs WorkWeirdArgsSendTemplate(Action<EventWithXferWeirdArgsArgs> action)
// { // action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
// return new EventWithXferWeirdArgsArgs(action, 31, 4, "WorkWeirdArgs", Guid.Empty, 9, "Send", ProviderGuid, ProviderName);
// }
-// static private volatile TraceEvent[] s_templates;
+// private static volatile TraceEvent[] s_templates;
// protected override void EnumerateTemplates(Func<string, string, EventFilterResponse> eventsToObserve, Action<TraceEvent> callback)
// {
// if (s_templates == null)
diff --git a/src/System.Diagnostics.Tracing/tests/CustomEventSources/EventSourceTest.cs b/src/System.Diagnostics.Tracing/tests/CustomEventSources/EventSourceTest.cs
index 5bbff01690..9757329e4b 100644
--- a/src/System.Diagnostics.Tracing/tests/CustomEventSources/EventSourceTest.cs
+++ b/src/System.Diagnostics.Tracing/tests/CustomEventSources/EventSourceTest.cs
@@ -76,7 +76,7 @@ namespace SdtEventSources
public void StartTrackingActivity() { WriteEvent(15); }
[Event(17, Keywords = Keywords.Transfer | Keywords.HasStringArgs, Opcode = EventOpcode.Send, Task = Tasks.WorkItem)]
- unsafe public void LogTaskScheduled(Guid RelatedActivityId, string message)
+ public unsafe void LogTaskScheduled(Guid RelatedActivityId, string message)
{
unsafe
{
diff --git a/src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/EventSourceForReflection.cs b/src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/EventSourceForReflection.cs
index f64273b3b4..67aabe71ae 100644
--- a/src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/EventSourceForReflection.cs
+++ b/src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/EventSourceForReflection.cs
@@ -88,7 +88,7 @@ namespace EvtSrcForReflection
public void StartTrackingActivity() { WriteEvent(15); }
[Event(16, Keywords = Keywords.Transfer | Keywords.HasStringArgs, Opcode = EventOpcode.Send, Task = Tasks.WorkItem)]
- unsafe public void LogTaskScheduled(Guid RelatedActivityId, string message)
+ public unsafe void LogTaskScheduled(Guid RelatedActivityId, string message)
{
unsafe
{
diff --git a/src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/Properties/AssemblyInfo.cs b/src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/Properties/AssemblyInfo.cs
index cb51092160..479ee59f07 100644
--- a/src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/Properties/AssemblyInfo.cs
+++ b/src/System.Diagnostics.Tracing/tests/EvtSrcForReflection/Properties/AssemblyInfo.cs
@@ -14,11 +14,3 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("EvtSrcForReflection")]
[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("618f93c9-e76d-4f97-9a79-9623d27e20e5")]
diff --git a/src/System.DirectoryServices.AccountManagement/System.DirectoryServices.AccountManagement.sln b/src/System.DirectoryServices.AccountManagement/System.DirectoryServices.AccountManagement.sln
new file mode 100644
index 0000000000..ab8e79f588
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/System.DirectoryServices.AccountManagement.sln
@@ -0,0 +1,107 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.DirectoryServices.AccountManagement", "ref\System.DirectoryServices.AccountManagement.csproj", "{2F7F1E21-0277-436B-85B8-E8FFA902FA66}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.DirectoryServices.AccountManagement", "src\System.DirectoryServices.AccountManagement.csproj", "{879C23DC-D828-4DFB-8E92-ABBC11B71035}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.DirectoryServices.AccountManagement.Tests", "tests\System.DirectoryServices.AccountManagement.Tests.csproj", "{57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{E37A8E5B-B822-436D-84FD-99EE46C0733F}"
+ ProjectSection(SolutionItems) = preProject
+ ref\project.lock.json = ref\project.lock.json
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AD3CFC4E-B3AE-4931-B631-C39216ABD115}"
+ ProjectSection(SolutionItems) = preProject
+ src\System.DirectoryServices.AccountManagement.builds = src\System.DirectoryServices.AccountManagement.builds
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{8CC3DFAB-7778-4181-A13D-321FC719A78D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ net46_Debug|Any CPU = net46_Debug|Any CPU
+ net46_Release|Any CPU = net46_Release|Any CPU
+ Release|Any CPU = Release|Any CPU
+ Unix_Debug|Any CPU = Unix_Debug|Any CPU
+ Unix_Release|Any CPU = Unix_Release|Any CPU
+ Windows_Debug|Any CPU = Windows_Debug|Any CPU
+ Windows_netcore50_Debug|Any CPU = Windows_netcore50_Debug|Any CPU
+ Windows_netcore50_Release|Any CPU = Windows_netcore50_Release|Any CPU
+ Windows_Release|Any CPU = Windows_Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Release|Any CPU.Build.0 = Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Debug|Any CPU.ActiveCfg = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Debug|Any CPU.ActiveCfg = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.net46_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.net46_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.net46_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.net46_Release|Any CPU.Build.0 = Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Unix_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Unix_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Unix_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Unix_Release|Any CPU.Build.0 = Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Windows_netcore50_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Windows_netcore50_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Windows_netcore50_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Windows_netcore50_Release|Any CPU.Build.0 = Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Windows_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}.Windows_Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66} = {E37A8E5B-B822-436D-84FD-99EE46C0733F}
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035} = {AD3CFC4E-B3AE-4931-B631-C39216ABD115}
+ {57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5} = {8CC3DFAB-7778-4181-A13D-321FC719A78D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/System.DirectoryServices.AccountManagement/dir.props b/src/System.DirectoryServices.AccountManagement/dir.props
new file mode 100644
index 0000000000..503cf86a87
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/dir.props
@@ -0,0 +1,7 @@
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\dir.props" />
+ <PropertyGroup>
+ <AssemblyVersion>4.1.0.0</AssemblyVersion>
+ </PropertyGroup>
+</Project>
+
diff --git a/src/System.DirectoryServices.AccountManagement/pkg/System.DirectoryServices.AccountManagement.builds b/src/System.DirectoryServices.AccountManagement/pkg/System.DirectoryServices.AccountManagement.builds
new file mode 100644
index 0000000000..71fc0db69f
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/pkg/System.DirectoryServices.AccountManagement.builds
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!--
+ <Project Include="System.DirectoryServices.AccountManagement.pkgproj"/>
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.DirectoryServices.AccountManagement/pkg/System.DirectoryServices.AccountManagement.pkgproj b/src/System.DirectoryServices.AccountManagement/pkg/System.DirectoryServices.AccountManagement.pkgproj
new file mode 100644
index 0000000000..ae3858fa9e
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/pkg/System.DirectoryServices.AccountManagement.pkgproj
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <ProjectReference Include="..\ref\System.DirectoryServices.AccountManagement.csproj">
+ <SupportedFramework>netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ </ProjectReference>
+ <ProjectReference Include="..\src\System.DirectoryServices.AccountManagement.builds" />
+ <InboxOnTargetFramework Include="MonoAndroid10" />
+ <InboxOnTargetFramework Include="MonoTouch10" />
+ <InboxOnTargetFramework Include="xamarinios10" />
+ <InboxOnTargetFramework Include="xamarinmac20" />
+ <InboxOnTargetFramework Include="xamarintvos10" />
+ <InboxOnTargetFramework Include="xamarinwatchos10" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.DirectoryServices.AccountManagement/ref/System.DirectoryServices.AccountManagement.cs b/src/System.DirectoryServices.AccountManagement/ref/System.DirectoryServices.AccountManagement.cs
new file mode 100644
index 0000000000..d3da1f8534
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/ref/System.DirectoryServices.AccountManagement.cs
@@ -0,0 +1,8 @@
+// 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.
+// ------------------------------------------------------------------------------
+// Changes to this file must follow the http://aka.ms/api-review process.
+// ------------------------------------------------------------------------------
+
+
diff --git a/src/System.DirectoryServices.AccountManagement/ref/System.DirectoryServices.AccountManagement.csproj b/src/System.DirectoryServices.AccountManagement/ref/System.DirectoryServices.AccountManagement.csproj
new file mode 100644
index 0000000000..76c749469d
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/ref/System.DirectoryServices.AccountManagement.csproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="System.DirectoryServices.AccountManagement.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.DirectoryServices.AccountManagement/src/Resources/System.DirectoryServices.AccountManagement.StringResources.txt b/src/System.DirectoryServices.AccountManagement/src/Resources/System.DirectoryServices.AccountManagement.StringResources.txt
new file mode 100644
index 0000000000..102ae7cb48
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/Resources/System.DirectoryServices.AccountManagement.StringResources.txt
@@ -0,0 +1,127 @@
+ContextNoWellKnownObjects=The domain's wellKnownObjects attribute does not contain values for the well-known users and/or computers containers.
+ContextNoContainerForMachineCtx=A container cannot be specified when using the Machine context.
+ContextNoContainerForApplicationDirectoryCtx=A container and name must be specified when using the Application Directory context.
+ContextBadUserPwdCombo=The user name and password must either both be null or both must be non-null.
+StoreNotSupportMethod=This store does not support this method.
+PrincipalCantSetContext=The PrincipalContext can only be set on an unpersisted Principal.
+PrincipalUnsupportedProperty=Principals in this type of store do not support the property '{0}'.
+PrincipalUnsupportPropertyForPlatform=Principals in this version of the store do not support the property '{0}'.
+PrincipalUnsupportPropertyForType=Principal objects of type {0} in this type of store do not support the property '{1}'.
+PrincipalMustSetContextForSave=A PrincipalContext must first be assigned to an unpersisted Principal object before the Principal can be saved.
+PrincipalMustSetContextForNative=A PrincipalContext must first be assigned to an unpersisted Principal object before the type of the underlying object can be retrieved.
+PrincipalMustSetContextForProperty=A PrincipalContext must first be assigned to the unpersisted Principal object before this property can be accessed.
+PrincipalCantDeleteUnpersisted=Unpersisted Principal objects can not be deleted.
+PrincipalDeleted=Cant delete an already deleted object
+PrincipalNotSupportedOnFakePrincipal=This Principal object represents a well-known SID and does not correspond to an actual store object. This operation is not supported on it.
+PrincipalMustPersistFirst=The Principal object must be persisted before this method can be called.
+PrincipalIdentityTypeNotAllowed=This type of identity information is not supported on principals in this type of store.
+PrincipalIdentityTypeNotRemovable=This type of identity information can not be cleared on principals in this type of store.
+PrincipalCantChangeSamNameOnPersistedSAM=This type of store does not permit changing the SAM account name after the principal has been persisted.
+EmptyIdentityType=The identityType parameter cannot be empty.
+PrincipalSearcherPersistedPrincipal=Persisted Principal objects cannot be used as query filters.
+PrincipalSearcherMustSetContext=A PrincipalContext must first be assigned to the PrincipalSearcher before the query can be performed.
+PrincipalSearcherMustSetFilter=A QueryFilter must first be assigned to the PrincipalSearcher before the query can be performed.
+PrincipalSearcherMustSetContextForUnderlying=A PrincipalContext must first be assigned to the PrincipalSearcher before the underlying searcher can be retrieved.
+PrincipalSearcherNoUnderlying=There is no underlying searcher for the type of store associated with the PrincipalContext.
+PrincipalSearcherNonReferentialProps=Only non-referential properties (properties which do not contain or refer to Principal objects) can be used in the query filter. The Principal object specified as the query filter has referential properties set.
+FindResultEnumInvalidPos=The enumerator is positioned before the first element of the collection or after the last element.
+TrackedCollectionNotOneDimensional=The destination array must be one-dimensional.
+TrackedCollectionIndexNotInArray=The specified index is greater than or equal to than the length of the destination array.
+TrackedCollectionArrayTooSmall=The number of elements to copy is greater than the available space in the destination array.
+TrackedCollectionEnumHasChanged=The collection was modified after the enumerator was created.
+TrackedCollectionEnumInvalidPos=The enumerator is positioned before the first element of the collection or after the last element.
+MultipleMatchesExceptionText=More than one matching identity was found.
+MultipleMatchingPrincipals=Multiple principals contain a matching Identity.
+NoMatchingPrincipalExceptionText=No principal matching the specified parameters was found.
+NoMatchingGroupExceptionText=No group matching the specified parameters was found.
+PrincipalExistsExceptionText=The principal already exists in the store.
+PrincipalCollectionNotOneDimensional=The destination array must be one-dimensional.
+PrincipalCollectionIndexNotInArray=The specified index is greater than or equal to than the length of the destination array.
+PrincipalCollectionArrayTooSmall=The number of elements to copy is greater than the available space in the destination array.
+PrincipalCollectionEnumHasChanged=The collection was modified after the enumerator was created.
+PrincipalCollectionEnumInvalidPos=The enumerator is positioned before the first element of the collection or after the last element.
+PrincipalCollectionAlreadyMember=The Principal object already exists in the collection.
+AuthenticablePrincipalMustBeSubtypeOfAuthPrinc=The subtype parameter must be either AuthenticablePrincipal or a subtype of AuthenticablePrincipal.
+PasswordInfoChangePwdOnUnpersistedPrinc=The ChangePassword method can not be called on an unpersisted Principal object.
+UserMustSetContextForMethod=A PrincipalContext must first be assigned to the unpersisted User object before this method can be called.
+UserDomainNotSupportedOnPlatform=Domain users are not supported on this platform.
+UserLocalNotSupportedOnPlatform=Local machine users not supported on this platform.
+UserCouldNotFindCurrent=The User object for the current user could not be found. You may not have access to it.
+UnableToRetrieveDomainInfo=Information about the domain could not be retrieved ({0}).
+UnableToOpenToken=The thread or process token could not be accessed ({0}).
+UnableToRetrieveTokenInfo=Information from the thread token could not be retrieved ({0}).
+UnableToRetrievePolicy=This computer's policy information could not be retrieved ({0}).
+UnableToImpersonateCredentials=The supplied credentials could not be impersonated.
+StoreCtxUnsupportedPrincipalTypeForSave=Principal objects of type {0} can not be saved in this store.
+StoreCtxUnsupportedPrincipalTypeForGroupInsert=Principal objects of type {0} can not be inserted into groups in this store
+StoreCtxUnsupportedPrincipalTypeForQuery=Principal objects of type {0} can not be used in a query against this store.
+StoreCtxUnsupportedPropertyForQuery=The property '{0}' can not be used in a query against this store.
+StoreCtxUnsupportedIdentityClaimForQuery=This IdentityType can not be used in a query against this store.
+StoreCtxIdentityClaimMustHaveScheme=The IdentityClaim to use in the query must have a UrnScheme specified.
+StoreCtxSecurityIdentityClaimBadFormat=The SID is not in a valid format.
+StoreCtxGuidIdentityClaimBadFormat=The GUID is not in a valid format.
+StoreCtxNT4IdentityClaimWrongForm=The samAccountName IdentityType must be in the form "domainname\\userName", "machinename\\userName", or "userName".
+StoreCtxCantSetTimeLimitOnIdentityClaim=This store does not support setting IdentityClaims with a restricted range of times for which the IdentityClaim is valid.
+StoreCtxGroupHasUnpersistedInsertedPrincipal=The Group object can not be saved until the unpersisted Principal object in its Members property is either saved or removed from the collection.
+StoreCtxNeedValueSecurityIdentityClaimToQuery=The Principal object must have a valid SID IdentityType in order to perform this operation.
+StoreCtxExceptionUpdatingGroup=An exception occurred while updating the group membership on the store.
+StoreCtxExceptionCommittingChanges=An exception occurred while saving the changes to the store.
+ADStoreCtxUnsupportedPrincipalContextForGroupInsert=Only domain Principal objects can be inserted into groups in this store.
+ADStoreCtxCouldntGetSIDForGroupMember=The SID for one of the Principal objects to be inserted into the group could not be retrieved from the store.
+ADStoreCtxMustBeContainer=Domain PrincipalContext objects must be rooted at a directory entry that is a container.
+ADStoreCtxCantRetrieveObjectSidForCrossStore=While trying to resolve a cross-store reference, the objectSid could not be retrieved from the representation of the target principal.
+ADStoreCtxCantResolveSidForCrossStore=While trying to resolve a cross-store reference, the SID of the target principal could not be resolved. The error code is {0}.
+ADStoreCtxFailedFindCrossStoreTarget=While trying to resolve a cross-store reference, the target principal could not be found in the domain indicated by the principal's SID.
+ADStoreCtxUnableToReadExistingAccountControlFlagsToEnable=The principal could not be enabled because the existing account control flags could not be read.
+ADStoreCtxUnableToReadExistingAccountControlFlagsForUpdate=The principal could not be updated because the existing account control flags could not be read.
+ADStoreCtxUnableToReadExistingGroupTypeFlagsForUpdate=The group could not be updated because the existing group type flags could not be read.
+ADStoreCtxCantClearGroup=The Group object's Members property can not be cleared because one or more of the group's members have this group as their primary group.
+ADStoreCtxCantRemoveMemberFromGroup=The member can not be removed from the Group object's Members property because it has this group as its primary group.
+ADStoreCtxNoComputerPasswordChange=Password change operation is not supported for Computer accounts in this store.
+SAMStoreCtxUnableToRetrieveVersion=The operating system version of the target computer could not be retrieved.
+SAMStoreCtxUnableToRetrieveMachineName=The name of the target computer could not be retrieved.
+SAMStoreCtxUnableToRetrieveFlatMachineName=The flat name of the target computer could not be retrieved ({0}).
+SAMStoreCtxNoComputerPasswordSet=Computer accounts in this store can not have their passwords reset or changed.
+SAMStoreCtxNoComputerPasswordExpire=Computer accounts in this store can not have their passwords expired.
+SAMStoreCtxIdentityClaimsImmutable=This store does not permit changing the IdentityClaims on a principal once the principal has been persisted.
+SAMStoreCtxCouldntGetSIDForGroupMember=One of the Principal objects to be inserted into or removed from the group's membership does not contain a SID.
+SAMStoreCtxFailedToClearGroup=An error ({0}) occurred while trying to clear the group membership.
+SAMStoreCtxCantRetrieveObjectSidForCrossStore=While trying to resolve a cross-store reference, the objectSid could not be retrieved from the representation of the target principal.
+SAMStoreCtxCantResolveSidForCrossStore=While trying to resolve a cross-store reference, the SID of the target principal could not be resolved. The error code is {0}.
+SAMStoreCtxFailedFindCrossStoreTarget=While trying to resolve a cross-store reference, the target principal could not be found in the domain indicated by the principal's SID.
+SAMStoreCtxErrorEnumeratingGroup=An error ({0}) occurred while enumerating the group membership. The member's SID could not be resolved.
+SAMStoreCtxLocalGroupsOnly=Only local groups are supported by this store.
+AuthZFailedToRetrieveGroupList=While trying to retrieve the authorization groups, an error ({0}) occurred.
+AuthZNotSupported=Retrieval of authorization groups is not supported by this platform.
+AuthZErrorEnumeratingGroups=An error ({0}) occurred while enumerating the groups. The group's SID could not be resolved.
+AuthZCantFindGroup=An error occurred while enumerating the groups. The group could not be found.
+ConfigHandlerConfigSectionsUnique=The '{0}' element can only appear once in the configuration file.
+ConfigHandlerInvalidBoolAttribute=The '{0}' attribute for element '{1}' of the configuration file must be set to 'true' or 'false'.
+ConfigHandlerInvalidEnumAttribute=The '{0}' attribute for element '{1}' of the configuration file is set to an unknown value.
+ConfigHandlerInvalidStringAttribute=The '{0}' attribute for element '{1}' of the configuration file must be set to a string.
+ConfigHandlerUnknownConfigSection=Unknown element '{0}' was found in the configuration file.
+PrincipalPermWrongType=The target parameter is not a PrincipalPermission.
+PrincipalPermXmlNotPermission=The SecurityElement is not a permission.
+PrincipalPermXmlBadVersion=The SecurityElement does not have a valid version. Version '1' was expected.
+PrincipalPermXmlBadContents=The SecurityElement does not contain a valid value for the 'Unrestricted' attribute.
+ContextOptionsNotValidForMachineStore=The options value is invalid. The Machine store only supports Negotiate.
+PassedContextTypeDoesNotMatchDetectedType=The supplied context type does not match the server contacted. The server type is {0}.
+NullArguments=The supplied arguments cannot be null.
+InvalidStringValueForStore=Empty string is not supported by the property {0} for this store type.
+InvalidNullArgument={0} cannot be null or empty.
+ServerDown=The server could not be contacted.
+InvalidPropertyForStore=Property is not valid for this store type.
+InvalidOperationForStore={0} is not supported by the {1} ContextType.
+NameMustBeSetToPersistPrincipal=SamAccountName or Name must be assigned to a newly-created Principal object in this store prior to saving.
+ExtensionInvalidClassDefinitionConstructor=Extension class must define a constructor that accepts a PrincipalContext argument.
+ExtensionInvalidClassAttributes=Extension class must set DirectoryObjectClassAttribute and DirectoryRdnPrefixAttribute.
+SaveToMustHaveSamecontextType=The target context must have the same type as the object's current context.
+ComputerInvalidForAppDirectoryStore=The ComputerPrincipal object is not supported by the ApplicationDirectory store.
+SaveToNotSupportedAgainstMachineStore=Saving to an alternate context is not supported by the Machine store.
+InvalidContextOptionsForMachine=The ContextOptions passed are invalid for the Machine store. Only ContextOptions.Negotiate is supported.
+InvalidContextOptionsForAD=The ContextOptions passed are invalid for this store type. Either Negotiate or SimpleBind must be specified and they cannot be combined.
+InvalidExtensionCollectionType=Collections whose elements are another collection cannot be set by ExtensionClasses.
+ADAMStoreUnableToPopulateSchemaList=The store is unable to populate a list of bindable object types. Check access to the Schema container.
+StoreCtxMultipleFiltersForPropertyUnsupported=Multiple filters on the property {0} are not supported.
+AdsiNotInstalled=Active Directory Client is not installed on this computer.
+DSUnknown=Unknown error (0x{0}) \ No newline at end of file
diff --git a/src/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.builds b/src/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.builds
new file mode 100644
index 0000000000..005e591d07
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.builds
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!-- Disabling the builds for DirectoryServices until we get it up and running. This excludes it from being built by build.cmd
+ <Project Include="System.DirectoryServices.AccountManagement.csproj">
+ <OSGroup>Windows_NT</OSGroup>
+ </Project>
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project>
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj b/src/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj
new file mode 100644
index 0000000000..ec7283e3d0
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <Configuration Condition="'$(Configuration)'=='' AND '$(TargetGroup)' == ''">Windows_Debug</Configuration>
+ </PropertyGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <ProjectGuid>{879C23DC-D828-4DFB-8E92-ABBC11B71035}</ProjectGuid>
+ <AssemblyName>System.DirectoryServices.AccountManagement</AssemblyName>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DefineConstants>$(DefineConstants);FLAVOR_WHIDBEY;PAPI_AD;PAPI_REGSAM;USE_CTX_CACHE</DefineConstants>
+ <NoWarn>$(NoWarn);8073</NoWarn>
+ <NuGetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ <GeneratePlatformNotSupportedAssembly Condition="'$(TargetsUnix)' == 'true'">true</GeneratePlatformNotSupportedAssembly>
+ </PropertyGroup>
+ <!-- Help VS understand available configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
+ <ItemGroup>
+ <Compile Include="System\DirectoryServices\AccountManagement\externdll.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\interopt.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\PrincipalSearcher.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\utils.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\constants.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\Context.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\Resources.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\StoreCtx.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\StoreKey.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\Principal.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AuthenticablePrincipal.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\User.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\Computer.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\Group.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AccountInfo.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\PasswordInfo.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\MatchType.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\CredentialTypes.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\RejectedClaimChange.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\ContextType.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\ContextOptions.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\SidType.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\ResultSet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\EmptySet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\QbeFilterDescription.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\PrincipalCollection.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\PrincipalCollectionEnumerator.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\TrackedCollection.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\TrackedCollectionEnumerator.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\ValueCollection.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\ValueCollectionEnumerator.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\Pair.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\FindResult.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\FindResultEnumerator.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\exceptions.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\IdentityType.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\UrnScheme.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\GroupType.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AuthZSet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\ConfigurationHandler.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\GlobalConfig.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\GlobalDebug.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\NetCred.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\ExtensionAttributes.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\ExtensionCache.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\ExtensionHelper.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AdvancedFilters.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\GlobalSuppressions.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\QBEMatchType.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\SidList.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\ADDNConstraintLinkedAttrSet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\dspropertycollection.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\ADStoreCtx.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\ADStoreCtx_Query.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\ADStoreCtx_LoadStore.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\ADStoreKey.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\ADEntriesSet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\ADDNLinkedAttrSet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\ADUtils.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\SDSUtils.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\SDSCache.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\RangeRetriever.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\ADAMStoreCtx.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\AD\TokenGroupsSet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\SAM\SAMStoreCtx.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\SAM\SAMStoreCtx_Query.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\SAM\SAMStoreCtx_LoadStore.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\SAM\SAMQuerySet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\SAM\SAMMembersSet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\SAM\SAMGroupsSet.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\SAM\SAMStoreKey.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\SAM\SAMUtils.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\IdentityClaim.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\IdentityReference.cs" />
+ <Compile Include="System\DirectoryServices\AccountManagement\UnknownPrincipal.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADAMStoreCtx.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADAMStoreCtx.cs
new file mode 100644
index 0000000000..703987a349
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADAMStoreCtx.cs
@@ -0,0 +1,496 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Net;
+using System.Security.Principal;
+using System.Security.Permissions;
+
+using System.DirectoryServices;
+using System.Text;
+
+namespace System.DirectoryServices.AccountManagement
+{
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal partial class ADAMStoreCtx : ADStoreCtx
+ {
+ private const int mappingIndex = 1;
+ private List<string> _cachedBindableObjectList = null;
+ private string _cachedBindableObjectFilter = null;
+ private object _objectListLock = new object();
+
+ public ADAMStoreCtx(DirectoryEntry ctxBase, bool ownCtxBase, string username, string password, string serverName, ContextOptions options) : base(ctxBase, ownCtxBase, username, password, options)
+ {
+ this.userSuppliedServerName = serverName;
+ }
+
+ //
+ // Static constructor: used for initializing static tables
+ //
+ static ADAMStoreCtx()
+ {
+ LoadFilterMappingTable(mappingIndex, s_filterPropertiesTableRaw);
+ LoadPropertyMappingTable(mappingIndex, s_propertyMappingTableRaw);
+
+ if (NonPresentAttrDefaultStateMapping == null)
+ NonPresentAttrDefaultStateMapping = new Dictionary<string, bool>();
+
+ for (int i = 0; i < s_presenceStateTable.GetLength(0); i++)
+ {
+ string attributeName = s_presenceStateTable[i, 0] as string;
+ string defaultState = s_presenceStateTable[i, 1] as string;
+ NonPresentAttrDefaultStateMapping.Add(attributeName, (defaultState == "FALSE") ? false : true);
+ }
+ }
+
+ protected override int MappingTableIndex
+ {
+ get
+ {
+ return mappingIndex;
+ }
+ }
+
+ protected internal override void InitializeNewDirectoryOptions(DirectoryEntry newDeChild)
+ {
+ newDeChild.Options.PasswordPort = ctxBase.Options.PasswordPort;
+ }
+
+ protected override void SetAuthPrincipalEnableStatus(AuthenticablePrincipal ap, bool enable)
+ {
+ Debug.Assert(ap.fakePrincipal == false);
+
+ bool acctDisabled;
+ DirectoryEntry de = (DirectoryEntry)ap.UnderlyingObject;
+
+ if (de.Properties["msDS-UserAccountDisabled"].Count > 0)
+ {
+ Debug.Assert(de.Properties["msDS-UserAccountDisabled"].Count == 1);
+
+ acctDisabled = (bool)de.Properties["msDS-UserAccountDisabled"][0];
+ }
+ else
+ {
+ // Since we loaded the properties, we should have it. Perhaps we don't have access
+ // to it. In that case, we don't want to blindly overwrite whatever other bits might be there.
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADAMStoreCtx", "SetAuthPrincipalEnableStatus: can't read userAccountControl");
+
+ throw new PrincipalOperationException(
+ StringResources.ADStoreCtxUnableToReadExistingAccountControlFlagsToEnable);
+ }
+
+ if ((enable && acctDisabled) || (!enable && !acctDisabled))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADAMStoreCtx", "SetAuthPrincipalEnableStatus: Enabling (old enabled ={0} new enabled= {1})", !acctDisabled, enable);
+
+ WriteAttribute<bool>(ap, "msDS-UserAccountDisabled", !enable);
+ }
+ }
+
+ // Must be called inside of lock(domainInfoLock)
+ override protected void LoadDomainInfo()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo");
+
+ Debug.Assert(this.ctxBase != null);
+
+ //
+ // DNS Domain Name
+ //
+ this.dnsHostName = ADUtils.GetServerName(this.ctxBase);
+ // Treat the user supplied server name as the domain and forest name...
+ this.domainFlatName = userSuppliedServerName;
+ this.forestDnsName = userSuppliedServerName;
+ this.domainDnsName = userSuppliedServerName;
+
+ //
+ // Find the partition in which the supplied ctxBase belongs by comparing it with the list of partitions hosted by this
+ // LDS (ADAM) instance.
+ //
+ using (DirectoryEntry rootDse = new DirectoryEntry("LDAP://" + this.userSuppliedServerName + "/rootDse", "", "", AuthenticationTypes.Anonymous))
+ {
+ string ctxBaseDN = (string)this.ctxBase.Properties["distinguishedName"][0];
+ int maxMatchLength = -1;
+ foreach (string partitionDN in rootDse.Properties["namingContexts"])
+ {
+ if ((partitionDN.Length > maxMatchLength) && ctxBaseDN.EndsWith(partitionDN, StringComparison.OrdinalIgnoreCase))
+ {
+ maxMatchLength = partitionDN.Length;
+ this.contextBasePartitionDN = partitionDN;
+ }
+ }
+ }
+
+ //
+ // User supplied name
+ //
+ UnsafeNativeMethods.Pathname pathCracker = new UnsafeNativeMethods.Pathname();
+ UnsafeNativeMethods.IADsPathname pathName = (UnsafeNativeMethods.IADsPathname)pathCracker;
+
+ pathName.Set(this.ctxBase.Path, 1 /* ADS_SETTYPE_FULL */);
+
+ try
+ {
+ this.userSuppliedServerName = pathName.Retrieve(9 /*ADS_FORMAT_SERVER */);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo: using user-supplied name {0}", this.userSuppliedServerName);
+ }
+ catch (COMException e)
+ {
+ if (((uint)e.ErrorCode) == ((uint)0x80005000)) // E_ADS_BAD_PATHNAME
+ {
+ // Serverless path
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo: using empty string as user-supplied name");
+ this.userSuppliedServerName = "";
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "ADStoreCtx",
+ "LoadComputerInfo: caught COMException {0} {1} looking for user-supplied name",
+ e.ErrorCode,
+ e.Message);
+
+ throw;
+ }
+ }
+ }
+
+ internal override ResultSet GetGroupsMemberOfAZ(Principal p)
+ {
+ // Enforced by the methods that call us
+ Debug.Assert(p.unpersisted == false);
+ Debug.Assert(p is UserPrincipal);
+
+ Debug.Assert(p.UnderlyingObject != null);
+
+ DirectoryEntry principalDE = (DirectoryEntry)p.UnderlyingObject;
+
+ string principalDN = (string)principalDE.Properties["distinguishedName"].Value;
+ return (new TokenGroupSet(principalDN, this, true));
+ }
+
+ // modifies the connections settings for the upcoming password operation..
+ // If Signing + Sealing are enabled on the connection a direct call to SetPassword will always fail for ADAM.
+ // ADSI will first attempt to set the password over SSL which will fail because double encryption is not supported.
+ // It will then try KetSetPassword and NetApi which will both always fail against ADAM.
+ // We need to tell ADSI to send a clear text password which is not actually clear text because
+ // the initial connection is encrypted with sign + seal. Once this call is made the user needs to call CleanupAfterPasswordModification
+ // To reset the options that were modified.
+ private void SetupPasswordModification(AuthenticablePrincipal p)
+ {
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+
+ if (((this.contextOptions & ContextOptions.Signing) != 0) &&
+ ((this.contextOptions & ContextOptions.Sealing) != 0))
+ {
+ try
+ {
+ de.Invoke("SetOption", new object[]{UnsafeNativeMethods.ADS_OPTION_ENUM.ADS_OPTION_PASSWORD_METHOD,
+ UnsafeNativeMethods.ADS_PASSWORD_ENCODING_ENUM.ADS_PASSWORD_ENCODE_CLEAR});
+
+ de.Options.PasswordPort = p.Context.ServerInformation.portLDAP;
+ }
+ catch (System.Reflection.TargetInvocationException e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "ADAMStoreCtx", "SetupPasswordModification: caught TargetInvocationException with message " + e.Message);
+
+ if (e.InnerException is System.Runtime.InteropServices.COMException)
+ {
+ throw (ExceptionHelper.GetExceptionFromCOMException((System.Runtime.InteropServices.COMException)e.InnerException));
+ }
+
+ // Unknown exception. We don't want to suppress it.
+ throw;
+ }
+ }
+ }
+
+ internal override void SetPassword(AuthenticablePrincipal p, string newPassword)
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ Debug.Assert(p != null);
+ Debug.Assert(newPassword != null); // but it could be an empty string
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ SetupPasswordModification(p);
+
+ SDSUtils.SetPassword(de, newPassword);
+ }
+
+ /// <summary>
+ /// Change the password on the principal
+ /// </summary>
+ /// <param name="p">Principal to modify</param>
+ /// <param name="oldPassword">Current password</param>
+ /// <param name="newPassword">New password</param>
+ internal override void ChangePassword(AuthenticablePrincipal p, string oldPassword, string newPassword)
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ // Shouldn't be being called if this is the case
+ Debug.Assert(p.unpersisted == false);
+
+ Debug.Assert(p != null);
+ Debug.Assert(newPassword != null); // but it could be an empty string
+ Debug.Assert(oldPassword != null); // but it could be an empty string
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ SetupPasswordModification(p);
+
+ SDSUtils.ChangePassword(de, oldPassword, newPassword);
+ }
+
+ //------------------------------------------------------------------------------------
+ // Taking a server target and Auxillary class name return
+ // a list of all possible objectClasses that include that auxClass. A search for object that have a specific
+ // aux class cannot be done directly on the objects because static auxClasses to not appear in the
+ // actual object. This is done by
+ // 1. Searching the schema container for schema classes that include the aux class as a
+ // SystemAuxiliaryClass. This covers StaticAuxClasses.
+ // 2. Add the aux class name as an additional returned objectClass to cover Dynamic AuxClasses.
+ //------------------------------------------------------------------------------------
+ private List<string> PopulatAuxObjectList(string auxClassName)
+ {
+ string SchemaNamingContext;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADAMStoreCtx", "PopulatAuxObjectList Building object list");
+
+ try
+ {
+ using (DirectoryEntry deRoot = new DirectoryEntry("LDAP://" + userSuppliedServerName + "/rootDSE", credentials == null ? null : credentials.UserName, credentials == null ? null : credentials.Password, authTypes))
+ {
+ if (deRoot.Properties["schemaNamingContext"].Count == 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "ADAMStoreCtx", "PopulatAuxObjectList Unable to read schemaNamingContrext from " + userSuppliedServerName);
+ throw new PrincipalOperationException(StringResources.ADAMStoreUnableToPopulateSchemaList);
+ }
+
+ SchemaNamingContext = (string)deRoot.Properties["schemaNamingContext"].Value;
+ }
+
+ using (DirectoryEntry deSCN = new DirectoryEntry("LDAP://" + userSuppliedServerName + "/" + SchemaNamingContext, credentials == null ? null : credentials.UserName, credentials == null ? null : credentials.Password, authTypes))
+ {
+ using (DirectorySearcher dirSearcher = new DirectorySearcher(deSCN))
+ {
+ dirSearcher.Filter = "(&(objectClass=classSchema)(systemAuxiliaryClass=" + auxClassName + "))";
+ dirSearcher.PropertiesToLoad.Add("ldapDisplayName");
+
+ List<string> objectClasses = new List<string>();
+ using (SearchResultCollection searchResCollection = dirSearcher.FindAll())
+ {
+ foreach (SearchResult res in searchResCollection)
+ {
+ if (null == res.Properties["ldapDisplayName"])
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "ADAMStoreCtx", "PopulatAuxObjectList Unable to read ldapDisplayName from " + SchemaNamingContext);
+ throw new PrincipalOperationException(StringResources.ADAMStoreUnableToPopulateSchemaList);
+ }
+
+ objectClasses.Add(res.Properties["ldapDisplayName"][0].ToString());
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADAMStoreCtx", "PopulatAuxObjectList Adding " + res.Properties["ldapDisplayName"][0].ToString());
+ }
+ }
+
+ objectClasses.Add(auxClassName);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADAMStoreCtx", "PopulatAuxObjectList Adding " + auxClassName);
+
+ return objectClasses;
+ }
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "ADAMStoreCtx", "PopulatAuxObjectList COM Exception");
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ protected override string GetObjectClassPortion(Type principalType)
+ {
+ if (principalType == typeof(AuthenticablePrincipal) || principalType == typeof(Principal))
+ {
+ lock (_objectListLock)
+ {
+ if (null == _cachedBindableObjectList)
+ {
+ _cachedBindableObjectList = PopulatAuxObjectList("msDS-BindableObject");
+ }
+
+ if (null == _cachedBindableObjectFilter)
+ {
+ StringBuilder filter = new StringBuilder();
+
+ filter.Append("(&(|");
+ foreach (string objectClass in _cachedBindableObjectList)
+ {
+ filter.Append("(objectClass=");
+ filter.Append(objectClass);
+ filter.Append(")");
+ }
+
+ _cachedBindableObjectFilter = filter.ToString();
+ }
+
+ if (principalType == typeof(Principal))
+ {
+ // IF we are searching for a principal then we also have to add Group type into the filter...
+ return _cachedBindableObjectFilter + "(objectClass=group))";
+ }
+ else
+ {
+ return _cachedBindableObjectFilter + ")";
+ }
+ }
+ }
+ else
+ {
+ return base.GetObjectClassPortion(principalType);
+ }
+ }
+
+ /// <summary>
+ /// This method sets the default user account control bits for the new principal
+ /// being created in this account store.
+ /// </summary>
+ /// <param name="p"> Principal to set the user account control bits for </param>
+ internal override void InitializeUserAccountControl(AuthenticablePrincipal p)
+ {
+ // In ADAM, there is no user account control property that needs to be initialized
+ // so do nothing
+ }
+
+ //
+ // Property mapping tables
+ //
+
+ //
+ // This table maps properties where the non-presence of the property
+ // indicates the state shown in the table. When searching for these properties
+ // If the state desired matches that default state then we also must search for
+ // non-existence of the attribute.
+ private static object[,] s_presenceStateTable =
+ {
+ {"ms-DS-UserPasswordNotRequired", "FALSE" },
+ {"msDS-UserDontExpirePassword", "FALSE" },
+ {"ms-DS-UserEncryptedTextPasswordAllowed", "FALSE" }
+ };
+
+ // We only list properties we map in this table. At run-time, if we detect they set a
+ // property that's not listed here when writing to AD, we throw an exception.
+ //
+ // When updating this table, be sure to also update LoadDirectoryEntryAttributes() to load
+ // in any newly-added attributes.
+ private static object[,] s_propertyMappingTableRaw =
+ {
+ // PropertyName AD property Converter(LDAP->PAPI) Converter(PAPI->LDAP)
+ {PropertyNames.PrincipalDescription, "description", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalDisplayName, "displayName", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalDistinguishedName, "distinguishedName", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalSid, "objectSid", new FromLdapConverterDelegate(SidFromLdapConverter), null},
+ {PropertyNames.PrincipalSamAccountName, "name", null, null},
+ {PropertyNames.PrincipalUserPrincipalName, "userPrincipalName", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalGuid, "objectGuid", new FromLdapConverterDelegate(GuidFromLdapConverter), null},
+ {PropertyNames.PrincipalStructuralObjectClass, "objectClass", new FromLdapConverterDelegate(ObjectClassFromLdapConverter), null},
+ {PropertyNames.PrincipalName, "name", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalExtensionCache, null, null, new ToLdapConverterDelegate(ExtensionCacheToLdapConverter)},
+
+ {PropertyNames.AuthenticablePrincipalEnabled, "msDS-UserAccountDisabled", new FromLdapConverterDelegate(AcctDisabledFromLdapConverter), new ToLdapConverterDelegate(AcctDisabledToLdapConverter)},
+ {PropertyNames.AuthenticablePrincipalCertificates, "userCertificate", new FromLdapConverterDelegate(CertFromLdapConverter), new ToLdapConverterDelegate(CertToLdap)},
+
+ {PropertyNames.GroupIsSecurityGroup, "groupType", new FromLdapConverterDelegate(GroupTypeFromLdapConverter), new ToLdapConverterDelegate(GroupTypeToLdapConverter)},
+ {PropertyNames.GroupGroupScope, "groupType", new FromLdapConverterDelegate(GroupTypeFromLdapConverter), new ToLdapConverterDelegate(GroupTypeToLdapConverter)},
+
+ {PropertyNames.UserGivenName, "givenName", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserMiddleName, "middleName", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserSurname, "sn", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserEmailAddress, "mail", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserVoiceTelephoneNumber, "telephoneNumber", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserEmployeeID, "employeeID", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+
+ {PropertyNames.ComputerServicePrincipalNames, "servicePrincipalName", new FromLdapConverterDelegate(MultiStringFromLdapConverter), new ToLdapConverterDelegate(MultiStringToLdapConverter)},
+
+ {PropertyNames.AcctInfoAcctLockoutTime, "lockoutTime", new FromLdapConverterDelegate(GenericDateTimeFromLdapConverter), null},
+ {PropertyNames.AcctInfoLastLogon, "lastLogon", new FromLdapConverterDelegate(LastLogonFromLdapConverter), null},
+ {PropertyNames.AcctInfoLastLogon, "lastLogonTimestamp", new FromLdapConverterDelegate(LastLogonFromLdapConverter), null},
+ {PropertyNames.AcctInfoPermittedWorkstations, "userWorkstations", null, null},
+ {PropertyNames.AcctInfoPermittedLogonTimes, "logonHours", null, null},
+ {PropertyNames.AcctInfoExpirationDate, "accountExpires", new FromLdapConverterDelegate(AcctExpirFromLdapConverter), new ToLdapConverterDelegate(AcctExpirToLdapConverter)},
+ {PropertyNames.AcctInfoSmartcardRequired, "userAccountControl", null, null},
+ {PropertyNames.AcctInfoDelegationPermitted, "userAccountControl", null, null},
+ {PropertyNames.AcctInfoBadLogonCount, "badPwdCount", new FromLdapConverterDelegate(IntFromLdapConverter), null},
+ {PropertyNames.AcctInfoHomeDirectory, "homeDirectory", null, null},
+ {PropertyNames.AcctInfoHomeDrive, "homeDrive", null, null},
+ {PropertyNames.AcctInfoScriptPath, "scriptPath", null, null},
+
+ {PropertyNames.PwdInfoLastPasswordSet, "pwdLastSet", new FromLdapConverterDelegate(GenericDateTimeFromLdapConverter), null},
+ {PropertyNames.PwdInfoLastBadPasswordAttempt, "badPasswordTime", new FromLdapConverterDelegate(GenericDateTimeFromLdapConverter), null},
+ {PropertyNames.PwdInfoPasswordNotRequired, "ms-DS-UserPasswordNotRequired", new FromLdapConverterDelegate(BoolFromLdapConverter), new ToLdapConverterDelegate(BoolToLdapConverter)},
+ {PropertyNames.PwdInfoPasswordNeverExpires, "msDS-UserDontExpirePassword", new FromLdapConverterDelegate(BoolFromLdapConverter), new ToLdapConverterDelegate(BoolToLdapConverter)},
+ {PropertyNames.PwdInfoCannotChangePassword, "ntSecurityDescriptor", null , new ToLdapConverterDelegate(CannotChangePwdToLdapConverter)},
+ {PropertyNames.PwdInfoAllowReversiblePasswordEncryption, "ms-DS-UserEncryptedTextPasswordAllowed", new FromLdapConverterDelegate(BoolFromLdapConverter), new ToLdapConverterDelegate(BoolToLdapConverter)}
+ };
+
+ //
+ // Query tables
+ //
+
+ // We only list properties we support filtering on in this table. At run-time, if we detect they set a
+ // property that's not listed here, we throw an exception.
+ private static object[,] s_filterPropertiesTableRaw =
+ {
+ // QbeType AD property Converter
+ {typeof(DescriptionFilter), "description", new FilterConverterDelegate(StringConverter)},
+ {typeof(DisplayNameFilter), "displayName", new FilterConverterDelegate(StringConverter)},
+ {typeof(IdentityClaimFilter), "", new FilterConverterDelegate(IdentityClaimConverter)},
+ {typeof(DistinguishedNameFilter), "distinguishedName", new FilterConverterDelegate(StringConverter)},
+ {typeof(GuidFilter), "objectGuid", new FilterConverterDelegate(GuidConverter)},
+ {typeof(UserPrincipalNameFilter), "userPrincipalName", new FilterConverterDelegate(StringConverter)},
+ {typeof(StructuralObjectClassFilter), "objectClass", new FilterConverterDelegate(StringConverter)},
+ {typeof(NameFilter), "name", new FilterConverterDelegate(StringConverter)},
+
+ {typeof(CertificateFilter), "", new FilterConverterDelegate(CertificateConverter)},
+ {typeof(AuthPrincEnabledFilter), "msDS-UserAccountDisabled", new FilterConverterDelegate(AcctDisabledConverter)}, /*##*/
+ {typeof(PermittedWorkstationFilter), "userWorkstations", new FilterConverterDelegate(StringConverter)},
+ {typeof(PermittedLogonTimesFilter), "logonHours", new FilterConverterDelegate(BinaryConverter)},
+ {typeof(ExpirationDateFilter), "accountExpires", new FilterConverterDelegate(ExpirationDateConverter)},
+ {typeof(SmartcardLogonRequiredFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},/*##*/
+ {typeof(DelegationPermittedFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},/*##*/
+ {typeof(HomeDirectoryFilter), "homeDirectory", new FilterConverterDelegate(StringConverter)},
+ {typeof(HomeDriveFilter), "homeDrive", new FilterConverterDelegate(StringConverter)},
+ {typeof(ScriptPathFilter), "scriptPath", new FilterConverterDelegate(StringConverter)},
+ {typeof(PasswordNotRequiredFilter), "ms-DS-UserPasswordNotRequired", new FilterConverterDelegate(DefaultValueBoolConverter)},/*##*/
+ {typeof(PasswordNeverExpiresFilter), "msDS-UserDontExpirePassword", new FilterConverterDelegate(DefaultValueBoolConverter)},/*##*/
+ {typeof(CannotChangePasswordFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},/*##*/
+ {typeof(AllowReversiblePasswordEncryptionFilter), "ms-DS-UserEncryptedTextPasswordAllowed", new FilterConverterDelegate(DefaultValueBoolConverter)},/*##*/
+ {typeof(GivenNameFilter), "givenName", new FilterConverterDelegate(StringConverter)},
+ {typeof(MiddleNameFilter), "middleName", new FilterConverterDelegate(StringConverter)},
+ {typeof(SurnameFilter), "sn", new FilterConverterDelegate(StringConverter)},
+ {typeof(EmailAddressFilter), "mail", new FilterConverterDelegate(StringConverter)},
+ {typeof(VoiceTelephoneNumberFilter), "telephoneNumber", new FilterConverterDelegate(StringConverter)},
+ {typeof(EmployeeIDFilter), "employeeID", new FilterConverterDelegate(StringConverter)},
+ {typeof(GroupIsSecurityGroupFilter), "groupType", new FilterConverterDelegate(GroupTypeConverter)},
+ {typeof(GroupScopeFilter), "groupType", new FilterConverterDelegate(GroupTypeConverter)},
+ {typeof(ServicePrincipalNameFilter), "servicePrincipalName",new FilterConverterDelegate(StringConverter)},
+ {typeof(ExtensionCacheFilter), null ,new FilterConverterDelegate(ExtensionCacheConverter)},
+ {typeof(BadPasswordAttemptFilter), "badPasswordTime",new FilterConverterDelegate(DefaultValutMatchingDateTimeConverter)},
+ {typeof(ExpiredAccountFilter), "accountExpires",new FilterConverterDelegate(MatchingDateTimeConverter)},
+ {typeof(LastLogonTimeFilter), "lastLogonTimestamp",new FilterConverterDelegate(DefaultValutMatchingDateTimeConverter)},
+ {typeof(LockoutTimeFilter), "lockoutTime",new FilterConverterDelegate(DefaultValutMatchingDateTimeConverter)},
+ {typeof(PasswordSetTimeFilter), "pwdLastSet",new FilterConverterDelegate(DefaultValutMatchingDateTimeConverter)}
+ };
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADDNConstraintLinkedAttrSet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADDNConstraintLinkedAttrSet.cs
new file mode 100644
index 0000000000..54341f6687
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADDNConstraintLinkedAttrSet.cs
@@ -0,0 +1,151 @@
+// 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;
+using System.Collections.Generic;
+using System.Collections;
+using System.Diagnostics;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // <ReferencesCritical Name="Type ADDNLinkedAttrSet" Ring="1" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class ADDNConstraintLinkedAttrSet : ADDNLinkedAttrSet
+ {
+ ///
+ /// <summary>
+ /// Result validator - Delegate function signature.
+ ///
+ /// The result validator should return true if the result is valid
+ /// and false if the result is invalid and needs to be skipped.
+ /// </summary>
+ /// <param name="resultDirEntry">
+ /// Directory entry object of the result.
+ /// NOTE: ADDNLinkedAttrSet class is responsible for disposing this DirectoryEntry object.
+ /// </param>
+ /// <returns>
+ /// True - if the result is valid (further processing with the result will happen in this case)
+ /// False - If the result is invalid. In this case the result will skipped.
+ /// </returns>
+ ///
+ internal delegate bool ResultValidator(dSPropertyCollection resultPropCollection);
+
+ internal enum ConstraintType
+ {
+ ContainerStringMatch = 0, // match = the objects distinguishedName begins with the string supplied as constraintData, i.e. the object is under that container.
+ ResultValidatorDelegateMatch = 1, //match = the result object will be passed as an argument to the
+ //function supplied as constraintData and it should return true.
+ }
+
+ internal ADDNConstraintLinkedAttrSet(
+ ConstraintType constraint,
+ object constraintData,
+ string groupDN,
+ IEnumerable[] members,
+ string primaryGroupDN,
+ DirectorySearcher queryMembersSearcher,
+ bool recursive,
+ ADStoreCtx storeCtx) : base(groupDN, members, primaryGroupDN, queryMembersSearcher, recursive, storeCtx)
+ {
+ Debug.Assert(constraintData != null);
+
+ _constraint = constraint;
+ _constraintData = constraintData;
+ }
+
+ internal ADDNConstraintLinkedAttrSet(
+ ConstraintType constraint,
+ object constraintData,
+ string groupDN,
+ DirectorySearcher[] membersSearcher,
+ string primaryGroupDN,
+ DirectorySearcher primaryGroupMembersSearcher,
+ bool recursive,
+ ADStoreCtx storeCtx)
+ : base(groupDN, membersSearcher, primaryGroupDN, primaryGroupMembersSearcher, recursive, storeCtx)
+ {
+ Debug.Assert(constraintData != null);
+
+ _constraint = constraint;
+ _constraintData = constraintData;
+ }
+
+ private ConstraintType _constraint;
+ private object _constraintData;
+
+ override internal bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNConstraintLinkedAttrSet", "Entering MoveNext");
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNConstraintLinkedAttrSet", "Filter {0}", _constraintData);
+ bool match = false;
+ string dn = "NotSet";
+
+ if (!base.MoveNext())
+ return false;
+ else
+ {
+ while (!match)
+ {
+ if (null == this.current)
+ return false;
+
+ switch (_constraint)
+ {
+ case ConstraintType.ContainerStringMatch:
+
+ if (this.current is SearchResult)
+ dn = ((SearchResult)this.current).Properties["distinguishedName"][0].ToString();
+ else
+ dn = ((DirectoryEntry)this.current).Properties["distinguishedName"].Value.ToString();
+
+ if (dn.EndsWith((string)_constraintData, StringComparison.Ordinal))
+ match = true;
+
+ break;
+ case ConstraintType.ResultValidatorDelegateMatch:
+ {
+ ResultValidator resultValidator = _constraintData as ResultValidator;
+ if (resultValidator != null)
+ {
+ dSPropertyCollection resultPropCollection = null;
+ if (this.current is SearchResult)
+ {
+ resultPropCollection = new dSPropertyCollection(((SearchResult)this.current).Properties);
+ }
+ else
+ {
+ resultPropCollection = new dSPropertyCollection(((DirectoryEntry)this.current).Properties);
+ }
+ match = resultValidator.Invoke(resultPropCollection);
+ }
+ else
+ {
+ Debug.Fail("ADStoreCtx.ADDNConstraintLinkedAttrSet: Invalid constraint data. Expected: object of type ResultValidator");
+ }
+ break;
+ }
+ default:
+ Debug.Fail("ADStoreCtx.ADDNConstraintLinkedAttrSet: fell off end looking for " + _constraint.ToString());
+ break;
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNConstraintLinkedAttrSet", "Found {0} Match {1}", dn, match.ToString());
+
+ if (!match)
+ if (!this.MoveNext())
+ return false;
+ }
+
+ return match;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADDNLinkedAttrSet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADDNLinkedAttrSet.cs
new file mode 100644
index 0000000000..a651c7fa87
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADDNLinkedAttrSet.cs
@@ -0,0 +1,1425 @@
+// 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;
+using System.Collections.Generic;
+using System.Collections;
+using System.Diagnostics;
+using System.Security.Principal;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class ADDNLinkedAttrSet : BookmarkableResultSet
+ {
+ // This class can be used to either enumerate the members of a group, or the groups
+ // to which a principal belongs. If being used to enumerate the members of a group:
+ // * groupDN --- the DN of the group we're enumerating
+ // * members --- array of enumerators containing the DNs of the members of the group we're enumerating (the "member" attribute)
+ // * primaryGroupDN --- should be null
+ // * recursive --- whether or not to recursively enumerate group membership
+ //
+ // If being used to enumerate the groups to which a principal belongs:
+ // * groupDN --- the DN of the principal (i.e., the user)
+ // * members --- the DNs of the groups to which that principal belongs (e.g, the "memberOf" attribute)
+ // * primaryGroupDN --- the DN of the principal's primary group (constructed from the "primaryGroupID" attribute)
+ // * recursive --- should be false
+ //
+ // Note that the variables in this class are generally named in accord with the "enumerating the members
+ // of a group" case.
+ //
+ // It is assumed that recursive enumeration will only be performed for the "enumerating the members of a group"
+ // case, not the "groups to which a principal belongs" case, thus, this.recursive == true implies the former
+ // (but this.recursive == false could imply either case).
+
+ internal ADDNLinkedAttrSet(
+ string groupDN,
+ IEnumerable[] members,
+ string primaryGroupDN,
+ DirectorySearcher primaryGroupMembersSearcher,
+ bool recursive,
+ ADStoreCtx storeCtx)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "ADDNLinkedAttrSet: groupDN={0}, primaryGroupDN={1}, recursive={2}, PG queryFilter={3}, PG queryBase={4}",
+ groupDN,
+ (primaryGroupDN != null ? primaryGroupDN : "NULL"),
+ recursive,
+ (primaryGroupMembersSearcher != null ? primaryGroupMembersSearcher.Filter : "NULL"),
+ (primaryGroupMembersSearcher != null ? primaryGroupMembersSearcher.SearchRoot.Path : "NULL"));
+
+ _groupsVisited.Add(groupDN); // so we don't revisit it
+ _recursive = recursive;
+ _storeCtx = storeCtx;
+ _originalStoreCtx = storeCtx;
+
+ if (null != members)
+ {
+ foreach (IEnumerable enumerator in members)
+ {
+ _membersQueue.Enqueue(enumerator);
+ _originalMembers.Enqueue(enumerator);
+ }
+ }
+
+ _members = null;
+
+ _currentMembersSearcher = null;
+ _primaryGroupDN = primaryGroupDN;
+ if (primaryGroupDN == null)
+ _returnedPrimaryGroup = true; // so we don't bother trying to return the primary group
+
+ _primaryGroupMembersSearcher = primaryGroupMembersSearcher;
+
+ _expansionMode = ExpansionMode.Enum;
+ _originalExpansionMode = _expansionMode;
+ }
+
+ internal ADDNLinkedAttrSet(
+ string groupDN,
+ DirectorySearcher[] membersSearcher,
+ string primaryGroupDN,
+ DirectorySearcher primaryGroupMembersSearcher,
+ bool recursive,
+ ADStoreCtx storeCtx)
+
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "ADDNLinkedAttrSet: groupDN={0}, primaryGroupDN={1}, recursive={2}, M queryFilter={3}, M queryBase={4}, PG queryFilter={5}, PG queryBase={6}",
+ groupDN,
+ (primaryGroupDN != null ? primaryGroupDN : "NULL"),
+ recursive,
+ (membersSearcher != null ? membersSearcher[0].Filter : "NULL"),
+ (membersSearcher != null ? membersSearcher[0].SearchRoot.Path : "NULL"),
+ (primaryGroupMembersSearcher != null ? primaryGroupMembersSearcher.Filter : "NULL"),
+ (primaryGroupMembersSearcher != null ? primaryGroupMembersSearcher.SearchRoot.Path : "NULL"));
+
+ _groupsVisited.Add(groupDN); // so we don't revisit it
+ _recursive = recursive;
+ _storeCtx = storeCtx;
+ _originalStoreCtx = storeCtx;
+
+ _members = null;
+ _originalMembers = null;
+ _membersEnum = null;
+
+ _primaryGroupDN = primaryGroupDN;
+ if (primaryGroupDN == null)
+ _returnedPrimaryGroup = true; // so we don't bother trying to return the primary group
+
+ if (null != membersSearcher)
+ {
+ foreach (DirectorySearcher ds in membersSearcher)
+ {
+ _memberSearchersQueue.Enqueue(ds);
+ _memberSearchersQueueOriginal.Enqueue(ds);
+ }
+ }
+
+ _currentMembersSearcher = null;
+
+ _primaryGroupMembersSearcher = primaryGroupMembersSearcher;
+
+ _expansionMode = ExpansionMode.ASQ;
+ _originalExpansionMode = _expansionMode;
+ }
+
+ // Return the principal we're positioned at as a Principal object.
+ // Need to use our StoreCtx's GetAsPrincipal to convert the native object to a Principal
+ override internal object CurrentAsPrincipal
+ {
+ get
+ {
+ if (this.current != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "CurrentAsPrincipal: using current");
+ if (this.current is DirectoryEntry)
+ return ADUtils.DirectoryEntryAsPrincipal((DirectoryEntry)this.current, _storeCtx);
+ else
+ {
+ return ADUtils.SearchResultAsPrincipal((SearchResult)this.current, _storeCtx, null);
+ }
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "CurrentAsPrincipal: using currentForeignPrincipal");
+ Debug.Assert(_currentForeignPrincipal != null);
+ return _currentForeignPrincipal;
+ }
+ }
+ }
+
+ // Advance the enumerator to the next principal in the result set, pulling in additional pages
+ // of results (or ranges of attribute values) as needed.
+ // Returns true if successful, false if no more results to return.
+ override internal bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Entering MoveNext");
+
+ _atBeginning = false;
+
+ bool needToRetry;
+ bool f = false;
+
+ do
+ {
+ needToRetry = false;
+ // reset our found state. If we are restarting the loop we don't have a current principal yet.
+ f = false;
+
+ if (!_returnedPrimaryGroup)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNext: trying PrimaryGroup DN");
+ f = MoveNextPrimaryGroupDN();
+ }
+
+ if (!f)
+ {
+ if (_expansionMode == ExpansionMode.ASQ)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNext: trying member searcher");
+ f = MoveNextMemberSearcher();
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNext: trying member enum");
+ f = MoveNextMemberEnum();
+ }
+ }
+
+ if (!f)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNext: trying foreign");
+ f = MoveNextForeign(ref needToRetry);
+ }
+
+ if (!f)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNext: trying primary group search");
+ f = MoveNextQueryPrimaryGroupMember();
+ }
+ }
+ while (needToRetry);
+
+ return f;
+ }
+
+ private bool MoveNextPrimaryGroupDN()
+ {
+ // Do the special primary group ID processing if we haven't yet returned the primary group.
+ Debug.Assert(_primaryGroupDN != null);
+
+ this.current = SDSUtils.BuildDirectoryEntry(
+ BuildPathFromDN(_primaryGroupDN),
+ _storeCtx.Credentials,
+ _storeCtx.AuthTypes);
+
+ _storeCtx.InitializeNewDirectoryOptions((DirectoryEntry)this.current);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberSearcher: returning primary group {0}", ((DirectoryEntry)this.current).Path);
+
+ _currentForeignDE = null;
+ _currentForeignPrincipal = null;
+
+ _returnedPrimaryGroup = true;
+ return true;
+ }
+
+ private bool GetNextSearchResult()
+ {
+ bool memberFound = false;
+
+ do
+ {
+ if (_currentMembersSearcher == null)
+ {
+ Debug.Assert(_memberSearchersQueue != null);
+
+ if (_memberSearchersQueue.Count == 0)
+ {
+ // We are out of searchers in the queue.
+ return false;
+ }
+ else
+ {
+ // Remove the next searcher from the queue and place it in the current search variable.
+ _currentMembersSearcher = _memberSearchersQueue.Dequeue();
+ _memberSearchResults = _currentMembersSearcher.FindAll();
+ Debug.Assert(_memberSearchResults != null);
+ _memberSearchResultsEnumerator = _memberSearchResults.GetEnumerator();
+ }
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextQueryMember: have a searcher");
+
+ memberFound = _memberSearchResultsEnumerator.MoveNext();
+
+ // The search is complete.
+ // Dipose the searcher and search results.
+ if (!memberFound)
+ {
+ _currentMembersSearcher.Dispose();
+ _currentMembersSearcher = null;
+ _memberSearchResults.Dispose();
+ _memberSearchResults = null;
+ }
+ } while (!memberFound);
+
+ return memberFound;
+ }
+
+ private bool MoveNextMemberSearcher()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Entering MoveNextMemberSearcher");
+
+ bool needToRetry = false;
+ bool f = false;
+
+ do
+ {
+ f = GetNextSearchResult();
+ needToRetry = false;
+
+ if (f)
+ {
+ SearchResult currentSR = (SearchResult)_memberSearchResultsEnumerator.Current;
+
+ // Got a member from this group (or, got a group of which we're a member).
+ // Create a DirectoryEntry for it.
+ string memberDN = (string)currentSR.Properties["distinguishedName"][0];
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberSearcher: got a value from the enumerator: {0}", memberDN);
+
+ // Make sure the member is a principal
+ if ((!ADUtils.IsOfObjectClass(currentSR, "group")) &&
+ (!ADUtils.IsOfObjectClass(currentSR, "user")) && // includes computer as well
+ (!ADUtils.IsOfObjectClass(currentSR, "foreignSecurityPrincipal")))
+ {
+ // We found a member, but it's not a principal type. Skip it.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberSearcher: not a principal, skipping");
+ needToRetry = true;
+ }
+ // If we're processing recursively, and the member is a group, we DON'T return it,
+ // but rather treat it as something to recursively visit later
+ // (unless we've already visited the group previously)
+ else if (_recursive && ADUtils.IsOfObjectClass(currentSR, "group"))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberSearcher: adding to groupsToVisit");
+
+ if (!_groupsVisited.Contains(memberDN) && !_groupsToVisit.Contains(memberDN))
+ _groupsToVisit.Add(memberDN);
+
+ // and go on to the next member....
+ needToRetry = true;
+ }
+ else if (_recursive && ADUtils.IsOfObjectClass(currentSR, "foreignSecurityPrincipal"))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberSearcher: foreign principal, adding to foreignMembers");
+
+ // If we haven't seen this FPO yet then add it to the seen user database.
+ if (!_usersVisited.ContainsKey(currentSR.Properties["distinguishedName"][0].ToString()))
+ {
+ // The FPO might represent a group, in which case we should recursively enumerate its
+ // membership. So save it off for later processing.
+ _foreignMembersCurrentGroup.Add(currentSR.GetDirectoryEntry());
+ _usersVisited.Add(currentSR.Properties["distinguishedName"][0].ToString(), true);
+ }
+
+ // and go on to the next member....
+ needToRetry = true;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberSearcher: using as current");
+
+ // Check to see if we have already seen this user during the enumeration
+ // If so then move on to the next user. If not then return it as current.
+ if (!_usersVisited.ContainsKey(currentSR.Properties["distinguishedName"][0].ToString()))
+ {
+ this.current = currentSR;
+ _currentForeignDE = null;
+ _currentForeignPrincipal = null;
+ _usersVisited.Add(currentSR.Properties["distinguishedName"][0].ToString(), true);
+ }
+ else
+ {
+ needToRetry = true;
+ }
+ }
+ }
+ else
+ {
+ // We reached the end of this group's membership. If we're not processing recursively,
+ // we're done. Otherwise, go on to the next group to visit.
+ // First create a DE that points to the group we want to expand, Using that as a search root run
+ // an ASQ search against member and and start enumerting those results.
+ if (_recursive)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "MoveNextMemberSearcher: recursive processing, groupsToVisit={0}",
+ _groupsToVisit.Count);
+
+ if (_groupsToVisit.Count > 0)
+ {
+ // Pull off the next group to visit
+ string groupDN = _groupsToVisit[0];
+ _groupsToVisit.RemoveAt(0);
+ _groupsVisited.Add(groupDN);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberSearcher: recursively processing {0}", groupDN);
+
+ // get the membership of this new group
+ DirectoryEntry groupDE = SDSUtils.BuildDirectoryEntry(BuildPathFromDN(groupDN), _storeCtx.Credentials, _storeCtx.AuthTypes);
+
+ _storeCtx.InitializeNewDirectoryOptions(groupDE);
+
+ // Queue up a searcher for the new group expansion.
+ DirectorySearcher ds = SDSUtils.ConstructSearcher(groupDE);
+ ds.Filter = "(objectClass=*)";
+ ds.SearchScope = SearchScope.Base;
+ ds.AttributeScopeQuery = "member";
+ ds.CacheResults = false;
+
+ _memberSearchersQueue.Enqueue(ds);
+
+ // and go on to the first member of this new group.
+ needToRetry = true;
+ }
+ }
+ }
+ }
+ while (needToRetry);
+
+ return f;
+ }
+
+ private bool GetNextEnum()
+ {
+ bool memberFound = false;
+
+ do
+ {
+ if (null == _members)
+ {
+ if (_membersQueue.Count == 0)
+ {
+ return false;
+ }
+
+ _members = _membersQueue.Dequeue();
+ _membersEnum = _members.GetEnumerator();
+ }
+
+ memberFound = _membersEnum.MoveNext();
+
+ if (!memberFound)
+ {
+ IDisposable disposableMembers = _members as IDisposable;
+ if (disposableMembers != null)
+ {
+ disposableMembers.Dispose();
+ }
+ IDisposable disposableMembersEnum = _membersEnum as IDisposable;
+ if (disposableMembersEnum != null)
+ {
+ disposableMembersEnum.Dispose();
+ }
+ _members = null;
+ _membersEnum = null;
+ }
+ } while (!memberFound);
+
+ return memberFound;
+ }
+
+ private bool MoveNextMemberEnum()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Entering MoveNextMemberEnum");
+
+ bool needToRetry = false;
+ bool disposeMemberDE = false;
+ bool f;
+
+ do
+ {
+ f = GetNextEnum();
+ needToRetry = false;
+ disposeMemberDE = false;
+
+ if (f)
+ {
+ DirectoryEntry memberDE = null;
+ try
+ {
+ // Got a member from this group (or, got a group of which we're a member).
+ // Create a DirectoryEntry for it.
+ string memberDN = (string)_membersEnum.Current;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberEnum: got a value from the enumerator: {0}", memberDN);
+
+ memberDE = SDSUtils.BuildDirectoryEntry(
+ BuildPathFromDN(memberDN),
+ _storeCtx.Credentials,
+ _storeCtx.AuthTypes);
+
+ _storeCtx.InitializeNewDirectoryOptions(memberDE);
+
+ _storeCtx.LoadDirectoryEntryAttributes(memberDE);
+
+ // Make sure the member is a principal
+ if ((!ADUtils.IsOfObjectClass(memberDE, "group")) &&
+ (!ADUtils.IsOfObjectClass(memberDE, "user")) && // includes computer as well
+ (!ADUtils.IsOfObjectClass(memberDE, "foreignSecurityPrincipal")))
+ {
+ // We found a member, but it's not a principal type. Skip it.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberEnum: not a principal, skipping");
+ needToRetry = true;
+ disposeMemberDE = true; //Since member is not principal we don't return it. So mark it for dispose.
+ }
+ // If we're processing recursively, and the member is a group, we DON'T return it,
+ // but rather treat it as something to recursively visit later
+ // (unless we've already visited the group previously)
+ else if (_recursive && ADUtils.IsOfObjectClass(memberDE, "group"))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberEnum: adding to groupsToVisit");
+
+ if (!_groupsVisited.Contains(memberDN) && !_groupsToVisit.Contains(memberDN))
+ _groupsToVisit.Add(memberDN);
+
+ // and go on to the next member....
+ needToRetry = true;
+ disposeMemberDE = true; //Since recursive is set to true, we do not return groups. So mark it for dispose.
+ }
+ else if (_recursive && ADUtils.IsOfObjectClass(memberDE, "foreignSecurityPrincipal"))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberEnum: foreign principal, adding to foreignMembers");
+
+ // If we haven't seen this FPO yet then add it to the seen user database.
+ if (!_usersVisited.ContainsKey(memberDE.Properties["distinguishedName"][0].ToString()))
+ {
+ // The FPO might represent a group, in which case we should recursively enumerate its
+ // membership. So save it off for later processing.
+ _foreignMembersCurrentGroup.Add(memberDE);
+ _usersVisited.Add(memberDE.Properties["distinguishedName"][0].ToString(), true);
+ disposeMemberDE = false; //We store the FPO DirectoryEntry objects for further processing. So do NOT dispose it.
+ }
+
+ // and go on to the next member....
+ needToRetry = true;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberEnum: using as current");
+
+ // Check to see if we have already seen this user during the enumeration
+ // If so then move on to the next user. If not then return it as current.
+ if (!_usersVisited.ContainsKey(memberDE.Properties["distinguishedName"][0].ToString()))
+ {
+ this.current = memberDE;
+ _currentForeignDE = null;
+ _currentForeignPrincipal = null;
+ _usersVisited.Add(memberDE.Properties["distinguishedName"][0].ToString(), true);
+ disposeMemberDE = false; //memberDE will be set in the Principal object we return. So do NOT dispose it.
+ }
+ else
+ {
+ needToRetry = true;
+ }
+ }
+ }
+ finally
+ {
+ if (disposeMemberDE && memberDE != null)
+ {
+ //This means the constructed member is not used in the new principal
+ memberDE.Dispose();
+ }
+ }
+ }
+ else
+ {
+ // We reached the end of this group's membership. If we're not processing recursively,
+ // we're done. Otherwise, go on to the next group to visit.
+ if (_recursive)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "MoveNextLocal: recursive processing, groupsToVisit={0}",
+ _groupsToVisit.Count);
+
+ if (_groupsToVisit.Count > 0)
+ {
+ // Pull off the next group to visit
+ string groupDN = _groupsToVisit[0];
+ _groupsToVisit.RemoveAt(0);
+ _groupsVisited.Add(groupDN);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextMemberEnum: recursively processing {0}", groupDN);
+
+ // get the membership of this new group
+ DirectoryEntry groupDE = SDSUtils.BuildDirectoryEntry(
+ BuildPathFromDN(groupDN),
+ _storeCtx.Credentials,
+ _storeCtx.AuthTypes);
+
+ _storeCtx.InitializeNewDirectoryOptions(groupDE);
+
+ // set up for the next round of enumeration
+ //Here a new DirectoryEntry object is created and passed
+ //to RangeRetriever object. Hence, configure
+ //RangeRetriever to dispose the DirEntry on its dispose.
+ _membersQueue.Enqueue(new RangeRetriever(groupDE, "member", true));
+
+ // and go on to the first member of this new group....
+ needToRetry = true;
+ }
+ }
+ }
+ }
+ while (needToRetry);
+
+ return f;
+ }
+
+ private void TranslateForeignMembers()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADDNLinkedAttrSet", "TranslateForeignMembers: Translating foreign members");
+
+ List<Byte[]> sidList = new List<Byte[]>(_foreignMembersCurrentGroup.Count);
+
+ // Foreach foreign principal retrive the sid.
+ // If the SID is for a fake object we have to track it seperately. If we were attempt to translate it
+ // it would fail and not be returned and we would lose it.
+ // Once we have a list of sids then translate them against the target store in one call.
+ foreach (DirectoryEntry de in _foreignMembersCurrentGroup)
+ {
+ // Get the SID of the foreign principal
+ if (de.Properties["objectSid"].Count == 0)
+ {
+ throw new PrincipalOperationException(StringResources.ADStoreCtxCantRetrieveObjectSidForCrossStore);
+ }
+
+ Byte[] sid = (Byte[])de.Properties["objectSid"].Value;
+
+ // What type of SID is it?
+ SidType sidType = Utils.ClassifySID(sid);
+
+ if (sidType == SidType.FakeObject)
+ {
+ //Add the foreign member DirectoryEntry to fakePrincipalMembers list for further translation
+ //This de will be disposed after completing the translation by another code block.
+ _fakePrincipalMembers.Add(de);
+
+ // It's a FPO for something like NT AUTHORITY\NETWORK SERVICE.
+ // There's no real store object corresponding to this FPO, so
+ // fake a Principal.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "TranslateForeignMembers: fake principal, SID={0}",
+ Utils.ByteArrayToString(sid));
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "TranslateForeignMembers: standard principal, SID={0}",
+ Utils.ByteArrayToString(sid));
+
+ sidList.Add(sid);
+ //We do NOT need the Foreign member DirectoryEntry object once it has been translated and added to sidList.
+ //So disposing it off now
+ de.Dispose();
+ }
+ }
+
+ // This call will perform a bulk sid translate to the name + issuer domain.
+ _foreignMembersToReturn = new SidList(sidList, _storeCtx.DnsHostName, _storeCtx.Credentials);
+
+ // We have translated the sids so clear the group now.
+ _foreignMembersCurrentGroup.Clear();
+ }
+
+ private bool MoveNextForeign(ref bool outerNeedToRetry)
+ {
+ outerNeedToRetry = false;
+ bool needToRetry;
+ Principal foreignPrincipal;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Entering MoveNextForeign");
+
+ do
+ {
+ needToRetry = false;
+
+ if (_foreignMembersCurrentGroup.Count > 0)
+ {
+ TranslateForeignMembers();
+ }
+
+ if (_fakePrincipalMembers.Count > 0)
+ {
+ foreignPrincipal = _storeCtx.ConstructFakePrincipalFromSID((Byte[])_fakePrincipalMembers[0].Properties["objectSid"].Value);
+ _fakePrincipalMembers[0].Dispose();
+ _fakePrincipalMembers.RemoveAt(0);
+ }
+ else if ((_foreignMembersToReturn != null) && (_foreignMembersToReturn.Length > 0))
+ {
+ StoreCtx foreignStoreCtx;
+
+ SidListEntry foreignSid = _foreignMembersToReturn[0];
+
+ // sidIssuerName is null only if SID was not resolved
+ // return a unknown principal back
+ if (null == foreignSid.sidIssuerName)
+ {
+ // create and return the unknown principal if it is not yet present in usersVisited
+ if (!_usersVisited.ContainsKey(foreignSid.name))
+ {
+ byte[] sid = Utils.ConvertNativeSidToByteArray(foreignSid.pSid);
+ UnknownPrincipal unknownPrincipal = UnknownPrincipal.CreateUnknownPrincipal(_storeCtx.OwningContext, sid, foreignSid.name);
+ _usersVisited.Add(foreignSid.name, true);
+ this.current = null;
+ _currentForeignDE = null;
+ _currentForeignPrincipal = unknownPrincipal;
+ // remove the current member
+ _foreignMembersToReturn.RemoveAt(0);
+ return true;
+ }
+
+ // remove the current member
+ _foreignMembersToReturn.RemoveAt(0);
+
+ needToRetry = true;
+ continue;
+ }
+
+ SidType sidType = Utils.ClassifySID(foreignSid.pSid);
+
+ if (sidType == SidType.RealObjectFakeDomain)
+ {
+ // This is a BUILTIN object. It's a real object on the store we're connected to, but LookupSid
+ // will tell us it's a member of the BUILTIN domain. Resolve it as a principal on our store.
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADDNLinkedAttrSet", "MoveNextForeign: builtin principal");
+ foreignStoreCtx = _storeCtx;
+ }
+ else
+ {
+ ContextOptions remoteOptions = DefaultContextOptions.ADDefaultContextOption;
+
+#if USE_CTX_CACHE
+ PrincipalContext remoteCtx = SDSCache.Domain.GetContext(foreignSid.sidIssuerName, _storeCtx.Credentials, remoteOptions);
+#else
+ PrincipalContext remoteCtx = new PrincipalContext(
+ ContextType.Domain,
+ foreignSid.sidIssuerName,
+ null,
+ (this.storeCtx.Credentials != null ? this.storeCtx.Credentials.UserName : null),
+ (this.storeCtx.Credentials != null ? storeCtx.storeCtx.Credentials.Password : null),
+ remoteOptions);
+
+#endif
+ foreignStoreCtx = remoteCtx.QueryCtx;
+ }
+
+ foreignPrincipal = foreignStoreCtx.FindPrincipalByIdentRef(
+ typeof(Principal),
+ UrnScheme.SidScheme,
+ (new SecurityIdentifier(Utils.ConvertNativeSidToByteArray(_foreignMembersToReturn[0].pSid), 0)).ToString(),
+ DateTime.UtcNow);
+
+ if (null == foreignPrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADDNLinkedAttrSet", "MoveNextForeign: no matching principal");
+ throw new PrincipalOperationException(StringResources.ADStoreCtxFailedFindCrossStoreTarget);
+ }
+
+ _foreignMembersToReturn.RemoveAt(0);
+ }
+ else
+ {
+ // We don't have any more foreign principals to return so start with the foreign groups
+ if (_foreignGroups.Count > 0)
+ {
+ outerNeedToRetry = true;
+
+ // Determine the domainFunctionalityMode of the foreign domain. If they are W2k or not a global group then we can't use ASQ.
+ if (_foreignGroups[0].Context.ServerInformation.OsVersion == DomainControllerMode.Win2k ||
+ _foreignGroups[0].GroupScope != GroupScope.Global)
+ {
+ _expansionMode = ExpansionMode.Enum;
+ return ExpandForeignGroupEnumerator();
+ }
+ else
+ {
+ _expansionMode = ExpansionMode.ASQ;
+ return ExpandForeignGroupSearcher();
+ }
+ }
+ else
+ {
+ // We are done with foreign principals and groups..
+ return false;
+ }
+ }
+
+ if (foreignPrincipal is GroupPrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextForeign: foreign member is a group");
+
+ // A group, need to recursively expand it (unless it's a fake group,
+ // in which case it is by definition empty and so contains nothing to expand, or unless
+ // we've already or will visit it).
+ // Postpone to later.
+ if (!foreignPrincipal.fakePrincipal)
+ {
+ string groupDN = (string)((DirectoryEntry)foreignPrincipal.UnderlyingObject).Properties["distinguishedName"].Value;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "MoveNextForeign: not a fake group, adding {0} to foreignGroups",
+ groupDN);
+
+ if (!_groupsVisited.Contains(groupDN) && !_groupsToVisit.Contains(groupDN))
+ {
+ _foreignGroups.Add((GroupPrincipal)foreignPrincipal);
+ }
+ else
+ {
+ foreignPrincipal.Dispose();
+ }
+ }
+
+ needToRetry = true;
+ continue;
+ }
+ else
+ {
+ // Not a group, nothing to recursively expand, so just return it.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextForeign: using as currentForeignDE/currentForeignPrincipal");
+
+ DirectoryEntry foreignDE = (DirectoryEntry)foreignPrincipal.GetUnderlyingObject();
+
+ _storeCtx.LoadDirectoryEntryAttributes(foreignDE);
+
+ if (!_usersVisited.ContainsKey(foreignDE.Properties["distinguishedName"][0].ToString()))
+ {
+ _usersVisited.Add(foreignDE.Properties["distinguishedName"][0].ToString(), true);
+ this.current = null;
+ _currentForeignDE = null;
+ _currentForeignPrincipal = foreignPrincipal;
+ return true;
+ }
+ else
+ {
+ foreignPrincipal.Dispose();
+ }
+
+ needToRetry = true;
+ continue;
+ }
+ }
+ while (needToRetry);
+
+ return false;
+ }
+
+ private bool ExpandForeignGroupEnumerator()
+ {
+ Debug.Assert(_recursive == true);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "ExpandForeignGroupEnumerator: there are {0} foreignGroups",
+ _foreignGroups.Count);
+
+ GroupPrincipal foreignGroup = _foreignGroups[0];
+ _foreignGroups.RemoveAt(0);
+
+ // Since members of AD groups must be AD objects
+ Debug.Assert(foreignGroup.Context.QueryCtx is ADStoreCtx);
+ Debug.Assert(foreignGroup.UnderlyingObject is DirectoryEntry);
+ Debug.Assert(((DirectoryEntry)foreignGroup.UnderlyingObject).Path.StartsWith("LDAP:", StringComparison.Ordinal));
+
+ _storeCtx = (ADStoreCtx)foreignGroup.Context.QueryCtx;
+
+ //Here the foreignGroup object is removed from the foreignGroups collection.
+ //and not used anymore. Hence, configure RangeRetriever to dispose the DirEntry on its dispose.
+ _membersQueue.Enqueue(new RangeRetriever((DirectoryEntry)foreignGroup.UnderlyingObject, "member", true));
+
+ string groupDN = (string)((DirectoryEntry)foreignGroup.UnderlyingObject).Properties["distinguishedName"].Value;
+ _groupsVisited.Add(groupDN);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "ExpandForeignGroupEnumerator: recursively processing {0}", groupDN);
+
+ return true;
+ }
+
+ private bool ExpandForeignGroupSearcher()
+ {
+ Debug.Assert(_recursive == true);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "ExpandForeignGroupSearcher: there are {0} foreignGroups",
+ _foreignGroups.Count);
+
+ GroupPrincipal foreignGroup = _foreignGroups[0];
+ _foreignGroups.RemoveAt(0);
+
+ // Since members of AD groups must be AD objects
+ Debug.Assert(foreignGroup.Context.QueryCtx is ADStoreCtx);
+ Debug.Assert(foreignGroup.UnderlyingObject is DirectoryEntry);
+ Debug.Assert(((DirectoryEntry)foreignGroup.UnderlyingObject).Path.StartsWith("LDAP:", StringComparison.Ordinal));
+
+ _storeCtx = (ADStoreCtx)foreignGroup.Context.QueryCtx;
+
+ // Queue up a searcher for the new group expansion.
+ DirectorySearcher ds = SDSUtils.ConstructSearcher((DirectoryEntry)foreignGroup.UnderlyingObject);
+ ds.Filter = "(objectClass=*)";
+ ds.SearchScope = SearchScope.Base;
+ ds.AttributeScopeQuery = "member";
+ ds.CacheResults = false;
+
+ _memberSearchersQueue.Enqueue(ds);
+
+ string groupDN = (string)((DirectoryEntry)foreignGroup.UnderlyingObject).Properties["distinguishedName"].Value;
+ _groupsVisited.Add(groupDN);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "ExpandForeignGroupSearcher: recursively processing {0}", groupDN);
+
+ return true;
+ }
+
+ private bool MoveNextQueryPrimaryGroupMember()
+ {
+ bool f = false;
+
+ if (_primaryGroupMembersSearcher != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextQueryMember: have a searcher");
+
+ if (_queryMembersResults == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "MoveNextQueryMember: issuing query");
+
+ _queryMembersResults = _primaryGroupMembersSearcher.FindAll();
+
+ Debug.Assert(_queryMembersResults != null);
+
+ _queryMembersResultEnumerator = _queryMembersResults.GetEnumerator();
+ }
+
+ f = _queryMembersResultEnumerator.MoveNext();
+
+ if (f)
+ {
+ this.current = (SearchResult)_queryMembersResultEnumerator.Current;
+ Debug.Assert(this.current != null);
+
+ _currentForeignDE = null;
+ _currentForeignPrincipal = null;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADDNLinkedAttrSet",
+ "MoveNextQueryMember: got a result, using as current {0}",
+ ((SearchResult)this.current).Path);
+ }
+ }
+
+ return f;
+ }
+
+ // Resets the enumerator to before the first result in the set. This potentially can be an expensive
+ // operation, e.g., if doing a paged search, may need to re-retrieve the first page of results.
+ // As a special case, if the ResultSet is already at the very beginning, this is guaranteed to be
+ // a no-op.
+ override internal void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Reset");
+
+ if (!_atBeginning)
+ {
+ _usersVisited.Clear();
+ _groupsToVisit.Clear();
+ string originalGroupDN = _groupsVisited[0];
+ _groupsVisited.Clear();
+ _groupsVisited.Add(originalGroupDN);
+
+ // clear the current enumerator
+ _members = null;
+ _membersEnum = null;
+
+ // replace all items in the queue with the originals and reset them.
+ if (null != _originalMembers)
+ {
+ _membersQueue.Clear();
+ foreach (IEnumerable ie in _originalMembers)
+ {
+ _membersQueue.Enqueue(ie);
+ IEnumerator enumerator = ie.GetEnumerator();
+ enumerator.Reset();
+ }
+ }
+
+ _expansionMode = _originalExpansionMode;
+
+ _storeCtx = _originalStoreCtx;
+
+ this.current = null;
+ if (_primaryGroupDN != null)
+ _returnedPrimaryGroup = false;
+
+ _foreignMembersCurrentGroup.Clear();
+ _fakePrincipalMembers.Clear();
+
+ if (null != _foreignMembersToReturn)
+ _foreignMembersToReturn.Clear();
+
+ _currentForeignPrincipal = null;
+ _currentForeignDE = null;
+
+ _foreignGroups.Clear();
+
+ _queryMembersResultEnumerator = null;
+ if (_queryMembersResults != null)
+ {
+ _queryMembersResults.Dispose();
+ _queryMembersResults = null;
+ }
+
+ if (null != _currentMembersSearcher)
+ {
+ _currentMembersSearcher.Dispose();
+ _currentMembersSearcher = null;
+ }
+
+ _memberSearchResultsEnumerator = null;
+ if (_memberSearchResults != null)
+ {
+ _memberSearchResults.Dispose();
+ _memberSearchResults = null;
+ }
+
+ if (null != _memberSearchersQueue)
+ {
+ foreach (DirectorySearcher ds in _memberSearchersQueue)
+ {
+ ds.Dispose();
+ }
+
+ _memberSearchersQueue.Clear();
+
+ if (null != _memberSearchersQueueOriginal)
+ {
+ foreach (DirectorySearcher ds in _memberSearchersQueueOriginal)
+ {
+ _memberSearchersQueue.Enqueue(ds);
+ }
+ }
+ }
+
+ _atBeginning = true;
+ }
+ }
+
+ override internal ResultSetBookmark BookmarkAndReset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Bookmarking");
+
+ ADDNLinkedAttrSetBookmark bookmark = new ADDNLinkedAttrSetBookmark();
+
+ bookmark.usersVisited = _usersVisited;
+ _usersVisited = new Dictionary<string, bool>();
+
+ bookmark.groupsToVisit = _groupsToVisit;
+ _groupsToVisit = new List<string>();
+
+ string originalGroupDN = _groupsVisited[0];
+ bookmark.groupsVisited = _groupsVisited;
+ _groupsVisited = new List<string>();
+ _groupsVisited.Add(originalGroupDN);
+
+ bookmark.expansionMode = _expansionMode;
+
+ // bookmark the current enumerators
+ bookmark.members = _members;
+ bookmark.membersEnum = _membersEnum;
+
+ // Clear the current enumerators for reset
+ _members = null;
+ _membersEnum = null;
+
+ // Copy all enumerators in the queue over to the bookmark queue.
+ if (null != _membersQueue)
+ {
+ bookmark.membersQueue = new Queue<IEnumerable>(_membersQueue.Count);
+ foreach (IEnumerable ie in _membersQueue)
+ {
+ bookmark.membersQueue.Enqueue(ie);
+ }
+ }
+
+ // Refill the original queue with the original enumerators and reset them
+ if (null != _membersQueue)
+ {
+ _membersQueue.Clear();
+
+ if (_originalMembers != null)
+ {
+ foreach (IEnumerable ie in _originalMembers)
+ {
+ _membersQueue.Enqueue(ie);
+ IEnumerator enumerator = ie.GetEnumerator();
+ enumerator.Reset();
+ }
+ }
+ }
+
+ bookmark.storeCtx = _storeCtx;
+
+ _expansionMode = _originalExpansionMode;
+
+ if (null != _currentMembersSearcher)
+ {
+ _currentMembersSearcher.Dispose();
+ _currentMembersSearcher = null;
+ }
+
+ _storeCtx = _originalStoreCtx;
+
+ bookmark.current = this.current;
+ bookmark.returnedPrimaryGroup = _returnedPrimaryGroup;
+ this.current = null;
+ if (_primaryGroupDN != null)
+ _returnedPrimaryGroup = false;
+
+ bookmark.foreignMembersCurrentGroup = _foreignMembersCurrentGroup;
+ bookmark.fakePrincipalMembers = _fakePrincipalMembers;
+ bookmark.foreignMembersToReturn = _foreignMembersToReturn;
+ bookmark.currentForeignPrincipal = _currentForeignPrincipal;
+ bookmark.currentForeignDE = _currentForeignDE;
+ _foreignMembersCurrentGroup = new List<DirectoryEntry>();
+ _fakePrincipalMembers = new List<DirectoryEntry>();
+ _currentForeignDE = null;
+
+ bookmark.foreignGroups = _foreignGroups;
+ _foreignGroups = new List<GroupPrincipal>();
+
+ bookmark.queryMembersResults = _queryMembersResults;
+ bookmark.queryMembersResultEnumerator = _queryMembersResultEnumerator;
+ _queryMembersResults = null;
+ _queryMembersResultEnumerator = null;
+
+ bookmark.memberSearchResults = _memberSearchResults;
+ bookmark.memberSearchResultsEnumerator = _memberSearchResultsEnumerator;
+ _memberSearchResults = null;
+ _memberSearchResultsEnumerator = null;
+
+ if (null != _memberSearchersQueue)
+ {
+ bookmark.memberSearcherQueue = new Queue<DirectorySearcher>(_memberSearchersQueue.Count);
+
+ foreach (DirectorySearcher ds in _memberSearchersQueue)
+ {
+ bookmark.memberSearcherQueue.Enqueue(ds);
+ }
+ }
+
+ if (null != _memberSearchersQueueOriginal)
+ {
+ _memberSearchersQueue.Clear();
+
+ foreach (DirectorySearcher ds in _memberSearchersQueueOriginal)
+ {
+ _memberSearchersQueue.Enqueue(ds);
+ }
+ }
+
+ bookmark.atBeginning = _atBeginning;
+ _atBeginning = true;
+
+ return bookmark;
+ }
+
+ override internal void RestoreBookmark(ResultSetBookmark bookmark)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Restoring from bookmark");
+
+ Debug.Assert(bookmark is ADDNLinkedAttrSetBookmark);
+ ADDNLinkedAttrSetBookmark adBookmark = (ADDNLinkedAttrSetBookmark)bookmark;
+
+ _usersVisited = adBookmark.usersVisited;
+ _groupsToVisit = adBookmark.groupsToVisit;
+ _groupsVisited = adBookmark.groupsVisited;
+ _storeCtx = adBookmark.storeCtx;
+ this.current = adBookmark.current;
+ _returnedPrimaryGroup = adBookmark.returnedPrimaryGroup;
+ _foreignMembersCurrentGroup = adBookmark.foreignMembersCurrentGroup;
+ _fakePrincipalMembers = adBookmark.fakePrincipalMembers;
+ _foreignMembersToReturn = adBookmark.foreignMembersToReturn;
+ _currentForeignPrincipal = adBookmark.currentForeignPrincipal;
+ _currentForeignDE = adBookmark.currentForeignDE;
+ _foreignGroups = adBookmark.foreignGroups;
+ if (_queryMembersResults != null)
+ _queryMembersResults.Dispose();
+ _queryMembersResults = adBookmark.queryMembersResults;
+ _queryMembersResultEnumerator = adBookmark.queryMembersResultEnumerator;
+ _memberSearchResults = adBookmark.memberSearchResults;
+ _memberSearchResultsEnumerator = adBookmark.memberSearchResultsEnumerator;
+ _atBeginning = adBookmark.atBeginning;
+ _expansionMode = adBookmark.expansionMode;
+
+ // Replace enumerators
+ _members = adBookmark.members;
+ _membersEnum = adBookmark.membersEnum;
+
+ // Replace the enumerator queue elements
+ if (null != _membersQueue)
+ {
+ _membersQueue.Clear();
+
+ if (null != adBookmark.membersQueue)
+ {
+ foreach (IEnumerable ie in adBookmark.membersQueue)
+ {
+ _membersQueue.Enqueue(ie);
+ }
+ }
+ }
+
+ if (null != _memberSearchersQueue)
+ {
+ foreach (DirectorySearcher ds in _memberSearchersQueue)
+ {
+ ds.Dispose();
+ }
+
+ _memberSearchersQueue.Clear();
+
+ if (null != adBookmark.memberSearcherQueue)
+ {
+ foreach (DirectorySearcher ds in adBookmark.memberSearcherQueue)
+ {
+ _memberSearchersQueue.Enqueue(ds);
+ }
+ }
+ }
+ }
+
+ // IDisposable implementation
+ public override void Dispose()
+ {
+ try
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Dispose: disposing");
+
+ if (_primaryGroupMembersSearcher != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Dispose: disposing primaryGroupMembersSearcher");
+ _primaryGroupMembersSearcher.Dispose();
+ }
+
+ if (_queryMembersResults != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Dispose: disposing queryMembersResults");
+ _queryMembersResults.Dispose();
+ }
+
+ if (_currentMembersSearcher != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Dispose: disposing membersSearcher");
+ _currentMembersSearcher.Dispose();
+ }
+
+ if (_memberSearchResults != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Dispose: disposing memberSearchResults");
+ _memberSearchResults.Dispose();
+ }
+
+ if (_memberSearchersQueue != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Dispose: disposing memberSearchersQueue");
+ foreach (DirectorySearcher ds in _memberSearchersQueue)
+ {
+ ds.Dispose();
+ }
+
+ _memberSearchersQueue.Clear();
+ }
+ IDisposable disposableMembers = _members as IDisposable;
+ if (disposableMembers != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Dispose: disposing members Enumerable");
+ disposableMembers.Dispose();
+ }
+ IDisposable disposableMembersEnum = _membersEnum as IDisposable;
+ if (disposableMembersEnum != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Dispose: disposing membersEnum Enumerator");
+ disposableMembersEnum.Dispose();
+ }
+ if (_membersQueue != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNLinkedAttrSet", "Dispose: disposing membersQueue");
+ foreach (IEnumerable enumerable in _membersQueue)
+ {
+ IDisposable disposableEnum = enumerable as IDisposable;
+ if (disposableEnum != null)
+ {
+ disposableEnum.Dispose();
+ }
+ }
+ }
+ if (_foreignGroups != null)
+ {
+ foreach (GroupPrincipal gp in _foreignGroups)
+ {
+ gp.Dispose();
+ }
+ }
+
+ _disposed = true;
+ }
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+
+ //
+ //
+ //
+
+ private UnsafeNativeMethods.IADsPathname _pathCracker = null;
+ private object _pathLock = new object();
+ private Dictionary<string, bool> _usersVisited = new Dictionary<string, bool>();
+
+ // The 0th entry in this list is always the DN of the original group/user whose membership we're querying
+ private List<string> _groupsVisited = new List<string>();
+
+ private List<string> _groupsToVisit = new List<string>();
+
+ protected Object current = null; // current member of the group (or current group of the user)
+
+ private bool _returnedPrimaryGroup = false;
+ private string _primaryGroupDN; // the DN of the user's PrimaryGroup (not included in this.members/originalMembers)
+
+ private bool _recursive;
+
+ private Queue<IEnumerable> _membersQueue = new Queue<IEnumerable>();
+ private IEnumerable _members; // the membership we're currently enumerating over
+ private Queue<IEnumerable> _originalMembers = new Queue<IEnumerable>(); // the membership we started off with (before recursing)
+
+ private IEnumerator _membersEnum = null;
+
+ private ADStoreCtx _storeCtx;
+ private ADStoreCtx _originalStoreCtx;
+
+ private bool _atBeginning = true;
+
+ private bool _disposed = false;
+
+ // foreign
+ // This contains a list of employees built while enumerating the current group. These are FSP objects in the current domain and need to
+ // be translated to find out the domain that holds the actual object.
+ private List<DirectoryEntry> _foreignMembersCurrentGroup = new List<DirectoryEntry>();
+ // List of objects from the group tha are actual fake group objects.
+ private List<DirectoryEntry> _fakePrincipalMembers = new List<DirectoryEntry>();
+ // list of SIDs + store that have been translated. These could be any principal object
+ private SidList _foreignMembersToReturn = null;
+
+ private Principal _currentForeignPrincipal = null;
+ private DirectoryEntry _currentForeignDE = null;
+
+ private List<GroupPrincipal> _foreignGroups = new List<GroupPrincipal>();
+
+ // members based on a query (used for users who are group members by virtue of their primaryGroupId pointing to the group)
+ private DirectorySearcher _primaryGroupMembersSearcher;
+ private SearchResultCollection _queryMembersResults = null;
+ private IEnumerator _queryMembersResultEnumerator = null;
+
+ private DirectorySearcher _currentMembersSearcher = null;
+
+ private Queue<DirectorySearcher> _memberSearchersQueue = new Queue<DirectorySearcher>();
+ private Queue<DirectorySearcher> _memberSearchersQueueOriginal = new Queue<DirectorySearcher>();
+
+ private SearchResultCollection _memberSearchResults = null;
+ private IEnumerator _memberSearchResultsEnumerator = null;
+
+ private ExpansionMode _expansionMode;
+ private ExpansionMode _originalExpansionMode;
+
+ private string BuildPathFromDN(string dn)
+ {
+ string userSuppliedServername = _storeCtx.UserSuppliedServerName;
+
+ if (null == _pathCracker)
+ {
+ lock (_pathLock)
+ {
+ if (null == _pathCracker)
+ {
+ UnsafeNativeMethods.Pathname pathNameObj = new UnsafeNativeMethods.Pathname();
+ _pathCracker = (UnsafeNativeMethods.IADsPathname)pathNameObj;
+ _pathCracker.EscapedMode = 2 /* ADS_ESCAPEDMODE_ON */;
+ }
+ }
+ }
+
+ _pathCracker.Set(dn, 4 /* ADS_SETTYPE_DN */);
+
+ string escapedDn = _pathCracker.Retrieve(7 /* ADS_FORMAT_X500_DN */);
+
+ if (userSuppliedServername.Length > 0)
+ return "LDAP://" + _storeCtx.UserSuppliedServerName + "/" + escapedDn;
+ else
+ return "LDAP://" + escapedDn;
+ }
+ }
+
+ internal enum ExpansionMode
+ {
+ Enum = 0,
+ ASQ = 1,
+ }
+
+ internal class ADDNLinkedAttrSetBookmark : ResultSetBookmark
+ {
+ public Dictionary<string, bool> usersVisited;
+ public List<string> groupsToVisit;
+ public List<string> groupsVisited;
+ public IEnumerable members;
+ public IEnumerator membersEnum = null;
+ public Queue<IEnumerable> membersQueue;
+ public ADStoreCtx storeCtx;
+ public Object current;
+ public bool returnedPrimaryGroup;
+ public List<DirectoryEntry> foreignMembersCurrentGroup;
+ public List<DirectoryEntry> fakePrincipalMembers;
+ public SidList foreignMembersToReturn;
+ public Principal currentForeignPrincipal;
+ public DirectoryEntry currentForeignDE;
+ public List<GroupPrincipal> foreignGroups;
+ public SearchResultCollection queryMembersResults;
+ public IEnumerator queryMembersResultEnumerator;
+ public SearchResultCollection memberSearchResults;
+ public IEnumerator memberSearchResultsEnumerator;
+ public bool atBeginning;
+ public ExpansionMode expansionMode;
+ public Queue<DirectorySearcher> memberSearcherQueue;
+ }
+}
+
+// #endif
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADEntriesSet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADEntriesSet.cs
new file mode 100644
index 0000000000..067e3df0ad
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADEntriesSet.cs
@@ -0,0 +1,125 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Globalization;
+using System.DirectoryServices;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class ADEntriesSet : ResultSet
+ {
+ private SearchResultCollection _searchResults;
+ private ADStoreCtx _storeCtx;
+
+ private IEnumerator _enumerator;
+ private SearchResult _current = null;
+ private bool _endReached = false;
+
+ private bool _disposed = false;
+
+ private object _discriminant = null;
+
+ internal ADEntriesSet(SearchResultCollection src, ADStoreCtx storeCtx)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADEntriesSet", "Ctor");
+
+ _searchResults = src;
+ _storeCtx = storeCtx;
+ _enumerator = src.GetEnumerator();
+ }
+
+ internal ADEntriesSet(SearchResultCollection src, ADStoreCtx storeCtx, object discriminant) : this(src, storeCtx)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADEntriesSet", "Ctor");
+
+ _discriminant = discriminant;
+ }
+
+ // Return the principal we're positioned at as a Principal object.
+ // Need to use our StoreCtx's GetAsPrincipal to convert the native object to a Principal
+ override internal object CurrentAsPrincipal
+ {
+ get
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADEntriesSet", "CurrentAsPrincipal");
+
+ // Since this class is only used internally, none of our code should be even calling this
+ // if MoveNext returned false, or before calling MoveNext.
+ Debug.Assert(_endReached == false && _current != null);
+
+ return ADUtils.SearchResultAsPrincipal(_current, _storeCtx, _discriminant);
+ }
+ }
+
+ // Advance the enumerator to the next principal in the result set, pulling in additional pages
+ // of results as needed.
+ // Returns true if successful, false if no more results to return.
+ override internal bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADEntriesSet", "MoveNext");
+
+ Debug.Assert(_enumerator != null);
+
+ bool f = _enumerator.MoveNext();
+
+ if (f)
+ {
+ _current = (SearchResult)_enumerator.Current;
+ }
+ else
+ {
+ _endReached = true;
+ }
+
+ return f;
+ }
+
+ // Resets the enumerator to before the first result in the set. This potentially can be an expensive
+ // operation, e.g., if doing a paged search, may need to re-retrieve the first page of results.
+ // As a special case, if the ResultSet is already at the very beginning, this is guaranteed to be
+ // a no-op.
+ override internal void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADEntriesSet", "Reset");
+
+ _endReached = false;
+ _current = null;
+
+ if (_enumerator != null)
+ _enumerator.Reset();
+ }
+
+ // IDisposable implementation
+ public override void Dispose()
+ {
+ try
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADEntriesSet", "Dispose: disposing");
+
+ _searchResults.Dispose();
+
+ _disposed = true;
+ }
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+ }
+}
+
+// #endif // PAPI_AD
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx.cs
new file mode 100644
index 0000000000..97d5f04efc
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx.cs
@@ -0,0 +1,2619 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Net;
+using System.Security.Principal;
+using System.Security.Permissions;
+using System.Collections.Specialized;
+using System.DirectoryServices;
+using System.Text;
+using MACLPrinc = System.Security.Principal;
+using System.Security.AccessControl;
+using System.DirectoryServices.ActiveDirectory;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal partial class ADStoreCtx : StoreCtx
+ {
+ protected DirectoryEntry ctxBase;
+ private const int mappingIndex = 0;
+
+ private object _ctxBaseLock = new object(); // when mutating ctxBase
+
+ private bool _ownCtxBase; // if true, we "own" ctxBase and must Dispose of it when we're done
+
+ private bool _disposed = false;
+
+ protected internal NetCred Credentials { get { return this.credentials; } }
+ protected NetCred credentials = null;
+
+ protected internal AuthenticationTypes AuthTypes { get { return this.authTypes; } }
+ protected AuthenticationTypes authTypes;
+
+ protected ContextOptions contextOptions;
+
+ protected internal virtual void InitializeNewDirectoryOptions(DirectoryEntry newDeChild)
+ {
+ }
+
+ //
+ // Static constructor: used for initializing static tables
+ //
+ static ADStoreCtx()
+ {
+ //
+ // Load the filterPropertiesTable
+ //
+ LoadFilterMappingTable(mappingIndex, s_filterPropertiesTableRaw);
+ LoadPropertyMappingTable(mappingIndex, s_propertyMappingTableRaw);
+ }
+
+ protected virtual int MappingTableIndex
+ {
+ get
+ {
+ return mappingIndex;
+ }
+ }
+
+ protected static void LoadFilterMappingTable(int mappingIndex, object[,] rawFilterPropertiesTable)
+ {
+ if (null == s_filterPropertiesTable)
+ s_filterPropertiesTable = new Hashtable();
+
+ Hashtable mappingTable = new Hashtable();
+
+ for (int i = 0; i < rawFilterPropertiesTable.GetLength(0); i++)
+ {
+ Type qbeType = rawFilterPropertiesTable[i, 0] as Type;
+ string adPropertyName = rawFilterPropertiesTable[i, 1] as string;
+ FilterConverterDelegate f = rawFilterPropertiesTable[i, 2] as FilterConverterDelegate;
+
+ Debug.Assert(qbeType != null);
+ Debug.Assert(f != null);
+
+ // There should only be one entry per QBE type
+ Debug.Assert(mappingTable[qbeType] == null);
+
+ FilterPropertyTableEntry entry = new FilterPropertyTableEntry();
+ entry.suggestedADPropertyName = adPropertyName;
+ entry.converter = f;
+
+ mappingTable[qbeType] = entry;
+ }
+
+ s_filterPropertiesTable.Add(mappingIndex, mappingTable);
+ }
+
+ protected static void LoadPropertyMappingTable(int mappingIndex, object[,] rawPropertyMappingTable)
+ {
+ //
+ // Load the propertyMappingTableByProperty and propertyMappingTableByLDAP tables
+ //
+ if (null == s_propertyMappingTableByProperty)
+ s_propertyMappingTableByProperty = new Hashtable();
+
+ if (null == s_propertyMappingTableByLDAP)
+ s_propertyMappingTableByLDAP = new Hashtable();
+
+ if (null == s_propertyMappingTableByPropertyFull)
+ s_propertyMappingTableByPropertyFull = new Hashtable();
+
+ if (null == TypeToLdapPropListMap)
+ TypeToLdapPropListMap = new Dictionary<int, Dictionary<Type, StringCollection>>();
+
+ Hashtable mappingTableByProperty = new Hashtable();
+ Hashtable mappingTableByLDAP = new Hashtable();
+ Hashtable mappingTableByPropertyFull = new Hashtable();
+
+ Dictionary<string, string[]> propertyNameToLdapAttr = new Dictionary<string, string[]>();
+
+ Dictionary<Type, StringCollection> TypeToLdapDict = new Dictionary<Type, StringCollection>();
+
+ for (int i = 0; i < s_propertyMappingTableRaw.GetLength(0); i++)
+ {
+ string propertyName = rawPropertyMappingTable[i, 0] as string;
+ string ldapAttribute = rawPropertyMappingTable[i, 1] as string;
+ FromLdapConverterDelegate fromLdap = rawPropertyMappingTable[i, 2] as FromLdapConverterDelegate;
+ ToLdapConverterDelegate toLdap = rawPropertyMappingTable[i, 3] as ToLdapConverterDelegate;
+
+ Debug.Assert(propertyName != null);
+ Debug.Assert((ldapAttribute != null && fromLdap != null) || (fromLdap == null));
+ //Debug.Assert(toLdap != null);
+
+ // Build the table entry. The same entry will be used in both tables.
+ // Once constructed, the table entries are treated as read-only, so there's
+ // no danger in sharing the entries between tables.
+ PropertyMappingTableEntry propertyEntry = new PropertyMappingTableEntry();
+ propertyEntry.propertyName = propertyName;
+ propertyEntry.suggestedADPropertyName = ldapAttribute;
+ propertyEntry.ldapToPapiConverter = fromLdap;
+ propertyEntry.papiToLdapConverter = toLdap;
+
+ // Build a mapping table from PAPI propertyname to ldapAttribute that we can use below
+ // to build a list of ldap attributes for each object type.
+ if (null != ldapAttribute)
+ {
+ if (propertyNameToLdapAttr.ContainsKey(propertyName))
+ {
+ string[] props = new string[propertyNameToLdapAttr[propertyName].Length + 1];
+ propertyNameToLdapAttr[propertyName].CopyTo(props, 0);
+ props[propertyNameToLdapAttr[propertyName].Length] = ldapAttribute;
+ propertyNameToLdapAttr[propertyName] = props;
+ }
+ else
+ propertyNameToLdapAttr.Add(propertyName, new string[] { ldapAttribute });
+ }
+
+ // propertyMappingTableByProperty
+ // If toLdap is null, there's no PAPI->LDAP mapping for this property
+ // (it's probably read-only, e.g., "lastLogon").
+ if (toLdap != null)
+ {
+ if (mappingTableByProperty[propertyName] == null)
+ mappingTableByProperty[propertyName] = new ArrayList();
+
+ ((ArrayList)mappingTableByProperty[propertyName]).Add(propertyEntry);
+ }
+
+ if (mappingTableByPropertyFull[propertyName] == null)
+ mappingTableByPropertyFull[propertyName] = new ArrayList();
+
+ ((ArrayList)mappingTableByPropertyFull[propertyName]).Add(propertyEntry);
+
+ // mappingTableByLDAP
+ // If fromLdap is null, there's no direct LDAP->PAPI mapping for this property.
+ // It's probably a property that requires custom handling, such as IdentityClaim.
+ if (fromLdap != null)
+ {
+ string ldapAttributeLower = ldapAttribute.ToLower(CultureInfo.InvariantCulture);
+
+ if (mappingTableByLDAP[ldapAttributeLower] == null)
+ mappingTableByLDAP[ldapAttributeLower] = new ArrayList();
+
+ ((ArrayList)mappingTableByLDAP[ldapAttributeLower]).Add(propertyEntry);
+ }
+ }
+
+ s_propertyMappingTableByProperty.Add(mappingIndex, mappingTableByProperty);
+ s_propertyMappingTableByLDAP.Add(mappingIndex, mappingTableByLDAP);
+ s_propertyMappingTableByPropertyFull.Add(mappingIndex, mappingTableByPropertyFull);
+
+ // Build a table of Type mapped to a collection of all ldap attributes for that type.
+ // This table will be used to load the objects when searching.
+
+ StringCollection principalPropList = new StringCollection();
+ StringCollection authPrincipalPropList = new StringCollection();
+ StringCollection userPrincipalPropList = new StringCollection();
+ StringCollection computerPrincipalPropList = new StringCollection();
+ StringCollection groupPrincipalPropList = new StringCollection();
+
+ foreach (string prop in principalProperties)
+ {
+ string[] attr;
+ if (propertyNameToLdapAttr.TryGetValue(prop, out attr))
+ {
+ foreach (string plist in attr)
+ {
+ principalPropList.Add(plist);
+ authPrincipalPropList.Add(plist);
+ userPrincipalPropList.Add(plist);
+ computerPrincipalPropList.Add(plist);
+ groupPrincipalPropList.Add(plist);
+ }
+ }
+ }
+
+ foreach (string prop in authenticablePrincipalProperties)
+ {
+ string[] attr;
+ if (propertyNameToLdapAttr.TryGetValue(prop, out attr))
+ {
+ foreach (string plist in attr)
+ {
+ authPrincipalPropList.Add(plist);
+ userPrincipalPropList.Add(plist);
+ computerPrincipalPropList.Add(plist);
+ }
+ }
+ }
+
+ foreach (string prop in groupProperties)
+ {
+ string[] attr;
+ if (propertyNameToLdapAttr.TryGetValue(prop, out attr))
+ {
+ foreach (string plist in attr)
+ {
+ groupPrincipalPropList.Add(plist);
+ }
+ }
+ }
+
+ foreach (string prop in userProperties)
+ {
+ string[] attr;
+ if (propertyNameToLdapAttr.TryGetValue(prop, out attr))
+ {
+ foreach (string plist in attr)
+ {
+ userPrincipalPropList.Add(plist);
+ }
+ }
+ }
+
+ foreach (string prop in computerProperties)
+ {
+ string[] attr;
+ if (propertyNameToLdapAttr.TryGetValue(prop, out attr))
+ {
+ foreach (string plist in attr)
+ {
+ computerPrincipalPropList.Add(plist);
+ }
+ }
+ }
+
+ principalPropList.Add("objectClass");
+ authPrincipalPropList.Add("objectClass");
+ userPrincipalPropList.Add("objectClass");
+ computerPrincipalPropList.Add("objectClass");
+ groupPrincipalPropList.Add("objectClass");
+
+ TypeToLdapDict.Add(typeof(Principal), principalPropList);
+ TypeToLdapDict.Add(typeof(GroupPrincipal), groupPrincipalPropList);
+ TypeToLdapDict.Add(typeof(AuthenticablePrincipal), authPrincipalPropList);
+ TypeToLdapDict.Add(typeof(UserPrincipal), userPrincipalPropList);
+ TypeToLdapDict.Add(typeof(ComputerPrincipal), computerPrincipalPropList);
+
+ TypeToLdapPropListMap.Add(mappingIndex, TypeToLdapDict);
+ }
+
+ //
+ // Constructor
+ //
+
+ // Throws ArgumentException if base is not a container class (as indicated by an empty possibleInferiors
+ // attribute in the corresponding schema class definition)
+ public ADStoreCtx(DirectoryEntry ctxBase, bool ownCtxBase, string username, string password, ContextOptions options)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Constructing ADStoreCtx for {0}", ctxBase.Path);
+
+ Debug.Assert(ctxBase != null);
+
+ // This will also detect if the server is down or nonexistent
+ if (!IsContainer(ctxBase))
+ throw new InvalidOperationException(StringResources.ADStoreCtxMustBeContainer);
+
+ this.ctxBase = ctxBase;
+ _ownCtxBase = ownCtxBase;
+
+ if (username != null && password != null)
+ this.credentials = new NetCred(username, password);
+
+ this.contextOptions = options;
+ this.authTypes = SDSUtils.MapOptionsToAuthTypes(options);
+ }
+
+ protected bool IsContainer(DirectoryEntry de)
+ {
+ //NOTE: Invoking de.SchemaEntry creates a new DirectoryEntry object, which is not disposed by de.
+ using (DirectoryEntry schemaDE = de.SchemaEntry)
+ {
+ if (schemaDE.Properties["possibleInferiors"].Count == 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "IsContainer: not a container ({0})", schemaDE.Path);
+ return false;
+ }
+ return true;
+ }
+ }
+
+ //
+ // IDisposable implementation
+ //
+
+ public override void Dispose()
+ {
+ try
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Dispose: disposing, ownCtxBase={0}", _ownCtxBase);
+
+ if (_ownCtxBase)
+ ctxBase.Dispose();
+
+ _disposed = true;
+ }
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+
+ //
+ // StoreCtx information
+ //
+
+ // Retrieves the Path (ADsPath) of the object used as the base of the StoreCtx
+ internal override string BasePath
+ {
+ get
+ {
+ Debug.Assert(this.ctxBase != null);
+ return this.ctxBase.Path;
+ }
+ }
+
+ //
+ // CRUD
+ //
+
+ // Used to perform the specified operation on the Principal.
+ //
+ // Insert() and Update() must check to make sure no properties not supported by this StoreCtx
+ // have been set, prior to persisting the Principal.
+ internal override void Insert(Principal p)
+ {
+ try
+ {
+ Debug.Assert(p.unpersisted == true);
+ Debug.Assert(p.fakePrincipal == false);
+
+ // Insert the principal into the store
+ SDSUtils.InsertPrincipal(
+ p,
+ this,
+ new SDSUtils.GroupMembershipUpdater(UpdateGroupMembership),
+ this.credentials,
+ this.authTypes,
+ true
+ );
+
+ // Load in all the initial values from the store
+ //((DirectoryEntry)p.UnderlyingObject).RefreshCache();
+ LoadDirectoryEntryAttributes((DirectoryEntry)p.UnderlyingObject);
+
+ // If they set p.Enabled == true, enable the principal
+ EnablePrincipalIfNecessary(p);
+
+ // If they set CannotChangePassword then we need to set it here after the object is already created.
+ SetPasswordSecurityifNeccessary(p);
+
+ // Load in the StoreKey
+ Debug.Assert(p.Key == null); // since it was previously unpersisted
+
+ Debug.Assert(p.UnderlyingObject != null); // since we just persisted it
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+
+ ADStoreKey key = new ADStoreKey(((DirectoryEntry)p.UnderlyingObject).Guid);
+ p.Key = key;
+
+ // Reset the change tracking
+ p.ResetAllChangeStatus();
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Insert: new GUID is ", ((DirectoryEntry)p.UnderlyingObject).Guid);
+ }
+ catch (PrincipalExistsException)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Insert, object already exists");
+ throw;
+ }
+ catch (System.SystemException e)
+ {
+ try
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "ADStoreCtx", "Insert, Save Failed (attempting to delete) Exception {0} ", e.Message);
+ if (null != p.UnderlyingObject)
+ {
+ SDSUtils.DeleteDirectoryEntry((DirectoryEntry)p.UnderlyingObject);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Insert, object deleted");
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Insert, No object was created nothing to delete");
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException deleteFail)
+ {
+ // The delete failed. Just continue we will throw the original exception below.
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "ADStoreCtx", "Insert, Deletion Failed {0} ", deleteFail.Message);
+ }
+
+ if (e is System.Runtime.InteropServices.COMException)
+ throw ExceptionHelper.GetExceptionFromCOMException((System.Runtime.InteropServices.COMException)e);
+ else
+ throw e;
+ }
+ }
+
+ internal override bool AccessCheck(Principal p, PrincipalAccessMask targetPermission)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "AccessCheck " + targetPermission.ToString());
+
+ switch (targetPermission)
+ {
+ case PrincipalAccessMask.ChangePassword:
+
+ return CannotChangePwdFromLdapConverter((DirectoryEntry)p.GetUnderlyingObject());
+
+ default:
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "ADStoreCtx", "Invalid targetPermission in AccessCheck");
+
+ break;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// If The enabled property was set on the principal then perform actions
+ /// neccessary on the principal to set the enabled status to match
+ /// the set value.
+ /// </summary>
+ /// <param name="p"></param>
+ private void EnablePrincipalIfNecessary(Principal p)
+ {
+ if (p.GetChangeStatusForProperty(PropertyNames.AuthenticablePrincipalEnabled))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "EnablePrincipalIfNecessary: enabling principal");
+
+ Debug.Assert(p is AuthenticablePrincipal);
+
+ bool enable = (bool)p.GetValueForProperty(PropertyNames.AuthenticablePrincipalEnabled);
+
+ SetAuthPrincipalEnableStatus((AuthenticablePrincipal)p, enable);
+ }
+ }
+
+ private void SetPasswordSecurityifNeccessary(Principal p)
+ {
+ if (p.GetChangeStatusForProperty(PropertyNames.PwdInfoCannotChangePassword))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "EnablePrincipalIfNecessary: enabling principal");
+
+ Debug.Assert(p is AuthenticablePrincipal);
+
+ SetCannotChangePasswordStatus((AuthenticablePrincipal)p, (bool)p.GetValueForProperty(PropertyNames.PwdInfoCannotChangePassword), true);
+ }
+ }
+
+ private static void SetCannotChangePasswordStatus(Principal ap, bool userCannotChangePassword, bool commitChanges)
+ {
+ Debug.Assert(ap is AuthenticablePrincipal);
+ Debug.Assert(ap.GetUnderlyingObject() is DirectoryEntry);
+
+ DirectoryEntry de = (DirectoryEntry)ap.GetUnderlyingObject();
+ // retrieving ObjectSecurity after
+ // previously modifying the ACL will return null unless we force a cache refresh. We have to do this always,
+ // even before we call ObjectSecurity to see if it would return null, because once ObjectSecurity returns null the
+ // first time, it'll keep returning null even if we refresh the cache.
+ if (!de.Properties.Contains("nTSecurityDescriptor"))
+ de.RefreshCache(new string[] { "nTSecurityDescriptor" });
+ ActiveDirectorySecurity adsSecurity = de.ObjectSecurity;
+
+ bool denySelfFound;
+ bool denyWorldFound;
+ bool allowSelfFound;
+ bool allowWorldFound;
+
+ // Scan the existing ACL to determine its current state
+
+ ScanACLForChangePasswordRight(adsSecurity, out denySelfFound, out denyWorldFound, out allowSelfFound, out allowWorldFound);
+
+ // Build the ACEs that we'll use
+ ActiveDirectoryAccessRule denySelfACE = new ExtendedRightAccessRule(
+ new MACLPrinc.SecurityIdentifier(SelfSddl),
+ AccessControlType.Deny,
+ s_changePasswordGuid);
+
+ ActiveDirectoryAccessRule denyWorldAce = new ExtendedRightAccessRule(
+ new MACLPrinc.SecurityIdentifier(WorldSddl),
+ AccessControlType.Deny,
+ s_changePasswordGuid);
+
+ ActiveDirectoryAccessRule allowSelfACE = new ExtendedRightAccessRule(
+ new MACLPrinc.SecurityIdentifier(SelfSddl),
+ AccessControlType.Allow,
+ s_changePasswordGuid);
+
+ ActiveDirectoryAccessRule allowWorldAce = new ExtendedRightAccessRule(
+ new MACLPrinc.SecurityIdentifier(WorldSddl),
+ AccessControlType.Allow,
+ s_changePasswordGuid);
+
+ // Based on the current state of the ACL and the userCannotChangePassword status, perform the necessary modifications,
+ // if any
+ if (userCannotChangePassword)
+ {
+ // If we want to make it so the user cannot change their password, we need to remove the ALLOW ACEs
+ // (if they exist) and add the necessary explicit DENY ACEs if they don't already exist.
+
+ if (!denySelfFound)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "CannotChangePwdToLdapConverter: add deny self");
+ adsSecurity.AddAccessRule(denySelfACE);
+ }
+
+ if (!denyWorldFound)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "CannotChangePwdToLdapConverter: add deny world");
+ adsSecurity.AddAccessRule(denyWorldAce);
+ }
+
+ if (allowSelfFound)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "CannotChangePwdToLdapConverter: remove allow self");
+ adsSecurity.RemoveAccessRuleSpecific(allowSelfACE);
+ }
+
+ if (allowWorldFound)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "CannotChangePwdToLdapConverter: remove allow world");
+ adsSecurity.RemoveAccessRuleSpecific(allowWorldAce);
+ }
+ }
+ else
+ {
+ // If we want to make to give the user back the right to change their password, we need to remove
+ // the explicit DENY ACEs if they exist. We'll also add in explicit ALLOW ACEs.
+
+ if (denySelfFound)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "CannotChangePwdToLdapConverter: remove deny self");
+ adsSecurity.RemoveAccessRuleSpecific(denySelfACE);
+ }
+
+ if (denyWorldFound)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "CannotChangePwdToLdapConverter: remove deny world");
+ adsSecurity.RemoveAccessRuleSpecific(denyWorldAce);
+ }
+
+ if (!allowSelfFound)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "CannotChangePwdToLdapConverter: add allow self");
+ adsSecurity.AddAccessRule(allowSelfACE);
+ }
+
+ if (!allowWorldFound)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "CannotChangePwdToLdapConverter: add allow world");
+ adsSecurity.AddAccessRule(allowWorldAce);
+ }
+ }
+
+ if (commitChanges)
+ de.CommitChanges();
+ }
+ /// <summary>
+ /// Read the Account Control From the Directory entry. If the control is read then set or
+ /// clear bit 0x2 corresponding to the enable parameter
+ /// </summary>
+ /// <param name="ap">Principal to modify</param>
+ /// <param name="enable">New state of the enable bit</param>
+ ///
+
+ protected virtual void SetAuthPrincipalEnableStatus(AuthenticablePrincipal ap, bool enable)
+ {
+ try
+ {
+ Debug.Assert(ap.fakePrincipal == false);
+
+ int uacValue;
+
+ DirectoryEntry de = (DirectoryEntry)ap.UnderlyingObject;
+
+ if (de.Properties["userAccountControl"].Count > 0)
+ {
+ Debug.Assert(de.Properties["userAccountControl"].Count == 1);
+
+ uacValue = (int)de.Properties["userAccountControl"][0];
+ }
+ else
+ {
+ // Since we loaded the properties, we should have it. Perhaps we don't have access
+ // to it. In that case, we don't want to blindly overwrite whatever other bits might be there.
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "SetAuthPrincipalEnableStatus: can't read userAccountControl");
+
+ throw new PrincipalOperationException(
+ StringResources.ADStoreCtxUnableToReadExistingAccountControlFlagsToEnable);
+ }
+
+ if (enable && ((uacValue & 0x2) != 0))
+ {
+ // It's currently disabled, and we need to enable it
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "SetAuthPrincipalEnableStatus: Enabling (old uac={0})", uacValue);
+
+ Utils.ClearBit(ref uacValue, 0x2); // UF_ACCOUNTDISABLE
+
+ WriteAttribute(ap, "userAccountControl", uacValue);
+ }
+ else if (!enable && ((uacValue & 0x2) == 0))
+ {
+ // It's current enabled, and we need to disable it
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "SetAuthPrincipalEnableStatus: Disabling (old uac={0})", uacValue);
+
+ Utils.SetBit(ref uacValue, 0x2); // UF_ACCOUNTDISABLE
+
+ WriteAttribute(ap, "userAccountControl", uacValue);
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+ /// <summary>
+ /// Apply all changed properties on the principal to the Directory Entry.
+ /// Reset the changed status on all the properties
+ /// </summary>
+ /// <param name="p">Principal to update</param>
+ internal override void Update(Principal p)
+ {
+ try
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Update");
+
+ Debug.Assert(p.fakePrincipal == false);
+ Debug.Assert(p.unpersisted == false);
+ Debug.Assert(p.UnderlyingObject != null);
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+
+ // Commit the properties
+ SDSUtils.ApplyChangesToDirectory(
+ p,
+ this,
+ new SDSUtils.GroupMembershipUpdater(UpdateGroupMembership),
+ this.credentials,
+ this.authTypes
+ );
+
+ // Reset the change tracking
+ p.ResetAllChangeStatus();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ /// <summary>
+ /// Delete the directory entry that corresponds to the principal
+ /// </summary>
+ /// <param name="p">Principal to delete</param>
+ internal override void Delete(Principal p)
+ {
+ try
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Delete");
+
+ Debug.Assert(p.fakePrincipal == false);
+
+ // Principal.Delete() shouldn't be calling us on an unpersisted Principal.
+ Debug.Assert(p.unpersisted == false);
+ Debug.Assert(p.UnderlyingObject != null);
+
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+ SDSUtils.DeleteDirectoryEntry((DirectoryEntry)p.UnderlyingObject);
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ internal override void Move(StoreCtx originalStore, Principal p)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Move");
+
+ Debug.Assert(p != null);
+ Debug.Assert(originalStore != null);
+ Debug.Assert(originalStore is ADStoreCtx);
+
+ string name = null;
+ string rdnPrefix = p.ExtensionHelper.RdnPrefix;
+ string baseObjectRdnPrefix = null;
+ Type principalType = p.GetType();
+
+ if (null == rdnPrefix)
+ {
+ throw new InvalidOperationException(StringResources.ExtensionInvalidClassAttributes);
+ }
+
+ if (p.GetChangeStatusForProperty(PropertyNames.PrincipalName))
+ {
+ name = rdnPrefix + "=" + (string)p.GetValueForProperty(PropertyNames.PrincipalName);
+
+ // If the principal class is derived from Group, Computer or User then we need to see
+ // if the class has an RdnPrefix set that differs from the base class prefix. If so then we need
+ // to modify that attribute when if changed the name during the move.
+
+ if (principalType.IsSubclassOf(typeof(GroupPrincipal)) ||
+ principalType.IsSubclassOf(typeof(UserPrincipal)) ||
+ principalType.IsSubclassOf(typeof(ComputerPrincipal)))
+ {
+ DirectoryRdnPrefixAttribute[] MyAttribute =
+ (DirectoryRdnPrefixAttribute[])Attribute.GetCustomAttributes(principalType.BaseType, typeof(DirectoryRdnPrefixAttribute), false);
+
+ if (MyAttribute == null)
+ throw new InvalidOperationException(StringResources.ExtensionInvalidClassAttributes);
+
+ string defaultRdn = null;
+
+ // Search for the rdn prefix. This will use either the prefix that has a context type
+ // that matches the principals context or the first rdnPrefix that has a null context type
+ for (int i = 0; i < MyAttribute.Length; i++)
+ {
+ if ((MyAttribute[i].Context == null && null == defaultRdn) ||
+ (p.ContextType == MyAttribute[i].Context))
+ {
+ defaultRdn = MyAttribute[i].RdnPrefix;
+ }
+ }
+
+ // If the base objects RDN prefix is not the same as the dervied class then we need to set both
+ if (defaultRdn != rdnPrefix)
+ {
+ baseObjectRdnPrefix = defaultRdn;
+ }
+ }
+ }
+
+ SDSUtils.MoveDirectoryEntry((DirectoryEntry)p.GetUnderlyingObject(),
+ ctxBase,
+ name);
+
+ p.LoadValueIntoProperty(PropertyNames.PrincipalName, p.GetValueForProperty(PropertyNames.PrincipalName));
+
+ if (null != baseObjectRdnPrefix)
+ {
+ ((DirectoryEntry)p.GetUnderlyingObject()).Properties[baseObjectRdnPrefix].Value = (string)p.GetValueForProperty(PropertyNames.PrincipalName);
+ }
+ }
+
+ //
+ // Special operations: the Principal classes delegate their implementation of many of the
+ // special methods to their underlying StoreCtx
+ //
+
+ // methods for manipulating accounts
+
+ /// <summary>
+ /// This method sets the default user account control bits for the new principal
+ /// being created in this account store.
+ /// </summary>
+ /// <param name="p"> Principal to set the user account control bits for </param>
+ internal override void InitializeUserAccountControl(AuthenticablePrincipal p)
+ {
+ Debug.Assert(p != null);
+ Debug.Assert(p.fakePrincipal == false);
+ Debug.Assert(p.unpersisted == true); // should only ever be called for new principals
+
+ // set the userAccountControl bits on the underlying directory entry
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+ Type principalType = p.GetType();
+
+ if ((principalType == typeof(ComputerPrincipal)) || (principalType.IsSubclassOf(typeof(ComputerPrincipal))))
+ {
+ de.Properties["userAccountControl"].Value = SDSUtils.AD_DefaultUAC_Machine;
+ }
+ else if ((principalType == typeof(UserPrincipal)) || (principalType.IsSubclassOf(typeof(UserPrincipal))))
+ {
+ de.Properties["userAccountControl"].Value = SDSUtils.AD_DefaultUAC;
+ }
+ }
+
+ /// <summary>
+ /// Determine if principal account is locked.
+ /// First read User-Account-control-computed from the DE. On Uplevel platforms this computed attribute will exist and we can
+ /// just check bit 0x0010. On DL platforms this attribute does not exist so we must read lockoutTime and return locked if
+ /// this is greater than 0
+ /// </summary>
+ /// <param name="p">Princiapl to check status</param>
+ /// <returns>true is account is locked, false if not</returns>
+ internal override bool IsLockedOut(AuthenticablePrincipal p)
+ {
+ try
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ Debug.Assert(p.unpersisted == false);
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ de.RefreshCache(new string[] { "msDS-User-Account-Control-Computed", "lockoutTime" });
+
+ if (de.Properties["msDS-User-Account-Control-Computed"].Count > 0)
+ {
+ // Uplevel platform --- the DC will compute it for us
+ Debug.Assert(de.Properties["msDS-User-Account-Control-Computed"].Count == 1);
+ int uacComputed = (int)de.Properties["msDS-User-Account-Control-Computed"][0];
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "IsLockedOut: using computed uac={0}", uacComputed);
+
+ return ((uacComputed & 0x0010) != 0); // UF_LOCKOUT
+ }
+ else
+ {
+ // Downlevel platform --- we have to compute it
+ bool isLockedOut = false;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "IsLockedOut: downlevel");
+
+ if (de.Properties["lockoutTime"].Count > 0)
+ {
+ ulong lockoutTime = (ulong)ADUtils.LargeIntToInt64((UnsafeNativeMethods.IADsLargeInteger)de.Properties["lockoutTime"][0]);
+
+ if (lockoutTime != 0)
+ {
+ ulong lockoutDuration = this.LockoutDuration;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "IsLockedOut: lockoutTime={0}, lockoutDuration={1}",
+ lockoutTime,
+ lockoutDuration);
+
+ if ((lockoutDuration + lockoutTime) > ((ulong)ADUtils.DateTimeToADFileTime(DateTime.UtcNow)))
+ isLockedOut = true;
+ }
+ }
+
+ return isLockedOut;
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ /// <summary>
+ /// Unlock account by setting LockoutTime to 0
+ /// </summary>
+ /// <param name="p">Principal to unlock</param>
+ internal override void UnlockAccount(AuthenticablePrincipal p)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UnlockAccount");
+
+ Debug.Assert(p.fakePrincipal == false);
+
+ WriteAttribute(p, "lockoutTime", 0);
+ }
+
+ // methods for manipulating passwords
+ /// <summary>
+ /// Set the password on the principal. This function requires administrator privilages
+ /// </summary>
+ /// <param name="p">Principal to modify</param>
+ /// <param name="newPassword">New password</param>
+ internal override void SetPassword(AuthenticablePrincipal p, string newPassword)
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ Debug.Assert(p != null);
+ Debug.Assert(newPassword != null); // but it could be an empty string
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ SDSUtils.SetPassword(de, newPassword);
+ }
+
+ /// <summary>
+ /// Change the password on the principal
+ /// </summary>
+ /// <param name="p">Principal to modify</param>
+ /// <param name="oldPassword">Current password</param>
+ /// <param name="newPassword">New password</param>
+ internal override void ChangePassword(AuthenticablePrincipal p, string oldPassword, string newPassword)
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ // Shouldn't be being called if this is the case
+ Debug.Assert(p.unpersisted == false);
+
+ Debug.Assert(p != null);
+ Debug.Assert(newPassword != null); // but it could be an empty string
+ Debug.Assert(oldPassword != null); // but it could be an empty string
+
+ if ((p.GetType() == typeof(ComputerPrincipal)) || (p.GetType().IsSubclassOf(typeof(ComputerPrincipal))))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "ADStoreCtx", "ChangePassword: computer acct, can't change password.");
+ throw new NotSupportedException(StringResources.ADStoreCtxNoComputerPasswordChange);
+ }
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ SDSUtils.ChangePassword(de, oldPassword, newPassword);
+ }
+ /// <summary>
+ /// Expire password by setting pwdLastSet to 0
+ /// </summary>
+ /// <param name="p"></param>
+ internal override void ExpirePassword(AuthenticablePrincipal p)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExpirePassword");
+
+ Debug.Assert(p.fakePrincipal == false);
+
+ WriteAttribute(p, "pwdLastSet", 0);
+ }
+
+ /// <summary>
+ /// Unexpire password by setting pwdLastSet to -1
+ /// </summary>
+ /// <param name="p"></param>
+ internal override void UnexpirePassword(AuthenticablePrincipal p)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UnexpirePassword");
+
+ Debug.Assert(p.fakePrincipal == false);
+
+ WriteAttribute(p, "pwdLastSet", -1);
+ }
+
+ /// <summary>
+ /// Set value for attribute on the passed principal. This is only valid for integer attribute types
+ /// </summary>
+ /// <param name="p"></param>
+ /// <param name="attribute"></param>
+ /// <param name="value"></param>
+ protected void WriteAttribute(Principal p, string attribute, int value)
+ {
+ ;
+
+ Debug.Assert(p != null);
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+
+ SDSUtils.WriteAttribute(de.Path, attribute, value, this.credentials, this.authTypes);
+ }
+
+ protected void WriteAttribute<T>(Principal p, string attribute, T value)
+ {
+ Debug.Assert(p != null);
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+
+ SDSUtils.WriteAttribute<T>(de.Path, attribute, value, this.credentials, this.authTypes);
+ }
+
+ // the various FindBy* methods
+ internal override ResultSet FindByLockoutTime(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ return FindByDate(principalType, new string[] { "lockoutTime" }, matchType, dt);
+ }
+
+ internal override ResultSet FindByLogonTime(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ return FindByDate(principalType, new string[] { "lastLogon", "lastLogonTimestamp" }, matchType, dt);
+ }
+
+ internal override ResultSet FindByPasswordSetTime(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ return FindByDate(principalType, new string[] { "pwdLastSet" }, matchType, dt);
+ }
+
+ internal override ResultSet FindByBadPasswordAttempt(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ return FindByDate(principalType, new string[] { "badPasswordTime" }, matchType, dt);
+ }
+
+ internal override ResultSet FindByExpirationTime(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ return FindByDate(principalType, new string[] { "accountExpires" }, matchType, dt);
+ }
+
+ private ResultSet FindByDate(Type subtype, string[] ldapAttributes, MatchType matchType, DateTime value)
+ {
+ Debug.Assert(ldapAttributes != null);
+ Debug.Assert(ldapAttributes.Length > 0);
+ Debug.Assert(subtype == typeof(Principal) || subtype.IsSubclassOf(typeof(Principal)));
+ DirectorySearcher ds = new DirectorySearcher(this.ctxBase);
+
+ try
+ {
+ // Pick some reasonable default values
+ ds.PageSize = 256;
+ ds.ServerTimeLimit = new TimeSpan(0, 0, 30); // 30 seconds
+
+ // We don't need any attributes returned, since we're just going to get a DirectoryEntry
+ // for the result. Per RFC 2251, OID 1.1 == no attributes.
+ BuildPropertySet(subtype, ds.PropertiesToLoad);
+
+ // Build the LDAP filter
+ string ldapValue = ADUtils.DateTimeToADString(value);
+ StringBuilder ldapFilter = new StringBuilder();
+
+ ldapFilter.Append(GetObjectClassPortion(subtype));
+ ldapFilter.Append("(|");
+
+ foreach (string ldapAttribute in ldapAttributes)
+ {
+ ldapFilter.Append("(");
+
+ switch (matchType)
+ {
+ case MatchType.Equals:
+ ldapFilter.Append(ldapAttribute);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapValue);
+ break;
+
+ case MatchType.NotEquals:
+ ldapFilter.Append("!(");
+ ldapFilter.Append(ldapAttribute);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapValue);
+ ldapFilter.Append(")");
+ break;
+
+ case MatchType.GreaterThanOrEquals:
+ ldapFilter.Append(ldapAttribute);
+ ldapFilter.Append(">=");
+ ldapFilter.Append(ldapValue);
+ break;
+
+ case MatchType.LessThanOrEquals:
+ ldapFilter.Append(ldapAttribute);
+ ldapFilter.Append("<=");
+ ldapFilter.Append(ldapValue);
+ break;
+
+ case MatchType.GreaterThan:
+ ldapFilter.Append("&");
+
+ // Greater-than-or-equals (or less-than-or-equals))
+ ldapFilter.Append("(");
+ ldapFilter.Append(ldapAttribute);
+ ldapFilter.Append(matchType == MatchType.GreaterThan ? ">=" : "<=");
+ ldapFilter.Append(ldapValue);
+ ldapFilter.Append(")");
+
+ // And not-equal
+ ldapFilter.Append("(!(");
+ ldapFilter.Append(ldapAttribute);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapValue);
+ ldapFilter.Append("))");
+
+ // And exists (need to include because of tristate LDAP logic)
+ ldapFilter.Append("(");
+ ldapFilter.Append(ldapAttribute);
+ ldapFilter.Append("=*)");
+ break;
+
+ case MatchType.LessThan:
+ goto case MatchType.GreaterThan;
+
+ default:
+ Debug.Fail("ADStoreCtx.FindByDate: fell off end looking for " + matchType.ToString());
+ break;
+ }
+
+ ldapFilter.Append(")");
+ }
+
+ ldapFilter.Append("))");
+
+ ds.Filter = ldapFilter.ToString();
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "FindByDate: using LDAP filter {0}", ds.Filter);
+
+ // Perform the search
+ SearchResultCollection src = ds.FindAll();
+ Debug.Assert(src != null);
+
+ // Create a ResultSet for the search results
+ ADEntriesSet resultSet = new ADEntriesSet(src, this);
+
+ return resultSet;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ ds.Dispose();
+ }
+ }
+
+ // Get groups of which p is a direct member
+ // search
+ // 1. search for group with same group id as principals primary group ID.
+ // Then
+ // 2. use enumeration to expand the users group membership
+ // ASQ will not work because we cannot correctly generate referrals if one of the users
+ // groups if from another domain in the forest.
+ internal override ResultSet GetGroupsMemberOf(Principal p)
+ {
+ // Enforced by the methods that call us
+ Debug.Assert(p.unpersisted == false);
+
+ DirectoryEntry gcPrincipalDe = null;
+ DirectorySearcher memberOfSearcher = null;
+ ADDNConstraintLinkedAttrSet.ResultValidator resultValidator = null;
+
+ try
+ {
+ if (p.fakePrincipal)
+ {
+ // If p is a fake principal, this will find the representation of p in the store
+ // (namely, a FPO), and return the groups of which that FPO is a member
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf: fake principal");
+ return GetGroupsMemberOf(p, this);
+ }
+
+ Debug.Assert(p.UnderlyingObject != null);
+
+ string primaryGroupDN = null;
+ ResultSet resultSet = null;
+ bool useASQ = false;
+ List<DirectoryEntry> roots = new List<DirectoryEntry>(1);
+ DirectorySearcher[] searchers = null;
+ IEnumerable[] enumerators = null;
+
+ DirectoryEntry principalDE = (DirectoryEntry)p.GetUnderlyingObject();
+
+ if ((p.ContextType == ContextType.ApplicationDirectory) || (p.Context.ServerInformation.OsVersion == DomainControllerMode.Win2k))
+ {
+ useASQ = false;
+ }
+ else
+ {
+ useASQ = true;
+ }
+
+ if (p.ContextType != ContextType.ApplicationDirectory)
+ {
+ // A users group membership that applies to a particular domain includes the domain's universal, local and global groups plus the
+ // universal groups from every other domain in the forest that the user is a member of. To get this list we must contact both a GlobalCatalog to get the forest
+ // universal list and a DC in the users domain to get the domain local groups which are not replicated to the GC.
+ // If we happen to get a GC in the same domain as the user
+ // then we don't also need a DC because the domain local group memberships will show up as well. The enumerator code that expands these lists must detect
+ // duplicates because the list of global groups will show up on both the GC and DC.
+ Debug.Assert(p.ContextType == ContextType.Domain);
+
+ Forest forest = Forest.GetForest(new DirectoryContext(DirectoryContextType.Forest, this.DnsForestName, this.credentials != null ? this.credentials.UserName : null, this.credentials != null ? this.credentials.Password : null));
+
+ DirectoryContext dc = new DirectoryContext(DirectoryContextType.Domain, this.DnsDomainName, this.credentials != null ? this.credentials.UserName : null, this.credentials != null ? this.credentials.Password : null);
+ DomainController dd = DomainController.FindOne(dc);
+
+ GlobalCatalog gc = null;
+
+ try
+ {
+ gc = forest.FindGlobalCatalog();
+
+ var gg = forest.FindAllGlobalCatalogs(dd.SiteName);
+ foreach (GlobalCatalog g in gg)
+ {
+ if (0 == string.Compare(this.DnsDomainName, g.Domain.Name, StringComparison.OrdinalIgnoreCase))
+ {
+ gc = g;
+ break;
+ }
+ }
+
+ roots.Add(new DirectoryEntry("GC://" + gc.Name + "/" + p.DistinguishedName, this.credentials != null ? this.credentials.UserName : null, this.credentials != null ? this.credentials.Password : null, this.AuthTypes));
+
+ if (0 != string.Compare(this.DnsDomainName, gc.Domain.Name, StringComparison.OrdinalIgnoreCase))
+ {
+ //useASQ = false;
+ roots.Add(principalDE);
+
+ //Since the GC does not belong to the same domain (as the principal object passed)
+ //We should make sure that we ignore domain local groups that we obtained from the cross-domain GC.
+ resultValidator = delegate (dSPropertyCollection resultPropCollection)
+ {
+ if (resultPropCollection["groupType"].Count > 0 && resultPropCollection["objectSid"].Count > 0)
+ {
+ int? groupTypeValue = (int?)resultPropCollection["groupType"][0];
+ if (groupTypeValue.HasValue && ((groupTypeValue.Value & ADGroupScope.Local) == ADGroupScope.Local))
+ {
+ byte[] sidByteArray = (byte[])resultPropCollection["objectSid"][0];
+ SecurityIdentifier resultSid = new SecurityIdentifier(sidByteArray, 0);
+ return ADUtils.AreSidsInSameDomain(p.Sid, resultSid);
+ }
+ }
+ return true; //Return true for all other case, including the case where we don't have permissions
+ //to read groupType/objectSid attribute then we declare the result as a match.
+ };
+ }
+ }
+ catch (System.DirectoryServices.ActiveDirectory.ActiveDirectoryOperationException e)
+ {
+ // if we can't get a GC then just fail.
+ throw new PrincipalOperationException(e.Message, e);
+ }
+ catch (System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException e)
+ {
+ // if we can't get a GC then just fail.
+ throw new PrincipalOperationException(e.Message, e);
+ }
+ finally
+ {
+ if (gc != null)
+ {
+ gc.Dispose();
+ }
+ if (forest != null)
+ {
+ forest.Dispose();
+ }
+ }
+ }
+
+ if (false == useASQ)
+ {
+ // If this is ADAM then we only need to use the original object.
+ // IF AD then we will use whatever enumerators we discovered above.
+ if (p.ContextType != ContextType.ApplicationDirectory)
+ {
+ int index = 0;
+ enumerators = new IEnumerable[roots.Count];
+
+ foreach (DirectoryEntry de in roots)
+ {
+ //If, de is not equal to principalDE then it must have been created by this function (above code)
+ //In that case de is NOT owned by any other modules outside. Hence, configure RangeRetriever to dispose the DirEntry on its dispose.
+ enumerators[index] = new RangeRetriever(de, "memberOf", (de != principalDE));
+ index++;
+ }
+ }
+ else
+ {
+ enumerators = new IEnumerable[1];
+ //Since principalDE is not owned by us,
+ //configuring RangeRetriever _NOT_ to dispose the DirEntry on its dispose.
+ enumerators[0] = new RangeRetriever(principalDE, "memberOf", false);
+ }
+ }
+ else
+ {
+ int index = 0;
+ searchers = new DirectorySearcher[roots.Count];
+
+ foreach (DirectoryEntry de in roots)
+ {
+ searchers[index] = SDSUtils.ConstructSearcher(de);
+ searchers[index].SearchScope = SearchScope.Base;
+ searchers[index].AttributeScopeQuery = "memberOf";
+ searchers[index].Filter = "(objectClass=*)";
+ searchers[index].CacheResults = false;
+
+ BuildPropertySet(typeof(GroupPrincipal), searchers[index].PropertiesToLoad);
+ index++;
+ }
+ }
+
+ string principalDN = (string)principalDE.Properties["distinguishedName"].Value;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf: principalDN={0}", principalDN);
+
+ principalDE.RefreshCache(new string[] { "memberOf", "primaryGroupID" });
+
+ if ((principalDE.Properties["primaryGroupID"].Count > 0) &&
+ (principalDE.Properties["objectSid"].Count > 0))
+ {
+ Debug.Assert(principalDE.Properties["primaryGroupID"].Count == 1);
+ Debug.Assert(principalDE.Properties["objectSid"].Count == 1);
+
+ int primaryGroupID = (int)principalDE.Properties["primaryGroupID"].Value;
+ byte[] principalSid = (byte[])principalDE.Properties["objectSid"].Value;
+
+ primaryGroupDN = GetGroupDnFromGroupID(principalSid, primaryGroupID);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf: primary group DN={0}", primaryGroupDN);
+ }
+
+ // We must use enumeration to expand the users group membership
+ // ASQ will not work because we cannot correctly generate referrals if one of the users
+ // groups if from another domain in the forest.
+
+ if (useASQ)
+ {
+ if (resultValidator != null)
+ {
+ resultSet = new ADDNConstraintLinkedAttrSet(
+ ADDNConstraintLinkedAttrSet.ConstraintType.ResultValidatorDelegateMatch,
+ resultValidator, principalDN, searchers, primaryGroupDN, null, false, this);
+ }
+ else
+ {
+ resultSet = new ADDNLinkedAttrSet(principalDN, searchers, primaryGroupDN, null, false, this);
+ }
+ }
+ else
+ {
+ if (resultValidator != null)
+ {
+ resultSet = new ADDNConstraintLinkedAttrSet(
+ ADDNConstraintLinkedAttrSet.ConstraintType.ResultValidatorDelegateMatch,
+ resultValidator, principalDN, enumerators, primaryGroupDN, null, false, this);
+ }
+ else
+ {
+ resultSet = new ADDNLinkedAttrSet(principalDN, enumerators, primaryGroupDN, null, false, this);
+ }
+ }
+ return resultSet;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ if (null != gcPrincipalDe)
+ {
+ gcPrincipalDe.Dispose();
+ }
+
+ if (null != memberOfSearcher)
+ {
+ memberOfSearcher.Dispose();
+ }
+ }
+ }
+
+ // Get groups from this ctx which contain a principal corresponding to foreignPrincipal
+ // (which is a principal from foreignContext)
+ internal override ResultSet GetGroupsMemberOf(Principal foreignPrincipal, StoreCtx foreignContext)
+ {
+ // Get the Principal's SID, so we can look it up by SID in our store
+ SecurityIdentifier Sid = foreignPrincipal.Sid;
+
+ if (Sid == null)
+ throw new InvalidOperationException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery);
+
+ // Search our store for a object with a matching SID. This could be a user/group/computer object,
+ // or a foreignSecurityPrincipal. Doesn't really matter --- either way, the store object will have a objectSid
+ // and a memberOf attribute.
+ // SID search
+ //
+ //
+ // If we can read the defaultNamingContext and retrive the well known path for the foreignSecurityPrincipal container start there.
+ // If we can only read the defaultNamingContext then start there
+ // Else just start at the base DN from the original context
+ //
+ // If the object was not found and we started at teh fsp container then search the entire DC.
+ // Else just exit. we have nothing else to search
+
+ // An object exists in the domain that contains links to all the groups it is a member of.
+ bool rootPrincipalExists = true;
+
+ if ((foreignContext is ADStoreCtx) && !(foreignContext is ADAMStoreCtx))
+ {
+ // We only need to check forest status for AD stores. Forest concept does not apply to ADAM.
+ ADStoreCtx foreignADStore = (ADStoreCtx)foreignContext;
+
+ // If same forest but different domain then we have a child or alternate tree domain. We don't have a starting user
+ // object and must do a search on all groups to find membership.
+ if (0 == string.Compare(foreignADStore.DnsForestName, this.DnsForestName, StringComparison.OrdinalIgnoreCase))
+ {
+ if (0 == string.Compare(foreignADStore.DnsDomainName, this.DnsDomainName, StringComparison.OrdinalIgnoreCase))
+ {
+ rootPrincipalExists = true;
+ }
+ else
+ {
+ rootPrincipalExists = false;
+ }
+ }
+ }
+
+ DirectoryEntry dncContainer = null;
+ string fspWkDn = null;
+ DirectoryEntry fspContainer = null;
+ ResultSet resultSet = null;
+ DirectorySearcher ds = null;
+
+ try
+ {
+ if (rootPrincipalExists)
+ {
+ if (this.DefaultNamingContext != null)
+ {
+ dncContainer = new DirectoryEntry(@"LDAP://" + this.UserSuppliedServerName + @"/" + this.DefaultNamingContext, Credentials != null ? this.Credentials.UserName : null, Credentials != null ? this.Credentials.Password : null, this.AuthTypes);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf(ctx): Read DNC of {0}", this.DefaultNamingContext);
+
+ fspWkDn = ADUtils.RetriveWkDn(dncContainer, this.DefaultNamingContext, this.UserSuppliedServerName, Constants.GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER_BYTE);
+
+ if (null != fspWkDn)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf(ctx): Read fsp DN {0}", fspWkDn);
+ fspContainer = new DirectoryEntry(fspWkDn, Credentials != null ? this.credentials.UserName : null, Credentials != null ? this.credentials.Password : null, this.authTypes);
+ }
+ }
+
+ ds = new DirectorySearcher((fspContainer != null) ? fspContainer : ((dncContainer != null ? dncContainer : this.ctxBase)));
+
+ // Pick some reasonable default values
+ ds.PageSize = 256;
+ ds.ServerTimeLimit = new TimeSpan(0, 0, 30); // 30 seconds
+
+ // Build the LDAP filter
+ // Converr the object to a SDDL format
+ string stringSid = Utils.SecurityIdentifierToLdapHexFilterString(Sid);
+ if (stringSid == null)
+ throw new InvalidOperationException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery);
+
+ ds.Filter = "(objectSid=" + stringSid + ")";
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf(ctx): using LDAP filter {0}", ds.Filter);
+
+ // We only need a few attributes
+ ds.PropertiesToLoad.Add("memberOf");
+ ds.PropertiesToLoad.Add("distinguishedName");
+ ds.PropertiesToLoad.Add("primaryGroupID");
+ ds.PropertiesToLoad.Add("objectSid");
+
+ // If no corresponding principal exists in this store, then by definition the principal isn't
+ // a member of any groups in this store.
+ SearchResult sr = ds.FindOne();
+
+ if (sr == null)
+ {
+ // no match so we better do a root level search in case we are targetting a domain where
+ // the user is not an FSP.
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf(ctx): No match");
+
+ // We already did a root level search so just exit.
+
+ if (null == fspWkDn)
+ return new EmptySet();
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf(ctx): performing DNC level search");
+
+ ds.SearchRoot = dncContainer;
+ sr = ds.FindOne();
+
+ if (sr == null)
+ return new EmptySet();
+ }
+
+ // Now that we found the corresponding principal, the rest is very similiar to the plain GetGroupsMemberOf()
+ // case, exception we're working with search results (SearchResult/ResultPropertyValueCollection) rather
+ // than DirectoryEntry/PropertyValueCollection.
+ string principalDN = (string)sr.Properties["distinguishedName"][0];
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf(ctx): match, DN={0}", principalDN);
+
+ //Here a new DirectoryEntry object is created by sr.GetDirectoryEntry() and passed
+ //to RangeRetriever object. Hence, configuring RangeRetriever to dispose the DirEntry on its dispose.
+ IEnumerable memberOf = new RangeRetriever(sr.GetDirectoryEntry(), "memberOf", true);
+
+ string primaryGroupDN = null;
+
+ if ((sr.Properties["primaryGroupID"].Count > 0) &&
+ (sr.Properties["objectSid"].Count > 0))
+ {
+ Debug.Assert(sr.Properties["primaryGroupID"].Count == 1);
+ Debug.Assert(sr.Properties["objectSid"].Count == 1);
+
+ int primaryGroupID = (int)sr.Properties["primaryGroupID"][0];
+ byte[] principalSid = (byte[])sr.Properties["objectSid"][0];
+
+ primaryGroupDN = GetGroupDnFromGroupID(principalSid, primaryGroupID);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf(ctx): primary group DN={0}", primaryGroupDN);
+ }
+
+ resultSet = new ADDNConstraintLinkedAttrSet(ADDNConstraintLinkedAttrSet.ConstraintType.ContainerStringMatch, this.ctxBase.Properties["distinguishedName"].Value, principalDN, new IEnumerable[] { memberOf }, primaryGroupDN, null, false, this);
+ }
+ else
+ {
+ // We don't need to retrive the Primary group ID here because we have already established that this user is not from this domain
+ // and the users primary group must be from the same domain as the user.
+ Debug.Assert(foreignPrincipal.ContextType != ContextType.ApplicationDirectory);
+
+ DirectorySearcher[] memberSearcher = { SDSUtils.ConstructSearcher(this.ctxBase) };
+ memberSearcher[0].Filter = "(&(objectClass=Group)(member=" + foreignPrincipal.DistinguishedName + "))";
+ memberSearcher[0].CacheResults = false;
+
+ resultSet = new ADDNLinkedAttrSet(foreignPrincipal.DistinguishedName, memberSearcher, null, null, false, this);
+ }
+
+ return resultSet;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ if (null != fspContainer)
+ fspContainer.Dispose();
+ if (null != ds)
+ ds.Dispose();
+ if (null != dncContainer)
+ dncContainer.Dispose();
+ }
+ }
+
+ private string GetGroupDnFromGroupID(byte[] userSid, int primaryGroupId)
+ {
+ IntPtr pGroupSid = IntPtr.Zero;
+ byte[] groupSid = null;
+
+ // This function is based on the technique in KB article 297951.
+
+ try
+ {
+ string sddlSid = Utils.ConvertSidToSDDL(userSid);
+ if (sddlSid != null)
+ {
+ // Next, we modify the SDDL SID to replace with final subauthority
+ // with the primary group's RID (the primaryGroupID)
+ int index = sddlSid.LastIndexOf('-');
+
+ if (index != -1)
+ {
+ sddlSid = sddlSid.Substring(0, index) + "-" + ((uint)primaryGroupId).ToString(CultureInfo.InvariantCulture);
+
+ // Now, we convert the SDDL back into a SID
+ if (UnsafeNativeMethods.ConvertStringSidToSid(sddlSid, ref pGroupSid))
+ {
+ // Now we convert the native SID to a byte[] SID
+ groupSid = Utils.ConvertNativeSidToByteArray(pGroupSid);
+ }
+ }
+ }
+ }
+ finally
+ {
+ if (pGroupSid != IntPtr.Zero)
+ UnsafeNativeMethods.LocalFree(pGroupSid);
+ }
+
+ if (groupSid != null)
+ {
+ return "<SID=" + Utils.ByteArrayToString(groupSid) + ">";
+ }
+
+ return null;
+ }
+
+ // Get groups of which p is a member, using AuthZ S4U APIs for recursive membership
+ internal override ResultSet GetGroupsMemberOfAZ(Principal p)
+ {
+ // Enforced by the methods that call us
+ Debug.Assert(p.unpersisted == false);
+ Debug.Assert(p is UserPrincipal);
+
+ // Get the user SID that AuthZ will use.
+ SecurityIdentifier SidObj = p.Sid;
+
+ if (SidObj == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "GetGroupsMemberOfAZ: no SID IC");
+ throw new InvalidOperationException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery);
+ }
+
+ byte[] sid = new byte[SidObj.BinaryLength];
+ SidObj.GetBinaryForm(sid, 0);
+
+ if (sid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "GetGroupsMemberOfAZ: bad SID IC");
+ throw new ArgumentException(StringResources.StoreCtxSecurityIdentityClaimBadFormat);
+ }
+
+ try
+ {
+ if (true == ADUtils.VerifyOutboundTrust(this.DnsDomainName, (this.credentials == null ? null : this.credentials.UserName), (this.credentials == null ? null : this.credentials.Password)))
+ {
+ return new AuthZSet(sid, this.credentials, this.contextOptions, this.FlatDomainName, this, this.ctxBase);
+ }
+ else
+ {
+ DirectoryEntry principalDE = (DirectoryEntry)p.UnderlyingObject;
+ string principalDN = (string)principalDE.Properties["distinguishedName"].Value;
+
+ return (new TokenGroupSet(principalDN, this, true));
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ // Get members of group g
+ // Need 2 searchers
+ // 1. Users with this group as their primary group ID
+ // 2. ASQ search against the member attribute on the group object for all contained objects.
+ internal override BookmarkableResultSet GetGroupMembership(GroupPrincipal g, bool recursive)
+ {
+ // Enforced by the methods that call us
+ Debug.Assert(g.unpersisted == false);
+
+ // Fake groups are a member of other groups, but they themselves have no members
+ // (they don't even exist in the store)
+ if (g.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupMembership: fake principal");
+ return new EmptySet();
+ }
+
+ Debug.Assert(g.UnderlyingObject != null);
+
+ try
+ {
+ DirectoryEntry groupDE = (DirectoryEntry)g.UnderlyingObject;
+
+ // Create a DirectorySearcher for users who are members of this group via their primaryGroupId attribute
+ DirectorySearcher ds = null;
+
+ if (groupDE.Properties["objectSid"].Count > 0)
+ {
+ Debug.Assert(groupDE.Properties["objectSid"].Count == 1);
+ byte[] groupSid = (byte[])groupDE.Properties["objectSid"][0];
+
+ ds = GetDirectorySearcherFromGroupID(groupSid);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupMembership: using LDAP filter={0}", ds.Filter);
+ }
+
+ string groupDN = (string)groupDE.Properties["distinguishedName"].Value;
+ BookmarkableResultSet resultSet = null;
+
+ // We must use enumeration to expand groups if their scope is Universal or Local
+ // or if the domain controller is w2k
+ // or if the context type is ApplicationDirectory (in AD LDS, Global groups can contain members from other partition)
+ // Universal and Local groups can contain members from other domains in the forest. When this occurs
+ // the referral is not generated correctly and we get an error.
+ //
+ if (g.Context.ContextType == ContextType.ApplicationDirectory ||
+ g.Context.ServerInformation.OsVersion == DomainControllerMode.Win2k ||
+ g.GroupScope != GroupScope.Global)
+ {
+ //Here the directory entry passed to RangeRetriever constructor belongs to
+ //the GroupPrincipal object supplied to this function, which is not owned by us.
+ //Hence, configuring RangeRetriever _NOT_ to dispose the DirEntry on its dispose.
+ IEnumerable members = new RangeRetriever(groupDE, "member", false);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupMembership: groupDN={0}", groupDN);
+ resultSet = new ADDNLinkedAttrSet(groupDN, new IEnumerable[] { members }, null, ds, recursive, this);
+ }
+ else
+ {
+ DirectorySearcher[] dsMembers = new DirectorySearcher[1];
+ dsMembers[0] = SDSUtils.ConstructSearcher((DirectoryEntry)g.UnderlyingObject);
+ dsMembers[0].AttributeScopeQuery = "member";
+ dsMembers[0].SearchScope = SearchScope.Base;
+ dsMembers[0].Filter = "(objectClass=*)";
+ dsMembers[0].CacheResults = false;
+
+ BuildPropertySet(typeof(UserPrincipal), dsMembers[0].PropertiesToLoad);
+ BuildPropertySet(typeof(GroupPrincipal), dsMembers[0].PropertiesToLoad);
+ resultSet = new ADDNLinkedAttrSet(groupDN, dsMembers, null, ds, recursive, this);
+ }
+
+ return resultSet;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ private DirectorySearcher GetDirectorySearcherFromGroupID(byte[] groupSid)
+ {
+ Debug.Assert(groupSid != null);
+
+ // Get the group's RID from the group's SID
+ int groupRid = Utils.GetLastRidFromSid(groupSid);
+
+ // Build a DirectorySearcher for users whose primaryGroupId == the group's RID
+ DirectorySearcher ds = new DirectorySearcher(this.ctxBase);
+ ds.Filter = GetObjectClassPortion(typeof(Principal)) + "(primaryGroupId=" + groupRid.ToString(CultureInfo.InvariantCulture) + "))";
+
+ // Pick some reasonable default values
+ ds.PageSize = 256;
+ ds.ServerTimeLimit = new TimeSpan(0, 0, 30); // 30 seconds
+
+ BuildPropertySet(typeof(Principal), ds.PropertiesToLoad);
+
+ return ds;
+ }
+
+ // Is p a member of g in the store?
+ internal override bool SupportsNativeMembershipTest { get { return true; } }
+
+ /// First check direct group membership by using DE.IsMember
+ /// If this fails then we may have a ForeignSecurityPrincipal so search for Foreign Security Principals
+ /// With the p's SID and then call IsMember with the ADS Path returned from the search.
+ internal override bool IsMemberOfInStore(GroupPrincipal g, Principal p)
+ {
+ Debug.Assert(g.unpersisted == false);
+ Debug.Assert(p.unpersisted == false);
+
+ // Consistent with GetGroupMembership, a group that is a fake principal has no members
+ if (g.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "IsMemberOfInStore: fake group");
+ return false;
+ }
+
+ // AD Groups can only have AD principals as members
+ if (p.ContextType != ContextType.Domain && p.ContextType != ContextType.ApplicationDirectory)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "IsMemberOfInStore: member is not a domain principal");
+ return false;
+ }
+
+ Debug.Assert(g.UnderlyingObject != null && g.UnderlyingObject is DirectoryEntry);
+ UnsafeNativeMethods.IADsGroup adsGroup = (UnsafeNativeMethods.IADsGroup)((DirectoryEntry)g.UnderlyingObject).NativeObject;
+ IEnumerable cachedMembersEnum = null; //This variables stores a reference to the direct members enumerator of the group.
+
+ // Only real principals can be directly a member of the group, since only real principals
+ // actually exist in the store.
+ if (!p.fakePrincipal)
+ {
+ Debug.Assert(p.UnderlyingObject != null && p.UnderlyingObject is DirectoryEntry);
+
+ //// Test for direct membership
+ ////
+
+ DirectoryEntry principalDE = (DirectoryEntry)p.UnderlyingObject;
+ DirectoryEntry groupDE = (DirectoryEntry)g.UnderlyingObject;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "IsMemberOfInStore: real principal, DN={0}", principalDE.Path);
+ string principalDN = (string)principalDE.Properties["distinguishedName"].Value;
+
+ // we want to find if a group is "small", meaning that it has less than MaxValRange values (usually 1500)
+ // the property list for the searcher of a a group has "member" attribute. if there are more results than MaxValRange, there will also be a "member;range=..." attribute
+ if (g.IsSmallGroup())
+ {
+ // small groups has special search object that holds the member attribute so we use it for our search (no need to use the DirectoryEntry)
+ Debug.Assert(g.SmallGroupMemberSearchResult != null);
+ cachedMembersEnum = g.SmallGroupMemberSearchResult.Properties["member"];
+ if ((g.SmallGroupMemberSearchResult != null) && g.SmallGroupMemberSearchResult.Properties["member"].Contains(principalDN))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ // this is a large group. use range retrieval instead of simple attribute check.
+ RangeRetriever rangeRetriever = new RangeRetriever(groupDE, "member", false);
+ rangeRetriever.CacheValues = true;
+ foreach (string memberDN in rangeRetriever)
+ {
+ if (principalDN.Equals(memberDN, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+ rangeRetriever.Reset(); //Reset range-retriever enum, so that it can be traversed again.
+ cachedMembersEnum = rangeRetriever;
+ }
+ }
+
+ //
+ // Might be an FPO (either a real principal from another forest, or a fake principal
+ // that AD represents as an FPO). Search for the FPO, and test its DN for membership.
+ //
+
+ // Get the Principal's SID, so we can look it up by SID in our store
+ SecurityIdentifier Sid = p.Sid;
+
+ if (Sid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "IsMemberOfInStore: no SID IC or null UrnValue");
+ throw new ArgumentException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery);
+ }
+ DirectoryEntry defaultNCDirEntry = null;
+ DirectorySearcher ds = null;
+
+ try
+ {
+ string path = String.Format(
+ CultureInfo.InvariantCulture,
+ "LDAP://{0}/{1}",
+ String.IsNullOrEmpty(this.UserSuppliedServerName) ? this.DnsHostName : this.UserSuppliedServerName,
+ this.ContextBasePartitionDN
+ );
+
+ defaultNCDirEntry = SDSUtils.BuildDirectoryEntry(path, this.credentials, this.authTypes);
+
+ ds = new DirectorySearcher(defaultNCDirEntry);
+
+ // Pick some reasonable default values
+ ds.ServerTimeLimit = new TimeSpan(0, 0, 30); // 30 seconds
+
+ // Build the LDAP filter, Convert the sid to SDDL format
+ string stringSid = Utils.SecurityIdentifierToLdapHexFilterString(Sid);
+ if (stringSid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "IsMemberOfInStore: bad SID IC");
+ throw new ArgumentException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery);
+ }
+
+ ds.Filter = "(&(objectClass=foreignSecurityPrincipal)(objectSid=" + stringSid + "))";
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "IsMemberOfInStore: FPO principal, using LDAP filter {0}",
+ ds.Filter);
+
+ ds.PropertiesToLoad.Add("distinguishedName");
+
+ SearchResult sr = ds.FindOne();
+
+ // No FPO ---> not a member
+ if (sr == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "IsMemberOfInStore: no FPO found");
+ return false;
+ }
+ string fpoDN = (string)sr.Properties["distinguishedName"][0];
+ foreach (string memberDN in cachedMembersEnum)
+ {
+ if (string.Equals(fpoDN, memberDN, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ if (ds != null)
+ {
+ ds.Dispose();
+ }
+ if (defaultNCDirEntry != null)
+ {
+ defaultNCDirEntry.Dispose();
+ }
+ }
+ }
+
+ // The only reason a Clear() operation can not be performed on the group is if there
+ // are one or more members on the store who are a member of the group by virtue of their
+ // primaryGroupId, rather than by the group's "member" attribute.
+ internal override bool CanGroupBeCleared(GroupPrincipal g, out string explanationForFailure)
+ {
+ explanationForFailure = null;
+
+ // If the group is unpersisted, there are certainly no principals in the store who
+ // are a member of it by vitue of primaryGroupId. If the group is a fake group, it has no
+ // members. Either way, they can clear it.
+ if (g.unpersisted || g.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "CanGroupBeCleared: unpersisted={0}, fake={1}",
+ g.unpersisted,
+ g.fakePrincipal);
+ return true;
+ }
+
+ Debug.Assert(g.UnderlyingObject != null);
+ DirectoryEntry groupDE = (DirectoryEntry)g.UnderlyingObject;
+
+ // Create a DirectorySearcher for users who are members of this group via their primaryGroupId attribute
+ DirectorySearcher ds = null;
+
+ try
+ {
+ if (groupDE.Properties["objectSid"].Count > 0)
+ {
+ Debug.Assert(groupDE.Properties["objectSid"].Count == 1);
+ byte[] groupSid = (byte[])groupDE.Properties["objectSid"][0];
+
+ ds = GetDirectorySearcherFromGroupID(groupSid);
+
+ // We only need to know if there's at least one such user
+ ds.SizeLimit = 1;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "IsMemberOfInStore: using LDAP filter {0}", ds.Filter);
+
+ SearchResult sr = ds.FindOne();
+
+ if (sr != null)
+ {
+ // there is such a member, we can't clear the group
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "IsMemberOfInStore: found member, can't clear");
+
+ explanationForFailure = StringResources.ADStoreCtxCantClearGroup;
+ return false;
+ }
+ else
+ {
+ // no such members, we can clear the group
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "IsMemberOfInStore: no member, can clear");
+
+ return true;
+ }
+ }
+ else
+ {
+ // We don't have sufficient information. Assume we can clear it.
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "IsMemberOfInStore: can't search, assume can clear");
+ return true;
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ if (ds != null)
+ ds.Dispose();
+ }
+ }
+
+ // The only reason we wouldn't be able to remove this member is if it's a member by virtue of its
+ // primaryGroupId rather than the group's "member" attribute
+ internal override bool CanGroupMemberBeRemoved(GroupPrincipal g, Principal member, out string explanationForFailure)
+ {
+ explanationForFailure = null;
+
+ // If the member is unpersisted, it has no primaryGroupId attribute that could point to the group.
+ // If the member is a fake princiapl, it also has no primaryGroupId attribute that could point to the group.
+ // So either way, we have no objections to it being removed from the group.
+ if (member.unpersisted || member.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "CanGroupMemberBeRemoved: member unpersisted={0}, fake={1}",
+ member.unpersisted,
+ member.fakePrincipal);
+
+ return true;
+ }
+
+ // If the group is unpersisted, then clearly there is no way the principal is
+ // a member of it by vitue of primaryGroupId. If the group is a fake group, it has no
+ // members and so we don't care about it.
+ if (g.unpersisted || g.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "CanGroupMemberBeRemoved: group unpersisted={0}, fake={1}",
+ g.unpersisted,
+ g.fakePrincipal);
+ return true;
+ }
+
+ // ADAM groups can have AD or ADAM members, AD groups can only have AD members
+ //, but we could be called before our caller
+ // has verified the principal being passed in as the member. Just ignore it if the member isn't an AD principal,
+ // it'll be caught later in PrincipalCollection.Remove().
+ if ((g.ContextType == ContextType.Domain && member.ContextType != ContextType.Domain) ||
+ (member.ContextType != ContextType.Domain && member.ContextType != ContextType.ApplicationDirectory))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "CanGroupMemberBeRemoved: member is not a domain or application directory principal");
+ return true;
+ }
+
+ try
+ {
+ Debug.Assert(g.UnderlyingObject != null);
+ Debug.Assert(member.UnderlyingObject != null);
+ DirectoryEntry groupDE = (DirectoryEntry)g.UnderlyingObject;
+ DirectoryEntry memberDE = (DirectoryEntry)member.UnderlyingObject;
+
+ if ((groupDE.Properties["objectSid"].Count > 0) &&
+ (memberDE.Properties["primaryGroupID"].Count > 0))
+ {
+ Debug.Assert(groupDE.Properties["objectSid"].Count == 1);
+ Debug.Assert(memberDE.Properties["primaryGroupID"].Count == 1);
+
+ byte[] groupSid = (byte[])groupDE.Properties["objectSid"][0];
+ int primaryGroupID = (int)memberDE.Properties["primaryGroupID"][0];
+
+ int groupRid = Utils.GetLastRidFromSid(groupSid);
+
+ if (groupRid == primaryGroupID)
+ {
+ // It is a primary group member, we can't remove it.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "CanGroupMemberBeRemoved: primary group member (rid={0}), can't remove",
+ groupRid);
+
+ explanationForFailure = StringResources.ADStoreCtxCantRemoveMemberFromGroup;
+ return false;
+ }
+ else
+ {
+ // It's not a primary group member, we can remove it.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "CanGroupMemberBeRemoved: not primary group member (group rid={0}, primary group={1}), can remove",
+ groupRid,
+ primaryGroupID);
+
+ return true;
+ }
+ }
+ else
+ {
+ // We don't have sufficient information. Assume we can remove it.
+ // If we can't, we'll get an exception when we try to save the changes.
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "CanGroupMemberBeRemoved: can't test, assume can remove");
+ return true;
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ //
+ // Cross-store support
+ //
+
+ // Given a native store object that represents a "foreign" principal (e.g., a FPO object in this store that
+ // represents a pointer to another store), maps that representation to the other store's StoreCtx and returns
+ // a Principal from that other StoreCtx. The implementation of this method is highly dependent on the
+ // details of the particular store, and must have knowledge not only of this StoreCtx, but also of how to
+ // interact with other StoreCtxs to fulfill the request.
+ //
+ // This method is typically used by ResultSet implementations, when they're iterating over a collection
+ // (e.g., of group membership) and encounter a entry that represents a foreign principal.
+ internal override Principal ResolveCrossStoreRefToPrincipal(object o)
+ {
+ Debug.Assert(o is DirectoryEntry);
+ Debug.Assert(ADUtils.IsOfObjectClass((DirectoryEntry)o, "foreignSecurityPrincipal"));
+
+ try
+ {
+ // Get the SID of the foreign principal
+ DirectoryEntry fpoDE = (DirectoryEntry)o;
+
+ if (fpoDE.Properties["objectSid"].Count == 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "ResolveCrossStoreRefToPrincipal: no objectSid found");
+ throw new PrincipalOperationException(StringResources.ADStoreCtxCantRetrieveObjectSidForCrossStore);
+ }
+
+ Debug.Assert(fpoDE.Properties["objectSid"].Count == 1);
+
+ byte[] sid = (byte[])fpoDE.Properties["objectSid"].Value;
+
+ // What type of SID is it?
+ SidType sidType = Utils.ClassifySID(sid);
+
+ if (sidType == SidType.FakeObject)
+ {
+ // It's a FPO for something like NT AUTHORITY\NETWORK SERVICE.
+ // There's no real store object corresponding to this FPO, so
+ // fake a Principal.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "ResolveCrossStoreRefToPrincipal: fake principal, SID={0}",
+ Utils.ByteArrayToString(sid));
+
+ return ConstructFakePrincipalFromSID(sid);
+ }
+
+ StoreCtx foreignStoreCtx;
+ if (sidType == SidType.RealObjectFakeDomain)
+ {
+ // This is a BUILTIN object. It's a real object on the store we're connected to, but LookupSid
+ // will tell us it's a member of the BUILTIN domain. Resolve it as a principal on our store.
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "ResolveCrossStoreRefToPrincipal: builtin principal");
+
+ foreignStoreCtx = this;
+ }
+ else
+ {
+ // Ask the OS to resolve the SID to its target.
+ UnsafeNativeMethods.IAdsObjectOptions objOptions = (UnsafeNativeMethods.IAdsObjectOptions)this.ctxBase.NativeObject;
+ string serverName = (string)objOptions.GetOption(0 /* == ADS_OPTION_SERVERNAME */);
+
+ int accountUsage = 0;
+
+ string name;
+ string domainName;
+
+ int err = Utils.LookupSid(serverName, this.credentials, sid, out name, out domainName, out accountUsage);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn,
+ "ADStoreCtx",
+ "ResolveCrossStoreRefToPrincipal: LookupSid failed, err={0}, server={1}",
+ err,
+ serverName);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.ADStoreCtxCantResolveSidForCrossStore,
+ err));
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "ResolveCrossStoreRefToPrincipal: LookupSid found {0} in {1}",
+ name,
+ domainName);
+
+ // Since this is AD, the remote principal must be an AD principal.
+ // Build a PrincipalContext for the store which owns the principal
+
+ // We are now connecting to AD so change to negotiate with signing and sealing
+
+ ContextOptions remoteOptions = DefaultContextOptions.ADDefaultContextOption;
+
+#if USE_CTX_CACHE
+ PrincipalContext remoteCtx = SDSCache.Domain.GetContext(domainName, this.credentials, remoteOptions);
+#else
+ PrincipalContext remoteCtx = new PrincipalContext(
+ ContextType.Domain,
+ domainName,
+ null,
+ (this.credentials != null ? credentials.UserName : null),
+ (this.credentials != null ? credentials.Password : null),
+ remoteOptions);
+
+#endif
+ foreignStoreCtx = remoteCtx.QueryCtx;
+ }
+
+ Principal p = foreignStoreCtx.FindPrincipalByIdentRef(
+ typeof(Principal),
+ UrnScheme.SidScheme,
+ (new SecurityIdentifier(sid, 0)).ToString(),
+ DateTime.UtcNow);
+
+ if (p != null)
+ return p;
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "ResolveCrossStoreRefToPrincipal: no matching principal");
+ throw new PrincipalOperationException(StringResources.ADStoreCtxFailedFindCrossStoreTarget);
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ // Returns true if AccountInfo is supported for the specified principal, false otherwise.
+ // Used when a application tries to access the AccountInfo property of a newly-inserted
+ // (not yet persisted) AuthenticablePrincipal, to determine whether it should be allowed.
+ internal override bool SupportsAccounts(AuthenticablePrincipal p)
+ {
+ // Fake principals do not have store objects, so they certainly don't have stored account info.
+ if (p.fakePrincipal)
+ return false;
+
+ // Computer is a subclass of user in AD, and both therefore support account info.
+ return true;
+ }
+
+ // Returns the set of credential types supported by this store for the specified principal.
+ // Used when a application tries to access the PasswordInfo property of a newly-inserted
+ // (not yet persisted) AuthenticablePrincipal, to determine whether it should be allowed.
+ // Also used to implement AuthenticablePrincipal.SupportedCredentialTypes.
+ internal override CredentialTypes SupportedCredTypes(AuthenticablePrincipal p)
+ {
+ // Fake principals do not have store objects, so they certainly don't have stored creds.
+ if (p.fakePrincipal)
+ return (CredentialTypes)0;
+
+ return CredentialTypes.Password | CredentialTypes.Certificate;
+ }
+
+ //
+ // When called, this function does a GetInfoEx() to preload the DirectoryEntry's
+ // property cache with all the attributes we'll be using. This avoids DirectoryEntry
+ // doing an implicit GetInfo() and pulling down every attribute.
+ //
+ // This function is currently loading every attribute from the directory instead of using the known list.
+ internal void LoadDirectoryEntryAttributes(DirectoryEntry de)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadDirectoryEntryAttributes, path={0}", de.Path);
+
+ string[] ldapAttributesUsed = new string[]
+ {
+ "accountExpires",
+ "badPasswordTime",
+ "badPwdCount",
+ "displayName",
+ "distinguishedName",
+ "description",
+ "employeeID",
+ "givenName",
+ "groupType",
+ "homeDirectory",
+ "homeDrive",
+ "lastLogon",
+ "lastLogonTimestamp",
+ "lockoutTime",
+ "logonHours",
+ "mail",
+ "member",
+ "memberOf",
+ "middleName",
+ "msDS-User-Account-Control-Computed",
+ "ntSecurityDescriptor",
+ "objectClass",
+ "objectGuid",
+ "objectSid",
+ "primaryGroupID",
+ "pwdLastSet",
+ "samAccountName",
+ "scriptPath",
+ "servicePrincipalName",
+ "sn",
+ "telephoneNumber",
+ "userAccountControl",
+ "userCertificate",
+ "userPrincipalName",
+ "userWorkstations"
+ };
+ try
+ {
+ // de.RefreshCache(ldapAttributesUsed);
+ de.RefreshCache();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ //
+ // Construct a fake Principal to represent a well-known SID like
+ // "\Everyone" or "NT AUTHORITY\NETWORK SERVICE"
+ //
+ internal override Principal ConstructFakePrincipalFromSID(byte[] sid)
+ {
+ UnsafeNativeMethods.IAdsObjectOptions objOptions = (UnsafeNativeMethods.IAdsObjectOptions)this.ctxBase.NativeObject;
+ string serverName = (string)objOptions.GetOption(0 /* == ADS_OPTION_SERVERNAME */);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "ConstructFakePrincipalFromSID: sid={0}, server={1}, authority={2}",
+ Utils.ByteArrayToString(sid),
+ serverName,
+ this.DnsDomainName);
+
+ Principal p = Utils.ConstructFakePrincipalFromSID(
+ sid,
+ this.OwningContext,
+ serverName,
+ this.credentials,
+ this.DnsDomainName);
+
+ // Assign it a StoreKey
+ ADStoreKey key = new ADStoreKey(this.DnsDomainName, sid);
+ p.Key = key;
+
+ return p;
+ }
+
+ //
+ // Private data
+ //
+
+ ///
+ /// <summary>
+ /// Returns the DN of the Partition to which the user supplied
+ /// context base (this.ctxBase) belongs.
+ /// </summary>
+ ///
+ internal string ContextBasePartitionDN
+ {
+ get
+ {
+ if (this.contextBasePartitionDN == null)
+ {
+ lock (this.domainInfoLock)
+ {
+ if (contextBasePartitionDN == null)
+ LoadDomainInfo();
+ }
+ }
+
+ return this.contextBasePartitionDN;
+ }
+ }
+
+ internal string DefaultNamingContext
+ {
+ get
+ {
+ if (this.defaultNamingContext == null)
+ {
+ lock (this.domainInfoLock)
+ {
+ if (defaultNamingContext == null)
+ LoadDomainInfo();
+ }
+ }
+
+ return this.defaultNamingContext;
+ }
+ }
+
+ private string FlatDomainName
+ {
+ get
+ {
+ if (this.domainFlatName == null)
+ {
+ lock (this.domainInfoLock)
+ {
+ if (domainFlatName == null)
+ LoadDomainInfo();
+ }
+ }
+
+ return this.domainFlatName;
+ }
+ }
+
+ internal string DnsDomainName
+ {
+ get
+ {
+ if (this.domainDnsName == null)
+ {
+ lock (this.domainInfoLock)
+ {
+ if (domainDnsName == null)
+ LoadDomainInfo();
+ }
+ }
+
+ return this.domainDnsName;
+ }
+ }
+
+ internal string DnsHostName
+ {
+ get
+ {
+ if (this.dnsHostName == null)
+ {
+ lock (this.domainInfoLock)
+ {
+ if (dnsHostName == null)
+ LoadDomainInfo();
+ }
+ }
+
+ return this.dnsHostName;
+ }
+ }
+
+ internal string DnsForestName
+ {
+ get
+ {
+ if (this.forestDnsName == null)
+ {
+ lock (this.domainInfoLock)
+ {
+ if (forestDnsName == null)
+ LoadDomainInfo();
+ }
+ }
+
+ return this.forestDnsName;
+ }
+ }
+
+ internal string UserSuppliedServerName
+ {
+ get
+ {
+ if (this.userSuppliedServerName == null)
+ {
+ lock (this.domainInfoLock)
+ {
+ if (this.userSuppliedServerName == null)
+ LoadDomainInfo();
+ }
+ }
+
+ return this.userSuppliedServerName;
+ }
+ }
+
+ private ulong LockoutDuration
+ {
+ get
+ {
+ // We test domainDnsName for null because lockoutDuration could legitimately be 0,
+ // but lockoutDuration is valid iff domainDnsName is non-null
+ if (this.domainDnsName == null)
+ {
+ lock (this.domainInfoLock)
+ {
+ if (domainDnsName == null)
+ LoadDomainInfo();
+ }
+ }
+
+ return this.lockoutDuration;
+ }
+ }
+
+ protected object domainInfoLock = new object();
+ protected string domainFlatName = null;
+ protected string domainDnsName = null;
+ protected string forestDnsName = null;
+ protected string userSuppliedServerName = null;
+ protected string defaultNamingContext = null;
+ protected string contextBasePartitionDN = null; //contains the DN of the Partition to which the user supplied context base (this.ctxBase) belongs.
+ protected string dnsHostName = null;
+ protected ulong lockoutDuration = 0;
+
+ protected enum StoreCapabilityMap
+ {
+ ASQSearch = 1,
+ }
+
+ protected StoreCapabilityMap storeCapability = 0;
+
+ // Must be called inside of lock(domainInfoLock)
+ virtual protected void LoadDomainInfo()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo");
+
+ Debug.Assert(this.ctxBase != null);
+
+ //
+ // DNS Domain Name
+ //
+
+ // We need to connect to the server's rootDse to get the naming context
+ // From that, we can build the DNS Domain Name
+ this.dnsHostName = ADUtils.GetServerName(this.ctxBase);
+
+ string dnsDomainName = "";
+
+ using (DirectoryEntry rootDse = new DirectoryEntry("LDAP://" + this.dnsHostName + "/rootDse", "", "", AuthenticationTypes.Anonymous))
+ {
+ this.defaultNamingContext = (string)rootDse.Properties["defaultNamingContext"][0];
+ this.contextBasePartitionDN = this.defaultNamingContext;
+
+ // Split the naming context's DN into its RDNs
+ string[] ncComponents = defaultNamingContext.Split(new char[] { ',' });
+
+ StringBuilder sb = new StringBuilder();
+
+ // Reassemble the RDNs (minus the tag) into the DNS domain name
+ foreach (string component in ncComponents)
+ {
+ // If it's not a "DC=" component, skip it
+ if ((component.Length > 3) &&
+ (String.Compare(component.Substring(0, 3), "DC=", StringComparison.OrdinalIgnoreCase) == 0))
+ {
+ sb.Append(component.Substring(3));
+ sb.Append(".");
+ }
+ }
+
+ dnsDomainName = sb.ToString();
+
+ // The loop added an extra period at the end. Remove it.
+ if (dnsDomainName.Length > 0)
+ dnsDomainName = dnsDomainName.Substring(0, dnsDomainName.Length - 1);
+
+ this.domainDnsName = dnsDomainName;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo: using DNS domain name {0}", dnsDomainName);
+ }
+
+ //
+ // NetBios (flat) Domain Name, and DNS Forest Name
+ //
+ // Given the DNS domain name, we use DsGetDcName to get the flat name.
+ // The same DsGetDcName call also retrieves the DNS forest name as a side effect.
+ //
+
+ // DS_IS_DNS_NAME | DS_RETURN_FLAT_NAME | DS_DIRECTORY_SERVICE_REQUIRED | DS_BACKGROUND_ONLY
+ int flags = unchecked((int)(0x00020000 | 0x80000000 | 0x00000010 | 0x00000100));
+ UnsafeNativeMethods.DomainControllerInfo info = Utils.GetDcName(null, dnsDomainName, null, flags);
+
+ this.domainFlatName = info.DomainName;
+ this.forestDnsName = info.DnsForestName;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "LoadComputerInfo: using domainFlatName={0}, forestDnsName={1}",
+ this.domainFlatName,
+ this.forestDnsName);
+
+ //
+ // Lockout duration
+ //
+ // Query the domain NC head to determine the lockout duration. Note that this is stored
+ // on the server as a negative filetime.
+ //
+ DirectoryEntry domainNC = SDSUtils.BuildDirectoryEntry(
+ "LDAP://" + this.dnsHostName + "/" + this.defaultNamingContext,
+ this.credentials,
+ this.authTypes);
+
+ // So we don't load every property
+ domainNC.RefreshCache(new string[] { "lockoutDuration" });
+
+ if (domainNC.Properties["lockoutDuration"].Count > 0)
+ {
+ Debug.Assert(domainNC.Properties["lockoutDuration"].Count == 1);
+ long negativeLockoutDuration = ADUtils.LargeIntToInt64((UnsafeNativeMethods.IADsLargeInteger)domainNC.Properties["lockoutDuration"][0]);
+ Debug.Assert(negativeLockoutDuration <= 0);
+ ulong lockoutDuration = (ulong)(-negativeLockoutDuration);
+ this.lockoutDuration = lockoutDuration;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo: using lockout duration {0}", lockoutDuration);
+ }
+
+ //
+ // User supplied name
+ //
+ UnsafeNativeMethods.Pathname pathCracker = new UnsafeNativeMethods.Pathname();
+ UnsafeNativeMethods.IADsPathname pathName = (UnsafeNativeMethods.IADsPathname)pathCracker;
+
+ pathName.Set(this.ctxBase.Path, 1 /* ADS_SETTYPE_FULL */);
+
+ try
+ {
+ this.userSuppliedServerName = pathName.Retrieve(9 /*ADS_FORMAT_SERVER */);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo: using user-supplied name {0}", this.userSuppliedServerName);
+ }
+ catch (COMException e)
+ {
+ if (((uint)e.ErrorCode) == ((uint)0x80005000)) // E_ADS_BAD_PATHNAME
+ {
+ // Serverless path
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo: using empty string as user-supplied name");
+ this.userSuppliedServerName = "";
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "ADStoreCtx",
+ "LoadComputerInfo: caught COMException {0} {1} looking for user-supplied name",
+ e.ErrorCode,
+ e.Message);
+
+ throw;
+ }
+ }
+ }
+
+ internal override bool IsValidProperty(Principal p, string propertyName)
+ {
+ return ((Hashtable)s_propertyMappingTableByProperty[this.MappingTableIndex]).Contains(propertyName);
+ }
+ }
+}
+
+//#endif // PAPI_AD
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs
new file mode 100644
index 0000000000..dd6e878673
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs
@@ -0,0 +1,1728 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Text;
+using System.Globalization;
+using System.Security.Cryptography.X509Certificates;
+using System.Runtime.InteropServices;
+using System.Net;
+using System.Security.Principal;
+
+using System.DirectoryServices;
+
+using MACLPrinc = System.Security.Principal;
+using System.Security.AccessControl;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal partial class ADStoreCtx : StoreCtx
+ {
+ //
+ // Native <--> Principal
+ //
+
+ // For modified object, pushes any changes (including IdentityClaim changes)
+ // into the underlying store-specific object (e.g., DirectoryEntry) and returns the underlying object.
+ // For unpersisted object, creates a underlying object if one doesn't already exist (in
+ // Principal.UnderlyingObject), then pushes any changes into the underlying object.
+ internal override object PushChangesToNative(Principal p)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Entering PushChangesToNative, type={0}", p.GetType());
+
+ try
+ {
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+
+ if (de == null)
+ {
+ // Must be a newly-inserted Principal for which PushChangesToNative has not yet
+ // been called.
+
+ // Determine the objectClass of the AD entry we'll be creating
+ string objectClass;
+ Type principalType = p.GetType();
+ // read the rdnPrefix off of the class attribute. This defaults to CN for the internal classes
+ string rdnPrefix = p.ExtensionHelper.RdnPrefix;
+ string rdnValue = null;
+ string baseObjectRdnPrefix = null;
+
+ if (principalType == typeof(UserPrincipal))
+ objectClass = "user";
+ else if (principalType == typeof(GroupPrincipal))
+ objectClass = "group";
+ else if (principalType == typeof(ComputerPrincipal))
+ objectClass = "computer";
+ else
+ {
+ objectClass = p.ExtensionHelper.StructuralObjectClass;
+
+ if (null == objectClass || null == rdnPrefix)
+ {
+ throw new InvalidOperationException(StringResources.ExtensionInvalidClassAttributes);
+ }
+
+ // We need to determine if this class is dervived from one of the base classes but has a different RdnPrefix
+ // For the base objects ( User, Computer and Group ) Their RDNPrefix is a required field along with the RDNPrefix for the
+ // derived object. This is only done for classes that derive from User, Computer or Group. If a user derives his own class from AuthPrincipal
+ // they are responsible for setting all required base class properties.
+
+ if (principalType.IsSubclassOf(typeof(GroupPrincipal)) ||
+ principalType.IsSubclassOf(typeof(UserPrincipal)) ||
+ principalType.IsSubclassOf(typeof(ComputerPrincipal)))
+ {
+ DirectoryRdnPrefixAttribute[] MyAttribute =
+ (DirectoryRdnPrefixAttribute[])Attribute.GetCustomAttributes(principalType.BaseType, typeof(DirectoryRdnPrefixAttribute), false);
+
+ if (MyAttribute == null)
+ throw new InvalidOperationException(StringResources.ExtensionInvalidClassAttributes);
+
+ string defaultRdn = null;
+
+ // Search for the rdn prefix. This will use either the prefix that has a context type
+ // that matches the principals context or the first rdnPrefix that has a null context type
+ for (int i = 0; i < MyAttribute.Length; i++)
+ {
+ if ((MyAttribute[i].Context == null && null == defaultRdn) ||
+ (p.ContextType == MyAttribute[i].Context))
+ {
+ defaultRdn = MyAttribute[i].RdnPrefix;
+ }
+ }
+
+ // If the base objects RDN prefix is not the same as the dervied class then we need to set both
+ if (defaultRdn != rdnPrefix)
+ {
+ baseObjectRdnPrefix = defaultRdn;
+ }
+ }
+ }
+
+ // Determine a RDN for the AD entry we'll be creating.
+ // In order, try:
+ // (1) The NAme is they set one.
+ // (2) The SAM account name if they set one
+ string rdn = null;
+
+ if (p.GetChangeStatusForProperty(PropertyNames.PrincipalName))
+ {
+ // They set a display name.
+ string name = (string)p.GetValueForProperty(PropertyNames.PrincipalName);
+
+ if ((name != null) && (name.Length > 0))
+ rdnValue = ADUtils.EscapeDNComponent(name);
+ }
+
+ if (rdnValue == null)
+ {
+ if (p.GetChangeStatusForProperty(PropertyNames.PrincipalSamAccountName))
+ {
+ // They set a sAMAccountName. If it's an invalid claim, we'll just ignore it here.
+ // The error will get picked up in IdentClaimToLdapConverter.
+ string samAccountName = (string)p.GetValueForProperty(PropertyNames.PrincipalSamAccountName);
+
+ int index = samAccountName.IndexOf('\\');
+
+ if (index != samAccountName.Length - 1)
+ {
+ samAccountName = (index != -1) ? samAccountName.Substring(index + 1) : // +1 to skip the '/'
+ samAccountName;
+ }
+
+ if ((samAccountName != null) && (samAccountName.Length > 0))
+ {
+ rdnValue = ADUtils.EscapeDNComponent(samAccountName);
+ }
+ }
+ }
+
+ if (rdnPrefix == null)
+ {
+ // There was no rdn prefix attribute set on the principal class
+ throw new InvalidOperationException(StringResources.ExtensionInvalidClassAttributes);
+ }
+
+ if (rdnValue == null)
+ {
+ // They didn't set a display name or SAM IdentityClaim (or set an empty/invalid value for those).
+ throw new InvalidOperationException(StringResources.NameMustBeSetToPersistPrincipal);
+ }
+
+ rdn = rdnPrefix + "=" + rdnValue;
+
+ lock (_ctxBaseLock)
+ {
+ de = this.ctxBase.Children.Add(rdn, objectClass);
+ }
+
+ if (null != baseObjectRdnPrefix)
+ {
+ de.Properties[baseObjectRdnPrefix].Value = rdnValue;
+ }
+
+ InitializeNewDirectoryOptions(de);
+
+ p.UnderlyingObject = de;
+
+ // set the default user account control bits for authenticable principals
+ if (principalType.IsSubclassOf(typeof(AuthenticablePrincipal)))
+ {
+ InitializeUserAccountControl((AuthenticablePrincipal)p);
+ }
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info, "ADStoreCtx", "PushChangesToNative: created fresh DE, oc={0}, path={1}",
+ objectClass, de.Path);
+ }
+
+ // propertyMappingTableByProperty only has entries for writable properties,
+ // including writable properties which we don't support in AD.
+ // If we don't support the property, the PropertyMappingTableEntry will map
+ // it to a converter which will throw an appropriate exception.
+ Hashtable mappingTableByProp = (Hashtable)s_propertyMappingTableByProperty[this.MappingTableIndex];
+
+ foreach (DictionaryEntry dictEntry in mappingTableByProp)
+ {
+ ArrayList propertyEntries = (ArrayList)dictEntry.Value;
+
+ foreach (PropertyMappingTableEntry propertyEntry in propertyEntries)
+ {
+ if (p.GetChangeStatusForProperty(propertyEntry.propertyName))
+ {
+ // The property was set. Write it to the DirectoryEntry.
+ Debug.Assert(propertyEntry.propertyName == (string)dictEntry.Key);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "PushChangesToNative: pushing {0}", propertyEntry.propertyName);
+
+ propertyEntry.papiToLdapConverter(p, propertyEntry.propertyName, de, propertyEntry.suggestedADPropertyName);
+ }
+ }
+ }
+
+ return de;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ // Given a underlying store object (e.g., DirectoryEntry), further narrowed down a discriminant
+ // (if applicable for the StoreCtx type), returns a fresh instance of a Principal
+ // object based on it. The WinFX Principal API follows ADSI-style semantics, where you get multiple
+ // in-memory objects all referring to the same store pricipal, rather than WinFS semantics, where
+ // multiple searches all return references to the same in-memory object.
+ // Used to implement the reverse wormhole. Also, used internally by FindResultEnumerator
+ // to construct Principals from the store objects returned by a store query.
+ //
+ // The Principal object produced by this method does not have all the properties
+ // loaded. The Principal object will call the Load method on demand to load its properties
+ // from its Principal.UnderlyingObject.
+ //
+ //
+ // This method works for native objects from the store corresponding to _this_ StoreCtx.
+ // Each StoreCtx will also have its own internal algorithms used for dealing with cross-store objects, e.g.,
+ // for use when iterating over group membership. These routines are exposed as
+ // ResolveCrossStoreRefToPrincipal, and will be called by the StoreCtx's associated ResultSet
+ // classes when iterating over a representation of a "foreign" principal.
+
+ // This method will either be passed a DirectoryEntry or SearchResult object if this is the result of a search.
+ // We need to determine the type and then use the appropriate object.
+ internal override Principal GetAsPrincipal(object storeObject, object discriminant)
+ {
+ Debug.Assert(storeObject != null);
+
+ DirectoryEntry de = null;
+ SearchResult sr = null;
+ string path;
+ string distinguishedName;
+
+ if (storeObject is DirectoryEntry)
+ {
+ de = (DirectoryEntry)storeObject;
+ path = de.Path;
+ distinguishedName = (string)de.Properties["distinguishedName"].Value;
+ }
+ else
+ {
+ Debug.Assert(storeObject is SearchResult);
+ sr = (SearchResult)storeObject;
+ path = sr.Path;
+ distinguishedName = (string)sr.Properties["distinguishedName"][0];
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetAsPrincipal: using path={0}", (null != de ? de.Path : "searchResult"));
+
+ // Construct a appropriate Principal object.
+
+ bool targetIsFromGC = SDSUtils.IsObjectFromGC(path);
+ try
+ {
+ Principal p;
+
+ DirectoryEntry dcEntry = null;
+ PrincipalContext constructedContext = null;
+
+ // if the object was obtained from a GC, we have to construct a new context, and build a new DirectoryEntry
+ // if the object is not from a GC but belongs to another domain, we just have to construct a new context. We can still use the storeObject or searchresult's DirectoryEntry.
+ // if our context is not a domain (that is, it's ADLDS) we don't build a new context unless the object was obtained from a GC.
+ if (targetIsFromGC || OwningContext.ContextType == ContextType.Domain)
+ {
+ string dnsDomainName = SDSUtils.ConstructDnsDomainNameFromDn(distinguishedName);
+ if (targetIsFromGC ||
+ (!String.IsNullOrEmpty(this.domainDnsName) && String.Compare(this.DnsDomainName, dnsDomainName, StringComparison.OrdinalIgnoreCase) != 0))
+ {
+ constructedContext = SDSCache.Domain.GetContext(dnsDomainName, this.Credentials, this.OwningContext.Options);
+ }
+
+ if (targetIsFromGC)
+ {
+ dcEntry = SDSUtils.BuildDirectoryEntry("LDAP://" + dnsDomainName + "/" + GetEscapedDN(distinguishedName), this.Credentials, this.authTypes);
+ this.InitializeNewDirectoryOptions(dcEntry);
+ }
+ }
+
+ if (de != null)
+ {
+ //NOTE: If target is GC then we do NOT use variable "de". So, need to dispose this at the end.
+ p = SDSUtils.DirectoryEntryToPrincipal((targetIsFromGC ? dcEntry : de), constructedContext ?? this.OwningContext, (Type)discriminant);
+ }
+ else
+ {
+ //NOTE: If input storeObject is searchResult then variable "de" gets used in all cases.
+ p = SDSUtils.SearchResultToPrincipal(sr, constructedContext ?? this.OwningContext, (Type)discriminant);
+ p.UnderlyingObject = (targetIsFromGC ? dcEntry : sr.GetDirectoryEntry());
+ }
+
+ Debug.Assert(p != null);
+
+ Guid g;
+
+ if (de != null)
+ g = de.Guid;
+ else
+ {
+ byte[] guid = (byte[])sr.Properties["objectGuid"][0];
+ g = new Guid(guid);
+ }
+
+ ADStoreKey key = new ADStoreKey(g);
+ p.Key = key;
+
+ return p;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ if (targetIsFromGC && de != null)
+ {
+ //Since target is GC, variable "de" is not getting used. Disposing it.
+ de.Dispose();
+ }
+ }
+ }
+
+ /// <summary>
+ /// This Calls the Native API to Escape the DN
+ /// </summary>
+ /// <param name="dn"></param>
+ /// <returns>Escaped DN</returns>
+ private string GetEscapedDN(string dn)
+ {
+ UnsafeNativeMethods.Pathname pathNameObj = new UnsafeNativeMethods.Pathname();
+ UnsafeNativeMethods.IADsPathname pathCracker = (UnsafeNativeMethods.IADsPathname)pathNameObj;
+
+ // Set the Escape mode On
+ pathCracker.EscapedMode = 2 /* ADS_ESCAPEDMODE_ON */;
+
+ // Set the type of path to DN
+ pathCracker.Set(dn, 4 /* ADS_SETTYPE_DN */);
+
+ // Get back the escaped DN
+ return pathCracker.Retrieve(7 /* ADS_FORMAT_X500_DN */);
+ }
+
+ internal override void Load(Principal p, string principalPropertyName)
+ {
+ Debug.Assert(p != null);
+ Debug.Assert(p.UnderlyingObject != null);
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+
+ dSPropertyCollection props;
+
+ SearchResult sr = (SearchResult)p.UnderlyingSearchObject;
+ if (null == sr)
+ {
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+ Debug.Assert(p.GetUnderlyingObjectType() == typeof(DirectoryEntry));
+
+ props = new dSPropertyCollection(de.Properties);
+ }
+ else
+ {
+ props = new dSPropertyCollection(sr.Properties);
+ }
+
+ Hashtable propertyMappingTable = (Hashtable)s_propertyMappingTableByPropertyFull[this.MappingTableIndex];
+
+ ArrayList entries = (ArrayList)propertyMappingTable[principalPropertyName];
+
+ // We don't support this property and cannot load it. To maintain backward compatibility with the old code just return.
+ if (entries == null)
+ return;
+
+ Debug.Assert(null != entries);
+
+ try
+ {
+ foreach (PropertyMappingTableEntry entry in entries)
+ {
+ if (null != entry.ldapToPapiConverter)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Load_PropertyName: loading {0}", entry.propertyName);
+ entry.ldapToPapiConverter(props, entry.suggestedADPropertyName, p, entry.propertyName);
+ }
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ // Loads the store values from p.UnderlyingObject into p, performing schema mapping as needed.
+ internal override void Load(Principal p)
+ {
+ Debug.Assert(p != null);
+ Debug.Assert(p.UnderlyingObject != null);
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Entering Load, type={0}, path={1}", p.GetType(), de.Path);
+
+ Hashtable ldapMappingTable = (Hashtable)s_propertyMappingTableByLDAP[this.MappingTableIndex];
+ foreach (DictionaryEntry Dictentry in ldapMappingTable)
+ {
+ ArrayList entries = (ArrayList)Dictentry.Value;
+ try
+ {
+ foreach (PropertyMappingTableEntry entry in entries)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Load: loading {0}", entry.propertyName);
+ entry.ldapToPapiConverter(new dSPropertyCollection(de.Properties), entry.suggestedADPropertyName, p, entry.propertyName);
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ p.Loaded = true;
+ }
+
+ // Performs store-specific resolution of an IdentityReference to a Principal
+ // corresponding to the IdentityReference. Returns null if no matching object found.
+ // principalType can be used to scope the search to principals of a specified type, e.g., users or groups.
+ // Specify typeof(Principal) to search all principal types.
+ internal override Principal FindPrincipalByIdentRef(
+ Type principalType, string urnScheme, string urnValue, DateTime referenceDate)
+ {
+ return FindPrincipalByIdentRefHelper(principalType, urnScheme, urnValue, referenceDate, false);
+ }
+
+ // Normally, doing a FindByIdentity for a SID doesn't include the SID History. This method provides a
+ // means to include the sidHistory as well as the objectSid in the search.
+ internal Principal FindPrincipalBySID(
+ Type principalType, IdentityReference ir, bool useSidHistory)
+ {
+ return FindPrincipalByIdentRefHelper(principalType,
+ ir.UrnScheme,
+ ir.UrnValue,
+ DateTime.UtcNow,
+ useSidHistory);
+ }
+
+ // Handles all the work required to implement FindPrincipalByIdentRef (and FindPrincipalBySID).
+ private Principal FindPrincipalByIdentRefHelper(
+ Type principalType,
+ string urnScheme,
+ string urnValue,
+ DateTime referenceDate,
+ bool useSidHistory)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "FindPrincipalByIdentRefHelper: type={0}, scheme={1}, value={2}, useSidHistory={3}",
+ principalType.ToString(),
+ (urnScheme != null ? urnScheme : "NULL"),
+ (urnValue != null ? urnValue : "NULL"),
+ useSidHistory);
+
+ //
+ // Set up a DirectorySearcher
+ //
+ DirectorySearcher ds = new DirectorySearcher(this.ctxBase);
+ SearchResultCollection src = null;
+
+ try
+ {
+ ds.SizeLimit = 2; // so we can efficiently check for duplicates
+
+ // If we are searching for AuthPrincpal or Principal in the end we will construct the acutal type
+ // i.e. if the objects objectClass is User we will construct a UserPrincipal even though they searched for Principal.FindByIdentity
+ // At this time we don't know the actual object type so we have to ask AD for all the attributes of the derived types so they are there
+ // when we go to load the principal.
+ if (principalType == typeof(Principal) || principalType == typeof(AuthenticablePrincipal))
+ {
+ BuildPropertySet(typeof(UserPrincipal), ds.PropertiesToLoad);
+ BuildPropertySet(typeof(GroupPrincipal), ds.PropertiesToLoad);
+ BuildPropertySet(typeof(ComputerPrincipal), ds.PropertiesToLoad);
+
+ if (principalType == typeof(Principal))
+ {
+ BuildPropertySet(typeof(AuthenticablePrincipal), ds.PropertiesToLoad);
+ }
+ }
+
+ BuildPropertySet(principalType, ds.PropertiesToLoad);
+
+ //
+ // Build an appropriate filter
+ //
+
+ StringBuilder ldapFilter = new StringBuilder();
+
+ // Limit the results returned to principalType by specifying the corresponding objectClass/objectCategory
+ ldapFilter.Append(GetObjectClassPortion(principalType));
+
+ // Build the rest of the filter based off of the user's specified IdentityReference.
+ if (urnScheme != null)
+ {
+ // If they're searching by SID for a SID corresponding to a fake group, construct
+ // and return the fake group
+ if ((urnScheme == UrnScheme.SidScheme) &&
+ (principalType == typeof(Principal) || principalType == typeof(GroupPrincipal) || principalType.IsSubclassOf(typeof(GroupPrincipal))))
+ {
+ SecurityIdentifier sid = new SecurityIdentifier(urnValue);
+ byte[] sidb = new byte[sid.BinaryLength];
+ sid.GetBinaryForm(sidb, 0);
+ // = Utils.StringToByteArray(urnValue);
+
+ if (sid == null)
+ throw new ArgumentException(StringResources.StoreCtxSecurityIdentityClaimBadFormat);
+
+ IntPtr pSid = IntPtr.Zero;
+
+ try
+ {
+ pSid = Utils.ConvertByteArrayToIntPtr(sidb);
+
+ if (UnsafeNativeMethods.IsValidSid(pSid) && (Utils.ClassifySID(pSid) == SidType.FakeObject))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "FindPrincipalByIdentRefHelper: fake principal, SID Scheme, {0}",
+ sid.ToString());
+
+ return ConstructFakePrincipalFromSID(sidb);
+ }
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pSid);
+ }
+ }
+
+ // This is the simple case --- we got a specific UrnScheme, so we'll just build
+ // a filter for it.
+
+ // Ignore referenceDate --- all IdentityClaims in AD are forever
+ string innerLdapFilter = null;
+ BuildLdapFilterFromIdentityClaim(urnValue, urnScheme, ref innerLdapFilter, useSidHistory, true);
+
+ ldapFilter.Append(innerLdapFilter);
+ }
+ else
+ {
+ // Are they perhaps searching for a fake group?
+ // If they passed in a valid SID for a fake group, construct and return the fake
+ // group.
+ if (principalType == typeof(Principal) || principalType == typeof(GroupPrincipal) || principalType.IsSubclassOf(typeof(GroupPrincipal)))
+ {
+ SecurityIdentifier sid = null;
+ byte[] sidb = null;
+ try
+ {
+ sid = new SecurityIdentifier(urnValue);
+ sidb = new byte[sid.BinaryLength];
+ sid.GetBinaryForm(sidb, 0);
+ }
+ catch (ArgumentException)
+ {
+ }
+
+ if (sidb != null)
+ {
+ // They passed in a hex string, is it a valid SID, and if so, does it correspond to a fake
+ // principal?
+ IntPtr pSid = IntPtr.Zero;
+
+ try
+ {
+ pSid = Utils.ConvertByteArrayToIntPtr(sidb);
+
+ if (UnsafeNativeMethods.IsValidSid(pSid) && (Utils.ClassifySID(pSid) == SidType.FakeObject))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "ADStoreCtx",
+ "FindPrincipalByIdentRefHelper: fake principal, null Scheme, {0}",
+ sid.ToString());
+
+ return ConstructFakePrincipalFromSID(sidb);
+ }
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pSid);
+ }
+ }
+ }
+
+ // This is the tricky case. They didn't specify a UrnScheme, so we need to
+ // try all of them.
+
+ string[] urnSchemesToTry = new string[]
+ {
+ UrnScheme.SamAccountScheme,
+ UrnScheme.UpnScheme,
+ UrnScheme.DistinguishedNameScheme,
+ UrnScheme.SidScheme,
+ UrnScheme.GuidScheme,
+ UrnScheme.NameScheme
+ };
+
+ StringBuilder innerLdapFilter = new StringBuilder();
+
+ innerLdapFilter.Append("(|");
+
+ string filterVal = null;
+
+ foreach (string urnSchemeToTry in urnSchemesToTry)
+ {
+ if (BuildLdapFilterFromIdentityClaim(urnValue, urnSchemeToTry, ref filterVal, useSidHistory, false))
+ if (null != filterVal)
+ innerLdapFilter.Append(filterVal);
+ }
+
+ innerLdapFilter.Append(")");
+
+ ldapFilter.Append(innerLdapFilter.ToString());
+ }
+
+ // Wrap off the filter
+ ldapFilter.Append(")");
+
+ ds.Filter = ldapFilter.ToString();
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "FindPrincipalByIdentRefHelper: using LDAP filter {0}", ds.Filter);
+
+ //
+ // Perform the actual search
+ //
+ src = ds.FindAll();
+
+ Debug.Assert(src != null);
+
+ if (src == null)
+ return null;
+
+ // Did we find a match?
+ int count = src.Count;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "FindPrincipalByIdentRefHelper: found {0} matches", count);
+
+ // Did we find more than one match?
+ if (count > 1)
+ throw new MultipleMatchesException(StringResources.MultipleMatchingPrincipals);
+
+ if (count == 0)
+ return null;
+
+ return GetAsPrincipal(src[0], principalType);
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ ds.Dispose();
+ if (src != null)
+ {
+ src.Dispose();
+ }
+ }
+ }
+
+ // Returns a type indicating the type of object that would be returned as the wormhole for the specified
+ // Principal. For some StoreCtxs, this method may always return a constant (e.g., typeof(DirectoryEntry)
+ // for ADStoreCtx). For others, it may vary depending on the Principal passed in.
+ internal override Type NativeType(Principal p)
+ {
+ Debug.Assert(p != null);
+
+ return typeof(DirectoryEntry);
+ }
+
+ //
+ // Property mapping tables
+ //
+
+ // We only list properties we map in this table. At run-time, if we detect they set a
+ // property that's not listed here when writing to AD, we throw an exception.
+ //
+ // When updating this table, be sure to also update LoadDirectoryEntryAttributes() to load
+ // in any newly-added attributes.
+
+ private static object[,] s_propertyMappingTableRaw =
+ {
+ // PropertyName AD property Converter(LDAP->PAPI) Converter(PAPI->LDAP)
+ {PropertyNames.PrincipalDisplayName, "displayname", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalDescription, "description", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalDistinguishedName, "distinguishedname", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalSid, "objectsid", new FromLdapConverterDelegate(SidFromLdapConverter), null},
+ {PropertyNames.PrincipalSamAccountName, "samaccountname", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalUserPrincipalName, "userprincipalname", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalGuid, "objectguid", new FromLdapConverterDelegate(GuidFromLdapConverter), null},
+ {PropertyNames.PrincipalStructuralObjectClass, "objectclass", new FromLdapConverterDelegate(ObjectClassFromLdapConverter), null},
+ {PropertyNames.PrincipalName, "name", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalExtensionCache, null, null, new ToLdapConverterDelegate(ExtensionCacheToLdapConverter)},
+
+ {PropertyNames.AuthenticablePrincipalEnabled, "useraccountcontrol", new FromLdapConverterDelegate(UACFromLdapConverter), new ToLdapConverterDelegate(UACToLdapConverter)},
+ {PropertyNames.AuthenticablePrincipalCertificates, "usercertificate", new FromLdapConverterDelegate(CertFromLdapConverter), new ToLdapConverterDelegate(CertToLdap)},
+
+ {PropertyNames.GroupIsSecurityGroup, "grouptype", new FromLdapConverterDelegate(GroupTypeFromLdapConverter), new ToLdapConverterDelegate(GroupTypeToLdapConverter)},
+ {PropertyNames.GroupGroupScope, "grouptype", new FromLdapConverterDelegate(GroupTypeFromLdapConverter), new ToLdapConverterDelegate(GroupTypeToLdapConverter)},
+
+ {PropertyNames.UserGivenName, "givenname", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserMiddleName, "middlename", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserSurname, "sn", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserEmailAddress, "mail", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserVoiceTelephoneNumber, "telephonenumber", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.UserEmployeeID, "employeeid", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+
+ {PropertyNames.ComputerServicePrincipalNames, "serviceprincipalname", new FromLdapConverterDelegate(MultiStringFromLdapConverter), new ToLdapConverterDelegate(MultiStringToLdapConverter)},
+
+ {PropertyNames.AcctInfoAcctLockoutTime, "lockouttime", new FromLdapConverterDelegate(GenericDateTimeFromLdapConverter), null},
+ {PropertyNames.AcctInfoLastLogon, "lastlogon", new FromLdapConverterDelegate(LastLogonFromLdapConverter), null},
+ {PropertyNames.AcctInfoLastLogon, "lastlogontimestamp", new FromLdapConverterDelegate(LastLogonFromLdapConverter), null},
+ {PropertyNames.AcctInfoPermittedWorkstations, "userworkstations", new FromLdapConverterDelegate(CommaStringFromLdapConverter), new ToLdapConverterDelegate(CommaStringToLdapConverter)},
+ {PropertyNames.AcctInfoPermittedLogonTimes, "logonhours", new FromLdapConverterDelegate(BinaryFromLdapConverter), new ToLdapConverterDelegate(BinaryToLdapConverter)},
+ {PropertyNames.AcctInfoExpirationDate, "accountexpires", new FromLdapConverterDelegate(AcctExpirFromLdapConverter), new ToLdapConverterDelegate(AcctExpirToLdapConverter)},
+ {PropertyNames.AcctInfoSmartcardRequired, "useraccountcontrol", new FromLdapConverterDelegate(UACFromLdapConverter), new ToLdapConverterDelegate(UACToLdapConverter)},
+ {PropertyNames.AcctInfoDelegationPermitted, "useraccountcontrol", new FromLdapConverterDelegate(UACFromLdapConverter), new ToLdapConverterDelegate(UACToLdapConverter)},
+ {PropertyNames.AcctInfoBadLogonCount, "badpwdcount", new FromLdapConverterDelegate(IntFromLdapConverter), null},
+ {PropertyNames.AcctInfoHomeDirectory, "homedirectory", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.AcctInfoHomeDrive, "homedrive", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.AcctInfoScriptPath, "scriptpath", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+
+ {PropertyNames.PwdInfoLastPasswordSet, "pwdlastset", new FromLdapConverterDelegate(GenericDateTimeFromLdapConverter), null},
+ {PropertyNames.PwdInfoLastBadPasswordAttempt, "badpasswordtime", new FromLdapConverterDelegate(GenericDateTimeFromLdapConverter), null},
+ {PropertyNames.PwdInfoPasswordNotRequired, "useraccountcontrol", new FromLdapConverterDelegate(UACFromLdapConverter), new ToLdapConverterDelegate(UACToLdapConverter)},
+ {PropertyNames.PwdInfoPasswordNeverExpires, "useraccountcontrol", new FromLdapConverterDelegate(UACFromLdapConverter), new ToLdapConverterDelegate(UACToLdapConverter)},
+ {PropertyNames.PwdInfoCannotChangePassword, null, null, new ToLdapConverterDelegate(CannotChangePwdToLdapConverter)},
+ {PropertyNames.PwdInfoAllowReversiblePasswordEncryption, "useraccountcontrol", new FromLdapConverterDelegate(UACFromLdapConverter), new ToLdapConverterDelegate(UACToLdapConverter)}
+ };
+ /*/
+ ///******* Mapping table for perf testing...
+ static object[,] propertyMappingTableRaw =
+ {
+ // PropertyName AD property Converter(LDAP->PAPI) Converter(PAPI->LDAP)
+ {PropertyNames.PrincipalDisplayName, "displayName", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalDescription, "description", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ // {PropertyNames.PrincipalDistinguishedName, "distinguishedName", null, null},
+ {PropertyNames.PrincipalSid, "objectSid", new FromLdapConverterDelegate(SidFromLdapConverter), null},
+ {PropertyNames.PrincipalSamAccountName, "samAccountName", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalUserPrincipalName, "userPrincipalName", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalGuid, "objectGuid", new FromLdapConverterDelegate(GuidFromLdapConverter), null},
+ {PropertyNames.PrincipalStructuralObjectClass, "objectClass", null, null},
+ {PropertyNames.PrincipalName, "name", new FromLdapConverterDelegate(StringFromLdapConverter), new ToLdapConverterDelegate(StringToLdapConverter)},
+ {PropertyNames.PrincipalExtensionCache, null, null, null},
+
+ {PropertyNames.AuthenticablePrincipalEnabled, "userAccountControl", null, null},
+ {PropertyNames.AuthenticablePrincipalCertificates, "userCertificate", null, null},
+
+ {PropertyNames.GroupIsSecurityGroup, "groupType", null, null},
+ {PropertyNames.GroupGroupScope, "groupType", null, null},
+ //
+ {PropertyNames.UserGivenName, "givenName", null, null},
+ {PropertyNames.UserMiddleName, "middleName", null, null},
+ {PropertyNames.UserSurname, "sn", null, null},
+ {PropertyNames.UserEmailAddress, "mail", null, null},
+ {PropertyNames.UserVoiceTelephoneNumber, "telephoneNumber", null, null},
+ {PropertyNames.UserEmployeeID, "employeeID", null, null},
+
+ {PropertyNames.ComputerServicePrincipalNames, "servicePrincipalName", null, null},
+ {PropertyNames.AcctInfoAcctLockoutTime, "lockoutTime", null, null},
+ {PropertyNames.AcctInfoLastLogon, "lastLogon", null, null},
+ {PropertyNames.AcctInfoLastLogon, "lastLogonTimestamp", null, null},
+ {PropertyNames.AcctInfoPermittedWorkstations, "userWorkstations", null, null},
+ {PropertyNames.AcctInfoPermittedLogonTimes, "logonHours", null, null},
+ {PropertyNames.AcctInfoExpirationDate, "accountExpires", new FromLdapConverterDelegate(AcctExpirFromLdapConverter), new ToLdapConverterDelegate(AcctExpirToLdapConverter)},
+ {PropertyNames.AcctInfoSmartcardRequired, "userAccountControl", null, null},
+ {PropertyNames.AcctInfoDelegationPermitted, "userAccountControl", null, null},
+ {PropertyNames.AcctInfoBadLogonCount, "badPwdCount", null, null},
+ {PropertyNames.AcctInfoHomeDirectory, "homeDirectory", null, null},
+ {PropertyNames.AcctInfoHomeDrive, "homeDrive", null, null},
+ {PropertyNames.AcctInfoScriptPath, "scriptPath", null, null},
+
+ {PropertyNames.PwdInfoLastPasswordSet, "pwdLastSet", null, null},
+ {PropertyNames.PwdInfoLastBadPasswordAttempt, "badPasswordTime", null, null},
+ {PropertyNames.PwdInfoPasswordNotRequired, "userAccountControl", null, null},
+ {PropertyNames.PwdInfoPasswordNeverExpires, "userAccountControl", null, null},
+ // {PropertyNames.PwdInfoCannotChangePassword, "ntSecurityDescriptor", null, new ToLdapConverterDelegate(CannotChangePwdToLdapConverter)},
+ {PropertyNames.PwdInfoAllowReversiblePasswordEncryption, "userAccountControl", null, null}
+ };
+
+ /************************/
+ // This table only includes properties that are writeable.
+ private static Hashtable s_propertyMappingTableByProperty = null;
+ private static Hashtable s_propertyMappingTableByLDAP = null;
+ protected static Dictionary<string, bool> NonPresentAttrDefaultStateMapping = null;
+ private static Hashtable s_propertyMappingTableByPropertyFull = null;
+
+ protected static Dictionary<int, Dictionary<Type, StringCollection>> TypeToLdapPropListMap = null;
+
+ private class PropertyMappingTableEntry
+ {
+ internal string propertyName; // PAPI name
+ internal string suggestedADPropertyName; // LDAP attribute name
+ internal FromLdapConverterDelegate ldapToPapiConverter;
+ internal ToLdapConverterDelegate papiToLdapConverter;
+ }
+
+ //
+ // Conversion routines
+ //
+
+ // Loads the specified attribute of the DirectoryEntry into the specified property of the Principal
+ protected delegate void FromLdapConverterDelegate(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName);
+
+ // Loads the specified property of the Principal into the specified attribute of the DirectoryEntry.
+ // For multivalued attributes, must test to make sure the value hasn't already been loaded into the DirectoryEntry
+ // (to maintain idempotency when PushChangesToNative is called multiple times).
+ protected delegate void ToLdapConverterDelegate(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty);
+
+ //
+ // Conversion: LDAP --> PAPI
+ //
+ protected static void SidFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ if (properties["objectSid"].Count > 0)
+ {
+ byte[] sid = (byte[])properties["objectSid"][0];
+
+ SecurityIdentifier SecurityId = new SecurityIdentifier(sid, 0);
+
+ p.LoadValueIntoProperty(propertyName, (object)SecurityId);
+ }
+ else
+ {
+ p.LoadValueIntoProperty(propertyName, null);
+ }
+ }
+
+ protected static void GuidFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ Debug.Assert(properties["objectGuid"].Count == 1);
+
+ if (properties["objectGuid"].Count == 1)
+ {
+ byte[] guid = (byte[])properties["objectGuid"][0];
+
+ Guid g = new Guid(guid);
+
+ p.LoadValueIntoProperty(propertyName, g);
+ }
+ else
+ {
+ p.LoadValueIntoProperty(propertyName, null);
+ }
+ }
+
+ protected static void StringFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ SDSUtils.SingleScalarFromDirectoryEntry<string>(properties, suggestedAdProperty, p, propertyName);
+ }
+
+ protected static void MultiStringFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ // ValueCollection<string> is Load'ed from a List<string>
+ SDSUtils.MultiScalarFromDirectoryEntry<string>(properties, suggestedAdProperty, p, propertyName);
+ }
+
+ protected static void BoolFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ SDSUtils.SingleScalarFromDirectoryEntry<bool>(properties, suggestedAdProperty, p, propertyName);
+ }
+
+ // This function is converting the disabled directory status into the enabled principal property
+ // the boolan value needs to be negated
+ protected static void AcctDisabledFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ if (properties[suggestedAdProperty].Count > 0)
+ {
+ // We're intended to handle single-valued scalar properties
+ Debug.Assert(properties[suggestedAdProperty].Count == 1);
+ Debug.Assert(properties[suggestedAdProperty][0] is bool);
+
+ p.LoadValueIntoProperty(propertyName, !(bool)properties[suggestedAdProperty][0]);
+ }
+ }
+
+ protected static void CommaStringFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ Debug.Assert(String.Compare(suggestedAdProperty, "userWorkstations", StringComparison.OrdinalIgnoreCase) == 0);
+
+ // The userWorkstations attribute is odd. Rather than being a multivalued string attribute, it's a single-valued
+ // string of comma-separated values.
+
+ dSPropertyValueCollection values = properties[suggestedAdProperty];
+
+ if (values.Count != 0)
+ {
+ Debug.Assert(values.Count == 1);
+ Debug.Assert(values[0] is string);
+
+ string commaSeparatedValues = (string)values[0];
+ string[] individualValues = commaSeparatedValues.Split(new char[] { ',' });
+
+ // ValueCollection<string> is Load'ed from a List<string>
+ List<string> list = new List<string>(individualValues.Length);
+
+ foreach (string s in individualValues)
+ {
+ list.Add(s);
+ }
+
+ p.LoadValueIntoProperty(propertyName, list);
+ }
+ }
+
+ protected static void IntFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ SDSUtils.SingleScalarFromDirectoryEntry<int>(properties, suggestedAdProperty, p, propertyName);
+ }
+
+ protected static void BinaryFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ SDSUtils.SingleScalarFromDirectoryEntry<byte[]>(properties, suggestedAdProperty, p, propertyName);
+ }
+
+ protected static void CertFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ // Cert collection is Load'ed via a list of byte[], each representing a cert
+ SDSUtils.MultiScalarFromDirectoryEntry<byte[]>(properties, suggestedAdProperty, p, propertyName);
+ }
+
+ protected static void UACFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ Debug.Assert(String.Compare(suggestedAdProperty, "userAccountControl", StringComparison.OrdinalIgnoreCase) == 0);
+
+ SDSUtils.AccountControlFromDirectoryEntry(properties, suggestedAdProperty, p, propertyName, false);
+ }
+
+ protected static void GenericDateTimeFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ DateTimeFromLdapConverter(properties, suggestedAdProperty, p, propertyName, false);
+ }
+
+ protected static void ObjectClassFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ dSPropertyValueCollection values = properties[suggestedAdProperty];
+
+ if (values.Count > 0)
+ {
+ // This is a multivalued attribute and we want the last element. The most specialized object class...
+ Debug.Assert(values[values.Count - 1] is string);
+ p.LoadValueIntoProperty(propertyName, (string)values[values.Count - 1]);
+ }
+ }
+
+ protected static void LastLogonFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ // W2k DCs support just "lastLogon". W2k3 DCs also support "lastLogonTimestamp". The latter is replicated, and
+ // preferred over the former.
+ if (String.Compare(suggestedAdProperty, "lastLogon", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ // Is "lastLogonTimestamp" available instead?
+
+ if (properties["lastLogonTimestamp"].Count != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LastLogonFromLdapConverter: found lastLogonTimestamp");
+
+ // "lastLogonTimestamp" is available. So ignore "lastLogon" and do nothing. We'll be called again
+ // when Load() gets to the "lastLogonTimestamp" attribute (or it may already have).
+ return;
+ }
+ }
+
+ // Either we're processing "lastLogonTimestamp", or there is no "lastLogonTimestamp" and we're processing "lastLogon".
+ // Either way, it's handled like a generic date.
+ DateTimeFromLdapConverter(properties, suggestedAdProperty, p, propertyName, false);
+ }
+
+ protected static void AcctExpirFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ DateTimeFromLdapConverter(properties, suggestedAdProperty, p, propertyName, true);
+ }
+
+ protected static void DateTimeFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName, bool useAcctExpLogic)
+ {
+ dSPropertyValueCollection values = properties[suggestedAdProperty];
+
+ if (values.Count != 0)
+ {
+ Debug.Assert(values.Count == 1);
+
+ Int64 filetime;
+
+ if (values[0] is Int64)
+ filetime = (Int64)values[0];
+ else
+ filetime = ADUtils.LargeIntToInt64((UnsafeNativeMethods.IADsLargeInteger)values[0]);
+
+ Nullable<DateTime> dt;
+
+ // Filetimes use "0" to mean "no value, except for accountExpires,
+ // which uses both "0" and "0x7fffffffffffffff" to mean "no expiration date"
+ if ((!useAcctExpLogic) && (filetime == 0x0))
+ dt = null;
+ else if ((useAcctExpLogic) && (filetime == 0x0 || filetime == 0x7fffffffffffffff))
+ dt = null;
+ else
+ dt = ADUtils.ADFileTimeToDateTime(filetime);
+
+ p.LoadValueIntoProperty(propertyName, dt);
+ }
+ }
+
+ protected static void GroupTypeFromLdapConverter(dSPropertyCollection properties, string suggestedAdProperty, Principal p, string propertyName)
+ {
+ Debug.Assert(String.Compare(suggestedAdProperty, "groupType", StringComparison.OrdinalIgnoreCase) == 0);
+
+ dSPropertyValueCollection values = properties[suggestedAdProperty];
+
+ if (values.Count != 0)
+ {
+ Debug.Assert(values.Count == 1);
+ Debug.Assert(values[0] is int);
+
+ int groupTypeCombined = (int)values[0];
+
+ switch (propertyName)
+ {
+ case PropertyNames.GroupIsSecurityGroup:
+
+ bool isSecurityEnabled = false;
+
+ // GROUP_TYPE_SECURITY_ENABLED
+ if ((groupTypeCombined & 0x80000000) != 0)
+ isSecurityEnabled = true;
+
+ // isSecurityEnabled --> group IS enabled
+ p.LoadValueIntoProperty(propertyName, isSecurityEnabled);
+ break;
+
+ case PropertyNames.GroupGroupScope:
+
+ GroupScope groupType = GroupScope.Universal;
+
+ if ((groupTypeCombined & ADGroupScope.Global) != 0) // ADS_GROUP_TYPE_GLOBAL_GROUP
+ groupType = GroupScope.Global;
+ else if ((groupTypeCombined & ADGroupScope.Local) != 0) // ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP
+ groupType = GroupScope.Local;
+ else
+ Debug.Assert((groupTypeCombined & ADGroupScope.Universal) != 0); // ADS_GROUP_TYPE_UNIVERSAL_GROUP
+
+ p.LoadValueIntoProperty(propertyName, groupType);
+ break;
+
+ default:
+ Debug.Fail("ADStoreCtx.GroupTypeFromLdapConverter: Fell off end looking for " + propertyName);
+ break;
+ }
+ }
+ }
+
+ protected static bool CannotChangePwdFromLdapConverter(DirectoryEntry de)
+ {
+ // We use the same logic as the AD Users & Computers snapin. We scan the DACL,
+ // looking for ALLOW or DENY ACEs for the "user can change password" right. We scan
+ // for both self and world ACEs. If we find neither explitic allow nor explicit deny ACEs,
+ // we (like the AD U&C snapin) default to assuming the user can change his or her password.
+
+ // *******************************
+ // retrieving ObjectSecurity after
+ // previously modifying the ACL will return null unless we force a cache refresh. We have to do this always,
+ // even before we call ObjectSecurity to see if it would return null, because once ObjectSecurity returns null the
+ // first time, it'll keep returning null even if we refresh the cache.
+
+ if (!de.Properties.Contains("nTSecurityDescriptor"))
+ de.RefreshCache(new string[] { "nTSecurityDescriptor" });
+
+ ActiveDirectorySecurity adsSecurity = de.ObjectSecurity;
+
+ bool denySelfFound;
+ bool denyWorldFound;
+ bool allowSelfFound;
+ bool allowWorldFound;
+
+ // Perform the scan
+ ScanACLForChangePasswordRight(adsSecurity, out denySelfFound, out denyWorldFound, out allowSelfFound, out allowWorldFound);
+
+ // Map the ACEs found to "user cannot change password" status
+ bool userCannotChangePassword;
+
+ if (denySelfFound || denyWorldFound)
+ {
+ // Explicit deny --> user can't change password
+ userCannotChangePassword = true;
+ }
+ else if ((!denySelfFound && !denyWorldFound) && (allowSelfFound || allowWorldFound))
+ {
+ // Explitic allow --> user can change password
+ userCannotChangePassword = false;
+ }
+ else
+ {
+ // As with the AD U&C snapin, if the explitic ACEs don't tell us anything, we
+ // fallback to assuming the user can change their password
+ userCannotChangePassword = false;
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "CannotChangePwdFromLdapConverter: fallback, assume user can change pwd");
+ }
+
+ return userCannotChangePassword;
+ }
+
+ private const string SelfSddl = "S-1-5-10"; // NT AUTHORITY\SELF
+ private const string WorldSddl = "S-1-1-0"; // EVERYONE
+ private static readonly Guid s_changePasswordGuid = new Guid("{ab721a53-1e2f-11d0-9819-00aa0040529b}");
+
+ protected static void ScanACLForChangePasswordRight(
+ ActiveDirectorySecurity adsSecurity,
+ out bool denySelfFound,
+ out bool denyWorldFound,
+ out bool allowSelfFound,
+ out bool allowWorldFound)
+ {
+ denySelfFound = false;
+ denyWorldFound = false;
+ allowSelfFound = false;
+ allowWorldFound = false;
+
+ MACLPrinc.SecurityIdentifier trustee;
+
+ foreach (ActiveDirectoryAccessRule rule in adsSecurity.GetAccessRules(true, true, typeof(MACLPrinc.SecurityIdentifier)))
+ {
+ trustee = (MACLPrinc.SecurityIdentifier)rule.IdentityReference;
+ string sidSddl = trustee.Value;
+
+ if (rule.ObjectType == s_changePasswordGuid)
+ {
+ if (rule.AccessControlType == AccessControlType.Deny)
+ {
+ if (sidSddl == SelfSddl)
+ {
+ denySelfFound = true;
+ }
+ else if (sidSddl == WorldSddl)
+ {
+ denyWorldFound = true;
+ }
+ }
+ else if (rule.AccessControlType == AccessControlType.Allow)
+ {
+ if (sidSddl == SelfSddl)
+ {
+ allowSelfFound = true;
+ }
+ else if (sidSddl == WorldSddl)
+ {
+ allowWorldFound = true;
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Conversion: PAPI --> LDAP
+ //
+
+ protected static void StringToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ string value = (string)p.GetValueForProperty(propertyName);
+
+ if (p.unpersisted && value == null)
+ return;
+
+ if ((value == null) || (value.Length > 0))
+ de.Properties[suggestedAdProperty].Value = value;
+ else
+ throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, StringResources.InvalidStringValueForStore, propertyName));
+ }
+
+ protected static void BinaryToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ byte[] value = (byte[])p.GetValueForProperty(propertyName);
+
+ if (p.unpersisted && value == null)
+ return;
+
+ if (value != null && value.Length != 0)
+ de.Properties[suggestedAdProperty].Value = value;
+ else
+ de.Properties[suggestedAdProperty].Value = null;
+ }
+
+ protected static void MultiStringToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ SDSUtils.MultiStringToDirectoryEntryConverter(p, propertyName, de, suggestedAdProperty);
+ }
+
+ protected static void BoolToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ object value = (bool)p.GetValueForProperty(propertyName);
+
+ if (p.unpersisted && value == null)
+ return;
+
+ if (value != null)
+ de.Properties[suggestedAdProperty].Value = (bool)value;
+ else
+ de.Properties[suggestedAdProperty].Value = null;
+ }
+
+ // This function is converting the disabled directory status into the enabled principal property
+ // the boolan value needs to be negated
+ protected static void AcctDisabledToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ // Only modify disabled property if we are talking to an already persisted user.
+ // We need to set the password before we can enable the user on new objects.
+ if (!p.unpersisted)
+ {
+ object value = (bool)p.GetValueForProperty(propertyName);
+ if (value != null)
+ de.Properties[suggestedAdProperty].Value = !(bool)value;
+ else
+ de.Properties[suggestedAdProperty].Value = null;
+ }
+ }
+
+ protected static void CommaStringToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ PrincipalValueCollection<string> trackingList = (PrincipalValueCollection<string>)p.GetValueForProperty(propertyName);
+
+ StringBuilder sb = new StringBuilder();
+
+ foreach (string value in trackingList)
+ {
+ // Preexisting values that have not been removed.
+ // This also includes inserted values.
+ sb.Append(value);
+ sb.Append(",");
+ }
+
+ // We have an extra comma at the end (assuming we added any values to the string). Remove it.
+ if (sb.Length > 0)
+ sb.Remove(sb.Length - 1, 1);
+
+ string s = (sb.Length > 0) ? sb.ToString() : null;
+
+ if (p.unpersisted && s == null)
+ return;
+
+ de.Properties[suggestedAdProperty].Value = s;
+ }
+
+ protected static void CertToLdap(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ X509Certificate2Collection certificates = (X509Certificate2Collection)p.GetValueForProperty(propertyName);
+
+ if (certificates.Count == 0)
+ {
+ // Clear out the certificates
+ de.Properties[suggestedAdProperty].Value = null;
+ }
+ else
+ {
+ // Replace the existing certs with the modified certs. Note that this replaces all the certs ---
+ // X509CertificateExCollection doesn't expose a finer-grained change-tracking mechanism
+ byte[][] rawCerts = new byte[certificates.Count][];
+
+ for (int i = 0; i < certificates.Count; i++)
+ {
+ rawCerts[i] = certificates[i].RawData;
+ }
+
+ de.Properties[suggestedAdProperty].Value = null; // remove the old
+ de.Properties[suggestedAdProperty].Value = rawCerts; // and put in the new
+ }
+ }
+
+ protected static void UACToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ Debug.Assert(String.Compare(suggestedAdProperty, "userAccountControl", StringComparison.OrdinalIgnoreCase) == 0);
+
+ SDSUtils.AccountControlToDirectoryEntry(p, propertyName, de, suggestedAdProperty, false, p.unpersisted);
+ }
+
+ protected static void AcctExpirToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ Nullable<DateTime> dt = (Nullable<DateTime>)p.GetValueForProperty(propertyName);
+
+ if (p.unpersisted && dt == null)
+ return;
+
+ UnsafeNativeMethods.ADsLargeInteger largeIntObj = new UnsafeNativeMethods.ADsLargeInteger();
+ UnsafeNativeMethods.IADsLargeInteger largeInt = (UnsafeNativeMethods.IADsLargeInteger)largeIntObj;
+
+ if (!dt.HasValue)
+ {
+ // no expiration date
+ largeInt.LowPart = unchecked((int)0xffffffff);
+ largeInt.HighPart = (int)0x7fffffff;
+ }
+ else
+ {
+ Int64 filetime = ADUtils.DateTimeToADFileTime(dt.Value);
+
+ uint lowPart = (uint)(((ulong)filetime) & ((ulong)0x00000000ffffffff));
+ uint highPart = (uint)((((ulong)filetime) & ((ulong)0xffffffff00000000)) >> 32);
+
+ largeInt.LowPart = (int)lowPart;
+ largeInt.HighPart = (int)highPart;
+ }
+
+ de.Properties[suggestedAdProperty].Value = largeInt;
+ }
+
+ // Supported types
+ // ICollection where an item of the collection is not an ICollection or IList
+ // object[]
+ // object
+ protected static void ExtensionCacheToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ ExtensionCache cacheValues = (ExtensionCache)p.GetValueForProperty(propertyName);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheToLdapConverter");
+
+ foreach (KeyValuePair<string, ExtensionCacheValue> kvp in cacheValues.properties)
+ {
+ if (!kvp.Value.Filter && null != kvp.Value.Value && kvp.Value.Value.Length != 0)
+ {
+ // array of objects ( .Length > 1 && typeof(array[0] != ICollection or IList )
+ // Single collection ( .Length == 1 ) && typeof(array[0] == ICollection ) && typeof(array[0][0] != ICollection or IList )
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheToLdapConverter - Value Type " + kvp.Value.Value.GetType().ToString());
+
+ if ((kvp.Value.Value.Length == 1 && kvp.Value.Value[0] is ICollection) || (kvp.Value.Value.Length > 1))
+ {
+ if (kvp.Value.Value.Length > 1 && (kvp.Value.Value[0] is ICollection))
+ throw new ArgumentException(StringResources.InvalidExtensionCollectionType);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheToLdapConverter - Value implements ICollection");
+
+ ICollection valueCollection;
+
+ // byte[] gets special treatment (following S.DS and ADSI) - we don't treat it as ICollection but rather as a whole
+ if (kvp.Value.Value.Length == 1 && kvp.Value.Value[0] is ICollection && !(kvp.Value.Value[0] is byte[]))
+ {
+ valueCollection = (ICollection)kvp.Value.Value[0];
+ }
+ else
+ {
+ valueCollection = (ICollection)kvp.Value.Value;
+ }
+
+ foreach (object oVal in valueCollection)
+ {
+ if (null != oVal)
+ {
+ if ((oVal is ICollection || oVal is IList) && !(oVal is byte[]))
+ throw new ArgumentException(StringResources.InvalidExtensionCollectionType);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheToLdapConverter - Element Value Type " + oVal.GetType().ToString());
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheToLdapConverter - Adding Element " + oVal.ToString());
+ }
+
+ // Do nothing if we are not persisted and the value is null. We can't delete a property that
+ // has not already been set.
+ if (p.unpersisted && null == oVal)
+ continue;
+
+ de.Properties[kvp.Key].Add(oVal);
+ }
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheToLdapConverter - Collection complete");
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheToLdapConverter - Adding " + kvp.Value.Value.ToString());
+ // Do nothing if we are not persisted and the value is null. We can't delete a property that
+ // has not already been set.
+ if (p.unpersisted && (null == kvp.Value.Value[0]))
+ continue;
+
+ de.Properties[kvp.Key].Value = kvp.Value.Value[0];
+ }
+ }
+ }
+ }
+
+ protected static void GroupTypeToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ Debug.Assert(propertyName == PropertyNames.GroupIsSecurityGroup || propertyName == PropertyNames.GroupGroupScope);
+
+ int groupTypeCombined;
+
+ // We want to get the current value, so we can flip the appropriate bit while leaving the other bits as-is.
+ // If this is a to-be-inserted Principal, we may not have an existing groupType, so we'll use AD's default value
+ // for new groups.
+ if (de.Properties[suggestedAdProperty].Count > 0)
+ {
+ Debug.Assert(de.Properties[suggestedAdProperty].Count == 1);
+
+ groupTypeCombined = (int)de.Properties[suggestedAdProperty][0];
+ }
+ else
+ {
+ if (!p.unpersisted)
+ {
+ // It's not an unpersisted principal, so we should have the property. Perhaps we don't have access
+ // to it. In that case, we don't want to blindly overwrite whatever other bits might be there.
+ throw new PrincipalOperationException(
+ StringResources.ADStoreCtxUnableToReadExistingGroupTypeFlagsForUpdate);
+ }
+
+ // initial default value
+ groupTypeCombined = unchecked((int)(0x80000000 | 0x00000002)); // GROUP_TYPE_SECURITY_ENABLED | GROUP_TYPE_ACCOUNT_GROUP
+ }
+
+ switch (propertyName)
+ {
+ case PropertyNames.GroupIsSecurityGroup:
+ bool groupEnabled = (bool)p.GetValueForProperty(propertyName);
+
+ // Flip the bit without touching the other bits.
+ if (!groupEnabled)
+ Utils.ClearBit(ref groupTypeCombined, 0x80000000); // disabled --> clear GROUP_TYPE_SECURITY_ENABLED
+ else
+ Utils.SetBit(ref groupTypeCombined, 0x80000000); // enabled --> set GROUP_TYPE_SECURITY_ENABLED
+
+ break;
+
+ case PropertyNames.GroupGroupScope:
+
+ GroupScope groupType = (GroupScope)p.GetValueForProperty(propertyName);
+
+ // Remove the bits indicating the group type it currently is...
+ Utils.ClearBit(ref groupTypeCombined, ADGroupScope.Local);
+ Utils.ClearBit(ref groupTypeCombined, ADGroupScope.Global);
+ Utils.ClearBit(ref groupTypeCombined, ADGroupScope.Universal);
+
+ // ...and set the bit for the group type we want it to be
+ if (groupType == GroupScope.Local)
+ {
+ Utils.SetBit(ref groupTypeCombined, ADGroupScope.Local);
+ }
+ else if (groupType == GroupScope.Global)
+ {
+ Utils.SetBit(ref groupTypeCombined, ADGroupScope.Global);
+ }
+ else
+ {
+ Debug.Assert(groupType == GroupScope.Universal);
+ Utils.SetBit(ref groupTypeCombined, ADGroupScope.Universal);
+ }
+
+ break;
+
+ default:
+ Debug.Fail("ADStoreCtx.GroupTypeToLdapConverter: Fell off end looking for " + propertyName);
+ break;
+ }
+
+ de.Properties[suggestedAdProperty].Value = groupTypeCombined;
+ }
+
+ // {PropertyNames.GroupMembers, "members", null, new ToLdapConverterDelegate(GroupMembersToLdapConverter)},
+
+ protected static void UpdateGroupMembership(Principal group, DirectoryEntry de, NetCred credentials, AuthenticationTypes authTypes)
+ {
+ Debug.Assert(group.fakePrincipal == false);
+
+ PrincipalCollection members = (PrincipalCollection)group.GetValueForProperty(PropertyNames.GroupMembers);
+
+ DirectoryEntry groupDe = null;
+
+ try
+ {
+ //
+ // Process clear
+ //
+ if (members.Cleared)
+ {
+ DirectoryEntry copyOfDe = null;
+
+ try
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: clearing {0}", de.Path);
+
+ copyOfDe = SDSUtils.BuildDirectoryEntry(
+ de.Path,
+ credentials,
+ authTypes);
+
+ Debug.Assert(copyOfDe != null);
+ copyOfDe.Properties["member"].Clear();
+ copyOfDe.CommitChanges();
+ }
+ finally
+ {
+ if (copyOfDe != null)
+ copyOfDe.Dispose();
+ }
+ }
+
+ //
+ // Process inserted members
+ //
+
+ List<Principal> insertedMembers = members.Inserted;
+ List<Principal> removedMembers = members.Removed;
+
+ if (insertedMembers.Count > 0 || removedMembers.Count > 0)
+ {
+ groupDe = SDSUtils.BuildDirectoryEntry(
+ de.Path,
+ credentials,
+ authTypes);
+ }
+
+ // First, validate the members to be added
+ foreach (Principal member in insertedMembers)
+ {
+ Type memberType = member.GetType();
+ if ((memberType != typeof(UserPrincipal)) && (!memberType.IsSubclassOf(typeof(UserPrincipal))) &&
+ (memberType != typeof(ComputerPrincipal)) && (!memberType.IsSubclassOf(typeof(ComputerPrincipal))) &&
+ (memberType != typeof(GroupPrincipal)) && (!memberType.IsSubclassOf(typeof(GroupPrincipal))) &&
+ (!memberType.IsSubclassOf(typeof(AuthenticablePrincipal))))
+ {
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForGroupInsert, memberType.ToString()));
+ }
+ // Can't inserted unpersisted principal
+ if (member.unpersisted)
+ throw new InvalidOperationException(StringResources.StoreCtxGroupHasUnpersistedInsertedPrincipal);
+
+ Debug.Assert(member.Context != null);
+
+ // Can only insert AD principals (no reg-SAM/MSAM principals)
+ if (member.ContextType == ContextType.Machine)
+ throw new InvalidOperationException(StringResources.ADStoreCtxUnsupportedPrincipalContextForGroupInsert);
+ }
+
+ // Now add each member to the group
+ foreach (Principal member in insertedMembers)
+ {
+ // For objects in the current domain or any other domains in the forest we need to use the objects DN
+ // SID path would work for current domain but would not work for child or parent domains.
+ // For foreign objects we must use SID path e.g. "<SID=...>" so that the necessary FPO gets autocreated by AD.
+ // It also works in the "fake principal" case (which are always represented as FPOs).
+ if (!member.fakePrincipal && ADUtils.ArePrincipalsInSameForest(group, member))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: add {0}", member.DistinguishedName);
+
+ groupDe.Properties["member"].Add(member.DistinguishedName);
+ }
+ else
+ {
+ // Build a SID DN. This needs to be a DN path not an ADSI sid path with the LDAP prefix.
+ string memberSidDN = GetSidPathFromPrincipal(member);
+
+ if (memberSidDN == null)
+ throw new PrincipalOperationException(StringResources.ADStoreCtxCouldntGetSIDForGroupMember);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: add {0}", memberSidDN);
+
+ // Add the member to the group
+ groupDe.Properties["member"].Add(memberSidDN);
+ }
+ }
+
+ // If we had any members then commit them.
+ if (insertedMembers.Count > 0)
+ groupDe.CommitChanges();
+
+ //
+ // Process removed members
+ //
+
+ foreach (Principal member in removedMembers)
+ {
+ // Since we don't allow any of these to be inserted, none of them should ever
+ // show up in the removal list
+ Debug.Assert(member.unpersisted == false);
+ Debug.Assert(member.ContextType == ContextType.Domain || member.ContextType == ContextType.ApplicationDirectory);
+
+ // If the collection was cleared, there should be no original members to remove
+ Debug.Assert(members.Cleared == false);
+
+ // Since we are using PropertyValueCollection to do the item removal we are constrainted to items that are in the collection
+ // For principals that are in the same forest just use their DN to do the removal. This is how they are represented in the member attr.
+ // For foreign principals we must represent them with their SID binding string since they are locally represented by an FSP object.
+ if (!member.fakePrincipal && ADUtils.ArePrincipalsInSameForest(group, member))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: remove via DN {0}", member.DistinguishedName);
+
+ // Remove the member from the group
+
+ groupDe.Properties["member"].Remove(member.DistinguishedName);
+ }
+ else
+ {
+ // SID DN case
+
+ // Build a SID DN.
+ string memberSidDN = GetSidPathFromPrincipal(member);
+
+ if (memberSidDN == null)
+ throw new PrincipalOperationException(StringResources.ADStoreCtxCouldntGetSIDForGroupMember);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: remove via SID {0}", memberSidDN);
+
+ // Remove the member from the group
+ groupDe.Properties["member"].Remove(memberSidDN);
+ }
+ }
+
+ // If we used the collection to do a modification then commit it.
+ if (removedMembers.Count > 0)
+ groupDe.CommitChanges();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ if (null != groupDe)
+ groupDe.Dispose();
+ }
+ }
+
+ // Builds a SID dn for the principal <SID=...>
+ protected static string GetSidPathFromPrincipal(Principal p)
+ {
+ Debug.Assert(p.unpersisted == false);
+
+ if (p.fakePrincipal)
+ {
+ SecurityIdentifier Sid = p.Sid;
+ if (Sid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "GetSidADsPathFromPrincipal: no SID IC (fake principal)");
+ throw new InvalidOperationException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery);
+ }
+
+ return @"<SID=" + Utils.SecurityIdentifierToLdapHexBindingString(Sid) + ">";
+ }
+ else
+ {
+ // Retrieve the member's SID
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null); // since member can't be unpersisted
+
+ // Force it to load if it hasn't been already loaded
+ if (!de.Properties.Contains("objectSid"))
+ de.RefreshCache(new string[] { "objectSid" });
+
+ byte[] sid = (byte[])de.Properties["objectSid"].Value;
+
+ if (sid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADStoreCtx", "GetSidADsPathFromPrincipal: no SID");
+ return null;
+ }
+
+ // Build a SID DN
+ return @"<SID=" + Utils.ByteArrayToString(sid) + ">";
+ }
+ }
+
+ protected static void CannotChangePwdToLdapConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedAdProperty)
+ {
+ Debug.Assert(propertyName == PropertyNames.PwdInfoCannotChangePassword);
+
+ // Only modify disabled property if we are talking to an already persisted user.
+ // We need to set the password before we can enable the user on new objects.
+ // We can't read the sec desc of an unpersisted object so just return here. this will be set later.
+ if (p.unpersisted)
+ {
+ return;
+ }
+
+ SetCannotChangePasswordStatus(p, (bool)p.GetValueForProperty(propertyName), false);
+ }
+
+ protected bool BuildLdapFilterFromIdentityClaim(string urnValue, string urnScheme, ref string filter, bool useSidHistory, bool throwOnFail)
+ {
+ // To build the filter, we'll use the same IdentityClaimConverter routine as the QBE mechanism.
+ // This routine takes an IdentityClaimFilter as input, which in turn wraps an IdentityClaim.
+ // So we'll build an IdentityClaim from the user's parameters.
+
+ IdentityClaim ic = new IdentityClaim();
+ ic.UrnValue = urnValue;
+ ic.UrnScheme = urnScheme;
+
+ IdentityClaimFilter icFilterBase = new IdentityClaimFilter();
+ icFilterBase.Value = ic;
+
+ if (useSidHistory)
+ {
+ // Special handling if we want to include the SID History in the search
+ Debug.Assert(urnScheme == UrnScheme.SidScheme);
+ StringBuilder sb = new StringBuilder();
+ if (false == SecurityIdentityClaimConverterHelper(urnValue, useSidHistory, sb, throwOnFail))
+ {
+ return false;
+ }
+ filter = sb.ToString();
+ }
+ else
+ {
+ if (false == IdentityClaimToFilter(urnValue, urnScheme, ref filter, throwOnFail))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
+
+// #endif // PAPI_AD
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_Query.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_Query.cs
new file mode 100644
index 0000000000..0dcd963612
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_Query.cs
@@ -0,0 +1,1190 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+using System.Collections;
+using System.Text;
+using System.Globalization;
+using System.Security.Principal;
+using System.DirectoryServices;
+using System.Collections.Specialized;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ internal partial class ADStoreCtx : StoreCtx
+ {
+ //
+ // Query operations
+ //
+
+ // Returns true if this store has native support for search (and thus a wormhole).
+ // Returns true for everything but SAM (both reg-SAM and MSAM).
+ internal override bool SupportsSearchNatively { get { return true; } }
+
+ // Returns a type indicating the type of object that would be returned as the wormhole for the specified
+ // PrincipalSearcher.
+ internal override Type SearcherNativeType() { return typeof(DirectorySearcher); }
+
+ private void BuildExtensionPropertyList(Hashtable propertyList, Type p)
+ {
+ System.Reflection.PropertyInfo[] propertyInfoList = p.GetProperties();
+
+ foreach (System.Reflection.PropertyInfo pInfo in propertyInfoList)
+ {
+ DirectoryPropertyAttribute[] pAttributeList = (DirectoryPropertyAttribute[])(pInfo.GetCustomAttributes(typeof(DirectoryPropertyAttribute), true));
+ foreach (DirectoryPropertyAttribute pAttribute in pAttributeList)
+ {
+ if (!propertyList.Contains(pAttribute.SchemaAttributeName))
+ propertyList.Add(pAttribute.SchemaAttributeName, pAttribute.SchemaAttributeName);
+ }
+ }
+ }
+
+ protected void BuildPropertySet(Type p, StringCollection propertySet)
+ {
+ if (TypeToLdapPropListMap[this.MappingTableIndex].ContainsKey(p))
+ {
+ Debug.Assert(TypeToLdapPropListMap[this.MappingTableIndex].ContainsKey(p));
+ string[] props = new string[TypeToLdapPropListMap[this.MappingTableIndex][p].Count];
+ TypeToLdapPropListMap[this.MappingTableIndex][p].CopyTo(props, 0);
+ propertySet.AddRange(props);
+ }
+ else
+ {
+ Type baseType;
+
+ if (p.IsSubclassOf(typeof(UserPrincipal)))
+ {
+ baseType = typeof(UserPrincipal);
+ }
+ else if (p.IsSubclassOf(typeof(GroupPrincipal)))
+ {
+ baseType = typeof(GroupPrincipal);
+ }
+ else if (p.IsSubclassOf(typeof(ComputerPrincipal)))
+ {
+ baseType = typeof(ComputerPrincipal);
+ }
+ else if (p.IsSubclassOf(typeof(AuthenticablePrincipal)))
+ {
+ baseType = typeof(AuthenticablePrincipal);
+ }
+ else
+ {
+ baseType = typeof(Principal);
+ }
+
+ Hashtable propertyList = new Hashtable();
+
+ // Load the properties for the base types...
+ foreach (string s in TypeToLdapPropListMap[this.MappingTableIndex][baseType])
+ {
+ if (!propertyList.Contains(s))
+ {
+ propertyList.Add(s, s);
+ }
+ }
+
+ // Reflect the properties off the extension class and add them to the list.
+ BuildExtensionPropertyList(propertyList, p);
+
+ foreach (string property in propertyList.Values)
+ {
+ propertySet.Add(property);
+ }
+
+ // Cache the list for this property type so we don't need to reflect again in the future.
+ this.AddPropertySetToTypePropListMap(p, propertySet);
+ }
+ }
+
+ // Pushes the query represented by the QBE filter into the PrincipalSearcher's underlying native
+ // searcher object (creating a fresh native searcher and assigning it to the PrincipalSearcher if one
+ // doesn't already exist) and returns the native searcher.
+ // If the PrincipalSearcher does not have a query filter set (PrincipalSearcher.QueryFilter == null),
+ // produces a query that will match all principals in the store.
+ //
+ // For stores which don't have a native searcher (SAM), the StoreCtx
+ // is free to create any type of object it chooses to use as its internal representation of the query.
+ //
+ // Also adds in any clauses to the searcher to ensure that only principals, not mere
+ // contacts, are retrieved from the store.
+ internal override object PushFilterToNativeSearcher(PrincipalSearcher ps)
+ {
+ // This is the first time we're being called on this principal. Create a fresh searcher.
+ if (ps.UnderlyingSearcher == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "PushFilterToNativeSearcher: creating fresh DirectorySearcher");
+
+ ps.UnderlyingSearcher = new DirectorySearcher(this.ctxBase);
+ ((DirectorySearcher)ps.UnderlyingSearcher).PageSize = ps.PageSize;
+ ((DirectorySearcher)ps.UnderlyingSearcher).ServerTimeLimit = new TimeSpan(0, 0, 30); // 30 seconds
+ }
+
+ DirectorySearcher ds = (DirectorySearcher)ps.UnderlyingSearcher;
+
+ Principal qbeFilter = ps.QueryFilter;
+
+ StringBuilder ldapFilter = new StringBuilder();
+
+ if (qbeFilter == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "PushFilterToNativeSearcher: no qbeFilter specified");
+
+ // No filter specified. Search for all principals (all users, computers, groups).
+ ldapFilter.Append("(|(objectClass=user)(objectClass=computer)(objectClass=group))");
+ }
+ else
+ {
+ //
+ // Start by appending the appropriate objectClass given the Principal type
+ //
+ ldapFilter.Append(GetObjectClassPortion(qbeFilter.GetType()));
+
+ //
+ // Next, fill in the properties (if any)
+ //
+ QbeFilterDescription filters = BuildQbeFilterDescription(qbeFilter);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "PushFilterToNativeSearcher: using {0} filters", filters.FiltersToApply.Count);
+
+ Hashtable filterTable = (Hashtable)s_filterPropertiesTable[this.MappingTableIndex];
+
+ foreach (FilterBase filter in filters.FiltersToApply)
+ {
+ FilterPropertyTableEntry entry = (FilterPropertyTableEntry)filterTable[filter.GetType()];
+
+ if (entry == null)
+ {
+ // Must be a property we don't support
+ throw new InvalidOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.StoreCtxUnsupportedPropertyForQuery,
+ PropertyNamesExternal.GetExternalForm(filter.PropertyName)));
+ }
+
+ ldapFilter.Append(entry.converter(filter, entry.suggestedADPropertyName));
+ }
+
+ //
+ // Wrap off the filter
+ //
+ ldapFilter.Append(")");
+ }
+
+ // We don't need any attributes returned, since we're just going to get a DirectoryEntry
+ // for the result. Per RFC 2251, OID 1.1 == no attributes.
+ //ds.PropertiesToLoad.Add("1.1");
+ BuildPropertySet(qbeFilter.GetType(), ds.PropertiesToLoad);
+
+ ds.Filter = ldapFilter.ToString();
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "PushFilterToNativeSearcher: using LDAP filter {0}", ds.Filter);
+
+ return ds;
+ }
+
+ virtual protected string GetObjectClassPortion(Type principalType)
+ {
+ string ldapFilter;
+
+ if (principalType == typeof(UserPrincipal))
+ ldapFilter = "(&(objectCategory=user)(objectClass=user)"; // objCat because we don't want to match on computer accounts
+ else if (principalType == typeof(GroupPrincipal))
+ ldapFilter = "(&(objectClass=group)";
+ else if (principalType == typeof(ComputerPrincipal))
+ ldapFilter = "(&(objectClass=computer)";
+ else if (principalType == typeof(Principal))
+ ldapFilter = "(&(|(objectClass=user)(objectClass=group))";
+ else if (principalType == typeof(AuthenticablePrincipal))
+ ldapFilter = "(&(objectClass=user)";
+ else
+ {
+ string objClass = ExtensionHelper.ReadStructuralObjectClass(principalType);
+ if (null == objClass)
+ {
+ Debug.Fail("ADStoreCtx.GetObjectClassPortion: fell off end looking for " + principalType.ToString());
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForQuery, principalType.ToString()));
+ }
+ StringBuilder SB = new StringBuilder();
+ SB.Append("(&(objectClass=");
+ SB.Append(objClass);
+ SB.Append(")");
+ ldapFilter = SB.ToString();
+ }
+
+ return ldapFilter;
+ }
+
+ // The core query operation.
+ // Given a PrincipalSearcher containg a query filter, transforms it into the store schema
+ // and performs the query to get a collection of matching native objects (up to a maximum of sizeLimit,
+ // or uses the sizelimit already set on the DirectorySearcher if sizeLimit == -1).
+ // If the PrincipalSearcher does not have a query filter (PrincipalSearcher.QueryFilter == null),
+ // matches all principals in the store.
+ //
+ // The collection may not be complete, i.e., paging - the returned ResultSet will automatically
+ // page in additional results as needed.
+ internal override ResultSet Query(PrincipalSearcher ps, int sizeLimit)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "Query");
+
+ try
+ {
+ // Set up the DirectorySearcher
+ DirectorySearcher ds = (DirectorySearcher)PushFilterToNativeSearcher(ps);
+ int oldSizeLimit = ds.SizeLimit;
+
+ Debug.Assert(sizeLimit >= -1);
+
+ if (sizeLimit != -1)
+ ds.SizeLimit = sizeLimit;
+
+ // Perform the actual search
+ SearchResultCollection src = ds.FindAll();
+ Debug.Assert(src != null);
+
+ // Create a ResultSet for the search results
+ ADEntriesSet resultSet = new ADEntriesSet(src, this, ps.QueryFilter.GetType());
+
+ ds.SizeLimit = oldSizeLimit;
+
+ return resultSet;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ //
+ // Query tables
+ //
+
+ // We only list properties we support filtering on in this table. At run-time, if we detect they set a
+ // property that's not listed here, we throw an exception.
+ private static object[,] s_filterPropertiesTableRaw =
+ {
+ // QbeType AD property Converter
+ {typeof(DescriptionFilter), "description", new FilterConverterDelegate(StringConverter)},
+ {typeof(DisplayNameFilter), "displayName", new FilterConverterDelegate(StringConverter)},
+ {typeof(IdentityClaimFilter), "", new FilterConverterDelegate(IdentityClaimConverter)},
+ {typeof(SamAccountNameFilter), "sAMAccountName", new FilterConverterDelegate(StringConverter)},
+ {typeof(DistinguishedNameFilter), "distinguishedName", new FilterConverterDelegate(StringConverter)},
+ {typeof(GuidFilter), "objectGuid", new FilterConverterDelegate(GuidConverter)},
+ {typeof(UserPrincipalNameFilter), "userPrincipalName", new FilterConverterDelegate(StringConverter)},
+ {typeof(StructuralObjectClassFilter), "objectClass", new FilterConverterDelegate(StringConverter)},
+ {typeof(NameFilter), "name", new FilterConverterDelegate(StringConverter)},
+ {typeof(CertificateFilter), "", new FilterConverterDelegate(CertificateConverter)},
+ {typeof(AuthPrincEnabledFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},
+ {typeof(PermittedWorkstationFilter), "userWorkstations", new FilterConverterDelegate(CommaStringConverter)},
+ {typeof(PermittedLogonTimesFilter), "logonHours", new FilterConverterDelegate(BinaryConverter)},
+ {typeof(ExpirationDateFilter), "accountExpires", new FilterConverterDelegate(ExpirationDateConverter)},
+ {typeof(SmartcardLogonRequiredFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},
+ {typeof(DelegationPermittedFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},
+ {typeof(HomeDirectoryFilter), "homeDirectory", new FilterConverterDelegate(StringConverter)},
+ {typeof(HomeDriveFilter), "homeDrive", new FilterConverterDelegate(StringConverter)},
+ {typeof(ScriptPathFilter), "scriptPath", new FilterConverterDelegate(StringConverter)},
+ {typeof(PasswordNotRequiredFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},
+ {typeof(PasswordNeverExpiresFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},
+ {typeof(CannotChangePasswordFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},
+ {typeof(AllowReversiblePasswordEncryptionFilter), "userAccountControl", new FilterConverterDelegate(UserAccountControlConverter)},
+ {typeof(GivenNameFilter), "givenName", new FilterConverterDelegate(StringConverter)},
+ {typeof(MiddleNameFilter), "middleName", new FilterConverterDelegate(StringConverter)},
+ {typeof(SurnameFilter), "sn", new FilterConverterDelegate(StringConverter)},
+ {typeof(EmailAddressFilter), "mail", new FilterConverterDelegate(StringConverter)},
+ {typeof(VoiceTelephoneNumberFilter), "telephoneNumber", new FilterConverterDelegate(StringConverter)},
+ {typeof(EmployeeIDFilter), "employeeID", new FilterConverterDelegate(StringConverter)},
+ {typeof(GroupIsSecurityGroupFilter), "groupType", new FilterConverterDelegate(GroupTypeConverter)},
+ {typeof(GroupScopeFilter), "groupType", new FilterConverterDelegate(GroupTypeConverter)},
+ {typeof(ServicePrincipalNameFilter), "servicePrincipalName",new FilterConverterDelegate(StringConverter)},
+ {typeof(ExtensionCacheFilter), null ,new FilterConverterDelegate(ExtensionCacheConverter)},
+ {typeof(BadPasswordAttemptFilter), "badPasswordTime",new FilterConverterDelegate(DefaultValutMatchingDateTimeConverter)},
+ {typeof(ExpiredAccountFilter), "accountExpires",new FilterConverterDelegate(MatchingDateTimeConverter)},
+ {typeof(LastLogonTimeFilter), "lastLogon",new FilterConverterDelegate(LastLogonConverter)},
+ {typeof(LockoutTimeFilter), "lockoutTime",new FilterConverterDelegate(MatchingDateTimeConverter)},
+ {typeof(PasswordSetTimeFilter), "pwdLastSet",new FilterConverterDelegate(DefaultValutMatchingDateTimeConverter)},
+ {typeof(BadLogonCountFilter), "badPwdCount",new FilterConverterDelegate(MatchingIntConverter)}
+ };
+
+ private static Hashtable s_filterPropertiesTable = null;
+
+ private class FilterPropertyTableEntry
+ {
+ internal string suggestedADPropertyName;
+ internal FilterConverterDelegate converter;
+ }
+
+ //
+ // Conversion routines
+ //
+
+ // returns LDAP filter clause, e.g., "(description=foo*")
+ protected delegate string FilterConverterDelegate(FilterBase filter, string suggestedAdProperty);
+
+ protected static string StringConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ if (filter.Value != null)
+ {
+ sb.Append("(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=");
+ sb.Append(ADUtils.PAPIQueryToLdapQueryString((string)filter.Value));
+
+ sb.Append(")");
+ }
+ else
+ {
+ sb.Append("(!(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=*))");
+ }
+
+ return sb.ToString();
+ }
+
+ protected static string AcctDisabledConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ // Principal property is AccountEnabled where TRUE = enabled FALSE = disabled. In ADAM
+ // this is stored as accountDisabled where TRUE = disabled and FALSE = enabled so here we need to revese the value.
+ StringBuilder sb = new StringBuilder();
+
+ if (filter.Value != null)
+ {
+ sb.Append("(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=");
+ sb.Append(!(bool)filter.Value ? "TRUE" : "FALSE");
+ sb.Append(")");
+ }
+ else
+ {
+ sb.Append("(!(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=*))");
+ }
+
+ return sb.ToString();
+ }
+
+ // Use this function when searching for an attribute where the absence of the attribute = a default setting.
+ // i.e. ms-DS-UserPasswordNotRequired in ADAM where non existence equals false.
+ protected static string DefaultValueBoolConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ Debug.Assert(NonPresentAttrDefaultStateMapping != null);
+ Debug.Assert(NonPresentAttrDefaultStateMapping.ContainsKey(suggestedAdProperty));
+
+ StringBuilder sb = new StringBuilder();
+
+ if (filter.Value != null)
+ {
+ bool defaultState = NonPresentAttrDefaultStateMapping[suggestedAdProperty];
+
+ if (defaultState == (bool)filter.Value)
+ {
+ sb.Append("(|(!(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=*)(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=");
+ sb.Append((bool)filter.Value ? "TRUE" : "FALSE");
+ sb.Append(")))");
+ }
+ else
+ {
+ sb.Append("(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=");
+ sb.Append((bool)filter.Value ? "TRUE" : "FALSE");
+ sb.Append(")");
+ }
+ }
+ else
+ {
+ sb.Append("(!(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=*))");
+ }
+
+ return sb.ToString();
+ }
+ /*** If standard bool conversion is needed uncomment this function
+ protected static string BoolConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ if (filter.Value != null)
+ {
+ sb.Append("(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=");
+ sb.Append( (bool)filter.Value ? "TRUE" : "FALSE" );
+ sb.Append(")");
+ }
+ else
+ {
+ sb.Append("(!(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=*))");
+ }
+
+ return sb.ToString();
+ }
+ *****/
+ protected static string CommaStringConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ if (filter.Value != null)
+ {
+ sb.Append("(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=*");
+ sb.Append(ADUtils.PAPIQueryToLdapQueryString((string)filter.Value));
+ sb.Append("*");
+ sb.Append(")");
+ }
+ else
+ {
+ sb.Append("(!(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=*))");
+ }
+
+ return sb.ToString();
+ }
+
+ protected static bool IdentityClaimToFilter(string identity, string identityFormat, ref String filter, bool throwOnFail)
+ {
+ if (identity == null)
+ identity = "";
+
+ StringBuilder sb = new StringBuilder();
+
+ switch (identityFormat)
+ {
+ case UrnScheme.GuidScheme:
+
+ // Transform from hex string ("1AFF") to LDAP hex string ("\1A\FF")
+ // The string passed is the string format of a GUID. We neeed to convert it into the ldap hex string
+ // to build a query
+ Guid g;
+
+ try
+ {
+ g = new Guid(identity);
+ }
+ catch (FormatException e)
+ {
+ if (throwOnFail)
+ // For now throw an exception to let the caller know the type was invalid.
+ throw new ArgumentException(e.Message, e);
+ else
+ return false;
+ }
+
+ Byte[] gByte = g.ToByteArray();
+
+ StringBuilder stringguid = new StringBuilder();
+
+ foreach (byte b in gByte)
+ {
+ stringguid.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+ }
+
+ string ldapHexGuid = ADUtils.HexStringToLdapHexString(stringguid.ToString());
+
+ if (ldapHexGuid == null)
+ {
+ if (throwOnFail)
+ throw new ArgumentException(StringResources.StoreCtxGuidIdentityClaimBadFormat);
+ else
+ return false;
+ }
+
+ sb.Append("(objectGuid=");
+
+ sb.Append(ldapHexGuid);
+
+ sb.Append(")");
+ break;
+
+ case UrnScheme.DistinguishedNameScheme:
+ sb.Append("(distinguishedName=");
+ sb.Append(ADUtils.EscapeRFC2254SpecialChars(identity));
+ sb.Append(")");
+ break;
+
+ case UrnScheme.SidScheme:
+
+ if (false == SecurityIdentityClaimConverterHelper(identity, false, sb, throwOnFail))
+ {
+ return false;
+ }
+
+ break;
+
+ case UrnScheme.SamAccountScheme:
+
+ int index = identity.IndexOf('\\');
+
+ if (index == identity.Length - 1)
+ if (throwOnFail)
+ throw new ArgumentException(StringResources.StoreCtxNT4IdentityClaimWrongForm);
+ else
+ return false;
+
+ string samAccountName = (index != -1) ? identity.Substring(index + 1) : // +1 to skip the '/'
+ identity;
+
+ sb.Append("(samAccountName=");
+ sb.Append(ADUtils.EscapeRFC2254SpecialChars(samAccountName));
+ sb.Append(")");
+ break;
+
+ case UrnScheme.NameScheme:
+ sb.Append("(name=");
+ sb.Append(ADUtils.EscapeRFC2254SpecialChars(identity));
+ sb.Append(")");
+ break;
+
+ case UrnScheme.UpnScheme:
+ sb.Append("(userPrincipalName=");
+ sb.Append(ADUtils.EscapeRFC2254SpecialChars(identity));
+ sb.Append(")");
+ break;
+
+ default:
+ if (throwOnFail)
+ throw new ArgumentException(StringResources.StoreCtxUnsupportedIdentityClaimForQuery);
+ else
+ return false;
+ }
+
+ filter = sb.ToString();
+ return true;
+ }
+
+ protected static string IdentityClaimConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ IdentityClaim ic = (IdentityClaim)filter.Value;
+
+ if (ic.UrnScheme == null)
+ throw new ArgumentException(StringResources.StoreCtxIdentityClaimMustHaveScheme);
+
+ string urnValue = ic.UrnValue;
+ if (urnValue == null)
+ urnValue = "";
+
+ string filterString = null;
+
+ IdentityClaimToFilter(urnValue, ic.UrnScheme, ref filterString, true);
+
+ return filterString;
+ }
+
+ // If useSidHistory == false, build a filter for objectSid.
+ // If useSidHistory == true, build a filter for objectSid and sidHistory.
+ protected static bool SecurityIdentityClaimConverterHelper(string urnValue, bool useSidHistory, StringBuilder filter, bool throwOnFail)
+ {
+ // String is in SDDL format. Translate it to ldap hex format
+
+ IntPtr pBytePtr = IntPtr.Zero;
+ byte[] sidB = null;
+
+ try
+ {
+ if (UnsafeNativeMethods.ConvertStringSidToSid(urnValue, ref pBytePtr))
+ {
+ // Now we convert the native SID to a byte[] SID
+ sidB = Utils.ConvertNativeSidToByteArray(pBytePtr);
+ if (null == sidB)
+ {
+ if (throwOnFail)
+ throw new ArgumentException(StringResources.StoreCtxSecurityIdentityClaimBadFormat);
+ else
+ return false;
+ }
+ }
+ else
+ {
+ if (throwOnFail)
+ throw new ArgumentException(StringResources.StoreCtxSecurityIdentityClaimBadFormat);
+ else
+ return false;
+ }
+ }
+ finally
+ {
+ if (IntPtr.Zero != pBytePtr)
+ UnsafeNativeMethods.LocalFree(pBytePtr);
+ }
+
+ StringBuilder stringizedBinarySid = new StringBuilder();
+ foreach (byte b in sidB)
+ {
+ stringizedBinarySid.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+ }
+ string ldapHexSid = ADUtils.HexStringToLdapHexString(stringizedBinarySid.ToString());
+
+ if (ldapHexSid == null)
+ return false;
+
+ if (useSidHistory)
+ {
+ filter.Append("(|(objectSid=");
+ filter.Append(ldapHexSid);
+ filter.Append(")(sidHistory=");
+ filter.Append(ldapHexSid);
+ filter.Append("))");
+ }
+ else
+ {
+ filter.Append("(objectSid=");
+ filter.Append(ldapHexSid);
+ filter.Append(")");
+ }
+
+ return true;
+ }
+
+ protected static string CertificateConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ System.Security.Cryptography.X509Certificates.X509Certificate2 certificate =
+ (System.Security.Cryptography.X509Certificates.X509Certificate2)filter.Value;
+
+ byte[] rawCertificate = certificate.RawData;
+
+ StringBuilder sb = new StringBuilder();
+
+ sb.Append("(userCertificate=");
+ sb.Append(ADUtils.EscapeBinaryValue(rawCertificate));
+ sb.Append(")");
+
+ return sb.ToString();
+ }
+ protected static string UserAccountControlConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ Debug.Assert(String.Compare(suggestedAdProperty, "userAccountControl", StringComparison.OrdinalIgnoreCase) == 0);
+
+ StringBuilder sb = new StringBuilder();
+
+ // bitwise-AND
+
+ bool value = (bool)filter.Value;
+
+ switch (filter.PropertyName)
+ {
+ case AuthPrincEnabledFilter.PropertyNameStatic:
+ // UF_ACCOUNTDISABLE
+ // Note that the logic is inverted on this one. We expose "Enabled",
+ // but AD stores it as "Disabled".
+ if (value)
+ sb.Append("(!(userAccountControl:1.2.840.113556.1.4.803:=2))");
+ else
+ sb.Append("(userAccountControl:1.2.840.113556.1.4.803:=2)");
+ break;
+
+ case SmartcardLogonRequiredFilter.PropertyNameStatic:
+ // UF_SMARTCARD_REQUIRED
+ if (value)
+ sb.Append("(userAccountControl:1.2.840.113556.1.4.803:=262144)");
+ else
+ sb.Append("(!(userAccountControl:1.2.840.113556.1.4.803:=262144))");
+
+ break;
+
+ case DelegationPermittedFilter.PropertyNameStatic:
+ // UF_NOT_DELEGATED
+ // Note that the logic is inverted on this one. That's because we expose
+ // "delegation allowed", but AD represents it as the inverse, "delegation NOT allowed"
+ if (value)
+ sb.Append("(!(userAccountControl:1.2.840.113556.1.4.803:=1048576))");
+ else
+ sb.Append("(userAccountControl:1.2.840.113556.1.4.803:=1048576)");
+
+ break;
+
+ case PasswordNotRequiredFilter.PropertyNameStatic:
+ // UF_PASSWD_NOTREQD
+ if (value)
+ sb.Append("(userAccountControl:1.2.840.113556.1.4.803:=32)");
+ else
+ sb.Append("(!(userAccountControl:1.2.840.113556.1.4.803:=32))");
+
+ break;
+
+ case PasswordNeverExpiresFilter.PropertyNameStatic:
+ // UF_DONT_EXPIRE_PASSWD
+ if (value)
+ sb.Append("(userAccountControl:1.2.840.113556.1.4.803:=65536)");
+ else
+ sb.Append("(!(userAccountControl:1.2.840.113556.1.4.803:=65536))");
+
+ break;
+
+ case CannotChangePasswordFilter.PropertyNameStatic:
+ // UF_PASSWD_CANT_CHANGE
+ // This bit doesn't work correctly in AD (AD models the "user can't change password"
+ // setting as special ACEs in the ntSecurityDescriptor).
+ throw new InvalidOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.StoreCtxUnsupportedPropertyForQuery,
+ PropertyNamesExternal.GetExternalForm(filter.PropertyName)));
+
+ case AllowReversiblePasswordEncryptionFilter.PropertyNameStatic:
+ // UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
+ if (value)
+ sb.Append("(userAccountControl:1.2.840.113556.1.4.803:=128)");
+ else
+ sb.Append("(!(userAccountControl:1.2.840.113556.1.4.803:=128))");
+
+ break;
+
+ default:
+ Debug.Fail("ADStoreCtx.UserAccountControlConverter: fell off end looking for " + filter.PropertyName);
+ break;
+ }
+
+ return sb.ToString();
+ }
+
+ protected static string BinaryConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ if (filter.Value != null)
+ {
+ sb.Append("(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=");
+ sb.Append(ADUtils.EscapeBinaryValue((byte[])filter.Value));
+ }
+ else
+ {
+ sb.Append("(!(");
+ sb.Append(suggestedAdProperty);
+ sb.Append("=*))");
+ }
+
+ sb.Append(")");
+
+ return sb.ToString();
+ }
+
+ protected static string ExpirationDateConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ Debug.Assert(String.Compare(suggestedAdProperty, "accountExpires", StringComparison.OrdinalIgnoreCase) == 0);
+ Debug.Assert(filter is ExpirationDateFilter);
+
+ Nullable<DateTime> date = (Nullable<DateTime>)filter.Value;
+ StringBuilder sb = new StringBuilder();
+
+ if (!date.HasValue)
+ {
+ // Spoke with ColinBr. Both values are used to represent "no expiration date set".
+ sb.Append("(|(accountExpires=9223372036854775807)(accountExpires=0))");
+ }
+ else
+ {
+ sb.Append("(accountExpires=");
+ sb.Append(ADUtils.DateTimeToADString(date.Value));
+ sb.Append(")");
+ }
+
+ return sb.ToString();
+ }
+
+ protected static string GuidConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ Debug.Assert(String.Compare(suggestedAdProperty, "objectGuid", StringComparison.OrdinalIgnoreCase) == 0);
+ Debug.Assert(filter is GuidFilter);
+
+ Nullable<Guid> guid = (Nullable<Guid>)filter.Value;
+ StringBuilder sb = new StringBuilder();
+
+ if (guid == null)
+ {
+ // Spoke with ColinBr. Both values are used to represent "no expiration date set".
+ // sb.Append("(|(accountExpires=9223372036854775807)(accountExpires=0))");
+ }
+ else
+ {
+ sb.Append("(objectGuid=");
+
+ // Transform from hex string ("1AFF") to LDAP hex string ("\1A\FF")
+ string ldapHexGuid = ADUtils.HexStringToLdapHexString(guid.ToString());
+
+ if (ldapHexGuid == null)
+ throw new InvalidOperationException(StringResources.StoreCtxGuidIdentityClaimBadFormat);
+
+ sb.Append(ldapHexGuid);
+
+ sb.Append(")");
+ }
+
+ return sb.ToString();
+ }
+
+ protected static string MatchingIntConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ Debug.Assert(filter.Value is QbeMatchType);
+
+ QbeMatchType qmt = (QbeMatchType)filter.Value;
+
+ return (ExtensionTypeConverter(suggestedAdProperty, qmt.Value.GetType(), qmt.Value, qmt.Match));
+ }
+
+ protected static string DefaultValutMatchingDateTimeConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ Debug.Assert(filter.Value is QbeMatchType);
+
+ QbeMatchType qmt = (QbeMatchType)filter.Value;
+
+ Debug.Assert(qmt.Value is DateTime);
+
+ return (DateTimeFilterBuilder(suggestedAdProperty, (DateTime)qmt.Value, LdapConstants.defaultUtcTime, false, qmt.Match));
+ }
+
+ protected static string MatchingDateTimeConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ Debug.Assert(filter.Value is QbeMatchType);
+
+ QbeMatchType qmt = (QbeMatchType)filter.Value;
+
+ Debug.Assert(qmt.Value is DateTime);
+
+ return (ExtensionTypeConverter(suggestedAdProperty, qmt.Value.GetType(), qmt.Value, qmt.Match));
+ }
+
+ protected static string LastLogonConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ Debug.Assert(filter.Value is QbeMatchType);
+
+ QbeMatchType qmt = (QbeMatchType)filter.Value;
+
+ Debug.Assert(qmt.Value is DateTime);
+ Debug.Assert((suggestedAdProperty == "lastLogon") || (suggestedAdProperty == "lastLogonTimestamp"));
+
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(|");
+ sb.Append(DateTimeFilterBuilder("lastLogon", (DateTime)qmt.Value, LdapConstants.defaultUtcTime, false, qmt.Match));
+ sb.Append(DateTimeFilterBuilder("lastLogonTimestamp", (DateTime)qmt.Value, LdapConstants.defaultUtcTime, true, qmt.Match));
+ sb.Append(")");
+
+ return (sb.ToString());
+ }
+
+ protected static string GroupTypeConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ Debug.Assert(String.Compare(suggestedAdProperty, "groupType", StringComparison.OrdinalIgnoreCase) == 0);
+ Debug.Assert(filter is GroupIsSecurityGroupFilter || filter is GroupScopeFilter);
+
+ // 1.2.840.113556.1.4.803 is like a bit-wise AND operator
+ switch (filter.PropertyName)
+ {
+ case GroupIsSecurityGroupFilter.PropertyNameStatic:
+
+ bool value = (bool)filter.Value;
+
+ // GROUP_TYPE_SECURITY_ENABLED
+ // If group is enabled, it IS security-enabled
+ if (value)
+ return "(groupType:1.2.840.113556.1.4.803:=2147483648)";
+ else
+ return "(!(groupType:1.2.840.113556.1.4.803:=2147483648))";
+
+ case GroupScopeFilter.PropertyNameStatic:
+
+ GroupScope value2 = (GroupScope)filter.Value;
+
+ switch (value2)
+ {
+ case GroupScope.Local:
+ // GROUP_TYPE_RESOURCE_GROUP, a.k.a. ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP
+ return "(groupType:1.2.840.113556.1.4.803:=4)";
+
+ case GroupScope.Global:
+ // GROUP_TYPE_ACCOUNT_GROUP, a.k.a. ADS_GROUP_TYPE_GLOBAL_GROUP
+ return "(groupType:1.2.840.113556.1.4.803:=2)";
+
+ default:
+ // GROUP_TYPE_UNIVERSAL_GROUP, a.k.a. ADS_GROUP_TYPE_UNIVERSAL_GROUP
+ Debug.Assert(value2 == GroupScope.Universal);
+ return "(groupType:1.2.840.113556.1.4.803:=8)";
+ }
+
+ default:
+ Debug.Fail("ADStoreCtx.GroupTypeConverter: fell off end looking for " + filter.PropertyName);
+ return "";
+ }
+ }
+
+ public static string DateTimeFilterBuilder(string attributeName, DateTime searchValue, DateTime defaultValue, bool requirePresence, MatchType mt)
+ {
+ string ldapSearchValue = null;
+ string ldapDefaultValue = null;
+ bool defaultNeeded = false;
+
+ ldapSearchValue = ADUtils.DateTimeToADString(searchValue);
+ if (defaultValue != null)
+ {
+ ldapDefaultValue = ADUtils.DateTimeToADString(defaultValue);
+ }
+
+ StringBuilder ldapFilter = new StringBuilder("(");
+
+ if (defaultValue != null && (mt != MatchType.Equals && mt != MatchType.NotEquals))
+ {
+ defaultNeeded = true;
+ }
+
+ if (defaultNeeded || (mt == MatchType.NotEquals && requirePresence))
+ {
+ ldapFilter.Append("&(");
+ }
+
+ switch (mt)
+ {
+ case MatchType.Equals:
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapSearchValue);
+ break;
+
+ case MatchType.NotEquals:
+ ldapFilter.Append("!(");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapSearchValue);
+ ldapFilter.Append(")");
+ break;
+
+ case MatchType.GreaterThanOrEquals:
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append(">=");
+ ldapFilter.Append(ldapSearchValue);
+ break;
+
+ case MatchType.LessThanOrEquals:
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("<=");
+ ldapFilter.Append(ldapSearchValue);
+ break;
+
+ case MatchType.GreaterThan:
+ ldapFilter.Append("&");
+
+ // Greater-than-or-equals (or less-than-or-equals))
+ ldapFilter.Append("(");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append(mt == MatchType.GreaterThan ? ">=" : "<=");
+ ldapFilter.Append(ldapSearchValue);
+ ldapFilter.Append(")");
+
+ // And not-equal
+ ldapFilter.Append("(!(");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapSearchValue);
+ ldapFilter.Append("))");
+
+ // And exists (need to include because of tristate LDAP logic)
+ ldapFilter.Append("(");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=*)");
+ break;
+
+ case MatchType.LessThan:
+ goto case MatchType.GreaterThan;
+ }
+
+ ldapFilter.Append(")");
+ bool closeFilter = false;
+
+ if (defaultNeeded)
+ {
+ ldapFilter.Append("(!");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapDefaultValue);
+ ldapFilter.Append(")");
+ closeFilter = true;
+ }
+
+ if (mt == MatchType.NotEquals && requirePresence)
+ {
+ ldapFilter.Append("(");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=*)");
+ closeFilter = true;
+ }
+
+ if (closeFilter)
+ ldapFilter.Append(")");
+
+ return (ldapFilter.ToString());
+ }
+
+ public static string ExtensionTypeConverter(string attributeName, Type type, Object value, MatchType mt)
+ {
+ StringBuilder ldapFilter = new StringBuilder("(");
+ string ldapValue;
+
+ if (typeof(Boolean) == type)
+ {
+ ldapValue = ((bool)value ? "TRUE" : "FALSE");
+ }
+ else if (type is ICollection)
+ {
+ StringBuilder collectionFilter = new StringBuilder();
+
+ ICollection collection = (ICollection)value;
+
+ foreach (object o in collection)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionTypeConverter collection filter type " + o.GetType().ToString());
+ collectionFilter.Append(ExtensionTypeConverter(attributeName, o.GetType(), o, mt));
+ }
+ return collectionFilter.ToString();
+ }
+ else if (typeof(DateTime) == type)
+ {
+ ldapValue = ADUtils.DateTimeToADString((DateTime)value);
+ }
+ else
+ {
+ ldapValue = ADUtils.PAPIQueryToLdapQueryString(value.ToString());
+ }
+
+ switch (mt)
+ {
+ case MatchType.Equals:
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapValue);
+ break;
+
+ case MatchType.NotEquals:
+ ldapFilter.Append("!(");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapValue);
+ ldapFilter.Append(")");
+ break;
+
+ case MatchType.GreaterThanOrEquals:
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append(">=");
+ ldapFilter.Append(ldapValue);
+ break;
+
+ case MatchType.LessThanOrEquals:
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("<=");
+ ldapFilter.Append(ldapValue);
+ break;
+
+ case MatchType.GreaterThan:
+ ldapFilter.Append("&");
+
+ // Greater-than-or-equals (or less-than-or-equals))
+ ldapFilter.Append("(");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append(mt == MatchType.GreaterThan ? ">=" : "<=");
+ ldapFilter.Append(ldapValue);
+ ldapFilter.Append(")");
+
+ // And not-equal
+ ldapFilter.Append("(!(");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=");
+ ldapFilter.Append(ldapValue);
+ ldapFilter.Append("))");
+
+ // And exists (need to include because of tristate LDAP logic)
+ ldapFilter.Append("(");
+ ldapFilter.Append(attributeName);
+ ldapFilter.Append("=*)");
+ break;
+
+ case MatchType.LessThan:
+ goto case MatchType.GreaterThan;
+ }
+
+ ldapFilter.Append(")");
+
+ return ldapFilter.ToString();
+ }
+
+ protected static string ExtensionCacheConverter(FilterBase filter, string suggestedAdProperty)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheConverter ");
+
+ StringBuilder query = new StringBuilder();
+
+ if (filter.Value != null)
+ {
+ ExtensionCache ec = (ExtensionCache)filter.Value;
+
+ foreach (KeyValuePair<string, ExtensionCacheValue> kvp in ec.properties)
+ {
+ Type type = kvp.Value.Type == null ? kvp.Value.Value.GetType() : kvp.Value.Type;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheConverter filter type " + type.ToString());
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheConverter match type " + kvp.Value.MatchType.ToString());
+
+ if (kvp.Value.Value is ICollection)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheConverter encountered collection.");
+
+ ICollection collection = (ICollection)kvp.Value.Value;
+ foreach (object o in collection)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheConverter collection filter type " + o.GetType().ToString());
+ query.Append(ExtensionTypeConverter(kvp.Key, o.GetType(), o, kvp.Value.MatchType));
+ }
+ }
+ else
+ {
+ query.Append(ExtensionTypeConverter(kvp.Key, type, kvp.Value.Value, kvp.Value.MatchType));
+ }
+ }
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheConverter complete built filter " + query.ToString());
+ return query.ToString();
+ }
+
+ ///
+ /// <summary>
+ /// Adds the specified Property set to the TypeToPropListMap data structure.
+ /// </summary>
+ ///
+ private void AddPropertySetToTypePropListMap(Type principalType, StringCollection propertySet)
+ {
+ lock (TypeToLdapPropListMap)
+ {
+ if (!TypeToLdapPropListMap[this.MappingTableIndex].ContainsKey(principalType))
+ {
+ TypeToLdapPropListMap[this.MappingTableIndex].Add(principalType, propertySet);
+ }
+ }
+ }
+ }
+}
+
+//#endif // PAPI_AD
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreKey.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreKey.cs
new file mode 100644
index 0000000000..b2f62f7dca
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreKey.cs
@@ -0,0 +1,87 @@
+// 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.Diagnostics;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class ADStoreKey : StoreKey
+ {
+ // For regular ADStoreKeys
+ private System.Guid _objectGuid;
+
+ // For ADStoreKeys corresponding to well-known SIDs
+ private bool _wellKnownSid;
+ private string _domainName;
+ private byte[] _sid;
+
+ public ADStoreKey(Guid guid)
+ {
+ Debug.Assert(guid != Guid.Empty);
+
+ _objectGuid = guid;
+ _wellKnownSid = false;
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "ADStoreKey",
+ "creating GUID key for GUID={0}",
+ guid);
+ }
+
+ public ADStoreKey(string domainName, byte[] sid)
+ {
+ Debug.Assert(domainName != null && domainName.Length > 0);
+ Debug.Assert(sid != null && sid.Length != 0);
+
+ // Make a copy of the SID, since a byte[] is mutable
+ _sid = new byte[sid.Length];
+ Array.Copy(sid, _sid, sid.Length);
+
+ _domainName = domainName;
+ _wellKnownSid = true;
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "ADStoreKey",
+ "creating SID key for domainName={0}, sid={1}",
+ domainName,
+ Utils.ByteArrayToString(sid));
+ }
+
+ override public bool Equals(object o)
+ {
+ if (!(o is ADStoreKey))
+ return false;
+
+ ADStoreKey that = (ADStoreKey)o;
+
+ if (_wellKnownSid != that._wellKnownSid)
+ return false;
+
+ if (!_wellKnownSid)
+ {
+ if (_objectGuid == that._objectGuid)
+ return true;
+ }
+ else
+ {
+ if ((String.Compare(_domainName, that._domainName, StringComparison.OrdinalIgnoreCase) == 0) &&
+ (Utils.AreBytesEqual(_sid, that._sid)))
+ return true;
+ }
+
+ return false;
+ }
+
+ override public int GetHashCode()
+ {
+ return (_wellKnownSid == false) ?
+ _objectGuid.GetHashCode() :
+ (_domainName.GetHashCode() ^ _sid.GetHashCode());
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADUtils.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADUtils.cs
new file mode 100644
index 0000000000..8c5f8f3218
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADUtils.cs
@@ -0,0 +1,550 @@
+// 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.Diagnostics;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.DirectoryServices;
+using System.DirectoryServices.ActiveDirectory;
+using System.Text;
+using System.Security.Principal;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class ADUtils
+ {
+ // To stop the compiler from autogenerating a constructor for this class
+ private ADUtils() { }
+
+ // We use this, rather than simply testing DirectoryEntry.SchemaClassName, because we don't
+ // want to miss objects that are of a derived type.
+ // Note that, since computer is a derived class of user in AD, if you don't want to confuse
+ // computers with users, you must test an object for computer status before testing it for
+ // user status.
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ [System.Security.SecurityCritical]
+ static internal bool IsOfObjectClass(DirectoryEntry de, string classToCompare)
+ {
+ return de.Properties["objectClass"].Contains(classToCompare);
+ }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ [System.Security.SecurityCritical]
+ static internal bool IsOfObjectClass(SearchResult sr, string classToCompare)
+ {
+ return sr.Properties["objectClass"].Contains(classToCompare);
+ }
+
+ // Retrieves the name of the actual server that the DirectoryEntry is connected to
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ [System.Security.SecurityCritical]
+ static internal string GetServerName(DirectoryEntry de)
+ {
+ UnsafeNativeMethods.IAdsObjectOptions objOptions = (UnsafeNativeMethods.IAdsObjectOptions)de.NativeObject;
+ return (string)objOptions.GetOption(0 /* == ADS_OPTION_SERVERNAME */);
+ }
+
+ // This routine escapes values used in DNs, per RFC 2253 and ADSI escaping rules.
+ // It treats its input as a unescaped literal and produces a LDAP string that represents that literal
+ // and that is escaped according to RFC 2253 and ADSI rules for DN components.
+ [System.Security.SecurityCritical]
+ static internal string EscapeDNComponent(string dnComponent)
+ {
+ //
+ // From RFC 2254:
+ //
+ // If the UTF-8 string does not have any of the following characters
+ // which need escaping, then that string can be used as the string
+ // representation of the value.
+ //
+ // o a space or "#" character occurring at the beginning of the
+ // string
+ //
+ // o a space character occurring at the end of the string
+ //
+ // o one of the characters ",", "+", """, "\", "<", ">" or ";"
+ //
+ // Implementations MAY escape other characters.
+ //
+ // If a character to be escaped is one of the list shown above, then it
+ // is prefixed by a backslash ('\' ASCII 92).
+ //
+ // Otherwise the character to be escaped is replaced by a backslash and
+ // two hex digits, which form a single byte in the code of the
+ // character.
+ //
+ // ADSI imposes the additional requirement that occurrences of '=' be escaped.
+ // For ADsPaths, ADSI also requires the '/' (forward slash) to be escaped,
+ // but not for the individual DN components that we're building here
+ // (e.g., for IADsContainer::Create).
+
+ StringBuilder sb = new StringBuilder(dnComponent.Length);
+
+ // If it starts with ' ' or '#', escape the first character (clause one)
+ int startingIndex = 0;
+ if (dnComponent[0] == ' ' || dnComponent[0] == '#')
+ {
+ sb.Append(@"\");
+ sb.Append(dnComponent[0]);
+ startingIndex++;
+ }
+
+ // Handle the escaping of the remaining characters (clause three)
+ for (int i = startingIndex; i < dnComponent.Length; i++)
+ {
+ char c = dnComponent[i];
+
+ switch (c)
+ {
+ case ',':
+ sb.Append(@"\,");
+ break;
+
+ case '+':
+ sb.Append(@"\+");
+ break;
+
+ case '\"':
+ sb.Append("\\\""); // that's the literal sequence "backslash followed by a quotation mark"
+ break;
+
+ case '\\':
+ sb.Append(@"\\");
+ break;
+
+ case '>':
+ sb.Append(@"\>");
+ break;
+
+ case '<':
+ sb.Append(@"\<");
+ break;
+
+ case ';':
+ sb.Append(@"\;");
+ break;
+
+ case '=':
+ sb.Append(@"\=");
+ break;
+
+ default:
+ sb.Append(c.ToString());
+ break;
+ }
+ }
+
+ // If it ends in a space, escape that space (clause two)
+ if (sb[sb.Length - 1] == ' ')
+ {
+ sb.Remove(sb.Length - 1, 1);
+ sb.Append(@"\ ");
+ }
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "ADUtils",
+ "EscapeDNComponent: mapped '{0}' to '{1}'",
+ dnComponent,
+ sb.ToString());
+
+ return sb.ToString();
+ }
+
+ // This routine escapes values used in search filters, per RFC 2254 escaping rules.
+ // It treats its input as a unescaped literal and produces a LDAP string that represents that literal
+ // and that is escaped according to RFC 2254 rules.
+ [System.Security.SecurityCritical]
+ static internal string EscapeRFC2254SpecialChars(string s)
+ {
+ StringBuilder sb = new StringBuilder(s.Length);
+
+ foreach (char c in s)
+ {
+ switch (c)
+ {
+ case '(':
+ sb.Append(@"\28");
+ break;
+
+ case ')':
+ sb.Append(@"\29");
+ break;
+
+ case '*':
+ sb.Append(@"\2a");
+ break;
+
+ case '\\':
+ sb.Append(@"\5c");
+ break;
+
+ default:
+ sb.Append(c.ToString());
+ break;
+ }
+ }
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "ADUtils",
+ "EscapeRFC2254SpecialChars: mapped '{0}' to '{1}'",
+ s,
+ sb.ToString());
+
+ return sb.ToString();
+ }
+
+ // This routine escapes PAPI string values that may contain wilcards.
+ // It treats its input string as a PAPI string filter (escaped according to
+ // PAPI rules, and possibly containing wildcards), and produces a string
+ // escaped to RFC 2254 rules and possibly containing wildcards.
+ static internal string PAPIQueryToLdapQueryString(string papiString)
+ {
+ //
+ // Wildcard
+ // * --> *
+ //
+ // Escaped Literals
+ // \* --> \2a
+ // \\ --> \5c
+ //
+ // Other
+ // ( --> \28
+ // ) --> \29
+ // \( --> \28
+ // \) --> \29
+ // x --> x (where x is anything else)
+ // \x --> x (where x is anything else)
+
+ StringBuilder sb = new StringBuilder(papiString.Length);
+
+ bool escapeMode = false;
+
+ foreach (char c in papiString)
+ {
+ if (escapeMode == false)
+ {
+ switch (c)
+ {
+ case '(':
+ sb.Append(@"\28"); // ( --> \28
+ break;
+
+ case ')':
+ sb.Append(@"\29"); // ) --> \29
+ break;
+
+ case '\\':
+ escapeMode = true;
+ break;
+
+ default:
+ // including the '*' wildcard
+ sb.Append(c.ToString()); // * --> * and x --> x
+ break;
+ }
+ }
+ else
+ {
+ escapeMode = false;
+
+ switch (c)
+ {
+ case '(':
+ sb.Append(@"\28"); // \( --> \28
+ break;
+
+ case ')':
+ sb.Append(@"\29"); // \) --> \29
+ break;
+
+ case '*':
+ sb.Append(@"\2a"); // \* --> \2a
+ break;
+
+ case '\\':
+ sb.Append(@"\5c"); // \\ --> \5c
+ break;
+
+ default:
+ sb.Append(c.ToString()); // \x --> x
+ break;
+ }
+ }
+ }
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "ADUtils",
+ "PAPIQueryToLdapQueryString: mapped '{0}' to '{1}'",
+ papiString,
+ sb.ToString());
+
+ return sb.ToString();
+ }
+
+ static internal string EscapeBinaryValue(byte[] bytes)
+ {
+ StringBuilder sb = new StringBuilder(bytes.Length * 3);
+
+ foreach (byte b in bytes)
+ {
+ sb.Append(@"\");
+ sb.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+ }
+
+ return sb.ToString();
+ }
+
+ static internal string DateTimeToADString(DateTime dateTime)
+ {
+ // DateTime --> FILETIME --> stringized FILETIME
+
+ long fileTime = dateTime.ToFileTimeUtc();
+
+ return fileTime.ToString(CultureInfo.InvariantCulture);
+ }
+
+ static internal DateTime ADFileTimeToDateTime(Int64 filetime)
+ {
+ // int64 FILETIME --> DateTime
+ return DateTime.FromFileTimeUtc(filetime);
+ }
+
+ static internal Int64 DateTimeToADFileTime(DateTime dt)
+ {
+ // DateTime --> int64 FILETIME
+ return dt.ToFileTimeUtc();
+ }
+
+ static internal Int64 LargeIntToInt64(UnsafeNativeMethods.IADsLargeInteger largeInt)
+ {
+ uint lowPart = (uint)largeInt.LowPart;
+ uint highPart = (uint)largeInt.HighPart;
+ Int64 i = (long)(((ulong)lowPart) | (((ulong)highPart) << 32));
+
+ return i;
+ }
+
+ // Transform from hex string ("1AFF") to LDAP hex string ("\1A\FF").
+ // Returns null if input string is not a valid hex string.
+ static internal string HexStringToLdapHexString(string s)
+ {
+ Debug.Assert(s != null);
+
+ if (s.Length % 2 != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADUtils", "HexStringToLdapHexString: string has bad length " + s.Length);
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < (s.Length) / 2; i++)
+ {
+ char firstChar = s[i * 2];
+ char secondChar = s[(i * 2) + 1];
+
+ if (((firstChar >= '0' && firstChar <= '9') || (firstChar >= 'A' && firstChar <= 'F') || (firstChar >= 'a' && firstChar <= 'f')) &&
+ ((secondChar >= '0' && secondChar <= '9') || (secondChar >= 'A' && secondChar <= 'F') || (secondChar >= 'a' && secondChar <= 'f')))
+ {
+ sb.Append(@"\");
+ sb.Append(firstChar);
+ sb.Append(secondChar);
+ }
+ else
+ {
+ // not a hex character
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "ADUtils", "HexStringToLdapHexString: invalid string " + s);
+ return null;
+ }
+ }
+
+ return sb.ToString();
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: ADStoreCtx.get_DnsForestName():System.String" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal bool ArePrincipalsInSameForest(Principal p1, Principal p2)
+ {
+ string p1DnsForestName = ((ADStoreCtx)p1.GetStoreCtxToUse()).DnsForestName;
+ string p2DnsForestName = ((ADStoreCtx)p2.GetStoreCtxToUse()).DnsForestName;
+
+ return (String.Compare(p1DnsForestName, p2DnsForestName, StringComparison.OrdinalIgnoreCase) == 0);
+ }
+
+ ///
+ /// <summary>
+ /// Returns true if the specified SIDs are from the same domain.
+ /// Otherwise return false.
+ /// </summary>
+ /// <param name="sid1"></param>
+ /// <param name="sid2"></param>
+ /// <returns>Returns true if the specified SIDs are from the same domain.
+ /// Otherwise return false
+ /// </returns>
+ ///
+ static internal bool AreSidsInSameDomain(SecurityIdentifier sid1, SecurityIdentifier sid2)
+ {
+ if (sid1.IsAccountSid() && sid2.IsAccountSid())
+ {
+ return (sid1.AccountDomainSid.Equals(sid2.AccountDomainSid));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ [System.Security.SecurityCritical]
+ static internal Principal DirectoryEntryAsPrincipal(DirectoryEntry de, ADStoreCtx storeCtx)
+ {
+ if (ADUtils.IsOfObjectClass(de, "computer") ||
+ ADUtils.IsOfObjectClass(de, "user") ||
+ ADUtils.IsOfObjectClass(de, "group"))
+ {
+ return storeCtx.GetAsPrincipal(de, null);
+ }
+ else if (ADUtils.IsOfObjectClass(de, "foreignSecurityPrincipal"))
+ {
+ return storeCtx.ResolveCrossStoreRefToPrincipal(de);
+ }
+ else
+ {
+ return storeCtx.GetAsPrincipal(de, null);
+ }
+ }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ [System.Security.SecurityCritical]
+ static internal Principal SearchResultAsPrincipal(SearchResult sr, ADStoreCtx storeCtx, object discriminant)
+ {
+ if (ADUtils.IsOfObjectClass(sr, "computer") ||
+ ADUtils.IsOfObjectClass(sr, "user") ||
+ ADUtils.IsOfObjectClass(sr, "group"))
+ {
+ return storeCtx.GetAsPrincipal(sr, discriminant);
+ }
+ else if (ADUtils.IsOfObjectClass(sr, "foreignSecurityPrincipal"))
+ {
+ return storeCtx.ResolveCrossStoreRefToPrincipal(sr.GetDirectoryEntry());
+ }
+ else
+ {
+ return storeCtx.GetAsPrincipal(sr, discriminant);
+ }
+ }
+
+ // This function is used to check if we will be able to lookup a SID from the
+ // target domain by targeting the local computer. This is done by checking for either
+ // a outbound or bidirectional trust between the computers domain and the target
+ // domain or the current forest and the target domain's forest.
+ // target domain must be the full DNS domain name of the target domain to make the string
+ // compare below work properly.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Domain.GetComputerDomain():System.DirectoryServices.ActiveDirectory.Domain" />
+ // <SatisfiesLinkDemand Name="Domain.GetTrustRelationship(System.String):System.DirectoryServices.ActiveDirectory.TrustRelationshipInformation" />
+ // <SatisfiesLinkDemand Name="Forest.GetCurrentForest():System.DirectoryServices.ActiveDirectory.Forest" />
+ // <SatisfiesLinkDemand Name="Domain.GetDomain(System.DirectoryServices.ActiveDirectory.DirectoryContext):System.DirectoryServices.ActiveDirectory.Domain" />
+ // <SatisfiesLinkDemand Name="Domain.get_Forest():System.DirectoryServices.ActiveDirectory.Forest" />
+ // <SatisfiesLinkDemand Name="Forest.get_Name():System.String" />
+ // <SatisfiesLinkDemand Name="Forest.GetTrustRelationship(System.String):System.DirectoryServices.ActiveDirectory.ForestTrustRelationshipInformation" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal bool VerifyOutboundTrust(string targetDomain, string username, string password)
+ {
+ Domain currentDom = null;
+
+ try
+ {
+ currentDom = Domain.GetComputerDomain();
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // The computer is not domain joined so there cannot be a trust...
+ return false;
+ }
+ catch (System.Security.Authentication.AuthenticationException)
+ {
+ // The computer is domain joined but we are running with creds that can't access it. We can't determine trust.
+ return false;
+ }
+
+ // If this is the same domain then we have a trust.
+ // Domain.Name always returns full dns name.
+ // function is always supplied with a full DNS domain name.
+ if (String.Compare(currentDom.Name, targetDomain, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ return true;
+ }
+
+ try
+ {
+ TrustRelationshipInformation TRI = currentDom.GetTrustRelationship(targetDomain);
+
+ if (TrustDirection.Outbound == TRI.TrustDirection || TrustDirection.Bidirectional == TRI.TrustDirection)
+ {
+ return true;
+ }
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ }
+
+ // Since we were able to retrive the computer domain above we should be able to access the current forest here.
+ Forest currentForest = Forest.GetCurrentForest();
+
+ Domain targetdom = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, targetDomain, username, password));
+
+ try
+ {
+ ForestTrustRelationshipInformation FTC = currentForest.GetTrustRelationship(targetdom.Forest.Name);
+
+ if (TrustDirection.Outbound == FTC.TrustDirection || TrustDirection.Bidirectional == FTC.TrustDirection)
+ {
+ return true;
+ }
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ }
+
+ return false;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Properties():System.DirectoryServices.PropertyCollection" />
+ // <SatisfiesLinkDemand Name="PropertyCollection.get_Item(System.String):System.DirectoryServices.PropertyValueCollection" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal string RetriveWkDn(DirectoryEntry deBase, string defaultNamingContext, string serverName, Byte[] wellKnownContainerGuid)
+ {
+ /*
+ bool w2k3Supported = false;
+ if ( w2k3Supported )
+ {
+ return @"LDAP://" + this.UserSuppliedServerName + @"/<WKGUID= " + Constants.GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER_W + @"," + this.DefaultNamingContext + @">";
+ }
+ */
+ PropertyValueCollection wellKnownObjectValues = deBase.Properties["wellKnownObjects"];
+
+ foreach (UnsafeNativeMethods.IADsDNWithBinary value in wellKnownObjectValues)
+ {
+ if (Utils.AreBytesEqual(wellKnownContainerGuid, (byte[])value.BinaryValue))
+ {
+ return ("LDAP://" + serverName + @"/" + value.DNString);
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/DSPropertyCollection.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/DSPropertyCollection.cs
new file mode 100644
index 0000000000..075242e866
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/DSPropertyCollection.cs
@@ -0,0 +1,89 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.DirectoryServices;
+using System.Text;
+using System.Net;
+using System.Collections;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class dSPropertyCollection
+ {
+ private PropertyCollection _pc;
+ private ResultPropertyCollection _rp;
+
+ private dSPropertyCollection() { }
+ internal dSPropertyCollection(PropertyCollection pc) { _pc = pc; }
+ internal dSPropertyCollection(ResultPropertyCollection rp) { _rp = rp; }
+
+ public dSPropertyValueCollection this[string propertyName]
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PropertyCollection.get_Item(System.String):System.DirectoryServices.PropertyValueCollection" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ if (propertyName == null)
+ throw new ArgumentNullException("propertyName");
+
+ if (null != _pc)
+ {
+ return new dSPropertyValueCollection(_pc[propertyName]);
+ }
+ else
+ {
+ return new dSPropertyValueCollection(_rp[propertyName]);
+ }
+ }
+ }
+ }
+
+ internal class dSPropertyValueCollection
+ {
+ private PropertyValueCollection _pc;
+ private ResultPropertyValueCollection _rc;
+
+ private dSPropertyValueCollection() { }
+ internal dSPropertyValueCollection(PropertyValueCollection pc) { _pc = pc; }
+ internal dSPropertyValueCollection(ResultPropertyValueCollection rc) { _rc = rc; }
+
+ public object this[int index]
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PropertyValueCollection.get_Item(System.Int32):System.Object" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ if (_pc != null)
+ {
+ return _pc[index];
+ }
+ else
+ {
+ return _rc[index];
+ }
+ }
+ }
+ public int Count
+ {
+ get
+ {
+ return (_pc != null ? _pc.Count : _rc.Count);
+ }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return (_pc != null ? _pc.GetEnumerator() : _rc.GetEnumerator());
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/QBEMatchType.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/QBEMatchType.cs
new file mode 100644
index 0000000000..96f606a5fd
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/QBEMatchType.cs
@@ -0,0 +1,44 @@
+// 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;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class QbeMatchType
+ {
+ private object _value;
+ private MatchType _matchType;
+
+ internal QbeMatchType(object value, MatchType matchType)
+ {
+ _value = value;
+ _matchType = matchType;
+ }
+
+ internal object Value
+ {
+ get
+ {
+ return _value;
+ }
+ set
+ {
+ _value = value;
+ }
+ }
+
+ internal MatchType Match
+ {
+ get
+ {
+ return _matchType;
+ }
+ set
+ {
+ _matchType = value;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/RangeRetriever.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/RangeRetriever.cs
new file mode 100644
index 0000000000..609f1a5e08
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/RangeRetriever.cs
@@ -0,0 +1,257 @@
+// 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.Collections;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ ///
+ /// <summary>
+ /// Retrieves all the values of the specified attribute using the supplied DirectoryEntry object.
+ /// This function would additionally dispose the supplied DirectoryEntry object in its Dispose() method
+ /// if disposeDirEntry parameter is set to true in its constructor.
+ /// </summary>
+ ///
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class RangeRetriever : CollectionBase, IEnumerable, IEnumerator, IDisposable
+ {
+ ///
+ /// <summary>
+ /// Creates a new RangeRetriever object.
+ /// </summary>
+ /// <param name="de">DirectoryEntry object whose attribute needs to be range retrieved</param>
+ /// <param name="propertyName">name of the attribute that needs to be range retrieved, ex: "memberOf"</param>
+ /// <param name="disposeDirEntry">
+ /// If set to true, the supplied DirectoryEntry will be diposed,
+ /// by this object's Dispose() method
+ /// </param>
+ ///
+ public RangeRetriever(DirectoryEntry de, string propertyName, bool disposeDirEntry)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "RangeRetriever: de.Path={0}, propertyName={1}", de.Path, propertyName);
+
+ _de = de;
+ _propertyName = propertyName;
+ _disposeDirEntry = disposeDirEntry;
+ }
+
+ new public IEnumerator GetEnumerator()
+ {
+ return this;
+ }
+
+ public void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "Reset");
+
+ _endReached = false;
+ _lowRange = 0;
+ _currentResult = null;
+ //this.currentEnumerator = null;
+ _currentIndex = 0;
+ }
+
+ public bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "Entering MoveNext");
+
+ if (_endReached)
+ return false;
+
+ // Determine if we have already visited the current object.
+ if (_currentIndex < InnerList.Count)
+ {
+ _currentResult = InnerList[_currentIndex];
+ _currentIndex++;
+ return true;
+ }
+ else if (_cacheFilled)
+ {
+ // We have just walked the entire cache. No need to visit the directory
+ // since we cached everything that is out there.
+ return false;
+ }
+
+ if (!_endReached && _currentEnumerator == null)
+ {
+ // First time we're being called
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "MoveNext: first time");
+
+ _currentEnumerator = GetNextChunk();
+
+ if (_currentEnumerator == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "MoveNext: got null enumerator for first time");
+ _endReached = true;
+ }
+ }
+
+ if (_endReached)
+ return false;
+
+ bool needToRetry;
+ bool f;
+
+ do
+ {
+ needToRetry = false;
+
+ f = _currentEnumerator.MoveNext();
+
+ if (f)
+ {
+ // Got a result, prepare to return it
+ _currentResult = _currentEnumerator.Current;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "MoveNext: got a result '{0}'", _currentResult.ToString());
+ }
+ else
+ {
+ // Ran out of results in this range, try the next chunk
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "MoveNext: retrieving next range");
+ _currentEnumerator = GetNextChunk();
+
+ if (_currentEnumerator == null)
+ {
+ // No more chunks remain
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "MoveNext: end reached");
+ _endReached = true;
+ _cacheFilled = _cacheValues; //Set cachedFilled boolean to cacheValues flags.
+ }
+ else
+ {
+ // Got the next chunk, try pulling a result out of it
+ needToRetry = true;
+ }
+ }
+ }
+ while (needToRetry);
+
+ if (f)
+ {
+ if (_cacheValues)
+ {
+ InnerList.Add(_currentResult);
+ }
+ _currentIndex++;
+ }
+
+ return f;
+ }
+
+ void IDisposable.Dispose()
+ {
+ if (!_disposed)
+ {
+ if (_disposeDirEntry)
+ {
+ _de.Dispose();
+ }
+ }
+ _disposed = true;
+ }
+
+ // returns null if no more results
+ private IEnumerator GetNextChunk()
+ {
+ string rangedAttribute = String.Format(
+ CultureInfo.InvariantCulture,
+ "{0};range={1}-*",
+ _propertyName,
+ _lowRange);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "GetNextChunk: rangedAttribute={0}", rangedAttribute);
+
+ try
+ {
+ // Pull in the next chunk of results
+ _de.RefreshCache(new string[] { rangedAttribute, _propertyName });
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072020))
+ {
+ // ran out of results to retrieve
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "GetNextChunk: no more results");
+ return null;
+ }
+
+ // unknown failure, don't want to suppress it
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "RangeRetriever", "GetNextChunk: caught COMException, ErrorCode={0}", e.ErrorCode);
+
+ throw;
+ }
+
+ PropertyValueCollection pvc = _de.Properties[_propertyName];
+
+ if (pvc == null || pvc.Count == 0)
+ {
+ // No results (the property may have been empty)
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "GetNextChunk: empty property?");
+ return null;
+ }
+ else
+ {
+ _lowRange = _lowRange + pvc.Count;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "RangeRetriever",
+ "GetNextChunk: new lowRange={0}",
+ _lowRange);
+
+ return pvc.GetEnumerator();
+ }
+ }
+
+ ///
+ /// <summary>
+ /// If set to true then the attribute values will be cached in the InnerList
+ /// </summary>
+ /// <remarks>
+ /// By default caching is turned off.
+ /// </remarks>
+ public bool CacheValues
+ {
+ set { _cacheValues = value; }
+ }
+
+ public object Current
+ {
+ get
+ {
+ // Technically, should throw an InvalidOperationException if the enumerator is positioned before
+ // the beginning or after the end, but this will only be used internally.
+ Debug.Assert(_currentResult != null && _endReached == false);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "RangeRetriever", "Current: currentResult={0}", _currentResult.ToString());
+ return _currentResult;
+ }
+ }
+
+ private bool _disposed = false; // keeps track of whether this object was disposed or not.
+ private bool _disposeDirEntry = false; // If set to true then the RangeRetriever object will own the directory entry
+ // supplied to it in the constructor and will be responsible for disposing this entry
+ // when Dispose() is called on this object.
+ private bool _cacheValues = false; // If set to true then the attribute values will be cached in the InnerList
+ // By default caching is turned off.
+ private DirectoryEntry _de; // the DirectoryEntry whose property we're retrieving the values of
+ private string _propertyName; // the property we're retrieving the values of
+
+ private bool _endReached = false; // if true, all property values (from all chunks) have been retrieved
+
+ private int _lowRange = 0; // the lower-bound of the current chunk
+ private int _currentIndex = 0; // Index of the next object we will return.
+ private bool _cacheFilled = false; // Set to true after we have visited all attributes in the directory
+
+ private object _currentResult = null; // the property value the enumerator is positioned at
+ private IEnumerator _currentEnumerator = null; // the PropertyValueCollection enumerator for the current chunk
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSCache.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSCache.cs
new file mode 100644
index 0000000000..3a0b25be97
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSCache.cs
@@ -0,0 +1,228 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Globalization;
+using System.DirectoryServices;
+using System.Net;
+using System.Threading;
+/// This is a class designed to cache DirectoryEntires instead of creating them every time.
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class SDSCache
+ {
+ public static SDSCache Domain
+ {
+ get
+ {
+ return SDSCache.s_domainCache;
+ }
+ }
+
+ public static SDSCache LocalMachine
+ {
+ get
+ {
+ return SDSCache.s_localMachineCache;
+ }
+ }
+
+ private static SDSCache s_domainCache = new SDSCache(false);
+ private static SDSCache s_localMachineCache = new SDSCache(true);
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_Disposed():System.Boolean" />
+ // <SatisfiesLinkDemand Name="PrincipalContext..ctor(System.DirectoryServices.AccountManagement.ContextType,System.String,System.String,System.DirectoryServices.AccountManagement.ContextOptions,System.String,System.String)" />
+ // <ReferencesCritical Name="Method: NetCred.get_Domain():System.String" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_Disposed():System.Boolean" Ring="1" />
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ [System.DirectoryServices.DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ public PrincipalContext GetContext(string name, NetCred credentials, ContextOptions contextOptions)
+ {
+ string contextName = name;
+ string userName = null;
+ bool explicitCreds = false;
+ if (credentials != null && credentials.UserName != null)
+ {
+ if (credentials.Domain != null)
+ userName = credentials.Domain + "\\" + credentials.UserName;
+ else
+ userName = credentials.UserName;
+
+ explicitCreds = true;
+ }
+ else
+ {
+ userName = Utils.GetNT4UserName();
+ }
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "SDSCache",
+ "GetContext: looking for context for server {0}, user {1}, explicitCreds={2}, options={3}",
+ name,
+ userName,
+ explicitCreds.ToString(),
+ contextOptions.ToString());
+
+ if (!_isSAM)
+ {
+ // Determine the domain DNS name
+
+ // DS_RETURN_DNS_NAME | DS_DIRECTORY_SERVICE_REQUIRED | DS_BACKGROUND_ONLY
+ int flags = unchecked((int)(0x40000000 | 0x00000010 | 0x00000100));
+ UnsafeNativeMethods.DomainControllerInfo info = Utils.GetDcName(null, contextName, null, flags);
+ contextName = info.DomainName;
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: final contextName is " + contextName);
+
+ ManualResetEvent contextReadyEvent = null;
+
+ while (true)
+ {
+ Hashtable credTable = null;
+ PrincipalContext ctx = null;
+
+ // Wait for the PrincipalContext to be ready
+ if (contextReadyEvent != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: waiting");
+
+ contextReadyEvent.WaitOne();
+ }
+
+ contextReadyEvent = null;
+
+ lock (_tableLock)
+ {
+ CredHolder credHolder = (CredHolder)_table[contextName];
+
+ if (credHolder != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: found a credHolder for " + contextName);
+
+ credTable = (explicitCreds ? credHolder.explicitCreds : credHolder.defaultCreds);
+ Debug.Assert(credTable != null);
+
+ object o = credTable[userName];
+
+ if (o is Placeholder)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: credHolder for " + contextName + " has a Placeholder");
+
+ // A PrincipalContext is currently being constructed by another thread.
+ // Wait for it.
+ contextReadyEvent = ((Placeholder)o).contextReadyEvent;
+ continue;
+ }
+
+ WeakReference refToContext = o as WeakReference;
+ if (refToContext != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: refToContext is non-null");
+
+ ctx = (PrincipalContext)refToContext.Target; // null if GC'ed
+
+ // If the PrincipalContext hasn't been GCed or disposed, use it.
+ // Otherwise, we'll need to create a new one
+ if (ctx != null && ctx.Disposed == false)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: using found refToContext");
+ return ctx;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: refToContext is GCed/disposed, removing");
+ credTable.Remove(userName);
+ }
+ }
+ }
+
+ // Either credHolder/credTable are null (no contexts exist for the contextName), or credHolder/credTable
+ // are non-null (contexts exist, but none for the userName). Either way, we need to create a PrincipalContext.
+
+ if (credHolder == null)
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "SDSCache",
+ "GetContext: null credHolder for " + contextName + ", explicitCreds=" + explicitCreds.ToString());
+
+ // No contexts exist for the contextName. Create a CredHolder for the contextName so we have a place
+ // to store the PrincipalContext we'll be creating.
+ credHolder = new CredHolder();
+ _table[contextName] = credHolder;
+
+ credTable = (explicitCreds ? credHolder.explicitCreds : credHolder.defaultCreds);
+ }
+
+ // Put a placeholder on the contextName/userName slot, so that other threads that come along after
+ // we release the tableLock know we're in the process of creating the needed PrincipalContext and will wait for us
+ credTable[userName] = new Placeholder();
+ }
+
+ // Now we just need to create a PrincipalContext for the contextName and credentials
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "SDSCache",
+ "GetContext: creating context, contextName=" + contextName + ", options=" + contextOptions.ToString());
+
+ ctx = new PrincipalContext(
+ (_isSAM ? ContextType.Machine : ContextType.Domain),
+ contextName,
+ null,
+ contextOptions,
+ (credentials != null ? credentials.UserName : null),
+ (credentials != null ? credentials.Password : null)
+ );
+
+ lock (_tableLock)
+ {
+ Placeholder placeHolder = (Placeholder)credTable[userName];
+
+ // Replace the placeholder with the newly-created PrincipalContext
+ credTable[userName] = new WeakReference(ctx);
+
+ // Signal waiting threads to continue. We do this after inserting the PrincipalContext
+ // into the table, so that the PrincipalContext is ready as soon as the other threads wake up.
+ // (Actually, the order probably doesn't matter, since even if we did it in the
+ // opposite order and the other thread woke up before we inserted the PrincipalContext, it would
+ // just block as soon as it tries to acquire the tableLock that we're currently holding.)
+ bool f = placeHolder.contextReadyEvent.Set();
+ Debug.Assert(f == true);
+ }
+
+ return ctx;
+ }
+ }
+
+ //
+ private SDSCache(bool isSAM)
+ {
+ _isSAM = isSAM;
+ }
+
+ private Hashtable _table = new Hashtable();
+ private object _tableLock = new object();
+ private bool _isSAM;
+
+ private class CredHolder
+ {
+ public Hashtable explicitCreds = new Hashtable();
+ public Hashtable defaultCreds = new Hashtable();
+ }
+
+ private class Placeholder
+ {
+ // initially non-signaled
+ public ManualResetEvent contextReadyEvent = new ManualResetEvent(false);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSUtils.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSUtils.cs
new file mode 100644
index 0000000000..144c7fdb53
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSUtils.cs
@@ -0,0 +1,957 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.DirectoryServices;
+using System.Text;
+using System.Net;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // [System.DirectoryServices.DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted=true)]
+ internal class SDSUtils
+ {
+ // To stop the compiler from autogenerating a constructor for this class
+ private SDSUtils() { }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <ReferencesCritical Name="Method: UserPrincipal.MakeUser(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.UserPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: ComputerPrincipal.MakeComputer(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.ComputerPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: GroupPrincipal.MakeGroup(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.GroupPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: AuthenticablePrincipal.MakeAuthenticablePrincipal(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.AuthenticablePrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <SatisfiesLinkDemand Name="UserPrincipal.MakeUser(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.UserPrincipal" />
+ // <SatisfiesLinkDemand Name="ComputerPrincipal.MakeComputer(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.ComputerPrincipal" />
+ // <SatisfiesLinkDemand Name="GroupPrincipal.MakeGroup(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.GroupPrincipal" />
+ // <SatisfiesLinkDemand Name="AuthenticablePrincipal.MakeAuthenticablePrincipal(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.AuthenticablePrincipal" />
+ // <SatisfiesLinkDemand Name="Principal.MakePrincipal(System.DirectoryServices.AccountManagement.PrincipalContext,System.Type):System.DirectoryServices.AccountManagement.Principal" />
+ // <SatisfiesLinkDemand Name="SearchResult.GetDirectoryEntry():System.DirectoryServices.DirectoryEntry" />
+ // <SatisfiesLinkDemand Name="Principal.set_UnderlyingObject(System.Object):System.Void" />
+ // <SatisfiesLinkDemand Name="Principal.set_UnderlyingSearchObject(System.Object):System.Void" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="Principal.get_UnderlyingObject():System.Object" />
+ // <ReferencesCritical Name="Method: IsOfObjectClass(SearchResult, String):Boolean" Ring="1" />
+ // <ReferencesCritical Name="Method: ADStoreCtx.InitializeNewDirectoryOptions(System.DirectoryServices.DirectoryEntry):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal Principal SearchResultToPrincipal(SearchResult sr, PrincipalContext owningContext, Type principalType)
+ {
+ Principal p;
+
+ // Construct a appropriate Principal object.
+ // Make* constructs a Principal that is marked persisted
+ // and not loaded (p.unpersisted = false, p.loaded = false).
+
+ // Since there should be no more multistore contexts, the owning context IS
+ // the specific context
+
+ // If we know the type we should just construct it ourselves so that we don't need to incur the costs of reflection.
+ // If this is an extension type then we must reflect teh constructor to create the object.
+
+ if (typeof(UserPrincipal) == principalType)
+ {
+ p = UserPrincipal.MakeUser(owningContext);
+ }
+ else if (typeof(ComputerPrincipal) == principalType)
+ {
+ p = ComputerPrincipal.MakeComputer(owningContext);
+ }
+ else if (typeof(GroupPrincipal) == principalType)
+ {
+ p = GroupPrincipal.MakeGroup(owningContext);
+ }
+ else if (null == principalType ||
+ typeof(AuthenticablePrincipal) == principalType ||
+ typeof(Principal) == principalType)
+ {
+ if (SDSUtils.IsOfObjectClass(sr, "computer"))
+ {
+ p = ComputerPrincipal.MakeComputer(owningContext);
+ }
+ else if (SDSUtils.IsOfObjectClass(sr, "user"))
+ {
+ p = UserPrincipal.MakeUser(owningContext);
+ }
+ else if (SDSUtils.IsOfObjectClass(sr, "group"))
+ {
+ p = GroupPrincipal.MakeGroup(owningContext);
+ }
+ else
+ {
+ p = AuthenticablePrincipal.MakeAuthenticablePrincipal(owningContext);
+ }
+ }
+ else
+ {
+ p = Principal.MakePrincipal(owningContext, principalType);
+ }
+
+ // The DirectoryEntry we're constructing the Principal from
+ // will serve as the underlying object for that Principal.
+ p.UnderlyingSearchObject = sr;
+
+ // It's up to our caller to assign an appropriate StoreKey.
+ // Caller must also populate the underlyingObject field if the P is to be used R/W
+ return p;
+ }
+ // Used to implement StoreCtx.GetAsPrincipal for AD and SAM
+ // <SecurityKernel Critical="True" Ring="0">
+ // <ReferencesCritical Name="Method: UserPrincipal.MakeUser(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.UserPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: ComputerPrincipal.MakeComputer(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.ComputerPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: GroupPrincipal.MakeGroup(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.GroupPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: AuthenticablePrincipal.MakeAuthenticablePrincipal(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.AuthenticablePrincipal" Ring="1" />
+ // <SatisfiesLinkDemand Name="UserPrincipal.MakeUser(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.UserPrincipal" />
+ // <SatisfiesLinkDemand Name="ComputerPrincipal.MakeComputer(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.ComputerPrincipal" />
+ // <SatisfiesLinkDemand Name="GroupPrincipal.MakeGroup(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.GroupPrincipal" />
+ // <SatisfiesLinkDemand Name="AuthenticablePrincipal.MakeAuthenticablePrincipal(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.AuthenticablePrincipal" />
+ // <SatisfiesLinkDemand Name="Principal.MakePrincipal(System.DirectoryServices.AccountManagement.PrincipalContext,System.Type):System.DirectoryServices.AccountManagement.Principal" />
+ // <SatisfiesLinkDemand Name="Principal.set_UnderlyingObject(System.Object):System.Void" />
+ // <ReferencesCritical Name="Method: IsOfObjectClass(DirectoryEntry, String):Boolean" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal Principal DirectoryEntryToPrincipal(DirectoryEntry de, PrincipalContext owningContext, Type principalType)
+ {
+ Principal p;
+
+ // Construct a appropriate Principal object.
+ // Make* constructs a Principal that is marked persisted
+ // and not loaded (p.unpersisted = false, p.loaded = false).
+
+ // Since there should be no more multistore contexts, the owning context IS
+ // the specific context
+
+ if (typeof(UserPrincipal) == principalType)
+ {
+ p = UserPrincipal.MakeUser(owningContext);
+ }
+ else if (typeof(ComputerPrincipal) == principalType)
+ {
+ p = ComputerPrincipal.MakeComputer(owningContext);
+ }
+ else if (typeof(GroupPrincipal) == principalType)
+ {
+ p = GroupPrincipal.MakeGroup(owningContext);
+ }
+ else if (null == principalType ||
+ typeof(AuthenticablePrincipal) == principalType ||
+ typeof(Principal) == principalType)
+ {
+ if (SDSUtils.IsOfObjectClass(de, "computer"))
+ {
+ p = ComputerPrincipal.MakeComputer(owningContext);
+ }
+ else if (SDSUtils.IsOfObjectClass(de, "user"))
+ {
+ p = UserPrincipal.MakeUser(owningContext);
+ }
+ else if (SDSUtils.IsOfObjectClass(de, "group"))
+ {
+ p = GroupPrincipal.MakeGroup(owningContext);
+ }
+ else
+ {
+ p = AuthenticablePrincipal.MakeAuthenticablePrincipal(owningContext);
+ }
+ }
+ else
+ {
+ p = Principal.MakePrincipal(owningContext, principalType);
+ }
+ // The DirectoryEntry we're constructing the Principal from
+ // will serve as the underlying object for that Principal.
+ p.UnderlyingObject = de;
+
+ // It's up to our caller to assign an appropriate StoreKey.
+
+ return p;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <ReferencesCritical Name="Method: ADUtils.IsOfObjectClass(System.DirectoryServices.SearchResult,System.String):System.Boolean" Ring="1" />
+ // <SatisfiesLinkDemand Name="SearchResult.get_Path():System.String" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ private static bool IsOfObjectClass(SearchResult sr, string className)
+ {
+ Debug.Assert(sr.Path.StartsWith("LDAP:", StringComparison.Ordinal) || sr.Path.StartsWith("GC:", StringComparison.Ordinal));
+ return ADUtils.IsOfObjectClass(sr, className);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <ReferencesCritical Name="Method: ADUtils.IsOfObjectClass(System.DirectoryServices.DirectoryEntry,System.String):System.Boolean" Ring="1" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Path():System.String" />
+ // <ReferencesCritical Name="Method: SAMUtils.IsOfObjectClass(System.DirectoryServices.DirectoryEntry,System.String):System.Boolean" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ private static bool IsOfObjectClass(DirectoryEntry de, string className)
+ {
+ if (de.Path.StartsWith("WinNT:", StringComparison.Ordinal))
+ {
+ return SAMUtils.IsOfObjectClass(de, className);
+ }
+ else
+ {
+ Debug.Assert(de.Path.StartsWith("LDAP:", StringComparison.Ordinal));
+ return ADUtils.IsOfObjectClass(de, className);
+ }
+ }
+ static internal AuthenticationTypes MapOptionsToAuthTypes(ContextOptions options)
+ {
+ AuthenticationTypes authTypes = AuthenticationTypes.Secure;
+
+ if ((options & ContextOptions.SimpleBind) != 0)
+ authTypes = AuthenticationTypes.None;
+
+ if ((options & ContextOptions.ServerBind) != 0)
+ authTypes |= AuthenticationTypes.ServerBind;
+
+ if ((options & ContextOptions.SecureSocketLayer) != 0)
+ authTypes |= AuthenticationTypes.SecureSocketsLayer;
+
+ if ((options & ContextOptions.Signing) != 0)
+ authTypes |= AuthenticationTypes.Signing;
+
+ if ((options & ContextOptions.Sealing) != 0)
+ authTypes |= AuthenticationTypes.Sealing;
+
+ return authTypes;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="DirectoryEntry.MoveTo(System.DirectoryServices.DirectoryEntry,System.String):System.Void" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.MoveTo(System.DirectoryServices.DirectoryEntry):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void MoveDirectoryEntry(DirectoryEntry deToMove, DirectoryEntry newParent, string newName)
+ {
+ if (newName != null)
+ deToMove.MoveTo(newParent, newName);
+ else
+ deToMove.MoveTo(newParent);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Parent():System.DirectoryServices.DirectoryEntry" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Children():System.DirectoryServices.DirectoryEntries" />
+ // <SatisfiesLinkDemand Name="DirectoryEntries.Remove(System.DirectoryServices.DirectoryEntry):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void DeleteDirectoryEntry(DirectoryEntry deToDelete)
+ {
+ DirectoryEntry deParent = deToDelete.Parent;
+
+ try
+ {
+ deParent.Children.Remove(deToDelete);
+ }
+ finally
+ {
+ deParent.Dispose();
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetChangeStatusForProperty(System.String):System.Boolean" />
+ // <SatisfiesLinkDemand Name="Principal.GetValueForProperty(System.String):System.Object" />
+ // <ReferencesCritical Name="Method: ApplyChangesToDirectory(Principal, StoreCtx, GroupMembershipUpdater, NetCred, AuthenticationTypes):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void InsertPrincipal(
+ Principal p,
+ StoreCtx storeCtx,
+ GroupMembershipUpdater updateGroupMembership,
+ NetCred credentials,
+ AuthenticationTypes authTypes,
+ bool needToSetPassword)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "Entering InsertPrincipal");
+
+ Debug.Assert(storeCtx != null);
+ Debug.Assert(storeCtx is ADStoreCtx || storeCtx is SAMStoreCtx);
+ Debug.Assert(p != null);
+
+ if ((!(p is UserPrincipal)) &&
+ (!(p is GroupPrincipal)) &&
+ (!(p is AuthenticablePrincipal)) &&
+ (!(p is ComputerPrincipal)))
+ {
+ // It's not a type of Principal that we support
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SDSUtils", "InsertPrincipal: Bad principal type:" + p.GetType().ToString());
+
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForSave, p.GetType().ToString()));
+ }
+
+ // Commit the properties
+ SDSUtils.ApplyChangesToDirectory(
+ p,
+ storeCtx,
+ updateGroupMembership,
+ credentials,
+ authTypes
+ );
+
+ // Handle any saved-off operations
+
+ // For SAM, we set password elsewhere prior to creating the principal, so needToSetPassword == false
+ // For AD, we have to set the password after creating the principal, so needToSetPassword == true
+ if (needToSetPassword && p.GetChangeStatusForProperty(PropertyNames.PwdInfoPassword))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "InsertPrincipal: Setting password");
+
+ // Only AuthenticablePrincipals can have PasswordInfo
+ Debug.Assert(p is AuthenticablePrincipal);
+
+ string password = (string)p.GetValueForProperty(PropertyNames.PwdInfoPassword);
+ Debug.Assert(password != null); // if null, PasswordInfo should not have indicated it was changed
+
+ storeCtx.SetPassword((AuthenticablePrincipal)p, password);
+ }
+
+ if (p.GetChangeStatusForProperty(PropertyNames.PwdInfoExpireImmediately))
+ {
+ // Only AuthenticablePrincipals can have PasswordInfo
+ Debug.Assert(p is AuthenticablePrincipal);
+
+ bool expireImmediately = (bool)p.GetValueForProperty(PropertyNames.PwdInfoExpireImmediately);
+
+ if (expireImmediately)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "InsertPrincipal: Setting pwd expired");
+
+ storeCtx.ExpirePassword((AuthenticablePrincipal)p);
+ }
+ }
+ }
+
+ internal delegate void GroupMembershipUpdater(Principal p, DirectoryEntry de, NetCred credentials, AuthenticationTypes authTypes);
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.get_UnderlyingObject():System.Object" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.CommitChanges():System.Void" />
+ // <SatisfiesLinkDemand Name="Principal.GetChangeStatusForProperty(System.String):System.Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void ApplyChangesToDirectory(
+ Principal p,
+ StoreCtx storeCtx,
+ GroupMembershipUpdater updateGroupMembership,
+ NetCred credentials,
+ AuthenticationTypes authTypes)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "Entering ApplyChangesToDirectory");
+ Debug.Assert(storeCtx != null);
+ Debug.Assert(storeCtx is ADStoreCtx || storeCtx is SAMStoreCtx || storeCtx is ADAMStoreCtx);
+ Debug.Assert(p != null);
+ Debug.Assert(updateGroupMembership != null);
+
+ // Update the properties in the DirectoryEntry. Note that this does NOT
+ // update group membership.
+ DirectoryEntry de = (DirectoryEntry)storeCtx.PushChangesToNative(p);
+ Debug.Assert(de == p.UnderlyingObject);
+
+ // Commit the property update
+ try
+ {
+ de.CommitChanges();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "SDSUtils", "ApplyChangesToDirectory: caught COMException with message " + e.Message);
+
+ throw (ExceptionHelper.GetExceptionFromCOMException(e));
+ }
+
+ if ((p is GroupPrincipal) && (p.GetChangeStatusForProperty(PropertyNames.GroupMembers)))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "ApplyChangesToDirectory: Updating group membership");
+
+ // It's a group, and it's membership has changed. Commit those membership changes.
+ // Note that this is an immediate operation, because it goes through IADsGroup,
+ // and does not require a call to de.CommitChanges().
+ updateGroupMembership(p, de, credentials, authTypes);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="DirectoryEntry.Invoke(System.String,System.Object[]):System.Object" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void SetPassword(DirectoryEntry de, string newPassword)
+ {
+ Debug.Assert(newPassword != null); // but it could be an empty string
+ Debug.Assert(de != null);
+
+ try
+ {
+ de.Invoke("SetPassword", new object[] { newPassword });
+ }
+ catch (System.Reflection.TargetInvocationException e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "SDSUtils", "SetPassword: caught TargetInvocationException with message " + e.Message);
+
+ if (e.InnerException is System.Runtime.InteropServices.COMException)
+ {
+ if (((System.Runtime.InteropServices.COMException)e.InnerException).ErrorCode == unchecked((int)ExceptionHelper.ERROR_HRESULT_CONSTRAINT_VIOLATION))
+ {
+ // We have a special case of constraint violation here. We know this is a password failure to convert to this
+ // specialized type instead of the generic InvalidOperationException
+ throw (new PasswordException(((System.Runtime.InteropServices.COMException)e.InnerException).Message, (System.Runtime.InteropServices.COMException)e.InnerException));
+ }
+ else
+ {
+ throw (ExceptionHelper.GetExceptionFromCOMException((System.Runtime.InteropServices.COMException)e.InnerException));
+ }
+ }
+
+ // Unknown exception. We don't want to suppress it.
+ throw;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="DirectoryEntry.Invoke(System.String,System.Object[]):System.Object" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void ChangePassword(DirectoryEntry de, string oldPassword, string newPassword)
+ {
+ Debug.Assert(newPassword != null); // but it could be an empty string
+ Debug.Assert(oldPassword != null); // but it could be an empty string
+
+ Debug.Assert(de != null);
+
+ try
+ {
+ de.Invoke("ChangePassword", new object[] { oldPassword, newPassword });
+ }
+ catch (System.Reflection.TargetInvocationException e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "SDSUtils", "ChangePassword: caught TargetInvocationException with message " + e.Message);
+
+ if (e.InnerException is System.Runtime.InteropServices.COMException)
+ {
+ if (((System.Runtime.InteropServices.COMException)e.InnerException).ErrorCode == unchecked((int)ExceptionHelper.ERROR_HRESULT_CONSTRAINT_VIOLATION))
+ {
+ // We have a special case of constraint violation here. We know this is a password failure to convert to this
+ // specialized type instead of the generic InvalidOperationException
+ throw (new PasswordException(((System.Runtime.InteropServices.COMException)e.InnerException).Message, (System.Runtime.InteropServices.COMException)e.InnerException));
+ }
+ else
+ {
+ throw (ExceptionHelper.GetExceptionFromCOMException((System.Runtime.InteropServices.COMException)e.InnerException));
+ }
+ }
+
+ // Unknown exception. We don't want to suppress it.
+ throw;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="DirectoryEntry..ctor(System.String,System.String,System.String,System.DirectoryServices.AuthenticationTypes)" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Path():System.String" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal DirectoryEntry BuildDirectoryEntry(string path, NetCred credentials, AuthenticationTypes authTypes)
+ {
+ DirectoryEntry de = new DirectoryEntry(path,
+ credentials != null ? credentials.UserName : null,
+ credentials != null ? credentials.Password : null,
+ authTypes);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "BuildDirectoryEntry (1): built DE for " + de.Path);
+
+ return de;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="DirectoryEntry..ctor()" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.set_Username(System.String):System.Void" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.set_Password(System.String):System.Void" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.set_AuthenticationType(System.DirectoryServices.AuthenticationTypes):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal DirectoryEntry BuildDirectoryEntry(NetCred credentials, AuthenticationTypes authTypes)
+ {
+ DirectoryEntry de = new DirectoryEntry();
+
+ de.Username = credentials != null ? credentials.UserName : null;
+ de.Password = credentials != null ? credentials.Password : null;
+ de.AuthenticationType = authTypes;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "BuildDirectoryEntry (2): built DE");
+
+ return de;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="DirectoryEntry.RefreshCache(System.String[]):System.Void" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Properties():System.DirectoryServices.PropertyCollection" />
+ // <SatisfiesLinkDemand Name="PropertyCollection.get_Item(System.String):System.DirectoryServices.PropertyValueCollection" />
+ // <SatisfiesLinkDemand Name="PropertyValueCollection.set_Value(System.Object):System.Void" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.CommitChanges():System.Void" />
+ // <ReferencesCritical Name="Method: BuildDirectoryEntry(String, NetCred, AuthenticationTypes):DirectoryEntry" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void WriteAttribute<T>(string dePath, string attribute, T value, NetCred credentials, AuthenticationTypes authTypes)
+ {
+ Debug.Assert(attribute != null && attribute.Length > 0);
+
+ // Ideally, we'd just like to set the property in the principal's DirectoryEntry and write
+ // the changes to the store. However, there might be other changes in the DirectoryEntry,
+ // and we don't want to write all of them to the store. So we must make
+ // a fresh DirectoryEntry and write using that.
+
+ DirectoryEntry copyOfDe = null;
+
+ try
+ {
+ copyOfDe = SDSUtils.BuildDirectoryEntry(dePath, credentials, authTypes);
+
+ Debug.Assert(copyOfDe != null);
+
+ // So we don't do a implicit GetInfo() and retrieve every attribute
+ copyOfDe.RefreshCache(new string[] { attribute });
+
+ copyOfDe.Properties[attribute].Value = value;
+ copyOfDe.CommitChanges();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ // ADSI threw an exception trying to write the change
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ if (copyOfDe != null)
+ copyOfDe.Dispose();
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="DirectoryEntry.RefreshCache(System.String[]):System.Void" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Properties():System.DirectoryServices.PropertyCollection" />
+ // <SatisfiesLinkDemand Name="PropertyCollection.get_Item(System.String):System.DirectoryServices.PropertyValueCollection" />
+ // <SatisfiesLinkDemand Name="PropertyValueCollection.set_Value(System.Object):System.Void" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.CommitChanges():System.Void" />
+ // <ReferencesCritical Name="Method: BuildDirectoryEntry(String, NetCred, AuthenticationTypes):DirectoryEntry" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void WriteAttribute(string dePath, string attribute, int value, NetCred credentials, AuthenticationTypes authTypes)
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "SDSUtils",
+ "WriteAttribute: writing {0} to {1} on {2}",
+ value.ToString(CultureInfo.InvariantCulture),
+ attribute,
+ dePath);
+
+ Debug.Assert(attribute != null && attribute.Length > 0);
+
+ // Ideally, we'd just like to set the property in the principal's DirectoryEntry and write
+ // the changes to the store. However, there might be other changes in the DirectoryEntry,
+ // and we don't want to write all of them to the store. So we must make
+ // a fresh DirectoryEntry and write using that.
+
+ DirectoryEntry copyOfDe = null;
+
+ try
+ {
+ copyOfDe = SDSUtils.BuildDirectoryEntry(dePath, credentials, authTypes);
+
+ Debug.Assert(copyOfDe != null);
+
+ // So we don't do a implicit GetInfo() and retrieve every attribute
+ copyOfDe.RefreshCache(new string[] { attribute });
+
+ copyOfDe.Properties[attribute].Value = value;
+ copyOfDe.CommitChanges();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Error,
+ "SDSUtils",
+ "WriteAttribute: caught exception with message '{0}' writing {1} to {2} on {3}",
+ e.Message,
+ value.ToString(CultureInfo.InvariantCulture),
+ attribute,
+ dePath);
+
+ // ADSI threw an exception trying to write the change
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ if (copyOfDe != null)
+ copyOfDe.Dispose();
+ }
+ }
+
+ //
+ // S.DS (LDAP or WinNT) --> PAPI conversion routines
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.LoadValueIntoProperty(System.String,System.Object):System.Void" />
+ // <ReferencesCritical Name="Method: dSPropertyCollection.get_Item(System.String):System.DirectoryServices.AccountManagement.dSPropertyValueCollection" Ring="1" />
+ // <ReferencesCritical Name="Method: dSPropertyValueCollection.get_Item(System.Int32):System.Object" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void SingleScalarFromDirectoryEntry<T>(dSPropertyCollection properties, string suggestedProperty, Principal p, string propertyName)
+ {
+ if (properties[suggestedProperty].Count != 0 && properties[suggestedProperty][0] != null)
+ {
+ // We're intended to handle single-valued scalar properties
+ Debug.Assert(properties[suggestedProperty].Count == 1);
+ Debug.Assert(properties[suggestedProperty][0] is T);
+
+ p.LoadValueIntoProperty(propertyName, (T)properties[suggestedProperty][0]);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.LoadValueIntoProperty(System.String,System.Object):System.Void" />
+ // <ReferencesCritical Name="Method: dSPropertyCollection.get_Item(System.String):System.DirectoryServices.AccountManagement.dSPropertyValueCollection" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void MultiScalarFromDirectoryEntry<T>(dSPropertyCollection properties, string suggestedProperty, Principal p, string propertyName)
+ {
+ dSPropertyValueCollection values = properties[suggestedProperty];
+
+ List<T> list = new List<T>();
+
+ foreach (object value in values)
+ {
+ Debug.Assert(value is T);
+
+ list.Add((T)value);
+ }
+
+ p.LoadValueIntoProperty(propertyName, list);
+ }
+
+ static internal bool StatusFromAccountControl(int uacValue, string propertyName)
+ {
+ bool flag = false;
+
+ switch (propertyName)
+ {
+ case PropertyNames.AuthenticablePrincipalEnabled:
+ // UF_ACCOUNTDISABLE
+ // Note that the logic is inverted on this one. We expose "Enabled",
+ // but AD/SAM store it as "Disabled".
+ flag = ((uacValue & 0x2) == 0);
+ break;
+
+ case PropertyNames.AcctInfoSmartcardRequired:
+ // UF_SMARTCARD_REQUIRED
+ flag = ((uacValue & 0x40000) != 0);
+ break;
+
+ case PropertyNames.AcctInfoDelegationPermitted:
+ // UF_NOT_DELEGATED
+ // Note that the logic is inverted on this one. That's because we expose
+ // "delegation allowed", but AD represents it as the inverse, "delegation NOT allowed"
+ flag = ((uacValue & 0x100000) == 0);
+ break;
+
+ case PropertyNames.PwdInfoPasswordNotRequired:
+ // UF_PASSWD_NOTREQD
+ flag = ((uacValue & 0x0020) != 0);
+ break;
+
+ case PropertyNames.PwdInfoPasswordNeverExpires:
+ // UF_DONT_EXPIRE_PASSWD
+ flag = ((uacValue & 0x10000) != 0);
+ break;
+
+ // This bit doesn't work in userAccountControl
+ case PropertyNames.PwdInfoCannotChangePassword:
+ // UF_PASSWD_CANT_CHANGE
+ flag = ((uacValue & 0x0040) != 0);
+ break;
+
+ case PropertyNames.PwdInfoAllowReversiblePasswordEncryption:
+ // UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
+ flag = ((uacValue & 0x0080) != 0);
+ break;
+
+ default:
+ Debug.Fail("SDSUtils.AccountControlFromDirectoryEntry: Fell off end looking for " + propertyName);
+ flag = false;
+ break;
+ }
+
+ return flag;
+ }
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.LoadValueIntoProperty(System.String,System.Object):System.Void" />
+ // <ReferencesCritical Name="Method: dSPropertyCollection.get_Item(System.String):System.DirectoryServices.AccountManagement.dSPropertyValueCollection" Ring="1" />
+ // <ReferencesCritical Name="Method: dSPropertyValueCollection.get_Item(System.Int32):System.Object" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void AccountControlFromDirectoryEntry(dSPropertyCollection properties, string suggestedProperty, Principal p, string propertyName, bool testCantChangePassword)
+ {
+ Debug.Assert(
+ (!testCantChangePassword && (String.Compare(suggestedProperty, "userAccountControl", StringComparison.OrdinalIgnoreCase) == 0)) ||
+ (testCantChangePassword && (String.Compare(suggestedProperty, "UserFlags", StringComparison.OrdinalIgnoreCase) == 0))
+ );
+
+ Debug.Assert((String.Compare(propertyName, PropertyNames.PwdInfoCannotChangePassword, StringComparison.OrdinalIgnoreCase) != 0) || testCantChangePassword);
+
+ dSPropertyValueCollection values = properties[suggestedProperty];
+
+ if (values.Count != 0)
+ {
+ Debug.Assert(values.Count == 1);
+ Debug.Assert(values[0] is int);
+
+ int uacValue = (int)values[0];
+ bool flag;
+
+ flag = StatusFromAccountControl(uacValue, propertyName);
+
+ p.LoadValueIntoProperty(propertyName, flag);
+ }
+ }
+
+ //
+ // PAPI --> S.DS (LDAP or WinNT) conversion routines
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetValueForProperty(System.String):System.Object" />
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<System.String>.get_Inserted():System.Collections.Generic.List`1<System.String>" />
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<System.String>.get_Removed():System.Collections.Generic.List`1<System.String>" />
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<System.String>.get_ChangedValues():System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Pair`2<System.String,System.String>>" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Properties():System.DirectoryServices.PropertyCollection" />
+ // <SatisfiesLinkDemand Name="PropertyCollection.get_Item(System.String):System.DirectoryServices.PropertyValueCollection" />
+ // <SatisfiesLinkDemand Name="PropertyValueCollection.Contains(System.Object):System.Boolean" />
+ // <SatisfiesLinkDemand Name="PropertyValueCollection.Remove(System.Object):System.Void" />
+ // <SatisfiesLinkDemand Name="PropertyValueCollection.Add(System.Object):System.Int32" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void MultiStringToDirectoryEntryConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedProperty)
+ {
+ PrincipalValueCollection<string> trackingList = (PrincipalValueCollection<string>)p.GetValueForProperty(propertyName);
+
+ if (p.unpersisted && trackingList == null)
+ return;
+
+ List<string> insertedValues = trackingList.Inserted;
+ List<string> removedValues = trackingList.Removed;
+ List<Pair<string, string>> changedValues = trackingList.ChangedValues;
+
+ PropertyValueCollection properties = de.Properties[suggestedProperty];
+
+ // We test to make sure the change hasn't already been applied to the PropertyValueCollection,
+ // because PushChangesToNative can be called multiple times prior to committing the changes and
+ // we want to maintain idempotency
+ foreach (string value in removedValues)
+ {
+ if (value != null && properties.Contains(value))
+ properties.Remove(value);
+ }
+
+ foreach (Pair<string, string> changedValue in changedValues)
+ {
+ // Remove the original value and add in the new value
+ Debug.Assert(changedValue.Left != null); // since it came from the system
+ properties.Remove(changedValue.Left);
+
+ if (changedValue.Right != null && !properties.Contains(changedValue.Right))
+ properties.Add(changedValue.Right);
+ }
+
+ foreach (string value in insertedValues)
+ {
+ if (value != null && !properties.Contains(value))
+ properties.Add(value);
+ }
+ }
+
+ internal const int AD_DefaultUAC = (int)(0x200 | 0X20 | 0x2); // UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE
+ internal const int AD_DefaultUAC_Machine = (int)(0x1000 | 0X20 | 0x2); // UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE
+ internal const int SAM_DefaultUAC = (int)(0x200 | 0x1); // UF_NORMAL_ACCOUNT | UF_SCRIPT
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetValueForProperty(System.String):System.Object" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Properties():System.DirectoryServices.PropertyCollection" />
+ // <SatisfiesLinkDemand Name="PropertyCollection.get_Item(System.String):System.DirectoryServices.PropertyValueCollection" />
+ // <SatisfiesLinkDemand Name="PropertyValueCollection.get_Item(System.Int32):System.Object" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Path():System.String" />
+ // <SatisfiesLinkDemand Name="PropertyValueCollection.set_Value(System.Object):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static internal void AccountControlToDirectoryEntry(
+ Principal p,
+ string propertyName,
+ DirectoryEntry de,
+ string suggestedProperty,
+ bool isSAM,
+ bool isUnpersisted)
+ {
+ Debug.Assert(
+ (!isSAM && (String.Compare(suggestedProperty, "userAccountControl", StringComparison.OrdinalIgnoreCase) == 0)) ||
+ (isSAM && (String.Compare(suggestedProperty, "UserFlags", StringComparison.OrdinalIgnoreCase) == 0))
+ );
+
+ bool flag = (bool)p.GetValueForProperty(propertyName);
+
+ int uacValue = 0;
+
+ // We want to get the current value, so we can flip the appropriate bit while leaving the other bits as-is.
+ // If this is a to-be-inserted Principal, we should have already initialized the userAccountControl property
+ if (de.Properties[suggestedProperty].Count > 0)
+ {
+ Debug.Assert(de.Properties[suggestedProperty].Count == 1);
+
+ uacValue = (int)de.Properties[suggestedProperty][0];
+
+ // When we write to userAccountControl, we must OR the new value with the value of msDS-User-Account-Control-Computed.
+ // Otherwise we might mistakenly clear computed bits like UF_LOCKOUT.
+ if (!isSAM && de.Properties["msDS-User-Account-Control-Computed"].Count > 0)
+ {
+ Debug.Assert(de.Properties["msDS-User-Account-Control-Computed"].Count == 1);
+ uacValue = uacValue | (int)de.Properties["msDS-User-Account-Control-Computed"][0];
+ }
+ }
+ else
+ {
+ // We don't have the userAccountControl property, this must be a persisted principal. Perhaps we don't have access
+ // to it. In that case, we don't want to blindly overwrite whatever other bits might be there.
+ Debug.Assert(p.unpersisted == false);
+ throw new PrincipalOperationException(
+ StringResources.ADStoreCtxUnableToReadExistingAccountControlFlagsForUpdate);
+ }
+
+ uint bitmask;
+
+ // Get the right bitmask for the property
+ switch (propertyName)
+ {
+ case PropertyNames.AuthenticablePrincipalEnabled:
+ if (!isUnpersisted || isSAM)
+ {
+ // UF_ACCOUNTDISABLE
+ // Note that the logic is inverted on this one. We expose "Enabled",
+ // but AD/SAM store it as "Disabled".
+ bitmask = 0x2;
+ flag = !flag;
+ }
+ else
+ {
+ // We're writing to an unpersisted AD principal
+ Debug.Assert(!isSAM && isUnpersisted);
+
+ // Nothing to do here. The ADStoreCtx will take care of enabling the
+ // principal after it's persisted.
+ bitmask = 0;
+ }
+ break;
+
+ case PropertyNames.AcctInfoSmartcardRequired:
+ // UF_SMARTCARD_REQUIRED
+ bitmask = 0x40000;
+ break;
+
+ case PropertyNames.AcctInfoDelegationPermitted:
+ // UF_NOT_DELEGATED
+ // Note that the logic is inverted on this one. That's because we expose
+ // "delegation allowed", but AD represents it as the inverse, "delegation NOT allowed"
+ bitmask = 0x100000;
+ flag = !flag;
+ break;
+
+ case PropertyNames.PwdInfoPasswordNotRequired:
+ // UF_PASSWD_NOTREQD
+ bitmask = 0x0020;
+ break;
+
+ case PropertyNames.PwdInfoPasswordNeverExpires:
+ // UF_DONT_EXPIRE_PASSWD
+ bitmask = 0x10000;
+ break;
+
+ case PropertyNames.PwdInfoAllowReversiblePasswordEncryption:
+ // UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
+ bitmask = 0x0080;
+ break;
+
+ // This bit doesn't work in userAccountControl
+ case PropertyNames.PwdInfoCannotChangePassword:
+ if (isSAM)
+ {
+ // UF_PASSWD_CANT_CHANGE
+ bitmask = 0x0040;
+ break;
+ }
+ else
+ {
+ Debug.Fail(
+ "SDSUtils.AccountControlToDirectoryEntry: At PwdInfoCannotChangePassword but isSAM==false, path=" + de.Path
+ );
+
+ goto default;
+ }
+
+ default:
+ Debug.Fail("SDSUtils.AccountControlToDirectoryEntry: Fell off end looking for " + propertyName);
+ bitmask = 0;
+ break;
+ }
+
+ // Set/clear the "bitmask" bit in "uacValue", based on the value of "flag"
+ if (flag)
+ Utils.SetBit(ref uacValue, bitmask);
+ else
+ Utils.ClearBit(ref uacValue, bitmask);
+
+ de.Properties[suggestedProperty].Value = uacValue;
+ }
+
+ static internal DirectorySearcher ConstructSearcher(DirectoryEntry de)
+ {
+ DirectorySearcher ds = new DirectorySearcher(de);
+ ds.ClientTimeout = new TimeSpan(0, 0, 30);
+ ds.PageSize = 256;
+ return ds;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ static internal bool IsObjectFromGC(string path)
+ {
+ return path.StartsWith("GC:", StringComparison.OrdinalIgnoreCase);
+ }
+
+ static internal string ConstructDnsDomainNameFromDn(string dn)
+ {
+ // Split the DN into its RDNs
+ string[] ncComponents = dn.Split(new char[] { ',' });
+
+ StringBuilder sb = new StringBuilder();
+
+ // Reassemble the RDNs (minus the tag) into the DNS domain name
+ foreach (string component in ncComponents)
+ {
+ if ((component.Length > 3) &&
+ (String.Compare(component.Substring(0, 3), "DC=", StringComparison.OrdinalIgnoreCase) == 0))
+ {
+ sb.Append(component.Substring(3));
+ sb.Append(".");
+ }
+ }
+
+ if (sb.Length > 0)
+ sb.Remove(sb.Length - 1, 1);
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SidList.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SidList.cs
new file mode 100644
index 0000000000..d7ab36a7c3
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SidList.cs
@@ -0,0 +1,339 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.DirectoryServices;
+using System.Text;
+using System.Net;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [System.DirectoryServices.DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+
+ internal class SidList
+ {
+ internal SidList(List<Byte[]> sidListByteFormat) : this(sidListByteFormat, null, null)
+ {
+ }
+
+ internal SidList(List<Byte[]> sidListByteFormat, string target, NetCred credentials)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SidList", "SidList: processing {0} ByteFormat SIDs", sidListByteFormat.Count);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SidList", "SidList: Targetting {0} ", (target != null) ? target : "local store");
+
+ // Build the list of SIDs to resolve
+ IntPtr hUser = IntPtr.Zero;
+
+ int sidCount = sidListByteFormat.Count;
+ IntPtr[] pSids = new IntPtr[sidCount];
+
+ for (int i = 0; i < sidCount; i++)
+ {
+ pSids[i] = Utils.ConvertByteArrayToIntPtr(sidListByteFormat[i]);
+ }
+
+ try
+ {
+ if (credentials != null)
+ {
+ Utils.BeginImpersonation(credentials, out hUser);
+ }
+
+ TranslateSids(target, pSids);
+ }
+ finally
+ {
+ if (hUser != IntPtr.Zero)
+ Utils.EndImpersonation(hUser);
+ }
+ }
+
+ internal SidList(UnsafeNativeMethods.SID_AND_ATTR[] sidAndAttr)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SidList", "SidList: processing {0} Sid+Attr SIDs", sidAndAttr.Length);
+
+ // Build the list of SIDs to resolve
+ int sidCount = sidAndAttr.Length;
+ IntPtr[] pSids = new IntPtr[sidCount];
+
+ for (int i = 0; i < sidCount; i++)
+ {
+ pSids[i] = sidAndAttr[i].pSid;
+ }
+
+ TranslateSids(null, pSids);
+ }
+
+ protected void TranslateSids(string target, IntPtr[] pSids)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "SidList: processing {0} SIDs", pSids.Length);
+
+ // if there are no SIDs to translate return
+ if (pSids.Length == 0)
+ {
+ return;
+ }
+
+ // Build the list of SIDs to resolve
+ int sidCount = pSids.Length;
+
+ // Translate the SIDs in bulk
+ IntPtr pOA = IntPtr.Zero;
+ IntPtr pPolicyHandle = IntPtr.Zero;
+
+ IntPtr pDomains = IntPtr.Zero;
+ UnsafeNativeMethods.LSA_TRUST_INFORMATION[] domains;
+
+ IntPtr pNames = IntPtr.Zero;
+ UnsafeNativeMethods.LSA_TRANSLATED_NAME[] names;
+
+ try
+ {
+ //
+ // Get the policy handle
+ //
+ UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES oa = new UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES();
+
+ pOA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES)));
+ Marshal.StructureToPtr(oa, pOA, false);
+
+ int err = 0;
+ if (target == null)
+ {
+ err = UnsafeNativeMethods.LsaOpenPolicy(
+ IntPtr.Zero,
+ pOA,
+ 0x800, // POLICY_LOOKUP_NAMES
+ ref pPolicyHandle);
+ }
+ else
+ {
+ // Build an entry. Note that LSA_UNICODE_STRING.length is in bytes,
+ // while PtrToStringUni expects a length in characters.
+ UnsafeNativeMethods.LSA_UNICODE_STRING_Managed lsaTargetString = new UnsafeNativeMethods.LSA_UNICODE_STRING_Managed();
+ lsaTargetString.buffer = target;
+ lsaTargetString.length = (ushort)(target.Length * 2);
+ lsaTargetString.maximumLength = lsaTargetString.length;
+
+ IntPtr lsaTargetPr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_UNICODE_STRING)));
+
+ try
+ {
+ Marshal.StructureToPtr(lsaTargetString, lsaTargetPr, false);
+
+ err = UnsafeNativeMethods.LsaOpenPolicy(
+ lsaTargetPr,
+ pOA,
+ 0x800, // POLICY_LOOKUP_NAMES
+ ref pPolicyHandle);
+ }
+ finally
+ {
+ if (lsaTargetPr != IntPtr.Zero)
+ {
+ UnsafeNativeMethods.LSA_UNICODE_STRING lsaTargetUnmanagedPtr =
+ (UnsafeNativeMethods.LSA_UNICODE_STRING)Marshal.PtrToStructure(lsaTargetPr, typeof(UnsafeNativeMethods.LSA_UNICODE_STRING));
+ if (lsaTargetUnmanagedPtr.buffer != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(lsaTargetUnmanagedPtr.buffer);
+ lsaTargetUnmanagedPtr.buffer = IntPtr.Zero;
+ }
+ Marshal.FreeHGlobal(lsaTargetPr);
+ }
+ }
+ }
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "SidList: couldn't get policy handle, err={0}", err);
+
+ throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
+ StringResources.AuthZErrorEnumeratingGroups,
+ SafeNativeMethods.LsaNtStatusToWinError(err)));
+ }
+
+ Debug.Assert(pPolicyHandle != IntPtr.Zero);
+
+ //
+ // Translate the SIDs
+ //
+
+ err = UnsafeNativeMethods.LsaLookupSids(
+ pPolicyHandle,
+ sidCount,
+ pSids,
+ out pDomains,
+ out pNames);
+
+ // ignore error STATUS_SOME_NOT_MAPPED = 0x00000107 and
+ // STATUS_NONE_MAPPED = 0xC0000073
+ if (err != 0 &&
+ err != 263 &&
+ err != -1073741709)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "SidList: LsaLookupSids failed, err={0}", err);
+
+ throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
+ StringResources.AuthZErrorEnumeratingGroups,
+ SafeNativeMethods.LsaNtStatusToWinError(err)));
+ }
+
+ //
+ // Get the group names in managed form
+ //
+ names = new UnsafeNativeMethods.LSA_TRANSLATED_NAME[sidCount];
+ IntPtr pCurrentName = pNames;
+
+ for (int i = 0; i < sidCount; i++)
+ {
+ names[i] = (UnsafeNativeMethods.LSA_TRANSLATED_NAME)
+ Marshal.PtrToStructure(pCurrentName, typeof(UnsafeNativeMethods.LSA_TRANSLATED_NAME));
+
+ pCurrentName = new IntPtr(pCurrentName.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_TRANSLATED_NAME)));
+ }
+
+ //
+ // Get the domain names in managed form
+ //
+
+ // Extract LSA_REFERENCED_DOMAIN_LIST.Entries
+
+ UnsafeNativeMethods.LSA_REFERENCED_DOMAIN_LIST referencedDomains = (UnsafeNativeMethods.LSA_REFERENCED_DOMAIN_LIST)Marshal.PtrToStructure(pDomains, typeof(UnsafeNativeMethods.LSA_REFERENCED_DOMAIN_LIST));
+
+ int domainCount = referencedDomains.entries;
+
+ // Extract LSA_REFERENCED_DOMAIN_LIST.Domains, by iterating over the array and marshalling
+ // each native LSA_TRUST_INFORMATION into a managed LSA_TRUST_INFORMATION.
+
+ domains = new UnsafeNativeMethods.LSA_TRUST_INFORMATION[domainCount];
+
+ IntPtr pCurrentDomain = referencedDomains.domains;
+
+ for (int i = 0; i < domainCount; i++)
+ {
+ domains[i] = (UnsafeNativeMethods.LSA_TRUST_INFORMATION)Marshal.PtrToStructure(pCurrentDomain, typeof(UnsafeNativeMethods.LSA_TRUST_INFORMATION));
+ pCurrentDomain = new IntPtr(pCurrentDomain.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_TRUST_INFORMATION)));
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "SidList: got {0} groups in {1} domains", sidCount, domainCount);
+
+ //
+ // Build the list of entries
+ //
+ Debug.Assert(names.Length == sidCount);
+
+ for (int i = 0; i < names.Length; i++)
+ {
+ UnsafeNativeMethods.LSA_TRANSLATED_NAME name = names[i];
+
+ // Build an entry. Note that LSA_UNICODE_STRING.length is in bytes,
+ // while PtrToStringUni expects a length in characters.
+ SidListEntry entry = new SidListEntry();
+
+ Debug.Assert(name.name.length % 2 == 0);
+ entry.name = Marshal.PtrToStringUni(name.name.buffer, name.name.length / 2);
+
+ // Get the domain associated with this name
+ Debug.Assert(name.domainIndex < domains.Length);
+ if (name.domainIndex >= 0)
+ {
+ UnsafeNativeMethods.LSA_TRUST_INFORMATION domain = domains[name.domainIndex];
+ Debug.Assert(domain.name.length % 2 == 0);
+ entry.sidIssuerName = Marshal.PtrToStringUni(domain.name.buffer, domain.name.length / 2);
+ }
+
+ entry.pSid = pSids[i];
+
+ _entries.Add(entry);
+ }
+
+ // Sort the list so they are oriented by the issuer name.
+ // this.entries.Sort( new SidListComparer());
+ }
+ finally
+ {
+ if (pDomains != IntPtr.Zero)
+ UnsafeNativeMethods.LsaFreeMemory(pDomains);
+
+ if (pNames != IntPtr.Zero)
+ UnsafeNativeMethods.LsaFreeMemory(pNames);
+
+ if (pPolicyHandle != IntPtr.Zero)
+ UnsafeNativeMethods.LsaClose(pPolicyHandle);
+
+ if (pOA != IntPtr.Zero)
+ Marshal.FreeHGlobal(pOA);
+ }
+ }
+
+ private List<SidListEntry> _entries = new List<SidListEntry>();
+
+ public SidListEntry this[int index]
+ {
+ get { return _entries[index]; }
+ }
+
+ public int Length
+ {
+ get { return _entries.Count; }
+ }
+
+ public void RemoveAt(int index)
+ {
+ _entries[index].Dispose();
+ _entries.RemoveAt(index);
+ }
+
+ public void Clear()
+ {
+ foreach (SidListEntry sl in _entries)
+ sl.Dispose();
+
+ _entries.Clear();
+ }
+ }
+
+ /******
+ class SidListComparer : IComparer<SidListEntry>
+ {
+ public int Compare(SidListEntry entry1, SidListEntry entry2)
+ {
+ return ( string.Compare( entry1.sidIssuerName, entry2.sidIssuerName, true, CultureInfo.InvariantCulture));
+ }
+
+ }
+ ********/
+ internal class SidListEntry : IDisposable
+ {
+ public IntPtr pSid = IntPtr.Zero;
+ public string name;
+ public string sidIssuerName;
+ //
+ // IDisposable
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public virtual void Dispose()
+ {
+ if (pSid != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(pSid);
+ pSid = IntPtr.Zero;
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/TokenGroupsSet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/TokenGroupsSet.cs
new file mode 100644
index 0000000000..a60bf18a06
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/TokenGroupsSet.cs
@@ -0,0 +1,168 @@
+// 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;
+using System.Collections.Generic;
+using System.Collections;
+using System.Diagnostics;
+using System.Text;
+using System.Security.Principal;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class TokenGroupSet : ResultSet
+ {
+ internal TokenGroupSet(
+ string userDN,
+ ADStoreCtx storeCtx,
+ bool readDomainGroups)
+ {
+ _principalDN = userDN;
+ _storeCtx = storeCtx;
+ _attributeToQuery = readDomainGroups ? "tokenGroups" : "tokenGroupsGlobalAndUniversal";
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "TokenGroupSet",
+ "TokenGroupSet: userDN={0}",
+ userDN);
+ }
+
+ private string _principalDN;
+ private ADStoreCtx _storeCtx;
+
+ private bool _atBeginning = true;
+ private DirectoryEntry _current = null; // current member of the group (or current group of the user)
+
+ private IEnumerator _tokenGroupsEnum;
+
+ private SecurityIdentifier _currentSID;
+ private bool _disposed = false;
+
+ private string _attributeToQuery;
+
+ // Return the principal we're positioned at as a Principal object.
+ // Need to use our StoreCtx's GetAsPrincipal to convert the native object to a Principal
+ override internal object CurrentAsPrincipal
+ {
+ get
+ {
+ if (_currentSID != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TokenGroupSet", "CurrentAsPrincipal: using current");
+
+ StringBuilder SidBindingString = new StringBuilder();
+
+ SidBindingString.Append("<SID=");
+ SidBindingString.Append(Utils.SecurityIdentifierToLdapHexBindingString(_currentSID));
+ SidBindingString.Append(">");
+
+ DirectoryEntry currentDE = SDSUtils.BuildDirectoryEntry(
+ BuildPathFromDN(SidBindingString.ToString()),
+ _storeCtx.Credentials,
+ _storeCtx.AuthTypes);
+
+ _storeCtx.InitializeNewDirectoryOptions(currentDE);
+ _storeCtx.LoadDirectoryEntryAttributes(currentDE);
+
+ return ADUtils.DirectoryEntryAsPrincipal(currentDE, _storeCtx);
+ }
+
+ return null;
+ }
+ }
+
+ // Advance the enumerator to the next principal in the result set, pulling in additional pages
+ // of results (or ranges of attribute values) as needed.
+ // Returns true if successful, false if no more results to return.
+ override internal bool MoveNext()
+ {
+ if (_atBeginning)
+ {
+ Debug.Assert(_principalDN != null);
+
+ _current = SDSUtils.BuildDirectoryEntry(
+ BuildPathFromDN(_principalDN),
+ _storeCtx.Credentials,
+ _storeCtx.AuthTypes);
+
+ _current.RefreshCache(new string[] { _attributeToQuery });
+
+ _tokenGroupsEnum = _current.Properties[_attributeToQuery].GetEnumerator();
+
+ _atBeginning = false;
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TokenGroupSet", "MoveNextLocal: returning primary group {0}", _current.Path);
+
+ if (_tokenGroupsEnum.MoveNext())
+ {
+ // Got a member from this group (or, got a group of which we're a member).
+ // Create a DirectoryEntry for it.
+
+ byte[] sid = (byte[])_tokenGroupsEnum.Current;
+ _currentSID = new SecurityIdentifier(sid, 0);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TokenGroupSet", "MoveNextLocal: got a value from the enumerator: {0}", _currentSID.ToString());
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // Resets the enumerator to before the first result in the set. This potentially can be an expensive
+ // operation, e.g., if doing a paged search, may need to re-retrieve the first page of results.
+ // As a special case, if the ResultSet is already at the very beginning, this is guaranteed to be
+ // a no-op.
+ override internal void Reset()
+ {
+ if (_atBeginning)
+ return;
+
+ _tokenGroupsEnum.Reset();
+ }
+
+ // IDisposable implementation
+ public override void Dispose()
+ {
+ try
+ {
+ if (!_disposed)
+ {
+ if (_current != null)
+ _current.Dispose();
+
+ _disposed = true;
+ }
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+
+ private string BuildPathFromDN(string dn)
+ {
+ string userSuppliedServername = _storeCtx.UserSuppliedServerName;
+
+ UnsafeNativeMethods.Pathname pathCracker = new UnsafeNativeMethods.Pathname();
+ UnsafeNativeMethods.IADsPathname pathName = (UnsafeNativeMethods.IADsPathname)pathCracker;
+ pathName.EscapedMode = 2 /* ADS_ESCAPEDMODE_ON */;
+ pathName.Set(dn, 4 /* ADS_SETTYPE_DN */);
+ string escapedDn = pathName.Retrieve(7 /* ADS_FORMAT_X500_DN */);
+
+ if (userSuppliedServername.Length > 0)
+ return "LDAP://" + _storeCtx.UserSuppliedServerName + "/" + escapedDn;
+ else
+ return "LDAP://" + escapedDn;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AccountInfo.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AccountInfo.cs
new file mode 100644
index 0000000000..4f30235748
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AccountInfo.cs
@@ -0,0 +1,620 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+#if TESTHOOK
+ public class AccountInfo
+#else
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ internal class AccountInfo
+#endif
+ {
+ //
+ // Properties exposed to the public through AuthenticablePrincipal
+ //
+
+ // AccountLockoutTime
+ private Nullable<DateTime> _accountLockoutTime = null;
+ private LoadState _accountLockoutTimeLoaded = LoadState.NotSet;
+
+ public Nullable<DateTime> AccountLockoutTime
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Nullable`1<System.DateTime>>(System.Nullable`1<System.DateTime>&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Nullable`1<System.DateTime>" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<Nullable<DateTime>>(ref _accountLockoutTime, PropertyNames.AcctInfoAcctLockoutTime, ref _accountLockoutTimeLoaded);
+ }
+ }
+
+ // LastLogon
+ private Nullable<DateTime> _lastLogon = null;
+ private LoadState _lastLogonLoaded = LoadState.NotSet;
+
+ public Nullable<DateTime> LastLogon
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Nullable`1<System.DateTime>>(System.Nullable`1<System.DateTime>&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Nullable`1<System.DateTime>" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<Nullable<DateTime>>(ref _lastLogon, PropertyNames.AcctInfoLastLogon, ref _lastLogonLoaded);
+ }
+ }
+
+ // PermittedWorkstations
+ private PrincipalValueCollection<string> _permittedWorkstations = new PrincipalValueCollection<string>();
+ private LoadState _permittedWorkstationsLoaded = LoadState.NotSet;
+
+ public PrincipalValueCollection<string> PermittedWorkstations
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.DirectoryServices.AccountManagement.PrincipalValueCollection`1<System.String>>(System.DirectoryServices.AccountManagement.PrincipalValueCollection`1<System.String>&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.DirectoryServices.AccountManagement.PrincipalValueCollection`1<System.String>" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ if (!_owningPrincipal.GetStoreCtxToUse().IsValidProperty(_owningPrincipal, PropertyNames.AcctInfoPermittedWorkstations))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ return _owningPrincipal.HandleGet<PrincipalValueCollection<string>>(ref _permittedWorkstations, PropertyNames.AcctInfoPermittedWorkstations, ref _permittedWorkstationsLoaded);
+ }
+ }
+
+ // PermittedLogonTimes
+ // We have to handle the change-tracking for this differently than for the other properties, because
+ // a byte[] is mutable. After calling the get accessor, the app can change the permittedLogonTimes,
+ // without needing to ever call the set accessor. Therefore, rather than a simple "changed" flag set
+ // by the set accessor, we need to track the original value of the property, and flag it as changed
+ // if current value != original value.
+ private byte[] _permittedLogonTimes = null;
+ private byte[] _permittedLogonTimesOriginal = null;
+ private LoadState _permittedLogonTimesLoaded = LoadState.NotSet;
+
+ public byte[] PermittedLogonTimes
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Byte[]>(System.Byte[]&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Byte[]" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<byte[]>(ref _permittedLogonTimes, PropertyNames.AcctInfoPermittedLogonTimes, ref _permittedLogonTimesLoaded);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ // We don't use HandleSet<T> here because of the slightly non-standard implementation of the change-tracking
+ // for this property.
+
+ // Check that we actually support this propery in our store
+ //this.owningPrincipal.CheckSupportedProperty(PropertyNames.AcctInfoPermittedLogonTimes);
+
+ if (!_owningPrincipal.GetStoreCtxToUse().IsValidProperty(_owningPrincipal, PropertyNames.AcctInfoPermittedLogonTimes))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ // If we get to this point we know that the value of the property has changed and we should not load it from the store.
+ // If value is retrived the state is set to loaded. Even if user modifies the reference we will
+ // not overwrite it because we mark it as loaded.
+ // If the user sets it before reading it we mark it as changed. When the users accesses it we just return the current
+ // value. All change tracking to the store is done off of an actual object comparison because users can change the value
+ // either through property set or modifying the reference returned.
+ _permittedLogonTimesLoaded = LoadState.Changed;
+
+ _permittedLogonTimes = value;
+ }
+ }
+
+ // AccountExpirationDate
+ private Nullable<DateTime> _expirationDate = null;
+ private LoadState _expirationDateChanged = LoadState.NotSet;
+
+ public Nullable<DateTime> AccountExpirationDate
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Nullable`1<System.DateTime>>(System.Nullable`1<System.DateTime>&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Nullable`1<System.DateTime>" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<Nullable<DateTime>>(ref _expirationDate, PropertyNames.AcctInfoExpirationDate, ref _expirationDateChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.Nullable`1<System.DateTime>>(System.Nullable`1<System.DateTime>&,System.Nullable`1<System.DateTime>,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (!_owningPrincipal.GetStoreCtxToUse().IsValidProperty(_owningPrincipal, PropertyNames.AcctInfoExpirationDate))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ _owningPrincipal.HandleSet<Nullable<DateTime>>(ref _expirationDate, value, ref _expirationDateChanged,
+ PropertyNames.AcctInfoExpirationDate);
+ }
+ }
+
+ // SmartcardLogonRequired
+ private bool _smartcardLogonRequired = false;
+ private LoadState _smartcardLogonRequiredChanged = LoadState.NotSet;
+
+ public bool SmartcardLogonRequired
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Boolean>(System.Boolean&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Boolean" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<bool>(ref _smartcardLogonRequired, PropertyNames.AcctInfoSmartcardRequired, ref _smartcardLogonRequiredChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.Boolean>(System.Boolean&,System.Boolean,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (!_owningPrincipal.GetStoreCtxToUse().IsValidProperty(_owningPrincipal, PropertyNames.AcctInfoSmartcardRequired))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ _owningPrincipal.HandleSet<bool>(ref _smartcardLogonRequired, value, ref _smartcardLogonRequiredChanged,
+ PropertyNames.AcctInfoSmartcardRequired);
+ }
+ }
+
+ // DelegationPermitted
+ private bool _delegationPermitted = false;
+ private LoadState _delegationPermittedChanged = LoadState.NotSet;
+
+ public bool DelegationPermitted
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Boolean>(System.Boolean&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Boolean" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<bool>(ref _delegationPermitted, PropertyNames.AcctInfoDelegationPermitted, ref _delegationPermittedChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.Boolean>(System.Boolean&,System.Boolean,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (!_owningPrincipal.GetStoreCtxToUse().IsValidProperty(_owningPrincipal, PropertyNames.AcctInfoDelegationPermitted))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ _owningPrincipal.HandleSet<bool>(ref _delegationPermitted, value, ref _delegationPermittedChanged,
+ PropertyNames.AcctInfoDelegationPermitted);
+ }
+ }
+
+ // BadLogonCount
+ private int _badLogonCount = 0;
+ private LoadState _badLogonCountChanged = LoadState.NotSet;
+
+ public int BadLogonCount
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Int32>(System.Int32&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Int32" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<int>(ref _badLogonCount, PropertyNames.AcctInfoBadLogonCount, ref _badLogonCountChanged);
+ }
+ }
+
+ // HomeDirectory
+ private string _homeDirectory = null;
+ private LoadState _homeDirectoryChanged = LoadState.NotSet;
+
+ public string HomeDirectory
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.String>(System.String&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.String" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<string>(ref _homeDirectory, PropertyNames.AcctInfoHomeDirectory, ref _homeDirectoryChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.String>(System.String&,System.String,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (!_owningPrincipal.GetStoreCtxToUse().IsValidProperty(_owningPrincipal, PropertyNames.AcctInfoHomeDirectory))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ _owningPrincipal.HandleSet<string>(ref _homeDirectory, value, ref _homeDirectoryChanged,
+ PropertyNames.AcctInfoHomeDirectory);
+ }
+ }
+
+ // HomeDrive
+ private string _homeDrive = null;
+ private LoadState _homeDriveChanged = LoadState.NotSet;
+
+ public string HomeDrive
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.String>(System.String&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.String" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<string>(ref _homeDrive, PropertyNames.AcctInfoHomeDrive, ref _homeDriveChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.String>(System.String&,System.String,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (!_owningPrincipal.GetStoreCtxToUse().IsValidProperty(_owningPrincipal, PropertyNames.AcctInfoHomeDrive))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ _owningPrincipal.HandleSet<string>(ref _homeDrive, value, ref _homeDriveChanged,
+ PropertyNames.AcctInfoHomeDrive);
+ }
+ }
+
+ // ScriptPath
+ private string _scriptPath = null;
+ private LoadState _scriptPathChanged = LoadState.NotSet;
+
+ public string ScriptPath
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.String>(System.String&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.String" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<string>(ref _scriptPath, PropertyNames.AcctInfoScriptPath, ref _scriptPathChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.String>(System.String&,System.String,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (!_owningPrincipal.GetStoreCtxToUse().IsValidProperty(_owningPrincipal, PropertyNames.AcctInfoScriptPath))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ _owningPrincipal.HandleSet<string>(ref _scriptPath, value, ref _scriptPathChanged,
+ PropertyNames.AcctInfoScriptPath);
+ }
+ }
+
+ //
+ // Methods exposed to the public through AuthenticablePrincipal
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.get_Context():System.DirectoryServices.AccountManagement.PrincipalContext" />
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool IsAccountLockedOut()
+ {
+ if (!_owningPrincipal.unpersisted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AccountInfo", "IsAccountLockedOut: sending lockout query");
+
+ Debug.Assert(_owningPrincipal.Context != null);
+
+ return _owningPrincipal.GetStoreCtxToUse().IsLockedOut(_owningPrincipal);
+ }
+ else
+ {
+ // A Principal that hasn't even been persisted can't be locked out
+ return false;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.get_Context():System.DirectoryServices.AccountManagement.PrincipalContext" />
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void UnlockAccount()
+ {
+ if (!_owningPrincipal.unpersisted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AccountInfo", "UnlockAccount: sending unlock request");
+
+ Debug.Assert(_owningPrincipal.Context != null);
+
+ _owningPrincipal.GetStoreCtxToUse().UnlockAccount(_owningPrincipal);
+ }
+
+ // Since a Principal that's not persisted can't have been locked-out,
+ // there's nothing to do in that case
+ }
+
+ //
+ // Internal constructor
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<System.String>..ctor()" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal AccountInfo(AuthenticablePrincipal principal)
+ {
+ _owningPrincipal = principal;
+ }
+
+ //
+ // Private implementation
+ //
+ private AuthenticablePrincipal _owningPrincipal;
+
+ //
+ // Load/Store
+ //
+
+ //
+ // Loading with query results
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<System.String>.Load(System.Collections.Generic.List`1<System.String>):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal void LoadValueIntoProperty(string propertyName, object value)
+ {
+ // GlobalDebug.WriteLineIf(GlobalDebug.Info, "AccountInfo", "LoadValueIntoProperty: name=" + propertyName + " value=" + value.ToString());
+
+ switch (propertyName)
+ {
+ case (PropertyNames.AcctInfoAcctLockoutTime):
+ _accountLockoutTime = (Nullable<DateTime>)value;
+ _accountLockoutTimeLoaded = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoLastLogon):
+ _lastLogon = (Nullable<DateTime>)value;
+ _lastLogonLoaded = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoPermittedWorkstations):
+ _permittedWorkstations.Load((List<string>)value);
+ _permittedWorkstationsLoaded = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoPermittedLogonTimes):
+ _permittedLogonTimes = (byte[])value;
+ _permittedLogonTimesOriginal = (byte[])((byte[])value).Clone();
+ _permittedLogonTimesLoaded = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoExpirationDate):
+ _expirationDate = (Nullable<DateTime>)value;
+ _expirationDateChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoSmartcardRequired):
+ _smartcardLogonRequired = (bool)value;
+ _smartcardLogonRequiredChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoDelegationPermitted):
+ _delegationPermitted = (bool)value;
+ _delegationPermittedChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoBadLogonCount):
+ _badLogonCount = (int)value;
+ _badLogonCountChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoHomeDirectory):
+ _homeDirectory = (string)value;
+ _homeDirectoryChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoHomeDrive):
+ _homeDrive = (string)value;
+ _homeDriveChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.AcctInfoScriptPath):
+ _scriptPath = (string)value;
+ _scriptPathChanged = LoadState.Loaded;
+ break;
+
+ default:
+ Debug.Fail(String.Format(CultureInfo.CurrentCulture, "AccountInfo.LoadValueIntoProperty: fell off end looking for {0}", propertyName));
+ break;
+ }
+ }
+
+ //
+ // Getting changes to persist (or to build a query from a QBE filter)
+ //
+
+ // Given a property name, returns true if that property has changed since it was loaded, false otherwise.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<System.String>.get_Changed():System.Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal bool GetChangeStatusForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AccountInfo", "GetChangeStatusForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case (PropertyNames.AcctInfoPermittedWorkstations):
+ return _permittedWorkstations.Changed;
+
+ case (PropertyNames.AcctInfoPermittedLogonTimes):
+ // If they're equal, they have _not_ changed
+ if ((_permittedLogonTimes == null) && (_permittedLogonTimesOriginal == null))
+ return false;
+
+ if ((_permittedLogonTimes == null) || (_permittedLogonTimesOriginal == null))
+ return true;
+
+ return !Utils.AreBytesEqual(_permittedLogonTimes, _permittedLogonTimesOriginal);
+
+ case (PropertyNames.AcctInfoExpirationDate):
+ return _expirationDateChanged == LoadState.Changed;
+
+ case (PropertyNames.AcctInfoSmartcardRequired):
+ return _smartcardLogonRequiredChanged == LoadState.Changed;
+
+ case (PropertyNames.AcctInfoDelegationPermitted):
+ return _delegationPermittedChanged == LoadState.Changed;
+
+ case (PropertyNames.AcctInfoHomeDirectory):
+ return _homeDirectoryChanged == LoadState.Changed;
+
+ case (PropertyNames.AcctInfoHomeDrive):
+ return _homeDriveChanged == LoadState.Changed;
+
+ case (PropertyNames.AcctInfoScriptPath):
+ return _scriptPathChanged == LoadState.Changed;
+
+ default:
+ Debug.Fail(String.Format(CultureInfo.CurrentCulture, "AccountInfo.GetChangeStatusForProperty: fell off end looking for {0}", propertyName));
+ return false;
+ }
+ }
+
+ // Given a property name, returns the current value for the property.
+ internal object GetValueForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AccountInfo", "GetValueForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case (PropertyNames.AcctInfoPermittedWorkstations):
+ return _permittedWorkstations;
+
+ case (PropertyNames.AcctInfoPermittedLogonTimes):
+ return _permittedLogonTimes;
+
+ case (PropertyNames.AcctInfoExpirationDate):
+ return _expirationDate;
+
+ case (PropertyNames.AcctInfoSmartcardRequired):
+ return _smartcardLogonRequired;
+
+ case (PropertyNames.AcctInfoDelegationPermitted):
+ return _delegationPermitted;
+
+ case (PropertyNames.AcctInfoHomeDirectory):
+ return _homeDirectory;
+
+ case (PropertyNames.AcctInfoHomeDrive):
+ return _homeDrive;
+
+ case (PropertyNames.AcctInfoScriptPath):
+ return _scriptPath;
+
+ default:
+ Debug.Fail(String.Format(CultureInfo.CurrentCulture, "AccountInfo.GetValueForProperty: fell off end looking for {0}", propertyName));
+ return null;
+ }
+ }
+
+ // Reset all change-tracking status for all properties on the object to "unchanged".
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<System.String>.ResetTracking():System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal void ResetAllChangeStatus()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AccountInfo", "ResetAllChangeStatus");
+
+ _permittedWorkstations.ResetTracking();
+
+ _permittedLogonTimesOriginal = (_permittedLogonTimes != null) ?
+ (byte[])_permittedLogonTimes.Clone() :
+ null;
+ _expirationDateChanged = (_expirationDateChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _smartcardLogonRequiredChanged = (_smartcardLogonRequiredChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _delegationPermittedChanged = (_delegationPermittedChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _homeDirectoryChanged = (_homeDirectoryChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _homeDriveChanged = (_homeDriveChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _scriptPathChanged = (_scriptPathChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AdvancedFilters.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AdvancedFilters.cs
new file mode 100644
index 0000000000..567498f3e3
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AdvancedFilters.cs
@@ -0,0 +1,256 @@
+// 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.Diagnostics;
+using System.Globalization;
+using System.Security.Principal;
+using System.Security.Permissions;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Collections;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ public class AdvancedFilters
+ {
+ internal protected AdvancedFilters(Principal p)
+ {
+ _p = p;
+ }
+
+ private bool _badPasswordAttemptChanged = false;
+ private QbeMatchType _badPasswordAttemptVal = null;
+ private Principal _p;
+
+ public void LastBadPasswordAttempt(DateTime lastAttempt, MatchType match)
+ {
+ if (lastAttempt == null)
+ {
+ _expirationTimeChanged = false;
+ _expirationTimeVal = null;
+ }
+ else
+ {
+ if (null == _badPasswordAttemptVal)
+ _badPasswordAttemptVal = new QbeMatchType(lastAttempt, match);
+ else
+ {
+ _badPasswordAttemptVal.Match = match;
+ _badPasswordAttemptVal.Value = lastAttempt;
+ }
+ _badPasswordAttemptChanged = true;
+ }
+ }
+
+ private bool _expirationTimeChanged = false;
+ private QbeMatchType _expirationTimeVal = null;
+
+ public void AccountExpirationDate(DateTime expirationTime, MatchType match)
+ {
+ if (expirationTime == null)
+ {
+ _expirationTimeChanged = false;
+ _expirationTimeVal = null;
+ }
+ else
+ {
+ if (null == _expirationTimeVal)
+ _expirationTimeVal = new QbeMatchType(expirationTime, match);
+ else
+ {
+ _expirationTimeVal.Match = match;
+ _expirationTimeVal.Value = expirationTime;
+ }
+ _expirationTimeChanged = true;
+ }
+ }
+
+ private bool _lockoutTimeChanged = false;
+ private QbeMatchType _lockoutTimeVal = null;
+
+ public void AccountLockoutTime(DateTime lockoutTime, MatchType match)
+ {
+ if (lockoutTime == null)
+ {
+ _lockoutTimeChanged = false;
+ _lockoutTimeVal = null;
+ }
+ else
+ {
+ if (null == _lockoutTimeVal)
+ _lockoutTimeVal = new QbeMatchType(lockoutTime, match);
+ else
+ {
+ _lockoutTimeVal.Match = match;
+ _lockoutTimeVal.Value = lockoutTime;
+ }
+ _lockoutTimeChanged = true;
+ }
+ }
+
+ private bool _badLogonCountChanged = false;
+ private QbeMatchType _badLogonCountVal = null;
+
+ public void BadLogonCount(int badLogonCount, MatchType match)
+ {
+ if (null == _badLogonCountVal)
+ {
+ _badLogonCountVal = new QbeMatchType(badLogonCount, match);
+ }
+ else
+ {
+ _badLogonCountVal.Match = match;
+ _badLogonCountVal.Value = badLogonCount;
+ }
+ _badLogonCountChanged = true;
+ }
+
+ private bool _logonTimeChanged = false;
+ private QbeMatchType _logonTimeVal = null;
+
+ public void LastLogonTime(DateTime logonTime, MatchType match)
+ {
+ if (logonTime == null)
+ {
+ _logonTimeChanged = false;
+ _logonTimeVal = null;
+ }
+ else
+ {
+ if (null == _logonTimeVal)
+ _logonTimeVal = new QbeMatchType(logonTime, match);
+ else
+ {
+ _logonTimeVal.Match = match;
+ _logonTimeVal.Value = logonTime;
+ }
+ _logonTimeChanged = true;
+ }
+ }
+
+ private bool _passwordSetTimeChanged = false;
+ private QbeMatchType _passwordSetTimeVal = null;
+
+ public void LastPasswordSetTime(DateTime passwordSetTime, MatchType match)
+ {
+ if (passwordSetTime == null)
+ {
+ _passwordSetTimeChanged = false;
+ _passwordSetTimeVal = null;
+ }
+ else
+ {
+ if (null == _passwordSetTimeVal)
+ _passwordSetTimeVal = new QbeMatchType(passwordSetTime, match);
+ else
+ {
+ _passwordSetTimeVal.Match = match;
+ _passwordSetTimeVal.Value = passwordSetTime;
+ }
+ _passwordSetTimeChanged = true;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.AdvancedFilterSet(System.String,System.Object,System.Type,System.DirectoryServices.AccountManagement.MatchType):System.Void" />
+ // <ReferencesCritical Name="Method: Principal.AdvancedFilterSet(System.String,System.Object,System.Type,System.DirectoryServices.AccountManagement.MatchType):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ protected void AdvancedFilterSet(string attribute, object value, Type objectType, MatchType mt)
+ {
+ _p.AdvancedFilterSet(attribute, value, objectType, mt);
+ }
+
+ //
+ // Getting changes to persist (or to build a query from a QBE filter)
+ //
+
+ internal bool? GetChangeStatusForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AdvancedFilters", "GetChangeStatusForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case PropertyNames.PwdInfoLastBadPasswordAttempt:
+ return _badPasswordAttemptChanged;
+
+ case PropertyNames.AcctInfoExpiredAccount:
+ return _expirationTimeChanged;
+
+ case PropertyNames.AcctInfoBadLogonCount:
+ return _badLogonCountChanged;
+
+ case PropertyNames.AcctInfoLastLogon:
+ return _logonTimeChanged;
+
+ case PropertyNames.AcctInfoAcctLockoutTime:
+ return _lockoutTimeChanged;
+
+ case PropertyNames.PwdInfoLastPasswordSet:
+ return _passwordSetTimeChanged;
+
+ default:
+ return null;
+ }
+ }
+
+ // Given a property name, returns the current value for the property.
+ // Generally, this method is called only if GetChangeStatusForProperty indicates there are changes on the
+ // property specified.
+ //
+ // If the property is a scalar property, the return value is an object of the property type.
+ // If the property is an IdentityClaimCollection property, the return value is the IdentityClaimCollection
+ // itself.
+ // If the property is a ValueCollection<T>, the return value is the ValueCollection<T> itself.
+ // If the property is a X509Certificate2Collection, the return value is the X509Certificate2Collection itself.
+ // If the property is a PrincipalCollection, the return value is the PrincipalCollection itself.
+ //[StrongNameIdentityPermission(SecurityAction.InheritanceDemand, PublicKey = Microsoft.Internal.BuildInfo.WINDOWS_PUBLIC_KEY_STRING)]
+ internal object GetValueForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AdvancedFilters", "GetValueForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case PropertyNames.PwdInfoLastBadPasswordAttempt:
+ return _badPasswordAttemptVal;
+
+ case PropertyNames.AcctInfoExpiredAccount:
+ return _expirationTimeVal;
+
+ case PropertyNames.AcctInfoBadLogonCount:
+ return _badLogonCountVal;
+
+ case PropertyNames.AcctInfoLastLogon:
+ return _logonTimeVal;
+
+ case PropertyNames.AcctInfoAcctLockoutTime:
+ return _lockoutTimeVal;
+
+ case PropertyNames.PwdInfoLastPasswordSet:
+ return _passwordSetTimeVal;
+
+ default:
+ return null;
+ }
+ }
+
+ // Reset all change-tracking status for all properties on the object to "unchanged".
+ // This is used by StoreCtx.Insert() and StoreCtx.Update() to reset the change-tracking after they
+ // have persisted all current changes to the store.
+ //[StrongNameIdentityPermission(SecurityAction.InheritanceDemand, PublicKey = Microsoft.Internal.BuildInfo.WINDOWS_PUBLIC_KEY_STRING)]
+ internal virtual void ResetAllChangeStatus()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "ResetAllChangeStatus");
+
+ _badPasswordAttemptChanged = false;
+ _expirationTimeChanged = false;
+ _logonTimeChanged = false;
+ _lockoutTimeChanged = false;
+ _passwordSetTimeChanged = false;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AuthZSet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AuthZSet.cs
new file mode 100644
index 0000000000..3b834fb00b
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AuthZSet.cs
@@ -0,0 +1,848 @@
+// 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.Collections.Generic;
+using System.Collections;
+using System.Diagnostics;
+using System.Globalization;
+using System.Security.Principal;
+
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class AuthZSet : ResultSet
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_ContextType():System.DirectoryServices.AccountManagement.ContextType" />
+ // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
+ // <SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
+ // <SatisfiesLinkDemand Name="Marshal.AllocHGlobal(System.Int32):System.IntPtr" />
+ // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ // <SatisfiesLinkDemand Name="Marshal.SizeOf(System.Type):System.Int32" />
+ // <SatisfiesLinkDemand Name="SafeHandle.Close():System.Void" />
+ // <SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.AuthzInitializeResourceManager(System.Int32,System.IntPtr,System.IntPtr,System.IntPtr,System.String,System.IntPtr&):System.Boolean" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.AuthzInitializeContextFromSid(System.Int32,System.IntPtr,System.IntPtr,System.IntPtr,System.DirectoryServices.AccountManagement.UnsafeNativeMethods+LUID,System.IntPtr,System.IntPtr&):System.Boolean" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.AuthzGetInformationFromContext(System.IntPtr,System.Int32,System.Int32,System.Int32&,System.IntPtr):System.Boolean" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.AuthzFreeContext(System.IntPtr):System.Boolean" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.AuthzFreeResourceManager(System.IntPtr):System.Boolean" />
+ // <ReferencesCritical Name="Method: Utils.GetMachineDomainSid():System.IntPtr" Ring="1" />
+ // <ReferencesCritical Name="Method: SafeMemoryPtr..ctor(System.IntPtr)" Ring="1" />
+ // <ReferencesCritical Name="Field: psMachineSid" Ring="1" />
+ // <ReferencesCritical Name="Method: Utils.ConvertByteArrayToIntPtr(System.Byte[]):System.IntPtr" Ring="1" />
+ // <ReferencesCritical Name="Field: psUserSid" Ring="1" />
+ // <ReferencesCritical Name="Method: SidList..ctor(System.DirectoryServices.AccountManagement.UnsafeNativeMethods+SID_AND_ATTR[])" Ring="1" />
+ // <ReferencesCritical Name="Field: groupSidList" Ring="1" />
+ // <ReferencesCritical Name="Field: psBuffer" Ring="1" />
+ // <ReferencesCritical Name="Method: StoreCtx.get_OwningContext():System.DirectoryServices.AccountManagement.PrincipalContext" Ring="2" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal AuthZSet(
+ byte[] userSid,
+ NetCred credentials,
+ ContextOptions contextOptions,
+ string flatUserAuthority,
+ StoreCtx userStoreCtx,
+ object userCtxBase)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "AuthZSet",
+ "AuthZSet: SID={0}, authority={1}, storeCtx={2}",
+ Utils.ByteArrayToString(userSid),
+ flatUserAuthority,
+ userStoreCtx.GetType());
+
+ _userType = userStoreCtx.OwningContext.ContextType;
+ _userCtxBase = userCtxBase;
+ _userStoreCtx = userStoreCtx;
+ _credentials = credentials;
+ _contextOptions = contextOptions;
+
+ // flatUserAuthority is flat domain name if userType == Domain,
+ // flat host name if userType == LocalMachine
+ _flatUserAuthority = flatUserAuthority;
+
+ // Preload the PrincipalContext cache with the user's PrincipalContext
+ _contexts[flatUserAuthority] = userStoreCtx.OwningContext;
+
+ IntPtr hUser = IntPtr.Zero;
+
+ //
+ // Get the SIDs of the groups to which the user belongs
+ //
+
+ IntPtr pClientContext = IntPtr.Zero;
+ IntPtr pResManager = IntPtr.Zero;
+ IntPtr pBuffer = IntPtr.Zero;
+
+ try
+ {
+ UnsafeNativeMethods.LUID luid = new UnsafeNativeMethods.LUID();
+ luid.low = 0;
+ luid.high = 0;
+
+ _psMachineSid = new SafeMemoryPtr(Utils.GetMachineDomainSid());
+ _psUserSid = new SafeMemoryPtr(Utils.ConvertByteArrayToIntPtr(userSid));
+
+ bool f;
+ int lastError = 0;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Initializing resource manager");
+
+ // Create a resource manager
+ f = UnsafeNativeMethods.AuthzInitializeResourceManager(
+ UnsafeNativeMethods.AUTHZ_RM_FLAG.AUTHZ_RM_FLAG_NO_AUDIT,
+ IntPtr.Zero,
+ IntPtr.Zero,
+ IntPtr.Zero,
+ null,
+ out pResManager
+ );
+
+ if (f)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Getting ctx from SID");
+
+ // Construct a context for the user based on the user's SID
+ f = UnsafeNativeMethods.AuthzInitializeContextFromSid(
+ 0, // default flags
+ _psUserSid.DangerousGetHandle(),
+ pResManager,
+ IntPtr.Zero,
+ luid,
+ IntPtr.Zero,
+ out pClientContext
+ );
+
+ if (f)
+ {
+ int bufferSize = 0;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Getting info from ctx");
+
+ // Extract the group SIDs from the user's context. Determine the size of the buffer we need.
+ f = UnsafeNativeMethods.AuthzGetInformationFromContext(
+ pClientContext,
+ 2, // AuthzContextInfoGroupsSids
+ 0,
+ out bufferSize,
+ IntPtr.Zero
+ );
+ if (!f && (bufferSize > 0) && (Marshal.GetLastWin32Error() == 122) /*ERROR_INSUFFICIENT_BUFFER*/)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Getting info from ctx (size={0})", bufferSize);
+
+ Debug.Assert(bufferSize > 0);
+
+ // Set up the needed buffer
+ pBuffer = Marshal.AllocHGlobal(bufferSize);
+
+ // Extract the group SIDs from the user's context, into our buffer.0
+ f = UnsafeNativeMethods.AuthzGetInformationFromContext(
+ pClientContext,
+ 2, // AuthzContextInfoGroupsSids
+ bufferSize,
+ out bufferSize,
+ pBuffer
+ );
+
+ if (f)
+ {
+ // Marshall the native buffer into managed SID_AND_ATTR structures.
+ // The native buffer holds a TOKEN_GROUPS structure:
+ //
+ // struct TOKEN_GROUPS {
+ // DWORD GroupCount;
+ // SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY];
+ // };
+ //
+
+ // Extract TOKEN_GROUPS.GroupCount
+
+ UnsafeNativeMethods.TOKEN_GROUPS tokenGroups = (UnsafeNativeMethods.TOKEN_GROUPS)Marshal.PtrToStructure(pBuffer, typeof(UnsafeNativeMethods.TOKEN_GROUPS));
+
+ int groupCount = tokenGroups.groupCount;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Found {0} groups", groupCount);
+
+ // Extract TOKEN_GROUPS.Groups, by iterating over the array and marshalling
+ // each native SID_AND_ATTRIBUTES into a managed SID_AND_ATTR.
+ UnsafeNativeMethods.SID_AND_ATTR[] groups = new UnsafeNativeMethods.SID_AND_ATTR[groupCount];
+
+ IntPtr currentItem = new IntPtr(pBuffer.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.TOKEN_GROUPS)) - Marshal.SizeOf(typeof(IntPtr)));
+
+ for (int i = 0; i < groupCount; i++)
+ {
+ groups[i] = (UnsafeNativeMethods.SID_AND_ATTR)Marshal.PtrToStructure(currentItem, typeof(UnsafeNativeMethods.SID_AND_ATTR));
+
+ currentItem = new IntPtr(currentItem.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.SID_AND_ATTR)));
+ }
+
+ _groupSidList = new SidList(groups);
+ }
+ else
+ {
+ lastError = Marshal.GetLastWin32Error();
+ }
+ }
+ else
+ {
+ lastError = Marshal.GetLastWin32Error();
+ // With a zero-length buffer, this should have never succeeded
+ Debug.Assert(false);
+ }
+ }
+ else
+ {
+ lastError = Marshal.GetLastWin32Error();
+ }
+ }
+ else
+ {
+ lastError = Marshal.GetLastWin32Error();
+ }
+
+ if (!f)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "Failed to retrieve group list, {0}", lastError);
+
+ throw new PrincipalOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.AuthZFailedToRetrieveGroupList,
+ lastError));
+ }
+
+ // Save off the buffer since it still holds the native SIDs referenced by SidList
+ _psBuffer = new SafeMemoryPtr(pBuffer);
+ pBuffer = IntPtr.Zero;
+ }
+ catch (Exception e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "AuthZSet", "Caught exception {0} with message {1}", e.GetType(), e.Message);
+
+ if (_psBuffer != null && !_psBuffer.IsInvalid)
+ _psBuffer.Close();
+
+ if (_psUserSid != null && !_psUserSid.IsInvalid)
+ _psUserSid.Close();
+
+ if (_psMachineSid != null && !_psMachineSid.IsInvalid)
+ _psMachineSid.Close();
+
+ // We're on a platform that doesn't have the AuthZ library
+ if (e is DllNotFoundException)
+ throw new NotSupportedException(StringResources.AuthZNotSupported, e);
+
+ if (e is EntryPointNotFoundException)
+ throw new NotSupportedException(StringResources.AuthZNotSupported, e);
+
+ throw;
+ }
+ finally
+ {
+ if (pClientContext != IntPtr.Zero)
+ UnsafeNativeMethods.AuthzFreeContext(pClientContext);
+
+ if (pResManager != IntPtr.Zero)
+ UnsafeNativeMethods.AuthzFreeResourceManager(pResManager);
+
+ if (pBuffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(pBuffer);
+ }
+ }
+
+ override internal object CurrentAsPrincipal
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
+ // <SatisfiesLinkDemand Name="GroupPrincipal.FindByIdentity(System.DirectoryServices.AccountManagement.PrincipalContext,System.DirectoryServices.AccountManagement.IdentityType,System.String):System.DirectoryServices.AccountManagement.GroupPrincipal" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.EqualDomainSid(System.IntPtr,System.IntPtr,System.Boolean&):System.Boolean" />
+ // <ReferencesCritical Name="Field: groupSidList" Ring="1" />
+ // <ReferencesCritical Name="Method: SidList.get_Length():System.Int32" Ring="1" />
+ // <ReferencesCritical Name="Method: SidList.get_Item(System.Int32):System.DirectoryServices.AccountManagement.SidListEntry" Ring="1" />
+ // <ReferencesCritical Name="Method: Utils.ConvertNativeSidToByteArray(System.IntPtr):System.Byte[]" Ring="1" />
+ // <ReferencesCritical Name="Method: Utils.ClassifySID(System.IntPtr):System.DirectoryServices.AccountManagement.SidType" Ring="1" />
+ // <ReferencesCritical Name="Field: psUserSid" Ring="1" />
+ // <ReferencesCritical Name="Field: psMachineSid" Ring="1" />
+ // <ReferencesCritical Name="Method: Utils.IsMachineDC(System.String):System.Boolean" Ring="1" />
+ // <ReferencesCritical Name="Method: SDSCache.GetContext(System.String,System.DirectoryServices.AccountManagement.NetCred,System.DirectoryServices.AccountManagement.ContextOptions):System.DirectoryServices.AccountManagement.PrincipalContext" Ring="1" />
+ // <ReferencesCritical Name="Method: Utils.GetComputerFlatName():System.String" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: ADStoreCtx.FindPrincipalBySID(System.Type,System.DirectoryServices.AccountManagement.IdentityReference,System.Boolean):System.DirectoryServices.AccountManagement.Principal" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ Debug.Assert(_currentGroup >= 0 && _currentGroup < _groupSidList.Length);
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "AuthZSet",
+ "CurrentAsPrincipal: currentGroup={0}, list length={1}",
+ _currentGroup,
+ _groupSidList.Length);
+
+ // Convert native SID to byte[] SID
+ IntPtr pSid = _groupSidList[_currentGroup].pSid;
+ byte[] sid = Utils.ConvertNativeSidToByteArray(pSid);
+
+ // sidIssuerName is null only if SID was not resolved
+ // return a fake principal back
+ if (null == _groupSidList[_currentGroup].sidIssuerName)
+ {
+ string name = _groupSidList[_currentGroup].name;
+ // Create a Principal object to represent it
+ GroupPrincipal g = GroupPrincipal.MakeGroup(_userStoreCtx.OwningContext);
+ g.fakePrincipal = true;
+ g.LoadValueIntoProperty(PropertyNames.PrincipalDisplayName, name);
+ g.LoadValueIntoProperty(PropertyNames.PrincipalName, name);
+ SecurityIdentifier sidObj = new SecurityIdentifier(Utils.ConvertSidToSDDL(sid));
+ g.LoadValueIntoProperty(PropertyNames.PrincipalSid, sidObj);
+ g.LoadValueIntoProperty(PropertyNames.GroupIsSecurityGroup, true);
+ return g;
+ }
+
+ GroupPrincipal group = null;
+
+ // Classify the SID
+ SidType sidType = Utils.ClassifySID(pSid);
+
+ // It's a fake principal. Construct and respond the corresponding fake Principal object.
+ if (sidType == SidType.FakeObject)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "CurrentAsPrincipal: fake principal {0}", Utils.ByteArrayToString(sid));
+ return _userStoreCtx.ConstructFakePrincipalFromSID(sid);
+ }
+
+ // Try to figure out who issued the SID
+ string sidIssuerName = null;
+
+ if (sidType == SidType.RealObjectFakeDomain)
+ {
+ // BUILTIN principal --> issuer is the same authority as the user's SID
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "CurrentAsPrincipal: builtin principal {0}", Utils.ByteArrayToString(sid));
+
+ sidIssuerName = _flatUserAuthority;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "CurrentAsPrincipal: real principal {0}", Utils.ByteArrayToString(sid));
+
+ // Is the SID from the same domain as the user?
+ bool sameDomain = false;
+
+ bool success = UnsafeNativeMethods.EqualDomainSid(_psUserSid.DangerousGetHandle(), pSid, ref sameDomain);
+
+ // if failed, psUserSid must not be a domain sid
+ if (!success)
+ {
+#if !SUPPORT_WK_USER_OBJS
+ Debug.Fail("AuthZSet.CurrentAsPrincipal: hit a user with a non-domain SID");
+#endif // SUPPORT_WK_USER_OBJS
+
+ sameDomain = false;
+ }
+
+ // same domain --> issuer is the same authority as the user's SID
+ if (sameDomain)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "CurrentAsPrincipal: same domain as user ({0})", _flatUserAuthority);
+ sidIssuerName = _flatUserAuthority;
+ }
+ }
+
+ // The SID comes from another domain. Use the domain name that the OS resolved the SID to.
+ if (sidIssuerName == null)
+ {
+ sidIssuerName = _groupSidList[_currentGroup].sidIssuerName;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "CurrentAsPrincipal: different domain ({0}) than user ({1})", sidIssuerName, _flatUserAuthority);
+ }
+
+ Debug.Assert(sidIssuerName != null);
+ Debug.Assert(sidIssuerName.Length > 0);
+
+ // Determine whether it's a local (WinNT) or Active Directory domain (LDAP) group
+ bool isLocalGroup = false;
+ if (_userType == ContextType.Machine)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "CurrentAsPrincipal: local group (user is SAM)");
+
+ // Machine local user ---> must be a local group
+ isLocalGroup = true;
+ }
+ else
+ {
+ Debug.Assert(_userType == ContextType.Domain);
+
+ // Domain user, but the group SID is from the machine domain --> must be a local group
+ // EqualDomainSid will return false if pSid is a BUILTIN SID, but that's okay, we treat those as domain (not local)
+ // groups for domain users.
+ bool inMachineDomain = false;
+ if (UnsafeNativeMethods.EqualDomainSid(_psMachineSid.DangerousGetHandle(), pSid, ref inMachineDomain))
+ if (inMachineDomain)
+ {
+ // At this point we know that the group was issued by the local machine. Now determine if this machine is
+ // a DC. Cache the results of the read.
+
+ if (!_localMachineIsDC.HasValue)
+ {
+ _localMachineIsDC = (bool?)Utils.IsMachineDC(null);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "CurrentAsPrincipal: IsLocalMachine a DC, localMachineIsDC={0}", _localMachineIsDC.Value);
+ }
+
+ isLocalGroup = !_localMachineIsDC.Value;
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "CurrentAsPrincipal: user is non-SAM, isLocalGroup={0}", isLocalGroup);
+ }
+
+ if (isLocalGroup)
+ {
+ // It's a local group, because either (1) it's a local machine user, and local users can't be a member of a domain group,
+ // or (2) it's a domain user that's a member of a group on the local machine. Pass the default machine context options
+ // If we initially targetted AD then those options will not be valid for the machine store.
+
+#if USE_CTX_CACHE
+ PrincipalContext ctx = SDSCache.LocalMachine.GetContext(
+ sidIssuerName,
+ _credentials,
+ DefaultContextOptions.MachineDefaultContextOption);
+#else
+ PrincipalContext ctx = (PrincipalContext) this.contexts[sidIssuerName];
+ if (ctx == null)
+ {
+ // Build a PrincipalContext for the machine
+ ctx = new PrincipalContext(
+ ContextType.Machine,
+ sidIssuerName,
+ null,
+ (this.credentials != null ? credentials.UserName : null),
+ (this.credentials != null ? credentials.Password : null),
+ DefaultContextOptions.MachineDefaultContextOption);
+
+ this.contexts[sidIssuerName] = ctx;
+ }
+#endif
+ SecurityIdentifier sidObj = new SecurityIdentifier(sid, 0);
+ group = GroupPrincipal.FindByIdentity(ctx, IdentityType.Sid, sidObj.ToString());
+ }
+ else
+ {
+ Debug.Assert((_userType == ContextType.Domain) &&
+ (String.Compare(Utils.GetComputerFlatName(), sidIssuerName, StringComparison.OrdinalIgnoreCase) != 0));
+
+ // It's a domain group, because it's a domain user and the SID issuer isn't the local machine
+
+#if USE_CTX_CACHE
+ PrincipalContext ctx = SDSCache.Domain.GetContext(
+ sidIssuerName,
+ _credentials,
+ _contextOptions);
+#else
+ PrincipalContext ctx = (PrincipalContext) this.contexts[sidIssuerName];
+ if (ctx == null)
+ {
+ // Determine the domain DNS name
+
+ // DS_RETURN_DNS_NAME | DS_DIRECTORY_SERVICE_REQUIRED | DS_BACKGROUND_ONLY
+ int flags = unchecked((int) (0x40000000 | 0x00000010 | 0x00000100));
+ UnsafeNativeMethods.DomainControllerInfo info = Utils.GetDcName(null, sidIssuerName, null, flags);
+
+ // Build a PrincipalContext for the domain
+ ctx = new PrincipalContext(
+ ContextType.Domain,
+ info.DomainName,
+ null,
+ (this.credentials != null ? credentials.UserName : null),
+ (this.credentials != null ? credentials.Password : null),
+ this.contextOptions);
+
+ this.contexts[sidIssuerName] = ctx;
+ }
+#endif
+ // Retrieve the group. We'd normally just do a Group.FindByIdentity here, but
+ // because the AZMan API can return "old" SIDs, we also need to check the SID
+ // history. So we'll use the special FindPrincipalBySID method that the ADStoreCtx
+ // exposes for that purpose.
+ Debug.Assert(ctx.QueryCtx is ADStoreCtx);
+
+ IdentityReference ir = new IdentityReference();
+ // convert byte sid to SDDL string.
+ SecurityIdentifier sidObj = new SecurityIdentifier(sid, 0);
+ ir.UrnScheme = UrnScheme.SidScheme;
+ ir.UrnValue = sidObj.ToString();
+
+ group = (GroupPrincipal)((ADStoreCtx)ctx.QueryCtx).FindPrincipalBySID(typeof(GroupPrincipal), ir, true);
+ }
+
+ if (group == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "CurrentAsPrincipal: Couldn't find group {0}");
+ throw new NoMatchingPrincipalException(StringResources.AuthZCantFindGroup);
+ }
+
+ return group;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.EqualDomainSid(System.IntPtr,System.IntPtr,System.Boolean&):System.Boolean" />
+ // <ReferencesCritical Name="Field: groupSidList" Ring="1" />
+ // <ReferencesCritical Name="Method: SidList.get_Length():System.Int32" Ring="1" />
+ // <ReferencesCritical Name="Method: SidList.get_Item(System.Int32):System.DirectoryServices.AccountManagement.SidListEntry" Ring="1" />
+ // <ReferencesCritical Name="Method: Utils.ClassifySID(System.IntPtr):System.DirectoryServices.AccountManagement.SidType" Ring="1" />
+ // <ReferencesCritical Name="Field: psUserSid" Ring="1" />
+ // <ReferencesCritical Name="Method: Utils.GetLastRidFromSid(System.IntPtr):System.Int32" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ override internal bool MoveNext()
+ {
+ bool needToRetry;
+
+ do
+ {
+ needToRetry = false;
+
+ _currentGroup++;
+
+ if (_currentGroup >= _groupSidList.Length)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "MoveNext: ran off end of list ({0})", _groupSidList.Length);
+ return false;
+ }
+
+ // Test for the NONE group for a local user. We recognize it by:
+ // * we're enumerating the authz groups for a local machine user
+ // * it's a domain sid (SidType.RealObject) for the same domain as the user
+ // * it has the RID of the "Domain Users" group, 513
+ if (_userType == ContextType.Machine)
+ {
+ IntPtr pSid = _groupSidList[_currentGroup].pSid;
+
+ bool sameDomain = false;
+ if (Utils.ClassifySID(pSid) == SidType.RealObject && UnsafeNativeMethods.EqualDomainSid(_psUserSid.DangerousGetHandle(), pSid, ref sameDomain))
+ {
+ if (sameDomain)
+ {
+ int lastRid = Utils.GetLastRidFromSid(pSid);
+
+ if (lastRid == 513) // DOMAIN_GROUP_RID_USERS
+ {
+ // This is the NONE group for a local user. This isn't a real group, and
+ // has no impact on authorization (per ColinBr). Skip it.
+ needToRetry = true;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "MoveNext: found NONE group, skipping");
+ }
+ }
+ }
+ }
+ }
+ while (needToRetry);
+
+ return true;
+ }
+
+ override internal void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Reset");
+
+ _currentGroup = -1;
+ }
+
+ // IDisposable implementation
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="SafeHandle.Close():System.Void" />
+ // <ReferencesCritical Name="Field: psBuffer" Ring="1" />
+ // <ReferencesCritical Name="Field: psUserSid" Ring="1" />
+ // <ReferencesCritical Name="Field: psMachineSid" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public override void Dispose()
+ {
+ try
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Dispose: disposing");
+
+ _psBuffer.Close();
+ _psUserSid.Close();
+ _psMachineSid.Close();
+
+ _disposed = true;
+ }
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+
+ //
+ // Private fields
+ //
+
+ // The user whose groups we're retrieving
+ private SafeMemoryPtr _psUserSid = null;
+
+ // The SID of the machine domain of the machine we're running on
+ private SafeMemoryPtr _psMachineSid = null;
+
+ // The user's StoreCtx
+ private StoreCtx _userStoreCtx;
+
+ // The user's credentials
+ private NetCred _credentials;
+
+ // The user's options
+ private ContextOptions _contextOptions;
+
+ // The ctxBase (e.g., DirectoryEntry) from the user's StoreCtx
+ private object _userCtxBase;
+
+ // The type (domain, local, etc.) of the user
+ private ContextType _userType;
+
+ // The authority's name (hostname or domainname)
+ private string _flatUserAuthority;
+
+ // The index (into this.groupSidList) of the group we're currently enumerating
+ private int _currentGroup = -1;
+
+ // The groups we're enumerating over
+ private SidList _groupSidList;
+
+ // The native TOKEN_GROUPS returned by AuthzGetInformationFromContext
+ private SafeMemoryPtr _psBuffer = null;
+
+ // Have we been disposed?
+ private bool _disposed = false;
+
+ // Maps sidIssuerName --> PrincipalContext
+ private Hashtable _contexts = new Hashtable();
+
+ // Contains cached results if the local machine is a DC.
+ private bool? _localMachineIsDC = null;
+
+ //
+ // Guarantees finalization of the native resources
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="SafeHandle" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ private sealed class SafeMemoryPtr : SafeHandle
+ {
+ private SafeMemoryPtr() : base(IntPtr.Zero, true)
+ { }
+
+ internal SafeMemoryPtr(IntPtr handle) : base(IntPtr.Zero, true)
+ {
+ SetHandle(handle);
+ }
+
+ // for the critial finalizer object
+ public override bool IsInvalid
+ {
+ get { return (handle == IntPtr.Zero); }
+ }
+
+ override protected bool ReleaseHandle()
+ {
+ if (handle != IntPtr.Zero)
+ Marshal.FreeHGlobal(handle);
+
+ return true;
+ }
+ }
+
+ /*
+ //
+ // Holds the list of group SIDs. Also translates them in bulk into domain name and group name.
+ //
+ class SidList
+ {
+ public SidList(UnsafeNativeMethods.SID_AND_ATTR[] groupSidAndAttrs)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "SidList: processing {0} SIDs", groupSidAndAttrs.Length);
+
+ // Build the list of SIDs to resolve
+ int groupCount = groupSidAndAttrs.Length;
+ IntPtr[] pGroupSids = new IntPtr[groupCount];
+
+ for(int i=0; i < groupCount; i++)
+ {
+ pGroupSids[i] = groupSidAndAttrs[i].pSid;
+
+ }
+
+ // Translate the SIDs in bulk
+ IntPtr pOA = IntPtr.Zero;
+ IntPtr pPolicyHandle = IntPtr.Zero;
+
+ IntPtr pDomains = IntPtr.Zero;
+ UnsafeNativeMethods.LSA_TRUST_INFORMATION[] domains;
+
+ IntPtr pNames = IntPtr.Zero;
+ UnsafeNativeMethods.LSA_TRANSLATED_NAME[] names;
+
+ try
+ {
+ //
+ // Get the policy handle
+ //
+ UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES oa = new UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES();
+
+ pOA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES)));
+ Marshal.StructureToPtr(oa, pOA, false);
+ int err = UnsafeNativeMethods.LsaOpenPolicy(
+ IntPtr.Zero,
+ pOA,
+ 0x800, // POLICY_LOOKUP_NAMES
+ ref pPolicyHandle);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "SidList: couldn't get policy handle, err={0}", err);
+
+ throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
+ StringResources.AuthZErrorEnumeratingGroups,
+ SafeNativeMethods.LsaNtStatusToWinError(err)));
+ }
+
+ Debug.Assert(pPolicyHandle != IntPtr.Zero);
+
+ //
+ // Translate the SIDs
+ //
+
+ err = UnsafeNativeMethods.LsaLookupSids(
+ pPolicyHandle,
+ groupCount,
+ pGroupSids,
+ out pDomains,
+ out pNames);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "SidList: LsaLookupSids failed, err={0}", err);
+
+ throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
+ StringResources.AuthZErrorEnumeratingGroups,
+ SafeNativeMethods.LsaNtStatusToWinError(err)));
+ }
+
+ //
+ // Get the group names in managed form
+ //
+ names = new UnsafeNativeMethods.LSA_TRANSLATED_NAME[groupCount];
+ IntPtr pCurrentName = pNames;
+
+ for (int i=0; i < groupCount; i++)
+ {
+ names[i] = (UnsafeNativeMethods.LSA_TRANSLATED_NAME)
+ Marshal.PtrToStructure(pCurrentName, typeof(UnsafeNativeMethods.LSA_TRANSLATED_NAME));
+
+ pCurrentName = new IntPtr(pCurrentName.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_TRANSLATED_NAME)));
+ }
+
+ //
+ // Get the domain names in managed form
+ //
+
+ // Extract LSA_REFERENCED_DOMAIN_LIST.Entries
+ int domainCount = Marshal.ReadInt32(pDomains);
+
+ // Extract LSA_REFERENCED_DOMAIN_LIST.Domains, by iterating over the array and marshalling
+ // each native LSA_TRUST_INFORMATION into a managed LSA_TRUST_INFORMATION.
+ domains = new UnsafeNativeMethods.LSA_TRUST_INFORMATION[domainCount];
+
+ IntPtr pCurrentDomain = Marshal.ReadIntPtr(pDomains, Marshal.SizeOf(typeof(Int32)));
+
+ for(int i=0; i < domainCount; i++)
+ {
+ domains[i] =(UnsafeNativeMethods.LSA_TRUST_INFORMATION) Marshal.PtrToStructure(pCurrentDomain, typeof(UnsafeNativeMethods.LSA_TRUST_INFORMATION));
+ pCurrentDomain = new IntPtr(pCurrentDomain.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_TRUST_INFORMATION)));
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "SidList: got {0} groups in {1} domains", groupCount, domainCount);
+
+ //
+ // Build the list of entries
+ //
+ Debug.Assert(names.Length == groupCount);
+
+ for (int i = 0; i < names.Length; i++)
+ {
+ UnsafeNativeMethods.LSA_TRANSLATED_NAME name = names[i];
+
+ // Get the domain associated with this name
+ Debug.Assert(name.domainIndex >= 0);
+ Debug.Assert(name.domainIndex < domains.Length);
+ UnsafeNativeMethods.LSA_TRUST_INFORMATION domain = domains[name.domainIndex];
+
+ // Build an entry. Note that LSA_UNICODE_STRING.length is in bytes,
+ // while PtrToStringUni expects a length in characters.
+ SidListEntry entry = new SidListEntry();
+
+ Debug.Assert(name.name.length % 2 == 0);
+ entry.name = Marshal.PtrToStringUni(name.name.buffer, name.name.length/2);
+
+ Debug.Assert(domain.name.length % 2 == 0);
+ entry.sidIssuerName = Marshal.PtrToStringUni(domain.name.buffer, domain.name.length/2);
+
+ entry.pSid = groupSidAndAttrs[i].pSid;
+
+ this.entries.Add(entry);
+ }
+
+ }
+ finally
+ {
+ if (pDomains != IntPtr.Zero)
+ UnsafeNativeMethods.LsaFreeMemory(pDomains);
+
+ if (pNames != IntPtr.Zero)
+ UnsafeNativeMethods.LsaFreeMemory(pNames);
+
+ if (pPolicyHandle != IntPtr.Zero)
+ UnsafeNativeMethods.LsaClose(pPolicyHandle);
+
+ if (pOA != IntPtr.Zero)
+ Marshal.FreeHGlobal(pOA);
+ }
+ }
+
+ List<SidListEntry> entries = new List<SidListEntry>();
+
+ public SidListEntry this[int index]
+ {
+ get { return this.entries[index]; }
+ }
+
+ public int Length
+ {
+ get { return this.entries.Count; }
+ }
+ }
+
+ class SidListEntry
+ {
+ public IntPtr pSid;
+
+ public string name;
+ public string sidIssuerName;
+ }
+ */
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AuthenticablePrincipal.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AuthenticablePrincipal.cs
new file mode 100644
index 0000000000..471de7bf31
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AuthenticablePrincipal.cs
@@ -0,0 +1,646 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Permissions;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ [DirectoryRdnPrefix("CN")]
+ public class AuthenticablePrincipal : Principal
+ {
+ //
+ // Public Properties
+ //
+
+ // Enabled property
+ private bool _enabled = false; // the actual property value
+ private LoadState _enabledChanged = LoadState.NotSet; // change-tracking
+
+ public Nullable<bool> Enabled
+ {
+ get
+ {
+ // Make sure we're not disposed or deleted. Although HandleGet/HandleSet will check this,
+ // we need to check these before we do anything else.
+ CheckDisposedOrDeleted();
+
+ // Different stores have different defaults as to the Enabled setting
+ // (AD: creates disabled by default; SAM: creates enabled by default).
+ // So if the principal is unpersisted (and thus we may not know what store it's
+ // going to end up in), we'll just return null unless they previously
+ // set an explicit value.
+ if (this.unpersisted && (_enabledChanged != LoadState.Changed))
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "AuthenticablePrincipal",
+ "Enabled: returning null, unpersisted={0}, enabledChanged={1}",
+ this.unpersisted,
+ _enabledChanged);
+
+ return null;
+ }
+
+ return HandleGet<bool>(ref _enabled, PropertyNames.AuthenticablePrincipalEnabled, ref _enabledChanged);
+ }
+
+ set
+ {
+ // Make sure we're not disposed or deleted. Although HandleGet/HandleSet will check this,
+ // we need to check these before we do anything else.
+ CheckDisposedOrDeleted();
+
+ // We don't want to let them set a null value.
+ if (!value.HasValue)
+ throw new ArgumentNullException("value");
+
+ HandleSet<bool>(ref _enabled, value.Value, ref _enabledChanged,
+ PropertyNames.AuthenticablePrincipalEnabled);
+ }
+ }
+
+ //
+ // AccountInfo-related properties/methods
+ //
+
+ private AccountInfo _accountInfo = null;
+
+ private AccountInfo AccountInfo
+ {
+ get
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ if (_accountInfo == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthenticablePrincipal", "AccountInfo: creating new AccountInfo");
+ _accountInfo = new AccountInfo(this);
+ }
+
+ return _accountInfo;
+ }
+ }
+
+ public Nullable<DateTime> AccountLockoutTime
+ {
+ get { return this.AccountInfo.AccountLockoutTime; }
+ }
+
+ public Nullable<DateTime> LastLogon
+ {
+ get { return this.AccountInfo.LastLogon; }
+ }
+
+ public PrincipalValueCollection<string> PermittedWorkstations
+ {
+ get { return this.AccountInfo.PermittedWorkstations; }
+ }
+
+ public byte[] PermittedLogonTimes
+ {
+ get { return this.AccountInfo.PermittedLogonTimes; }
+ set { this.AccountInfo.PermittedLogonTimes = value; }
+ }
+
+ public Nullable<DateTime> AccountExpirationDate
+ {
+ get { return this.AccountInfo.AccountExpirationDate; }
+ set { this.AccountInfo.AccountExpirationDate = value; }
+ }
+
+ public bool SmartcardLogonRequired
+ {
+ get { return this.AccountInfo.SmartcardLogonRequired; }
+ set { this.AccountInfo.SmartcardLogonRequired = value; }
+ }
+
+ public bool DelegationPermitted
+ {
+ get { return this.AccountInfo.DelegationPermitted; }
+ set { this.AccountInfo.DelegationPermitted = value; }
+ }
+
+ public int BadLogonCount
+ {
+ get { return this.AccountInfo.BadLogonCount; }
+ }
+
+ public string HomeDirectory
+ {
+ get { return this.AccountInfo.HomeDirectory; }
+ set { this.AccountInfo.HomeDirectory = value; }
+ }
+
+ public string HomeDrive
+ {
+ get { return this.AccountInfo.HomeDrive; }
+ set { this.AccountInfo.HomeDrive = value; }
+ }
+
+ public string ScriptPath
+ {
+ get { return this.AccountInfo.ScriptPath; }
+ set { this.AccountInfo.ScriptPath = value; }
+ }
+
+ public bool IsAccountLockedOut()
+ {
+ return this.AccountInfo.IsAccountLockedOut();
+ }
+
+ public void UnlockAccount()
+ {
+ this.AccountInfo.UnlockAccount();
+ }
+
+ //
+ // PasswordInfo-related properties/methods
+ //
+
+ private PasswordInfo _passwordInfo = null;
+
+ private PasswordInfo PasswordInfo
+ {
+ get
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ if (_passwordInfo == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthenticablePrincipal", "PasswordInfo: creating new PasswordInfo");
+ _passwordInfo = new PasswordInfo(this);
+ }
+
+ return _passwordInfo;
+ }
+ }
+
+ public Nullable<DateTime> LastPasswordSet
+ {
+ get { return this.PasswordInfo.LastPasswordSet; }
+ }
+
+ public Nullable<DateTime> LastBadPasswordAttempt
+ {
+ get { return this.PasswordInfo.LastBadPasswordAttempt; }
+ }
+
+ public bool PasswordNotRequired
+ {
+ get { return this.PasswordInfo.PasswordNotRequired; }
+ set { this.PasswordInfo.PasswordNotRequired = value; }
+ }
+
+ public bool PasswordNeverExpires
+ {
+ get { return this.PasswordInfo.PasswordNeverExpires; }
+ set { this.PasswordInfo.PasswordNeverExpires = value; }
+ }
+
+ public bool UserCannotChangePassword
+ {
+ get { return this.PasswordInfo.UserCannotChangePassword; }
+ set { this.PasswordInfo.UserCannotChangePassword = value; }
+ }
+
+ public bool AllowReversiblePasswordEncryption
+ {
+ get { return this.PasswordInfo.AllowReversiblePasswordEncryption; }
+ set { this.PasswordInfo.AllowReversiblePasswordEncryption = value; }
+ }
+
+ internal AdvancedFilters rosf;
+
+ public virtual AdvancedFilters AdvancedSearchFilter
+ {
+ get
+ {
+ return rosf;
+ }
+ }
+
+ public void SetPassword(string newPassword)
+ {
+ this.PasswordInfo.SetPassword(newPassword);
+ }
+
+ public void ChangePassword(string oldPassword, string newPassword)
+ {
+ this.PasswordInfo.ChangePassword(oldPassword, newPassword);
+ }
+
+ public void ExpirePasswordNow()
+ {
+ this.PasswordInfo.ExpirePasswordNow();
+ }
+
+ public void RefreshExpiredPassword()
+ {
+ this.PasswordInfo.RefreshExpiredPassword();
+ }
+
+ // Certificates property
+ private X509Certificate2Collection _certificates = new X509Certificate2Collection();
+ private List<string> _certificateOriginalThumbprints = new List<string>();
+ private LoadState _X509Certificate2CollectionLoaded = LoadState.NotSet;
+
+ public X509Certificate2Collection Certificates
+ {
+ get
+ {
+ return HandleGet<X509Certificate2Collection>(ref _certificates,
+ PropertyNames.AuthenticablePrincipalCertificates, ref _X509Certificate2CollectionLoaded);
+ }
+ }
+
+ //
+ // Public Methods
+ //
+ public static PrincipalSearchResult<AuthenticablePrincipal> FindByLockoutTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByLockoutTime<AuthenticablePrincipal>(context, time, type);
+ }
+
+ public static PrincipalSearchResult<AuthenticablePrincipal> FindByLogonTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByLogonTime<AuthenticablePrincipal>(context, time, type);
+ }
+
+ public static PrincipalSearchResult<AuthenticablePrincipal> FindByExpirationTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByExpirationTime<AuthenticablePrincipal>(context, time, type);
+ }
+
+ public static PrincipalSearchResult<AuthenticablePrincipal> FindByBadPasswordAttempt(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByBadPasswordAttempt<AuthenticablePrincipal>(context, time, type);
+ }
+
+ public static PrincipalSearchResult<AuthenticablePrincipal> FindByPasswordSetTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByPasswordSetTime<AuthenticablePrincipal>(context, time, type);
+ }
+
+ //
+ // Protected implementations
+ //
+
+ protected static PrincipalSearchResult<T> FindByLockoutTime<T>(PrincipalContext context, DateTime time, MatchType type)
+ {
+ CheckFindByArgs(context, time, type, typeof(T));
+
+ return new PrincipalSearchResult<T>(context.QueryCtx.FindByLockoutTime(time, type, typeof(T)));
+ }
+ protected static PrincipalSearchResult<T> FindByLogonTime<T>(PrincipalContext context, DateTime time, MatchType type)
+ {
+ CheckFindByArgs(context, time, type, typeof(T));
+
+ return new PrincipalSearchResult<T>(context.QueryCtx.FindByLogonTime(time, type, typeof(T)));
+ }
+ protected static PrincipalSearchResult<T> FindByExpirationTime<T>(PrincipalContext context, DateTime time, MatchType type)
+ {
+ CheckFindByArgs(context, time, type, typeof(T));
+
+ return new PrincipalSearchResult<T>(context.QueryCtx.FindByExpirationTime(time, type, typeof(T)));
+ }
+ protected static PrincipalSearchResult<T> FindByBadPasswordAttempt<T>(PrincipalContext context, DateTime time, MatchType type)
+ {
+ CheckFindByArgs(context, time, type, typeof(T));
+
+ return new PrincipalSearchResult<T>(context.QueryCtx.FindByBadPasswordAttempt(time, type, typeof(T)));
+ }
+ protected static PrincipalSearchResult<T> FindByPasswordSetTime<T>(PrincipalContext context, DateTime time, MatchType type)
+ {
+ CheckFindByArgs(context, time, type, typeof(T));
+
+ return new PrincipalSearchResult<T>(context.QueryCtx.FindByPasswordSetTime(time, type, typeof(T)));
+ }
+
+ //
+ // Private implementation
+ //
+ internal protected AuthenticablePrincipal(PrincipalContext context)
+ {
+ if (context == null)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ this.ContextRaw = context;
+ this.unpersisted = true;
+ this.rosf = new AdvancedFilters(this);
+ }
+
+ internal protected AuthenticablePrincipal(PrincipalContext context, string samAccountName, string password, bool enabled) : this(context)
+ {
+ if (samAccountName != null)
+ {
+ this.SamAccountName = samAccountName;
+ }
+
+ if (password != null)
+ {
+ this.SetPassword(password);
+ }
+
+ this.Enabled = enabled;
+ }
+
+ static internal AuthenticablePrincipal MakeAuthenticablePrincipal(PrincipalContext ctx)
+ {
+ AuthenticablePrincipal ap = new AuthenticablePrincipal(ctx);
+ ap.unpersisted = false;
+
+ return ap;
+ }
+
+ private static void CheckFindByArgs(PrincipalContext context, DateTime time, MatchType type, Type subtype)
+ {
+ if ((subtype != typeof(AuthenticablePrincipal)) &&
+ (!subtype.IsSubclassOf(typeof(AuthenticablePrincipal))))
+ throw new ArgumentException(StringResources.AuthenticablePrincipalMustBeSubtypeOfAuthPrinc);
+
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ if (subtype == null)
+ throw new ArgumentNullException("subtype");
+ }
+
+ //
+ // Load/Store
+ //
+
+ //
+ // Loading with query results
+ //
+
+ internal override void LoadValueIntoProperty(string propertyName, object value)
+ {
+ switch (propertyName)
+ {
+ case PropertyNames.AuthenticablePrincipalCertificates:
+ LoadCertificateCollection((List<byte[]>)value);
+ RefreshOriginalThumbprintList();
+ _X509Certificate2CollectionLoaded = LoadState.Loaded;
+ break;
+
+ case PropertyNames.AuthenticablePrincipalEnabled:
+ _enabled = (bool)value;
+ _enabledChanged = LoadState.Loaded;
+ break;
+
+ default:
+ if (propertyName.StartsWith(PropertyNames.AcctInfoPrefix, StringComparison.Ordinal))
+ {
+ // If this is the first AccountInfo attribute we're loading,
+ // we'll need to create the AccountInfo to hold it
+ if (_accountInfo == null)
+ _accountInfo = new AccountInfo(this);
+
+ _accountInfo.LoadValueIntoProperty(propertyName, value);
+ }
+ else if (propertyName.StartsWith(PropertyNames.PwdInfoPrefix, StringComparison.Ordinal))
+ {
+ // If this is the first PasswordInfo attribute we're loading,
+ // we'll need to create the PasswordInfo to hold it
+ if (_passwordInfo == null)
+ _passwordInfo = new PasswordInfo(this);
+
+ _passwordInfo.LoadValueIntoProperty(propertyName, value);
+ }
+ else
+ {
+ base.LoadValueIntoProperty(propertyName, value);
+ }
+ break;
+ }
+ }
+
+ //
+ // Getting changes to persist (or to build a query from a QBE filter)
+ //
+
+ // Given a property name, returns true if that property has changed since it was loaded, false otherwise.
+ internal override bool GetChangeStatusForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthenticablePrincipal", "GetChangeStatusForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case PropertyNames.AuthenticablePrincipalCertificates:
+ return HasCertificateCollectionChanged();
+
+ case PropertyNames.AuthenticablePrincipalEnabled:
+ return _enabledChanged == LoadState.Changed;
+
+ default:
+
+ // Check if the property is supported by AdvancedFilter class.
+ // If writeable properties are added to the rosf class then we will need
+ // to add some type of tag to the property names to differentiate them here
+ bool? val = rosf.GetChangeStatusForProperty(propertyName);
+
+ if (val.HasValue == true)
+ return val.Value;
+
+ if (propertyName.StartsWith(PropertyNames.AcctInfoPrefix, StringComparison.Ordinal))
+ {
+ if (_accountInfo == null)
+ return false;
+
+ return _accountInfo.GetChangeStatusForProperty(propertyName);
+ }
+ else if (propertyName.StartsWith(PropertyNames.PwdInfoPrefix, StringComparison.Ordinal))
+ {
+ if (_passwordInfo == null)
+ return false;
+
+ return _passwordInfo.GetChangeStatusForProperty(propertyName);
+ }
+ else
+ {
+ return base.GetChangeStatusForProperty(propertyName);
+ }
+ }
+ }
+
+ // Given a property name, returns the current value for the property.
+ internal override object GetValueForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthenticablePrincipal", "GetValueForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case PropertyNames.AuthenticablePrincipalCertificates:
+ return _certificates;
+
+ case PropertyNames.AuthenticablePrincipalEnabled:
+ return _enabled;
+
+ default:
+
+ object val = rosf.GetValueForProperty(propertyName);
+
+ if (null != val)
+ return val;
+
+ if (propertyName.StartsWith(PropertyNames.AcctInfoPrefix, StringComparison.Ordinal))
+ {
+ if (_accountInfo == null)
+ {
+ // Should never happen, since GetChangeStatusForProperty returned false
+ Debug.Fail("AuthenticablePrincipal.GetValueForProperty(AcctInfo): shouldn't be here");
+ throw new InvalidOperationException();
+ }
+
+ return _accountInfo.GetValueForProperty(propertyName);
+ }
+ else if (propertyName.StartsWith(PropertyNames.PwdInfoPrefix, StringComparison.Ordinal))
+ {
+ if (_passwordInfo == null)
+ {
+ // Should never happen, since GetChangeStatusForProperty returned false
+ Debug.Fail("AuthenticablePrincipal.GetValueForProperty(PwdInfo): shouldn't be here");
+ throw new InvalidOperationException();
+ }
+
+ return _passwordInfo.GetValueForProperty(propertyName);
+ }
+ else
+ {
+ return base.GetValueForProperty(propertyName);
+ }
+ }
+ }
+
+ // Reset all change-tracking status for all properties on the object to "unchanged".
+ internal override void ResetAllChangeStatus()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthenticablePrincipal", "ResetAllChangeStatus");
+
+ _enabledChanged = (_enabledChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+
+ RefreshOriginalThumbprintList();
+
+ if (_accountInfo != null)
+ {
+ _accountInfo.ResetAllChangeStatus();
+ }
+
+ if (_passwordInfo != null)
+ {
+ _passwordInfo.ResetAllChangeStatus();
+ }
+
+ rosf.ResetAllChangeStatus();
+
+ base.ResetAllChangeStatus();
+ }
+
+ //
+ // Certificate support routines
+ //
+
+ // Given a list of certs (expressed as byte[]s), loads them into
+ // the certificate collection
+ private void LoadCertificateCollection(List<byte[]> certificatesToLoad)
+ {
+ // To support reload
+ _certificates.Clear();
+ Debug.Assert(_certificates.Count == 0);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthenticablePrincipal", "LoadCertificateCollection: loading {0} certs", certificatesToLoad.Count);
+
+ foreach (byte[] rawCert in certificatesToLoad)
+ {
+ try
+ {
+ _certificates.Import(rawCert);
+ }
+ catch (System.Security.Cryptography.CryptographicException)
+ {
+ // skip the invalid certificate
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthenticablePrincipal", "LoadCertificateCollection: skipped bad cert");
+ continue;
+ }
+ }
+ }
+
+ // Regenerates the certificateOriginalThumbprints list based on what's
+ // currently in the certificate collection
+ private void RefreshOriginalThumbprintList()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthenticablePrincipal", "RefreshOriginalThumbprintList: resetting thumbprints");
+
+ _certificateOriginalThumbprints.Clear();
+
+ foreach (X509Certificate2 certificate in _certificates)
+ {
+ _certificateOriginalThumbprints.Add(certificate.Thumbprint);
+ }
+ }
+
+ // Returns true if the certificate collection has changed since the last time
+ // certificateOriginalThumbprints was refreshed (i.e., since the last time
+ // RefreshOriginalThumbprintList was called)
+ private bool HasCertificateCollectionChanged()
+ {
+ // If the size isn't the same, the collection has certainly changed
+ if (_certificates.Count != _certificateOriginalThumbprints.Count)
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "AuthenticablePrincipal",
+ "HasCertificateCollectionChanged: original count {0}, current count{1}",
+ _certificateOriginalThumbprints.Count,
+ _certificates.Count);
+ return true;
+ }
+
+ // Make a copy of the thumbprint list, so we can alter the copy without effecting the original.
+ List<string> remainingOriginalThumbprints = new List<string>(_certificateOriginalThumbprints);
+
+ foreach (X509Certificate2 certificate in _certificates)
+ {
+ string thumbprint = certificate.Thumbprint;
+
+ // If we found a cert whose thumbprint wasn't in the thumbprints list,
+ // it was inserted --> collection has changed
+ if (!remainingOriginalThumbprints.Contains(thumbprint))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthenticablePrincipal", "RefreshOriginalThumbprintList: found inserted cert");
+ return true;
+ }
+
+ // We remove the thumbprint from the list so that if, for some reason, they inserted
+ // a duplicate of a certificate that was already in the list, we'll detect it as an insert
+ // when we encounter that cert a second time
+ remainingOriginalThumbprints.Remove(thumbprint);
+ }
+
+ // If a certificate was deleted, there are two possibilities:
+ // (1) The removal caused the size to change. We'll have caught it above and returned true.
+ // (2) The size didn't change (because there was also an insert). We'll have caught the insert
+ // above and returned true. Note that even if they insert a duplicate of a cert that was
+ // already in the collection, we'll catch it because we remove the thumbprint from the
+ // local copy of the thumbprint list each time we use that thumbprint.
+
+ Debug.Assert(remainingOriginalThumbprints.Count == 0);
+ return false;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/CertificateCollectionDeltas.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/CertificateCollectionDeltas.cs
new file mode 100644
index 0000000000..c7e72ed6f8
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/CertificateCollectionDeltas.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Diagnostics;
+using System.Security.Cryptography.X509Certificates;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ class CertificateCollectionDeltas
+ {
+ public CertificateCollectionDeltas(X509Certificate2Collection currentCerts, List<string> originalThumbprints)
+ {
+ List<string> originalThumbprintsRemaining = new List<string>(originalThumbprints);
+
+ foreach (X509Certificate2 cert in currentCerts)
+ {
+ string thumbprint = cert.Thumbprint;
+
+ // If this cert isn't in the list of original certs, it must have been added
+ if (!originalThumbprints.Contains(thumbprint))
+ this.addedCerts.Add(cert);
+
+ // We've visited this thumbprint, so remove it from the list of unvisited thumbprints
+ originalThumbprintsRemaining.Remove(thumbprint);
+ }
+
+ foreach (string thumbprint in originalThumbprintsRemaining)
+ {
+ // these are the removed certs
+ }
+ }
+
+ public List<X509Certificate2> Inserted
+ {
+ get { return this.addedCerts; }
+ }
+
+ public List<X509Certificate2> Removed
+ {
+ get { return this.removedCerts; }
+ }
+
+ //
+ //
+ //
+ List<X509Certificate2> addedCerts = new List<X509Certificate2>();
+ List<X509Certificate2> removedCerts = new List<X509Certificate2>();
+
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Computer.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Computer.cs
new file mode 100644
index 0000000000..13e2e2af25
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Computer.cs
@@ -0,0 +1,191 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+using System.Security.Permissions;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="AuthenticablePrincipal" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ [DirectoryRdnPrefix("CN")]
+ public class ComputerPrincipal : AuthenticablePrincipal
+ {
+ //
+ // Public constructors
+ //
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ public ComputerPrincipal(PrincipalContext context) : base(context)
+ {
+ if (context == null)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ if (Context.ContextType == ContextType.ApplicationDirectory && this.GetType() == typeof(ComputerPrincipal))
+ throw new InvalidOperationException(StringResources.ComputerInvalidForAppDirectoryStore);
+
+ this.ContextRaw = context;
+ this.unpersisted = true;
+ }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ public ComputerPrincipal(PrincipalContext context, string samAccountName, string password, bool enabled) : this(context)
+ {
+ if (samAccountName == null || password == null)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ if (Context.ContextType == ContextType.ApplicationDirectory && this.GetType() == typeof(ComputerPrincipal))
+ throw new InvalidOperationException(StringResources.ComputerInvalidForAppDirectoryStore);
+
+ if (Context.ContextType != ContextType.ApplicationDirectory)
+ this.SamAccountName = samAccountName;
+
+ this.Name = samAccountName;
+ this.SetPassword(password);
+ this.Enabled = enabled;
+ }
+
+ //
+ // Public properties
+ //
+
+ // ServicePrincipalNames
+ private PrincipalValueCollection<string> _servicePrincipalNames = new PrincipalValueCollection<string>();
+ private LoadState _servicePrincipalNamesLoaded = LoadState.NotSet;
+
+ public PrincipalValueCollection<string> ServicePrincipalNames
+ {
+ get
+ {
+ return HandleGet<PrincipalValueCollection<string>>(ref _servicePrincipalNames, PropertyNames.ComputerServicePrincipalNames, ref _servicePrincipalNamesLoaded);
+ }
+ }
+
+ //
+ // Public methods
+ //
+ public static new PrincipalSearchResult<ComputerPrincipal> FindByLockoutTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByLockoutTime<ComputerPrincipal>(context, time, type);
+ }
+
+ public static new PrincipalSearchResult<ComputerPrincipal> FindByLogonTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByLogonTime<ComputerPrincipal>(context, time, type);
+ }
+
+ public static new PrincipalSearchResult<ComputerPrincipal> FindByExpirationTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByExpirationTime<ComputerPrincipal>(context, time, type);
+ }
+
+ public static new PrincipalSearchResult<ComputerPrincipal> FindByBadPasswordAttempt(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByBadPasswordAttempt<ComputerPrincipal>(context, time, type);
+ }
+
+ public static new PrincipalSearchResult<ComputerPrincipal> FindByPasswordSetTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByPasswordSetTime<ComputerPrincipal>(context, time, type);
+ }
+
+ public static new ComputerPrincipal FindByIdentity(PrincipalContext context, string identityValue)
+ {
+ return (ComputerPrincipal)FindByIdentityWithType(context, typeof(ComputerPrincipal), identityValue);
+ }
+
+ public static new ComputerPrincipal FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
+ {
+ return (ComputerPrincipal)FindByIdentityWithType(context, typeof(ComputerPrincipal), identityType, identityValue);
+ }
+
+ //
+ // Internal "constructor": Used for constructing Computer returned by a query
+ //
+ static internal ComputerPrincipal MakeComputer(PrincipalContext ctx)
+ {
+ ComputerPrincipal computer = new ComputerPrincipal(ctx);
+ computer.unpersisted = false;
+
+ return computer;
+ }
+
+ //
+ // Load/Store implementation
+ //
+
+ //
+ // Loading with query results
+ //
+ internal override void LoadValueIntoProperty(string propertyName, object value)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Computer", "LoadValueIntoProperty: name=" + propertyName + " value=" + (value == null ? "null" : value.ToString()));
+
+ switch (propertyName)
+ {
+ case (PropertyNames.ComputerServicePrincipalNames):
+ _servicePrincipalNames.Load((List<string>)value);
+ _servicePrincipalNamesLoaded = LoadState.Loaded;
+ break;
+
+ default:
+ base.LoadValueIntoProperty(propertyName, value);
+ break;
+ }
+ }
+
+ //
+ // Getting changes to persist (or to build a query from a QBE filter)
+ //
+
+ // Given a property name, returns true if that property has changed since it was loaded, false otherwise.
+ internal override bool GetChangeStatusForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Computer", "GetChangeStatusForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case (PropertyNames.ComputerServicePrincipalNames):
+ return _servicePrincipalNames.Changed;
+
+ default:
+ return base.GetChangeStatusForProperty(propertyName);
+ }
+ }
+
+ // Given a property name, returns the current value for the property.
+ internal override object GetValueForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Computer", "GetValueForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case (PropertyNames.ComputerServicePrincipalNames):
+ return _servicePrincipalNames;
+
+ default:
+ return base.GetValueForProperty(propertyName);
+ }
+ }
+
+ // Reset all change-tracking status for all properties on the object to "unchanged".
+ internal override void ResetAllChangeStatus()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Computer", "ResetAllChangeStatus");
+
+ _servicePrincipalNames.ResetTracking();
+
+ base.ResetAllChangeStatus();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ConfigurationHandler.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ConfigurationHandler.cs
new file mode 100644
index 0000000000..1da9bd21ee
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ConfigurationHandler.cs
@@ -0,0 +1,133 @@
+// 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.Collections;
+using System.Diagnostics;
+using System.Xml;
+using System.Configuration;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class ConfigurationHandler : IConfigurationSectionHandler
+ {
+ public virtual object Create(object parent, object configContext, XmlNode section)
+ {
+ ConfigSettings configSettings = null;
+ bool foundDebugging = false;
+ System.Enum debugLevelEnum = (System.Enum)GlobalConfig.DefaultDebugLevel;
+ string debugLogFile = null;
+
+ foreach (XmlNode child in section.ChildNodes)
+ {
+ switch (child.Name)
+ {
+#if DEBUG
+ case "Debugging":
+ if (foundDebugging)
+ throw new ConfigurationErrorsException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.ConfigHandlerConfigSectionsUnique,
+ "Debugging"));
+
+ RemoveEnumAttribute(child, "Debugging", "debugLevel", typeof(DebugLevel), ref debugLevelEnum);
+ RemoveStringAttribute(child, "Debugging", "debugLogFile", out debugLogFile);
+
+ foundDebugging = true;
+ break;
+#endif
+
+ default:
+ throw new ConfigurationErrorsException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.ConfigHandlerUnknownConfigSection,
+ child.Name));
+ }
+ }
+
+ if (foundDebugging)
+ configSettings = new ConfigSettings((DebugLevel)debugLevelEnum, debugLogFile);
+ else
+ configSettings = new ConfigSettings();
+
+ // We need to always return an object so if we haven't read the debug section just create a default object.
+ return (configSettings);
+ }
+
+#if DEBUG
+ private void RemoveEnumAttribute(XmlNode node, string sectionName, string attributeName, Type enumType, ref System.Enum value)
+ {
+ XmlNode attribute = node.Attributes.RemoveNamedItem(attributeName);
+ if (null != attribute)
+ {
+ try
+ {
+ // case-insensitive, for ease of use
+ value = (System.Enum)System.Enum.Parse(enumType, attribute.Value, true);
+ }
+ catch (ArgumentException)
+ {
+ throw new ConfigurationErrorsException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.ConfigHandlerInvalidEnumAttribute,
+ attributeName,
+ sectionName));
+ }
+ }
+ }
+
+ private void RemoveStringAttribute(XmlNode node, string sectionName, string attributeName, out string value)
+ {
+ value = null;
+ XmlNode attribute = node.Attributes.RemoveNamedItem(attributeName);
+ if (null != attribute)
+ {
+ value = attribute.Value as string;
+
+ if (value == null)
+ throw new ConfigurationErrorsException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.ConfigHandlerInvalidStringAttribute,
+ attributeName,
+ sectionName));
+
+ // Treat empty string the same as no string
+ if (value.Length == 0)
+ value = null;
+ }
+ }
+#endif
+ }
+
+ internal class ConfigSettings
+ {
+ public ConfigSettings(DebugLevel debugLevel, string debugLogFile)
+ {
+ _debugLevel = debugLevel;
+ _debugLogFile = debugLogFile;
+ }
+
+ public ConfigSettings() : this(GlobalConfig.DefaultDebugLevel, null)
+ {
+ }
+
+ public DebugLevel DebugLevel
+ {
+ get { return _debugLevel; }
+ }
+
+ public string DebugLogFile
+ {
+ get { return _debugLogFile; }
+ }
+
+ private DebugLevel _debugLevel = GlobalConfig.DefaultDebugLevel;
+ private string _debugLogFile = null;
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs
new file mode 100644
index 0000000000..8997180875
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs
@@ -0,0 +1,1310 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.ComponentModel;
+using System.Configuration;
+using System.DirectoryServices.Protocols;
+using System.DirectoryServices;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Collections;
+using System.Security.Permissions;
+
+[assembly: System.Security.SecurityCritical]
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal struct ServerProperties
+ {
+ public string dnsHostName;
+ public DomainControllerMode OsVersion;
+ public ContextType contextType;
+ public string[] SupportCapabilities;
+ public int portSSL;
+ public int portLDAP;
+ };
+
+ internal enum DomainControllerMode
+ {
+ Win2k = 0,
+ Win2k3 = 2,
+ WinLH = 3
+ };
+
+ static internal class CapabilityMap
+ {
+ public const string LDAP_CAP_ACTIVE_DIRECTORY_OID = "1.2.840.113556.1.4.800";
+ public const string LDAP_CAP_ACTIVE_DIRECTORY_V51_OID = "1.2.840.113556.1.4.1670";
+ public const string LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID = "1.2.840.113556.1.4.1791";
+ public const string LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID = "1.2.840.113556.1.4.1851";
+ public const string LDAP_CAP_ACTIVE_DIRECTORY_PARTIAL_SECRETS_OID = "1.2.840.113556.1.4.1920";
+ public const string LDAP_CAP_ACTIVE_DIRECTORY_V61_OID = "1.2.840.113556.1.4.1935";
+ }
+
+ internal sealed class CredentialValidator
+ {
+ private enum AuthMethod
+ {
+ Simple = 1,
+ Negotiate = 2
+ }
+
+ private bool _fastConcurrentSupported = true;
+
+ private Hashtable _connCache = new Hashtable(4);
+ private LdapDirectoryIdentifier _directoryIdent;
+ private object _cacheLock = new object();
+
+ private AuthMethod _lastBindMethod = AuthMethod.Simple;
+ private string _serverName;
+ private ContextType _contextType;
+ private ServerProperties _serverProperties;
+
+ private const ContextOptions defaultContextOptionsNegotiate = ContextOptions.Signing | ContextOptions.Sealing | ContextOptions.Negotiate;
+ private const ContextOptions defaultContextOptionsSimple = ContextOptions.SecureSocketLayer | ContextOptions.SimpleBind;
+
+ public CredentialValidator(ContextType contextType, string serverName, ServerProperties serverProperties)
+ {
+ _fastConcurrentSupported = !(serverProperties.OsVersion == DomainControllerMode.Win2k);
+
+ if (contextType == ContextType.Machine && serverName == null)
+ {
+ _serverName = Environment.MachineName;
+ }
+ else
+ {
+ _serverName = serverName;
+ }
+
+ _contextType = contextType;
+ _serverProperties = serverProperties;
+ }
+
+ [System.Security.SecurityCritical]
+ private bool BindSam(string target, string userName, string password)
+ {
+ StringBuilder adsPath = new StringBuilder();
+ adsPath.Append("WinNT://");
+ adsPath.Append(_serverName);
+ adsPath.Append(",computer");
+ Guid g = new Guid("fd8256d0-fd15-11ce-abc4-02608c9e7553"); // IID_IUnknown
+ object value = null;
+ // always attempt secure auth..
+ int authenticationType = 1;
+ object unmanagedResult = null;
+
+ try
+ {
+ if (Thread.CurrentThread.GetApartmentState() == ApartmentState.Unknown)
+ Thread.CurrentThread.SetApartmentState(ApartmentState.MTA);
+ // We need the credentials to be in the form <machine>\\<user>
+ // if they just passed user then append the machine name here.
+ if (null != userName)
+ {
+ int index = userName.IndexOf("\\", StringComparison.Ordinal);
+ if (index == -1)
+ {
+ userName = _serverName + "\\" + userName;
+ }
+ }
+
+ int hr = UnsafeNativeMethods.ADsOpenObject(adsPath.ToString(), userName, password, (int)authenticationType, ref g, out value);
+
+ if (hr != 0)
+ {
+ if (hr == unchecked((int)(ExceptionHelper.ERROR_HRESULT_LOGON_FAILURE)))
+ {
+ // This is the invalid credetials case. We want to return false
+ // instead of throwing an exception
+ return false;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(hr);
+ }
+ }
+
+ unmanagedResult = ((UnsafeNativeMethods.IADs)value).Get("name");
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)(ExceptionHelper.ERROR_HRESULT_LOGON_FAILURE)))
+ {
+ return false;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+ finally
+ {
+ if (value != null)
+ System.Runtime.InteropServices.Marshal.ReleaseComObject(value);
+ }
+
+ return true;
+ }
+
+ private bool BindLdap(NetworkCredential creds, ContextOptions contextOptions)
+ {
+ LdapConnection current = null;
+ bool useSSL = (ContextOptions.SecureSocketLayer & contextOptions) > 0;
+
+ if (_contextType == ContextType.ApplicationDirectory)
+ {
+ _directoryIdent = new LdapDirectoryIdentifier(_serverProperties.dnsHostName, useSSL ? _serverProperties.portSSL : _serverProperties.portLDAP);
+ }
+ else
+ {
+ _directoryIdent = new LdapDirectoryIdentifier(_serverName, useSSL ? LdapConstants.LDAP_SSL_PORT : LdapConstants.LDAP_PORT);
+ }
+
+ bool attemptFastConcurrent = useSSL && _fastConcurrentSupported;
+ int index = Convert.ToInt32(attemptFastConcurrent) * 2 + Convert.ToInt32(useSSL);
+
+ if (!_connCache.Contains(index))
+ {
+ lock (_cacheLock)
+ {
+ if (!_connCache.Contains(index))
+ {
+ current = new LdapConnection(_directoryIdent);
+ // First attempt to turn on SSL
+ current.SessionOptions.SecureSocketLayer = useSSL;
+
+ if (attemptFastConcurrent)
+ {
+ try
+ {
+ current.SessionOptions.FastConcurrentBind();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ current.Dispose();
+ current = null;
+ _fastConcurrentSupported = false;
+ index = Convert.ToInt32(useSSL);
+ current = new LdapConnection(_directoryIdent);
+ // We have fallen back to another connection so we need to set SSL again.
+ current.SessionOptions.SecureSocketLayer = useSSL;
+ }
+ }
+
+ _connCache.Add(index, current);
+ }
+ else
+ {
+ current = (LdapConnection)_connCache[index];
+ }
+ }
+ }
+ else
+ {
+ current = (LdapConnection)_connCache[index];
+ }
+
+ // If we are performing fastConcurrentBind there is no need to prevent multithreadaccess. FSB is thread safe and multi cred safe
+ // FSB also always has the same contextoptions so there is no need to lock the code that is modifying the current connection
+ if (attemptFastConcurrent && _fastConcurrentSupported)
+ {
+ lockedLdapBind(current, creds, contextOptions);
+ }
+ else
+ {
+ lock (_cacheLock)
+ {
+ lockedLdapBind(current, creds, contextOptions);
+ }
+ }
+ return true;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="LdapConnection.Bind():System.Void" />
+ // <SatisfiesLinkDemand Name="LdapConnection.Bind(System.Net.NetworkCredential):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ private void lockedLdapBind(LdapConnection current, NetworkCredential creds, ContextOptions contextOptions)
+ {
+ current.AuthType = ((ContextOptions.SimpleBind & contextOptions) > 0 ? AuthType.Basic : AuthType.Negotiate);
+ current.SessionOptions.Signing = ((ContextOptions.Signing & contextOptions) > 0 ? true : false);
+ current.SessionOptions.Sealing = ((ContextOptions.Sealing & contextOptions) > 0 ? true : false);
+ if ((null == creds.UserName) && (null == creds.Password))
+ {
+ current.Bind();
+ }
+ else
+ {
+ current.Bind(creds);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // <ReferencesCritical Name="Method: BindSam(String, String, String):Boolean" Ring="1" />
+ // <ReferencesCritical Name="Method: BindLdap(NetworkCredential, ContextOptions):Boolean" Ring="2" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ public bool Validate(string userName, string password)
+ {
+ NetworkCredential networkCredential = new NetworkCredential(userName, password);
+
+ // empty username and password on the local box
+ // causes authentication to succeed. If the username is empty we should just fail it
+ // here.
+ if (userName != null && userName.Length == 0)
+ return false;
+
+ if (_contextType == ContextType.Domain || _contextType == ContextType.ApplicationDirectory)
+ {
+ try
+ {
+ if (_lastBindMethod == AuthMethod.Simple && (_fastConcurrentSupported || _contextType == ContextType.ApplicationDirectory))
+ {
+ try
+ {
+ BindLdap(networkCredential, defaultContextOptionsSimple);
+ _lastBindMethod = AuthMethod.Simple;
+ return true;
+ }
+ catch (LdapException)
+ {
+ // we don't return false here even if we failed with ERROR_LOGON_FAILURE. We must check Negotiate
+ // because there might be cases in which SSL fails and Negotiate succeeds
+ }
+
+ BindLdap(networkCredential, defaultContextOptionsNegotiate);
+ _lastBindMethod = AuthMethod.Negotiate;
+ return true;
+ }
+ else
+ {
+ try
+ {
+ BindLdap(networkCredential, defaultContextOptionsNegotiate);
+ _lastBindMethod = AuthMethod.Negotiate;
+ return true;
+ }
+ catch (LdapException)
+ {
+ // we don't return false here even if we failed with ERROR_LOGON_FAILURE. We must check SSL
+ // because there might be cases in which Negotiate fails and SSL succeeds
+ }
+
+ BindLdap(networkCredential, defaultContextOptionsSimple);
+ _lastBindMethod = AuthMethod.Simple;
+ return true;
+ }
+ }
+ catch (LdapException ldapex)
+ {
+ // If we got here it means that both SSL and Negotiate failed. Tough luck.
+ if (ldapex.ErrorCode == ExceptionHelper.ERROR_LOGON_FAILURE)
+ {
+ return false;
+ }
+
+ throw;
+ }
+ }
+ else
+ {
+ Debug.Assert(_contextType == ContextType.Machine);
+ return (BindSam(_serverName, userName, password));
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // <ReferencesCritical Name="Method: BindSam(String, String, String):Boolean" Ring="1" />
+ // <ReferencesCritical Name="Method: BindLdap(NetworkCredential, ContextOptions):Boolean" Ring="2" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ public bool Validate(string userName, string password, ContextOptions connectionMethod)
+ {
+ // empty username and password on the local box
+ // causes authentication to succeed. If the username is empty we should just fail it
+ // here.
+ if (userName != null && userName.Length == 0)
+ return false;
+
+ if (_contextType == ContextType.Domain || _contextType == ContextType.ApplicationDirectory)
+ {
+ try
+ {
+ NetworkCredential networkCredential = new NetworkCredential(userName, password);
+ BindLdap(networkCredential, connectionMethod);
+ return true;
+ }
+ catch (LdapException ldapex)
+ {
+ if (ldapex.ErrorCode == ExceptionHelper.ERROR_LOGON_FAILURE)
+ {
+ return false;
+ }
+
+ throw;
+ }
+ }
+ else
+ {
+ return (BindSam(_serverName, userName, password));
+ }
+ }
+ }
+ // ********************************************
+ [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Assert,
+ Flags = System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)]
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ // [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted=true)]
+ public class PrincipalContext : IDisposable
+ {
+ //
+ // Public Constructors
+ //
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted = true)]
+ public PrincipalContext(ContextType contextType) :
+ this(contextType, null, null, PrincipalContext.GetDefaultOptionForStore(contextType), null, null)
+ { }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted = true)]
+ public PrincipalContext(ContextType contextType, string name) :
+ this(contextType, name, null, PrincipalContext.GetDefaultOptionForStore(contextType), null, null)
+ { }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted = true)]
+ public PrincipalContext(ContextType contextType, string name, string container) :
+ this(contextType, name, container, PrincipalContext.GetDefaultOptionForStore(contextType), null, null)
+ { }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted = true)]
+ public PrincipalContext(ContextType contextType, string name, string container, ContextOptions options) :
+ this(contextType, name, container, options, null, null)
+ { }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted = true)]
+ public PrincipalContext(ContextType contextType, string name, string userName, string password) :
+ this(contextType, name, null, PrincipalContext.GetDefaultOptionForStore(contextType), userName, password)
+ { }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted = true)]
+ public PrincipalContext(ContextType contextType, string name, string container, string userName, string password) :
+ this(contextType, name, container, PrincipalContext.GetDefaultOptionForStore(contextType), userName, password)
+ { }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted = true)]
+ public PrincipalContext(
+ ContextType contextType, string name, string container, ContextOptions options, string userName, string password)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "Entering ctor");
+
+ if ((userName == null && password != null) ||
+ (userName != null && password == null))
+ throw new ArgumentException(StringResources.ContextBadUserPwdCombo);
+
+ if ((options & ~(ContextOptions.Signing | ContextOptions.Negotiate | ContextOptions.Sealing | ContextOptions.SecureSocketLayer | ContextOptions.SimpleBind | ContextOptions.ServerBind)) != 0)
+ throw new InvalidEnumArgumentException("options", (int)options, typeof(ContextOptions));
+
+ if (contextType == ContextType.Machine && ((options & ~ContextOptions.Negotiate) != 0))
+ {
+ throw new ArgumentException(StringResources.InvalidContextOptionsForMachine);
+ }
+
+ if ((contextType == ContextType.Domain || contextType == ContextType.ApplicationDirectory) &&
+ (((options & (ContextOptions.Negotiate | ContextOptions.SimpleBind)) == 0) ||
+ (((options & (ContextOptions.Negotiate | ContextOptions.SimpleBind)) == ((ContextOptions.Negotiate | ContextOptions.SimpleBind))))))
+ {
+ throw new ArgumentException(StringResources.InvalidContextOptionsForAD);
+ }
+
+ if ((contextType != ContextType.Machine) &&
+ (contextType != ContextType.Domain) &&
+ (contextType != ContextType.ApplicationDirectory)
+#if TESTHOOK
+ && (contextType != ContextType.Test)
+#endif
+ )
+ {
+ throw new InvalidEnumArgumentException("contextType", (int)contextType, typeof(ContextType));
+ }
+
+ if ((contextType == ContextType.Machine) && (container != null))
+ throw new ArgumentException(StringResources.ContextNoContainerForMachineCtx);
+
+ if ((contextType == ContextType.ApplicationDirectory) && ((String.IsNullOrEmpty(container)) || (String.IsNullOrEmpty(name))))
+ throw new ArgumentException(StringResources.ContextNoContainerForApplicationDirectoryCtx);
+
+ _contextType = contextType;
+ _name = name;
+ _container = container;
+ _options = options;
+
+ _username = userName;
+ _password = password;
+
+ DoServerVerifyAndPropRetrieval();
+
+ _credValidate = new CredentialValidator(contextType, name, _serverProperties);
+ }
+
+ //
+ // Public Properties
+ //
+
+ public ContextType ContextType
+ {
+ get
+ {
+ CheckDisposed();
+
+ return _contextType;
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ CheckDisposed();
+
+ return _name;
+ }
+ }
+
+ public string Container
+ {
+ get
+ {
+ CheckDisposed();
+
+ return _container;
+ }
+ }
+
+ public string UserName
+ {
+ get
+ {
+ CheckDisposed();
+
+ return _username;
+ }
+ }
+
+ public ContextOptions Options
+ {
+ get
+ {
+ CheckDisposed();
+
+ return _options;
+ }
+ }
+
+ public string ConnectedServer
+ {
+ get
+ {
+ CheckDisposed();
+
+ Initialize();
+
+ // Unless we're not initialized, connectedServer should not be null
+ Debug.Assert(_connectedServer != null || _initialized == false);
+
+ // connectedServer should never be an empty string
+ Debug.Assert(_connectedServer == null || _connectedServer.Length != 0);
+
+ return _connectedServer;
+ }
+ }
+
+ /// <summary>
+ /// Validate the passed credentials against the directory supplied.
+ // This function will use the best determined method to do the evaluation
+ /// </summary>
+
+ public bool ValidateCredentials(string userName, string password)
+ {
+ CheckDisposed();
+
+ if ((userName == null && password != null) ||
+ (userName != null && password == null))
+ throw new ArgumentException(StringResources.ContextBadUserPwdCombo);
+
+#if TESTHOOK
+ if ( contextType == ContextType.Test )
+ {
+ return true;
+ }
+#endif
+
+ return (_credValidate.Validate(userName, password));
+ }
+
+ /// <summary>
+ /// Validate the passed credentials against the directory supplied.
+ // The supplied options will determine the directory method for credential validation.
+ /// </summary>
+ public bool ValidateCredentials(string userName, string password, ContextOptions options)
+ {
+ // Perform credential validation using fast concurrent bind...
+ CheckDisposed();
+
+ if ((userName == null && password != null) ||
+ (userName != null && password == null))
+ throw new ArgumentException(StringResources.ContextBadUserPwdCombo);
+
+ if (options != ContextOptions.Negotiate && _contextType == ContextType.Machine)
+ throw new ArgumentException(StringResources.ContextOptionsNotValidForMachineStore);
+
+#if TESTHOOK
+ if ( contextType == ContextType.Test )
+ {
+ return true;
+ }
+#endif
+
+ return (_credValidate.Validate(userName, password, options));
+ }
+
+ //
+ // Private methods for initialization
+ //
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ private void Initialize()
+ {
+ if (!_initialized)
+ {
+ lock (_initializationLock)
+ {
+ if (_initialized)
+ return;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "Initializing Context");
+
+ switch (_contextType)
+ {
+ case ContextType.Domain:
+ DoDomainInit();
+ break;
+
+ case ContextType.Machine:
+ DoMachineInit();
+ break;
+
+ case ContextType.ApplicationDirectory:
+ DoApplicationDirectoryInit();
+ break;
+#if TESTHOOK
+ case ContextType.Test:
+ // do nothing
+ break;
+#endif
+ default:
+ // Internal error
+ Debug.Fail("PrincipalContext.Initialize: fell off end looking for " + _contextType.ToString());
+ break;
+ }
+
+ _initialized = true;
+ }
+ }
+ }
+
+ private void DoApplicationDirectoryInit()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "Entering DoApplicationDirecotryInit");
+
+ Debug.Assert(_contextType == ContextType.ApplicationDirectory);
+
+ if (_container == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoApplicationDirecotryInit: using no-container path");
+ DoLDAPDirectoryInitNoContainer();
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoApplicationDirecotryInit: using container path");
+ DoLDAPDirectoryInit();
+ }
+ }
+
+ private void DoMachineInit()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "Entering DoMachineInit");
+
+ Debug.Assert(_contextType == ContextType.Machine);
+ Debug.Assert(_container == null);
+
+ DirectoryEntry de = null;
+
+ try
+ {
+ string hostname = _name;
+
+ if (hostname == null)
+ hostname = Utils.GetComputerFlatName();
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoMachineInit: hostname is " + hostname);
+
+ // use the options they specified
+ AuthenticationTypes authTypes = SDSUtils.MapOptionsToAuthTypes(_options);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoMachineInit: authTypes is " + authTypes.ToString());
+
+ de = new DirectoryEntry("WinNT://" + hostname + ",computer", _username, _password, authTypes);
+
+ // Force ADSI to connect so we detect if the server is down or if the servername is invalid
+ de.RefreshCache();
+
+ StoreCtx storeCtx = CreateContextFromDirectoryEntry(de);
+
+ _queryCtx = storeCtx;
+ _userCtx = storeCtx;
+ _groupCtx = storeCtx;
+ _computerCtx = storeCtx;
+
+ _connectedServer = hostname;
+ de = null;
+ }
+ catch (Exception e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "PrincipalContext",
+ "DoMachineInit: caught exception of type "
+ + e.GetType().ToString() +
+ " and message " + e.Message);
+
+ // Cleanup the DE on failure
+ if (de != null)
+ de.Dispose();
+
+ throw;
+ }
+ }
+
+ private void DoDomainInit()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "Entering DoDomainInit");
+
+ Debug.Assert(_contextType == ContextType.Domain);
+
+ if (_container == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoDomainInit: using no-container path");
+ DoLDAPDirectoryInitNoContainer();
+ return;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoDomainInit: using container path");
+ DoLDAPDirectoryInit();
+ return;
+ }
+ }
+
+ private void DoServerVerifyAndPropRetrieval()
+ {
+ _serverProperties = new ServerProperties();
+ if (_contextType == ContextType.ApplicationDirectory || _contextType == ContextType.Domain)
+ {
+ ReadServerConfig(_name, ref _serverProperties);
+
+ if (_serverProperties.contextType != _contextType)
+ {
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, StringResources.PassedContextTypeDoesNotMatchDetectedType, _serverProperties.contextType.ToString()));
+ }
+ }
+ }
+
+ private void DoLDAPDirectoryInit()
+ {
+ // use the servername if they gave us one, else let ADSI figure it out
+ string serverName = "";
+
+ if (_name != null)
+ {
+ if (_contextType == ContextType.ApplicationDirectory)
+ {
+ serverName = _serverProperties.dnsHostName + ":" +
+ ((ContextOptions.SecureSocketLayer & _options) > 0 ? _serverProperties.portSSL : _serverProperties.portLDAP);
+ }
+ else
+ {
+ serverName = _name;
+ }
+
+ serverName += "/";
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInit: serverName is " + serverName);
+
+ // use the options they specified
+ AuthenticationTypes authTypes = SDSUtils.MapOptionsToAuthTypes(_options);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInit: authTypes is " + authTypes.ToString());
+
+ DirectoryEntry de = new DirectoryEntry("LDAP://" + serverName + _container, _username, _password, authTypes);
+
+ try
+ {
+ // Set the password port to the ssl port read off of the rootDSE. Without this
+ // password change/set won't work when we connect without SSL and ADAM is running
+ // on non-standard port numbers. We have already verified directory connectivity at this point
+ // so this should always succeed.
+ if (_serverProperties.portSSL > 0)
+ {
+ de.Options.PasswordPort = _serverProperties.portSSL;
+ }
+
+ StoreCtx storeCtx = CreateContextFromDirectoryEntry(de);
+
+ _queryCtx = storeCtx;
+ _userCtx = storeCtx;
+ _groupCtx = storeCtx;
+ _computerCtx = storeCtx;
+
+ _connectedServer = ADUtils.GetServerName(de);
+ de = null;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ catch (Exception e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "PrincipalContext",
+ "DoLDAPDirectoryInit: caught exception of type "
+ + e.GetType().ToString() +
+ " and message " + e.Message);
+
+ throw;
+ }
+ finally
+ {
+ // Cleanup the DE on failure
+ if (de != null)
+ de.Dispose();
+ }
+ }
+
+ private void DoLDAPDirectoryInitNoContainer()
+ {
+ byte[] USERS_CONTAINER_GUID = new byte[] { 0xa9, 0xd1, 0xca, 0x15, 0x76, 0x88, 0x11, 0xd1, 0xad, 0xed, 0x00, 0xc0, 0x4f, 0xd8, 0xd5, 0xcd };
+ byte[] COMPUTERS_CONTAINER_GUID = new byte[] { 0xaa, 0x31, 0x28, 0x25, 0x76, 0x88, 0x11, 0xd1, 0xad, 0xed, 0x00, 0xc0, 0x4f, 0xd8, 0xd5, 0xcd };
+
+ // The StoreCtxs that will be used in the PrincipalContext, and their associated DirectoryEntry objects.
+ DirectoryEntry deUserGroupOrg = null;
+ DirectoryEntry deComputer = null;
+ DirectoryEntry deBase = null;
+
+ ADStoreCtx storeCtxUserGroupOrg = null;
+ ADStoreCtx storeCtxComputer = null;
+ ADStoreCtx storeCtxBase = null;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "Entering DoLDAPDirectoryInitNoContainer");
+
+ //
+ // Build a DirectoryEntry that represents the root of the domain.
+ //
+
+ // Use the RootDSE to find the default naming context
+ DirectoryEntry deRootDse = null;
+ string adsPathBase;
+
+ // use the servername if they gave us one, else let ADSI figure it out
+ string serverName = "";
+ if (_name != null)
+ {
+ serverName = _name + "/";
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInitNoContainer: serverName is " + serverName);
+
+ // use the options they specified
+ AuthenticationTypes authTypes = SDSUtils.MapOptionsToAuthTypes(_options);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInitNoContainer: authTypes is " + authTypes.ToString());
+
+ try
+ {
+ deRootDse = new DirectoryEntry("LDAP://" + serverName + "rootDse", _username, _password, authTypes);
+
+ // This will also detect if the server is down or nonexistent
+ string domainNC = (string)deRootDse.Properties["defaultNamingContext"][0];
+ adsPathBase = "LDAP://" + serverName + domainNC;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInitNoContainer: domainNC is " + domainNC);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInitNoContainer: adsPathBase is " + adsPathBase);
+ }
+ finally
+ {
+ // Don't allow the DE to leak
+ if (deRootDse != null)
+ deRootDse.Dispose();
+ }
+
+ try
+ {
+ // Build a DE for the root of the domain using the retrieved naming context
+ deBase = new DirectoryEntry(adsPathBase, _username, _password, authTypes);
+
+ // Set the password port to the ssl port read off of the rootDSE. Without this
+ // password change/set won't work when we connect without SSL and ADAM is running
+ // on non-standard port numbers. We have already verified directory connectivity at this point
+ // so this should always succeed.
+ if (_serverProperties.portSSL > 0)
+ {
+ deBase.Options.PasswordPort = _serverProperties.portSSL;
+ }
+
+ //
+ // Use the wellKnownObjects attribute to determine the default location
+ // for users and computers.
+ //
+ string adsPathUserGroupOrg = null;
+ string adsPathComputer = null;
+
+ PropertyValueCollection wellKnownObjectValues = deBase.Properties["wellKnownObjects"];
+
+ foreach (UnsafeNativeMethods.IADsDNWithBinary value in wellKnownObjectValues)
+ {
+ if (Utils.AreBytesEqual(USERS_CONTAINER_GUID, (byte[])value.BinaryValue))
+ {
+ Debug.Assert(adsPathUserGroupOrg == null);
+ adsPathUserGroupOrg = "LDAP://" + serverName + value.DNString;
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "PrincipalContext",
+ "DoLDAPDirectoryInitNoContainer: found USER, adsPathUserGroupOrg is " + adsPathUserGroupOrg);
+ }
+
+ // Is it the computer container?
+ if (Utils.AreBytesEqual(COMPUTERS_CONTAINER_GUID, (byte[])value.BinaryValue))
+ {
+ Debug.Assert(adsPathComputer == null);
+ adsPathComputer = "LDAP://" + serverName + value.DNString;
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "PrincipalContext",
+ "DoLDAPDirectoryInitNoContainer: found COMPUTER, adsPathComputer is " + adsPathComputer);
+ }
+ }
+
+ if ((adsPathUserGroupOrg == null) || (adsPathComputer == null))
+ {
+ // Something's wrong with the domain, it's not exposing the proper
+ // well-known object fields.
+ throw new PrincipalOperationException(StringResources.ContextNoWellKnownObjects);
+ }
+
+ //
+ // Build DEs for the Users and Computers containers.
+ // The Users container will also be used as the default for Groups.
+ // The reason there are different contexts for groups, users and computers is so that
+ // when a principal is created it will go into the appropriate default container. This is so users don't
+ // be default create principals in the root of their directory. When a search happens the base context is used so that
+ // the whole directory will be covered.
+ //
+ deUserGroupOrg = new DirectoryEntry(adsPathUserGroupOrg, _username, _password, authTypes);
+ deComputer = new DirectoryEntry(adsPathComputer, _username, _password, authTypes);
+
+ StoreCtx userStore = CreateContextFromDirectoryEntry(deUserGroupOrg);
+
+ _userCtx = userStore;
+ _groupCtx = userStore;
+ deUserGroupOrg = null; // since we handed off ownership to the StoreCtx
+
+ _computerCtx = CreateContextFromDirectoryEntry(deComputer);
+
+ deComputer = null;
+
+ _queryCtx = CreateContextFromDirectoryEntry(deBase);
+
+ _connectedServer = ADUtils.GetServerName(deBase);
+
+ deBase = null;
+ }
+ catch (Exception e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "PrincipalContext",
+ "DoLDAPDirectoryInitNoContainer: caught exception of type "
+ + e.GetType().ToString() +
+ " and message " + e.Message);
+
+ // Cleanup on failure. Once a DE has been successfully handed off to a ADStoreCtx,
+ // that ADStoreCtx will handle Dispose()'ing it
+ if (deUserGroupOrg != null)
+ deUserGroupOrg.Dispose();
+
+ if (deComputer != null)
+ deComputer.Dispose();
+
+ if (deBase != null)
+ deBase.Dispose();
+
+ if (storeCtxUserGroupOrg != null)
+ storeCtxUserGroupOrg.Dispose();
+
+ if (storeCtxComputer != null)
+ storeCtxComputer.Dispose();
+
+ if (storeCtxBase != null)
+ storeCtxBase.Dispose();
+
+ throw;
+ }
+ }
+
+#if TESTHOOK
+
+ static public PrincipalContext Test
+ {
+ get
+ {
+ StoreCtx storeCtx = new TestStoreCtx(true);
+ PrincipalContext ctx = new PrincipalContext(ContextType.Test);
+ ctx.SetupContext(storeCtx);
+ ctx.initialized = true;
+
+ storeCtx.OwningContext = ctx;
+ return ctx;
+ }
+ }
+
+ static public PrincipalContext TestAltValidation
+ {
+ get
+ {
+ TestStoreCtx storeCtx = new TestStoreCtx(true);
+ storeCtx.SwitchValidationMode = true;
+ PrincipalContext ctx = new PrincipalContext(ContextType.Test);
+ ctx.SetupContext(storeCtx);
+ ctx.initialized = true;
+
+ storeCtx.OwningContext = ctx;
+ return ctx;
+ }
+ }
+
+ static public PrincipalContext TestNoTimeLimited
+ {
+ get
+ {
+ TestStoreCtx storeCtx = new TestStoreCtx(true);
+ storeCtx.SupportTimeLimited = false;
+ PrincipalContext ctx = new PrincipalContext(ContextType.Test);
+ ctx.SetupContext(storeCtx);
+ ctx.initialized = true;
+
+ storeCtx.OwningContext = ctx;
+ return ctx;
+ }
+ }
+
+#endif // TESTHOOK
+
+ //
+ // Public Methods
+ //
+
+ public void Dispose()
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "Dispose: disposing");
+
+ // Note that we may end up calling Dispose multiple times on the same
+ // StoreCtx (since, for example, it might be that userCtx == groupCtx).
+ // This is okay, since StoreCtxs allow multiple Dispose() calls, and ignore
+ // all but the first call.
+
+ if (_userCtx != null)
+ _userCtx.Dispose();
+
+ if (_groupCtx != null)
+ _groupCtx.Dispose();
+
+ if (_computerCtx != null)
+ _computerCtx.Dispose();
+
+ if (_queryCtx != null)
+ _queryCtx.Dispose();
+
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ //
+ // Private Implementation
+ //
+
+ // Are we initialized?
+ private bool _initialized = false;
+ private object _initializationLock = new object();
+
+ // Have we been disposed?
+ private bool _disposed = false;
+ internal bool Disposed { get { return _disposed; } }
+
+ // Our constructor parameters
+
+ // encryption nor zeroing out the string when you're done with it.
+ private string _username;
+ private string _password;
+
+ // Cached connections to the server for fast credential validation
+ private CredentialValidator _credValidate;
+ private ServerProperties _serverProperties;
+
+ internal ServerProperties ServerInformation
+ {
+ get
+ {
+ return _serverProperties;
+ }
+ }
+
+ private string _name;
+ private string _container;
+ private ContextOptions _options;
+ private ContextType _contextType;
+
+ // The server we're connected to
+ private string _connectedServer = null;
+
+ // The reason there are different contexts for groups, users and computers is so that
+ // when a principal is created it will go into the appropriate default container. This is so users don't
+ // by default create principals in the root of their directory. When a search happens the base context is used so that
+ // the whole directory will be covered. User and Computers default are the same ( USERS container ), Computers are
+ // put under COMPUTERS container. If a container is specified then all the contexts will point to the same place.
+
+ // The StoreCtx to be used when inserting a new User/Computer/Group Principal into this
+ // PrincipalContext.
+ private StoreCtx _userCtx = null;
+ private StoreCtx _computerCtx = null;
+ private StoreCtx _groupCtx = null;
+
+ // The StoreCtx to be used when querying against this PrincipalContext for Principals
+ private StoreCtx _queryCtx = null;
+
+ internal StoreCtx QueryCtx
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ Initialize();
+ return _queryCtx;
+ }
+
+ set
+ {
+ _queryCtx = value;
+ }
+ }
+
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal void ReadServerConfig(string serverName, ref ServerProperties properties)
+ {
+ string[] proplist = new string[] { "msDS-PortSSL", "msDS-PortLDAP", "domainControllerFunctionality", "dnsHostName", "supportedCapabilities" };
+ LdapConnection ldapConnection = null;
+
+ try
+ {
+ bool useSSL = (_options & ContextOptions.SecureSocketLayer) > 0;
+
+ if (useSSL && _contextType == ContextType.Domain)
+ {
+ LdapDirectoryIdentifier directoryid = new LdapDirectoryIdentifier(serverName, LdapConstants.LDAP_SSL_PORT);
+ ldapConnection = new LdapConnection(directoryid);
+ }
+ else
+ {
+ ldapConnection = new LdapConnection(serverName);
+ }
+
+ ldapConnection.AutoBind = false;
+ // If SSL was enabled on the initial connection then turn it on for the search.
+ // This is requried bc the appended port number will be SSL and we don't know what port LDAP is running on.
+ ldapConnection.SessionOptions.SecureSocketLayer = useSSL;
+
+ string baseDN = null; // specify base as null for RootDSE search
+ string ldapSearchFilter = "(objectClass=*)";
+ SearchResponse searchResponse = null;
+
+ SearchRequest searchRequest = new SearchRequest(baseDN, ldapSearchFilter, System.DirectoryServices.Protocols
+ .SearchScope.Base, proplist);
+
+ try
+ {
+ searchResponse = (SearchResponse)ldapConnection.SendRequest(searchRequest);
+ }
+ catch (LdapException ex)
+ {
+ throw new PrincipalServerDownException(StringResources.ServerDown, ex);
+ }
+
+ // Fill in the struct with the casted properties from the serach results.
+ // there will always be only 1 item on the rootDSE so all entry indexes are 0
+ properties.dnsHostName = (string)searchResponse.Entries[0].Attributes["dnsHostName"][0];
+ properties.SupportCapabilities = new string[searchResponse.Entries[0].Attributes["supportedCapabilities"].Count];
+ for (int i = 0; i < searchResponse.Entries[0].Attributes["supportedCapabilities"].Count; i++)
+ {
+ properties.SupportCapabilities[i] = (string)searchResponse.Entries[0].Attributes["supportedCapabilities"][i];
+ }
+
+ foreach (string capability in properties.SupportCapabilities)
+ {
+ if (CapabilityMap.LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID == capability)
+ {
+ properties.contextType = ContextType.ApplicationDirectory;
+ }
+ else if (CapabilityMap.LDAP_CAP_ACTIVE_DIRECTORY_OID == capability)
+ {
+ properties.contextType = ContextType.Domain;
+ }
+ }
+
+ // If we can't determine the OS vesion so we must fall back to lowest level of functionality
+ if (searchResponse.Entries[0].Attributes.Contains("domainControllerFunctionality"))
+ {
+ properties.OsVersion = (DomainControllerMode)Convert.ToInt32(searchResponse.Entries[0].Attributes["domainControllerFunctionality"][0], CultureInfo.InvariantCulture);
+ }
+ else
+ {
+ properties.OsVersion = DomainControllerMode.Win2k;
+ }
+
+ if (properties.contextType == ContextType.ApplicationDirectory)
+ {
+ if (searchResponse.Entries[0].Attributes.Contains("msDS-PortSSL"))
+ {
+ properties.portSSL = Convert.ToInt32(searchResponse.Entries[0].Attributes["msDS-PortSSL"][0]);
+ }
+ if (searchResponse.Entries[0].Attributes.Contains("msDS-PortLDAP"))
+ {
+ properties.portLDAP = Convert.ToInt32(searchResponse.Entries[0].Attributes["msDS-PortLDAP"][0]);
+ }
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ReadServerConfig", "OsVersion : " + properties.OsVersion.ToString());
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ReadServerConfig", "dnsHostName : " + properties.dnsHostName);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ReadServerConfig", "contextType : " + properties.contextType.ToString());
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ReadServerConfig", "portSSL : " + properties.portSSL.ToString(CultureInfo.InvariantCulture));
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ReadServerConfig", "portLDAP :" + properties.portLDAP.ToString(CultureInfo.InvariantCulture));
+ }
+ finally
+ {
+ if (ldapConnection != null)
+ {
+ ldapConnection.Dispose();
+ }
+ }
+ }
+
+ private StoreCtx CreateContextFromDirectoryEntry(DirectoryEntry entry)
+ {
+ StoreCtx storeCtx;
+
+ Debug.Assert(entry != null);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "CreateContextFromDirectoryEntry: path is " + entry.Path);
+
+ if (entry.Path.StartsWith("LDAP:", StringComparison.Ordinal))
+ {
+ if (this.ContextType == ContextType.ApplicationDirectory)
+ {
+ storeCtx = new ADAMStoreCtx(entry, true, _username, _password, _name, _options);
+ }
+ else
+ {
+ storeCtx = new ADStoreCtx(entry, true, _username, _password, _options);
+ }
+ }
+ else
+ {
+ Debug.Assert(entry.Path.StartsWith("WinNT:", StringComparison.Ordinal));
+ storeCtx = new SAMStoreCtx(entry, true, _username, _password, _options);
+ }
+
+ storeCtx.OwningContext = this;
+ return storeCtx;
+ }
+
+ // Checks if we're already been disposed, and throws an appropriate
+ // exception if so.
+ internal void CheckDisposed()
+ {
+ if (_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalContext", "CheckDisposed: accessing disposed object");
+
+ throw new ObjectDisposedException("PrincipalContext");
+ }
+ }
+
+ // Match the default context options to the store type.
+ private static ContextOptions GetDefaultOptionForStore(ContextType storeType)
+ {
+ if (storeType == ContextType.Machine)
+ {
+ return DefaultContextOptions.MachineDefaultContextOption;
+ }
+ else
+ {
+ Debug.Assert(storeType == ContextType.Domain || storeType == ContextType.ApplicationDirectory);
+ return DefaultContextOptions.ADDefaultContextOption;
+ }
+ }
+
+ // Helper method: given a typeof(User/Computer/etc.), returns the userCtx/computerCtx/etc.
+ internal StoreCtx ContextForType(Type t)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "ContextForType: type is " + t.ToString());
+
+ Initialize();
+
+ if (t == typeof(System.DirectoryServices.AccountManagement.UserPrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.UserPrincipal)))
+ {
+ return _userCtx;
+ }
+ else if (t == typeof(System.DirectoryServices.AccountManagement.ComputerPrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.ComputerPrincipal)))
+ {
+ return _computerCtx;
+ }
+ else if (t == typeof(System.DirectoryServices.AccountManagement.AuthenticablePrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.AuthenticablePrincipal)))
+ {
+ return _userCtx;
+ }
+ else
+ {
+ Debug.Assert(t == typeof(System.DirectoryServices.AccountManagement.GroupPrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.GroupPrincipal)));
+ return _groupCtx;
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ContextOptions.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ContextOptions.cs
new file mode 100644
index 0000000000..2495d6b2f8
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ContextOptions.cs
@@ -0,0 +1,20 @@
+// 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;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [Flags]
+ public enum ContextOptions
+ {
+ Negotiate = 1,
+ SimpleBind = 2,
+ SecureSocketLayer = 4,
+ Signing = 8,
+ Sealing = 16,
+ ServerBind = 32,
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ContextType.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ContextType.cs
new file mode 100644
index 0000000000..d59f7914a7
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ContextType.cs
@@ -0,0 +1,21 @@
+// 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;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ public enum ContextType
+ {
+ Machine = 0,
+ Domain = 1,
+#if TESTHOOK
+ ApplicationDirectory = 2,
+ Test = 3
+#else
+ ApplicationDirectory = 2
+#endif // TESTHOOK
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/CredentialTypes.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/CredentialTypes.cs
new file mode 100644
index 0000000000..be4c31bff5
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/CredentialTypes.cs
@@ -0,0 +1,15 @@
+// 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;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [Flags]
+ internal enum CredentialTypes
+ {
+ Password = 1,
+ Certificate = 2
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/EmptySet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/EmptySet.cs
new file mode 100644
index 0000000000..5613ec4aed
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/EmptySet.cs
@@ -0,0 +1,51 @@
+// 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.Diagnostics;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class EmptySet : BookmarkableResultSet
+ {
+ internal EmptySet()
+ {
+ // Nothing to do
+ }
+
+ override internal object CurrentAsPrincipal
+ {
+ get
+ {
+ Debug.Fail("EmptySet.CurrentAsPrincipal: Shouldn't be here");
+ return null;
+ }
+ }
+ override internal bool MoveNext()
+ {
+ // Mimic an empty set
+ return false;
+ }
+
+ override internal void Reset()
+ {
+ // Nothing to do
+ }
+
+ override internal ResultSetBookmark BookmarkAndReset()
+ {
+ return new EmptySetBookmark();
+ }
+
+ override internal void RestoreBookmark(ResultSetBookmark bookmark)
+ {
+ // Nothing to do
+ }
+ }
+
+ internal class EmptySetBookmark : ResultSetBookmark
+ {
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionAttributes.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionAttributes.cs
new file mode 100644
index 0000000000..9d0f02005e
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionAttributes.cs
@@ -0,0 +1,95 @@
+// 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.Collections.Generic;
+using System.Text;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
+ public sealed class DirectoryPropertyAttribute : Attribute
+ {
+ private string _schemaAttributeName;
+ private Nullable<ContextType> _context;
+ public DirectoryPropertyAttribute(string schemaAttributeName)
+ {
+ _schemaAttributeName = schemaAttributeName;
+ _context = null;
+ }
+ public string SchemaAttributeName
+ {
+ get
+ {
+ return _schemaAttributeName;
+ }
+ }
+ public Nullable<ContextType> Context
+ {
+ get
+ {
+ return _context;
+ }
+ set
+ {
+ _context = value;
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public sealed class DirectoryRdnPrefixAttribute : Attribute
+ {
+ private string _rdnPrefix;
+ private Nullable<ContextType> _context;
+
+ public DirectoryRdnPrefixAttribute(string rdnPrefix)
+ {
+ _rdnPrefix = rdnPrefix;
+ _context = null;
+ }
+ public string RdnPrefix
+ {
+ get
+ {
+ return _rdnPrefix;
+ }
+ }
+ public Nullable<ContextType> Context
+ {
+ get
+ {
+ return _context;
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public sealed class DirectoryObjectClassAttribute : Attribute
+ {
+ private string _objectClass;
+ private Nullable<ContextType> _context;
+
+ public DirectoryObjectClassAttribute(string objectClass)
+ {
+ _objectClass = objectClass;
+ _context = null;
+ }
+ public string ObjectClass
+ {
+ get
+ {
+ return _objectClass;
+ }
+ }
+ public Nullable<ContextType> Context
+ {
+ get
+ {
+ return _context;
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionCache.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionCache.cs
new file mode 100644
index 0000000000..6760bf0858
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionCache.cs
@@ -0,0 +1,70 @@
+// 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.AccountManagement
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections;
+ using System.DirectoryServices;
+
+ internal class ExtensionCacheValue
+ {
+ internal ExtensionCacheValue(object[] value)
+ {
+ _value = value;
+ _filterOnly = false;
+ }
+
+ internal ExtensionCacheValue(object[] value, Type type, MatchType matchType)
+ {
+ _value = value;
+ _type = type;
+ _matchType = matchType;
+ _filterOnly = true;
+ }
+
+ internal object[] Value
+ {
+ get { return _value; }
+ }
+ internal bool Filter
+ {
+ get { return _filterOnly; }
+ }
+ internal Type Type
+ {
+ get { return _type; }
+ }
+ internal MatchType MatchType
+ {
+ get { return _matchType; }
+ }
+
+ private object[] _value;
+ private bool _filterOnly;
+ private Type _type;
+ private MatchType _matchType;
+ }
+
+ internal class ExtensionCache
+ {
+ private Dictionary<string, ExtensionCacheValue> _cache = new Dictionary<string, ExtensionCacheValue>();
+
+ internal ExtensionCache() { }
+
+ internal bool TryGetValue(string attr, out ExtensionCacheValue o)
+ {
+ return (_cache.TryGetValue(attr, out o));
+ }
+
+ internal Dictionary<string, ExtensionCacheValue> properties
+ {
+ get
+ {
+ return _cache;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionHelper.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionHelper.cs
new file mode 100644
index 0000000000..b77df381a4
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExtensionHelper.cs
@@ -0,0 +1,144 @@
+// 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.Collections.Generic;
+using System.Text;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class ExtensionHelper
+ {
+ internal ExtensionHelper(Principal p)
+ {
+ _p = p;
+ }
+
+ private Principal _p;
+
+ internal string RdnPrefix
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.get_ContextType():System.DirectoryServices.AccountManagement.ContextType" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ DirectoryRdnPrefixAttribute[] MyAttribute =
+ (DirectoryRdnPrefixAttribute[])Attribute.GetCustomAttributes(_p.GetType(), typeof(DirectoryRdnPrefixAttribute), false);
+
+ if (MyAttribute == null)
+ return null;
+
+ string defaultRdn = null;
+
+ for (int i = 0; i < MyAttribute.Length; i++)
+ {
+ if (MyAttribute[i].Context == null && null == defaultRdn)
+ {
+ defaultRdn = MyAttribute[i].RdnPrefix;
+ }
+ if (_p.ContextType == MyAttribute[i].Context)
+ {
+ return MyAttribute[i].RdnPrefix;
+ }
+ }
+
+ return defaultRdn;
+ }
+ }
+
+ static internal string ReadStructuralObjectClass(Type principalType)
+ {
+ DirectoryObjectClassAttribute[] MyAttribute =
+ (DirectoryObjectClassAttribute[])Attribute.GetCustomAttributes(principalType, typeof(DirectoryObjectClassAttribute), false);
+
+ if (MyAttribute == null)
+ return null;
+
+ string defaultObjectClass = null;
+
+ for (int i = 0; i < MyAttribute.Length; i++)
+ {
+ if (MyAttribute[i].Context == null && null == defaultObjectClass)
+ {
+ defaultObjectClass = MyAttribute[i].ObjectClass;
+ }
+ /*
+ if (p.ContextType == MyAttribute[i].Context)
+ {
+ return MyAttribute[i].ObjectClass;
+ }
+ */
+ }
+
+ return defaultObjectClass;
+ }
+
+ internal string StructuralObjectClass
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.get_ContextType():System.DirectoryServices.AccountManagement.ContextType" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ DirectoryObjectClassAttribute[] MyAttribute =
+ (DirectoryObjectClassAttribute[])Attribute.GetCustomAttributes(_p.GetType(), typeof(DirectoryObjectClassAttribute), false);
+
+ if (MyAttribute == null)
+ return null;
+
+ string defaultObjectClass = null;
+
+ for (int i = 0; i < MyAttribute.Length; i++)
+ {
+ if (MyAttribute[i].Context == null && null == defaultObjectClass)
+ {
+ defaultObjectClass = MyAttribute[i].ObjectClass;
+ }
+ if (_p.ContextType == MyAttribute[i].Context)
+ {
+ return MyAttribute[i].ObjectClass;
+ }
+ }
+
+ return defaultObjectClass;
+ }
+ }
+ /*
+ internal string SchemaAttributeName(string propertyName)
+ {
+ System.Reflection.PropertyInfo propInfo = this.GetType().GetProperty(propertyName);
+
+ if ( null == propInfo )
+ return null;
+
+ DirectoryPropertyAttribute[] MyAttribute = (DirectoryPropertyAttribute[])Attribute.GetCustomAttributes(propInfo, typeof(DirectoryPropertyAttribute));
+
+ if (MyAttribute == null)
+ return null;
+
+ string defaultAttribute = null;
+
+ for (int i = 0; i < MyAttribute.Length; i++)
+ {
+ if (MyAttribute[i].Context == null)
+ {
+ defaultAttribute = MyAttribute[i].SchemaAttributeName;
+ }
+ if (p.ContextType == MyAttribute[i].Context)
+ {
+ return MyAttribute[i].SchemaAttributeName;
+ }
+ }
+
+ return defaultAttribute;
+
+ }
+ */
+
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExternDll.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExternDll.cs
new file mode 100644
index 0000000000..6877ccedf6
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ExternDll.cs
@@ -0,0 +1,83 @@
+// 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
+{
+ internal static class ExternDll
+ {
+#if FEATURE_PAL && !SILVERLIGHT
+
+#if !PLATFORM_UNIX
+ internal const String DLLPREFIX = "";
+ internal const String DLLSUFFIX = ".dll";
+#else // !PLATFORM_UNIX
+#if __APPLE__
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".dylib";
+#elif _AIX
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".a";
+#elif __hppa__ || IA64
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".sl";
+#else
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".so";
+#endif
+#endif // !PLATFORM_UNIX
+
+ public const string Kernel32 = DLLPREFIX + "rotor_pal" + DLLSUFFIX;
+ public const string User32 = DLLPREFIX + "rotor_pal" + DLLSUFFIX;
+ public const string Mscoree = DLLPREFIX + "sscoree" + DLLSUFFIX;
+
+#elif FEATURE_PAL && SILVERLIGHT
+
+ public const string Kernel32 = "coreclr";
+ public const string User32 = "coreclr";
+
+#else
+ public const string Activeds = "activeds.dll";
+ public const string Advapi32 = "advapi32.dll";
+ public const string Comctl32 = "comctl32.dll";
+ public const string Comdlg32 = "comdlg32.dll";
+ public const string Gdi32 = "gdi32.dll";
+ public const string Gdiplus = "gdiplus.dll";
+ public const string Hhctrl = "hhctrl.ocx";
+ public const string Imm32 = "imm32.dll";
+ public const string Kernel32 = "kernel32.dll";
+ public const string Loadperf = "Loadperf.dll";
+ public const string Mscoree = "mscoree.dll";
+ public const string Clr = "clr.dll";
+ public const string Msi = "msi.dll";
+ public const string Mqrt = "mqrt.dll";
+ public const string Ntdll = "ntdll.dll";
+ public const string Ole32 = "ole32.dll";
+ public const string Oleacc = "oleacc.dll";
+ public const string Oleaut32 = "oleaut32.dll";
+ public const string Olepro32 = "olepro32.dll";
+ public const string PerfCounter = "perfcounter.dll";
+ public const string Powrprof = "Powrprof.dll";
+ public const string Psapi = "psapi.dll";
+ public const string Shell32 = "shell32.dll";
+ public const string User32 = "user32.dll";
+ public const string Uxtheme = "uxtheme.dll";
+ public const string WinMM = "winmm.dll";
+ public const string Winspool = "winspool.drv";
+ public const string Wtsapi32 = "wtsapi32.dll";
+ public const string Version = "version.dll";
+ public const string Vsassert = "vsassert.dll";
+ public const string Fxassert = "Fxassert.dll";
+ public const string Shlwapi = "shlwapi.dll";
+ public const string Crypt32 = "crypt32.dll";
+
+ // system.data specific
+ internal const string Odbc32 = "odbc32.dll";
+ internal const string SNI = "System.Data.dll";
+
+ // system.data.oracleclient specific
+ internal const string OciDll = "oci.dll";
+ internal const string OraMtsDll = "oramts.dll";
+#endif //!FEATURE_PAL
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/FindResult.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/FindResult.cs
new file mode 100644
index 0000000000..a8bb1fe26f
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/FindResult.cs
@@ -0,0 +1,100 @@
+// 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.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ public class PrincipalSearchResult<T> : IEnumerable<T>, IEnumerable, IDisposable
+ {
+ //
+ // Public methods
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalSearchResult`1<T>.CheckDisposed():System.Void" />
+ // <SatisfiesLinkDemand Name="FindResultEnumerator`1<T>..ctor(System.DirectoryServices.AccountManagement.ResultSet)" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public IEnumerator<T> GetEnumerator()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearchResult", "Entering GetEnumerator");
+
+ CheckDisposed();
+
+ return new FindResultEnumerator<T>(_resultSet);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalSearchResult`1<T>.GetEnumerator():System.Collections.Generic.IEnumerator`1<T>" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return (IEnumerator)GetEnumerator();
+ }
+
+ public void Dispose()
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearchResult", "Dispose: disposing");
+
+ if (_resultSet != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearchResult", "Dispose: disposing resultSet");
+
+ lock (_resultSet)
+ {
+ _resultSet.Dispose();
+ }
+ }
+
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ //
+ // Internal Constructors
+ //
+
+ // Note that resultSet can be null
+ internal PrincipalSearchResult(ResultSet resultSet)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearchResult", "Ctor");
+
+ _resultSet = resultSet;
+ }
+
+ //
+ // Private Implementation
+ //
+
+ //
+ // SYNCHRONIZATION
+ // Access to:
+ // resultSet
+ // must be synchronized, since multiple enumerators could be iterating over us at once.
+ // Synchronize by locking on resultSet (if resultSet is non-null).
+
+ // The ResultSet returned by the query.
+ private ResultSet _resultSet;
+
+ private bool _disposed = false;
+
+ private void CheckDisposed()
+ {
+ if (_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalSearchResult", "CheckDisposed: accessing disposed object");
+ throw new ObjectDisposedException("PrincipalSearchResult");
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/FindResultEnumerator.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/FindResultEnumerator.cs
new file mode 100644
index 0000000000..a79bdf084e
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/FindResultEnumerator.cs
@@ -0,0 +1,228 @@
+// 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.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ internal class FindResultEnumerator<T> : IEnumerator<T>, IEnumerator
+ {
+ //
+ // Public properties
+ //
+
+ // Checks to make sure we're not before the start (beforeStart == true) or after
+ // the end (endReached == true) of the FindResult<T> collection, then retrieves the current
+ // principal from resultSet. If T == typeof(Principal), calls resultSet.CurrentAsPrincipal.
+
+ public T Current
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindResultEnumerator`1<T>.CheckDisposed():System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "FindResultEnumerator", "Entering Current, T={0}", typeof(T));
+
+ CheckDisposed();
+
+ if (_beforeStart == true || _endReached == true || _resultSet == null)
+ {
+ // Either we're before the beginning or after the end of the collection.
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Warn,
+ "FindResultEnumerator",
+ "Current: bad position, beforeStart={0}, endReached={1}, resultSet={2}",
+ _beforeStart,
+ _endReached,
+ _resultSet);
+
+ throw new InvalidOperationException(StringResources.FindResultEnumInvalidPos);
+ }
+
+ Debug.Assert(typeof(T) == typeof(System.DirectoryServices.AccountManagement.Principal) || typeof(T).IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.Principal)));
+ return (T)_resultSet.CurrentAsPrincipal;
+ }
+ }
+
+ object IEnumerator.Current
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindResultEnumerator`1<T>.get_Current():T" />
+ // <ReferencesCritical Name="Method: get_Current():T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return Current;
+ }
+ }
+
+ //
+ // Public methods
+ //
+
+ // Calls resultSet.MoveNext() to advance to the next principal in the ResultSet.
+ // Returns false when it reaches the end of the last ResultSet in resultSets, and sets endReached to true.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindResultEnumerator`1<T>.CheckDisposed():System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "FindResultEnumerator", "Entering MoveNext, T={0}", typeof(T));
+
+ CheckDisposed();
+
+ // If we previously reached the end, nothing more to move on to
+ if (_endReached)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "FindResultEnumerator", "MoveNext: end previously reached");
+ return false;
+ }
+
+ // No ResultSet, so we've already reached the end
+ if (_resultSet == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "FindResultEnumerator", "MoveNext: no resultSet");
+ return false;
+ }
+
+ bool f;
+
+ lock (_resultSet)
+ {
+ // If before the first ResultSet, move to the first ResultSet
+ if (_beforeStart == true)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "FindResultEnumerator", "MoveNext: Moving to first resultSet");
+
+ _beforeStart = false;
+
+ // In case we previously iterated over this ResultSet,
+ // and are now back to the start because our Reset() method was called.
+ // Or in case another instance of FindResultEnumerator previously iterated over this ResultSet.
+ _resultSet.Reset();
+ }
+
+ f = _resultSet.MoveNext();
+ }
+
+ // If f is false, we must have reached the end of resultSet.
+ if (!f)
+ {
+ // we've reached the end
+ _endReached = true;
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "FindResultEnumerator", "MoveNext: returning {0}", f);
+ return f;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindResultEnumerator`1<T>.MoveNext():System.Boolean" />
+ // <ReferencesCritical Name="Method: MoveNext():Boolean" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ bool IEnumerator.MoveNext()
+ {
+ return MoveNext();
+ }
+
+ // Repositions us to the beginning by setting beforeStart to true. Also clears endReached
+ // by setting it back to false;
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindResultEnumerator`1<T>.CheckDisposed():System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "FindResultEnumerator", "Entering Reset");
+
+ CheckDisposed();
+
+ _endReached = false;
+ _beforeStart = true;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindResultEnumerator`1<T>.Reset():System.Void" />
+ // <ReferencesCritical Name="Method: Reset():Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ void IEnumerator.Reset()
+ {
+ Reset();
+ }
+
+ public void Dispose()
+ {
+ // We really don't have anything to Dispose, since our ResultSet is actually
+ // owned by our parent FindResult<T>. However, IEnumerable<T> requires us to implement
+ // IDisposable.
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "FindResultEnumerator", "Dispose: disposing");
+
+ _disposed = true;
+ }
+
+ //
+ // Internal Constructors
+ //
+
+ // Constructs a enumerator to enumerate over the supplied of ResultSet
+ // Note that resultSet can be null
+ internal FindResultEnumerator(ResultSet resultSet)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "FindResultEnumerator", "Ctor");
+
+ _resultSet = resultSet;
+ }
+
+ //
+ // Private Implementation
+ //
+
+ //
+ // SYNCHRONIZATION
+ // Access to:
+ // resultSet
+ // must be synchronized, since multiple enumerators could be iterating over us at once.
+ // Synchronize by locking on resultSet (if resultSet is non-null).
+
+ // The ResultSet over which we're enumerating, passed to us from the FindResult<T>.
+ // Note that there's conceptually one FindResultEnumerator per FindResult, but can be multiple
+ // actual FindResultEnumerator objects per FindResult, so there's no risk
+ // of multiple FindResultEnumerators "interfering" with each other by trying to enumerate
+ // over the same ResultSet.
+ //
+ // Note that S.DS (based on code review and testing) and Sys.Storage (based on code review)
+ // both seem fine with the "one enumerator per result set" model.
+ private ResultSet _resultSet;
+
+ // if true, we're before the start of the ResultSet
+ private bool _beforeStart = true;
+
+ // if true, we've reached the end of the ResultSet
+ private bool _endReached = false;
+
+ // true if Dispose() has been called
+ private bool _disposed = false;
+
+ //
+ private void CheckDisposed()
+ {
+ if (_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "FindResultEnumerator", "CheckDisposed: accessing disposed object");
+ throw new ObjectDisposedException("FindResultEnumerator");
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalConfig.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalConfig.cs
new file mode 100644
index 0000000000..0c509be235
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalConfig.cs
@@ -0,0 +1,48 @@
+// 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.Diagnostics;
+using System.Configuration;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal static class GlobalConfig
+ {
+ static GlobalConfig()
+ {
+ GlobalConfig.s_configSettings = (ConfigSettings)ConfigurationManager.GetSection("System.DirectoryServices.AccountManagement");
+ }
+
+#if DEBUG
+ public const DebugLevel DefaultDebugLevel = DebugLevel.Warn;
+#else
+ public const DebugLevel DefaultDebugLevel = DebugLevel.None;
+#endif
+
+ static public DebugLevel DebugLevel
+ {
+ get
+ {
+ if (GlobalConfig.s_configSettings == null)
+ return GlobalConfig.DefaultDebugLevel;
+
+ return GlobalConfig.s_configSettings.DebugLevel;
+ }
+ }
+
+ static public string DebugLogFile
+ {
+ get
+ {
+ if (GlobalConfig.s_configSettings == null)
+ return null;
+
+ return GlobalConfig.s_configSettings.DebugLogFile;
+ }
+ }
+
+ private static ConfigSettings s_configSettings;
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalDebug.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalDebug.cs
new file mode 100644
index 0000000000..505bf26e69
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalDebug.cs
@@ -0,0 +1,101 @@
+// 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.Diagnostics;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal enum DebugLevel
+ {
+ None = 0,
+ Info,
+ Warn,
+ Error
+ }
+
+ internal static class GlobalDebug
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Debug.get_Listeners():System.Diagnostics.TraceListenerCollection" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ static GlobalDebug()
+ {
+ GlobalDebug.s_debugLevel = GlobalConfig.DebugLevel;
+#if DEBUG
+ string debugLogFile = GlobalConfig.DebugLogFile;
+
+ if (debugLogFile != null)
+ {
+ foreach (TraceListener listener in Debug.Listeners)
+ {
+ if (listener is DefaultTraceListener)
+ ((DefaultTraceListener)listener).LogFileName = debugLogFile;
+ }
+
+ //
+ Debug.WriteLine(
+ String.Format(
+ System.Globalization.CultureInfo.InvariantCulture,
+ "Principal API Debug Log - AppDomain {0} with ID {1} - {2} (UTC)",
+ System.Threading.Thread.GetDomain().FriendlyName,
+ System.Threading.Thread.GetDomainID(),
+ DateTime.UtcNow));
+ }
+#endif
+ }
+
+ static public bool Error
+ {
+ get { return DebugLevel.Error >= GlobalDebug.s_debugLevel; }
+ }
+
+ static public bool Warn
+ {
+ get { return DebugLevel.Warn >= GlobalDebug.s_debugLevel; }
+ }
+
+ static public bool Info
+ {
+ get { return DebugLevel.Info >= GlobalDebug.s_debugLevel; }
+ }
+
+ // <SecurityKernel TreatAsSafe="Directly applied from MetaData" Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="SafeNativeMethods.GetCurrentThreadId():System.Int32" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ [ConditionalAttribute("DEBUG")]
+ static public void WriteLineIf(bool f, string category, string message, params object[] args)
+ {
+ message = "[" + SafeNativeMethods.GetCurrentThreadId().ToString("x", CultureInfo.InvariantCulture) + "] " + message;
+
+ Debug.WriteLineIf(
+ f,
+ String.Format(
+ CultureInfo.InvariantCulture,
+ message,
+ args),
+ category);
+ }
+
+ // <SecurityKernel TreatAsSafe="Directly applied from MetaData" Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="SafeNativeMethods.GetCurrentThreadId():System.Int32" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ [ConditionalAttribute("DEBUG")]
+ static public void WriteLineIf(bool f, string category, string message)
+ {
+ message = "[" + SafeNativeMethods.GetCurrentThreadId().ToString("x", CultureInfo.InvariantCulture) + "] " + message;
+
+ Debug.WriteLineIf(
+ f,
+ message,
+ category);
+ }
+
+ private static DebugLevel s_debugLevel;
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalSuppressions.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalSuppressions.cs
new file mode 100644
index 0000000000..6f1029acbd
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GlobalSuppressions.cs
@@ -0,0 +1,117 @@
+// 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.CodeAnalysis;
+
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AdvancedFilters.LastLogonTime(System.DateTime,System.DirectoryServices.AccountManagement.MatchType):System.Void", MessageId = "Logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AdvancedFilters.LastLogonTime(System.DateTime,System.DirectoryServices.AccountManagement.MatchType):System.Void", MessageId = "logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AdvancedFilters..ctor(System.DirectoryServices.AccountManagement.Principal)", MessageId = "p")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.Add(T):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.Contains(System.Object):System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IEnumerable.GetEnumerator():System.Collections.IEnumerator", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.get_IsFixedSize():System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.IndexOf(T):System.Int32", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.Remove(T):System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.ICollection.get_SyncRoot():System.Object", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.ICollection.get_IsSynchronized():System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.Add(System.Object):System.Int32", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.CopyTo(T[],System.Int32):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.GetEnumerator():System.Collections.Generic.IEnumerator`1<T>", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.get_IsReadOnly():System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.get_IsReadOnly():System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.get_Count():System.Int32", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.Clear():System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.Insert(System.Int32,T):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.Clear():System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.IndexOf(System.Object):System.Int32", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.ICollection.CopyTo(System.Array,System.Int32):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.Contains(T):System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.set_Item(System.Int32,T):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.get_Item(System.Int32):T", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.get_Item(System.Int32):System.Object", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.set_Item(System.Int32,System.Object):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.RemoveAt(System.Int32):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.Remove(System.Object):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.RemoveAt(System.Int32):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.IList.Insert(System.Int32,System.Object):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalValueCollection`1.System.Collections.ICollection.get_Count():System.Int32", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthenticablePrincipal.PermittedLogonTimes", Justification = "Returning an array is the proper design for this property. It matches the other properties in the object. Most callers will not be accessing into the array directly")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthenticablePrincipal.PermittedLogonTimes", MessageId = "Logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthenticablePrincipal.SmartcardLogonRequired", MessageId = "Logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthenticablePrincipal.LastLogon", MessageId = "Logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthenticablePrincipal.FindByLogonTime<T>(System.DirectoryServices.AccountManagement.PrincipalContext,System.DateTime,System.DirectoryServices.AccountManagement.MatchType):System.DirectoryServices.AccountManagement.PrincipalSearchResult`1<T>", MessageId = "Logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthenticablePrincipal.FindByLogonTime(System.DirectoryServices.AccountManagement.PrincipalContext,System.DateTime,System.DirectoryServices.AccountManagement.MatchType):System.DirectoryServices.AccountManagement.PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.AuthenticablePrincipal>", MessageId = "Logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthenticablePrincipal.BadLogonCount", MessageId = "Logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalContext.Dispose():System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(System.String,System.DirectoryServices.AccountManagement.ServerProperties&):System.Void", MessageId = "System.Convert.ToInt32(System.Object)")]
+[module: SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces", Scope = "type", Target = "System.DirectoryServices.AccountManagement.Principal", Justification = "Binary went through .NET naming review.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.Principal.Equals(System.Object):System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.Principal.Dispose():System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.Principal.GetHashCode():System.Int32", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.Principal.ToString():System.String", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.System.Collections.ICollection.get_IsSynchronized():System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.System.Collections.ICollection.get_SyncRoot():System.Object", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.GetEnumerator():System.Collections.Generic.IEnumerator`1<System.DirectoryServices.AccountManagement.Principal>", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.get_IsReadOnly():System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.get_Count():System.Int32", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.System.Collections.IEnumerable.GetEnumerator():System.Collections.IEnumerator", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.System.Collections.ICollection.CopyTo(System.Array,System.Int32):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.Contains(System.DirectoryServices.AccountManagement.Principal):System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.Add(System.DirectoryServices.AccountManagement.Principal):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.Remove(System.DirectoryServices.AccountManagement.Principal):System.Boolean", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.Clear():System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.CopyTo(System.DirectoryServices.AccountManagement.Principal[],System.Int32):System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalCollection.System.Collections.ICollection.get_Count():System.Int32", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.ComputerPrincipal.FindByLogonTime(System.DirectoryServices.AccountManagement.PrincipalContext,System.DateTime,System.DirectoryServices.AccountManagement.MatchType):System.DirectoryServices.AccountManagement.PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.ComputerPrincipal>", MessageId = "Logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.SidList..ctor(System.Collections.Generic.List`1<System.Byte[]>,System.String,System.DirectoryServices.AccountManagement.NetCred)")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.SidList..ctor(System.Collections.Generic.List`1<System.Byte[]>)")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalSearcher.Dispose():System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthZSet.MoveNext():System.Boolean", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]
+[module: SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthZSet.get_CurrentAsPrincipal():System.Object", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]
+[module: SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthZSet..ctor(System.Byte[],System.DirectoryServices.AccountManagement.NetCred,System.DirectoryServices.AccountManagement.ContextOptions,System.String,System.DirectoryServices.AccountManagement.StoreCtx,System.Object)", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]
+[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope = "type", Target = "System.DirectoryServices.AccountManagement.DirectoryRdnPrefixAttribute", MessageId = "Rdn")]
+[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.DirectoryRdnPrefixAttribute.RdnPrefix", MessageId = "Rdn", Justification = "rdn is a valid abbreviation for relative distinguished name.")]
+[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.DirectoryRdnPrefixAttribute..ctor(System.String)", MessageId = "rdn", Justification = "rdn is a valid abbreviation for relative distinguished name.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalSearchResult`1.GetEnumerator():System.Collections.Generic.IEnumerator`1<T>", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalSearchResult`1.Dispose():System.Void", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Scope = "member", Target = "System.DirectoryServices.AccountManagement.PrincipalSearchResult`1.System.Collections.IEnumerable.GetEnumerator():System.Collections.IEnumerator", Justification = "Different link demands are valid for these types because they derive from .NET base types which are not modifiiable.")]
+[module: SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Scope = "member", Target = "System.DirectoryServices.AccountManagement.GroupPrincipal.Members")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope = "member", Target = "System.DirectoryServices.AccountManagement.UserPrincipal.FindByLogonTime(System.DirectoryServices.AccountManagement.PrincipalContext,System.DateTime,System.DirectoryServices.AccountManagement.MatchType):System.DirectoryServices.AccountManagement.PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.UserPrincipal>", MessageId = "Logon", Justification = "Logon is valid casing for this word")]
+[module: SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations", Scope = "member", Target = "System.DirectoryServices.AccountManagement.UserPrincipal.get_Current():System.DirectoryServices.AccountManagement.UserPrincipal")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.SR.get_Resources():System.Resources.ResourceManager")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.SR.GetObject(System.String):System.Object")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.SR.GetString(System.String,System.Object[]):System.String")]
+[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "System.DirectoryServices.AccountManagement.StringResources.resources", MessageId = "machinename")]
+[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "System.DirectoryServices.AccountManagement.StringResources.resources", MessageId = "unpersisted")]
+[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "System.DirectoryServices.AccountManagement.StringResources.resources", MessageId = "Unpersisted")]
+[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "System.DirectoryServices.AccountManagement.StringResources.resources", MessageId = "Rdn")]
+[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "System.DirectoryServices.AccountManagement.StringResources.resources", MessageId = "domainname")]
+[module: SuppressMessage("Microsoft.Interoperability", "CA1404:CallGetLastErrorImmediatelyAfterPInvoke", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthZSet..ctor(System.Byte[],System.DirectoryServices.AccountManagement.NetCred,System.DirectoryServices.AccountManagement.ContextOptions,System.String,System.DirectoryServices.AccountManagement.StoreCtx,System.Object)")]
+[module: SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", Scope = "member", Target = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.DsRoleGetPrimaryDomainInformation(System.String,System.DirectoryServices.AccountManagement.UnsafeNativeMethods+DSROLE_PRIMARY_DOMAIN_INFO_LEVEL,System.IntPtr&):System.Int32", MessageId = "0")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.ConfigSettings.set_DebugLevel(System.DirectoryServices.AccountManagement.DebugLevel):System.Void")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.ConfigSettings.get_DebugLogFile():System.String")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.ConfigSettings.set_DebugLogFile(System.String):System.Void")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.GlobalConfig.get_DebugLogFile():System.String")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.GlobalDebug.get_Error():System.Boolean")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.GlobalDebug.get_Warn():System.Boolean")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.GlobalDebug.get_Info():System.Boolean")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.GlobalConfig.get_DebugLogFile():System.String")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.GlobalDebug.get_Error():System.Boolean")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.GlobalDebug.get_Warn():System.Boolean")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.DirectoryServices.AccountManagement.GlobalDebug.get_Info():System.Boolean")]
+[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.SR.#GetString(System.String,System.Boolean&)", Justification = "This code is generated dynamically by the compiler")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Logon", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AdvancedFilters.#BadLogonCount(System.Int32,System.DirectoryServices.AccountManagement.MatchType)", Justification = "Logon is a valid casing for this word")]
+[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Logon", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AuthenticablePrincipal.#FindByLogonTime`1(System.DirectoryServices.AccountManagement.PrincipalContext,System.DateTime,System.DirectoryServices.AccountManagement.MatchType)", Justification = "Logon is a valid casing for this word")]
+[module: SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#", Scope = "member", Target = "System.DirectoryServices.AccountManagement.AdvancedFilters.#BadLogonCount(System.Int32,System.DirectoryServices.AccountManagement.MatchType)", Justification = "Code was already shipped and change would break clients")]
+[module: SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Scope = "type", Target = "System.DirectoryServices.AccountManagement.PrincipalSearchResult`1", Justification = "Code was already shipped and change would break clients")]
+[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.NetApiBufferFree(System.IntPtr)", Scope = "member", Target = "System.DirectoryServices.AccountManagement.SAMStoreCtx.#LoadComputerInfo()", Justification = "The call is for an API cleanup method, we will not do anything with its return code anyway")]
+[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.LsaClose(System.IntPtr)", Scope = "member", Target = "System.DirectoryServices.AccountManagement.SidList.#TranslateSids(System.String,System.IntPtr[])", Justification = "The call is for an API cleanup method, we will not do anything with its return code anyway")]
+[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.NetApiBufferFree(System.IntPtr)", Scope = "member", Target = "System.DirectoryServices.AccountManagement.Utils.#GetDcName(System.String,System.String,System.String,System.Int32)", Justification = "The call is for an API cleanup method, we will not do anything with its return code anyway")]
+[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.RevertToSelf", Scope = "member", Target = "System.DirectoryServices.AccountManagement.Utils.#EndImpersonation(System.IntPtr)", Justification = "The call is for an API cleanup method, we will not do anything with its return code anyway")]
+[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.LsaFreeMemory(System.IntPtr)", Scope = "member", Target = "System.DirectoryServices.AccountManagement.SidList.#TranslateSids(System.String,System.IntPtr[])", Justification = "The call is for an API cleanup method, we will not do anything with its return code anyway")]
+[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.LsaClose(System.IntPtr)", Scope = "member", Target = "System.DirectoryServices.AccountManagement.SidList.#TranslateSids(System.String,System.IntPtr[])", Justification = "The call is for an API cleanup method, we will not do anything with its return code anyway")]
+[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.DsRoleFreeMemory(System.IntPtr)", Scope = "member", Target = "System.DirectoryServices.AccountManagement.Utils.#IsMachineDC(System.String)", Justification = "The call is for an API cleanup method, we will not do anything with its return code anyway")]
+[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.LsaFreeMemory(System.IntPtr)", Scope = "member", Target = "System.DirectoryServices.AccountManagement.Utils.#GetMachineDomainSid()", Justification = "The call is for an API cleanup method, we will not do anything with its return code anyway")]
+[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.DirectoryServices.AccountManagement.UnsafeNativeMethods.LsaClose(System.IntPtr)", Scope = "member", Target = "System.DirectoryServices.AccountManagement.Utils.#GetMachineDomainSid()", Justification = "The call is for an API cleanup method, we will not do anything with its return code anyway")]
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Group.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Group.cs
new file mode 100644
index 0000000000..bac8b2ab91
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Group.cs
@@ -0,0 +1,419 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+using System.Security.Permissions;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ [DirectoryRdnPrefix("CN")]
+ public class GroupPrincipal : Principal
+ {
+ //
+ // Public constructors
+ //
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ public GroupPrincipal(PrincipalContext context)
+ {
+ if (context == null)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ this.ContextRaw = context;
+ this.unpersisted = true;
+ }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ public GroupPrincipal(PrincipalContext context, string samAccountName) : this(context)
+ {
+ if (samAccountName == null)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ if (Context.ContextType != ContextType.ApplicationDirectory)
+ this.SamAccountName = samAccountName;
+
+ this.Name = samAccountName;
+ }
+
+ //
+ // Public properties
+ //
+
+ // IsSecurityGroup property
+ private bool _isSecurityGroup = false; // the actual property value
+ private LoadState _isSecurityGroupChanged = LoadState.NotSet; // change-tracking
+
+ public Nullable<bool> IsSecurityGroup
+ {
+ get
+ {
+ // Make sure we're not disposed or deleted. Although HandleGet/HandleSet will check this,
+ // we need to check these before we do anything else.
+ CheckDisposedOrDeleted();
+
+ // Different stores have different defaults as to the Enabled setting
+ // (AD: creates disabled by default; SAM: creates enabled by default).
+ // So if the principal is unpersisted (and thus we may not know what store it's
+ // going to end up in), we'll just return null unless they previously
+ // set an explicit value.
+ if (this.unpersisted && (_isSecurityGroupChanged != LoadState.Changed))
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "Group",
+ "Enabled: returning null, unpersisted={0}, enabledChanged={1}",
+ this.unpersisted,
+ _isSecurityGroupChanged);
+ return null;
+ }
+
+ return HandleGet<bool>(ref _isSecurityGroup, PropertyNames.GroupIsSecurityGroup, ref _isSecurityGroupChanged);
+ }
+
+ set
+ {
+ // Make sure we're not disposed or deleted. Although HandleGet/HandleSet will check this,
+ // we need to check these before we do anything else.
+ CheckDisposedOrDeleted();
+
+ // We don't want to let them set a null value.
+ if (!value.HasValue)
+ throw new ArgumentNullException("value");
+
+ HandleSet<bool>(ref _isSecurityGroup, value.Value, ref _isSecurityGroupChanged, PropertyNames.GroupIsSecurityGroup);
+ }
+ }
+
+ // GroupScope property
+ private GroupScope _groupScope = System.DirectoryServices.AccountManagement.GroupScope.Local; // the actual property value
+ private LoadState _groupScopeChanged = LoadState.NotSet; // change-tracking
+
+ public Nullable<GroupScope> GroupScope
+ {
+ get
+ {
+ // Make sure we're not disposed or deleted. Although HandleGet/HandleSet will check this,
+ // we need to check these before we do anything else.
+ CheckDisposedOrDeleted();
+
+ // Different stores have different defaults for the GroupScope setting
+ // (AD: Global; SAM: Local).
+ // So if the principal is unpersisted (and thus we may not know what store it's
+ // going to end up in), we'll just return null unless they previously
+ // set an explicit value.
+ if (this.unpersisted && (_groupScopeChanged != LoadState.Changed))
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "Group",
+ "GroupScope: returning null, unpersisted={0}, groupScopeChanged={1}",
+ this.unpersisted,
+ _groupScopeChanged);
+
+ return null;
+ }
+
+ return HandleGet<GroupScope>(ref _groupScope, PropertyNames.GroupGroupScope, ref _groupScopeChanged);
+ }
+
+ set
+ {
+ // Make sure we're not disposed or deleted. Although HandleGet/HandleSet will check this,
+ // we need to check these before we do anything else.
+ CheckDisposedOrDeleted();
+
+ // We don't want to let them set a null value.
+ if (!value.HasValue)
+ throw new ArgumentNullException("value");
+
+ HandleSet<GroupScope>(ref _groupScope, value.Value, ref _groupScopeChanged, PropertyNames.GroupGroupScope);
+ }
+ }
+
+ // Members property
+ private PrincipalCollection _members = null;
+
+ public PrincipalCollection Members
+ {
+ get
+ {
+ // We don't use HandleGet<T> here because we have to load in the PrincipalCollection
+ // using a special procedure. It's not loaded as part of the regular LoadIfNeeded call.
+
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Check that we actually support this propery in our store
+ //CheckSupportedProperty(PropertyNames.GroupMembers);
+
+ if (_members == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "Members: creating fresh PrincipalCollection");
+
+ if (!this.unpersisted)
+ {
+ // Retrieve the members from the store.
+ // QueryCtx because when this group was retrieved, it was
+ // assigned a _specific_ context for its store
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "Members: persisted, querying group membership");
+
+ BookmarkableResultSet refs = ContextRaw.QueryCtx.GetGroupMembership(this, false);
+ _members = new PrincipalCollection(refs, this);
+ }
+ else
+ {
+ // unpersisted means there's no values to retrieve from the store
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "Members: unpersisted, creating empty PrincipalCollection");
+ _members = new PrincipalCollection(new EmptySet(), this);
+ }
+ }
+
+ return _members;
+ }
+ }
+
+ //
+ // Public methods
+ //
+ public static new GroupPrincipal FindByIdentity(PrincipalContext context, string identityValue)
+ {
+ return (GroupPrincipal)FindByIdentityWithType(context, typeof(GroupPrincipal), identityValue);
+ }
+
+ public static new GroupPrincipal FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
+ {
+ return (GroupPrincipal)FindByIdentityWithType(context, typeof(GroupPrincipal), identityType, identityValue);
+ }
+
+ public PrincipalSearchResult<Principal> GetMembers()
+ {
+ return GetMembers(false);
+ }
+
+ public PrincipalSearchResult<Principal> GetMembers(bool recursive)
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ if (!this.unpersisted)
+ {
+ // Retrieve the members from the store.
+ // QueryCtx because when this group was retrieved, it was
+ // assigned a _specific_ context for its store
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "GetMembers: persisted, querying for members (recursive={0}", recursive);
+
+ return new PrincipalSearchResult<Principal>(ContextRaw.QueryCtx.GetGroupMembership(this, recursive));
+ }
+ else
+ {
+ // unpersisted means there's no values to retrieve from the store
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "GetMembers: unpersisted, creating empty PrincipalSearchResult");
+
+ return new PrincipalSearchResult<Principal>(null);
+ }
+ }
+
+ private bool _disposed = false;
+
+ public override void Dispose()
+ {
+ try
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "Dispose: disposing");
+
+ if (_members != null)
+ _members.Dispose();
+
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+
+ //
+ // Internal "constructor": Used for constructing Groups returned by a query
+ //
+ static internal GroupPrincipal MakeGroup(PrincipalContext ctx)
+ {
+ GroupPrincipal g = new GroupPrincipal(ctx);
+ g.unpersisted = false;
+
+ return g;
+ }
+
+ //
+ // Load/Store implementation
+ //
+
+ //
+ // Loading with query results
+ //
+
+ internal override void LoadValueIntoProperty(string propertyName, object value)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "LoadValueIntoProperty: name=" + propertyName + " value=" + (value != null ? value.ToString() : "null"));
+
+ switch (propertyName)
+ {
+ case PropertyNames.GroupIsSecurityGroup:
+ _isSecurityGroup = (bool)value;
+ _isSecurityGroupChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.GroupGroupScope:
+ _groupScope = (GroupScope)value;
+ _groupScopeChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.GroupMembers:
+ Debug.Fail("Group.LoadValueIntoProperty: Trying to load Members, but Members is demand-loaded.");
+ break;
+
+ default:
+ base.LoadValueIntoProperty(propertyName, value);
+ break;
+ }
+ }
+
+ //
+ // Getting changes to persist (or to build a query from a QBE filter)
+ //
+
+ // Given a property name, returns true if that property has changed since it was loaded, false otherwise.
+ internal override bool GetChangeStatusForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "GetChangeStatusForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case PropertyNames.GroupIsSecurityGroup:
+ return _isSecurityGroupChanged == LoadState.Changed;
+
+ case PropertyNames.GroupGroupScope:
+ return _groupScopeChanged == LoadState.Changed;
+
+ case PropertyNames.GroupMembers:
+ // If Members was never loaded, it couldn't possibly have changed
+ if (_members != null)
+ return _members.Changed;
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "GetChangeStatusForProperty: members was never loaded");
+ return false;
+ }
+
+ default:
+ return base.GetChangeStatusForProperty(propertyName);
+ }
+ }
+
+ // Given a property name, returns the current value for the property.
+ internal override object GetValueForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "GetValueForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case PropertyNames.GroupIsSecurityGroup:
+ return _isSecurityGroup;
+
+ case PropertyNames.GroupGroupScope:
+ return _groupScope;
+
+ case PropertyNames.GroupMembers:
+ return _members;
+
+ default:
+ return base.GetValueForProperty(propertyName);
+ }
+ }
+
+ // Reset all change-tracking status for all properties on the object to "unchanged".
+ internal override void ResetAllChangeStatus()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Group", "ResetAllChangeStatus");
+
+ _groupScopeChanged = (_groupScopeChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _isSecurityGroupChanged = (_isSecurityGroupChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+
+ if (_members != null)
+ _members.ResetTracking();
+
+ base.ResetAllChangeStatus();
+ }
+
+ /// <summary>
+ /// if isSmallGroup has a value, it means we already checked if the group is small
+ /// </summary>
+ private bool? _isSmallGroup;
+
+ /// <summary>
+ /// cache the search result for the member attribute
+ /// it will only be set for small groups!
+ /// </summary>
+ internal SearchResult SmallGroupMemberSearchResult { get; private set; }
+
+ /// <summary>
+ /// Finds if the group is "small", meaning that it has less than MaxValRange values (usually 1500)
+ /// The property list for the searcher of a a group has "member" attribute. if there are more results than MaxValRange, there will also be a "member;range=..." attribute
+ /// we can cache the result and don't fear from changes through Add/Remove/Save because the completed/pending lists are looked up before the actual values are
+ /// </summary>
+ internal bool IsSmallGroup()
+ {
+ if (_isSmallGroup.HasValue)
+ {
+ return _isSmallGroup.Value;
+ }
+
+ _isSmallGroup = false;
+
+ DirectoryEntry de = (DirectoryEntry)this.UnderlyingObject;
+ Debug.Assert(de != null);
+ if (de != null)
+ {
+ using (DirectorySearcher ds = new DirectorySearcher(de, "(objectClass=*)", new string[] { "member" }, SearchScope.Base))
+ {
+ SearchResult sr = ds.FindOne();
+ if (sr != null)
+ {
+ bool rangePropertyFound = false;
+ foreach (string propName in sr.Properties.PropertyNames)
+ {
+ if (propName.StartsWith("member;range=", StringComparison.OrdinalIgnoreCase))
+ {
+ rangePropertyFound = true;
+ break;
+ }
+ }
+
+ // we only consider the group "small" if there is a "member" property but no "member;range..." property
+ if (!rangePropertyFound)
+ {
+ _isSmallGroup = true;
+ SmallGroupMemberSearchResult = sr;
+ }
+ }
+ }
+ }
+ return _isSmallGroup.Value;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GroupType.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GroupType.cs
new file mode 100644
index 0000000000..60f916643f
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/GroupType.cs
@@ -0,0 +1,24 @@
+// 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;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ public enum GroupScope
+ {
+ Local = 0,
+ Global = 1,
+ Universal = 2
+ }
+
+ // The AD "groupType" bit flags corresponding to the above
+ internal static class ADGroupScope
+ {
+ internal const int Local = 0x00000004;
+ internal const int Global = 0x00000002;
+ internal const int Universal = 0x00000008;
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityClaim.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityClaim.cs
new file mode 100644
index 0000000000..424da90224
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityClaim.cs
@@ -0,0 +1,32 @@
+// 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.Collections.Generic;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class IdentityClaim
+ {
+ public string UrnValue
+ {
+ get { return _urnValue; }
+ set { _urnValue = value; }
+ }
+
+ public string UrnScheme
+ {
+ set { _urnScheme = value; }
+ get { return _urnScheme; }
+ }
+
+ private string _urnValue;
+ private string _urnScheme;
+
+ public IdentityClaim()
+ {
+ // Nothing to do here
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityReference.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityReference.cs
new file mode 100644
index 0000000000..fcb80e8174
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityReference.cs
@@ -0,0 +1,32 @@
+// 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.Collections.Generic;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class IdentityReference
+ {
+ public string UrnValue
+ {
+ get { return _urnValue; }
+ set { _urnValue = value; }
+ }
+
+ public string UrnScheme
+ {
+ get { return _urnScheme; }
+ set { _urnScheme = value; }
+ }
+
+ private string _urnValue;
+ private string _urnScheme;
+
+ public IdentityReference()
+ {
+ // Do nothing
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityType.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityType.cs
new file mode 100644
index 0000000000..9f447f47c5
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/IdentityType.cs
@@ -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;
+using System.Collections.Generic;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ public enum IdentityType
+ {
+ SamAccountName = 0,
+ Name = 1,
+ UserPrincipalName = 2,
+ DistinguishedName = 3,
+ Sid = 4,
+ Guid = 5
+ }
+
+ internal class IdentMap
+ {
+ private IdentMap() { }
+
+ internal static object[,] StringMap = {
+ {IdentityType.SamAccountName, IdentityTypeStringMap.SamAccount},
+ {IdentityType.Name, IdentityTypeStringMap.Name},
+ {IdentityType.UserPrincipalName, IdentityTypeStringMap.Upn},
+ {IdentityType.DistinguishedName, IdentityTypeStringMap.DistinguishedName},
+ {IdentityType.Sid, IdentityTypeStringMap.Sid},
+ {IdentityType.Guid, IdentityTypeStringMap.Guid}};
+ }
+ static internal class IdentityTypeStringMap
+ {
+ public const string Guid = "ms-guid";
+ public const string Sid = "ms-sid";
+ public const string DistinguishedName = "ldap-dn";
+ public const string SamAccount = "ms-nt4account";
+ public const string Upn = "ms-upn";
+ public const string Name = "ms-name";
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/MatchType.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/MatchType.cs
new file mode 100644
index 0000000000..71877e8a8d
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/MatchType.cs
@@ -0,0 +1,18 @@
+// 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;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ public enum MatchType
+ {
+ Equals = 0,
+ NotEquals = 1,
+ GreaterThan = 2,
+ GreaterThanOrEquals = 3,
+ LessThan = 4,
+ LessThanOrEquals = 5
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/NetCred.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/NetCred.cs
new file mode 100644
index 0000000000..c408aabf4a
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/NetCred.cs
@@ -0,0 +1,113 @@
+// 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.Diagnostics;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Net;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class NetCred
+ {
+ public NetCred(string username, string password)
+ {
+ _username = username;
+ _password = password;
+ }
+
+ public string UserName
+ {
+ get { return _username; }
+ }
+
+ public string Password
+ {
+ get { return _password; }
+ }
+
+ public string ParsedUserName
+ {
+ // <SecurityKernel Critical="True" Ring="1">
+ // <ReferencesCritical Name="Method: SplitUsername(String, String&, String&):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ if (null == _parsedUserName)
+ {
+ SplitUsername(_username, ref _parsedUserName, ref _domainname);
+ }
+
+ return _parsedUserName;
+ }
+ }
+
+ public string Domain
+ {
+ // <SecurityKernel Critical="True" Ring="1">
+ // <ReferencesCritical Name="Method: SplitUsername(String, String&, String&):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ if (null == _parsedUserName)
+ {
+ SplitUsername(_username, ref _parsedUserName, ref _domainname);
+ }
+
+ return _domainname;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.CredUIParseUserName(System.String,System.Text.StringBuilder,System.UInt32,System.Text.StringBuilder,System.UInt32):System.Int32" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ private void SplitUsername(string username, ref string parsedUserName, ref string parsedDomainName)
+ {
+ // If the user has passed null creds then parsed components should also be null.
+ if (username == null)
+ {
+ parsedDomainName = null;
+ parsedUserName = null;
+ return;
+ }
+
+ // Logon user expects the username in UPN or to have the username and domain split to the seperate parameters.
+ // It does not work properly with NT4 style name formats. This function will put the username in the proper format.
+ StringBuilder splitUsername = new StringBuilder(UnsafeNativeMethods.CRED_MAX_USERNAME_LENGTH);
+ StringBuilder splitDomain = new StringBuilder(UnsafeNativeMethods.CRED_MAX_DOMAIN_TARGET_LENGTH);
+
+ int result = UnsafeNativeMethods.CredUIParseUserName(
+ username,
+ splitUsername,
+ (System.UInt32)splitUsername.Capacity,
+ splitDomain,
+ (System.UInt32)splitDomain.Capacity);
+
+ // If CredUiParseUsername fails then username format must have been in a format it does not expect.
+ // Just pass then entire username as the user passed it with a null domain string.
+ if (result != 0)
+ {
+ parsedDomainName = null;
+ parsedUserName = username;
+ }
+ else
+ {
+ parsedDomainName = splitDomain.ToString();
+ parsedUserName = splitUsername.ToString();
+ }
+ }
+
+ //
+ private string _username = null;
+ private string _password = null;
+ private string _domainname = null;
+ private string _parsedUserName = null;
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Pair.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Pair.cs
new file mode 100644
index 0000000000..a99244cd8c
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Pair.cs
@@ -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;
+using System.Diagnostics;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class Pair<J, K>
+ {
+ //
+ // Constructor
+ //
+ internal Pair(J left, K right)
+ {
+ _left = left;
+ _right = right;
+ }
+
+ //
+ // Public properties
+ //
+ internal J Left
+ {
+ get { return _left; }
+ set { _left = value; }
+ }
+
+ internal K Right
+ {
+ get { return _right; }
+ set { _right = value; }
+ }
+
+ //
+ // Private implementation
+ //
+
+ private J _left;
+ private K _right;
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PasswordInfo.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PasswordInfo.cs
new file mode 100644
index 0000000000..fb6ab3af87
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PasswordInfo.cs
@@ -0,0 +1,458 @@
+// 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.Diagnostics;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+#if TESTHOOK
+ public class PasswordInfo
+#else
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ internal class PasswordInfo
+#endif
+ {
+ //
+ // Properties exposed to the public through AuthenticablePrincipal
+ //
+
+ // LastPasswordSet
+ private Nullable<DateTime> _lastPasswordSet = null;
+ private LoadState _lastPasswordSetLoaded = LoadState.NotSet;
+
+ public Nullable<DateTime> LastPasswordSet
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Nullable`1<System.DateTime>>(System.Nullable`1<System.DateTime>&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Nullable`1<System.DateTime>" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<Nullable<DateTime>>(ref _lastPasswordSet, PropertyNames.PwdInfoLastPasswordSet, ref _lastPasswordSetLoaded);
+ }
+ }
+
+ // LastBadPasswordAttempt
+ private Nullable<DateTime> _lastBadPasswordAttempt = null;
+ private LoadState _lastBadPasswordAttemptLoaded = LoadState.NotSet;
+
+ public Nullable<DateTime> LastBadPasswordAttempt
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Nullable`1<System.DateTime>>(System.Nullable`1<System.DateTime>&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Nullable`1<System.DateTime>" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<Nullable<DateTime>>(ref _lastBadPasswordAttempt, PropertyNames.PwdInfoLastBadPasswordAttempt, ref _lastBadPasswordAttemptLoaded);
+ }
+ }
+
+ // PasswordNotRequired
+ private bool _passwordNotRequired = false;
+ private LoadState _passwordNotRequiredChanged = LoadState.NotSet;
+
+ public bool PasswordNotRequired
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Boolean>(System.Boolean&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Boolean" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<bool>(ref _passwordNotRequired, PropertyNames.PwdInfoPasswordNotRequired, ref _passwordNotRequiredChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.Boolean>(System.Boolean&,System.Boolean,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ _owningPrincipal.HandleSet<bool>(ref _passwordNotRequired, value, ref _passwordNotRequiredChanged,
+ PropertyNames.PwdInfoPasswordNotRequired);
+ }
+ }
+
+ // PasswordNeverExpires
+ private bool _passwordNeverExpires = false;
+ private LoadState _passwordNeverExpiresChanged = LoadState.NotSet;
+
+ public bool PasswordNeverExpires
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Boolean>(System.Boolean&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Boolean" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<bool>(ref _passwordNeverExpires, PropertyNames.PwdInfoPasswordNeverExpires, ref _passwordNeverExpiresChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.Boolean>(System.Boolean&,System.Boolean,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ _owningPrincipal.HandleSet<bool>(ref _passwordNeverExpires, value, ref _passwordNeverExpiresChanged,
+ PropertyNames.PwdInfoPasswordNeverExpires);
+ }
+ }
+
+ // UserCannotChangePassword
+ private bool _cannotChangePassword = false;
+ private LoadState _cannotChangePasswordChanged = LoadState.NotSet;
+ private bool _cannotChangePasswordRead = false;
+
+ // For this property we are doing an on demand load. The store will not load this property when load is called beacuse
+ // the loading of this property is perf intensive. HandleGet still needs to be called to load the other object properties if
+ // needed. We read the status directly from the store and then cache it for use later.
+ public bool UserCannotChangePassword
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Boolean>(System.Boolean&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Boolean" />
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ _owningPrincipal.HandleGet<bool>(ref _cannotChangePassword, PropertyNames.PwdInfoCannotChangePassword, ref _cannotChangePasswordChanged);
+
+ if ((_cannotChangePasswordChanged != LoadState.Changed) && !_cannotChangePasswordRead && !_owningPrincipal.unpersisted)
+ {
+ _cannotChangePassword = _owningPrincipal.GetStoreCtxToUse().AccessCheck(_owningPrincipal, PrincipalAccessMask.ChangePassword);
+ _cannotChangePasswordRead = true;
+ }
+
+ return _cannotChangePassword;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.Boolean>(System.Boolean&,System.Boolean,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ _owningPrincipal.HandleSet<bool>(ref _cannotChangePassword, value, ref _cannotChangePasswordChanged,
+ PropertyNames.PwdInfoCannotChangePassword);
+ }
+ }
+
+ // AllowReversiblePasswordEncryption
+ private bool _allowReversiblePasswordEncryption = false;
+ private LoadState _allowReversiblePasswordEncryptionChanged = LoadState.NotSet;
+
+ public bool AllowReversiblePasswordEncryption
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleGet<System.Boolean>(System.Boolean&,System.String,System.DirectoryServices.AccountManagement.LoadState&):System.Boolean" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleGet(T&,System.String,System.DirectoryServices.AccountManagement.LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningPrincipal.HandleGet<bool>(ref _allowReversiblePasswordEncryption, PropertyNames.PwdInfoAllowReversiblePasswordEncryption, ref _allowReversiblePasswordEncryptionChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.HandleSet<System.Boolean>(System.Boolean&,System.Boolean,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.HandleSet(T&,T,System.DirectoryServices.AccountManagement.LoadState&,System.String):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ _owningPrincipal.HandleSet<bool>(ref _allowReversiblePasswordEncryption, value, ref _allowReversiblePasswordEncryptionChanged,
+ PropertyNames.PwdInfoAllowReversiblePasswordEncryption);
+ }
+ }
+
+ //
+ // Methods exposed to the public through AuthenticablePrincipal
+ //
+
+ private string _storedNewPassword = null;
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void SetPassword(string newPassword)
+ {
+ if (newPassword == null)
+ throw new ArgumentNullException("newPassword");
+
+ // If we're not persisted, we just save up the change until we're Saved
+ if (_owningPrincipal.unpersisted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "SetPassword: saving until persisted");
+ _storedNewPassword = newPassword;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "SetPassword: sending request");
+ _owningPrincipal.GetStoreCtxToUse().SetPassword(_owningPrincipal, newPassword);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void ChangePassword(string oldPassword, string newPassword)
+ {
+ if (oldPassword == null)
+ throw new ArgumentNullException("oldPassword");
+
+ if (newPassword == null)
+ throw new ArgumentNullException("newPassword");
+
+ // While you can reset the password on an unpersisted principal (and it will be used as the initial password
+ // for the pricipal), changing the password on a principal that doesn't exist yet doesn't make sense
+ if (_owningPrincipal.unpersisted)
+ throw new InvalidOperationException(StringResources.PasswordInfoChangePwdOnUnpersistedPrinc);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "ChangePassword: sending request");
+ _owningPrincipal.GetStoreCtxToUse().ChangePassword(_owningPrincipal, oldPassword, newPassword);
+ }
+
+ private bool _expirePasswordImmediately = false;
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void ExpirePasswordNow()
+ {
+ // If we're not persisted, we just save up the change until we're Saved
+ if (_owningPrincipal.unpersisted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "ExpirePasswordNow: saving until persisted");
+ _expirePasswordImmediately = true;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "ExpirePasswordNow: sending request");
+ _owningPrincipal.GetStoreCtxToUse().ExpirePassword(_owningPrincipal);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void RefreshExpiredPassword()
+ {
+ // If we're not persisted, we undo the expiration we saved up when ExpirePasswordNow was called (if it was).
+ if (_owningPrincipal.unpersisted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "RefreshExpiredPassword: saving until persisted");
+ _expirePasswordImmediately = false;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "RefreshExpiredPassword: sending request");
+ _owningPrincipal.GetStoreCtxToUse().UnexpirePassword(_owningPrincipal);
+ }
+ }
+
+ //
+ // Internal constructor
+ //
+ // <SecurityKernel Critical="True" Ring="1">
+ // <ReferencesCritical Name="Field: owningPrincipal" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal PasswordInfo(AuthenticablePrincipal principal)
+ {
+ _owningPrincipal = principal;
+ }
+
+ //
+ // Private implementation
+ //
+ private AuthenticablePrincipal _owningPrincipal;
+ /*
+ // These methods implement the logic shared by all the get/set accessors for the internal properties
+ T HandleGet<T>(ref T currentValue, string name)
+ {
+ // Check that we actually support this propery in our store
+ //this.owningPrincipal.CheckSupportedProperty(name);
+
+ return currentValue;
+ }
+
+ void HandleSet<T>(ref T currentValue, T newValue, ref bool changed, string name)
+ {
+ // Check that we actually support this propery in our store
+ //this.owningPrincipal.CheckSupportedProperty(name);
+
+ currentValue = newValue;
+ changed = true;
+ }
+ */
+
+ //
+ // Load/Store
+ //
+
+ //
+ // Loading with query results
+ //
+
+ internal void LoadValueIntoProperty(string propertyName, object value)
+ {
+ if (value != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "LoadValueIntoProperty: name=" + propertyName + " value=" + value.ToString());
+ }
+
+ switch (propertyName)
+ {
+ case (PropertyNames.PwdInfoLastPasswordSet):
+ _lastPasswordSet = (Nullable<DateTime>)value;
+ _lastPasswordSetLoaded = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.PwdInfoLastBadPasswordAttempt):
+ _lastBadPasswordAttempt = (Nullable<DateTime>)value;
+ _lastBadPasswordAttemptLoaded = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.PwdInfoPasswordNotRequired):
+ _passwordNotRequired = (bool)value;
+ _passwordNotRequiredChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.PwdInfoPasswordNeverExpires):
+ _passwordNeverExpires = (bool)value;
+ _passwordNeverExpiresChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.PwdInfoCannotChangePassword):
+ _cannotChangePassword = (bool)value;
+ _cannotChangePasswordChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.PwdInfoAllowReversiblePasswordEncryption):
+ _allowReversiblePasswordEncryption = (bool)value;
+ _allowReversiblePasswordEncryptionChanged = LoadState.Loaded;
+ break;
+
+ default:
+ Debug.Fail(String.Format(CultureInfo.CurrentCulture, "PasswordInfo.LoadValueIntoProperty: fell off end looking for {0}", propertyName));
+ break;
+ }
+ }
+
+ //
+ // Getting changes to persist (or to build a query from a QBE filter)
+ //
+
+ // Given a property name, returns true if that property has changed since it was loaded, false otherwise.
+ internal bool GetChangeStatusForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "GetChangeStatusForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case (PropertyNames.PwdInfoPasswordNotRequired):
+ return _passwordNotRequiredChanged == LoadState.Changed;
+
+ case (PropertyNames.PwdInfoPasswordNeverExpires):
+ return _passwordNeverExpiresChanged == LoadState.Changed;
+
+ case (PropertyNames.PwdInfoCannotChangePassword):
+ return _cannotChangePasswordChanged == LoadState.Changed;
+
+ case (PropertyNames.PwdInfoAllowReversiblePasswordEncryption):
+ return _allowReversiblePasswordEncryptionChanged == LoadState.Changed;
+
+ case (PropertyNames.PwdInfoPassword):
+ return (_storedNewPassword != null);
+
+ case (PropertyNames.PwdInfoExpireImmediately):
+ return (_expirePasswordImmediately != false);
+
+ default:
+ Debug.Fail(String.Format(CultureInfo.CurrentCulture, "PasswordInfo.GetChangeStatusForProperty: fell off end looking for {0}", propertyName));
+ return false;
+ }
+ }
+
+ // Given a property name, returns the current value for the property.
+ internal object GetValueForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "GetValueForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case (PropertyNames.PwdInfoPasswordNotRequired):
+ return _passwordNotRequired;
+
+ case (PropertyNames.PwdInfoPasswordNeverExpires):
+ return _passwordNeverExpires;
+
+ case (PropertyNames.PwdInfoCannotChangePassword):
+ return _cannotChangePassword;
+
+ case (PropertyNames.PwdInfoAllowReversiblePasswordEncryption):
+ return _allowReversiblePasswordEncryption;
+
+ case (PropertyNames.PwdInfoPassword):
+ return _storedNewPassword;
+
+ case (PropertyNames.PwdInfoExpireImmediately):
+ return _expirePasswordImmediately;
+
+ default:
+ Debug.Fail(String.Format(CultureInfo.CurrentCulture, "PasswordInfo.GetValueForProperty: fell off end looking for {0}", propertyName));
+ return null;
+ }
+ }
+
+ // Reset all change-tracking status for all properties on the object to "unchanged".
+ internal void ResetAllChangeStatus()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PasswordInfo", "ResetAllChangeStatus");
+
+ _passwordNotRequiredChanged = (_passwordNotRequiredChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _passwordNeverExpiresChanged = (_passwordNeverExpiresChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _cannotChangePasswordChanged = (_cannotChangePasswordChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _allowReversiblePasswordEncryptionChanged = (_allowReversiblePasswordEncryptionChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+
+ _storedNewPassword = null;
+ _expirePasswordImmediately = false;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Principal.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Principal.cs
new file mode 100644
index 0000000000..dfc3e94384
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Principal.cs
@@ -0,0 +1,1546 @@
+// 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.Diagnostics;
+using System.Globalization;
+using System.Security.Principal;
+using System.Security.Permissions;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Collections;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ [System.Diagnostics.DebuggerDisplay("Name ( {Name} )")]
+ abstract public class Principal : IDisposable
+ {
+ //
+ // Public properties
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="get_Name():String" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ // Context property
+ public PrincipalContext Context
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // The only way we can't have a PrincipalContext is if we're unpersisted
+ Debug.Assert(_ctx != null || this.unpersisted == true);
+
+ return _ctx;
+ }
+ }
+
+ // ContextType property
+ public ContextType ContextType
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_ContextType():System.DirectoryServices.AccountManagement.ContextType" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // The only way we can't have a PrincipalContext is if we're unpersisted
+ Debug.Assert(_ctx != null || this.unpersisted == true);
+
+ if (_ctx == null)
+ throw new InvalidOperationException(StringResources.PrincipalMustSetContextForProperty);
+
+ return _ctx.ContextType;
+ }
+ }
+
+ // Description property
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string _description = null; // the actual property value
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private LoadState _descriptionChanged = LoadState.NotSet; // change-tracking
+
+ public string Description
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="HandleGet<System.String>(String&, String, LoadState&):String" />
+ // <ReferencesCritical Name="Method: HandleGet(T&, String, LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return HandleGet<string>(ref _description, PropertyNames.PrincipalDescription, ref _descriptionChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="GetStoreCtxToUse():StoreCtx" />
+ // <SatisfiesLinkDemand Name="HandleSet<System.String>(String&, String, LoadState&, String):Void" />
+ // <ReferencesCritical Name="Method: GetStoreCtxToUse():StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: HandleSet(T&, T, LoadState&, String):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.PrincipalDescription))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _description, value, ref _descriptionChanged, PropertyNames.PrincipalDescription);
+ }
+ }
+
+ // DisplayName property
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string _displayName = null; // the actual property value
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private LoadState _displayNameChanged = LoadState.NotSet; // change-tracking
+
+ public string DisplayName
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="HandleGet<System.String>(String&, String, LoadState&):String" />
+ // <ReferencesCritical Name="Method: HandleGet(T&, String, LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return HandleGet<string>(ref _displayName, PropertyNames.PrincipalDisplayName, ref _displayNameChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="GetStoreCtxToUse():StoreCtx" />
+ // <SatisfiesLinkDemand Name="HandleSet<System.String>(String&, String, LoadState&, String):Void" />
+ // <ReferencesCritical Name="Method: GetStoreCtxToUse():StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: HandleSet(T&, T, LoadState&, String):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.PrincipalDisplayName))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _displayName, value, ref _displayNameChanged, PropertyNames.PrincipalDisplayName);
+ }
+ }
+
+ //
+ // Convenience wrappers for the IdentityClaims property
+
+ // SAM Account Name
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string _samName = null; // the actual property value
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private LoadState _samNameChanged = LoadState.NotSet; // change-tracking
+
+ public string SamAccountName
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="HandleGet<System.String>(String&, String, LoadState&):String" />
+ // <ReferencesCritical Name="Method: HandleGet(T&, String, LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return HandleGet<string>(ref _samName, PropertyNames.PrincipalSamAccountName, ref _samNameChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="GetStoreCtxToUse():StoreCtx" />
+ // <SatisfiesLinkDemand Name="HandleSet<System.String>(String&, String, LoadState&, String):Void" />
+ // <ReferencesCritical Name="Method: GetStoreCtxToUse():StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: HandleSet(T&, T, LoadState&, String):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (null == value || 0 == value.Length)
+ throw new ArgumentNullException(String.Format(CultureInfo.CurrentCulture, StringResources.InvalidNullArgument, PropertyNames.PrincipalSamAccountName));
+
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.PrincipalSamAccountName))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _samName, value, ref _samNameChanged, PropertyNames.PrincipalSamAccountName);
+ }
+ }
+
+ // UPN
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string _userPrincipalName = null; // the actual property value
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private LoadState _userPrincipalNameChanged = LoadState.NotSet; // change-tracking
+ public string UserPrincipalName
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="HandleGet<System.String>(String&, String, LoadState&):String" />
+ // <ReferencesCritical Name="Method: HandleGet(T&, String, LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return HandleGet<string>(ref _userPrincipalName, PropertyNames.PrincipalUserPrincipalName, ref _userPrincipalNameChanged);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="GetStoreCtxToUse():StoreCtx" />
+ // <SatisfiesLinkDemand Name="HandleSet<System.String>(String&, String, LoadState&, String):Void" />
+ // <ReferencesCritical Name="Method: GetStoreCtxToUse():StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: HandleSet(T&, T, LoadState&, String):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.PrincipalUserPrincipalName))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _userPrincipalName, value, ref _userPrincipalNameChanged, PropertyNames.PrincipalUserPrincipalName);
+ }
+ }
+
+ // SID
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private SecurityIdentifier _sid = null;
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private LoadState _sidChanged = LoadState.NotSet;
+
+ public SecurityIdentifier Sid
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="HandleGet<System.Security.Principal.SecurityIdentifier>(SecurityIdentifier&, String, LoadState&):SecurityIdentifier" />
+ // <ReferencesCritical Name="Method: HandleGet(T&, String, LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return HandleGet<SecurityIdentifier>(ref _sid, PropertyNames.PrincipalSid, ref _sidChanged);
+ }
+ }
+
+ // GUID
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private Nullable<Guid> _guid = null;
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private LoadState _guidChanged = LoadState.NotSet;
+ public Nullable<Guid> Guid
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="HandleGet<System.Nullable`1<System.Guid>>(Nullable`1<System.Guid>&, String, LoadState&):Nullable`1<System.Guid>" />
+ // <ReferencesCritical Name="Method: HandleGet(T&, String, LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return HandleGet<Nullable<Guid>>(ref _guid, PropertyNames.PrincipalGuid, ref _guidChanged);
+ }
+ }
+
+ // DistinguishedName
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string _distinguishedName = null;
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private LoadState _distinguishedNameChanged = LoadState.NotSet;
+ public string DistinguishedName
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="HandleGet<System.String>(String&, String, LoadState&):String" />
+ // <ReferencesCritical Name="Method: HandleGet(T&, String, LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return HandleGet<string>(ref _distinguishedName, PropertyNames.PrincipalDistinguishedName, ref _distinguishedNameChanged);
+ }
+ }
+
+ // DistinguishedName
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string _structuralObjectClass = null;
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private LoadState _structuralObjectClassChanged = LoadState.NotSet;
+
+ public string StructuralObjectClass
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="HandleGet<System.String>(String&, String, LoadState&):String" />
+ // <ReferencesCritical Name="Method: HandleGet(T&, String, LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return HandleGet<string>(ref _structuralObjectClass, PropertyNames.PrincipalStructuralObjectClass, ref _structuralObjectClassChanged);
+ }
+ }
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string _name = null;
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private LoadState _nameChanged = LoadState.NotSet;
+
+ public string Name
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_ContextType():System.DirectoryServices.AccountManagement.ContextType" />
+ // <SatisfiesLinkDemand Name="HandleGet<System.String>(String&, String, LoadState&):String" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: HandleGet(T&, String, LoadState&):T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ // TODO Store should be mapping both to the same property already....
+
+ // TQ Special case to map name and SamAccountNAme to same cache variable.
+ // This should be removed in the future.
+ // Context type could be null for an unpersisted user.
+ // Default to the original domain behavior if a context is not set.
+
+ ContextType ct = (_ctx == null) ? ContextType.Domain : _ctx.ContextType;
+
+ if (ct == ContextType.Machine)
+ {
+ return HandleGet<string>(ref _samName, PropertyNames.PrincipalSamAccountName, ref _samNameChanged);
+ }
+ else
+ {
+ return HandleGet<string>(ref _name, PropertyNames.PrincipalName, ref _nameChanged);
+ }
+ }
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="GetStoreCtxToUse():StoreCtx" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_ContextType():System.DirectoryServices.AccountManagement.ContextType" />
+ // <SatisfiesLinkDemand Name="HandleSet<System.String>(String&, String, LoadState&, String):Void" />
+ // <ReferencesCritical Name="Method: GetStoreCtxToUse():StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: HandleSet(T&, T, LoadState&, String):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (null == value || 0 == value.Length)
+ throw new ArgumentNullException(String.Format(CultureInfo.CurrentCulture, StringResources.InvalidNullArgument, PropertyNames.PrincipalName));
+
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.PrincipalName))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ ContextType ct = (_ctx == null) ? ContextType.Domain : _ctx.ContextType;
+
+ if (ct == ContextType.Machine)
+ {
+ HandleSet<string>(ref _samName, value, ref _samNameChanged, PropertyNames.PrincipalSamAccountName);
+ }
+ else
+ {
+ HandleSet<string>(ref _name, value, ref _nameChanged, PropertyNames.PrincipalName);
+ }
+ }
+ }
+
+ private ExtensionHelper _extensionHelper;
+
+ [System.Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ internal ExtensionHelper ExtensionHelper
+ {
+ get
+ {
+ if (null == _extensionHelper)
+ _extensionHelper = new ExtensionHelper(this);
+
+ return _extensionHelper;
+ }
+ }
+
+ //
+ // Public methods
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindByIdentityWithType(PrincipalContext, Type, String):Principal" />
+ // <ReferencesCritical Name="Method: FindByIdentityWithType(PrincipalContext, Type, String):Principal" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public static Principal FindByIdentity(PrincipalContext context, string identityValue)
+ {
+ return FindByIdentityWithType(context, typeof(Principal), identityValue);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindByIdentityWithType(PrincipalContext, Type, IdentityType, String):Principal" />
+ // <ReferencesCritical Name="Method: FindByIdentityWithType(PrincipalContext, Type, IdentityType, String):Principal" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public static Principal FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
+ {
+ return FindByIdentityWithType(context, typeof(Principal), identityType, identityValue);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <SatisfiesLinkDemand Name="CheckFakePrincipal():Void" />
+ // <SatisfiesLinkDemand Name="GetStoreCtxToUse():StoreCtx" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.ContextForType(System.Type):System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: GetStoreCtxToUse():StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.ContextForType(System.Type):System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Save()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Entering Save");
+
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Make sure we're not a fake principal
+ CheckFakePrincipal();
+
+ // We must have a PrincipalContext to save into. This should always be the case, unless we're unpersisted
+ // and they never set a PrincipalContext.
+ if (_ctx == null)
+ {
+ Debug.Assert(this.unpersisted == true);
+ throw new InvalidOperationException(StringResources.PrincipalMustSetContextForSave);
+ }
+
+ // Call the appropriate operation depending on whether this is an insert or update
+ StoreCtx storeCtxToUse = GetStoreCtxToUse();
+ Debug.Assert(storeCtxToUse != null); // since we know this.ctx isn't null
+
+ if (this.unpersisted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Save: inserting principal of type {0} using {1}", this.GetType(), storeCtxToUse.GetType());
+ Debug.Assert(storeCtxToUse == _ctx.ContextForType(this.GetType()));
+ storeCtxToUse.Insert(this);
+ this.unpersisted = false; // once we persist, we're no longer in the unpersisted state
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Save: updating principal of type {0} using {1}", this.GetType(), storeCtxToUse.GetType());
+ Debug.Assert(storeCtxToUse == _ctx.QueryCtx);
+ storeCtxToUse.Update(this);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <SatisfiesLinkDemand Name="CheckFakePrincipal():Void" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_ContextType():System.DirectoryServices.AccountManagement.ContextType" />
+ // <SatisfiesLinkDemand Name="Save():Void" />
+ // <SatisfiesLinkDemand Name="GetStoreCtxToUse():StoreCtx" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.ContextForType(System.Type):System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.set_QueryCtx(System.DirectoryServices.AccountManagement.StoreCtx):System.Void" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: GetStoreCtxToUse():StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.ContextForType(System.Type):System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.set_QueryCtx(System.DirectoryServices.AccountManagement.StoreCtx):System.Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Save(PrincipalContext context)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Entering Save(Context)");
+
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Make sure we're not a fake principal
+ CheckFakePrincipal();
+
+ if (context.ContextType == ContextType.Machine || _ctx.ContextType == ContextType.Machine)
+ {
+ throw new InvalidOperationException(StringResources.SaveToNotSupportedAgainstMachineStore);
+ }
+ // We must have a PrincipalContext to save into. This should always be the case, unless we're unpersisted
+ // and they never set a PrincipalContext.
+ if (context == null)
+ {
+ Debug.Assert(this.unpersisted == true);
+ throw new InvalidOperationException(StringResources.NullArguments);
+ }
+
+ // If the user is trying to save to the same context we are already set to then just save the changes
+ if (context == _ctx)
+ {
+ Save();
+ return;
+ }
+
+ // If we already have a context set on this object then make sure the new
+ // context is of the same type.
+ if (context.ContextType != _ctx.ContextType)
+ {
+ Debug.Assert(this.unpersisted == true);
+ throw new InvalidOperationException(StringResources.SaveToMustHaveSamecontextType);
+ }
+
+ StoreCtx originalStoreCtx = GetStoreCtxToUse();
+
+ _ctx = context;
+
+ // Call the appropriate operation depending on whether this is an insert or update
+ StoreCtx newStoreCtx = GetStoreCtxToUse();
+
+ Debug.Assert(newStoreCtx != null); // since we know this.ctx isn't null
+ Debug.Assert(originalStoreCtx != null); // since we know this.ctx isn't null
+
+ if (this.unpersisted)
+ {
+ // We have an unpersisted principal so we just want to create a principal in the new store.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Save(context): inserting new principal of type {0} using {1}", this.GetType(), newStoreCtx.GetType());
+ Debug.Assert(newStoreCtx == _ctx.ContextForType(this.GetType()));
+ newStoreCtx.Insert(this);
+ this.unpersisted = false; // once we persist, we're no longer in the unpersisted state
+ }
+ else
+ {
+ // We have a principal that already exists. We need to move it to the new store.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Save(context): Moving principal of type {0} using {1}", this.GetType(), newStoreCtx.GetType());
+
+ // we are now saving to a new store so this principal is unpersisted.
+ this.unpersisted = true;
+
+ // If the user has modified the name save away the current name so
+ // if the move succeeds and the update fails we will move the item back to the original
+ // store with the original name.
+ bool nameModified = _nameChanged == LoadState.Changed;
+ string previousName = null;
+
+ if (nameModified)
+ {
+ string newName = _name;
+ _ctx.QueryCtx.Load(this, PropertyNames.PrincipalName);
+ previousName = _name;
+ this.Name = newName;
+ }
+
+ newStoreCtx.Move(originalStoreCtx, this);
+
+ try
+ {
+ this.unpersisted = false; // once we persist, we're no longer in the unpersisted state
+
+ newStoreCtx.Update(this);
+ }
+ catch (System.SystemException e)
+ {
+ try
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Principal", "Save(context):, Update Failed (attempting to move back) Exception {0} ", e.Message);
+
+ if (nameModified)
+ this.Name = previousName;
+
+ originalStoreCtx.Move(newStoreCtx, this);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Move back succeeded");
+ }
+ catch (System.SystemException deleteFail)
+ {
+ // The move back failed. Just continue we will throw the original exception below.
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Principal", "Save(context):, Move back Failed {0} ", deleteFail.Message);
+ }
+
+ if (e is System.Runtime.InteropServices.COMException)
+ throw ExceptionHelper.GetExceptionFromCOMException((System.Runtime.InteropServices.COMException)e);
+ else
+ throw e;
+ }
+ }
+
+ _ctx.QueryCtx = newStoreCtx; // so Updates go to the right StoreCtx
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <SatisfiesLinkDemand Name="CheckFakePrincipal():Void" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Delete()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Entering Delete");
+
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Make sure we're not a fake principal
+ CheckFakePrincipal();
+
+ // If we're unpersisted, nothing to delete
+ if (this.unpersisted)
+ throw new InvalidOperationException(StringResources.PrincipalCantDeleteUnpersisted);
+
+ // Since we're not unpersisted, we must have come back from a query, and the query logic would
+ // have filled in a PrincipalContext on us.
+ Debug.Assert(_ctx != null);
+
+ _ctx.QueryCtx.Delete(this);
+ _isDeleted = true;
+ }
+
+ public override bool Equals(object o)
+ {
+ Principal that = o as Principal;
+
+ if (that == null)
+ return false;
+
+ if (Object.ReferenceEquals(this, that))
+ return true;
+
+ if ((_key != null) && (that._key != null) && (_key.Equals(that._key)))
+ return true;
+
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <SatisfiesLinkDemand Name="CheckFakePrincipal():Void" />
+ // <SatisfiesLinkDemand Name="get_UnderlyingObject():Object" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public object GetUnderlyingObject()
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Make sure we're not a fake principal
+ CheckFakePrincipal();
+
+ if (this.UnderlyingObject == null)
+ {
+ throw new InvalidOperationException(StringResources.PrincipalMustPersistFirst);
+ }
+
+ return this.UnderlyingObject;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <SatisfiesLinkDemand Name="CheckFakePrincipal():Void" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.ContextForType(System.Type):System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.ContextForType(System.Type):System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public Type GetUnderlyingObjectType()
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Make sure we're not a fake principal
+ CheckFakePrincipal();
+
+ if (this.unpersisted)
+ {
+ // If we're unpersisted, we can't determine the native type until our PrincipalContext has been set.
+ if (_ctx != null)
+ {
+ return _ctx.ContextForType(this.GetType()).NativeType(this);
+ }
+ else
+ {
+ throw new InvalidOperationException(StringResources.PrincipalMustSetContextForNative);
+ }
+ }
+ else
+ {
+ Debug.Assert(_ctx != null);
+ return _ctx.QueryCtx.NativeType(this);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="GetGroupsHelper():ResultSet" />
+ // <SatisfiesLinkDemand Name="PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.Principal>..ctor(System.DirectoryServices.AccountManagement.ResultSet)" />
+ // <ReferencesCritical Name="Method: GetGroupsHelper():ResultSet" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public PrincipalSearchResult<Principal> GetGroups()
+ {
+ return new PrincipalSearchResult<Principal>(GetGroupsHelper());
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="GetGroupsHelper(PrincipalContext):ResultSet" />
+ // <SatisfiesLinkDemand Name="PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.Principal>..ctor(System.DirectoryServices.AccountManagement.ResultSet)" />
+ // <ReferencesCritical Name="Method: GetGroupsHelper(PrincipalContext):ResultSet" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public PrincipalSearchResult<Principal> GetGroups(PrincipalContext contextToQuery)
+ {
+ if (contextToQuery == null)
+ throw new ArgumentNullException("contextToQuery");
+
+ return new PrincipalSearchResult<Principal>(GetGroupsHelper(contextToQuery));
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <SatisfiesLinkDemand Name="GroupPrincipal.get_Members():System.DirectoryServices.AccountManagement.PrincipalCollection" />
+ // <SatisfiesLinkDemand Name="PrincipalCollection.Contains(System.DirectoryServices.AccountManagement.Principal):System.Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool IsMemberOf(GroupPrincipal group)
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ if (group == null)
+ throw new ArgumentNullException("group");
+
+ return group.Members.Contains(this);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <SatisfiesLinkDemand Name="GroupPrincipal.FindByIdentity(System.DirectoryServices.AccountManagement.PrincipalContext,System.DirectoryServices.AccountManagement.IdentityType,System.String):System.DirectoryServices.AccountManagement.GroupPrincipal" />
+ // <SatisfiesLinkDemand Name="IsMemberOf(GroupPrincipal):Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool IsMemberOf(PrincipalContext context, IdentityType identityType, string identityValue)
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ if (identityValue == null)
+ throw new ArgumentNullException("identityValue");
+
+ GroupPrincipal g = GroupPrincipal.FindByIdentity(context, identityType, identityValue);
+
+ if (g != null)
+ {
+ return IsMemberOf(g);
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "Principal", "IsMemberOf(urn/urn): no matching principal");
+ throw new NoMatchingPrincipalException(StringResources.NoMatchingGroupExceptionText);
+ }
+ }
+
+ //
+ // IDisposable
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="get_UnderlyingObject():Object" />
+ // <SatisfiesLinkDemand Name="get_UnderlyingSearchObject():Object" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public virtual void Dispose()
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Dispose: disposing");
+
+ if ((this.UnderlyingObject != null) && (this.UnderlyingObject is IDisposable))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Dispose: disposing underlying object");
+ ((IDisposable)this.UnderlyingObject).Dispose();
+ }
+
+ if ((this.UnderlyingSearchObject != null) && (this.UnderlyingSearchObject is IDisposable))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Dispose: disposing underlying search object");
+ ((IDisposable)this.UnderlyingSearchObject).Dispose();
+ }
+
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ //
+ //
+ //
+ [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)]
+ protected Principal()
+ {
+ }
+
+ //------------------------------------------------
+ // Protected functions for use by derived classes.
+ //------------------------------------------------
+
+ // Stores all values from derived classes for use at attributes or search filter.
+ private ExtensionCache _extensionCache = new ExtensionCache();
+ private LoadState _extensionCacheChanged = LoadState.NotSet;
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="GetUnderlyingObjectType():Type" />
+ // <SatisfiesLinkDemand Name="GetUnderlyingObject():Object" />
+ // <SatisfiesLinkDemand Name="DirectoryEntry.get_Properties():System.DirectoryServices.PropertyCollection" />
+ // <SatisfiesLinkDemand Name="PropertyCollection.get_Item(System.String):System.DirectoryServices.PropertyValueCollection" />
+ // <SatisfiesLinkDemand Name="PropertyValueCollection.CopyTo(System.Object[],System.Int32):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ protected object[] ExtensionGet(string attribute)
+ {
+ if (null == attribute)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ ExtensionCacheValue val;
+ if (_extensionCache.TryGetValue(attribute, out val))
+ {
+ if (val.Filter)
+ {
+ return null;
+ }
+
+ return val.Value;
+ }
+ else if (this.unpersisted)
+ {
+ return new object[0];
+ }
+ else
+ {
+ Debug.Assert(this.GetUnderlyingObjectType() == typeof(DirectoryEntry));
+ DirectoryEntry de = (DirectoryEntry)this.GetUnderlyingObject();
+
+ int valCount = de.Properties[attribute].Count;
+
+ if (valCount == 0)
+ return new object[0];
+ else
+ {
+ object[] objectArray = new object[valCount];
+ de.Properties[attribute].CopyTo(objectArray, 0);
+ return objectArray;
+ }
+ }
+ }
+
+ private void ValidateExtensionObject(object value)
+ {
+ if (value is object[])
+ {
+ if (((object[])value).Length == 0)
+ throw new ArgumentException(StringResources.InvalidExtensionCollectionType);
+
+ foreach (object o in (object[])value)
+ {
+ if (o is ICollection)
+ throw new ArgumentException(StringResources.InvalidExtensionCollectionType);
+ }
+ }
+ if (value is byte[])
+ {
+ if (((byte[])value).Length == 0)
+ {
+ throw new ArgumentException(StringResources.InvalidExtensionCollectionType);
+ }
+ }
+ else
+ {
+ if (value != null && value is ICollection)
+ {
+ ICollection collection = (ICollection)value;
+ if (collection.Count == 0)
+ throw new ArgumentException(StringResources.InvalidExtensionCollectionType);
+ foreach (object o in collection)
+ {
+ if (o is ICollection)
+ throw new ArgumentException(StringResources.InvalidExtensionCollectionType);
+ }
+ }
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="ValidateExtensionObject(Object):Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ protected void ExtensionSet(string attribute, object value)
+ {
+ if (null == attribute)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ ValidateExtensionObject(value);
+
+ if (value is object[])
+ _extensionCache.properties[attribute] = new ExtensionCacheValue((object[])value);
+ else
+ _extensionCache.properties[attribute] = new ExtensionCacheValue(new object[] { value });
+
+ _extensionCacheChanged = LoadState.Changed;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="ValidateExtensionObject(Object):Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal void AdvancedFilterSet(string attribute, object value, Type objectType, MatchType mt)
+ {
+ if (null == attribute)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ ValidateExtensionObject(value);
+
+ if (value is object[])
+ _extensionCache.properties[attribute] = new ExtensionCacheValue((object[])value, objectType, mt);
+ else
+ _extensionCache.properties[attribute] = new ExtensionCacheValue(new object[] { value }, objectType, mt);
+
+ _extensionCacheChanged = LoadState.Changed; ;
+ }
+
+ //
+ // Internal implementation
+ //
+
+ // True indicates this is a new Principal object that has not yet been persisted to the store
+ internal bool unpersisted = false;
+
+ // True means our store object has been deleted
+ private bool _isDeleted = false;
+
+ // True means that StoreCtx.Load() has been called on this Principal to load in the values
+ // of all the delay-loaded properties.
+ private bool _loaded = false;
+
+ // True means this principal corresponds to one of the well-known SIDs that do not have a
+ // corresponding store object (e.g., NT AUTHORITY\NETWORK SERVICE). Such principals
+ // should be treated as read-only.
+ internal bool fakePrincipal = false;
+
+ // Directly corresponds to the Principal.PrincipalContext public property
+ [System.Security.SecuritySafeCritical]
+ private PrincipalContext _ctx = null;
+
+ internal bool Loaded
+ {
+ set
+ {
+ _loaded = value;
+ }
+ get
+ {
+ return _loaded;
+ }
+ }
+
+ // A low-level way for derived classes to access the ctx field. Note this is intended for internal use only,
+ // hence the LinkDemand.
+ [System.ComponentModel.Browsable(false)]
+ [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
+ internal protected PrincipalContext ContextRaw
+ {
+ //[StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey = Microsoft.Internal.BuildInfo.WINDOWS_PUBLIC_KEY_STRING)]
+ // <SecurityKernel Critical="True" Ring="1">
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ { return _ctx; }
+
+ //[StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey = Microsoft.Internal.BuildInfo.WINDOWS_PUBLIC_KEY_STRING)]
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalContext.CheckDisposed():System.Void" />
+ // <ReferencesCritical Name="Method: PrincipalContext.CheckDisposed():System.Void" Ring="1" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ // Verify that the passed context is not disposed.
+ if (value != null)
+ value.CheckDisposed();
+ _ctx = value;
+ }
+ }
+
+ static internal Principal MakePrincipal(PrincipalContext ctx, Type principalType)
+ {
+ Principal p = null;
+
+ System.Reflection.ConstructorInfo CI = principalType.GetConstructor(new Type[] { typeof(PrincipalContext) });
+
+ if (null == CI)
+ {
+ throw new NotSupportedException(StringResources.ExtensionInvalidClassDefinitionConstructor);
+ }
+
+ p = (Principal)CI.Invoke(new object[] { ctx });
+
+ if (null == p)
+ {
+ throw new NotSupportedException(StringResources.ExtensionInvalidClassDefinitionConstructor);
+ }
+
+ p.unpersisted = false;
+ return p;
+ }
+
+ // Depending on whether we're to-be-inserted or were retrieved from a query,
+ // returns the appropriate StoreCtx from the PrincipalContext that we should use for
+ // all StoreCtx-related operations.
+ // Returns null if no context has been set yet.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalContext.ContextForType(System.Type):System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.ContextForType(System.Type):System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ internal StoreCtx GetStoreCtxToUse()
+ {
+ if (_ctx == null)
+ {
+ Debug.Assert(this.unpersisted == true);
+ return null;
+ }
+
+ if (this.unpersisted)
+ {
+ return _ctx.ContextForType(this.GetType());
+ }
+ else
+ {
+ return _ctx.QueryCtx;
+ }
+ }
+
+ // The underlying object (e.g., DirectoryEntry, Item) corresponding to this Principal.
+ // Set by StoreCtx.GetAsPrincipal when this Principal was instantiated by it.
+ // If not set, this is a unpersisted principal and StoreCtx.PushChangesToNative()
+ // has not yet been called on it
+ private object _underlyingObject = null;
+ internal object UnderlyingObject
+ {
+ get
+ {
+ if (_underlyingObject != null)
+ return _underlyingObject;
+
+ return null;
+ }
+
+ set
+ {
+ _underlyingObject = value;
+ }
+ }
+
+ // The underlying search object (e.g., SearcResult, Item) corresponding to this Principal.
+ // Set by StoreCtx.GetAsPrincipal when this Principal was instantiated by it.
+ // If not set, this object was not created from a search. We need to store the searchresult until the object is persisted because
+ // we may need to load properties from it.
+ private object _underlyingSearchObject = null;
+ internal object UnderlyingSearchObject
+ {
+ get
+ {
+ if (_underlyingSearchObject != null)
+ return _underlyingSearchObject;
+
+ return null;
+ }
+
+ set
+ {
+ _underlyingSearchObject = value;
+ }
+ }
+
+ // Optional. This property exists entirely for the use of the StoreCtxs. When UnderlyingObject
+ // can correspond to more than one possible principal in the store (e.g., WinFS's "multiple principals
+ // per contact" model), the StoreCtx can use this to track and discern which principal in the
+ // UnderlyingObject this Principal object corresponds to. Set by GetAsPrincipal(), if set at all.
+ private object _discriminant = null;
+ internal object Discriminant
+ {
+ get { return _discriminant; }
+ set { _discriminant = value; }
+ }
+
+ // A store-specific key, used to determine if two CLR Principal objects represent the same store principal.
+ // Set by GetAsPrincipal when Principal is created from a query, or when a unpersisted Principal is persisted.
+ private StoreKey _key = null;
+ internal StoreKey Key
+ {
+ get { return _key; }
+ set { _key = value; }
+ }
+
+ private bool _disposed = false;
+
+ // Checks if the principal has been disposed or deleted, and throws an appropriate exception if it has.
+ [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.Security.SecuritySafeCritical]
+ protected void CheckDisposedOrDeleted()
+ {
+ if (_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "Principal", "CheckDisposedOrDeleted: accessing disposed object");
+ throw new ObjectDisposedException(this.GetType().ToString());
+ }
+
+ if (_isDeleted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "Principal", "CheckDisposedOrDeleted: accessing deleted object");
+ throw new InvalidOperationException(StringResources.PrincipalDeleted);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindByIdentityWithTypeHelper(PrincipalContext, Type, Nullable`1<System.DirectoryServices.AccountManagement.IdentityType>, String, DateTime):Principal" />
+ // <ReferencesCritical Name="Method: FindByIdentityWithTypeHelper(PrincipalContext, Type, Nullable`1<System.DirectoryServices.AccountManagement.IdentityType>, String, DateTime):Principal" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)]
+ protected static Principal FindByIdentityWithType(PrincipalContext context, Type principalType, string identityValue)
+ {
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ if (identityValue == null)
+ throw new ArgumentNullException("identityValue");
+
+ return FindByIdentityWithTypeHelper(context, principalType, null, identityValue, DateTime.UtcNow);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="FindByIdentityWithTypeHelper(PrincipalContext, Type, Nullable`1<System.DirectoryServices.AccountManagement.IdentityType>, String, DateTime):Principal" />
+ // <ReferencesCritical Name="Method: FindByIdentityWithTypeHelper(PrincipalContext, Type, Nullable`1<System.DirectoryServices.AccountManagement.IdentityType>, String, DateTime):Principal" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)]
+ protected static Principal FindByIdentityWithType(PrincipalContext context, Type principalType, IdentityType identityType, string identityValue)
+ {
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ if (identityValue == null)
+ throw new ArgumentNullException("identityValue");
+
+ if ((identityType < IdentityType.SamAccountName) || (identityType > IdentityType.Guid))
+ throw new InvalidEnumArgumentException("identityType", (int)identityType, typeof(IdentityType));
+
+ return FindByIdentityWithTypeHelper(context, principalType, identityType, identityValue, DateTime.UtcNow);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ private static Principal FindByIdentityWithTypeHelper(PrincipalContext context, Type principalType, Nullable<IdentityType> identityType, string identityValue, DateTime refDate)
+ {
+ // Ask the store to find a Principal based on this IdentityReference info.
+ Principal p = context.QueryCtx.FindPrincipalByIdentRef(principalType, (identityType == null) ? null : (string)IdentMap.StringMap[(int)identityType, 1], identityValue, refDate);
+
+ // Did we find a match?
+ if (p != null)
+ {
+ // Given the native object, ask the StoreCtx to construct a Principal object for us.
+ return p;
+ }
+ else
+ {
+ // No match.
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "Principal", "FindByIdentityWithTypeHelper: no match");
+ return null;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ private ResultSet GetGroupsHelper()
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Unpersisted principals are not members of any group
+ if (this.unpersisted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "GetGroupsHelper: returning empty set");
+ return new EmptySet();
+ }
+
+ StoreCtx storeCtx = GetStoreCtxToUse();
+ Debug.Assert(storeCtx != null);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "GetGroupsHelper: querying");
+ ResultSet resultSet = storeCtx.GetGroupsMemberOf(this);
+
+ return resultSet;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ private ResultSet GetGroupsHelper(PrincipalContext contextToQuery)
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ if (_ctx == null)
+ throw new InvalidOperationException(StringResources.UserMustSetContextForMethod);
+
+ StoreCtx storeCtx = GetStoreCtxToUse();
+ Debug.Assert(storeCtx != null);
+
+ return contextToQuery.QueryCtx.GetGroupsMemberOf(this, storeCtx);
+ }
+
+ // If we're the result of a query and our properties haven't been loaded yet, do so now
+ // We'd like this to be marked protected AND internal, but that's not possible, so we'll settle for
+ // internal and treat it as if it were also protected.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal void LoadIfNeeded(string principalPropertyName)
+ {
+ // Fake principals have nothing to load, since they have no store object.
+ // Just set the loaded flag.
+ if (this.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "LoadIfNeeded: not needed, fake principal");
+
+ Debug.Assert(this.unpersisted == false);
+ }
+ else if (!this.unpersisted)
+ {
+ // We came back from a query --> our PrincipalContext must be filled in
+ Debug.Assert(_ctx != null);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "LoadIfNeeded: loading");
+
+ // Just load the requested property...
+ _ctx.QueryCtx.Load(this, principalPropertyName);
+ }
+ }
+
+ // Checks if this is a fake principal, and throws an appropriate exception if so.
+ // We'd like this to be marked protected AND internal, but that's not possible, so we'll settle for
+ // internal and treat it as if it were also protected.
+ internal void CheckFakePrincipal()
+ {
+ if (this.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "Principal", "CheckFakePrincipal: fake principal");
+ throw new InvalidOperationException(StringResources.PrincipalNotSupportedOnFakePrincipal);
+ }
+ }
+
+ // These methods implement the logic shared by all the get/set accessors for the public properties.
+
+ // We pass currentValue by ref, even though we don't directly modify it, because if the LoadIfNeeded()
+ // call causes the data to be loaded, we need to pick up the post-load value, not the (empty) value at the point
+ // HandleGet<T> was called.
+ //
+ // We'd like this to be marked protected AND internal, but that's not possible, so we'll settle for
+ // internal and treat it as if it were also protected.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // <SatisfiesLinkDemand Name="LoadIfNeeded(String):Void" />
+ // <ReferencesCritical Name="Method: LoadIfNeeded(String):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal T HandleGet<T>(ref T currentValue, string name, ref LoadState state)
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Check that we actually support this propery in our store
+ //CheckSupportedProperty(name);
+
+ if (state == LoadState.NotSet)
+ {
+ // Load in the value, if not yet done so
+ LoadIfNeeded(name);
+ state = LoadState.Loaded;
+ }
+
+ return currentValue;
+ }
+
+ // We'd like this to be marked protected AND internal, but that's not possible, so we'll settle for
+ // internal and treat it as if it were also protected.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposedOrDeleted():Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal void HandleSet<T>(ref T currentValue, T newValue, ref LoadState state, string name)
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Check that we actually support this propery in our store
+ //CheckSupportedProperty(name);
+
+ // Need to do this now so that newly-set value doesn't get overwritten by later load
+ // LoadIfNeeded(name);
+
+ currentValue = newValue;
+ state = LoadState.Changed;
+ }
+
+ //
+ // Load/Store implementation
+ //
+
+ //
+ // Loading with query results
+ //
+
+ // Given a property name like "Principal.DisplayName",
+ // writes the value into the internal field backing that property and
+ // resets the change-tracking for that property to "unchanged".
+ //
+ // If the property is a scalar property, then value is simply an object of the property type
+ // (e.g., a string for a string-valued property).
+ // If the property is an IdentityClaimCollection property, then value must be a List<IdentityClaim>.
+ // If the property is a ValueCollection<T>, then value must be a List<T>.
+ // If the property is a X509Certificate2Collection, then value must be a List<byte[]>, where
+ // each byte[] is a certificate.
+ // (The property can never be a PrincipalCollection, since such properties
+ // are not loaded by StoreCtx.Load()).
+ //[StrongNameIdentityPermission(SecurityAction.InheritanceDemand, PublicKey = Microsoft.Internal.BuildInfo.WINDOWS_PUBLIC_KEY_STRING)]
+ // ExtensionCache is never directly loaded by the store hence it does not exist in the switch
+ internal virtual void LoadValueIntoProperty(string propertyName, object value)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "LoadValueIntoProperty: name=" + propertyName + " value=" + (value == null ? "null" : value.ToString()));
+
+ switch (propertyName)
+ {
+ case PropertyNames.PrincipalDisplayName:
+ _displayName = (string)value;
+ _displayNameChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.PrincipalDescription:
+ _description = (string)value;
+ _descriptionChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.PrincipalSamAccountName:
+ _samName = (string)value;
+ _samNameChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.PrincipalUserPrincipalName:
+ _userPrincipalName = (string)value;
+ _userPrincipalNameChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.PrincipalSid:
+ SecurityIdentifier SID = (SecurityIdentifier)value;
+ _sid = SID;
+ _sidChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.PrincipalGuid:
+ Guid PrincipalGuid = (Guid)value;
+ _guid = PrincipalGuid;
+ _guidChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.PrincipalDistinguishedName:
+ _distinguishedName = (string)value;
+ _distinguishedNameChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.PrincipalStructuralObjectClass:
+ _structuralObjectClass = (string)value;
+ _structuralObjectClassChanged = LoadState.Loaded;
+ break;
+
+ case PropertyNames.PrincipalName:
+ _name = (string)value;
+ _nameChanged = LoadState.Loaded;
+ break;
+
+ default:
+ // If we're here, we didn't find the property. They probably asked for a property we don't
+ // support (e.g., we're a Group, and they asked for PropertyNames.UserEmailAddress).
+ break;
+ }
+ }
+
+ //
+ // Getting changes to persist (or to build a query from a QBE filter)
+ //
+
+ // Given a property name, returns true if that property has changed since it was loaded, false otherwise.
+ //[StrongNameIdentityPermission(SecurityAction.InheritanceDemand, PublicKey = Microsoft.Internal.BuildInfo.WINDOWS_PUBLIC_KEY_STRING)]
+ [System.Security.SecuritySafeCritical]
+ internal virtual bool GetChangeStatusForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "GetChangeStatusForProperty: name=" + propertyName);
+ LoadState currentPropState;
+
+ switch (propertyName)
+ {
+ case PropertyNames.PrincipalDisplayName:
+ currentPropState = _displayNameChanged;
+ break;
+
+ case PropertyNames.PrincipalDescription:
+ currentPropState = _descriptionChanged;
+ break;
+
+ case PropertyNames.PrincipalSamAccountName:
+ currentPropState = _samNameChanged;
+ break;
+
+ case PropertyNames.PrincipalUserPrincipalName:
+ currentPropState = _userPrincipalNameChanged;
+ break;
+
+ case PropertyNames.PrincipalSid:
+ currentPropState = _sidChanged;
+ break;
+
+ case PropertyNames.PrincipalGuid:
+ currentPropState = _guidChanged;
+ break;
+
+ case PropertyNames.PrincipalDistinguishedName:
+ currentPropState = _distinguishedNameChanged;
+ break;
+
+ case PropertyNames.PrincipalStructuralObjectClass:
+ currentPropState = _structuralObjectClassChanged;
+ break;
+
+ case PropertyNames.PrincipalName:
+ currentPropState = _nameChanged;
+ break;
+
+ case PropertyNames.PrincipalExtensionCache:
+ currentPropState = _extensionCacheChanged;
+ break;
+
+ default:
+ // If we're here, we didn't find the property. They probably asked for a property we don't
+ // support (e.g., we're a User, and they asked for PropertyNames.GroupMembers). Since we don't
+ // have it, it didn't change.
+ currentPropState = LoadState.NotSet;
+ break;
+ }
+
+ return (currentPropState == LoadState.Changed);
+ }
+
+ // Given a property name, returns the current value for the property.
+ // Generally, this method is called only if GetChangeStatusForProperty indicates there are changes on the
+ // property specified.
+ //
+ // If the property is a scalar property, the return value is an object of the property type.
+ // If the property is an IdentityClaimCollection property, the return value is the IdentityClaimCollection
+ // itself.
+ // If the property is a ValueCollection<T>, the return value is the ValueCollection<T> itself.
+ // If the property is a X509Certificate2Collection, the return value is the X509Certificate2Collection itself.
+ // If the property is a PrincipalCollection, the return value is the PrincipalCollection itself.
+ //[StrongNameIdentityPermission(SecurityAction.InheritanceDemand, PublicKey = Microsoft.Internal.BuildInfo.WINDOWS_PUBLIC_KEY_STRING)]
+ internal virtual object GetValueForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "GetValueForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case PropertyNames.PrincipalDisplayName:
+ return _displayName;
+
+ case PropertyNames.PrincipalDescription:
+ return _description;
+
+ case PropertyNames.PrincipalSamAccountName:
+ return _samName;
+
+ case PropertyNames.PrincipalUserPrincipalName:
+ return _userPrincipalName;
+
+ case PropertyNames.PrincipalSid:
+ return _sid;
+
+ case PropertyNames.PrincipalGuid:
+ return _guid;
+
+ case PropertyNames.PrincipalDistinguishedName:
+ return _distinguishedName;
+
+ case PropertyNames.PrincipalStructuralObjectClass:
+ return _structuralObjectClass;
+
+ case PropertyNames.PrincipalName:
+ return _name;
+
+ case PropertyNames.PrincipalExtensionCache:
+ return _extensionCache;
+
+ default:
+ Debug.Fail(String.Format(CultureInfo.CurrentCulture, "Principal.GetValueForProperty: Ran off end of list looking for {0}", propertyName));
+ return null;
+ }
+ }
+
+ // Reset all change-tracking status for all properties on the object to "unchanged".
+ // This is used by StoreCtx.Insert() and StoreCtx.Update() to reset the change-tracking after they
+ // have persisted all current changes to the store.
+ //[StrongNameIdentityPermission(SecurityAction.InheritanceDemand, PublicKey = Microsoft.Internal.BuildInfo.WINDOWS_PUBLIC_KEY_STRING)]
+ internal virtual void ResetAllChangeStatus()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "ResetAllChangeStatus");
+
+ _displayNameChanged = (_displayNameChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _descriptionChanged = (_descriptionChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _samNameChanged = (_samNameChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _userPrincipalNameChanged = (_userPrincipalNameChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _sidChanged = (_sidChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _guidChanged = (_guidChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _distinguishedNameChanged = (_distinguishedNameChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _nameChanged = (_nameChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ _extensionCacheChanged = (_extensionCacheChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalCollection.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalCollection.cs
new file mode 100644
index 0000000000..a52dcd8c2a
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalCollection.cs
@@ -0,0 +1,904 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ public class PrincipalCollection : ICollection<Principal>, ICollection, IEnumerable<Principal>, IEnumerable
+ {
+ //
+ // ICollection
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="PrincipalCollectionEnumerator..ctor(System.DirectoryServices.AccountManagement.ResultSet,System.DirectoryServices.AccountManagement.PrincipalCollection,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>)" />
+ // <SatisfiesLinkDemand Name="PrincipalCollectionEnumerator.get_Current():System.DirectoryServices.AccountManagement.Principal" />
+ // <SatisfiesLinkDemand Name="PrincipalCollectionEnumerator.MoveNext():System.Boolean" />
+ // <ReferencesCritical Name="Method: PrincipalCollectionEnumerator.get_Current():System.DirectoryServices.AccountManagement.Principal" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalCollectionEnumerator.MoveNext():System.Boolean" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ void ICollection.CopyTo(Array array, int index)
+ {
+ CheckDisposed();
+
+ // Parameter validation
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ if (array == null)
+ throw new ArgumentNullException("array");
+
+ if (array.Rank != 1)
+ throw new ArgumentException(StringResources.PrincipalCollectionNotOneDimensional);
+
+ if (index >= array.GetLength(0))
+ throw new ArgumentException(StringResources.PrincipalCollectionIndexNotInArray);
+
+ ArrayList tempArray = new ArrayList();
+
+ lock (_resultSet)
+ {
+ ResultSetBookmark bookmark = null;
+
+ try
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "CopyTo: bookmarking");
+
+ bookmark = _resultSet.BookmarkAndReset();
+
+ PrincipalCollectionEnumerator containmentEnumerator =
+ new PrincipalCollectionEnumerator(
+ _resultSet,
+ this,
+ _removedValuesCompleted,
+ _removedValuesPending,
+ _insertedValuesCompleted,
+ _insertedValuesPending);
+
+ int arraySize = array.GetLength(0) - index;
+ int tempArraySize = 0;
+
+ while (containmentEnumerator.MoveNext())
+ {
+ tempArray.Add(containmentEnumerator.Current);
+ checked { tempArraySize++; }
+
+ // Make sure the array has enough space, allowing for the "index" offset.
+ // We check inline, rather than doing a PrincipalCollection.Count upfront,
+ // because counting is just as expensive as enumerating over all the results, so we
+ // only want to do it once.
+ if (arraySize < tempArraySize)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn,
+ "PrincipalCollection",
+ "CopyTo: array too small (has {0}, need >= {1}",
+ arraySize,
+ tempArraySize);
+
+ throw new ArgumentException(StringResources.PrincipalCollectionArrayTooSmall);
+ }
+ }
+ }
+ finally
+ {
+ if (bookmark != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "CopyTo: restoring from bookmark");
+ _resultSet.RestoreBookmark(bookmark);
+ }
+ }
+ }
+
+ foreach (object o in tempArray)
+ {
+ array.SetValue(o, index);
+ checked { index++; }
+ }
+ }
+
+ int ICollection.Count
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="get_Count():Int32" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return Count;
+ }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="get_IsSynchronized():Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return IsSynchronized;
+ }
+ }
+
+ object ICollection.SyncRoot
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="get_SyncRoot():Object" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return SyncRoot;
+ }
+ }
+
+ public bool IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public object SyncRoot
+ {
+ get
+ {
+ return this;
+ }
+ }
+
+ //
+ // IEnumerable
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="GetEnumerator():IEnumerator`1<System.DirectoryServices.AccountManagement.Principal>" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return (IEnumerator)GetEnumerator();
+ }
+
+ //
+ // ICollection<Principal>
+ //
+ public void CopyTo(Principal[] array, int index)
+ {
+ ((ICollection)this).CopyTo((Array)array, index);
+ }
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public int Count
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="PrincipalCollectionEnumerator..ctor(System.DirectoryServices.AccountManagement.ResultSet,System.DirectoryServices.AccountManagement.PrincipalCollection,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>)" />
+ // <SatisfiesLinkDemand Name="PrincipalCollectionEnumerator.MoveNext():System.Boolean" />
+ // <ReferencesCritical Name="Method: PrincipalCollectionEnumerator.MoveNext():System.Boolean" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ CheckDisposed();
+
+ // Yes, this is potentially quite expensive. Count is unfortunately
+ // an expensive operation to perform.
+ lock (_resultSet)
+ {
+ ResultSetBookmark bookmark = null;
+
+ try
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Count: bookmarking");
+
+ bookmark = _resultSet.BookmarkAndReset();
+
+ PrincipalCollectionEnumerator containmentEnumerator =
+ new PrincipalCollectionEnumerator(
+ _resultSet,
+ this,
+ _removedValuesCompleted,
+ _removedValuesPending,
+ _insertedValuesCompleted,
+ _insertedValuesPending);
+
+ int count = 0;
+
+ // Count all the members (including inserted members, but not including removed members)
+ while (containmentEnumerator.MoveNext())
+ {
+ count++;
+ }
+
+ return count;
+ }
+ finally
+ {
+ if (bookmark != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Count: restoring from bookmark");
+ _resultSet.Reset();
+ _resultSet.RestoreBookmark(bookmark);
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // IEnumerable<Principal>
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="PrincipalCollectionEnumerator..ctor(System.DirectoryServices.AccountManagement.ResultSet,System.DirectoryServices.AccountManagement.PrincipalCollection,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.Principal>)" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public IEnumerator<Principal> GetEnumerator()
+ {
+ CheckDisposed();
+
+ return new PrincipalCollectionEnumerator(
+ _resultSet,
+ this,
+ _removedValuesCompleted,
+ _removedValuesPending,
+ _insertedValuesCompleted,
+ _insertedValuesPending);
+ }
+
+ //
+ // Add
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Add(Principal):Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Add(UserPrincipal user)
+ {
+ Add((Principal)user);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Add(Principal):Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Add(GroupPrincipal group)
+ {
+ Add((Principal)group);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Add(Principal):Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Add(ComputerPrincipal computer)
+ {
+ Add((Principal)computer);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="Contains(Principal):Boolean" />
+ // <SatisfiesLinkDemand Name="MarkChange():Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Add(Principal principal)
+ {
+ CheckDisposed();
+
+ if (principal == null)
+ throw new ArgumentNullException("principal");
+
+ if (Contains(principal))
+ throw new PrincipalExistsException(StringResources.PrincipalExistsExceptionText);
+
+ MarkChange();
+
+ // If the value to be added is an uncommitted remove, just remove the uncommitted remove from the list.
+ if (_removedValuesPending.Contains(principal))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Add: removing from removedValuesPending");
+
+ _removedValuesPending.Remove(principal);
+
+ // If they did a Add(x) --> Save() --> Remove(x) --> Add(x), we'll end up with x in neither
+ // the ResultSet or the insertedValuesCompleted list. This is bad. Avoid that by adding x
+ // back to the insertedValuesCompleted list here.
+ //
+ // Note, this will add x to insertedValuesCompleted even if it's already in the resultSet.
+ // This is not a problem --- PrincipalCollectionEnumerator will detect such a situation and
+ // only return x once.
+ if (!_insertedValuesCompleted.Contains(principal))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Add: adding to insertedValuesCompleted");
+ _insertedValuesCompleted.Add(principal);
+ }
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Add: making it a pending insert");
+
+ // make it a pending insert
+ _insertedValuesPending.Add(principal);
+
+ // in case the value to be added is also a previous-but-already-committed remove
+ _removedValuesCompleted.Remove(principal);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="Principal.FindByIdentity(System.DirectoryServices.AccountManagement.PrincipalContext,System.DirectoryServices.AccountManagement.IdentityType,System.String):System.DirectoryServices.AccountManagement.Principal" />
+ // <SatisfiesLinkDemand Name="Add(Principal):Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Add(PrincipalContext context, IdentityType identityType, string identityValue)
+ {
+ CheckDisposed();
+
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ if (identityValue == null)
+ throw new ArgumentNullException("identityValue");
+
+ Principal principal = Principal.FindByIdentity(context, identityType, identityValue);
+
+ if (principal != null)
+ {
+ Add(principal);
+ }
+ else
+ {
+ // No Principal matching the IdentityReference could be found in the PrincipalContext
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalCollection", "Add(urn/urn): no match");
+ throw new NoMatchingPrincipalException(StringResources.NoMatchingPrincipalExceptionText);
+ }
+ }
+
+ //
+ // Clear
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="MarkChange():Void" />
+ // <ReferencesCritical Name="Field: owningGroup" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Clear()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Clear");
+
+ CheckDisposed();
+
+ // Ask the StoreCtx to verify that this group can be cleared. Right now, the only
+ // reason it couldn't is if it's an AD group with one principals that are members of it
+ // by virtue of their primaryGroupId.
+ //
+ // If storeCtxToUse == null, then we must be unpersisted, in which case there clearly
+ // can't be any such primary group members pointing to this group on the store.
+ StoreCtx storeCtxToUse = _owningGroup.GetStoreCtxToUse();
+ string explanation;
+
+ Debug.Assert(storeCtxToUse != null || _owningGroup.unpersisted == true);
+
+ if ((storeCtxToUse != null) && (!storeCtxToUse.CanGroupBeCleared(_owningGroup, out explanation)))
+ throw new InvalidOperationException(explanation);
+
+ MarkChange();
+
+ // We wipe out everything that's been inserted/removed
+ _insertedValuesPending.Clear();
+ _removedValuesPending.Clear();
+ _insertedValuesCompleted.Clear();
+ _removedValuesCompleted.Clear();
+
+ // flag that the collection has been cleared, so the StoreCtx and PrincipalCollectionEnumerator
+ // can take appropriate action
+ _clearPending = true;
+ }
+
+ //
+ // Remove
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Remove(Principal):Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Remove(UserPrincipal user)
+ {
+ return Remove((Principal)user);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Remove(Principal):Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Remove(GroupPrincipal group)
+ {
+ return Remove((Principal)group);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Remove(Principal):Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Remove(ComputerPrincipal computer)
+ {
+ return Remove((Principal)computer);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="MarkChange():Void" />
+ // <SatisfiesLinkDemand Name="Contains(Principal):Boolean" />
+ // <ReferencesCritical Name="Field: owningGroup" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Remove(Principal principal)
+ {
+ CheckDisposed();
+
+ if (principal == null)
+ throw new ArgumentNullException("principal");
+
+ // Ask the StoreCtx to verify that this member can be removed. Right now, the only
+ // reason it couldn't is if it's actually a member by virtue of its primaryGroupId
+ // pointing to this group.
+ //
+ // If storeCtxToUse == null, then we must be unpersisted, in which case there clearly
+ // can't be any such primary group members pointing to this group on the store.
+ StoreCtx storeCtxToUse = _owningGroup.GetStoreCtxToUse();
+ string explanation;
+
+ Debug.Assert(storeCtxToUse != null || _owningGroup.unpersisted == true);
+
+ if ((storeCtxToUse != null) && (!storeCtxToUse.CanGroupMemberBeRemoved(_owningGroup, principal, out explanation)))
+ throw new InvalidOperationException(explanation);
+
+ bool removed = false;
+
+ // If the value was previously inserted, we just remove it from insertedValuesPending.
+ if (_insertedValuesPending.Contains(principal))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Remove: removing from insertedValuesPending");
+
+ MarkChange();
+ _insertedValuesPending.Remove(principal);
+ removed = true;
+
+ // If they did a Remove(x) --> Save() --> Add(x) --> Remove(x), we'll end up with x in neither
+ // the ResultSet or the removedValuesCompleted list. This is bad. Avoid that by adding x
+ // back to the removedValuesCompleted list here.
+ //
+ // At worst, we end up with x on the removedValuesCompleted list even though it's not even in
+ // resultSet. That's not a problem. The only thing we use the removedValuesCompleted list for
+ // is deciding which values in resultSet to skip, anyway.
+ if (!_removedValuesCompleted.Contains(principal))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Remove: adding to removedValuesCompleted");
+ _removedValuesCompleted.Add(principal);
+ }
+ }
+ else
+ {
+ // They're trying to remove a already-persisted value. We add it to the
+ // removedValues list. Then, if it's already been loaded into insertedValuesCompleted,
+ // we remove it from insertedValuesCompleted.
+
+ removed = Contains(principal);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Remove: making it a pending remove, removed={0}", removed);
+
+ if (removed)
+ {
+ MarkChange();
+
+ _removedValuesPending.Add(principal);
+
+ // in case it's the result of a previous-but-already-committed insert
+ _insertedValuesCompleted.Remove(principal);
+ }
+ }
+
+ return removed;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="Principal.FindByIdentity(System.DirectoryServices.AccountManagement.PrincipalContext,System.DirectoryServices.AccountManagement.IdentityType,System.String):System.DirectoryServices.AccountManagement.Principal" />
+ // <SatisfiesLinkDemand Name="Remove(Principal):Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Remove(PrincipalContext context, IdentityType identityType, string identityValue)
+ {
+ CheckDisposed();
+
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ if (identityValue == null)
+ throw new ArgumentNullException("identityValue");
+
+ Principal principal = Principal.FindByIdentity(context, identityType, identityValue);
+
+ if (principal == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalCollection", "Remove(urn/urn): no match");
+ throw new NoMatchingPrincipalException(StringResources.NoMatchingPrincipalExceptionText);
+ }
+
+ return Remove(principal);
+ }
+
+ //
+ // Contains
+ //
+
+ [System.Security.SecuritySafeCritical]
+ private bool ContainsEnumTest(Principal principal)
+ {
+ CheckDisposed();
+
+ if (principal == null)
+ throw new ArgumentNullException("principal");
+
+ // Yes, this is potentially quite expensive. Contains is unfortunately
+ // an expensive operation to perform.
+ lock (_resultSet)
+ {
+ ResultSetBookmark bookmark = null;
+
+ try
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "ContainsEnumTest: bookmarking");
+
+ bookmark = _resultSet.BookmarkAndReset();
+
+ PrincipalCollectionEnumerator containmentEnumerator =
+ new PrincipalCollectionEnumerator(
+ _resultSet,
+ this,
+ _removedValuesCompleted,
+ _removedValuesPending,
+ _insertedValuesCompleted,
+ _insertedValuesPending);
+
+ while (containmentEnumerator.MoveNext())
+ {
+ Principal p = containmentEnumerator.Current;
+
+ if (p.Equals(principal))
+ return true;
+ }
+ }
+ finally
+ {
+ if (bookmark != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "ContainsEnumTest: restoring from bookmark");
+ _resultSet.RestoreBookmark(bookmark);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private bool ContainsNativeTest(Principal principal)
+ {
+ CheckDisposed();
+
+ if (principal == null)
+ throw new ArgumentNullException("principal");
+
+ // If they explicitly inserted it, then we certainly contain it
+ if (_insertedValuesCompleted.Contains(principal) || _insertedValuesPending.Contains(principal))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "ContainsNativeTest: found insert");
+ return true;
+ }
+
+ // If they removed it, we don't contain it, regardless of the group membership on the store
+ if (_removedValuesCompleted.Contains(principal) || _removedValuesPending.Contains(principal))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "ContainsNativeTest: found remove");
+ return false;
+ }
+
+ // The list was cleared at some point and the principal has not been reinsterted yet
+ if (_clearPending || _clearCompleted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "ContainsNativeTest: Clear pending");
+ return false;
+ }
+
+ // Otherwise, check the store
+ if (_owningGroup.unpersisted == false && principal.unpersisted == false)
+ return _owningGroup.GetStoreCtxToUse().IsMemberOfInStore(_owningGroup, principal);
+
+ // We (or the principal) must not be persisted, so there's no store membership to check.
+ // Out of things to check. We must not contain it.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "ContainsNativeTest: no store to check");
+ return false;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Contains(Principal):Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Contains(UserPrincipal user)
+ {
+ return Contains((Principal)user);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Contains(Principal):Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Contains(GroupPrincipal group)
+ {
+ return Contains((Principal)group);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Contains(Principal):Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Contains(ComputerPrincipal computer)
+ {
+ return Contains((Principal)computer);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <SatisfiesLinkDemand Name="ContainsNativeTest(Principal):Boolean" />
+ // <SatisfiesLinkDemand Name="ContainsEnumTest(Principal):Boolean" />
+ // <ReferencesCritical Name="Field: owningGroup" Ring="1" />
+ // <ReferencesCritical Name="Method: Principal.GetStoreCtxToUse():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // <ReferencesCritical Name="Method: ContainsNativeTest(Principal):Boolean" Ring="1" />
+ // <ReferencesCritical Name="Method: ContainsEnumTest(Principal):Boolean" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Contains(Principal principal)
+ {
+ StoreCtx storeCtxToUse = _owningGroup.GetStoreCtxToUse();
+
+ // If the store has a shortcut for testing membership, use it.
+ // Otherwise we enumerate all members and look for a match.
+ if ((storeCtxToUse != null) && (storeCtxToUse.SupportsNativeMembershipTest))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "PrincipalCollection",
+ "Contains: using native test (store ctx is null = {0})",
+ (storeCtxToUse == null));
+
+ return ContainsNativeTest(principal);
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Contains: using enum test");
+ return ContainsEnumTest(principal);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="Principal.FindByIdentity(System.DirectoryServices.AccountManagement.PrincipalContext,System.DirectoryServices.AccountManagement.IdentityType,System.String):System.DirectoryServices.AccountManagement.Principal" />
+ // <SatisfiesLinkDemand Name="Contains(Principal):Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public bool Contains(PrincipalContext context, IdentityType identityType, string identityValue)
+ {
+ CheckDisposed();
+
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ if (identityValue == null)
+ throw new ArgumentNullException("identityValue");
+
+ bool found = false;
+
+ Principal principal = Principal.FindByIdentity(context, identityType, identityValue);
+
+ if (principal != null)
+ found = Contains(principal);
+
+ return found;
+ }
+
+ //
+ // Internal constructor
+ //
+
+ // Constructs a fresh PrincipalCollection based on the supplied ResultSet.
+ // The ResultSet may not be null (use an EmptySet instead).
+ // <SecurityKernel Critical="True" Ring="1">
+ // <ReferencesCritical Name="Field: owningGroup" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal PrincipalCollection(BookmarkableResultSet results, GroupPrincipal owningGroup)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Ctor");
+
+ Debug.Assert(results != null);
+
+ _resultSet = results;
+ _owningGroup = owningGroup;
+ }
+
+ //
+ // Internal "disposer"
+ //
+
+ // Ideally, we'd like to implement IDisposable, since we need to dispose of the ResultSet.
+ // But IDisposable would have to be a public interface, and we don't want the apps calling Dispose()
+ // on us, only the Principal that owns us. So we implement an "internal" form of Dispose().
+ internal void Dispose()
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Dispose: disposing");
+
+ lock (_resultSet)
+ {
+ if (_resultSet != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Dispose: disposing resultSet");
+ _resultSet.Dispose();
+ }
+ }
+
+ _disposed = true;
+ }
+ }
+
+ //
+ // Private implementation
+ //
+
+ // The group we're a PrincipalCollection of
+ [System.Security.SecuritySafeCritical]
+ private GroupPrincipal _owningGroup;
+
+ //
+ // SYNCHRONIZATION
+ // Access to:
+ // resultSet
+ // must be synchronized, since multiple enumerators could be iterating over us at once.
+ // Synchronize by locking on resultSet.
+
+ // Represents the Principals retrieved from the store for this collection
+ private BookmarkableResultSet _resultSet;
+
+ // Contains Principals inserted into this collection for which the insertion has not been persisted to the store
+ private List<Principal> _insertedValuesCompleted = new List<Principal>();
+ private List<Principal> _insertedValuesPending = new List<Principal>();
+
+ // Contains Principals removed from this collection for which the removal has not been persisted
+ // to the store
+ private List<Principal> _removedValuesCompleted = new List<Principal>();
+ private List<Principal> _removedValuesPending = new List<Principal>();
+
+ // Has this collection been cleared?
+ private bool _clearPending = false;
+ private bool _clearCompleted = false;
+
+ internal bool ClearCompleted
+ {
+ get { return _clearCompleted; }
+ }
+
+ // Used so our enumerator can detect changes to the collection and throw an exception
+ private DateTime _lastChange = DateTime.UtcNow;
+
+ internal DateTime LastChange
+ {
+ get { return _lastChange; }
+ }
+
+ internal void MarkChange()
+ {
+ _lastChange = DateTime.UtcNow;
+ }
+
+ // To support disposal
+ private bool _disposed = false;
+
+ private void CheckDisposed()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException("PrincipalCollection");
+ }
+
+ //
+ // Load/Store Implementation
+ //
+
+ internal List<Principal> Inserted
+ {
+ get
+ {
+ return _insertedValuesPending;
+ }
+ }
+
+ internal List<Principal> Removed
+ {
+ get
+ {
+ return _removedValuesPending;
+ }
+ }
+
+ internal bool Cleared
+ {
+ get
+ {
+ return _clearPending;
+ }
+ }
+
+ // Return true if the membership has changed (i.e., either insertedValuesPending or removedValuesPending is
+ // non-empty)
+ internal bool Changed
+ {
+ get
+ {
+ return ((_insertedValuesPending.Count > 0) || (_removedValuesPending.Count > 0) || (_clearPending));
+ }
+ }
+
+ // Resets the change-tracking of the membership to 'unchanged', by moving all pending operations to completed status.
+ internal void ResetTracking()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "ResetTracking");
+
+ foreach (Principal p in _removedValuesPending)
+ {
+ Debug.Assert(!_removedValuesCompleted.Contains(p));
+ _removedValuesCompleted.Add(p);
+ }
+
+ _removedValuesPending.Clear();
+
+ foreach (Principal p in _insertedValuesPending)
+ {
+ Debug.Assert(!_insertedValuesCompleted.Contains(p));
+ _insertedValuesCompleted.Add(p);
+ }
+
+ _insertedValuesPending.Clear();
+
+ if (_clearPending)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "ResetTracking: clearing");
+
+ _clearCompleted = true;
+ _clearPending = false;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalCollectionEnumerator.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalCollectionEnumerator.cs
new file mode 100644
index 0000000000..6537d234c0
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalCollectionEnumerator.cs
@@ -0,0 +1,366 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ internal class PrincipalCollectionEnumerator : IEnumerator<Principal>, IEnumerator
+ {
+ //
+ // Public properties
+ //
+
+ public Principal Current
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ CheckDisposed();
+
+ // Since MoveNext() saved off the current value for us, this is largely trivial.
+
+ if (_endReached == true || _currentMode == CurrentEnumeratorMode.None)
+ {
+ // Either we're at the end or before the beginning
+ // (CurrentEnumeratorMode.None implies we're _before_ the first value)
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Warn,
+ "PrincipalCollectionEnumerator",
+ "Current: bad position, endReached={0}, currentMode={1}",
+ _endReached,
+ _currentMode);
+
+ throw new InvalidOperationException(StringResources.PrincipalCollectionEnumInvalidPos);
+ }
+
+ Debug.Assert(_current != null);
+ return _current;
+ }
+ }
+
+ object IEnumerator.Current
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="get_Current():Principal" />
+ // <ReferencesCritical Name="Method: get_Current():Principal" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return Current;
+ }
+ }
+
+ //
+ // Public methods
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="CheckChanged():Void" />
+ // <SatisfiesLinkDemand Name="PrincipalCollection.get_Cleared():System.Boolean" />
+ // <SatisfiesLinkDemand Name="PrincipalCollection.get_ClearCompleted():System.Boolean" />
+ // <ReferencesCritical Name="Method: CheckChanged():Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ public bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "Entering MoveNext");
+
+ CheckDisposed();
+ CheckChanged();
+
+ // We previously reached the end, nothing more to do
+ if (_endReached)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: endReached");
+ return false;
+ }
+
+ lock (_resultSet)
+ {
+ if (_currentMode == CurrentEnumeratorMode.None)
+ {
+ // At the very beginning
+
+ // In case this ResultSet was previously used with another PrincipalCollectionEnumerator instance
+ // (e.g., two foreach loops in a row)
+ _resultSet.Reset();
+
+ if (!_memberCollection.Cleared && !_memberCollection.ClearCompleted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: None mode, starting with existing values");
+
+ // Start by enumerating the existing values in the store
+ _currentMode = CurrentEnumeratorMode.ResultSet;
+ _enumerator = null;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: None mode, skipping existing values");
+
+ // The member collection was cleared. Skip the ResultSet phase
+ _currentMode = CurrentEnumeratorMode.InsertedValuesCompleted;
+ _enumerator = (IEnumerator<Principal>)_insertedValuesCompleted.GetEnumerator();
+ }
+ }
+
+ Debug.Assert(_resultSet != null);
+
+ if (_currentMode == CurrentEnumeratorMode.ResultSet)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: ResultSet mode");
+
+ bool needToRepeat = false;
+
+ do
+ {
+ bool f = _resultSet.MoveNext();
+
+ if (f)
+ {
+ Principal principal = (Principal)_resultSet.CurrentAsPrincipal;
+
+ if (_removedValuesCompleted.Contains(principal) || _removedValuesPending.Contains(principal))
+ {
+ // It's a value that's been removed (either a pending remove that hasn't completed, or a remove
+ // that completed _after_ we loaded the ResultSet from the store).
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: ResultSet mode, found remove, skipping");
+
+ needToRepeat = true;
+ continue;
+ }
+ else if (_insertedValuesCompleted.Contains(principal) || _insertedValuesPending.Contains(principal))
+ {
+ // insertedValuesCompleted: We must have gotten the ResultSet after the inserted committed.
+ // We don't want to return
+ // the principal twice, so we'll skip it here and later return it in
+ // the CurrentEnumeratorMode.InsertedValuesCompleted mode.
+ //
+ // insertedValuesPending: The principal must have been originally in the ResultSet, but then
+ // removed, saved, and re-added, with the re-add still pending.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: ResultSet mode, found insert, skipping");
+
+ needToRepeat = true;
+ continue;
+ }
+ else
+ {
+ needToRepeat = false;
+ _current = principal;
+ return true;
+ }
+ }
+ else
+ {
+ // No more values left to retrieve. Now try the insertedValuesCompleted list.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: ResultSet mode, moving to InsValuesComp mode");
+
+ _currentMode = CurrentEnumeratorMode.InsertedValuesCompleted;
+ _enumerator = (IEnumerator<Principal>)_insertedValuesCompleted.GetEnumerator();
+ needToRepeat = false;
+ }
+ }
+ while (needToRepeat);
+ }
+
+ // These are values whose insertion has completed, but after we already loaded the ResultSet from the store.
+ if (_currentMode == CurrentEnumeratorMode.InsertedValuesCompleted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: InsValuesComp mode");
+
+ bool f = _enumerator.MoveNext();
+
+ if (f)
+ {
+ _current = _enumerator.Current;
+ return true;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: InsValuesComp mode, moving to InsValuesPend mode");
+
+ _currentMode = CurrentEnumeratorMode.InsertedValuesPending;
+ _enumerator = (IEnumerator<Principal>)_insertedValuesPending.GetEnumerator();
+ }
+ }
+
+ // These are values whose insertion has not yet been committed to the store.
+ if (_currentMode == CurrentEnumeratorMode.InsertedValuesPending)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: InsValuesPend mode");
+
+ bool f = _enumerator.MoveNext();
+
+ if (f)
+ {
+ _current = _enumerator.Current;
+ return true;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "MoveNext: InsValuesPend mode, nothing left");
+
+ _endReached = true;
+ return false;
+ }
+ }
+ }
+
+ Debug.Fail(String.Format(CultureInfo.CurrentCulture, "PrincipalCollectionEnumerator.MoveNext: fell off end of function, mode = {0}", _currentMode.ToString()));
+ return false;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="MoveNext():Boolean" />
+ // <ReferencesCritical Name="Method: MoveNext():Boolean" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ bool IEnumerator.MoveNext()
+ {
+ return MoveNext();
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="CheckChanged():Void" />
+ // <ReferencesCritical Name="Method: CheckChanged():Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "Reset");
+
+ CheckDisposed();
+ CheckChanged();
+
+ // Set us up to start enumerating from the very beginning again
+ _endReached = false;
+ _enumerator = null;
+ _currentMode = CurrentEnumeratorMode.None;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Reset():Void" />
+ // <ReferencesCritical Name="Method: Reset():Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ void IEnumerator.Reset()
+ {
+ Reset();
+ }
+
+ public void Dispose() // IEnumerator<Principal> inherits from IDisposable
+ {
+ _disposed = true;
+ }
+
+ //
+ // Internal constructors
+ //
+ internal PrincipalCollectionEnumerator(
+ ResultSet resultSet,
+ PrincipalCollection memberCollection,
+ List<Principal> removedValuesCompleted,
+ List<Principal> removedValuesPending,
+ List<Principal> insertedValuesCompleted,
+ List<Principal> insertedValuesPending
+ )
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollectionEnumerator", "Ctor");
+
+ Debug.Assert(resultSet != null);
+
+ _resultSet = resultSet;
+ _memberCollection = memberCollection;
+ _removedValuesCompleted = removedValuesCompleted;
+ _removedValuesPending = removedValuesPending;
+ _insertedValuesCompleted = insertedValuesCompleted;
+ _insertedValuesPending = insertedValuesPending;
+ }
+
+ //
+ // Private implementation
+ //
+
+ private Principal _current;
+
+ // Remember: these are references to objects held by the PrincipalCollection class from which we came.
+ // We don't own these, and shouldn't Dispose the ResultSet.
+ //
+ // SYNCHRONIZATION
+ // Access to:
+ // resultSet
+ // must be synchronized, since multiple enumerators could be iterating over us at once.
+ // Synchronize by locking on resultSet.
+
+ private ResultSet _resultSet;
+ private List<Principal> _insertedValuesPending;
+ private List<Principal> _insertedValuesCompleted;
+ private List<Principal> _removedValuesPending;
+ private List<Principal> _removedValuesCompleted;
+
+ private bool _endReached = false; // true if there are no results left to iterate over
+
+ private IEnumerator<Principal> _enumerator = null; // The insertedValues{Completed,Pending} enumerator, used by MoveNext
+
+ private enum CurrentEnumeratorMode // The set of values that MoveNext is currently iterating over
+ {
+ None,
+ ResultSet,
+ InsertedValuesCompleted,
+ InsertedValuesPending
+ }
+
+ private CurrentEnumeratorMode _currentMode = CurrentEnumeratorMode.None;
+
+ // To support IDisposable
+ private bool _disposed = false;
+
+ private void CheckDisposed()
+ {
+ if (_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalCollectionEnumerator", "CheckDisposed: accessing disposed object");
+ throw new ObjectDisposedException("PrincipalCollectionEnumerator");
+ }
+ }
+
+ // When this enumerator was constructed, to detect changes made to the PrincipalCollection after it was constructed
+ private DateTime _creationTime = DateTime.UtcNow;
+
+ private PrincipalCollection _memberCollection = null;
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalCollection.get_LastChange():System.DateTime" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ private void CheckChanged()
+ {
+ // Make sure the app hasn't changed our underlying list
+ if (_memberCollection.LastChange > _creationTime)
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Warn,
+ "PrincipalCollectionEnumerator",
+ "CheckChanged: has changed (last change={0}, creation={1})",
+ _memberCollection.LastChange,
+ _creationTime);
+
+ throw new InvalidOperationException(StringResources.PrincipalCollectionEnumHasChanged);
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalSearcher.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalSearcher.cs
new file mode 100644
index 0000000000..1c37d8a400
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/PrincipalSearcher.cs
@@ -0,0 +1,419 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ public class PrincipalSearcher : IDisposable
+ {
+ //
+ // Public constructors
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="SetDefaultPageSizeForContext():Void" />
+ // <ReferencesCritical Name="Method: SetDefaultPageSizeForContext():Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted = true)]
+ public PrincipalSearcher()
+ {
+ SetDefaultPageSizeForContext();
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.get_Context():System.DirectoryServices.AccountManagement.PrincipalContext" />
+ // <SatisfiesLinkDemand Name="set_QueryFilter(Principal):Void" />
+ // <SatisfiesLinkDemand Name="SetDefaultPageSizeForContext():Void" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: SetDefaultPageSizeForContext():Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public PrincipalSearcher(Principal queryFilter)
+ {
+ if (null == queryFilter)
+ throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, StringResources.InvalidNullArgument, "queryFilter"));
+
+ _ctx = queryFilter.Context;
+ this.QueryFilter = queryFilter; // use property to enforce "no persisted principals" check
+
+ SetDefaultPageSizeForContext();
+ }
+
+ //
+ // Public properties
+ //
+ public PrincipalContext Context
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ CheckDisposed();
+
+ return _ctx;
+ }
+ }
+
+ public Principal QueryFilter
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ CheckDisposed();
+
+ return _qbeFilter;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="Principal.get_Context():System.DirectoryServices.AccountManagement.PrincipalContext" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (null == value)
+ throw new ArgumentNullException(String.Format(CultureInfo.CurrentCulture, StringResources.InvalidNullArgument, "queryFilter"));
+
+ CheckDisposed();
+ Debug.Assert(value.Context != null);
+
+ // Make sure they're not passing in a persisted Principal object
+ if ((value != null) && (!value.unpersisted))
+ throw new ArgumentException(StringResources.PrincipalSearcherPersistedPrincipal);
+
+ _qbeFilter = value;
+ _ctx = _qbeFilter.Context;
+ }
+ }
+
+ //
+ // Public methods
+ //
+
+ // Calls FindAll(false) to retrieve all matching results
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="FindAll(Boolean):PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.Principal>" />
+ // <ReferencesCritical Name="Method: FindAll(Boolean):PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.Principal>" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public PrincipalSearchResult<Principal> FindAll()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "Entering FindAll()");
+
+ CheckDisposed();
+
+ return FindAll(false);
+ }
+
+ // Calls FindAll(true) to retrieve at most one result, then retrieves the first (and only) result from the
+ // FindResult<Principal> and returns it.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="FindAll(Boolean):PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.Principal>" />
+ // <SatisfiesLinkDemand Name="PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.Principal>.GetEnumerator():System.Collections.Generic.IEnumerator`1<System.DirectoryServices.AccountManagement.Principal>" />
+ // <SatisfiesLinkDemand Name="FindResultEnumerator`1<System.DirectoryServices.AccountManagement.Principal>.MoveNext():System.Boolean" />
+ // <SatisfiesLinkDemand Name="FindResultEnumerator`1<System.DirectoryServices.AccountManagement.Principal>.get_Current():System.DirectoryServices.AccountManagement.Principal" />
+ // <ReferencesCritical Name="Method: FindAll(Boolean):PrincipalSearchResult`1<System.DirectoryServices.AccountManagement.Principal>" Ring="1" />
+ // <ReferencesCritical Name="Method: FindResultEnumerator`1.MoveNext():System.Boolean" Ring="1" />
+ // <ReferencesCritical Name="Method: FindResultEnumerator`1.get_Current():T" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public Principal FindOne()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "Entering FindOne()");
+
+ CheckDisposed();
+
+ using (PrincipalSearchResult<Principal> fr = FindAll(true))
+ {
+ FindResultEnumerator<Principal> fre = (FindResultEnumerator<Principal>)fr.GetEnumerator();
+
+ // If there's (at least) one result, return it. Else return null.
+ if (fre.MoveNext())
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "FindOne(): found a principal");
+ return (Principal)fre.Current;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "FindOne(): found no principal");
+ return null;
+ }
+ }
+ }
+
+ // The wormhole to the native searcher underlying this PrincipalSearcher.
+ // This method validates that a PrincipalContext has been set on the searcher and that the QBE
+ // filter, if supplied, has no referential properties set.
+ //
+ // If the underlying StoreCtx does not expose a native searcher (StoreCtx.SupportsSearchNatively is false),
+ // throws an exception.
+ //
+ // Otherwise, calls StoreCtx.PushFilterToNativeSearcher to push the current QBE filter
+ // into underlyingSearcher (automatically constructing a fresh native searcher if underlyingSearcher is null),
+ // and returns underlyingSearcher.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="HasReferentialPropertiesSet():Boolean" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Method: HasReferentialPropertiesSet():Boolean" Ring="1" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public object GetUnderlyingSearcher()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "Entering GetUnderlyingSearcher");
+
+ CheckDisposed();
+
+ // We have to have a filter
+ if (_qbeFilter == null)
+ throw new InvalidOperationException(StringResources.PrincipalSearcherMustSetFilter);
+
+ // Double-check that the Principal isn't persisted. We don't allow them to assign a persisted
+ // Principal as the filter, but they could have persisted it after assigning it to the QueryFilter
+ // property.
+ if (!_qbeFilter.unpersisted)
+ throw new InvalidOperationException(StringResources.PrincipalSearcherPersistedPrincipal);
+
+ // Validate the QBE filter: make sure it doesn't have any non-scalar properties set.
+ if (HasReferentialPropertiesSet())
+ throw new InvalidOperationException(StringResources.PrincipalSearcherNonReferentialProps);
+
+ StoreCtx storeCtx = _ctx.QueryCtx;
+ Debug.Assert(storeCtx != null);
+
+ // The underlying context must actually support search (i.e., no MSAM/reg-SAM)
+ if (storeCtx.SupportsSearchNatively == false)
+ throw new InvalidOperationException(StringResources.PrincipalSearcherNoUnderlying);
+
+ // We need to generate the searcher every time because the object could change
+ // outside of our control.
+ _underlyingSearcher = storeCtx.PushFilterToNativeSearcher(this);
+
+ return _underlyingSearcher;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="CheckDisposed():Void" />
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public Type GetUnderlyingSearcherType()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "Entering GetUnderlyingSearcherType");
+
+ CheckDisposed();
+
+ // We have to have a filter
+ if (_qbeFilter == null)
+ throw new InvalidOperationException(StringResources.PrincipalSearcherMustSetFilter);
+
+ StoreCtx storeCtx = _ctx.QueryCtx;
+ Debug.Assert(storeCtx != null);
+
+ // The underlying context must actually support search (i.e., no MSAM/reg-SAM)
+ if (storeCtx.SupportsSearchNatively == false)
+ throw new InvalidOperationException(StringResources.PrincipalSearcherNoUnderlying);
+
+ return storeCtx.SearcherNativeType();
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="get_UnderlyingSearcher():Object" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public virtual void Dispose()
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "Dispose: disposing");
+
+ if ((this.UnderlyingSearcher != null) && (this.UnderlyingSearcher is IDisposable))
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "PrincipalSearcher",
+ "Dispose: disposing underlying searcher of type " + this.UnderlyingSearcher.GetType().ToString());
+
+ ((IDisposable)this.UnderlyingSearcher).Dispose();
+ }
+
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ //
+ // Private implementation
+ //
+ [System.Security.SecuritySafeCritical]
+ private PrincipalContext _ctx;
+
+ // Are we disposed?
+ private bool _disposed = false;
+
+ // Directly corresponds to the PrincipalSearcher.QueryFilter property.
+ // Null means "return all principals".
+ private Principal _qbeFilter;
+
+ // The default page size to use. This value is automatically set
+ // whenever a PrincipalContext is assigned to this object.
+ private int _pageSize = 0;
+
+ internal int PageSize
+ {
+ get { return _pageSize; }
+ }
+
+ // The underlying searcher (e.g., DirectorySearcher) corresponding to this PrincipalSearcher.
+ // Set by StoreCtx. PushFilterToNativeSearcher(), based on the qbeFilter.
+ // If not set, either there is no underlying searcher (SAM), or PushFilterToNativeSearcher has not
+ // yet been called.
+ private object _underlyingSearcher = null;
+ internal object UnderlyingSearcher
+ {
+ get
+ {
+ return _underlyingSearcher;
+ }
+
+ set
+ {
+ _underlyingSearcher = value;
+ }
+ }
+
+ // The core search method.
+ // This method validates that a PrincipalContext has been set on the searcher and that the QBE
+ // filter, if supplied, has no referential properties set.
+ //
+ // For the ctx.QueryCtx, calls StoreCtx.Query to perform the query and retrieve a
+ // ResultSet representing the results of that query.
+ // Then constructs a FindResult<Principal>, passing it the collection of one or more ResultSets.
+ //
+ // Returns at most one result in the FindResult<Principal> if returnOne == true, no limit on results
+ // returned otherwise.
+ [System.Security.SecuritySafeCritical]
+ private PrincipalSearchResult<Principal> FindAll(bool returnOne)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "Entering FindAll, returnOne=" + returnOne.ToString());
+
+ if (_qbeFilter == null)
+ throw new InvalidOperationException(StringResources.PrincipalSearcherMustSetFilter);
+ // Double-check that the Principal isn't persisted. We don't allow them to assign a persisted
+ // Principal as the filter, but they could have persisted it after assigning it to the QueryFilter
+ // property.
+ if (!_qbeFilter.unpersisted)
+ throw new InvalidOperationException(StringResources.PrincipalSearcherPersistedPrincipal);
+
+ // Validate the QBE filter: make sure it doesn't have any non-scalar properties set.
+ if (HasReferentialPropertiesSet())
+ throw new InvalidOperationException(StringResources.PrincipalSearcherNonReferentialProps);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "FindAll: qbeFilter is non-null and passes");
+
+ ResultSet resultSet = _ctx.QueryCtx.Query(this, returnOne ? 1 : -1);
+
+ PrincipalSearchResult<Principal> fr = new PrincipalSearchResult<Principal>(resultSet);
+ return fr;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" />
+ // <ReferencesCritical Name="Field: ctx" Ring="1" />
+ // <ReferencesCritical Name="Method: PrincipalContext.get_QueryCtx():System.DirectoryServices.AccountManagement.StoreCtx" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ private void SetDefaultPageSizeForContext()
+ {
+ _pageSize = 0;
+
+ if (_qbeFilter != null)
+ {
+ // If our context is AD-backed (has an ADStoreCtx), use pagesize of 256.
+ // Otherwise, turn off paging.
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "PrincipalSearcher",
+ "SetDefaultPageSizeForContext: type is " + _ctx.QueryCtx.GetType().ToString());
+
+ if (_ctx.QueryCtx is ADStoreCtx)
+ {
+ // Found an AD context
+ _pageSize = 256;
+ }
+ }
+
+ return;
+ }
+
+ // Checks this.qbeFilter to determine if any referential properties are set
+ [System.Security.SecuritySafeCritical]
+ private bool HasReferentialPropertiesSet()
+ {
+ // If using a null query filter, nothing to validate, as it can't have any referential
+ // properties set.
+ if (_qbeFilter == null)
+ return false;
+
+ // Since the QBE filter must be in the "unpersisted" state, any set properties have their changed
+ // flag still set (qbeFilter.GetChangeStatusForProperty() == true). Therefore, checking which properties
+ // have been set == checking which properties have their change flag set to true.
+ Debug.Assert(_qbeFilter.unpersisted == true);
+
+ // Retrieve the list of referential properties for this type of Principal.
+ // If this type of Principal doesn't have any, the Properties hashtable will return null.
+ Type t = _qbeFilter.GetType();
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "HasReferentialPropertiesSet: using type " + t.ToString());
+
+ ArrayList referentialProperties = (ArrayList)ReferentialProperties.Properties[t];
+
+ if (referentialProperties != null)
+ {
+ foreach (string propertyName in referentialProperties)
+ {
+ if (_qbeFilter.GetChangeStatusForProperty(propertyName) == true)
+ {
+ // Property was set.
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalSearcher", "HasReferentialPropertiesSet: found ref property " + propertyName);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // Checks if the principal searcher has been disposed, and throws an appropriate exception if it has.
+ private void CheckDisposed()
+ {
+ if (_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalSearcher", "CheckDisposed: accessing disposed object");
+ throw new ObjectDisposedException(this.GetType().ToString());
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/QbeFilterDescription.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/QbeFilterDescription.cs
new file mode 100644
index 0000000000..27ac8bb8b8
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/QbeFilterDescription.cs
@@ -0,0 +1,361 @@
+// 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.Collections;
+using System.Diagnostics;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ //
+ // A collection of individual property filters
+ //
+ internal class QbeFilterDescription
+ {
+ private ArrayList _filtersToApply = new ArrayList();
+
+ public QbeFilterDescription()
+ {
+ // Nothing to do
+ }
+
+ public ArrayList FiltersToApply
+ {
+ get
+ {
+ return _filtersToApply;
+ }
+ }
+ }
+
+ //
+ // Constructs individual property filters, given the name of the property
+ //
+ internal class FilterFactory
+ {
+ // Put a private constructor because this class should only be used as static methods
+ private FilterFactory() { }
+
+ private static Hashtable s_subclasses = new Hashtable();
+
+ static FilterFactory()
+ {
+ s_subclasses[DescriptionFilter.PropertyNameStatic] = typeof(DescriptionFilter);
+ s_subclasses[DisplayNameFilter.PropertyNameStatic] = typeof(DisplayNameFilter);
+ s_subclasses[IdentityClaimFilter.PropertyNameStatic] = typeof(IdentityClaimFilter);
+ s_subclasses[SamAccountNameFilter.PropertyNameStatic] = typeof(SamAccountNameFilter);
+ s_subclasses[DistinguishedNameFilter.PropertyNameStatic] = typeof(DistinguishedNameFilter);
+ s_subclasses[GuidFilter.PropertyNameStatic] = typeof(GuidFilter);
+ s_subclasses[UserPrincipalNameFilter.PropertyNameStatic] = typeof(UserPrincipalNameFilter);
+ s_subclasses[StructuralObjectClassFilter.PropertyNameStatic] = typeof(StructuralObjectClassFilter);
+ s_subclasses[NameFilter.PropertyNameStatic] = typeof(NameFilter);
+ s_subclasses[CertificateFilter.PropertyNameStatic] = typeof(CertificateFilter);
+ s_subclasses[AuthPrincEnabledFilter.PropertyNameStatic] = typeof(AuthPrincEnabledFilter);
+ s_subclasses[PermittedWorkstationFilter.PropertyNameStatic] = typeof(PermittedWorkstationFilter);
+ s_subclasses[PermittedLogonTimesFilter.PropertyNameStatic] = typeof(PermittedLogonTimesFilter);
+ s_subclasses[ExpirationDateFilter.PropertyNameStatic] = typeof(ExpirationDateFilter);
+ s_subclasses[SmartcardLogonRequiredFilter.PropertyNameStatic] = typeof(SmartcardLogonRequiredFilter);
+ s_subclasses[DelegationPermittedFilter.PropertyNameStatic] = typeof(DelegationPermittedFilter);
+ s_subclasses[HomeDirectoryFilter.PropertyNameStatic] = typeof(HomeDirectoryFilter);
+ s_subclasses[HomeDriveFilter.PropertyNameStatic] = typeof(HomeDriveFilter);
+ s_subclasses[ScriptPathFilter.PropertyNameStatic] = typeof(ScriptPathFilter);
+ s_subclasses[PasswordNotRequiredFilter.PropertyNameStatic] = typeof(PasswordNotRequiredFilter);
+ s_subclasses[PasswordNeverExpiresFilter.PropertyNameStatic] = typeof(PasswordNeverExpiresFilter);
+ s_subclasses[CannotChangePasswordFilter.PropertyNameStatic] = typeof(CannotChangePasswordFilter);
+ s_subclasses[AllowReversiblePasswordEncryptionFilter.PropertyNameStatic] = typeof(AllowReversiblePasswordEncryptionFilter);
+ s_subclasses[GivenNameFilter.PropertyNameStatic] = typeof(GivenNameFilter);
+ s_subclasses[MiddleNameFilter.PropertyNameStatic] = typeof(MiddleNameFilter);
+ s_subclasses[SurnameFilter.PropertyNameStatic] = typeof(SurnameFilter);
+ s_subclasses[EmailAddressFilter.PropertyNameStatic] = typeof(EmailAddressFilter);
+ s_subclasses[VoiceTelephoneNumberFilter.PropertyNameStatic] = typeof(VoiceTelephoneNumberFilter);
+ s_subclasses[EmployeeIDFilter.PropertyNameStatic] = typeof(EmployeeIDFilter);
+ s_subclasses[GroupIsSecurityGroupFilter.PropertyNameStatic] = typeof(GroupIsSecurityGroupFilter);
+ s_subclasses[GroupScopeFilter.PropertyNameStatic] = typeof(GroupScopeFilter);
+ s_subclasses[ServicePrincipalNameFilter.PropertyNameStatic] = typeof(ServicePrincipalNameFilter);
+ s_subclasses[ExtensionCacheFilter.PropertyNameStatic] = typeof(ExtensionCacheFilter);
+ s_subclasses[BadPasswordAttemptFilter.PropertyNameStatic] = typeof(BadPasswordAttemptFilter);
+ s_subclasses[ExpiredAccountFilter.PropertyNameStatic] = typeof(ExpiredAccountFilter);
+ s_subclasses[LastLogonTimeFilter.PropertyNameStatic] = typeof(LastLogonTimeFilter);
+ s_subclasses[LockoutTimeFilter.PropertyNameStatic] = typeof(LockoutTimeFilter);
+ s_subclasses[PasswordSetTimeFilter.PropertyNameStatic] = typeof(PasswordSetTimeFilter);
+ s_subclasses[BadLogonCountFilter.PropertyNameStatic] = typeof(BadLogonCountFilter);
+ }
+
+ // Given a property name, constructs and returns the appropriate individual property
+ // filter
+ static public object CreateFilter(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "QbeFilterDescription", "FilterFactory.CreateFilter: name=" + propertyName);
+
+ Type type = (Type)s_subclasses[propertyName];
+ Debug.Assert(type != null);
+
+ return System.Activator.CreateInstance(type);
+ }
+ }
+
+ //
+ // The individual property filters
+ //
+
+ // Base class: Defines the external interface shared by all individual property filters
+ internal abstract class FilterBase
+ {
+ public object Value
+ {
+ get { return _value; }
+ set { _value = value; }
+ }
+
+ private object _value;
+
+ // Some providers need place to store extra state, e.g., a processed form of Value
+ public object Extra
+ {
+ get { return _extra; }
+ set { _extra = value; }
+ }
+
+ private object _extra = null;
+
+ public abstract string PropertyName { get; }
+ }
+
+ // The derived classes
+
+ internal class DescriptionFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalDescription;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class SidFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalSid;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class SamAccountNameFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalSamAccountName;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class DistinguishedNameFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalDistinguishedName;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+ internal class GuidFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalGuid;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+ internal class IdentityClaimFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalIdentityClaims;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class UserPrincipalNameFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalUserPrincipalName;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+ internal class StructuralObjectClassFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalStructuralObjectClass;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+ internal class NameFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalName;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class DisplayNameFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalDisplayName;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+ internal class CertificateFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AuthenticablePrincipalCertificates;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class AuthPrincEnabledFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AuthenticablePrincipalEnabled;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class PermittedWorkstationFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoPermittedWorkstations;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class PermittedLogonTimesFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoPermittedLogonTimes;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class ExpirationDateFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoExpirationDate;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class SmartcardLogonRequiredFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoSmartcardRequired;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class DelegationPermittedFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoDelegationPermitted;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class HomeDirectoryFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoHomeDirectory;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class HomeDriveFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoHomeDrive;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class ScriptPathFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoScriptPath;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class PasswordNotRequiredFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PwdInfoPasswordNotRequired;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class PasswordNeverExpiresFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PwdInfoPasswordNeverExpires;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class CannotChangePasswordFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PwdInfoCannotChangePassword;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class AllowReversiblePasswordEncryptionFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PwdInfoAllowReversiblePasswordEncryption;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class GivenNameFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.UserGivenName;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class MiddleNameFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.UserMiddleName;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class SurnameFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.UserSurname;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class EmailAddressFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.UserEmailAddress;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class VoiceTelephoneNumberFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.UserVoiceTelephoneNumber;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class EmployeeIDFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.UserEmployeeID;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class GroupIsSecurityGroupFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.GroupIsSecurityGroup;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class GroupScopeFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.GroupGroupScope;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class ServicePrincipalNameFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.ComputerServicePrincipalNames;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class ExtensionCacheFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PrincipalExtensionCache;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class BadPasswordAttemptFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PwdInfoLastBadPasswordAttempt;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class LastLogonTimeFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoLastLogon;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class LockoutTimeFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoAcctLockoutTime;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class ExpiredAccountFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoExpiredAccount;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class PasswordSetTimeFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.PwdInfoLastPasswordSet;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+
+ internal class BadLogonCountFilter : FilterBase
+ {
+ public const string PropertyNameStatic = PropertyNames.AcctInfoBadLogonCount;
+ public override string PropertyName { get { return PropertyNameStatic; } }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/RejectedClaimChange.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/RejectedClaimChange.cs
new file mode 100644
index 0000000000..dc9458515d
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/RejectedClaimChange.cs
@@ -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.
+
+using System;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal enum RejectedClaimChange
+ {
+ Allowed = 0, // change allowed
+ TimeRangeNotAllowed = 1, // change rejected: store doesn't support time-limited claims
+ DuplicateTypeNotAllowed = 2, // change rejected: store doesn't allow multiple of this type of claim
+ TypeNotAllowed = 3, // change rejected: store doesn't support claims of this type
+ NotAllowed = 4 // change rejected: other reason (e.g., removal of a mandatory claim)
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Resources.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Resources.cs
new file mode 100644
index 0000000000..066af1c64d
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Resources.cs
@@ -0,0 +1,196 @@
+// 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.Resources;
+using System.Reflection;
+using System.Globalization;
+
+// disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+
+namespace System.DirectoryServices.AccountManagement
+{
+ ///<summary>
+ /// This class loads all the localizable string resources.
+ ///</summary>
+ internal class StringResources
+ {
+ static StringResources()
+ {
+ Type t = typeof(StringResources);
+
+ ResourceManager rm = new ResourceManager(t);
+ MemberInfo[] infos = t.GetMembers(BindingFlags.Public | BindingFlags.Static);
+ foreach (MemberInfo m in infos)
+ {
+ t.InvokeMember(m.Name, BindingFlags.SetField, null, null,
+ new Object[] { rm.GetString(m.Name, CultureInfo.CurrentUICulture) },
+ CultureInfo.CurrentCulture);
+ }
+ }
+
+ public static string ContextNoWellKnownObjects = null;
+ public static string ContextNoContainerForMachineCtx = null;
+ public static string ContextBadUserPwdCombo = null;
+
+ public static string StoreNotSupportMethod = null;
+
+ public static string PrincipalCantSetContext = null;
+ public static string PrincipalUnsupportedProperty = null;
+ public static string PrincipalUnsupportPropertyForPlatform = null;
+ public static string PrincipalUnsupportPropertyForType = null;
+ public static string PrincipalMustSetContextForSave = null;
+ public static string PrincipalMustSetContextForNative = null;
+ public static string PrincipalMustSetContextForProperty = null;
+ public static string PrincipalCantDeleteUnpersisted = null;
+ public static string PrincipalDeleted = null;
+ public static string PrincipalNotSupportedOnFakePrincipal = null;
+ public static string PrincipalMustPersistFirst = null;
+ public static string PrincipalIdentityTypeNotAllowed = null;
+ public static string PrincipalIdentityTypeNotRemovable = null;
+ public static string PrincipalCantChangeSamNameOnPersistedSAM = null;
+
+ public static string EmptyIdentityType = null;
+
+ public static string PrincipalSearcherPersistedPrincipal = null;
+ public static string PrincipalSearcherMustSetContext = null;
+ public static string PrincipalSearcherMustSetContextForUnderlying = null;
+ public static string PrincipalSearcherNoUnderlying = null;
+ public static string PrincipalSearcherNonReferentialProps = null;
+
+ public static string FindResultEnumInvalidPos = null;
+
+ public static string TrackedCollectionNotOneDimensional = null;
+ public static string TrackedCollectionIndexNotInArray = null;
+ public static string TrackedCollectionArrayTooSmall = null;
+
+ public static string TrackedCollectionEnumHasChanged = null;
+ public static string TrackedCollectionEnumInvalidPos = null;
+
+ public static string MultipleMatchesExceptionText = null;
+ public static string MultipleMatchingPrincipals = null;
+ public static string NoMatchingPrincipalExceptionText = null;
+ public static string NoMatchingGroupExceptionText = null;
+ public static string PrincipalExistsExceptionText = null;
+
+ public static string IdentityClaimCollectionNullFields = null;
+
+ public static string PrincipalCollectionNotOneDimensional = null;
+ public static string PrincipalCollectionIndexNotInArray = null;
+ public static string PrincipalCollectionArrayTooSmall = null;
+
+ public static string PrincipalCollectionEnumHasChanged = null;
+ public static string PrincipalCollectionEnumInvalidPos = null;
+ public static string PrincipalCollectionAlreadyMember = null;
+
+ public static string AuthenticablePrincipalMustBeSubtypeOfAuthPrinc = null;
+
+ public static string PasswordInfoChangePwdOnUnpersistedPrinc = null;
+
+ public static string UserMustSetContextForMethod = null;
+ public static string UserDomainNotSupportedOnPlatform = null;
+ public static string UserLocalNotSupportedOnPlatform = null;
+ public static string UserCouldNotFindCurrent = null;
+
+ public static string UnableToRetrieveDomainInfo = null;
+ public static string UnableToOpenToken = null;
+ public static string UnableToRetrieveTokenInfo = null;
+ public static string UnableToRetrievePolicy = null;
+ public static string UnableToImpersonateCredentials = null;
+
+ public static string StoreCtxUnsupportedPrincipalTypeForSave = null;
+ public static string StoreCtxUnsupportedPrincipalTypeForGroupInsert = null;
+ public static string StoreCtxUnsupportedPrincipalTypeForQuery = null;
+ public static string StoreCtxUnsupportedPropertyForQuery = null;
+ public static string StoreCtxUnsupportedIdentityClaimForQuery = null;
+ public static string StoreCtxIdentityClaimMustHaveScheme = null;
+ public static string StoreCtxSecurityIdentityClaimBadFormat = null;
+ public static string StoreCtxGuidIdentityClaimBadFormat = null;
+ public static string StoreCtxNT4IdentityClaimWrongForm = null;
+ public static string StoreCtxCantSetTimeLimitOnIdentityClaim = null;
+ public static string StoreCtxGroupHasUnpersistedInsertedPrincipal = null;
+ public static string StoreCtxNeedValueSecurityIdentityClaimToQuery = null;
+ public static string StoreCtxExceptionUpdatingGroup = null;
+ public static string StoreCtxExceptionCommittingChanges = null;
+
+ public static string ADStoreCtxUnsupportedPrincipalContextForGroupInsert = null;
+ public static string ADStoreCtxCouldntGetSIDForGroupMember = null;
+ public static string ADStoreCtxMustBeContainer = null;
+ public static string ADStoreCtxCantRetrieveObjectSidForCrossStore = null;
+ public static string ADStoreCtxCantResolveSidForCrossStore = null;
+ public static string ADStoreCtxFailedFindCrossStoreTarget = null;
+ public static string ADStoreCtxCantClearGroup = null;
+ public static string ADStoreCtxCantRemoveMemberFromGroup = null;
+
+ public static string ADStoreCtxUnableToReadExistingAccountControlFlagsToEnable = null;
+ public static string ADStoreCtxUnableToReadExistingAccountControlFlagsForUpdate = null;
+ public static string ADStoreCtxUnableToReadExistingGroupTypeFlagsForUpdate = null;
+ public static string ADStoreCtxNoComputerPasswordChange = null;
+
+ public static string SAMStoreCtxUnableToRetrieveVersion = null;
+ public static string SAMStoreCtxUnableToRetrieveMachineName = null;
+ public static string SAMStoreCtxUnableToRetrieveFlatMachineName = null;
+
+ public static string SAMStoreCtxNoComputerPasswordSet = null;
+ public static string SAMStoreCtxNoComputerPasswordExpire = null;
+ public static string SAMStoreCtxIdentityClaimsImmutable = null;
+ public static string SAMStoreCtxCouldntGetSIDForGroupMember = null;
+ public static string SAMStoreCtxFailedToClearGroup = null;
+ public static string SAMStoreCtxCantRetrieveObjectSidForCrossStore = null;
+ public static string SAMStoreCtxCantResolveSidForCrossStore = null;
+ public static string SAMStoreCtxFailedFindCrossStoreTarget = null;
+ public static string SAMStoreCtxErrorEnumeratingGroup = null;
+ public static string SAMStoreCtxLocalGroupsOnly = null;
+
+ public static string AuthZFailedToRetrieveGroupList = null;
+ public static string AuthZNotSupported = null;
+ public static string AuthZErrorEnumeratingGroups = null;
+ public static string AuthZCantFindGroup = null;
+
+ public static string ConfigHandlerConfigSectionsUnique = null;
+ public static string ConfigHandlerInvalidBoolAttribute = null;
+ public static string ConfigHandlerInvalidEnumAttribute = null;
+ public static string ConfigHandlerInvalidStringAttribute = null;
+ public static string ConfigHandlerUnknownConfigSection = null;
+
+ public static string PrincipalPermWrongType = null;
+ public static string PrincipalPermXmlNotPermission = null;
+ public static string PrincipalPermXmlBadVersion = null;
+ public static string PrincipalPermXmlBadContents = null;
+ public static string ExtensionInvalidClassAttributes = null;
+ public static string ExtensionInvalidClassDefinitionConstructor = null;
+
+ public static string AdsiNotInstalled = null;
+ public static string DSUnknown = null;
+ public static string ContextOptionsNotValidForMachineStore = null;
+ public static string ContextNoContainerForApplicationDirectoryCtx = null;
+ public static string PassedContextTypeDoesNotMatchDetectedType = null;
+ public static string NullArguments = null;
+ public static string InvalidStringValueForStore = null;
+ public static string InvalidNullArgument = null;
+ public static string ServerDown = null;
+ public static string PrincipalSearcherMustSetFilter = null;
+ public static string InvalidPropertyForStore = null;
+ public static string InvalidOperationForStore = null;
+ public static string NameMustBeSetToPersistPrincipal = null;
+ public static string SaveToMustHaveSamecontextType = null;
+ public static string SaveToNotSupportedAgainstMachineStore = null;
+ public static string ComputerInvalidForAppDirectoryStore = null;
+
+ public static string InvalidContextOptionsForMachine = null;
+ public static string InvalidContextOptionsForAD = null;
+
+ public static string InvalidExtensionCollectionType = null;
+ public static string ADAMStoreUnableToPopulateSchemaList = null;
+ public static string StoreCtxMultipleFiltersForPropertyUnsupported = null;
+
+ //public static string PrincipalPermEmptyName = null;
+ // PrincipalPermEmptyName=Name cannot be an empty string.
+ //public static string PrincipalPermInvalidContextType = null;
+ // PrincipalPermInvalidContextType=The value '{0}' is not a valid value for the ContextType.
+ }
+}
+
+#pragma warning restore 0414
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ResultSet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ResultSet.cs
new file mode 100644
index 0000000000..0c352379f3
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ResultSet.cs
@@ -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;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal abstract class ResultSet : IDisposable
+ {
+ // Return the principal we're positioned at as a Principal object.
+ // Need to use our StoreCtx's GetAsPrincipal to convert the native object to a Principal
+ abstract internal object CurrentAsPrincipal { get; }
+
+ // Advance the enumerator to the next principal in the result set, pulling in additional pages
+ // of results (or ranges of attribute values) as needed.
+ // Returns true if successful, false if no more results to return.
+ abstract internal bool MoveNext();
+
+ // Resets the enumerator to before the first result in the set. This potentially can be an expensive
+ // operation, e.g., if doing a paged search, may need to re-retrieve the first page of results.
+ // As a special case, if the ResultSet is already at the very beginning, this is guaranteed to be
+ // a no-op.
+ abstract internal void Reset();
+
+ // IDisposable implementation
+ public virtual void Dispose()
+ {
+ // Nothing to do in base class
+ }
+ }
+
+ internal abstract class BookmarkableResultSet : ResultSet
+ {
+ abstract internal ResultSetBookmark BookmarkAndReset();
+
+ abstract internal void RestoreBookmark(ResultSetBookmark bookmark);
+ }
+
+ internal abstract class ResultSetBookmark
+ {
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMGroupsSet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMGroupsSet.cs
new file mode 100644
index 0000000000..08ffd17dc7
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMGroupsSet.cs
@@ -0,0 +1,112 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.DirectoryServices;
+
+using System.Runtime.InteropServices;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class SAMGroupsSet : ResultSet
+ {
+ internal SAMGroupsSet(UnsafeNativeMethods.IADsMembers iADsMembers, SAMStoreCtx storeCtx, DirectoryEntry ctxBase)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMGroupsSet", "SAMGroupsSet: creating for path={0}", ctxBase.Path);
+
+ _groupsEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();
+
+ _storeCtx = storeCtx;
+ _ctxBase = ctxBase;
+ }
+
+ // Return the principal we're positioned at as a Principal object.
+ // Need to use our StoreCtx's GetAsPrincipal to convert the native object to a Principal
+ override internal object CurrentAsPrincipal
+ {
+ get
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMGroupsSet", "CurrentAsPrincipal");
+
+ Debug.Assert(_current != null);
+
+ return SAMUtils.DirectoryEntryAsPrincipal(_current, _storeCtx);
+ }
+ }
+
+ // Advance the enumerator to the next principal in the result set, pulling in additional pages
+ // of results (or ranges of attribute values) as needed.
+ // Returns true if successful, false if no more results to return.
+ override internal bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMGroupsSet", "MoveNext");
+
+ _atBeginning = false;
+
+ bool f = _groupsEnumerator.MoveNext();
+
+ if (f)
+ {
+ // Got a group. Create a DirectoryEntry for it.
+ // Clone the ctxBase to pick up its credentials, then build an appropriate path.
+ UnsafeNativeMethods.IADs nativeMember = (UnsafeNativeMethods.IADs)_groupsEnumerator.Current;
+
+ // We do this, rather than using the DirectoryEntry constructor that takes a native IADs object,
+ // is so the credentials get transferred to the new DirectoryEntry. If we just use the native
+ // object constructor, the native object will have the right credentials, but the DirectoryEntry
+ // will have default (null) credentials, which it'll use anytime it needs to use credentials.
+ DirectoryEntry de = SDSUtils.BuildDirectoryEntry(
+ nativeMember.ADsPath,
+ _storeCtx.Credentials,
+ _storeCtx.AuthTypes);
+
+ _current = de;
+ }
+
+ return f;
+ }
+
+ // Resets the enumerator to before the first result in the set. This potentially can be an expensive
+ // operation, e.g., if doing a paged search, may need to re-retrieve the first page of results.
+ // As a special case, if the ResultSet is already at the very beginning, this is guaranteed to be
+ // a no-op.
+ override internal void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMGroupsSet", "Reset");
+
+ if (!_atBeginning)
+ {
+ _groupsEnumerator.Reset();
+ _current = null;
+
+ _atBeginning = true;
+ }
+ }
+
+ //
+ // Private fields
+ //
+
+ private IEnumerator _groupsEnumerator;
+ private SAMStoreCtx _storeCtx;
+ private DirectoryEntry _ctxBase;
+
+ private bool _atBeginning = true;
+
+ private DirectoryEntry _current = null;
+ }
+}
+
+// #endif
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMMembersSet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMMembersSet.cs
new file mode 100644
index 0000000000..d35c12c420
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMMembersSet.cs
@@ -0,0 +1,631 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.DirectoryServices;
+using System.Text;
+
+using System.Runtime.InteropServices;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class SAMMembersSet : BookmarkableResultSet
+ {
+ internal SAMMembersSet(string groupPath, UnsafeNativeMethods.IADsGroup group, bool recursive, SAMStoreCtx storeCtx, DirectoryEntry ctxBase)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMMembersSet",
+ "SAMMembersSet: groupPath={0}, recursive={1}, base={2}",
+ groupPath,
+ recursive,
+ ctxBase.Path);
+
+ _storeCtx = storeCtx;
+ _ctxBase = ctxBase;
+
+ _group = group;
+ _originalGroup = group;
+ _recursive = recursive;
+
+ _groupsVisited.Add(groupPath); // so we don't revisit it
+
+ UnsafeNativeMethods.IADsMembers iADsMembers = group.Members();
+ _membersEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();
+ }
+
+ // Return the principal we're positioned at as a Principal object.
+ // Need to use our StoreCtx's GetAsPrincipal to convert the native object to a Principal
+ override internal object CurrentAsPrincipal
+ {
+ get
+ {
+ if (_current != null)
+ {
+ // Local principal --- handle it ourself
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "CurrentAsPrincipal: returning current");
+ return SAMUtils.DirectoryEntryAsPrincipal(_current, _storeCtx);
+ }
+ else if (_currentFakePrincipal != null)
+ {
+ // Local fake principal --- handle it ourself
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "CurrentAsPrincipal: returning currentFakePrincipal");
+ return _currentFakePrincipal;
+ }
+ else if (_currentForeign != null)
+ {
+ // Foreign, non-recursive principal. Just return the principal.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "CurrentAsPrincipal: returning currentForeign");
+ return _currentForeign;
+ }
+ else
+ {
+ // Foreign recursive expansion. Proxy the call to the foreign ResultSet.
+ Debug.Assert(_foreignResultSet != null);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "CurrentAsPrincipal: returning foreignResultSet");
+ return _foreignResultSet.CurrentAsPrincipal;
+ }
+ }
+ }
+
+ // Advance the enumerator to the next principal in the result set, pulling in additional pages
+ // of results (or ranges of attribute values) as needed.
+ // Returns true if successful, false if no more results to return.
+ override internal bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "Entering MoveNext");
+
+ _atBeginning = false;
+
+ bool f = MoveNextLocal();
+
+ if (!f)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNext: trying foreign");
+
+ f = MoveNextForeign();
+ }
+
+ return f;
+ }
+
+ private bool MoveNextLocal()
+ {
+ bool needToRetry;
+
+ do
+ {
+ needToRetry = false;
+
+ object[] nativeMembers = new object[1];
+
+ bool f = _membersEnumerator.MoveNext();
+
+ if (f) // got a value
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: got a value from the enumerator");
+
+ UnsafeNativeMethods.IADs nativeMember = (UnsafeNativeMethods.IADs)_membersEnumerator.Current;
+
+ // If we encountered a group member corresponding to a fake principal such as
+ // NT AUTHORITY/NETWORK SERVICE, construct and prepare to return the fake principal.
+ byte[] sid = (byte[])nativeMember.Get("objectSid");
+ SidType sidType = Utils.ClassifySID(sid);
+ if (sidType == SidType.FakeObject)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: fake principal, sid={0}", Utils.ByteArrayToString(sid));
+
+ _currentFakePrincipal = _storeCtx.ConstructFakePrincipalFromSID(sid);
+ _current = null;
+ _currentForeign = null;
+
+ if (_foreignResultSet != null)
+ _foreignResultSet.Dispose();
+ _foreignResultSet = null;
+ return true;
+ }
+
+ // We do this, rather than using the DirectoryEntry constructor that takes a native IADs object,
+ // is so the credentials get transferred to the new DirectoryEntry. If we just use the native
+ // object constructor, the native object will have the right credentials, but the DirectoryEntry
+ // will have default (null) credentials, which it'll use anytime it needs to use credentials.
+ DirectoryEntry de = SDSUtils.BuildDirectoryEntry(
+ _storeCtx.Credentials,
+ _storeCtx.AuthTypes);
+
+ if (sidType == SidType.RealObjectFakeDomain)
+ {
+ // Transform the "WinNT://BUILTIN/foo" path to "WinNT://machineName/foo"
+ string builtinADsPath = nativeMember.ADsPath;
+
+ UnsafeNativeMethods.Pathname pathCracker = new UnsafeNativeMethods.Pathname();
+ UnsafeNativeMethods.IADsPathname pathName = (UnsafeNativeMethods.IADsPathname)pathCracker;
+
+ pathName.Set(builtinADsPath, 1 /* ADS_SETTYPE_FULL */);
+
+ // Build the "WinNT://" portion of the new path
+ StringBuilder adsPath = new StringBuilder();
+ adsPath.Append("WinNT://");
+ //adsPath.Append(pathName.Retrieve(9 /*ADS_FORMAT_SERVER */));
+
+ // Build the "WinNT://machineName/" portion of the new path
+ adsPath.Append(_storeCtx.MachineUserSuppliedName);
+ adsPath.Append("/");
+
+ // Build the "WinNT://machineName/foo" portion of the new path
+ int cElements = pathName.GetNumElements();
+
+ Debug.Assert(cElements >= 2); // "WinNT://BUILTIN/foo" == 2 elements
+
+ // Note that the ADSI WinNT provider indexes them backwards, e.g., in
+ // "WinNT://BUILTIN/A/B", BUILTIN == 2, A == 1, B == 0.
+ for (int i = cElements - 2; i >= 0; i--)
+ {
+ adsPath.Append(pathName.GetElement(i));
+ adsPath.Append("/");
+ }
+
+ adsPath.Remove(adsPath.Length - 1, 1); // remove the trailing "/"
+
+ de.Path = adsPath.ToString();
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: fake domain: {0} --> {1}", builtinADsPath, adsPath);
+ }
+ else
+ {
+ Debug.Assert(sidType == SidType.RealObject);
+ de.Path = nativeMember.ADsPath;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: real domain {0}", de.Path);
+ }
+
+ // Debug.Assert(Utils.AreBytesEqual(sid, (byte[]) de.Properties["objectSid"].Value));
+
+ if (IsLocalMember(sid))
+ {
+ // If we're processing recursively, and the member is a group,
+ // we don't return it but instead treat it as something to recursively
+ // visit (expand) later.
+ if (!_recursive || !SAMUtils.IsOfObjectClass(de, "Group"))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: setting current to {0}", de.Path);
+
+ // Not recursive, or not a group. Return the principal.
+ _current = de;
+ _currentFakePrincipal = null;
+ _currentForeign = null;
+
+ if (_foreignResultSet != null)
+ _foreignResultSet.Dispose();
+ _foreignResultSet = null;
+ return true;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: adding {0} to groupsToVisit", de.Path);
+
+ // Save off for later, if we haven't done so already.
+ if (!_groupsVisited.Contains(de.Path) && !_groupsToVisit.Contains(de.Path))
+ _groupsToVisit.Add(de.Path);
+
+ needToRetry = true;
+ continue;
+ }
+ }
+ else
+ {
+ // It's a foreign principal (e..g, an AD user or group).
+ // Save it off for later.
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: adding {0} to foreignMembers", de.Path);
+
+ _foreignMembers.Add(de);
+ needToRetry = true;
+ continue;
+ }
+ }
+ else
+ {
+ // We reached the end of this group's membership.
+ // If we're supposed to be recursively expanding, we need to expand
+ // any remaining non-foreign groups we earlier visited.
+ if (_recursive)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: recursive processing, groupsToVisit={0}", _groupsToVisit.Count);
+
+ if (_groupsToVisit.Count > 0)
+ {
+ // Pull off the next group to visit
+ string groupPath = _groupsToVisit[0];
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: recursively processing {0}", groupPath);
+
+ _groupsToVisit.RemoveAt(0);
+ _groupsVisited.Add(groupPath);
+
+ // Set up for the next round of enumeration
+ DirectoryEntry de = SDSUtils.BuildDirectoryEntry(
+ groupPath,
+ _storeCtx.Credentials,
+ _storeCtx.AuthTypes);
+
+ _group = (UnsafeNativeMethods.IADsGroup)de.NativeObject;
+
+ UnsafeNativeMethods.IADsMembers iADsMembers = _group.Members();
+ _membersEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();
+
+ // and go on to the first member of this new group
+ needToRetry = true;
+ continue;
+ }
+ }
+ }
+ }
+ while (needToRetry);
+
+ return false;
+ }
+
+ private bool MoveNextForeign()
+ {
+ bool needToRetry;
+
+ do
+ {
+ needToRetry = false;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextForeign: foreignMembers count={0}", _foreignMembers.Count);
+
+ if (_foreignMembers.Count > 0)
+ {
+ // foreignDE is a DirectoryEntry in _this_ store representing a principal in another store
+ DirectoryEntry foreignDE = _foreignMembers[0];
+ _foreignMembers.RemoveAt(0);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextForeign: foreignDE={0}", foreignDE.Path);
+
+ // foreignPrincipal is a principal from _another_ store (e.g., it's backed by an ADStoreCtx)
+ Principal foreignPrincipal = _storeCtx.ResolveCrossStoreRefToPrincipal(foreignDE);
+
+ // If we're not enumerating recursively, return the principal.
+ // If we are enumerating recursively, and it's a group, save it off for later.
+ if (!_recursive || !(foreignPrincipal is GroupPrincipal))
+ {
+ // Return the principal.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextForeign: setting currentForeign to {0}", foreignDE.Path);
+
+ _current = null;
+ _currentFakePrincipal = null;
+ _currentForeign = foreignPrincipal;
+
+ if (_foreignResultSet != null)
+ _foreignResultSet.Dispose();
+ _foreignResultSet = null;
+ return true;
+ }
+ else
+ {
+ // Save off the group for recursive expansion, and go on to the next principal.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextForeign: adding {0} to foreignGroups", foreignDE.Path);
+
+ _foreignGroups.Add((GroupPrincipal)foreignPrincipal);
+ needToRetry = true;
+ continue;
+ }
+ }
+
+ if (_foreignResultSet == null && _foreignGroups.Count > 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMMembersSet",
+ "MoveNextForeign: getting foreignResultSet (foreignGroups count={0})",
+ _foreignGroups.Count);
+
+ // We're expanding recursively, and either (1) we're immediately before
+ // the recursive expansion of the first foreign group, or (2) we just completed
+ // the recursive expansion of a foreign group, and now are moving on to the next.
+ Debug.Assert(_recursive == true);
+
+ // Pull off a foreign group to expand.
+ GroupPrincipal foreignGroup = _foreignGroups[0];
+ _foreignGroups.RemoveAt(0);
+
+ // Since it's a foreign group, we don't know how to enumerate its members. So we'll
+ // ask the group, through its StoreCtx, to do it for us. Effectively, we'll end up acting
+ // as a proxy to the foreign group's ResultSet.
+ _foreignResultSet = foreignGroup.GetStoreCtxToUse().GetGroupMembership(foreignGroup, true);
+ }
+
+ // We're either just beginning the recursive expansion of a foreign group, or we're continuing the expansion
+ // that we started on a previous call to MoveNext().
+ if (_foreignResultSet != null)
+ {
+ Debug.Assert(_recursive == true);
+
+ bool f = _foreignResultSet.MoveNext();
+
+ if (f)
+ {
+ // By setting current, currentFakePrincipal, and currentForeign to null,
+ // CurrentAsPrincipal/CurrentAsIdentityReference will know to proxy out to foreignResultSet.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextForeign: using foreignResultSet");
+
+ _current = null;
+ _currentFakePrincipal = null;
+ _currentForeign = null;
+ return true;
+ }
+
+ // Ran out of members in the foreign group, is there another foreign group remaining that we need
+ // to expand?
+ if (_foreignGroups.Count > 0)
+ {
+ // Yes, there is. Null out the foreignResultSet so we'll pull out the next foreign group
+ // the next time around the loop.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextForeign: ran out of members, using next foreignResultSet");
+
+ _foreignResultSet.Dispose();
+ _foreignResultSet = null;
+ Debug.Assert(_foreignMembers.Count == 0);
+ needToRetry = true;
+ }
+ else
+ {
+ // No, there isn't. Nothing left to do. We set foreignResultSet to null here just
+ // to leave things in a clean state --- it shouldn't really be necessary.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextForeign: ran out of members, nothing more to do");
+
+ _foreignResultSet.Dispose();
+ _foreignResultSet = null;
+ }
+ }
+ }
+ while (needToRetry);
+
+ return false;
+ }
+
+ private bool IsLocalMember(byte[] sid)
+ {
+ // BUILTIN SIDs are local, but we can't determine that by looking at domainName
+ SidType sidType = Utils.ClassifySID(sid);
+ Debug.Assert(sidType != SidType.FakeObject);
+
+ if (sidType == SidType.RealObjectFakeDomain)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMMembersSet",
+ "IsLocalMember: fake domain, SID={0}",
+ Utils.ByteArrayToString(sid));
+
+ return true;
+ }
+
+ bool isLocal = false;
+
+ // Ask the OS to resolve the SID to its target.
+ int accountUsage = 0;
+ string name;
+ string domainName;
+
+ int err = Utils.LookupSid(
+ _storeCtx.MachineUserSuppliedName,
+ _storeCtx.Credentials,
+ sid,
+ out name,
+ out domainName,
+ out accountUsage);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "SAMMembersSet",
+ "IsLocalMember: LookupSid failed, sid={0}, server={1}, err={2}",
+ Utils.ByteArrayToString(sid),
+ _storeCtx.MachineUserSuppliedName,
+ err);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.SAMStoreCtxErrorEnumeratingGroup,
+ err));
+ }
+
+ if (String.Compare(_storeCtx.MachineFlatName, domainName, StringComparison.OrdinalIgnoreCase) == 0)
+ isLocal = true;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMMembersSet",
+ "IsLocalMember: sid={0}, isLocal={1}, domainName={2}",
+ Utils.ByteArrayToString(sid),
+ isLocal,
+ domainName);
+
+ return isLocal;
+ }
+
+ // Resets the enumerator to before the first result in the set. This potentially can be an expensive
+ // operation, e.g., if doing a paged search, may need to re-retrieve the first page of results.
+ // As a special case, if the ResultSet is already at the very beginning, this is guaranteed to be
+ // a no-op.
+ override internal void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "Reset");
+
+ if (!_atBeginning)
+ {
+ _groupsToVisit.Clear();
+ string originalGroupPath = _groupsVisited[0];
+ _groupsVisited.Clear();
+ _groupsVisited.Add(originalGroupPath);
+
+ _group = _originalGroup;
+ UnsafeNativeMethods.IADsMembers iADsMembers = _group.Members();
+ _membersEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();
+
+ _current = null;
+ _currentFakePrincipal = null;
+ _currentForeign = null;
+
+ _foreignMembers.Clear();
+ _foreignGroups.Clear();
+
+ if (_foreignResultSet != null)
+ {
+ _foreignResultSet.Dispose();
+ _foreignResultSet = null;
+ }
+
+ _atBeginning = true;
+ }
+ }
+
+ override internal ResultSetBookmark BookmarkAndReset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "Bookmarking");
+
+ SAMMembersSetBookmark bookmark = new SAMMembersSetBookmark();
+
+ bookmark.groupsToVisit = _groupsToVisit;
+ _groupsToVisit = new List<string>();
+
+ string originalGroupPath = _groupsVisited[0];
+ bookmark.groupsVisited = _groupsVisited;
+ _groupsVisited = new List<string>();
+ _groupsVisited.Add(originalGroupPath);
+
+ bookmark.group = _group;
+ bookmark.membersEnumerator = _membersEnumerator;
+ _group = _originalGroup;
+ UnsafeNativeMethods.IADsMembers iADsMembers = _group.Members();
+ _membersEnumerator = ((IEnumerable)iADsMembers).GetEnumerator();
+
+ bookmark.current = _current;
+ bookmark.currentFakePrincipal = _currentFakePrincipal;
+ bookmark.currentForeign = _currentForeign;
+ _current = null;
+ _currentFakePrincipal = null;
+ _currentForeign = null;
+
+ bookmark.foreignMembers = _foreignMembers;
+ bookmark.foreignGroups = _foreignGroups;
+ bookmark.foreignResultSet = _foreignResultSet;
+ _foreignMembers = new List<DirectoryEntry>();
+ _foreignGroups = new List<GroupPrincipal>();
+ _foreignResultSet = null;
+
+ bookmark.atBeginning = _atBeginning;
+ _atBeginning = true;
+
+ return bookmark;
+ }
+
+ override internal void RestoreBookmark(ResultSetBookmark bookmark)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "Restoring from bookmark");
+
+ Debug.Assert(bookmark is SAMMembersSetBookmark);
+ SAMMembersSetBookmark samBookmark = (SAMMembersSetBookmark)bookmark;
+
+ _groupsToVisit = samBookmark.groupsToVisit;
+ _groupsVisited = samBookmark.groupsVisited;
+ _group = samBookmark.group;
+ _membersEnumerator = samBookmark.membersEnumerator;
+ _current = samBookmark.current;
+ _currentFakePrincipal = samBookmark.currentFakePrincipal;
+ _currentForeign = samBookmark.currentForeign;
+ _foreignMembers = samBookmark.foreignMembers;
+ _foreignGroups = samBookmark.foreignGroups;
+
+ if (_foreignResultSet != null)
+ _foreignResultSet.Dispose();
+
+ _foreignResultSet = samBookmark.foreignResultSet;
+ _atBeginning = samBookmark.atBeginning;
+ }
+
+ override public void Dispose()
+ {
+ try
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "Dispose: disposing");
+
+ if (_foreignResultSet != null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "Dispose: disposing foreignResultSet");
+ _foreignResultSet.Dispose();
+ }
+
+ _disposed = true;
+ }
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+
+ //
+ // Private fields
+ //
+
+ private bool _recursive;
+
+ private bool _disposed = false;
+
+ private SAMStoreCtx _storeCtx;
+ private DirectoryEntry _ctxBase;
+
+ private bool _atBeginning = true;
+
+ // local
+
+ // The 0th entry in this list is always the ADsPath of the original group whose membership we're querying
+ private List<string> _groupsVisited = new List<string>();
+
+ private List<string> _groupsToVisit = new List<string>();
+
+ private DirectoryEntry _current = null; // current member of the group (if enumerating local group and found a real principal)
+ private Principal _currentFakePrincipal = null; // current member of the group (if enumerating local group and found a fake pricipal)
+
+ private UnsafeNativeMethods.IADsGroup _group; // the group whose membership we're currently enumerating over
+ private UnsafeNativeMethods.IADsGroup _originalGroup; // the group whose membership we started off with (before recursing)
+
+ private IEnumerator _membersEnumerator; // the current group's membership enumerator
+
+ // foreign
+ private List<DirectoryEntry> _foreignMembers = new List<DirectoryEntry>();
+ private Principal _currentForeign = null; // current member of the group (if enumerating foreign principal)
+
+ private List<GroupPrincipal> _foreignGroups = new List<GroupPrincipal>();
+ private ResultSet _foreignResultSet = null; // current foreign group's ResultSet (if enumerating via proxy to foreign group)
+ }
+
+ internal class SAMMembersSetBookmark : ResultSetBookmark
+ {
+ public List<string> groupsToVisit;
+ public List<string> groupsVisited;
+ public UnsafeNativeMethods.IADsGroup group;
+ public IEnumerator membersEnumerator;
+ public DirectoryEntry current;
+ public Principal currentFakePrincipal;
+ public Principal currentForeign;
+ public List<DirectoryEntry> foreignMembers;
+ public List<GroupPrincipal> foreignGroups;
+ public ResultSet foreignResultSet;
+ public bool atBeginning;
+ }
+}
+// #endif
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMQuerySet.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMQuerySet.cs
new file mode 100644
index 0000000000..a9a653f889
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMQuerySet.cs
@@ -0,0 +1,926 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.DirectoryServices;
+using System.Text.RegularExpressions;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class SAMQuerySet : ResultSet
+ {
+ // We will iterate over all principals under ctxBase, returning only those which are in the list of types and which
+ // satisfy ALL the matching properties.
+ internal SAMQuerySet(
+ List<string> schemaTypes,
+ DirectoryEntries entries,
+ DirectoryEntry ctxBase,
+ int sizeLimit,
+ SAMStoreCtx storeCtx,
+ SAMMatcher samMatcher)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "SAMQuerySet: creating for path={0}, sizelimit={1}", ctxBase.Path, sizeLimit);
+
+ _schemaTypes = schemaTypes;
+ _entries = entries;
+ _sizeLimit = sizeLimit; // -1 == no limit
+ _storeCtx = storeCtx;
+ _ctxBase = ctxBase;
+ _matcher = samMatcher;
+
+ _enumerator = _entries.GetEnumerator();
+ }
+
+ // Return the principal we're positioned at as a Principal object.
+ // Need to use our StoreCtx's GetAsPrincipal to convert the native object to a Principal
+ override internal object CurrentAsPrincipal
+ {
+ get
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "CurrentAsPrincipal");
+
+ // Since this class is only used internally, none of our code should be even calling this
+ // if MoveNext returned false, or before calling MoveNext.
+ Debug.Assert(_endReached == false && _current != null);
+
+ return SAMUtils.DirectoryEntryAsPrincipal(_current, _storeCtx);
+ }
+ }
+
+ // Advance the enumerator to the next principal in the result set, pulling in additional pages
+ // of results (or ranges of attribute values) as needed.
+ // Returns true if successful, false if no more results to return.
+ override internal bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "Entering MoveNext");
+
+ Debug.Assert(_enumerator != null);
+
+ bool needToRetry = false;
+ bool f;
+
+ // Have we exceeded the requested size limit?
+ if ((_sizeLimit != -1) && (_resultsReturned >= _sizeLimit))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMQuerySet",
+ "MoveNext: exceeded sizelimit, ret={0}, limit={1}",
+ _resultsReturned,
+ _sizeLimit);
+ _endReached = true;
+ }
+
+ // End was reached previously. Nothing more to do.
+ if (_endReached)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: endReached");
+ return false;
+ }
+
+ // Pull the next result. We may have to repeat this several times
+ // until we find a result that matches the user's filter.
+ do
+ {
+ f = _enumerator.MoveNext();
+ needToRetry = false;
+
+ if (f)
+ {
+ DirectoryEntry entry = (DirectoryEntry)_enumerator.Current;
+
+ // Does it match the user's properties?
+ //
+ // We'd like to use DirectoryEntries.SchemaFilter rather than calling
+ // IsOfCorrectType here, but SchemaFilter has a bug
+ // where multiple DirectoryEntries all share the same SchemaFilter ---
+ // which would create multithreading issues for us.
+ if (IsOfCorrectType(entry) && _matcher.Matches(entry))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: found a match on {0}", entry.Path);
+
+ // Yes. It's our new current object
+ _current = entry;
+ _resultsReturned++;
+ }
+ else
+ {
+ // No. Retry.
+ needToRetry = true;
+ }
+ }
+ }
+ while (needToRetry);
+
+ if (!f)
+ {
+ /*
+ // One more to try: the root object
+ if (IsOfCorrectType(this.ctxBase) && this.matcher.Matches(this.ctxBase))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: found a match on root {0}", this.ctxBase);
+
+ this.current = this.ctxBase;
+ this.resultsReturned++;
+ f = true;
+ }
+ else
+ {
+ endReached = true;
+ }
+ * */
+ }
+
+ return f;
+ }
+
+ private bool IsOfCorrectType(DirectoryEntry de)
+ {
+ // Is the object in question one of the desired types?
+
+ foreach (string schemaType in _schemaTypes)
+ {
+ if (SAMUtils.IsOfObjectClass(de, schemaType))
+ return true;
+ }
+
+ return false;
+ }
+
+ // Resets the enumerator to before the first result in the set. This potentially can be an expensive
+ // operation, e.g., if doing a paged search, may need to re-retrieve the first page of results.
+ // As a special case, if the ResultSet is already at the very beginning, this is guaranteed to be
+ // a no-op.
+ override internal void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "Reset");
+
+ // if current == null, we're already at the beginning
+ if (_current != null)
+ {
+ _endReached = false;
+ _current = null;
+
+ if (_enumerator != null)
+ _enumerator.Reset();
+
+ _resultsReturned = 0;
+ }
+ }
+
+ //
+ // Private fields
+ //
+
+ private SAMStoreCtx _storeCtx;
+ private DirectoryEntry _ctxBase;
+ private DirectoryEntries _entries;
+ private IEnumerator _enumerator = null; // the enumerator for "entries"
+ private DirectoryEntry _current = null; // the DirectoryEntry that we're currently positioned at
+
+ // Filter parameters
+ private int _sizeLimit; // -1 == no limit
+ private List<string> _schemaTypes;
+ private SAMMatcher _matcher;
+
+ // Count of number of results returned so far
+ private int _resultsReturned = 0;
+
+ // Have we run out of entries?
+ private bool _endReached = false;
+ }
+
+ internal abstract class SAMMatcher
+ {
+ abstract internal bool Matches(DirectoryEntry de);
+ }
+
+ //
+ // The matcher routines for query-by-example support
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class QbeMatcher : SAMMatcher
+ {
+ private QbeFilterDescription _propertiesToMatch;
+
+ internal QbeMatcher(QbeFilterDescription propertiesToMatch)
+ {
+ _propertiesToMatch = propertiesToMatch;
+ }
+
+ //
+ // Static constructor: used for initializing static tables
+ //
+ static QbeMatcher()
+ {
+ //
+ // Load the filterPropertiesTable
+ //
+ s_filterPropertiesTable = new Hashtable();
+
+ for (int i = 0; i < s_filterPropertiesTableRaw.GetLength(0); i++)
+ {
+ Type qbeType = s_filterPropertiesTableRaw[i, 0] as Type;
+ string winNTPropertyName = s_filterPropertiesTableRaw[i, 1] as string;
+ MatcherDelegate f = s_filterPropertiesTableRaw[i, 2] as MatcherDelegate;
+
+ Debug.Assert(qbeType != null);
+ Debug.Assert(winNTPropertyName != null);
+ Debug.Assert(f != null);
+
+ // There should only be one entry per QBE type
+ Debug.Assert(s_filterPropertiesTable[qbeType] == null);
+
+ FilterPropertyTableEntry entry = new FilterPropertyTableEntry();
+ entry.winNTPropertyName = winNTPropertyName;
+ entry.matcher = f;
+
+ s_filterPropertiesTable[qbeType] = entry;
+ }
+ }
+
+ internal override bool Matches(DirectoryEntry de)
+ {
+ // If it has no SID, it's not a security principal, and we're not interested in it.
+ // (In reg-SAM, computers don't have accounts and therefore don't have SIDs, but ADSI
+ // creates fake Computer objects for them. In LSAM, computers CAN have accounts, and thus
+ // SIDs).
+ if (de.Properties["objectSid"] == null || de.Properties["objectSid"].Count == 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "SamMatcher: Matches: skipping no-SID {0}", de.Path);
+ return false;
+ }
+
+ // Try to match each specified property in turn
+ foreach (FilterBase filter in _propertiesToMatch.FiltersToApply)
+ {
+ FilterPropertyTableEntry entry = (FilterPropertyTableEntry)s_filterPropertiesTable[filter.GetType()];
+
+ if (entry == null)
+ {
+ // Must be a property we don't support
+ throw new NotSupportedException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.StoreCtxUnsupportedPropertyForQuery,
+ PropertyNamesExternal.GetExternalForm(filter.PropertyName)));
+ }
+
+ if (!entry.matcher(filter, entry.winNTPropertyName, de))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "SamMatcher: Matches: no match {0}", de.Path);
+ return false;
+ }
+ }
+
+ // All tests pass --- it's a match
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "SamMatcher: Matches: match {0}", de.Path);
+ return true;
+ }
+
+ // We only list properties we support filtering on in this table. At run-time, if we detect they set a
+ // property that's not listed here, we throw an exception.
+ private static object[,] s_filterPropertiesTableRaw =
+ {
+ // QbeType WinNT Property Matcher
+ {typeof(DescriptionFilter), "Description", new MatcherDelegate(StringMatcher)},
+ {typeof(DisplayNameFilter), "FullName", new MatcherDelegate(StringMatcher)},
+ {typeof(SidFilter), "objectSid", new MatcherDelegate(SidMatcher)},
+ {typeof(SamAccountNameFilter), "Name", new MatcherDelegate(SamAccountNameMatcher)},
+
+ {typeof(AuthPrincEnabledFilter), "UserFlags", new MatcherDelegate(UserFlagsMatcher)},
+ {typeof(PermittedWorkstationFilter), "LoginWorkstations", new MatcherDelegate(MultiStringMatcher)},
+ {typeof(PermittedLogonTimesFilter), "LoginHours", new MatcherDelegate(BinaryMatcher)},
+ {typeof(ExpirationDateFilter), "AccountExpirationDate", new MatcherDelegate(ExpirationDateMatcher)},
+ {typeof(SmartcardLogonRequiredFilter), "UserFlags", new MatcherDelegate(UserFlagsMatcher)},
+ {typeof(DelegationPermittedFilter), "UserFlags", new MatcherDelegate(UserFlagsMatcher)},
+ {typeof(HomeDirectoryFilter), "HomeDirectory", new MatcherDelegate(StringMatcher)},
+ {typeof(HomeDriveFilter), "HomeDirDrive", new MatcherDelegate(StringMatcher)},
+ {typeof(ScriptPathFilter), "LoginScript", new MatcherDelegate(StringMatcher)},
+ {typeof(PasswordNotRequiredFilter), "UserFlags", new MatcherDelegate(UserFlagsMatcher)},
+ {typeof(PasswordNeverExpiresFilter), "UserFlags", new MatcherDelegate(UserFlagsMatcher)},
+ {typeof(CannotChangePasswordFilter), "UserFlags", new MatcherDelegate(UserFlagsMatcher)},
+ {typeof(AllowReversiblePasswordEncryptionFilter), "UserFlags", new MatcherDelegate(UserFlagsMatcher)},
+ {typeof(GroupScopeFilter), "groupType", new MatcherDelegate(GroupTypeMatcher)},
+ {typeof(ExpiredAccountFilter), "AccountExpirationDate", new MatcherDelegate(DateTimeMatcher)},
+ {typeof(LastLogonTimeFilter), "LastLogin", new MatcherDelegate(DateTimeMatcher)},
+ {typeof(PasswordSetTimeFilter), "PasswordAge", new MatcherDelegate(DateTimeMatcher)},
+ {typeof(BadLogonCountFilter), "BadPasswordAttempts", new MatcherDelegate(IntMatcher)},
+ };
+
+ private static Hashtable s_filterPropertiesTable = null;
+
+ private class FilterPropertyTableEntry
+ {
+ internal string winNTPropertyName;
+ internal MatcherDelegate matcher;
+ }
+
+ //
+ // Conversion routines
+ //
+
+ private static bool WildcardStringMatch(FilterBase filter, string wildcardFilter, string property)
+ {
+ // Build a Regex that matches valueToMatch, and store it on the Filter (so that we don't have
+ // to have the CLR constantly reparse the regex string).
+ // Ideally, we'd like to use a compiled Regex (RegexOptions.Compiled) for performance,
+ // but the CLR cannot release generated MSIL. Thus, our memory usage would grow without bound
+ // each time a query was performed.
+
+ Regex regex = filter.Extra as Regex;
+ if (regex == null)
+ {
+ regex = new Regex(SAMUtils.PAPIQueryToRegexString(wildcardFilter), RegexOptions.Singleline);
+ filter.Extra = regex;
+ }
+
+ Match match = regex.Match(property);
+
+ return match.Success;
+ }
+ // returns true if specified WinNT property's value matches filter.Value
+ private delegate bool MatcherDelegate(FilterBase filter, string winNTPropertyName, DirectoryEntry de);
+
+ private static bool DateTimeMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ QbeMatchType valueToMatch = (QbeMatchType)filter.Value;
+
+ if (null == valueToMatch.Value)
+ {
+ if ((de.Properties.Contains(winNTPropertyName) == false) ||
+ (de.Properties[winNTPropertyName].Count == 0) ||
+ (de.Properties[winNTPropertyName].Value == null))
+ return true;
+ }
+ else
+ {
+ Debug.Assert(valueToMatch.Value is DateTime);
+
+ if (de.Properties.Contains(winNTPropertyName) && (de.Properties[winNTPropertyName].Value != null))
+ {
+ DateTime value;
+
+ if (winNTPropertyName == "PasswordAge")
+ {
+ PropertyValueCollection values = de.Properties["PasswordAge"];
+
+ if (values.Count != 0)
+ {
+ Debug.Assert(values.Count == 1);
+ Debug.Assert(values[0] is Int32);
+
+ int secondsLapsed = (int)values[0];
+
+ value = DateTime.UtcNow - new TimeSpan(0, 0, secondsLapsed);
+ }
+ else
+ {
+ // If we don't have a passwordAge then this item will never match.
+ return false;
+ }
+ }
+ else
+ {
+ value = (DateTime)de.Properties[winNTPropertyName].Value;
+ }
+
+ int comparisonResult = DateTime.Compare(value, (DateTime)valueToMatch.Value);
+ bool result = true;
+
+ switch (valueToMatch.Match)
+ {
+ case MatchType.Equals:
+ result = comparisonResult == 0;
+ break;
+ case MatchType.NotEquals:
+ result = comparisonResult != 0;
+ break;
+ case MatchType.GreaterThan:
+ result = comparisonResult > 0;
+ break;
+ case MatchType.GreaterThanOrEquals:
+ result = comparisonResult >= 0;
+ break;
+ case MatchType.LessThan:
+ result = comparisonResult < 0;
+ break;
+ case MatchType.LessThanOrEquals:
+ result = comparisonResult <= 0;
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ return result;
+ }
+ }
+
+ return false;
+ }
+
+ private static bool StringMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ string valueToMatch = (string)filter.Value;
+
+ if (valueToMatch == null)
+ {
+ if ((de.Properties.Contains(winNTPropertyName) == false) ||
+ (de.Properties[winNTPropertyName].Count == 0) ||
+ (((string)de.Properties[winNTPropertyName].Value).Length == 0))
+ return true;
+ }
+ else
+ {
+ if (de.Properties.Contains(winNTPropertyName))
+ {
+ string value = (string)de.Properties[winNTPropertyName].Value;
+
+ if (value != null)
+ {
+ return WildcardStringMatch(filter, valueToMatch, value);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private static bool IntMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ QbeMatchType valueToMatch = (QbeMatchType)filter.Value;
+ bool result = false;
+
+ if (null == valueToMatch.Value)
+ {
+ if ((de.Properties.Contains(winNTPropertyName) == false) ||
+ (de.Properties[winNTPropertyName].Count == 0) ||
+ (de.Properties[winNTPropertyName].Value == null))
+ result = true;
+ }
+ else
+ {
+ if (de.Properties.Contains(winNTPropertyName))
+ {
+ int value = (int)de.Properties[winNTPropertyName].Value;
+ int comparisonValue = (int)valueToMatch.Value;
+
+ switch (valueToMatch.Match)
+ {
+ case MatchType.Equals:
+ result = (value == comparisonValue);
+ break;
+ case MatchType.NotEquals:
+ result = (value != comparisonValue);
+ break;
+ case MatchType.GreaterThan:
+ result = (value > comparisonValue);
+ break;
+ case MatchType.GreaterThanOrEquals:
+ result = (value >= comparisonValue);
+ break;
+ case MatchType.LessThan:
+ result = (value < comparisonValue);
+ break;
+ case MatchType.LessThanOrEquals:
+ result = (value <= comparisonValue);
+ break;
+ default:
+ result = false;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private static bool SamAccountNameMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ string samToMatch = (string)filter.Value;
+
+ int index = samToMatch.IndexOf('\\');
+
+ if (index == samToMatch.Length - 1)
+ throw new InvalidOperationException(StringResources.StoreCtxNT4IdentityClaimWrongForm);
+
+ string samAccountName = (index != -1) ? samToMatch.Substring(index + 1) : // +1 to skip the '/'
+ samToMatch;
+
+ if (de.Properties["Name"].Count > 0 && de.Properties["Name"].Value != null)
+ {
+ return WildcardStringMatch(filter, samAccountName, (string)de.Properties["Name"].Value);
+ /*
+ return (String.Compare(((string)de.Properties["Name"].Value),
+ samAccountName,
+ true, // acct names are not case-sensitive
+ CultureInfo.InvariantCulture) == 0);
+ */
+ }
+
+ return false;
+ }
+
+ private static bool SidMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ byte[] sidToMatch = Utils.StringToByteArray((string)filter.Value);
+
+ if (sidToMatch == null)
+ throw new InvalidOperationException(StringResources.StoreCtxSecurityIdentityClaimBadFormat);
+
+ if (de.Properties["objectSid"].Count > 0 && de.Properties["objectSid"].Value != null)
+ {
+ return Utils.AreBytesEqual(sidToMatch, (byte[])de.Properties["objectSid"].Value);
+ }
+
+ return false;
+ }
+
+ private static bool UserFlagsMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ Debug.Assert(winNTPropertyName == "UserFlags");
+
+ bool valueToMatch = (bool)filter.Value;
+
+ // If it doesn't contain the property, it certainly can't match the user's value
+ if (!de.Properties.Contains(winNTPropertyName) || de.Properties[winNTPropertyName].Count == 0)
+ return false;
+
+ int value = (int)de.Properties[winNTPropertyName].Value;
+
+ switch (filter.PropertyName)
+ {
+ // We want to return true iff both value and valueToMatch are true, or both are false
+ // (i.e., NOT XOR)
+
+ case AuthPrincEnabledFilter.PropertyNameStatic:
+ // UF_ACCOUNTDISABLE
+ // Note that the logic is inverted on this one. We expose "Enabled",
+ // but SAM stores it as "Disabled".
+ return (((value & 0x0002) != 0) ^ valueToMatch);
+
+ case SmartcardLogonRequiredFilter.PropertyNameStatic:
+ // UF_SMARTCARD_REQUIRED
+ return !(((value & 0x40000) != 0) ^ valueToMatch);
+
+ case DelegationPermittedFilter.PropertyNameStatic:
+ // UF_NOT_DELEGATED
+ // Note that the logic is inverted on this one. That's because we expose
+ // "delegation allowed", but AD represents it as the inverse, "delegation NOT allowed"
+ return (((value & 0x100000) != 0) ^ valueToMatch);
+
+ case PasswordNotRequiredFilter.PropertyNameStatic:
+ // UF_PASSWD_NOTREQD
+ return !(((value & 0x0020) != 0) ^ valueToMatch);
+
+ case PasswordNeverExpiresFilter.PropertyNameStatic:
+ // UF_DONT_EXPIRE_PASSWD
+ return !(((value & 0x10000) != 0) ^ valueToMatch);
+
+ case CannotChangePasswordFilter.PropertyNameStatic:
+ // UF_PASSWD_CANT_CHANGE
+ return !(((value & 0x0040) != 0) ^ valueToMatch);
+
+ case AllowReversiblePasswordEncryptionFilter.PropertyNameStatic:
+ // UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
+ return !(((value & 0x0080) != 0) ^ valueToMatch);
+
+ default:
+ Debug.Fail("SAMQuerySet.UserFlagsMatcher: fell off end looking for " + filter.PropertyName);
+ return false;
+ }
+ }
+
+ private static bool MultiStringMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ string valueToMatch = (string)filter.Value;
+
+ if (valueToMatch == null)
+ {
+ if ((de.Properties.Contains(winNTPropertyName) == false) ||
+ (de.Properties[winNTPropertyName].Count == 0) ||
+ (((string)de.Properties[winNTPropertyName].Value).Length == 0))
+ return true;
+ }
+ else
+ {
+ if (de.Properties.Contains(winNTPropertyName) && (de.Properties[winNTPropertyName].Count != 0))
+ {
+ foreach (string value in de.Properties[winNTPropertyName])
+ {
+ if (value != null)
+ {
+ return WildcardStringMatch(filter, valueToMatch, value);
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private static bool BinaryMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ byte[] valueToMatch = (byte[])filter.Value;
+
+ if (valueToMatch == null)
+ {
+ if ((de.Properties.Contains(winNTPropertyName) == false) ||
+ (de.Properties[winNTPropertyName].Count == 0) ||
+ (de.Properties[winNTPropertyName].Value == null))
+ return true;
+ }
+ else
+ {
+ if (de.Properties.Contains(winNTPropertyName))
+ {
+ byte[] value = (byte[])de.Properties[winNTPropertyName].Value;
+
+ if ((value != null) && Utils.AreBytesEqual(value, valueToMatch))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static bool ExpirationDateMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ Debug.Assert(filter is ExpirationDateFilter);
+ Debug.Assert(winNTPropertyName == "AccountExpirationDate");
+
+ Nullable<DateTime> valueToCompare = (Nullable<DateTime>)filter.Value;
+
+ if (!valueToCompare.HasValue)
+ {
+ if ((de.Properties.Contains(winNTPropertyName) == false) ||
+ (de.Properties[winNTPropertyName].Count == 0) ||
+ (de.Properties[winNTPropertyName].Value == null))
+ return true;
+ }
+ else
+ {
+ if (de.Properties.Contains(winNTPropertyName) && (de.Properties[winNTPropertyName].Value != null))
+ {
+ DateTime value = (DateTime)de.Properties[winNTPropertyName].Value;
+
+ if (value.Equals(valueToCompare.Value))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static bool GroupTypeMatcher(FilterBase filter, string winNTPropertyName, DirectoryEntry de)
+ {
+ Debug.Assert(winNTPropertyName == "groupType");
+ Debug.Assert(filter is GroupScopeFilter);
+
+ GroupScope valueToMatch = (GroupScope)filter.Value;
+
+ // All SAM local machine groups are local groups
+ if (valueToMatch == GroupScope.Local)
+ return true;
+ else
+ return false;
+ }
+ }
+
+ //
+ // The matcher routines for FindBy* support
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class FindByDateMatcher : SAMMatcher
+ {
+ internal enum DateProperty
+ {
+ LogonTime,
+ PasswordSetTime,
+ AccountExpirationTime
+ }
+
+ private DateProperty _propertyToMatch;
+ private MatchType _matchType;
+ private DateTime _valueToMatch;
+
+ internal FindByDateMatcher(DateProperty property, MatchType matchType, DateTime value)
+ {
+ _propertyToMatch = property;
+ _matchType = matchType;
+ _valueToMatch = value;
+ }
+
+ internal override bool Matches(DirectoryEntry de)
+ {
+ // If it has no SID, it's not a security principal, and we're not interested in it.
+ // (In reg-SAM, computers don't have accounts and therefore don't have SIDs, but ADSI
+ // creates fake Computer objects for them. In LSAM, computers CAN have accounts, and thus
+ // SIDs).
+ if (de.Properties["objectSid"] == null || de.Properties["objectSid"].Count == 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "FindByDateMatcher: Matches: skipping no-SID {0}", de.Path);
+ return false;
+ }
+
+ switch (_propertyToMatch)
+ {
+ case DateProperty.LogonTime:
+ return MatchOnLogonTime(de);
+
+ case DateProperty.PasswordSetTime:
+ return MatchOnPasswordSetTime(de);
+
+ case DateProperty.AccountExpirationTime:
+ return MatchOnAccountExpirationTime(de);
+
+ default:
+ Debug.Fail("FindByDateMatcher.Matches: Fell off end looking for propertyToMatch=" + _propertyToMatch.ToString());
+ return false;
+ }
+ }
+
+ private bool MatchOnLogonTime(DirectoryEntry de)
+ {
+ PropertyValueCollection values = de.Properties["LastLogin"];
+ Nullable<DateTime> storeValue = null;
+
+ // Get the logon time from the DirectoryEntry
+ if (values.Count > 0)
+ {
+ Debug.Assert(values.Count == 1);
+
+ storeValue = (Nullable<DateTime>)values[0];
+ }
+
+ return TestForMatch(storeValue);
+ }
+
+ private bool MatchOnAccountExpirationTime(DirectoryEntry de)
+ {
+ PropertyValueCollection values = de.Properties["AccountExpirationDate"];
+ Nullable<DateTime> storeValue = null;
+
+ // Get the expiration date from the DirectoryEntry
+ if (values.Count > 0)
+ {
+ Debug.Assert(values.Count == 1);
+
+ storeValue = (Nullable<DateTime>)values[0];
+ }
+
+ return TestForMatch(storeValue);
+ }
+
+ private bool MatchOnPasswordSetTime(DirectoryEntry de)
+ {
+ PropertyValueCollection values = de.Properties["PasswordAge"];
+ Nullable<DateTime> storeValue = null;
+
+ if (values.Count != 0)
+ {
+ Debug.Assert(values.Count == 1);
+ Debug.Assert(values[0] is Int32);
+
+ int secondsLapsed = (int)values[0];
+
+ storeValue = DateTime.UtcNow - new TimeSpan(0, 0, secondsLapsed);
+ }
+
+ return TestForMatch(storeValue);
+ }
+
+ private bool TestForMatch(Nullable<DateTime> nullableStoreValue)
+ {
+ // If the store object doesn't have the property set, then the only
+ // way it could match is if they asked for a not-equals test
+ // (if the store object doesn't have a value, then it certainly doesn't match
+ // whatever value they specified)
+ if (!nullableStoreValue.HasValue)
+ return (_matchType == MatchType.NotEquals) ? true : false;
+
+ Debug.Assert(nullableStoreValue.HasValue);
+ DateTime storeValue = nullableStoreValue.Value;
+
+ switch (_matchType)
+ {
+ case MatchType.Equals:
+ return (storeValue == _valueToMatch);
+
+ case MatchType.NotEquals:
+ return (storeValue != _valueToMatch);
+
+ case MatchType.GreaterThan:
+ return (storeValue > _valueToMatch);
+
+ case MatchType.GreaterThanOrEquals:
+ return (storeValue >= _valueToMatch);
+
+ case MatchType.LessThan:
+ return (storeValue < _valueToMatch);
+
+ case MatchType.LessThanOrEquals:
+ return (storeValue <= _valueToMatch);
+
+ default:
+ Debug.Fail("FindByDateMatcher.TestForMatch: Fell off end looking for matchType=" + _matchType.ToString());
+ return false;
+ }
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class GroupMemberMatcher : SAMMatcher
+ {
+ private byte[] _memberSidToMatch;
+
+ internal GroupMemberMatcher(byte[] memberSidToMatch)
+ {
+ Debug.Assert(memberSidToMatch != null);
+ Debug.Assert(memberSidToMatch.Length != 0);
+ _memberSidToMatch = memberSidToMatch;
+ }
+
+ internal override bool Matches(DirectoryEntry groupDE)
+ {
+ // If it has no SID, it's not a security principal, and we're not interested in it.
+ // (In reg-SAM, computers don't have accounts and therefore don't have SIDs, but ADSI
+ // creates fake Computer objects for them. In LSAM, computers CAN have accounts, and thus
+ // SIDs).
+ if (groupDE.Properties["objectSid"] == null || groupDE.Properties["objectSid"].Count == 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "GroupMemberMatcher: Matches: skipping no-SID group={0}", groupDE.Path);
+ return false;
+ }
+
+ // Enumerate the members of the group, looking for a match
+ UnsafeNativeMethods.IADsGroup iADsGroup = (UnsafeNativeMethods.IADsGroup)groupDE.NativeObject;
+ UnsafeNativeMethods.IADsMembers iADsMembers = iADsGroup.Members();
+
+ foreach (UnsafeNativeMethods.IADs nativeMember in ((IEnumerable)iADsMembers))
+ {
+ // Wrap the DirectoryEntry around the native ADSI object
+ // (which already has the correct credentials)
+ DirectoryEntry memberDE = new DirectoryEntry(nativeMember);
+
+ // No SID --> not interesting
+ if (memberDE.Properties["objectSid"] == null || memberDE.Properties["objectSid"].Count == 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "GroupMemberMatcher: Matches: skipping member no-SID member={0}", memberDE.Path);
+ continue;
+ }
+
+ byte[] memberSid = (byte[])memberDE.Properties["objectSid"].Value;
+
+ // Did we find a matching member in the group?
+ if (Utils.AreBytesEqual(memberSid, _memberSidToMatch))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMQuerySet",
+ "GroupMemberMatcher: Matches: match member={0}, group={1)",
+ memberDE.Path,
+ groupDE.Path);
+ return true;
+ }
+ }
+
+ // We tried all the members in the group and didnt' get a match on any
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "SamMatcher: Matches: no match, group={0}", groupDE.Path);
+ return false;
+ }
+ }
+}
+
+//#endif // PAPI_REGSAM
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx.cs
new file mode 100644
index 0000000000..f34bce9376
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx.cs
@@ -0,0 +1,1116 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Net;
+using System.Security.Principal;
+
+using System.DirectoryServices;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal partial class SAMStoreCtx : StoreCtx
+ {
+ private DirectoryEntry _ctxBase;
+ private object _ctxBaseLock = new object(); // when mutating ctxBase
+
+ private bool _ownCtxBase; // if true, we "own" ctxBase and must Dispose of it when we're done
+
+ private bool _disposed = false;
+
+ internal NetCred Credentials { get { return _credentials; } }
+ private NetCred _credentials = null;
+
+ internal AuthenticationTypes AuthTypes { get { return _authTypes; } }
+ private AuthenticationTypes _authTypes;
+
+ private ContextOptions _contextOptions;
+
+ static SAMStoreCtx()
+ {
+ //
+ // Load the *PropertyMappingTableByProperty and *PropertyMappingTableByWinNT tables
+ //
+ s_userPropertyMappingTableByProperty = new Hashtable();
+ s_userPropertyMappingTableByWinNT = new Hashtable();
+
+ s_groupPropertyMappingTableByProperty = new Hashtable();
+ s_groupPropertyMappingTableByWinNT = new Hashtable();
+
+ s_computerPropertyMappingTableByProperty = new Hashtable();
+ s_computerPropertyMappingTableByWinNT = new Hashtable();
+
+ s_validPropertyMap = new Dictionary<string, ObjectMask>();
+
+ s_maskMap = new Dictionary<Type, ObjectMask>();
+ s_maskMap.Add(typeof(UserPrincipal), ObjectMask.User);
+ s_maskMap.Add(typeof(ComputerPrincipal), ObjectMask.Computer);
+ s_maskMap.Add(typeof(GroupPrincipal), ObjectMask.Group);
+ s_maskMap.Add(typeof(Principal), ObjectMask.Principal);
+
+ for (int i = 0; i < s_propertyMappingTableRaw.GetLength(0); i++)
+ {
+ string propertyName = s_propertyMappingTableRaw[i, 0] as string;
+ Type principalType = s_propertyMappingTableRaw[i, 1] as Type;
+ string winNTAttribute = s_propertyMappingTableRaw[i, 2] as string;
+ FromWinNTConverterDelegate fromWinNT = s_propertyMappingTableRaw[i, 3] as FromWinNTConverterDelegate;
+ ToWinNTConverterDelegate toWinNT = s_propertyMappingTableRaw[i, 4] as ToWinNTConverterDelegate;
+
+ Debug.Assert(propertyName != null);
+ Debug.Assert((winNTAttribute != null && fromWinNT != null) || (fromWinNT == null));
+ Debug.Assert(principalType == typeof(Principal) || principalType.IsSubclassOf(typeof(Principal)));
+
+ // Build the table entry. The same entry will be used in both tables.
+ // Once constructed, the table entries are treated as read-only, so there's
+ // no danger in sharing the entries between tables.
+ PropertyMappingTableEntry propertyEntry = new PropertyMappingTableEntry();
+ propertyEntry.propertyName = propertyName;
+ propertyEntry.suggestedWinNTPropertyName = winNTAttribute;
+ propertyEntry.winNTToPapiConverter = fromWinNT;
+ propertyEntry.papiToWinNTConverter = toWinNT;
+
+ // Add it to the appropriate tables
+ List<Hashtable> byPropertyTables = new List<Hashtable>();
+ List<Hashtable> byWinNTTables = new List<Hashtable>();
+
+ ObjectMask BitMask = 0;
+
+ if (principalType == typeof(UserPrincipal))
+ {
+ byPropertyTables.Add(s_userPropertyMappingTableByProperty);
+ byWinNTTables.Add(s_userPropertyMappingTableByWinNT);
+ BitMask = ObjectMask.User;
+ }
+ else if (principalType == typeof(ComputerPrincipal))
+ {
+ byPropertyTables.Add(s_computerPropertyMappingTableByProperty);
+ byWinNTTables.Add(s_computerPropertyMappingTableByWinNT);
+ BitMask = ObjectMask.Computer;
+ }
+ else if (principalType == typeof(GroupPrincipal))
+ {
+ byPropertyTables.Add(s_groupPropertyMappingTableByProperty);
+ byWinNTTables.Add(s_groupPropertyMappingTableByWinNT);
+ BitMask = ObjectMask.Group;
+ }
+ else
+ {
+ Debug.Assert(principalType == typeof(Principal));
+
+ byPropertyTables.Add(s_userPropertyMappingTableByProperty);
+ byPropertyTables.Add(s_computerPropertyMappingTableByProperty);
+ byPropertyTables.Add(s_groupPropertyMappingTableByProperty);
+
+ byWinNTTables.Add(s_userPropertyMappingTableByWinNT);
+ byWinNTTables.Add(s_computerPropertyMappingTableByWinNT);
+ byWinNTTables.Add(s_groupPropertyMappingTableByWinNT);
+ BitMask = ObjectMask.Principal;
+ }
+
+ if ((winNTAttribute == null) || (winNTAttribute == "*******"))
+ {
+ BitMask = ObjectMask.None;
+ }
+
+ ObjectMask currentMask;
+ if (s_validPropertyMap.TryGetValue(propertyName, out currentMask))
+ {
+ s_validPropertyMap[propertyName] = currentMask | BitMask;
+ }
+ else
+ {
+ s_validPropertyMap.Add(propertyName, BitMask);
+ }
+
+ // *PropertyMappingTableByProperty
+ // If toWinNT is null, there's no PAPI->WinNT mapping for this property
+ // (it's probably read-only, e.g., "LastLogon").
+ // if (toWinNT != null)
+ // {
+ foreach (Hashtable propertyMappingTableByProperty in byPropertyTables)
+ {
+ if (propertyMappingTableByProperty[propertyName] == null)
+ propertyMappingTableByProperty[propertyName] = new ArrayList();
+
+ ((ArrayList)propertyMappingTableByProperty[propertyName]).Add(propertyEntry);
+ }
+ // }
+
+ // *PropertyMappingTableByWinNT
+ // If fromLdap is null, there's no direct WinNT->PAPI mapping for this property.
+ // It's probably a property that requires custom handling, such as an IdentityClaim.
+ if (fromWinNT != null)
+ {
+ string winNTAttributeLower = winNTAttribute.ToLower(CultureInfo.InvariantCulture);
+
+ foreach (Hashtable propertyMappingTableByWinNT in byWinNTTables)
+ {
+ if (propertyMappingTableByWinNT[winNTAttributeLower] == null)
+ propertyMappingTableByWinNT[winNTAttributeLower] = new ArrayList();
+
+ ((ArrayList)propertyMappingTableByWinNT[winNTAttributeLower]).Add(propertyEntry);
+ }
+ }
+ }
+ }
+
+ // Throws exception if ctxBase is not a computer object
+ public SAMStoreCtx(DirectoryEntry ctxBase, bool ownCtxBase, string username, string password, ContextOptions options)
+ {
+ Debug.Assert(ctxBase != null);
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Constructing SAMStoreCtx for {0}", ctxBase.Path);
+
+ Debug.Assert(SAMUtils.IsOfObjectClass(ctxBase, "Computer"));
+
+ _ctxBase = ctxBase;
+ _ownCtxBase = ownCtxBase;
+
+ if (username != null && password != null)
+ _credentials = new NetCred(username, password);
+
+ _contextOptions = options;
+ _authTypes = SDSUtils.MapOptionsToAuthTypes(options);
+ }
+
+ public override void Dispose()
+ {
+ try
+ {
+ if (!_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Dispose: disposing, ownCtxBase={0}", _ownCtxBase);
+
+ if (_ownCtxBase)
+ _ctxBase.Dispose();
+
+ _disposed = true;
+ }
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+
+ //
+ // StoreCtx information
+ //
+
+ // Retrieves the Path (ADsPath) of the object used as the base of the StoreCtx
+ internal override string BasePath
+ {
+ get
+ {
+ Debug.Assert(_ctxBase != null);
+ return _ctxBase.Path;
+ }
+ }
+
+ //
+ // CRUD
+ //
+
+ // Used to perform the specified operation on the Principal. They also make any needed security subsystem
+ // calls to obtain digitial signatures.
+ //
+ // Insert() and Update() must check to make sure no properties not supported by this StoreCtx
+ // have been set, prior to persisting the Principal.
+ internal override void Insert(Principal p)
+ {
+ Debug.Assert(p.unpersisted == true);
+ Debug.Assert(p.fakePrincipal == false);
+
+ try
+ {
+ // Insert the principal into the store
+ SDSUtils.InsertPrincipal(
+ p,
+ this,
+ new SDSUtils.GroupMembershipUpdater(UpdateGroupMembership),
+ _credentials,
+ _authTypes,
+ false // handled in PushChangesToNative
+ );
+
+ // Load in all the initial values from the store
+ ((DirectoryEntry)p.UnderlyingObject).RefreshCache();
+
+ // Load in the StoreKey
+ Debug.Assert(p.Key == null); // since it was previously unpersisted
+
+ Debug.Assert(p.UnderlyingObject != null); // since we just persisted it
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+
+ // We just created a principal, so it should have an objectSid
+ Debug.Assert((de.Properties["objectSid"] != null) && (de.Properties["objectSid"].Count == 1));
+
+ SAMStoreKey key = new SAMStoreKey(
+ this.MachineFlatName,
+ (byte[])de.Properties["objectSid"].Value
+ );
+ p.Key = key;
+
+ // Reset the change tracking
+ p.ResetAllChangeStatus();
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Insert: new SID is ", Utils.ByteArrayToString((byte[])de.Properties["objectSid"].Value));
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ internal override void Update(Principal p)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Update");
+
+ Debug.Assert(p.fakePrincipal == false);
+ Debug.Assert(p.unpersisted == false);
+ Debug.Assert(p.UnderlyingObject != null);
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+
+ try
+ {
+ // Commit the properties
+ SDSUtils.ApplyChangesToDirectory(
+ p,
+ this,
+ new SDSUtils.GroupMembershipUpdater(UpdateGroupMembership),
+ _credentials,
+ _authTypes
+ );
+
+ // Reset the change tracking
+ p.ResetAllChangeStatus();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ internal override void Delete(Principal p)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Delete");
+ Debug.Assert(p.fakePrincipal == false);
+
+ // Principal.Delete() shouldn't be calling us on an unpersisted Principal.
+ Debug.Assert(p.unpersisted == false);
+ Debug.Assert(p.UnderlyingObject != null);
+
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+
+ try
+ {
+ SDSUtils.DeleteDirectoryEntry((DirectoryEntry)p.UnderlyingObject);
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ internal override bool AccessCheck(Principal p, PrincipalAccessMask targetPermission)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "AccessCheck " + targetPermission.ToString());
+
+ switch (targetPermission)
+ {
+ case PrincipalAccessMask.ChangePassword:
+
+ PropertyValueCollection values = ((DirectoryEntry)p.GetUnderlyingObject()).Properties["UserFlags"];
+
+ if (values.Count != 0)
+ {
+ Debug.Assert(values.Count == 1);
+ Debug.Assert(values[0] is int);
+
+ return (SDSUtils.StatusFromAccountControl((int)values[0], PropertyNames.PwdInfoCannotChangePassword));
+ }
+
+ Debug.Fail("SAMStoreCtx.AccessCheck: user entry has an empty UserFlags value");
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "AccessCheck Unable to read userAccountControl");
+
+ break;
+
+ default:
+
+ Debug.Fail("SAMStoreCtx.AccessCheck: Fell off end looking for " + targetPermission.ToString());
+
+ break;
+ }
+
+ return false;
+ }
+
+ internal override void Move(StoreCtx originalStore, Principal p)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Move");
+ }
+
+ //
+ // Special operations: the Principal classes delegate their implementation of many of the
+ // special methods to their underlying StoreCtx
+ //
+
+ // methods for manipulating accounts
+
+ /// <summary>
+ /// This method sets the default user account control bits for the new principal
+ /// being created in this account store.
+ /// </summary>
+ /// <param name="p"> Principal to set the user account control bits for </param>
+ internal override void InitializeUserAccountControl(AuthenticablePrincipal p)
+ {
+ Debug.Assert(p != null);
+ Debug.Assert(p.fakePrincipal == false);
+ Debug.Assert(p.unpersisted == true); // should only ever be called for new principals
+
+ // set the userAccountControl bits on the underlying directory entry
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+ Type principalType = p.GetType();
+
+ if ((principalType == typeof(UserPrincipal)) || (principalType.IsSubclassOf(typeof(UserPrincipal))))
+ {
+ de.Properties["userFlags"].Value = SDSUtils.SAM_DefaultUAC;
+ }
+ }
+
+ internal override bool IsLockedOut(AuthenticablePrincipal p)
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ Debug.Assert(p.unpersisted == false);
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ try
+ {
+ de.RefreshCache();
+ return (bool)de.InvokeGet("IsAccountLocked");
+ }
+ catch (System.Reflection.TargetInvocationException e)
+ {
+ if (e.InnerException is System.Runtime.InteropServices.COMException)
+ {
+ throw (ExceptionHelper.GetExceptionFromCOMException((System.Runtime.InteropServices.COMException)e.InnerException));
+ }
+ throw;
+ }
+ }
+
+ internal override void UnlockAccount(AuthenticablePrincipal p)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "UnlockAccount");
+
+ Debug.Assert(p.fakePrincipal == false);
+
+ Debug.Assert(p.unpersisted == false);
+
+ // Computer accounts are never locked out, so nothing to do
+ if (p is ComputerPrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "UnlockAccount: computer acct, skipping");
+ return;
+ }
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ // After setting the property, we need to commit the change to the store.
+ // We do it in a copy of de, so that we don't inadvertently commit any other
+ // pending changes in de.
+ DirectoryEntry copyOfDe = null;
+
+ try
+ {
+ copyOfDe = SDSUtils.BuildDirectoryEntry(de.Path, _credentials, _authTypes);
+
+ Debug.Assert(copyOfDe != null);
+ copyOfDe.InvokeSet("IsAccountLocked", new object[] { false });
+ copyOfDe.CommitChanges();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ // ADSI threw an exception trying to write the change
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "SAMStoreCtx", "UnlockAccount: caught COMException, message={0}", e.Message);
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ finally
+ {
+ if (copyOfDe != null)
+ copyOfDe.Dispose();
+ }
+ }
+
+ // methods for manipulating passwords
+ internal override void SetPassword(AuthenticablePrincipal p, string newPassword)
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ Debug.Assert(p is UserPrincipal || p is ComputerPrincipal);
+
+ // Shouldn't be being called if this is the case
+ Debug.Assert(p.unpersisted == false);
+
+ // ********** In SAM, computer accounts don't have a set password method
+ if (p is ComputerPrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "SetPassword: computer acct, can't reset");
+ throw new InvalidOperationException(StringResources.SAMStoreCtxNoComputerPasswordSet);
+ }
+
+ Debug.Assert(p != null);
+ Debug.Assert(newPassword != null); // but it could be an empty string
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ SDSUtils.SetPassword(de, newPassword);
+ }
+
+ internal override void ChangePassword(AuthenticablePrincipal p, string oldPassword, string newPassword)
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ Debug.Assert(p is UserPrincipal || p is ComputerPrincipal);
+
+ // Shouldn't be being called if this is the case
+ Debug.Assert(p.unpersisted == false);
+
+ // ********** In SAM, computer accounts don't have a change password method
+ if (p is ComputerPrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "ChangePassword: computer acct, can't change");
+ throw new InvalidOperationException(StringResources.SAMStoreCtxNoComputerPasswordSet);
+ }
+
+ Debug.Assert(p != null);
+ Debug.Assert(newPassword != null); // but it could be an empty string
+ Debug.Assert(oldPassword != null); // but it could be an empty string
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ SDSUtils.ChangePassword(de, oldPassword, newPassword);
+ }
+
+ internal override void ExpirePassword(AuthenticablePrincipal p)
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ // ********** In SAM, computer accounts don't have a password-expired property
+ if (p is ComputerPrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "ExpirePassword: computer acct, can't expire");
+ throw new InvalidOperationException(StringResources.SAMStoreCtxNoComputerPasswordExpire);
+ }
+
+ WriteAttribute(p, "PasswordExpired", 1);
+ }
+
+ internal override void UnexpirePassword(AuthenticablePrincipal p)
+ {
+ Debug.Assert(p.fakePrincipal == false);
+
+ // ********** In SAM, computer accounts don't have a password-expired property
+ if (p is ComputerPrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "UnexpirePassword: computer acct, can't unexpire");
+ throw new InvalidOperationException(StringResources.SAMStoreCtxNoComputerPasswordExpire);
+ }
+
+ WriteAttribute(p, "PasswordExpired", 0);
+ }
+
+ private void WriteAttribute(AuthenticablePrincipal p, string attribute, int value)
+ {
+ Debug.Assert(p is UserPrincipal || p is ComputerPrincipal);
+
+ Debug.Assert(p != null);
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+
+ SDSUtils.WriteAttribute(de.Path, attribute, value, _credentials, _authTypes);
+ }
+
+ //
+ // the various FindBy* methods
+ //
+
+ internal override ResultSet FindByLockoutTime(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ throw new NotSupportedException(StringResources.StoreNotSupportMethod);
+ }
+
+ internal override ResultSet FindByBadPasswordAttempt(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ throw new NotSupportedException(StringResources.StoreNotSupportMethod);
+ }
+
+ internal override ResultSet FindByLogonTime(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ return FindByDate(FindByDateMatcher.DateProperty.LogonTime, matchType, dt, principalType);
+ }
+
+ internal override ResultSet FindByPasswordSetTime(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ return FindByDate(FindByDateMatcher.DateProperty.PasswordSetTime, matchType, dt, principalType);
+ }
+
+ internal override ResultSet FindByExpirationTime(
+ DateTime dt, MatchType matchType, Type principalType)
+ {
+ return FindByDate(FindByDateMatcher.DateProperty.AccountExpirationTime, matchType, dt, principalType);
+ }
+
+ private ResultSet FindByDate(
+ FindByDateMatcher.DateProperty property,
+ MatchType matchType,
+ DateTime value,
+ Type principalType
+ )
+ {
+ // We use the same SAMQuery set that we use for query-by-example, but with a different
+ // SAMMatcher class to perform the date-range filter.
+
+ // Get the entries we'll iterate over. Write access to Children is controlled through the
+ // ctxBaseLock, but we don't want to have to hold that lock while we're iterating over all
+ // the child entries. So we have to clone the ctxBase --- not ideal, but it prevents
+ // multithreading issues.
+ DirectoryEntries entries = SDSUtils.BuildDirectoryEntry(_ctxBase.Path, _credentials, _authTypes).Children;
+ Debug.Assert(entries != null);
+
+ // The SAMQuerySet will use this to restrict the types of DirectoryEntry objects returned.
+ List<string> schemaTypes = GetSchemaFilter(principalType);
+
+ // Create the ResultSet that will perform the client-side filtering
+ SAMQuerySet resultSet = new SAMQuerySet(
+ schemaTypes,
+ entries,
+ _ctxBase,
+ -1, // no size limit
+ this,
+ new FindByDateMatcher(property, matchType, value));
+
+ return resultSet;
+ }
+
+ // Get groups of which p is a direct member
+ internal override ResultSet GetGroupsMemberOf(Principal p)
+ {
+ // Enforced by the methods that call us
+ Debug.Assert(p.unpersisted == false);
+
+ if (!p.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf: is real principal");
+
+ // No nested groups or computers as members of groups in SAM
+ if (!(p is UserPrincipal))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf: not a user, returning empty set");
+ return new EmptySet();
+ }
+
+ Debug.Assert(p.UnderlyingObject != null);
+
+ DirectoryEntry userDE = (DirectoryEntry)p.UnderlyingObject;
+
+ UnsafeNativeMethods.IADsMembers iadsMembers = (UnsafeNativeMethods.IADsMembers)userDE.Invoke("Groups");
+
+ ResultSet resultSet = new SAMGroupsSet(iadsMembers, this, _ctxBase);
+ return resultSet;
+ }
+ else
+ {
+ // ADSI's IADsGroups doesn't work for fake principals like NT AUTHORITY\NETWORK SERVICE
+
+ // We use the same SAMQuery set that we use for query-by-example, but with a different
+ // SAMMatcher class to match groups which contain the specified principal as a member
+
+ // Get the entries we'll iterate over. Write access to Children is controlled through the
+ // ctxBaseLock, but we don't want to have to hold that lock while we're iterating over all
+ // the child entries. So we have to clone the ctxBase --- not ideal, but it prevents
+ // multithreading issues.
+ DirectoryEntries entries = SDSUtils.BuildDirectoryEntry(_ctxBase.Path, _credentials, _authTypes).Children;
+ Debug.Assert(entries != null);
+
+ // The SAMQuerySet will use this to restrict the types of DirectoryEntry objects returned.
+ List<string> schemaTypes = GetSchemaFilter(typeof(GroupPrincipal));
+
+ SecurityIdentifier principalSid = p.Sid;
+ byte[] SidB = new byte[principalSid.BinaryLength];
+ principalSid.GetBinaryForm(SidB, 0);
+
+ if (principalSid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "GetGroupsMemberOf: bad SID IC");
+ throw new InvalidOperationException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery);
+ }
+
+ // Create the ResultSet that will perform the client-side filtering
+ SAMQuerySet resultSet = new SAMQuerySet(
+ schemaTypes,
+ entries,
+ _ctxBase,
+ -1, // no size limit
+ this,
+ new GroupMemberMatcher(SidB));
+
+ return resultSet;
+ }
+ }
+
+ // Get groups from this ctx which contain a principal corresponding to foreignPrincipal
+ // (which is a principal from foreignContext)
+ internal override ResultSet GetGroupsMemberOf(Principal foreignPrincipal, StoreCtx foreignContext)
+ {
+ // If it's a fake principal, we don't need to do any of the lookup to find a local representation.
+ // We'll skip straight to GetGroupsMemberOf(Principal), which will lookup the groups to which it belongs via its SID.
+ if (foreignPrincipal.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf(ctx): is fake principal");
+ return GetGroupsMemberOf(foreignPrincipal);
+ }
+
+ // Get the Principal's SID, so we can look it up by SID in our store
+ SecurityIdentifier Sid = foreignPrincipal.Sid;
+
+ if (Sid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "GetGroupsMemberOf(ctx): no SID IC");
+ throw new InvalidOperationException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery);
+ }
+
+ // In SAM, only users can be member of SAM groups (no nested groups)
+ UserPrincipal u = UserPrincipal.FindByIdentity(this.OwningContext, IdentityType.Sid, Sid.ToString());
+
+ // If no corresponding principal exists in this store, then by definition the principal isn't
+ // a member of any groups in this store.
+ if (u == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf(ctx): no corresponding user, returning empty set");
+ return new EmptySet();
+ }
+
+ // Now that we got the principal in our store, enumerating its group membership can be handled the
+ // usual way.
+ return GetGroupsMemberOf(u);
+ }
+
+ // Get groups of which p is a member, using AuthZ S4U APIs for recursive membership
+ internal override ResultSet GetGroupsMemberOfAZ(Principal p)
+ {
+ // Enforced by the methods that call us
+ Debug.Assert(p.unpersisted == false);
+ Debug.Assert(p is UserPrincipal);
+
+ // Get the user SID that AuthZ will use.
+ SecurityIdentifier Sid = p.Sid;
+
+ if (Sid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "GetGroupsMemberOfAZ: no SID IC");
+ throw new InvalidOperationException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery);
+ }
+
+ byte[] Sidb = new byte[Sid.BinaryLength];
+ Sid.GetBinaryForm(Sidb, 0);
+
+ if (Sidb == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "GetGroupsMemberOfAZ: Bad SID IC");
+ throw new ArgumentException(StringResources.StoreCtxSecurityIdentityClaimBadFormat);
+ }
+
+ try
+ {
+ return new AuthZSet(Sidb, _credentials, _contextOptions, this.MachineFlatName, this, _ctxBase);
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ // Get members of group g
+ internal override BookmarkableResultSet GetGroupMembership(GroupPrincipal g, bool recursive)
+ {
+ // Enforced by the methods that call us
+ Debug.Assert(g.unpersisted == false);
+
+ // Fake groups are a member of other groups, but they themselves have no members
+ // (they don't even exist in the store)
+ if (g.fakePrincipal)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupMembership: is fake principal, returning empty set");
+ return new EmptySet();
+ }
+
+ Debug.Assert(g.UnderlyingObject != null);
+
+ DirectoryEntry groupDE = (DirectoryEntry)g.UnderlyingObject;
+
+ UnsafeNativeMethods.IADsGroup iADsGroup = (UnsafeNativeMethods.IADsGroup)groupDE.NativeObject;
+
+ BookmarkableResultSet resultSet = new SAMMembersSet(groupDE.Path, iADsGroup, recursive, this, _ctxBase);
+ return resultSet;
+ }
+
+ // Is p a member of g in the store?
+ internal override bool SupportsNativeMembershipTest { get { return false; } }
+
+ internal override bool IsMemberOfInStore(GroupPrincipal g, Principal p)
+ {
+ Debug.Fail("SAMStoreCtx.IsMemberOfInStore: Shouldn't be here.");
+ return false;
+ }
+
+ // Can a Clear() operation be performed on the specified group? If not, also returns
+ // a string containing a human-readable explanation of why not, suitable for use in an exception.
+ internal override bool CanGroupBeCleared(GroupPrincipal g, out string explanationForFailure)
+ {
+ // Always true for this type of StoreCtx
+ explanationForFailure = null;
+ return true;
+ }
+
+ // Can the given member be removed from the specified group? If not, also returns
+ // a string containing a human-readable explanation of why not, suitable for use in an exception.
+ internal override bool CanGroupMemberBeRemoved(GroupPrincipal g, Principal member, out string explanationForFailure)
+ {
+ // Always true for this type of StoreCtx
+ explanationForFailure = null;
+ return true;
+ }
+
+ //
+ // Cross-store support
+ //
+
+ // Given a native store object that represents a "foreign" principal (e.g., a FPO object in this store that
+ // represents a pointer to another store), maps that representation to the other store's StoreCtx and returns
+ // a Principal from that other StoreCtx. The implementation of this method is highly dependent on the
+ // details of the particular store, and must have knowledge not only of this StoreCtx, but also of how to
+ // interact with other StoreCtxs to fulfill the request.
+ //
+ // This method is typically used by ResultSet implementations, when they're iterating over a collection
+ // (e.g., of group membership) and encounter a entry that represents a foreign principal.
+ internal override Principal ResolveCrossStoreRefToPrincipal(object o)
+ {
+ Debug.Assert(o is DirectoryEntry);
+
+ // Get the SID of the foreign principal
+ DirectoryEntry foreignDE = (DirectoryEntry)o;
+
+ if (foreignDE.Properties["objectSid"].Count == 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "ResolveCrossStoreRefToPrincipal: no objectSid found");
+ throw new PrincipalOperationException(StringResources.SAMStoreCtxCantRetrieveObjectSidForCrossStore);
+ }
+
+ Debug.Assert(foreignDE.Properties["objectSid"].Count == 1);
+
+ byte[] sid = (byte[])foreignDE.Properties["objectSid"].Value;
+
+ // Ask the OS to resolve the SID to its target.
+ int accountUsage = 0;
+ string name;
+ string domainName;
+
+ int err = Utils.LookupSid(this.MachineUserSuppliedName, _credentials, sid, out name, out domainName, out accountUsage);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn,
+ "SAMStoreCtx",
+ "ResolveCrossStoreRefToPrincipal: LookupSid failed, err={0}, server={1}",
+ err,
+ this.MachineUserSuppliedName);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.SAMStoreCtxCantResolveSidForCrossStore,
+ err));
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMStoreCtx",
+ "ResolveCrossStoreRefToPrincipal: LookupSid found {0} in {1}",
+ name,
+ domainName);
+
+ // Since this is SAM, the remote principal must be an AD principal.
+ // Build a PrincipalContext for the store which owns the principal
+ // Use the ad default options so we turn sign and seal back on.
+#if USE_CTX_CACHE
+ PrincipalContext remoteCtx = SDSCache.Domain.GetContext(domainName, _credentials, DefaultContextOptions.ADDefaultContextOption);
+#else
+ PrincipalContext remoteCtx = new PrincipalContext(
+ ContextType.Domain,
+ domainName,
+ null,
+ (this.credentials != null ? credentials.UserName : null),
+ (this.credentials != null ? credentials.Password : null),
+ DefaultContextOptions.ADDefaultContextOption);
+
+#endif
+
+ SecurityIdentifier sidObj = new SecurityIdentifier(sid, 0);
+
+ Principal p = remoteCtx.QueryCtx.FindPrincipalByIdentRef(
+ typeof(Principal),
+ UrnScheme.SidScheme,
+ sidObj.ToString(),
+ DateTime.UtcNow);
+
+ if (p != null)
+ return p;
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "ResolveCrossStoreRefToPrincipal: no matching principal");
+ throw new PrincipalOperationException(StringResources.SAMStoreCtxFailedFindCrossStoreTarget);
+ }
+ }
+
+ //
+ // Data Validation
+ //
+
+ // Returns true if AccountInfo is supported for the specified principal, false otherwise.
+ // Used when a application tries to access the AccountInfo property of a newly-inserted
+ // (not yet persisted) AuthenticablePrincipal, to determine whether it should be allowed.
+ internal override bool SupportsAccounts(AuthenticablePrincipal p)
+ {
+ // Fake principals do not have store objects, so they certainly don't have stored account info.
+ if (p.fakePrincipal)
+ return false;
+
+ // Both Computer and User support accounts.
+ return true;
+ }
+
+ // Returns the set of credential types supported by this store for the specified principal.
+ // Used when a application tries to access the PasswordInfo property of a newly-inserted
+ // (not yet persisted) AuthenticablePrincipal, to determine whether it should be allowed.
+ // Also used to implement AuthenticablePrincipal.SupportedCredentialTypes.
+ internal override CredentialTypes SupportedCredTypes(AuthenticablePrincipal p)
+ {
+ // Fake principals do not have store objects, so they certainly don't have stored creds.
+ if (p.fakePrincipal)
+ return (CredentialTypes)0;
+
+ CredentialTypes supportedTypes = CredentialTypes.Password;
+
+ // Longhorn SAM supports certificate-based authentication
+ if (this.IsLSAM)
+ supportedTypes |= CredentialTypes.Certificate;
+
+ return supportedTypes;
+ }
+
+ //
+ // Construct a fake Principal to represent a well-known SID like
+ // "\Everyone" or "NT AUTHORITY\NETWORK SERVICE"
+ //
+ internal override Principal ConstructFakePrincipalFromSID(byte[] sid)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMStoreCtx",
+ "ConstructFakePrincipalFromSID: sid={0}, machine={1}",
+ Utils.ByteArrayToString(sid),
+ this.MachineFlatName);
+
+ Principal p = Utils.ConstructFakePrincipalFromSID(
+ sid,
+ this.OwningContext,
+ this.MachineUserSuppliedName,
+ _credentials,
+ this.MachineUserSuppliedName);
+
+ // Assign it a StoreKey
+ SAMStoreKey key = new SAMStoreKey(this.MachineFlatName, sid);
+ p.Key = key;
+
+ return p;
+ }
+
+ //
+ // Private data
+ //
+
+ private bool IsLSAM // IsLonghornSAM (also called MSAM or LH-SAM)
+ {
+ get
+ {
+ if (!_isLSAM.HasValue)
+ {
+ lock (_computerInfoLock)
+ {
+ if (!_isLSAM.HasValue)
+ LoadComputerInfo();
+ }
+ }
+
+ Debug.Assert(_isLSAM.HasValue);
+ return _isLSAM.Value;
+ }
+ }
+
+ internal string MachineUserSuppliedName
+ {
+ get
+ {
+ if (_machineUserSuppliedName == null)
+ {
+ lock (_computerInfoLock)
+ {
+ if (_machineUserSuppliedName == null)
+ LoadComputerInfo();
+ }
+ }
+
+ Debug.Assert(_machineUserSuppliedName != null);
+ return _machineUserSuppliedName;
+ }
+ }
+
+ internal string MachineFlatName
+ {
+ get
+ {
+ if (_machineFlatName == null)
+ {
+ lock (_computerInfoLock)
+ {
+ if (_machineFlatName == null)
+ LoadComputerInfo();
+ }
+ }
+
+ Debug.Assert(_machineFlatName != null);
+ return _machineFlatName;
+ }
+ }
+
+ private object _computerInfoLock = new object();
+ private Nullable<bool> _isLSAM = null;
+ private string _machineUserSuppliedName = null;
+ private string _machineFlatName = null;
+
+ // computerInfoLock must be held coming in here
+ private void LoadComputerInfo()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo");
+
+ Debug.Assert(_ctxBase != null);
+ Debug.Assert(SAMUtils.IsOfObjectClass(_ctxBase, "Computer"));
+
+ //
+ // Target OS version
+ //
+ int versionMajor;
+ int versionMinor;
+
+ if (!SAMUtils.GetOSVersion(_ctxBase, out versionMajor, out versionMinor))
+ {
+ throw new PrincipalOperationException(StringResources.SAMStoreCtxUnableToRetrieveVersion);
+ }
+
+ Debug.Assert(versionMajor > 0);
+ Debug.Assert(versionMinor >= 0);
+
+ if (versionMajor >= 6) // 6.0 == Longhorn
+ _isLSAM = true;
+ else
+ _isLSAM = false;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo: ver={0}.{1}", versionMajor, versionMinor);
+
+ //
+ // Machine user-supplied name
+ //
+
+ // This ADSI property stores the machine name as supplied by the user in the ADsPath.
+ // It could be a flat name or a DNS name.
+ if (_ctxBase.Properties["Name"].Count > 0)
+ {
+ Debug.Assert(_ctxBase.Properties["Name"].Count == 1);
+
+ _machineUserSuppliedName = (string)_ctxBase.Properties["Name"].Value;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo: machineUserSuppliedName={0}", _machineUserSuppliedName);
+ }
+ else
+ {
+ throw new PrincipalOperationException(StringResources.SAMStoreCtxUnableToRetrieveMachineName);
+ }
+
+ //
+ // Machine flat name
+ //
+ IntPtr buffer = IntPtr.Zero;
+
+ try
+ {
+ // This function takes in a flat or DNS name, and returns the flat name of the computer
+ int err = UnsafeNativeMethods.NetWkstaGetInfo(_machineUserSuppliedName, 100, ref buffer);
+ if (err == 0)
+ {
+ UnsafeNativeMethods.WKSTA_INFO_100 wkstaInfo =
+ (UnsafeNativeMethods.WKSTA_INFO_100)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.WKSTA_INFO_100));
+
+ _machineFlatName = wkstaInfo.wki100_computername;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo: machineFlatName={0}", _machineFlatName);
+ }
+ else
+ {
+ throw new PrincipalOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.SAMStoreCtxUnableToRetrieveFlatMachineName,
+ err));
+ }
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ UnsafeNativeMethods.NetApiBufferFree(buffer);
+ }
+ }
+
+ internal override bool IsValidProperty(Principal p, string propertyName)
+ {
+ ObjectMask value = ObjectMask.None;
+
+ if (s_validPropertyMap.TryGetValue(propertyName, out value))
+ {
+ return ((s_maskMap[p.GetType()] & value) > 0 ? true : false);
+ }
+ else
+ {
+ Debug.Assert(false);
+ return false;
+ }
+ }
+ }
+}
+
+// #endif // PAPI_REGSAM
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx_LoadStore.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx_LoadStore.cs
new file mode 100644
index 0000000000..0fc7cbf354
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx_LoadStore.cs
@@ -0,0 +1,1190 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+using System.Collections;
+using System.Text;
+using System.Globalization;
+using System.Security.Cryptography.X509Certificates;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Net;
+using System.Security.Principal;
+
+using System.DirectoryServices;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal partial class SAMStoreCtx : StoreCtx
+ {
+ //
+ // Native <--> Principal
+ //
+
+ // For modified object, pushes any changes (including IdentityClaim changes)
+ // into the underlying store-specific object (e.g., DirectoryEntry) and returns the underlying object.
+ // For unpersisted object, creates a underlying object if one doesn't already exist (in
+ // Principal.UnderlyingObject), then pushes any changes into the underlying object.
+ internal override object PushChangesToNative(Principal p)
+ {
+ try
+ {
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Type principalType = p.GetType();
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Entering PushChangesToNative, type={0}", p.GetType());
+
+ if (de == null)
+ {
+ // Must be a newly-inserted Principal for which PushChangesToNative has not yet
+ // been called.
+
+ // Determine the objectClass of the SAM entry we'll be creating
+ string objectClass;
+
+ if (principalType == typeof(UserPrincipal) || principalType.IsSubclassOf(typeof(UserPrincipal)))
+ objectClass = "user";
+ else if (principalType == typeof(GroupPrincipal) || principalType.IsSubclassOf(typeof(GroupPrincipal)))
+ objectClass = "group";
+ else
+ {
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForSave, principalType.ToString()));
+ }
+
+ // Determine the SAM account name for the entry we'll be creating. Use the name from the NT4 IdentityClaim.
+ string samAccountName = GetSamAccountName(p);
+
+ if (samAccountName == null)
+ {
+ // They didn't set a NT4 IdentityClaim.
+ throw new InvalidOperationException(StringResources.NameMustBeSetToPersistPrincipal);
+ }
+
+ lock (_ctxBaseLock)
+ {
+ de = _ctxBase.Children.Add(samAccountName, objectClass);
+ }
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info, "SAMStoreCtx", "PushChangesToNative: created fresh DE, oc={0}, name={1}, path={2}",
+ objectClass, samAccountName, de.Path);
+
+ p.UnderlyingObject = de;
+
+ // set the default user account control bits for authenticable principals
+ if (principalType.IsSubclassOf(typeof(AuthenticablePrincipal)))
+ {
+ InitializeUserAccountControl((AuthenticablePrincipal)p);
+ }
+ }
+
+ // Determine the mapping table to use, based on the principal type
+ Hashtable propertyMappingTableByProperty;
+
+ if (principalType == typeof(UserPrincipal))
+ {
+ propertyMappingTableByProperty = s_userPropertyMappingTableByProperty;
+ }
+ else if (principalType == typeof(GroupPrincipal))
+ {
+ propertyMappingTableByProperty = s_groupPropertyMappingTableByProperty;
+ }
+ else
+ {
+ Debug.Assert(principalType == typeof(ComputerPrincipal));
+ propertyMappingTableByProperty = s_computerPropertyMappingTableByProperty;
+ }
+
+ // propertyMappingTableByProperty has entries for all writable properties,
+ // including writable properties which we don't support in SAM for some or
+ // all principal types.
+ // If we don't support the property, the PropertyMappingTableEntry will map
+ // it to a converter which will throw an appropriate exception.
+ foreach (DictionaryEntry dictEntry in propertyMappingTableByProperty)
+ {
+ ArrayList propertyEntries = (ArrayList)dictEntry.Value;
+
+ foreach (PropertyMappingTableEntry propertyEntry in propertyEntries)
+ {
+ if (null != propertyEntry.papiToWinNTConverter)
+ {
+ if (p.GetChangeStatusForProperty(propertyEntry.propertyName))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "PushChangesToNative: pushing {0}", propertyEntry.propertyName);
+
+ // The property was set. Write it to the DirectoryEntry.
+ Debug.Assert(propertyEntry.propertyName == (string)dictEntry.Key);
+ propertyEntry.papiToWinNTConverter(
+ p,
+ propertyEntry.propertyName,
+ de,
+ propertyEntry.suggestedWinNTPropertyName,
+ this.IsLSAM
+ );
+ }
+ }
+ }
+ }
+
+ // Unlike AD, where password sets on newly-created principals must be handled after persisting the principal,
+ // in SAM they get set before persisting the principal, and ADSI's WinNT provider saves off the operation
+ // until the SetInfo() is performed.
+
+ if (p.GetChangeStatusForProperty(PropertyNames.PwdInfoPassword))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "PushChangesToNative: setting password");
+
+ // Only AuthenticablePrincipals can have PasswordInfo
+ Debug.Assert(p is AuthenticablePrincipal);
+
+ string password = (string)p.GetValueForProperty(PropertyNames.PwdInfoPassword);
+ Debug.Assert(password != null); // if null, PasswordInfo should not have indicated it was changed
+
+ SDSUtils.SetPassword(de, password);
+ }
+
+ return de;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ private string GetSamAccountName(Principal p)
+ {
+ // They didn't set any IdentityClaims, so they certainly didn't set a NT4 IdentityClaim
+ if (!p.GetChangeStatusForProperty(PropertyNames.PrincipalSamAccountName))
+ return null;
+
+ string Name = p.SamAccountName;
+
+ if (Name == null)
+ return null;
+
+ // Split the SAM account name out of the UrnValue
+ // We accept both "host\user" and "user"
+ int index = Name.IndexOf('\\');
+
+ if (index == Name.Length - 1)
+ return null;
+
+ return (index != -1) ? Name.Substring(index + 1) : // +1 to skip the '/'
+ Name;
+ }
+
+ // Given a underlying store object (e.g., DirectoryEntry), further narrowed down a discriminant
+ // (if applicable for the StoreCtx type), returns a fresh instance of a Principal
+ // object based on it. The WinFX Principal API follows ADSI-style semantics, where you get multiple
+ // in-memory objects all referring to the same store pricipal, rather than WinFS semantics, where
+ // multiple searches all return references to the same in-memory object.
+ // Used to implement the reverse wormhole. Also, used internally by FindResultEnumerator
+ // to construct Principals from the store objects returned by a store query.
+ //
+ // The Principal object produced by this method does not have all the properties
+ // loaded. The Principal object will call the Load method on demand to load its properties
+ // from its Principal.UnderlyingObject.
+ //
+ //
+ // This method works for native objects from the store corresponding to _this_ StoreCtx.
+ // Each StoreCtx will also have its own internal algorithms used for dealing with cross-store objects, e.g.,
+ // for use when iterating over group membership. These routines are exposed as
+ // ResolveCrossStoreRefToPrincipal, and will be called by the StoreCtx's associated ResultSet
+ // classes when iterating over a representation of a "foreign" principal.
+ internal override Principal GetAsPrincipal(object storeObject, object discriminant)
+ {
+ // SAM doesn't use discriminant, should always be null.
+ Debug.Assert(discriminant == null);
+
+ Debug.Assert(storeObject != null);
+ Debug.Assert(storeObject is DirectoryEntry);
+
+ DirectoryEntry de = (DirectoryEntry)storeObject;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetAsPrincipal: using path={0}", de.Path);
+
+ // Construct a appropriate Principal object.
+ Principal p = SDSUtils.DirectoryEntryToPrincipal(de, this.OwningContext, null);
+ Debug.Assert(p != null);
+
+ // Assign a SAMStoreKey to the newly-constructed Principal.
+
+ // If it doesn't have an objectSid, it's not a principal and we shouldn't be here.
+ Debug.Assert((de.Properties["objectSid"] != null) && (de.Properties["objectSid"].Count == 1));
+
+ SAMStoreKey key = new SAMStoreKey(this.MachineFlatName, (byte[])de.Properties["objectSid"].Value);
+ p.Key = key;
+
+ return p;
+ }
+
+ internal override void Load(Principal p, string principalPropertyName)
+ {
+ Debug.Assert(p != null);
+ Debug.Assert(p.UnderlyingObject != null);
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+
+ Type principalType = p.GetType();
+ Hashtable propertyMappingTableByProperty;
+
+ if (principalType == typeof(UserPrincipal))
+ {
+ propertyMappingTableByProperty = s_userPropertyMappingTableByProperty;
+ }
+ else if (principalType == typeof(GroupPrincipal))
+ {
+ propertyMappingTableByProperty = s_groupPropertyMappingTableByProperty;
+ }
+ else
+ {
+ Debug.Assert(principalType == typeof(ComputerPrincipal));
+ propertyMappingTableByProperty = s_computerPropertyMappingTableByProperty;
+ }
+
+ ArrayList entries = (ArrayList)propertyMappingTableByProperty[principalPropertyName];
+
+ // We don't support this property and cannot load it. To maintain backward compatibility with the old code just return.
+ if (entries == null)
+ return;
+
+ try
+ {
+ foreach (PropertyMappingTableEntry entry in entries)
+ {
+ if (null != entry.winNTToPapiConverter)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Load_PropertyName: loading {0}", entry.propertyName);
+ entry.winNTToPapiConverter(de, entry.suggestedWinNTPropertyName, p, entry.propertyName);
+ }
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ // Loads the store values from p.UnderlyingObject into p, performing schema mapping as needed.
+ internal override void Load(Principal p)
+ {
+ try
+ {
+ Debug.Assert(p != null);
+ Debug.Assert(p.UnderlyingObject != null);
+ Debug.Assert(p.UnderlyingObject is DirectoryEntry);
+
+ DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject;
+ Debug.Assert(de != null);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Entering Load, type={0}, path={1}", p.GetType(), de.Path);
+
+ // The list of all the SAM attributes in the DirectoryEntry
+ ICollection samAttributes = de.Properties.PropertyNames;
+
+ // Determine the mapping table to use, based on the principal type
+ Type principalType = p.GetType();
+ Hashtable propertyMappingTableByWinNT;
+
+ if (principalType == typeof(UserPrincipal))
+ {
+ propertyMappingTableByWinNT = s_userPropertyMappingTableByWinNT;
+ }
+ else if (principalType == typeof(GroupPrincipal))
+ {
+ propertyMappingTableByWinNT = s_groupPropertyMappingTableByWinNT;
+ }
+ else
+ {
+ Debug.Assert(principalType == typeof(ComputerPrincipal));
+ propertyMappingTableByWinNT = s_computerPropertyMappingTableByWinNT;
+ }
+
+ // Map each SAM attribute into the Principal in turn
+ foreach (string samAttribute in samAttributes)
+ {
+ ArrayList entries = (ArrayList)propertyMappingTableByWinNT[samAttribute.ToLower(CultureInfo.InvariantCulture)];
+
+ // If it's not in the table, it's not an SAM attribute we care about
+ if (entries == null)
+ continue;
+
+ // Load it into the Principal. Some LDAP attributes (such as userAccountControl)
+ // map to more than one Principal property.
+ foreach (PropertyMappingTableEntry entry in entries)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Load: loading {0}", entry.propertyName);
+ entry.winNTToPapiConverter(de, entry.suggestedWinNTPropertyName, p, entry.propertyName);
+ }
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ // Performs store-specific resolution of an IdentityReference to a Principal
+ // corresponding to the IdentityReference. Returns null if no matching object found.
+ // principalType can be used to scope the search to principals of a specified type, e.g., users or groups.
+ // Specify typeof(Principal) to search all principal types.
+ internal override Principal FindPrincipalByIdentRef(
+ Type principalType, string urnScheme, string urnValue, DateTime referenceDate)
+ {
+ // Perform the appropriate action based on the type of the UrnScheme
+ if (urnScheme == UrnScheme.SidScheme)
+ {
+ // Get the SID from the UrnValue
+ SecurityIdentifier sidObj = new SecurityIdentifier(urnValue);
+ byte[] sid = new byte[sidObj.BinaryLength];
+ sidObj.GetBinaryForm(sid, 0);
+
+ if (sid == null)
+ throw new ArgumentException(StringResources.StoreCtxSecurityIdentityClaimBadFormat);
+
+ // If they're searching by SID for a SID corresponding to a fake group, construct
+ // and return the fake group
+ IntPtr pSid = IntPtr.Zero;
+
+ try
+ {
+ pSid = Utils.ConvertByteArrayToIntPtr(sid);
+
+ if (UnsafeNativeMethods.IsValidSid(pSid) && (Utils.ClassifySID(pSid) == SidType.FakeObject))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMStoreCtx",
+ "FindPrincipalByIdentRef: fake principal {0}",
+ sidObj.ToString());
+
+ return ConstructFakePrincipalFromSID(sid);
+ }
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pSid);
+ }
+
+ // Not a fake group. Search for the real group.
+ object o = FindNativeBySIDIdentRef(principalType, sid);
+ return (o != null) ? GetAsPrincipal(o, null) : null;
+ }
+ else if (urnScheme == UrnScheme.SamAccountScheme || urnScheme == UrnScheme.NameScheme)
+ {
+ object o = FindNativeByNT4IdentRef(principalType, urnValue);
+ return (o != null) ? GetAsPrincipal(o, null) : null;
+ }
+ else if (urnScheme == null)
+ {
+ object sidPrincipal = null;
+ object nt4Principal = null;
+
+ //
+ // Try UrnValue as a SID IdentityClaim
+ //
+
+ // Get the SID from the UrnValue
+ byte[] sid = null;
+
+ try
+ {
+ SecurityIdentifier sidObj = new SecurityIdentifier(urnValue);
+ sid = new byte[sidObj.BinaryLength];
+ sidObj.GetBinaryForm(sid, 0);
+ }
+ catch (ArgumentException)
+ {
+ // must not have been a valid sid claim ignore it.
+ }
+
+ // If null, must have been a non-SID UrnValue. Ignore it, and
+ // continue on to try NT4 Account IdentityClaim.
+ if (sid != null)
+ {
+ // Are they perhaps searching for a fake group?
+ // If they passed in a valid SID for a fake group, construct and return the fake
+ // group.
+ if (principalType == typeof(Principal) || principalType == typeof(GroupPrincipal) || principalType.IsSubclassOf(typeof(GroupPrincipal)))
+ {
+ // They passed in a hex string, is it a valid SID, and if so, does it correspond to a fake
+ // principal?
+ IntPtr pSid = IntPtr.Zero;
+
+ try
+ {
+ pSid = Utils.ConvertByteArrayToIntPtr(sid);
+
+ if (UnsafeNativeMethods.IsValidSid(pSid) && (Utils.ClassifySID(pSid) == SidType.FakeObject))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMStoreCtx",
+ "FindPrincipalByIdentRef: fake principal {0} (scheme==null)",
+ Utils.ByteArrayToString(sid));
+
+ return ConstructFakePrincipalFromSID(sid);
+ }
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pSid);
+ }
+ }
+
+ sidPrincipal = FindNativeBySIDIdentRef(principalType, sid);
+ }
+
+ //
+ // Try UrnValue as a NT4 IdentityClaim
+ //
+
+ try
+ {
+ nt4Principal = FindNativeByNT4IdentRef(principalType, urnValue);
+ }
+ catch (ArgumentException)
+ {
+ // Must have been a non-NT4 Account UrnValue. Ignore it.
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info,
+ "SAMStoreCtx",
+ "FindPrincipalByIdentRef: scheme==null, found nt4={0}, found sid={1}",
+ (nt4Principal != null),
+ (sidPrincipal != null));
+
+ // If they both succeeded in finding a match, we have too many matches.
+ // Throw an exception.
+ if ((sidPrincipal != null) && (nt4Principal != null))
+ throw new MultipleMatchesException(StringResources.MultipleMatchingPrincipals);
+
+ // Return whichever one matched. If neither matched, this will return null.
+ return (sidPrincipal != null) ? GetAsPrincipal(sidPrincipal, null) :
+ ((nt4Principal != null) ? GetAsPrincipal(nt4Principal, null) :
+ null);
+ }
+ else
+ {
+ // Unsupported type of IdentityClaim
+ throw new ArgumentException(StringResources.StoreCtxUnsupportedIdentityClaimForQuery);
+ }
+ }
+
+ private object FindNativeBySIDIdentRef(Type principalType, byte[] sid)
+ {
+ // We can't lookup directly by SID, so we transform the SID --> SAM account name,
+ // and do a lookup by that.
+
+ string samUrnValue;
+
+ string name;
+ string domainName;
+ int accountUsage;
+
+ // Map the SID to a machine and account name
+ // If this fails, there's no match
+ int err = Utils.LookupSid(this.MachineUserSuppliedName, _credentials, sid, out name, out domainName, out accountUsage);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "SAMStoreCtx",
+ "FindNativeBySIDIdentRef:LookupSid on {0} failed, err={1}",
+ this.MachineUserSuppliedName,
+ err);
+ return null;
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "FindNativeBySIDIdentRef: mapped to {0}\\{1}", domainName, name);
+
+ // Fixup the domainName for BUILTIN principals
+ if (Utils.ClassifySID(sid) == SidType.RealObjectFakeDomain)
+ {
+ // BUILTIN principal ---> Issuer is actually our machine, not "BUILTIN" domain.
+ domainName = this.MachineFlatName;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "FindNativeBySIDIdentRef: using {0} for domainName", domainName);
+ }
+
+ // Valid SID, but not for our context (machine). No match.
+ if (String.Compare(domainName, this.MachineFlatName, StringComparison.OrdinalIgnoreCase) != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "FindNativeBySIDIdentRef: {0} != {1}, no match", domainName, this.MachineFlatName);
+ return null;
+ }
+
+ // Build the NT4 UrnValue
+ samUrnValue = domainName + "\\" + name;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "FindNativeBySIDIdentRef: searching for {0}", samUrnValue);
+
+ return FindNativeByNT4IdentRef(principalType, samUrnValue);
+ }
+
+ private object FindNativeByNT4IdentRef(Type principalType, string urnValue)
+ {
+ // Extract the SAM account name from the UrnValue.
+ // We'll accept both "host\user" and "user".
+ int index = urnValue.IndexOf('\\');
+
+ if (index == urnValue.Length - 1)
+ throw new ArgumentException(StringResources.StoreCtxNT4IdentityClaimWrongForm);
+
+ string samAccountName = (index != -1) ? urnValue.Substring(index + 1) : // +1 to skip the '/'
+ urnValue;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "FindNativeByNT4IdentRef: searching for {0}", samAccountName);
+
+ // If they specified a specific type of principal, use that as a hint to speed up
+ // the lookup.
+ string principalHint = "";
+
+ if (principalType == typeof(UserPrincipal) || principalType.IsSubclassOf(typeof(UserPrincipal)))
+ {
+ principalHint = ",user";
+ principalType = typeof(UserPrincipal);
+ }
+ else if (principalType == typeof(GroupPrincipal) || principalType.IsSubclassOf(typeof(GroupPrincipal)))
+ {
+ principalHint = ",group";
+ principalType = typeof(GroupPrincipal);
+ }
+ else if (principalType == typeof(ComputerPrincipal) || principalType.IsSubclassOf(typeof(ComputerPrincipal)))
+ {
+ principalHint = ",computer";
+ principalType = typeof(ComputerPrincipal);
+ }
+
+ // Retrieve the object from SAM
+ string adsPath = "WinNT://" + this.MachineUserSuppliedName + "/" + samAccountName + principalHint;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "FindNativeByNT4IdentRef: adsPath={0}", adsPath);
+
+ DirectoryEntry de = SDSUtils.BuildDirectoryEntry(_credentials, _authTypes);
+
+ try
+ {
+ de.Path = adsPath;
+
+ // If it has no SID, it's not a security principal, and we're not interested in it.
+ // This also has the side effect of forcing the object to load, thereby testing
+ // whether or not it exists.
+ if (de.Properties["objectSid"] == null || de.Properties["objectSid"].Count == 0)
+ return false;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "SAMStoreCtx",
+ "FindNativeByNT4IdentRef: caught COMException, message={0}, code={1}",
+ e.Message,
+ e.ErrorCode);
+
+ // Failed to find it
+ if ((e.ErrorCode == unchecked((int)0x800708AB)) || // unknown user
+ (e.ErrorCode == unchecked((int)0x800708AC)) || // unknown group
+ (e.ErrorCode == unchecked((int)0x80070035)) || // bad net path
+ (e.ErrorCode == unchecked((int)0x800708AD)))
+ {
+ return null;
+ }
+
+ // Unknown error, don't suppress it
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+
+ // Make sure it's of the correct type
+ bool fMatch = false;
+
+ if ((principalType == typeof(UserPrincipal)) && SAMUtils.IsOfObjectClass(de, "User"))
+ fMatch = true;
+ else if ((principalType == typeof(GroupPrincipal)) && SAMUtils.IsOfObjectClass(de, "Group"))
+ fMatch = true;
+ else if ((principalType == typeof(ComputerPrincipal)) && SAMUtils.IsOfObjectClass(de, "Computer"))
+ fMatch = true;
+ else if ((principalType == typeof(AuthenticablePrincipal)) &&
+ (SAMUtils.IsOfObjectClass(de, "User") || SAMUtils.IsOfObjectClass(de, "Computer")))
+ fMatch = true;
+ else
+ {
+ Debug.Assert(principalType == typeof(Principal));
+
+ if (SAMUtils.IsOfObjectClass(de, "User") || SAMUtils.IsOfObjectClass(de, "Group") || SAMUtils.IsOfObjectClass(de, "Computer"))
+ fMatch = true;
+ }
+
+ if (fMatch)
+ return de;
+
+ return null;
+ }
+
+ // Returns a type indicating the type of object that would be returned as the wormhole for the specified
+ // Principal. For some StoreCtxs, this method may always return a constant (e.g., typeof(DirectoryEntry)
+ // for ADStoreCtx). For others, it may vary depending on the Principal passed in.
+ internal override Type NativeType(Principal p)
+ {
+ Debug.Assert(p != null);
+
+ return typeof(DirectoryEntry);
+ }
+
+ //
+ // Property mapping tables
+ //
+
+ // We only list properties we map in this table. At run-time, if we detect they set a
+ // property that's not listed here, or is listed here but not for the correct principal type,
+ // when writing to SAM, we throw an exception.
+ private static object[,] s_propertyMappingTableRaw =
+ {
+ // PropertyName Principal Type SAM property Converter(WinNT->PAPI) Converter(PAPI->WinNT)
+ {PropertyNames.PrincipalDisplayName, typeof(UserPrincipal), "FullName", new FromWinNTConverterDelegate(StringFromWinNTConverter), new ToWinNTConverterDelegate(StringToWinNTConverter)},
+ {PropertyNames.PrincipalDescription, typeof(UserPrincipal), "Description", new FromWinNTConverterDelegate(StringFromWinNTConverter), new ToWinNTConverterDelegate(StringToWinNTConverter)},
+ {PropertyNames.PrincipalDescription, typeof(GroupPrincipal), "Description", new FromWinNTConverterDelegate(StringFromWinNTConverter), new ToWinNTConverterDelegate(StringToWinNTConverter)},
+ {PropertyNames.PrincipalSamAccountName, typeof(Principal), "Name", new FromWinNTConverterDelegate(SamAccountNameFromWinNTConverter), null},
+ {PropertyNames.PrincipalSid, typeof(Principal), "objectSid", new FromWinNTConverterDelegate(SidFromWinNTConverter), null },
+ {PropertyNames.PrincipalDistinguishedName, typeof(UserPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.PrincipalGuid, typeof(UserPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.PrincipalUserPrincipalName, typeof(UserPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ // Name and SamAccountNAme properties are currently routed to the same underlying Name property.
+ {PropertyNames.PrincipalName, typeof(Principal), "Name", new FromWinNTConverterDelegate(SamAccountNameFromWinNTConverter), null},
+
+
+
+ //
+ {PropertyNames.AuthenticablePrincipalEnabled , typeof(UserPrincipal), "UserFlags", new FromWinNTConverterDelegate(UserFlagsFromWinNTConverter), new ToWinNTConverterDelegate(UserFlagsToWinNTConverter)},
+ {PropertyNames.AuthenticablePrincipalCertificates, typeof(UserPrincipal), "*******", new FromWinNTConverterDelegate(CertFromWinNTConverter), new ToWinNTConverterDelegate(CertToWinNT)},
+
+ //
+ {PropertyNames.GroupIsSecurityGroup, typeof(GroupPrincipal), "*******", new FromWinNTConverterDelegate(GroupTypeFromWinNTConverter), new ToWinNTConverterDelegate(GroupTypeToWinNTConverter)},
+ {PropertyNames.GroupGroupScope, typeof(GroupPrincipal), "groupType", new FromWinNTConverterDelegate(GroupTypeFromWinNTConverter), new ToWinNTConverterDelegate(GroupTypeToWinNTConverter)},
+
+ //
+ {PropertyNames.UserEmailAddress, typeof(UserPrincipal), "*******" , new FromWinNTConverterDelegate(EmailFromWinNTConverter), new ToWinNTConverterDelegate(EmailToWinNTConverter)},
+
+ //
+ {PropertyNames.AcctInfoLastLogon, typeof(UserPrincipal), "LastLogin", new FromWinNTConverterDelegate(DateFromWinNTConverter), null},
+ {PropertyNames.AcctInfoPermittedWorkstations, typeof(UserPrincipal), "LoginWorkstations", new FromWinNTConverterDelegate(MultiStringFromWinNTConverter), new ToWinNTConverterDelegate(MultiStringToWinNTConverter)},
+ {PropertyNames.AcctInfoPermittedLogonTimes, typeof(UserPrincipal), "LoginHours", new FromWinNTConverterDelegate(BinaryFromWinNTConverter), new ToWinNTConverterDelegate(LogonHoursToWinNTConverter)},
+ {PropertyNames.AcctInfoExpirationDate, typeof(UserPrincipal), "AccountExpirationDate", new FromWinNTConverterDelegate(DateFromWinNTConverter), new ToWinNTConverterDelegate(AcctExpirDateToNTConverter)},
+ {PropertyNames.AcctInfoSmartcardRequired, typeof(UserPrincipal), "UserFlags", new FromWinNTConverterDelegate(UserFlagsFromWinNTConverter), new ToWinNTConverterDelegate(UserFlagsToWinNTConverter)},
+ {PropertyNames.AcctInfoDelegationPermitted, typeof(UserPrincipal), "UserFlags", new FromWinNTConverterDelegate(UserFlagsFromWinNTConverter), new ToWinNTConverterDelegate(UserFlagsToWinNTConverter)},
+ {PropertyNames.AcctInfoBadLogonCount, typeof(UserPrincipal), "BadPasswordAttempts", new FromWinNTConverterDelegate(IntFromWinNTConverter), null},
+ {PropertyNames.AcctInfoHomeDirectory, typeof(UserPrincipal), "HomeDirectory", new FromWinNTConverterDelegate(StringFromWinNTConverter), new ToWinNTConverterDelegate(StringToWinNTConverter)},
+ {PropertyNames.AcctInfoHomeDrive, typeof(UserPrincipal), "HomeDirDrive", new FromWinNTConverterDelegate(StringFromWinNTConverter), new ToWinNTConverterDelegate(StringToWinNTConverter)},
+ {PropertyNames.AcctInfoScriptPath, typeof(UserPrincipal), "LoginScript", new FromWinNTConverterDelegate(StringFromWinNTConverter), new ToWinNTConverterDelegate(StringToWinNTConverter)},
+
+ //
+ {PropertyNames.PwdInfoLastPasswordSet, typeof(UserPrincipal), "PasswordAge", new FromWinNTConverterDelegate(ElapsedTimeFromWinNTConverter), null},
+ {PropertyNames.PwdInfoLastBadPasswordAttempt, typeof(UserPrincipal), "*******", new FromWinNTConverterDelegate(LastBadPwdAttemptFromWinNTConverter), null},
+ {PropertyNames.PwdInfoPasswordNotRequired, typeof(UserPrincipal), "UserFlags", new FromWinNTConverterDelegate(UserFlagsFromWinNTConverter), new ToWinNTConverterDelegate(UserFlagsToWinNTConverter)},
+ {PropertyNames.PwdInfoPasswordNeverExpires, typeof(UserPrincipal), "UserFlags", new FromWinNTConverterDelegate(UserFlagsFromWinNTConverter), new ToWinNTConverterDelegate(UserFlagsToWinNTConverter)},
+ {PropertyNames.PwdInfoCannotChangePassword, typeof(UserPrincipal), "UserFlags", new FromWinNTConverterDelegate(UserFlagsFromWinNTConverter), new ToWinNTConverterDelegate(UserFlagsToWinNTConverter)},
+ {PropertyNames.PwdInfoAllowReversiblePasswordEncryption, typeof(UserPrincipal), "UserFlags", new FromWinNTConverterDelegate(UserFlagsFromWinNTConverter), new ToWinNTConverterDelegate(UserFlagsToWinNTConverter)},
+
+ //
+ // Writable properties we don't support writing in SAM
+ //
+ {PropertyNames.UserGivenName, typeof(UserPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.UserMiddleName, typeof(UserPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.UserSurname, typeof(UserPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.UserVoiceTelephoneNumber, typeof(UserPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.UserEmployeeID, typeof(UserPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+
+ {PropertyNames.PrincipalDisplayName, typeof(GroupPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.PrincipalDisplayName, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+
+ {PropertyNames.PrincipalDescription, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+
+ {PropertyNames.AuthenticablePrincipalEnabled, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+
+ {PropertyNames.AuthenticablePrincipalCertificates, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+
+ {PropertyNames.ComputerServicePrincipalNames, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+
+ {PropertyNames.AcctInfoPermittedWorkstations, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.AcctInfoPermittedLogonTimes, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.AcctInfoExpirationDate, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.AcctInfoSmartcardRequired, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.AcctInfoDelegationPermitted, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.AcctInfoHomeDirectory, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.AcctInfoHomeDrive, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.AcctInfoScriptPath, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+
+ {PropertyNames.PwdInfoPasswordNotRequired, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.PwdInfoPasswordNeverExpires, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.PwdInfoCannotChangePassword, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)},
+ {PropertyNames.PwdInfoAllowReversiblePasswordEncryption, typeof(ComputerPrincipal), null, null, new ToWinNTConverterDelegate(ExceptionToWinNTConverter)}
+ };
+
+ private static Hashtable s_userPropertyMappingTableByProperty = null;
+ private static Hashtable s_userPropertyMappingTableByWinNT = null;
+
+ private static Hashtable s_groupPropertyMappingTableByProperty = null;
+ private static Hashtable s_groupPropertyMappingTableByWinNT = null;
+
+ private static Hashtable s_computerPropertyMappingTableByProperty = null;
+ private static Hashtable s_computerPropertyMappingTableByWinNT = null;
+
+ private static Dictionary<string, ObjectMask> s_validPropertyMap = null;
+ private static Dictionary<Type, ObjectMask> s_maskMap = null;
+
+ [Flags]
+ private enum ObjectMask
+ {
+ None = 0,
+ User = 0x1,
+ Computer = 0x2,
+ Group = 0x4,
+ Principal = User | Computer | Group
+ }
+
+ private class PropertyMappingTableEntry
+ {
+ internal string propertyName; // PAPI name
+ internal string suggestedWinNTPropertyName; // WinNT attribute name
+ internal FromWinNTConverterDelegate winNTToPapiConverter;
+ internal ToWinNTConverterDelegate papiToWinNTConverter;
+ }
+
+ //
+ // Conversion routines
+ //
+
+ // Loads the specified attribute of the DirectoryEntry into the specified property of the Principal
+ private delegate void FromWinNTConverterDelegate(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName);
+
+ // Loads the specified property of the Principal into the specified attribute of the DirectoryEntry.
+ // For multivalued attributes, must test to make sure the value hasn't already been loaded into the DirectoryEntry
+ // (to maintain idempotency when PushChangesToNative is called multiple times).
+ private delegate void ToWinNTConverterDelegate(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM);
+
+ //
+ // WinNT --> PAPI
+ //
+ private static void StringFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ PropertyValueCollection values = de.Properties[suggestedWinNTProperty];
+
+ // The WinNT provider represents some string attributes that haven't been set as an empty string.
+ // Map them to null (not set), to maintain consistency with the LDAP context.
+ if ((values.Count > 0) && (((string)values[0]).Length == 0))
+ return;
+
+ SDSUtils.SingleScalarFromDirectoryEntry<string>(new dSPropertyCollection(de.Properties), suggestedWinNTProperty, p, propertyName);
+ }
+
+ private static void SidFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ byte[] sid = (byte[])de.Properties["objectSid"][0];
+
+ string stringizedSid = Utils.ByteArrayToString(sid);
+ string sddlSid = Utils.ConvertSidToSDDL(sid);
+ SecurityIdentifier SidObj = new SecurityIdentifier(sddlSid);
+ p.LoadValueIntoProperty(propertyName, (object)SidObj);
+ }
+
+ private static void SamAccountNameFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ Debug.Assert(de.Properties["Name"].Count == 1);
+
+ string samAccountName = (string)de.Properties["Name"][0];
+ // string urnValue = p.Context.ConnectedServer + @"\" + samAccountName;
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "SamAccountNameFromWinNTConverter: loading SAM{0}", samAccountName);
+ p.LoadValueIntoProperty(propertyName, (object)samAccountName);
+ }
+
+ private static void MultiStringFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ // ValueCollection<string> is Load'ed from a List<string>
+ SDSUtils.MultiScalarFromDirectoryEntry<string>(new dSPropertyCollection(de.Properties), suggestedWinNTProperty, p, propertyName);
+ }
+
+ private static void IntFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ SDSUtils.SingleScalarFromDirectoryEntry<int>(new dSPropertyCollection(de.Properties), suggestedWinNTProperty, p, propertyName);
+ }
+
+ private static void BinaryFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ SDSUtils.SingleScalarFromDirectoryEntry<byte[]>(new dSPropertyCollection(de.Properties), suggestedWinNTProperty, p, propertyName);
+ }
+
+ private static void CertFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ }
+
+ private static void GroupTypeFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ // Groups are always enabled in SAM. There is no such thing as a distribution group.
+ p.LoadValueIntoProperty(PropertyNames.GroupIsSecurityGroup, (object)true);
+
+ if (propertyName == PropertyNames.GroupIsSecurityGroup)
+ {
+ // Do nothing for this property.
+ }
+ else
+ {
+ Debug.Assert(propertyName == PropertyNames.GroupGroupScope);
+
+ // All local machine SAM groups are local
+#if DEBUG
+ PropertyValueCollection values = de.Properties[suggestedWinNTProperty];
+ if (values.Count != 0)
+ Debug.Assert(((int)values[0]) == 4);
+#endif
+
+ p.LoadValueIntoProperty(propertyName, GroupScope.Local);
+ }
+ }
+
+ private static void EmailFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ }
+
+ private static void LastBadPwdAttemptFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ }
+
+ private static void ElapsedTimeFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ // These properties are expressed as "seconds passed since the event of interest". So to convert
+ // to a DateTime, we substract them from DateTime.UtcNow.
+
+ PropertyValueCollection values = de.Properties[suggestedWinNTProperty];
+
+ if (values.Count != 0)
+ {
+ // We're intended to handle single-valued scalar properties
+ Debug.Assert(values.Count == 1);
+ Debug.Assert(values[0] is Int32);
+
+ int secondsLapsed = (int)values[0];
+
+ Nullable<DateTime> dt = DateTime.UtcNow - new TimeSpan(0, 0, secondsLapsed);
+
+ p.LoadValueIntoProperty(propertyName, dt);
+ }
+ }
+
+ private static void DateFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ PropertyValueCollection values = de.Properties[suggestedWinNTProperty];
+
+ if (values.Count != 0)
+ {
+ Debug.Assert(values.Count == 1);
+
+ // Unlike with the ADSI LDAP provider, these come back as a DateTime (expressed in UTC), instead
+ // of a IADsLargeInteger.
+ Nullable<DateTime> dt = (Nullable<DateTime>)values[0];
+
+ p.LoadValueIntoProperty(propertyName, dt);
+ }
+ }
+
+ private static void UserFlagsFromWinNTConverter(DirectoryEntry de, string suggestedWinNTProperty, Principal p, string propertyName)
+ {
+ Debug.Assert(String.Compare(suggestedWinNTProperty, "UserFlags", StringComparison.OrdinalIgnoreCase) == 0);
+
+ SDSUtils.AccountControlFromDirectoryEntry(new dSPropertyCollection(de.Properties), suggestedWinNTProperty, p, propertyName, true);
+ }
+
+ //
+ // PAPI --> WinNT
+ //
+
+ private static void ExceptionToWinNTConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM)
+ {
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.PrincipalUnsupportPropertyForType,
+ p.GetType().ToString(),
+ PropertyNamesExternal.GetExternalForm(propertyName)));
+ }
+
+ private static void StringToWinNTConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM)
+ {
+ string value = (string)p.GetValueForProperty(propertyName);
+
+ if (p.unpersisted && value == null)
+ return;
+
+ if (value != null && value.Length > 0)
+ de.Properties[suggestedWinNTProperty].Value = value;
+ else
+ de.Properties[suggestedWinNTProperty].Value = "";
+ }
+
+ private static void MultiStringToWinNTConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM)
+ {
+ SDSUtils.MultiStringToDirectoryEntryConverter(p, propertyName, de, suggestedWinNTProperty);
+ }
+
+ private static void LogonHoursToWinNTConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM)
+ {
+ Debug.Assert(propertyName == PropertyNames.AcctInfoPermittedLogonTimes);
+
+ byte[] value = (byte[])p.GetValueForProperty(propertyName);
+
+ if (p.unpersisted && value == null)
+ return;
+
+ if (value != null && value.Length != 0)
+ {
+ de.Properties[suggestedWinNTProperty].Value = value;
+ }
+ else
+ {
+ byte[] allHours = new byte[]{0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff};
+
+ de.Properties[suggestedWinNTProperty].Value = allHours;
+ }
+ }
+
+ private static void CertToWinNT(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM)
+ {
+ if (!isLSAM)
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.PrincipalUnsupportPropertyForPlatform,
+ PropertyNamesExternal.GetExternalForm(propertyName)));
+ }
+
+ private static void GroupTypeToWinNTConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM)
+ {
+ if (propertyName == PropertyNames.GroupIsSecurityGroup)
+ {
+ if (!isLSAM)
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.PrincipalUnsupportPropertyForPlatform,
+ PropertyNamesExternal.GetExternalForm(propertyName)));
+ }
+ else
+ {
+ Debug.Assert(propertyName == PropertyNames.GroupGroupScope);
+
+ // local machine SAM only supports local groups
+ GroupScope value = (GroupScope)p.GetValueForProperty(propertyName);
+
+ if (value != GroupScope.Local)
+ throw new InvalidOperationException(StringResources.SAMStoreCtxLocalGroupsOnly);
+ }
+ }
+
+ private static void EmailToWinNTConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM)
+ {
+ if (!isLSAM)
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.PrincipalUnsupportPropertyForPlatform,
+ PropertyNamesExternal.GetExternalForm(propertyName)));
+ }
+
+ private static void AcctExpirDateToNTConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM)
+ {
+ Nullable<DateTime> value = (Nullable<DateTime>)p.GetValueForProperty(propertyName);
+
+ if (p.unpersisted && value == null)
+ return;
+
+ // ADSI's WinNT provider uses 1/1/1970 to represent "never expires" when setting the property
+ if (value.HasValue)
+ de.Properties[suggestedWinNTProperty].Value = (DateTime)value;
+ else
+ de.Properties[suggestedWinNTProperty].Value = new DateTime(1970, 1, 1);
+ }
+
+ private static void UserFlagsToWinNTConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedWinNTProperty, bool isLSAM)
+ {
+ Debug.Assert(String.Compare(suggestedWinNTProperty, "UserFlags", StringComparison.OrdinalIgnoreCase) == 0);
+
+ SDSUtils.AccountControlToDirectoryEntry(p, propertyName, de, suggestedWinNTProperty, true, p.unpersisted);
+ }
+
+ private static void UpdateGroupMembership(Principal group, DirectoryEntry de, NetCred credentials, AuthenticationTypes authTypes)
+ {
+ Debug.Assert(group.fakePrincipal == false);
+
+ PrincipalCollection members = (PrincipalCollection)group.GetValueForProperty(PropertyNames.GroupMembers);
+
+ UnsafeNativeMethods.IADsGroup iADsGroup = (UnsafeNativeMethods.IADsGroup)de.NativeObject;
+
+ try
+ {
+ //
+ // Process clear
+ //
+ if (members.Cleared)
+ {
+ // Unfortunately, there's no quick way to clear a group's membership in SAM.
+ // So we remove each member in turn, by enumerating over the group membership
+ // and calling remove on each.
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "UpdateGroupMembership: clearing {0}", de.Path);
+
+ // Prepare the COM Interopt enumeration
+ UnsafeNativeMethods.IADsMembers iADsMembers = iADsGroup.Members();
+ IEnumVARIANT enumerator = (IEnumVARIANT)iADsMembers._NewEnum;
+
+ object[] nativeMembers = new object[1];
+ int hr;
+
+ do
+ {
+ hr = enumerator.Next(1, nativeMembers, IntPtr.Zero);
+
+ if (hr == 0) // S_OK
+ {
+ // Found a member, remove it.
+ UnsafeNativeMethods.IADs iADs = (UnsafeNativeMethods.IADs)nativeMembers[0];
+ iADsGroup.Remove(iADs.ADsPath);
+ }
+ }
+ while (hr == 0);
+
+ // Either hr == S_FALSE (1), which means we completed the enumerator,
+ // or we encountered an error
+ if (hr != 1)
+ {
+ // Error occurred.
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "UpdateGroupMembership: error while clearing, hr={0}", hr);
+
+ throw new PrincipalOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.SAMStoreCtxFailedToClearGroup,
+ hr.ToString(CultureInfo.InvariantCulture)));
+ }
+ }
+
+ //
+ // Process inserted members
+ //
+ List<Principal> insertedMembers = members.Inserted;
+
+ // First, validate the members to be added
+ foreach (Principal member in insertedMembers)
+ {
+ Type memberType = member.GetType();
+
+ if ((memberType != typeof(UserPrincipal)) && (!memberType.IsSubclassOf(typeof(UserPrincipal))) &&
+ (memberType != typeof(ComputerPrincipal)) && (!memberType.IsSubclassOf(typeof(ComputerPrincipal))) &&
+ (memberType != typeof(GroupPrincipal)) && (!memberType.IsSubclassOf(typeof(GroupPrincipal))))
+ {
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForGroupInsert, memberType.ToString()));
+ }
+
+ // Can't inserted unpersisted principal
+ if (member.unpersisted)
+ throw new InvalidOperationException(StringResources.StoreCtxGroupHasUnpersistedInsertedPrincipal);
+
+ Debug.Assert(member.Context != null);
+
+ // There's no restriction on the type of principal to be inserted (AD/reg-SAM/MSAM), but it needs
+ // to have a SID IdentityClaim. We'll check that as we go.
+ }
+
+ // Now add each member to the group
+ foreach (Principal member in insertedMembers)
+ {
+ // We'll add the member via its SID. This works for both MSAM members and AD members.
+
+ // Build a SID ADsPath
+ string memberSidPath = GetSidADsPathFromPrincipal(member);
+
+ if (memberSidPath == null)
+ throw new InvalidOperationException(StringResources.SAMStoreCtxCouldntGetSIDForGroupMember);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "UpdateGroupMembership: inserting {0}", memberSidPath);
+
+ // Add the member to the group
+ iADsGroup.Add(memberSidPath);
+ }
+
+ //
+ // Process removed members
+ //
+ List<Principal> removedMembers = members.Removed;
+
+ foreach (Principal member in removedMembers)
+ {
+ // Since we don't allow any of these to be inserted, none of them should ever
+ // show up in the removal list
+ Debug.Assert(member.unpersisted == false);
+
+ // If the collection was cleared, there should be no original members to remove
+ Debug.Assert(members.Cleared == false);
+
+ // Like insertion, we'll remove by SID.
+
+ // Build a SID ADsPath
+ string memberSidPath = GetSidADsPathFromPrincipal(member);
+
+ if (memberSidPath == null)
+ throw new InvalidOperationException(StringResources.SAMStoreCtxCouldntGetSIDForGroupMember);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "UpdateGroupMembership: removing {0}", memberSidPath);
+
+ // Remove the member from the group
+ iADsGroup.Remove(memberSidPath);
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "SAMStoreCtx",
+ "UpdateGroupMembership: caught COMException, message={0}, code={1}",
+ e.Message,
+ e.ErrorCode);
+
+ // ADSI threw an exception trying to update the group membership
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+ }
+
+ private static string GetSidADsPathFromPrincipal(Principal p)
+ {
+ Debug.Assert(p.unpersisted == false);
+
+ // Get the member's SID from its Security IdentityClaim
+
+ SecurityIdentifier Sid = p.Sid;
+
+ if (Sid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "GetSidADsPathFromPrincipal: no SID");
+ return null;
+ }
+
+ string sddlSid = Sid.ToString();
+
+ if (sddlSid == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn,
+ "SAMStoreCtx",
+ "GetSidADsPathFromPrincipal: Couldn't convert to SDDL ({0})",
+ Sid.ToString());
+ return null;
+ }
+
+ // Build a SID ADsPath
+ return @"WinNT://" + sddlSid;
+ }
+ }
+}
+
+// #endif // PAPI_REGSAM
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx_Query.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx_Query.cs
new file mode 100644
index 0000000000..7f319d2f3a
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreCtx_Query.cs
@@ -0,0 +1,157 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+using System.DirectoryServices;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ internal partial class SAMStoreCtx : StoreCtx
+ {
+ //
+ // Query operations
+ //
+
+ // Returns true if this store has native support for search (and thus a wormhole).
+ // Returns true for everything but SAM (both reg-SAM and MSAM).
+ internal override bool SupportsSearchNatively { get { return false; } }
+
+ // Returns a type indicating the type of object that would be returned as the wormhole for the specified
+ // PrincipalSearcher.
+ internal override Type SearcherNativeType()
+ {
+ Debug.Fail("SAMStoreCtx: SearcherNativeType: There is no native searcher type.");
+ throw new InvalidOperationException(StringResources.PrincipalSearcherNoUnderlying);
+ }
+
+ // Pushes the query represented by the QBE filter into the PrincipalSearcher's underlying native
+ // searcher object (creating a fresh native searcher and assigning it to the PrincipalSearcher if one
+ // doesn't already exist) and returns the native searcher.
+ // If the PrincipalSearcher does not have a query filter set (PrincipalSearcher.QueryFilter == null),
+ // produces a query that will match all principals in the store.
+ //
+ // For stores which don't have a native searcher (SAM), the StoreCtx
+ // is free to create any type of object it chooses to use as its internal representation of the query.
+ //
+ // Also adds in any clauses to the searcher to ensure that only principals, not mere
+ // contacts, are retrieved from the store.
+ internal override object PushFilterToNativeSearcher(PrincipalSearcher ps)
+ {
+ // There's no underlying searcher for SAM
+ Debug.Assert(ps.UnderlyingSearcher == null);
+
+ Principal qbeFilter = ps.QueryFilter;
+ QbeFilterDescription filters;
+
+ // If they specified a filter object, extract the set properties from it.
+ // Otherwise, use an empty set. Note that we don't worry about filtering by
+ // the type of the qbeFilter object (e.g., restricting the returned principals
+ // to only Users, or only Groups) --- that's handled in Query().
+ if (qbeFilter != null)
+ filters = BuildQbeFilterDescription(qbeFilter);
+ else
+ filters = new QbeFilterDescription();
+
+ return filters;
+ }
+
+ // The core query operation.
+ // Given a PrincipalSearcher containg a query filter, transforms it into the store schema
+ // and performs the query to get a collection of matching native objects (up to a maximum of sizeLimit,
+ // or uses the sizelimit already set on the DirectorySearcher if sizeLimit == -1).
+ // If the PrincipalSearcher does not have a query filter (PrincipalSearcher.QueryFilter == null),
+ // matches all principals in the store.
+ //
+ // The collection may not be complete, i.e., paging - the returned ResultSet will automatically
+ // page in additional results as needed.
+ internal override ResultSet Query(PrincipalSearcher ps, int sizeLimit)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Query");
+
+ Debug.Assert(sizeLimit >= -1);
+
+ // Build the description of the properties we'll filter by. In SAMStoreCtx, the "native" searcher
+ // is simply the QbeFilterDescription, which will be passed to the SAMQuerySet to use to
+ // manually filter out non-matching results.
+ QbeFilterDescription propertiesToMatch = (QbeFilterDescription)PushFilterToNativeSearcher(ps);
+
+ // Get the entries we'll iterate over. Write access to Children is controlled through the
+ // ctxBaseLock, but we don't want to have to hold that lock while we're iterating over all
+ // the child entries. So we have to clone the ctxBase --- not ideal, but it prevents
+ // multithreading issues.
+ DirectoryEntries entries = SDSUtils.BuildDirectoryEntry(_ctxBase.Path, _credentials, _authTypes).Children;
+ Debug.Assert(entries != null);
+
+ // Determine the principal types of interest. The SAMQuerySet will use this to restrict
+ // the types of DirectoryEntry objects returned.
+ Type qbeFilterType = typeof(Principal);
+ if (ps.QueryFilter != null)
+ qbeFilterType = ps.QueryFilter.GetType();
+
+ List<string> schemaTypes = GetSchemaFilter(qbeFilterType);
+
+ // Create the ResultSet that will perform the client-side filtering
+ SAMQuerySet resultSet = new SAMQuerySet(
+ schemaTypes,
+ entries,
+ _ctxBase,
+ sizeLimit,
+ this,
+ new QbeMatcher(propertiesToMatch));
+
+ return resultSet;
+ }
+
+ private List<string> GetSchemaFilter(Type principalType)
+ {
+ List<string> schemaTypes = new List<string>();
+
+ if (principalType == typeof(UserPrincipal) || principalType.IsSubclassOf(typeof(UserPrincipal)))
+ {
+ schemaTypes.Add("User");
+ }
+ else if (principalType == typeof(GroupPrincipal) || principalType.IsSubclassOf(typeof(GroupPrincipal)))
+ {
+ schemaTypes.Add("Group");
+ }
+ else if (principalType == typeof(ComputerPrincipal) || principalType.IsSubclassOf(typeof(ComputerPrincipal)))
+ {
+ schemaTypes.Add("Computer");
+ }
+ else if (principalType == typeof(Principal))
+ {
+ schemaTypes.Add("User");
+ schemaTypes.Add("Group");
+ schemaTypes.Add("Computer");
+ }
+ else if (principalType == typeof(AuthenticablePrincipal))
+ {
+ schemaTypes.Add("User");
+ schemaTypes.Add("Computer");
+ }
+ else
+ {
+ Debug.Fail("SAMStoreCtx.GetSchemaFilter: fell off end looking for " + principalType.ToString());
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForQuery, principalType.ToString()));
+ }
+
+ return schemaTypes;
+ }
+ }
+}
+
+//#endif // PAPI_REGSAM
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreKey.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreKey.cs
new file mode 100644
index 0000000000..801675262a
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMStoreKey.cs
@@ -0,0 +1,54 @@
+// 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.Diagnostics;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class SAMStoreKey : StoreKey
+ {
+ private byte[] _sid;
+ private string _machineName;
+
+ public SAMStoreKey(string machineName, byte[] sid)
+ {
+ Debug.Assert(machineName != null && machineName.Length > 0);
+ Debug.Assert(sid != null && sid.Length > 0);
+
+ _machineName = machineName;
+
+ // Make a copy of the SID, since a byte[] is mutable
+ _sid = new byte[sid.Length];
+ Array.Copy(sid, _sid, sid.Length);
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "SAMStoreKey",
+ "creating key for machineName={0}, sid={1}",
+ machineName,
+ Utils.ByteArrayToString(sid));
+ }
+
+ public override bool Equals(object o)
+ {
+ if (!(o is SAMStoreKey))
+ return false;
+
+ SAMStoreKey that = (SAMStoreKey)o;
+
+ if (String.Compare(_machineName, that._machineName, StringComparison.OrdinalIgnoreCase) != 0)
+ return false;
+
+ return Utils.AreBytesEqual(_sid, that._sid);
+ }
+
+ override public int GetHashCode()
+ {
+ return _machineName.GetHashCode() ^ _sid.GetHashCode();
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMUtils.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMUtils.cs
new file mode 100644
index 0000000000..680b1894bf
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMUtils.cs
@@ -0,0 +1,251 @@
+// 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.Diagnostics;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.DirectoryServices;
+using System.Text;
+using System.Security.Principal;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Declarative: [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
+ internal class SAMUtils
+ {
+ // To stop the compiler from autogenerating a constructor for this class
+ private SAMUtils() { }
+
+ static internal bool IsOfObjectClass(DirectoryEntry de, string classToCompare)
+ {
+ return (String.Compare(de.SchemaClassName, classToCompare, StringComparison.OrdinalIgnoreCase) == 0);
+ }
+
+ internal static bool GetOSVersion(DirectoryEntry computerDE, out int versionMajor, out int versionMinor)
+ {
+ Debug.Assert(SAMUtils.IsOfObjectClass(computerDE, "Computer"));
+
+ versionMajor = 0;
+ versionMinor = 0;
+
+ string version = null;
+
+ try
+ {
+ if (computerDE.Properties["OperatingSystemVersion"].Count > 0)
+ {
+ Debug.Assert(computerDE.Properties["OperatingSystemVersion"].Count == 1);
+
+ version = (string)computerDE.Properties["OperatingSystemVersion"].Value;
+ }
+ }
+ catch (COMException e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "SAMUtils", "GetOSVersion: caught COMException with message " + e.Message);
+
+ // Couldn't retrieve the value
+ if (e.ErrorCode == unchecked((int)0x80070035)) // ERROR_BAD_NETPATH
+ return false;
+
+ throw;
+ }
+
+ // Couldn't retrieve the value
+ if (version == null || version.Length == 0)
+ return false;
+
+ // This string should be in the form "M.N", where M and N are integers.
+ // We'll also accept "M", which we'll treat as "M.0".
+ //
+ // We'll split the string into its period-separated components, and parse
+ // each component into an int.
+ string[] versionComponents = version.Split(new char[] { '.' });
+
+ Debug.Assert(versionComponents.Length >= 1); // since version was a non-empty string
+
+ try
+ {
+ versionMajor = Int32.Parse(versionComponents[0], CultureInfo.InvariantCulture);
+
+ if (versionComponents.Length > 1)
+ versionMinor = Int32.Parse(versionComponents[1], CultureInfo.InvariantCulture);
+
+ // Sanity check: there are no negetive OS versions, nor is there a version "0".
+ if (versionMajor <= 0 || versionMinor < 0)
+ {
+ Debug.Fail(String.Format(
+ CultureInfo.CurrentCulture,
+ "SAMUtils.GetOSVersion: {0} claims to have negetive OS version, {1}",
+ computerDE.Path,
+ version));
+
+ return false;
+ }
+ }
+ catch (FormatException)
+ {
+ Debug.Fail(String.Format(
+ CultureInfo.CurrentCulture,
+ "SAMUtils.GetOSVersion: FormatException on {0} for {1}",
+ version,
+ computerDE.Path));
+
+ return false;
+ }
+ catch (OverflowException)
+ {
+ Debug.Fail(String.Format(
+ CultureInfo.CurrentCulture,
+ "SAMUtils.GetOSVersion: OverflowException on {0} for {1}",
+ version,
+ computerDE.Path));
+ return false;
+ }
+
+ return true;
+ }
+
+ static internal Principal DirectoryEntryAsPrincipal(DirectoryEntry de, StoreCtx storeCtx)
+ {
+ string className = de.SchemaClassName;
+
+ // Unlike AD, we don't have to worry about cross-store refs here. In AD, if there's
+ // a cross-store ref, we'll get back a DirectoryEntry of the FPO object. In the WinNT ADSI
+ // provider, we'll get back the DirectoryEntry of the remote object itself --- ADSI does
+ // the domain vs. local resolution for us.
+
+ if (SAMUtils.IsOfObjectClass(de, "Computer") ||
+ SAMUtils.IsOfObjectClass(de, "User") ||
+ SAMUtils.IsOfObjectClass(de, "Group"))
+ {
+ return storeCtx.GetAsPrincipal(de, null);
+ }
+ else
+ {
+ Debug.Fail(String.Format(
+ CultureInfo.CurrentCulture,
+ "SAMUtils.DirectoryEntryAsPrincipal: fell off end, Path={0}, SchemaClassName={1}",
+ de.Path,
+ de.SchemaClassName));
+ return null;
+ }
+ }
+
+ // These are verbatim C# string ( @ ) where \ is actually \\
+ // Input Matches RegEx
+ // ----- ------- -----
+ // * any ( 1 or more ) .*
+ //
+ // \* * \*
+ // \ \ \\
+ // ( ( \(
+ // \( ( \(
+ // ) ) \)
+ // \) ) \)
+ // \\ \ \\
+ // x x x (where x is anything else)
+ // Add \G to beginning and \z to the end so that the regex will be anchored at the either end of the property
+ // \G = Regex must match at the beginning
+ // \z = Regex must match at the end
+ // ( ) * are special characters to Regex so they must be escaped with \\. We support these from teh user either raw or already escaped.
+ // Any other \ in the input string are translated to an actual \ in the match because we cannot determine usage except for ( ) *
+ // The user cannot enter any regex escape sequence they would like in their match string. Only * is supported.
+ //
+ // @"c:\Home" -> "c:\\\\Home" OR @"c:\\Home"
+ //
+ //
+
+ static internal string PAPIQueryToRegexString(string papiString)
+ {
+ StringBuilder sb = new StringBuilder(papiString.Length);
+
+ sb.Append(@"\G");
+
+ bool escapeMode = false;
+
+ foreach (char c in papiString)
+ {
+ if (escapeMode == false)
+ {
+ switch (c)
+ {
+ case '(':
+ sb.Append(@"\("); // ( --> \(
+ break;
+
+ case ')':
+ sb.Append(@"\)"); // ) --> \)
+ break;
+
+ case '\\':
+ escapeMode = true;
+ break;
+
+ case '*':
+ sb.Append(@".*"); // * --> .*
+ break;
+
+ default:
+ sb.Append(c.ToString()); // x --> x
+ break;
+ }
+ }
+ else
+ {
+ escapeMode = false;
+
+ switch (c)
+ {
+ case '(':
+ sb.Append(@"\("); // \( --> \(
+ break;
+
+ case ')':
+ sb.Append(@"\)"); // \) --> \)
+ break;
+
+ case '*':
+ sb.Append(@"\*"); // \* --> \*
+ break;
+
+ case '\\':
+ sb.Append(@"\\\\"); // \\ --> \\
+ break;
+
+ default:
+ sb.Append(@"\\");
+ sb.Append(c.ToString()); // \x --> \x
+ break;
+ }
+ }
+ }
+
+ // There was a '\\' but no character after it because we were at the
+ // end of the string.
+ // Append '\\\\' to match the '\\'.
+ if (escapeMode)
+ {
+ sb.Append(@"\\");
+ }
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "SAMUtils",
+ "PAPIQueryToRegexString: mapped '{0}' to '{1}'",
+ papiString,
+ sb.ToString());
+
+ sb.Append(@"\z");
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SidType.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SidType.cs
new file mode 100644
index 0000000000..573220789d
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SidType.cs
@@ -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.
+
+using System;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal enum SidType
+ {
+ RealObject = 0, // Account SID (S-1-5-21-....)
+ RealObjectFakeDomain = 1, // BUILTIN SID (S-1-5-32-....)
+ FakeObject = 2 // everything else: S-1-1-0 (\Everyone), S-1-2-0 (\LOCAL),
+ // S-1-5-X for X != 21 and X != 32 (NT AUTHORITY), etc.
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/StoreCtx.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/StoreCtx.cs
new file mode 100644
index 0000000000..1f33859472
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/StoreCtx.cs
@@ -0,0 +1,476 @@
+// 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.Collections.Generic;
+using System.Security.Cryptography.X509Certificates;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal enum PrincipalAccessMask
+ {
+ ChangePassword
+ }
+ internal abstract class StoreCtx : IDisposable
+ {
+ //
+ // StoreCtx information
+ //
+
+ // Retrieves the Path (ADsPath) of the object used as the base of the StoreCtx
+ internal abstract string BasePath { get; }
+
+ // The PrincipalContext object to which this StoreCtx belongs. Initialized by PrincipalContext after it creates
+ // this StoreCtx instance.
+ private PrincipalContext _owningContext = null;
+ internal PrincipalContext OwningContext
+ {
+ // <SecurityKernel Critical="True" Ring="1">
+ // <ReferencesCritical Name="Field: owningContext" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _owningContext;
+ }
+
+ // <SecurityKernel Critical="True" Ring="1">
+ // <ReferencesCritical Name="Field: owningContext" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ Debug.Assert(value != null);
+ _owningContext = value;
+ }
+ }
+
+ //
+ // CRUD
+ //
+
+ // Used to perform the specified operation on the Principal. They also make any needed security subsystem
+ // calls to obtain digitial signatures (e..g, to sign the Principal Extension/GroupMember Relationship for
+ // WinFS).
+ //
+ // Insert() and Update() must check to make sure no properties not supported by this StoreCtx
+ // have been set, prior to persisting the Principal.
+ internal abstract void Insert(Principal p);
+ internal abstract void Update(Principal p);
+ internal abstract void Delete(Principal p);
+ internal abstract void Move(StoreCtx originalStore, Principal p);
+
+ //
+ // Native <--> Principal
+ //
+
+ // For modified object, pushes any changes (including IdentityClaim changes)
+ // into the underlying store-specific object (e.g., DirectoryEntry) and returns the underlying object.
+ // For unpersisted object, creates a underlying object if one doesn't already exist (in
+ // Principal.UnderlyingObject), then pushes any changes into the underlying object.
+ internal abstract object PushChangesToNative(Principal p);
+
+ // Given a underlying store object (e.g., DirectoryEntry), further narrowed down a discriminant
+ // (if applicable for the StoreCtx type), returns a fresh instance of a Principal
+ // object based on it. The WinFX Principal API follows ADSI-style semantics, where you get multiple
+ // in-memory objects all referring to the same store pricipal, rather than WinFS semantics, where
+ // multiple searches all return references to the same in-memory object.
+ // Used to implement the reverse wormhole. Also, used internally by FindResultEnumerator
+ // to construct Principals from the store objects returned by a store query.
+ //
+ // The Principal object produced by this method does not have all the properties
+ // loaded. The Principal object will call the Load method on demand to load its properties
+ // from its Principal.UnderlyingObject.
+ //
+ //
+ // This method works for native objects from the store corresponding to _this_ StoreCtx.
+ // Each StoreCtx will also have its own internal algorithms used for dealing with cross-store objects, e.g.,
+ // for use when iterating over group membership. These routines are exposed as
+ // ResolveCrossStoreRefToPrincipal, and will be called by the StoreCtx's associated ResultSet
+ // classes when iterating over a representation of a "foreign" principal.
+ internal abstract Principal GetAsPrincipal(object storeObject, object discriminant);
+
+ // Loads the store values from p.UnderlyingObject into p, performing schema mapping as needed.
+ internal abstract void Load(Principal p);
+ // Loads only the psecified property into the principal object. The object should have already been persisted or searched for this to happen.
+ internal abstract void Load(Principal p, string principalPropertyName);
+
+ // Performs store-specific resolution of an IdentityReference to a Principal
+ // corresponding to the IdentityReference. Returns null if no matching object found.
+ // principalType can be used to scope the search to principals of a specified type, e.g., users or groups.
+ // Specify typeof(Principal) to search all principal types.
+ internal abstract Principal FindPrincipalByIdentRef(
+ Type principalType, string urnScheme, string urnValue, DateTime referenceDate);
+
+ // Returns a type indicating the type of object that would be returned as the wormhole for the specified
+ // Principal. For some StoreCtxs, this method may always return a constant (e.g., typeof(DirectoryEntry)
+ // for ADStoreCtx). For others, it may vary depending on the Principal passed in.
+ internal abstract Type NativeType(Principal p);
+
+ //
+ // Special operations: the Principal classes delegate their implementation of many of the
+ // special methods to their underlying StoreCtx
+ //
+
+ // methods for manipulating accounts
+ internal abstract void InitializeUserAccountControl(AuthenticablePrincipal p);
+ internal abstract bool IsLockedOut(AuthenticablePrincipal p);
+ internal abstract void UnlockAccount(AuthenticablePrincipal p);
+
+ // methods for manipulating passwords
+ internal abstract void SetPassword(AuthenticablePrincipal p, string newPassword);
+ internal abstract void ChangePassword(AuthenticablePrincipal p, string oldPassword, string newPassword);
+ internal abstract void ExpirePassword(AuthenticablePrincipal p);
+ internal abstract void UnexpirePassword(AuthenticablePrincipal p);
+
+ internal abstract bool AccessCheck(Principal p, PrincipalAccessMask targetPermission);
+
+ // the various FindBy* methods
+ internal abstract ResultSet FindByLockoutTime(
+ DateTime dt, MatchType matchType, Type principalType);
+ internal abstract ResultSet FindByLogonTime(
+ DateTime dt, MatchType matchType, Type principalType);
+ internal abstract ResultSet FindByPasswordSetTime(
+ DateTime dt, MatchType matchType, Type principalType);
+ internal abstract ResultSet FindByBadPasswordAttempt(
+ DateTime dt, MatchType matchType, Type principalType);
+ internal abstract ResultSet FindByExpirationTime(
+ DateTime dt, MatchType matchType, Type principalType);
+
+ // Get groups of which p is a direct member
+ internal abstract ResultSet GetGroupsMemberOf(Principal p);
+
+ // Get groups from this ctx which contain a principal corresponding to foreignPrincipal
+ // (which is a principal from foreignContext)
+ internal abstract ResultSet GetGroupsMemberOf(Principal foreignPrincipal, StoreCtx foreignContext);
+
+ // Get groups of which p is a member, using AuthZ S4U APIs for recursive membership
+ internal abstract ResultSet GetGroupsMemberOfAZ(Principal p);
+
+ // Get members of group g
+ internal abstract BookmarkableResultSet GetGroupMembership(GroupPrincipal g, bool recursive);
+
+ // Is p a member of g in the store?
+ internal abstract bool SupportsNativeMembershipTest { get; }
+ internal abstract bool IsMemberOfInStore(GroupPrincipal g, Principal p);
+
+ // Can a Clear() operation be performed on the specified group? If not, also returns
+ // a string containing a human-readable explanation of why not, suitable for use in an exception.
+ internal abstract bool CanGroupBeCleared(GroupPrincipal g, out string explanationForFailure);
+
+ // Can the given member be removed from the specified group? If not, also returns
+ // a string containing a human-readable explanation of why not, suitable for use in an exception.
+ internal abstract bool CanGroupMemberBeRemoved(GroupPrincipal g, Principal member, out string explanationForFailure);
+
+ //
+ // Query operations
+ //
+
+ // Returns true if this store has native support for search (and thus a wormhole).
+ // Returns true for everything but SAM (both reg-SAM and MSAM).
+ internal abstract bool SupportsSearchNatively { get; }
+
+ // Returns a type indicating the type of object that would be returned as the wormhole for the specified
+ // PrincipalSearcher.
+ internal abstract Type SearcherNativeType();
+
+ // Pushes the query represented by the QBE filter into the PrincipalSearcher's underlying native
+ // searcher object (creating a fresh native searcher and assigning it to the PrincipalSearcher if one
+ // doesn't already exist) and returns the native searcher.
+ // If the PrincipalSearcher does not have a query filter set (PrincipalSearcher.QueryFilter == null),
+ // produces a query that will match all principals in the store.
+ //
+ // For stores which don't have a native searcher (SAM), the StoreCtx
+ // is free to create any type of object it chooses to use as its internal representation of the query.
+ //
+ // Also adds in any clauses to the searcher to ensure that only principals, not mere
+ // contacts, are retrieved from the store.
+ internal abstract object PushFilterToNativeSearcher(PrincipalSearcher ps);
+
+ // The core query operation.
+ // Given a PrincipalSearcher containg a query filter, transforms it into the store schema
+ // and performs the query to get a collection of matching native objects (up to a maximum of sizeLimit,
+ // or uses the sizelimit already set on the DirectorySearcher if sizeLimit == -1).
+ // If the PrincipalSearcher does not have a query filter (PrincipalSearcher.QueryFilter == null),
+ // matches all principals in the store.
+ //
+ // The collection may not be complete, i.e., paging - the returned ResultSet will automatically
+ // page in additional results as needed.
+ internal abstract ResultSet Query(PrincipalSearcher ps, int sizeLimit);
+
+ //
+ // Cross-store support
+ //
+
+ // Given a native store object that represents a "foreign" principal (e.g., a FPO object in this store that
+ // represents a pointer to another store), maps that representation to the other store's StoreCtx and returns
+ // a Principal from that other StoreCtx. The implementation of this method is highly dependent on the
+ // details of the particular store, and must have knowledge not only of this StoreCtx, but also of how to
+ // interact with other StoreCtxs to fulfill the request.
+ //
+ // This method is typically used by ResultSet implementations, when they're iterating over a collection
+ // (e.g., of group membership) and encounter a entry that represents a foreign principal.
+ internal abstract Principal ResolveCrossStoreRefToPrincipal(object o);
+
+ //
+ // Data Validation
+ //
+
+ // Validiate the passed property name to determine if it is valid for the store and Principal type.
+ // used by the principal objects to determine if a property is valid in the property before
+ // save is called.
+ internal abstract bool IsValidProperty(Principal p, string propertyName);
+
+ // Returns true if AccountInfo is supported for the specified principal, false otherwise.
+ // Used when a application tries to access the AccountInfo property of a newly-inserted
+ // (not yet persisted) AuthenticablePrincipal, to determine whether it should be allowed.
+ internal abstract bool SupportsAccounts(AuthenticablePrincipal p);
+
+ // Returns the set of credential types supported by this store for the specified principal.
+ // Used when a application tries to access the PasswordInfo property of a newly-inserted
+ // (not yet persisted) AuthenticablePrincipal, to determine whether it should be allowed.
+ // Also used to implement AuthenticablePrincipal.SupportedCredentialTypes.
+ internal abstract CredentialTypes SupportedCredTypes(AuthenticablePrincipal p);
+
+ //
+ // Construct a fake Principal to represent a well-known SID like
+ // "\Everyone" or "NT AUTHORITY\NETWORK SERVICE"
+ //
+ internal abstract Principal ConstructFakePrincipalFromSID(byte[] sid);
+
+ //
+ // IDisposable implementation
+ //
+
+ // Disposes of this instance of a StoreCtx. Calling this method more than once is allowed, and all but
+ // the first call should be ignored.
+ public virtual void Dispose()
+ {
+ // Nothing to do in the base class
+ }
+
+ //
+ // QBE Filter parsing
+ //
+
+ // These property sets include only the properties used to build QBE filters,
+ // e.g., the Group.Members property is not included
+
+ internal static string[] principalProperties = new string[]
+ {
+ PropertyNames.PrincipalDisplayName,
+ PropertyNames.PrincipalDescription,
+ PropertyNames.PrincipalSamAccountName,
+ PropertyNames.PrincipalUserPrincipalName,
+ PropertyNames.PrincipalGuid,
+ PropertyNames.PrincipalSid,
+ PropertyNames.PrincipalStructuralObjectClass,
+ PropertyNames.PrincipalName,
+ PropertyNames.PrincipalDistinguishedName,
+ PropertyNames.PrincipalExtensionCache
+ };
+
+ internal static string[] authenticablePrincipalProperties = new string[]
+ {
+ PropertyNames.AuthenticablePrincipalEnabled,
+ PropertyNames.AuthenticablePrincipalCertificates,
+ PropertyNames.PwdInfoLastBadPasswordAttempt,
+ PropertyNames.AcctInfoExpirationDate,
+ PropertyNames.AcctInfoExpiredAccount,
+ PropertyNames.AcctInfoLastLogon,
+ PropertyNames.AcctInfoAcctLockoutTime,
+ PropertyNames.AcctInfoBadLogonCount,
+ PropertyNames.PwdInfoLastPasswordSet
+ };
+
+ // includes AccountInfo and PasswordInfo
+ internal static string[] userProperties = new string[]
+ {
+ PropertyNames.UserGivenName,
+ PropertyNames.UserMiddleName,
+ PropertyNames.UserSurname,
+ PropertyNames.UserEmailAddress,
+ PropertyNames.UserVoiceTelephoneNumber,
+ PropertyNames.UserEmployeeID,
+
+ PropertyNames.AcctInfoPermittedWorkstations,
+ PropertyNames.AcctInfoPermittedLogonTimes,
+ PropertyNames.AcctInfoSmartcardRequired,
+ PropertyNames.AcctInfoDelegationPermitted,
+ PropertyNames.AcctInfoHomeDirectory,
+ PropertyNames.AcctInfoHomeDrive,
+ PropertyNames.AcctInfoScriptPath,
+
+ PropertyNames.PwdInfoPasswordNotRequired,
+ PropertyNames.PwdInfoPasswordNeverExpires,
+ PropertyNames.PwdInfoCannotChangePassword,
+ PropertyNames.PwdInfoAllowReversiblePasswordEncryption
+ };
+
+ internal static string[] groupProperties = new string[]
+ {
+ PropertyNames.GroupIsSecurityGroup,
+ PropertyNames.GroupGroupScope
+ };
+
+ internal static string[] computerProperties = new string[]
+ {
+ PropertyNames.ComputerServicePrincipalNames
+ };
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetChangeStatusForProperty(System.String):System.Boolean" />
+ // <ReferencesCritical Name="Method: BuildFilterSet(Principal, String[], QbeFilterDescription):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ protected QbeFilterDescription BuildQbeFilterDescription(Principal p)
+ {
+ QbeFilterDescription qbeFilterDescription = new QbeFilterDescription();
+
+ // We don't have to check to make sure the application didn't try to set any
+ // disallowed properties (i..e, referential properties, such as Group.Members),
+ // because that check was enforced by the PrincipalSearcher in its
+ // FindAll() and GetUnderlyingSearcher() methods, by calling
+ // PrincipalSearcher.HasReferentialPropertiesSet().
+
+ if (p is Principal)
+ BuildFilterSet(p, principalProperties, qbeFilterDescription);
+
+ if (p is AuthenticablePrincipal)
+ BuildFilterSet(p, authenticablePrincipalProperties, qbeFilterDescription);
+
+ if (p is UserPrincipal) // includes AccountInfo and PasswordInfo
+ {
+ // AcctInfoExpirationDate and AcctInfoExpiredAccount represent filters on the same property
+ // check that only one is specified
+ if (p.GetChangeStatusForProperty(PropertyNames.AcctInfoExpirationDate) &&
+ p.GetChangeStatusForProperty(PropertyNames.AcctInfoExpiredAccount))
+ {
+ throw new InvalidOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.StoreCtxMultipleFiltersForPropertyUnsupported,
+ PropertyNamesExternal.GetExternalForm(ExpirationDateFilter.PropertyNameStatic)));
+ }
+
+ BuildFilterSet(p, userProperties, qbeFilterDescription);
+ }
+
+ if (p is GroupPrincipal)
+ BuildFilterSet(p, groupProperties, qbeFilterDescription);
+
+ if (p is ComputerPrincipal)
+ BuildFilterSet(p, computerProperties, qbeFilterDescription);
+
+ return qbeFilterDescription;
+ }
+
+ // Applies to supplied propertySet to the supplied Principal, and adds any resulting filters
+ // to qbeFilterDescription.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal.GetChangeStatusForProperty(System.String):System.Boolean" />
+ // <SatisfiesLinkDemand Name="Principal.GetValueForProperty(System.String):System.Object" />
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<System.String>.get_Inserted():System.Collections.Generic.List`1<System.String>" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ private void BuildFilterSet(Principal p, string[] propertySet, QbeFilterDescription qbeFilterDescription)
+ {
+ foreach (string propertyName in propertySet)
+ {
+ if (p.GetChangeStatusForProperty(propertyName))
+ {
+ // Property has changed. Add it to the filter set.
+ object value = p.GetValueForProperty(propertyName);
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "StoreCtx",
+ "BuildFilterSet: type={0}, property name={1}, property value={2} of type {3}",
+ p.GetType().ToString(),
+ propertyName,
+ value.ToString(),
+ value.GetType().ToString());
+
+ // Build the right filter based on type of the property value
+ if (value is PrincipalValueCollection<string>)
+ {
+ PrincipalValueCollection<string> trackingList = (PrincipalValueCollection<string>)value;
+ foreach (string s in trackingList.Inserted)
+ {
+ object filter = FilterFactory.CreateFilter(propertyName);
+ ((FilterBase)filter).Value = (string)s;
+ qbeFilterDescription.FiltersToApply.Add(filter);
+ }
+ }
+ else if (value is X509Certificate2Collection)
+ {
+ // Since QBE filter objects are always unpersisted, any certs in the collection
+ // must have been inserted by the application.
+ X509Certificate2Collection certCollection = (X509Certificate2Collection)value;
+ foreach (X509Certificate2 cert in certCollection)
+ {
+ object filter = FilterFactory.CreateFilter(propertyName);
+ ((FilterBase)filter).Value = (X509Certificate2)cert;
+ qbeFilterDescription.FiltersToApply.Add(filter);
+ }
+ }
+ else
+ {
+ // It's not one of the multivalued cases. Try the scalar cases.
+
+ object filter = FilterFactory.CreateFilter(propertyName);
+
+ if (value == null)
+ {
+ ((FilterBase)filter).Value = null;
+ }
+ else if (value is bool)
+ {
+ ((FilterBase)filter).Value = (bool)value;
+ }
+ else if (value is string)
+ {
+ ((FilterBase)filter).Value = (string)value;
+ }
+ else if (value is GroupScope)
+ {
+ ((FilterBase)filter).Value = (GroupScope)value;
+ }
+ else if (value is byte[])
+ {
+ ((FilterBase)filter).Value = (byte[])value;
+ }
+ else if (value is Nullable<DateTime>)
+ {
+ ((FilterBase)filter).Value = (Nullable<DateTime>)value;
+ }
+ else if (value is ExtensionCache)
+ {
+ ((FilterBase)filter).Value = (ExtensionCache)value;
+ }
+ else if (value is QbeMatchType)
+ {
+ ((FilterBase)filter).Value = (QbeMatchType)value;
+ }
+ else
+ {
+ // Internal error. Didn't match either the known multivalued or scalar cases.
+ Debug.Fail(String.Format(
+ CultureInfo.CurrentCulture,
+ "StoreCtx.BuildFilterSet: fell off end looking for {0} of type {1}",
+ propertyName,
+ value.GetType().ToString()
+ ));
+ }
+
+ qbeFilterDescription.FiltersToApply.Add(filter);
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/StoreKey.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/StoreKey.cs
new file mode 100644
index 0000000000..308b11424d
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/StoreKey.cs
@@ -0,0 +1,13 @@
+// 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;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal abstract class StoreKey
+ {
+ // Nothing here, this is just a base class for the store-specific StoreKeys
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/TrackedCollection.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/TrackedCollection.cs
new file mode 100644
index 0000000000..2c74dfeaa5
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/TrackedCollection.cs
@@ -0,0 +1,319 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class TrackedCollection<T> : ICollection<T>, ICollection, IEnumerable<T>, IEnumerable
+ {
+ //
+ // ICollection
+ //
+ void ICollection.CopyTo(Array array, int index)
+ {
+ // Parameter validation
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ if (array == null)
+ throw new ArgumentNullException("array");
+
+ if (array.Rank != 1)
+ throw new ArgumentException(StringResources.TrackedCollectionNotOneDimensional);
+
+ if (index >= array.GetLength(0))
+ throw new ArgumentException(StringResources.TrackedCollectionIndexNotInArray);
+
+ // Make sure the array has enough space, allowing for the "index" offset
+ if ((array.GetLength(0) - index) < this.combinedValues.Count)
+ throw new ArgumentException(StringResources.TrackedCollectionArrayTooSmall);
+
+ // Copy out the original and inserted values
+ foreach (ValueEl el in this.combinedValues)
+ {
+ array.SetValue(el.GetCurrentValue(), index);
+ checked { index++; }
+ }
+ }
+
+ int ICollection.Count
+ {
+ get
+ {
+ return Count;
+ }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ // The classes that wrap us should expose themselves as the sync root.
+ // Hence, this should never be called.
+ Debug.Fail("TrackedCollection.SyncRoot: shouldn't be here.");
+ return this;
+ }
+ }
+
+ //
+ // IEnumerable
+ //
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ Debug.Fail("TrackedCollection.IEnumerable.GetEnumerator(): should not be here");
+ return (IEnumerator)GetEnumerator();
+ }
+
+ //
+ // ICollection<T>
+ //
+
+ public void CopyTo(T[] array, int index)
+ {
+ ((ICollection)this).CopyTo((Array)array, index);
+ }
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ // Note that any values removed by the application have already been removed
+ // from combinedValues, so we don't need to adjust for that here
+ return this.combinedValues.Count;
+ }
+ }
+
+ //
+ // IEnumerable<T>
+ //
+ public IEnumerator<T> GetEnumerator()
+ {
+ Debug.Fail("TrackedCollection.GetEnumerator(): should not be here");
+ return new TrackedCollectionEnumerator<T>("TrackedCollectionEnumerator", this, this.combinedValues);
+ }
+
+ //
+ //
+ //
+ public bool Contains(T value)
+ {
+ // Is it one of the inserted or original values?
+ foreach (ValueEl el in this.combinedValues)
+ {
+ if (el.GetCurrentValue().Equals(value))
+ return true;
+ }
+
+ return false;
+ }
+
+ public void Clear()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollection", "Clear");
+
+ MarkChange();
+
+ // Move all original values to the removed values list
+ foreach (ValueEl el in this.combinedValues)
+ {
+ if (!el.isInserted)
+ {
+ this.removedValues.Add(el.originalValue.Left);
+ }
+ }
+
+ // Remove all inserted values, and clean up the original values
+ // (which have been moved onto the removed value list)
+ this.combinedValues.Clear();
+ }
+
+ // Adds obj to the end of the list by inserting it into combinedValues.
+ public void Add(T o)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollection", "Add({0})", o.ToString());
+
+ MarkChange();
+
+ ValueEl el = new ValueEl();
+ el.isInserted = true;
+ el.insertedValue = o;
+
+ this.combinedValues.Add(el);
+ }
+
+ // If obj is an inserted value, removes it.
+ // Otherwise, if obj is in the right-side of a pair of an original value, removes that pair from combinedValues
+ // and adds the left-side of that pair to removedValues, to record the removal.
+ public bool Remove(T value)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollection", "Remove({0})", value.ToString());
+
+ MarkChange();
+
+ foreach (ValueEl el in this.combinedValues)
+ {
+ if (el.isInserted && el.insertedValue.Equals(value))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollection", "found value to remove on inserted");
+
+ this.combinedValues.Remove(el);
+ return true;
+ }
+
+ if (!el.isInserted && el.originalValue.Right.Equals(value))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollection", "found value to remove on original");
+
+ this.combinedValues.Remove(el);
+ this.removedValues.Add(el.originalValue.Left);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ //
+ // Private implementation
+ //
+
+ internal class ValueEl
+ {
+ public bool isInserted;
+
+ //public T insertedValue = T.default;
+ public T insertedValue;
+
+ public Pair<T, T> originalValue = null;
+
+ public T GetCurrentValue()
+ {
+ if (this.isInserted)
+ return this.insertedValue;
+ else
+ return this.originalValue.Right; // Right == current value
+ }
+ }
+
+ // Contains both the values retrieved from the store object backing this property.
+ // If isInserted == true, it is an inserted value and is stored in insertedValue.
+ // If isInserted == false, it is an original value and is stored in originalValue.
+ // For each originalValue Pair, the left side contains a copy of the value as it was originally retrieved from the store,
+ // while the right side contains the current value (which differs from the left side iff the application
+ // modified the value).
+ internal List<ValueEl> combinedValues = new List<ValueEl>();
+
+ // Contains values removed by the application for which the removal has not yet been committed
+ // to the store.
+ internal List<T> removedValues = new List<T>();
+
+ // Used so our enumerator can detect changes to the collection and throw an exception
+ private DateTime _lastChange = DateTime.UtcNow;
+
+ internal DateTime LastChange
+ {
+ get { return _lastChange; }
+ }
+
+ internal void MarkChange()
+ {
+ _lastChange = DateTime.UtcNow;
+ }
+
+ //
+ // Shared Load/Store implementation
+ //
+
+ internal List<T> Inserted
+ {
+ get
+ {
+ List<T> insertedValues = new List<T>();
+
+ foreach (ValueEl el in this.combinedValues)
+ {
+ if (el.isInserted)
+ insertedValues.Add(el.insertedValue);
+ }
+
+ return insertedValues;
+ }
+ }
+
+ internal List<T> Removed
+ {
+ get
+ {
+ return this.removedValues;
+ }
+ }
+
+ internal List<Pair<T, T>> ChangedValues
+ {
+ get
+ {
+ List<Pair<T, T>> changedList = new List<Pair<T, T>>();
+
+ foreach (ValueEl el in this.combinedValues)
+ {
+ if (!el.isInserted)
+ {
+ if (!el.originalValue.Left.Equals(el.originalValue.Right))
+ {
+ // Don't need to worry about whether we need to copy the T,
+ // since we're not handing it out to the app and we'll internally treat it as read-only
+ changedList.Add(new Pair<T, T>(el.originalValue.Left, el.originalValue.Right));
+ }
+ }
+ }
+
+ return changedList;
+ }
+ }
+
+ internal bool Changed
+ {
+ get
+ {
+ // Do the cheap test first: have any values been removed?
+ if (this.removedValues.Count > 0)
+ return true;
+
+ // have to do the comparatively expensive test: have any values been inserted or changed?
+ foreach (ValueEl el in this.combinedValues)
+ {
+ // Inserted
+ if (el.isInserted)
+ return true;
+
+ // Changed
+ if (!el.originalValue.Left.Equals(el.originalValue.Right))
+ return true;
+ }
+
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/TrackedCollectionEnumerator.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/TrackedCollectionEnumerator.cs
new file mode 100644
index 0000000000..53808cb173
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/TrackedCollectionEnumerator.cs
@@ -0,0 +1,192 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class TrackedCollectionEnumerator<T> : IEnumerator, IEnumerator<T>
+ {
+ //
+ // Public properties
+ //
+
+ public T Current
+ {
+ get
+ {
+ CheckDisposed();
+
+ // Since MoveNext() saved off the current value for us, this is largely trivial.
+
+ if (_endReached == true || _enumerator == null)
+ {
+ // Either we're at the end or before the beginning
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "TrackedCollectionEnumerator", "Current: bad position, endReached={0}", _endReached);
+ throw new InvalidOperationException(StringResources.TrackedCollectionEnumInvalidPos);
+ }
+
+ return _current;
+ }
+ }
+
+ object IEnumerator.Current
+ {
+ get
+ {
+ return Current;
+ }
+ }
+
+ //
+ // Public methods
+ //
+
+ public bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollectionEnumerator", "Entering MoveNext");
+
+ CheckDisposed();
+ CheckChanged();
+
+ if (_endReached)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollectionEnumerator", "MoveNext: endReached");
+ return false;
+ }
+
+ if (_enumerator == null)
+ {
+ // Must be at the very beginning
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollectionEnumerator", "MoveNext: at beginning");
+
+ _enumerator = ((IEnumerable)_combinedValues).GetEnumerator();
+ Debug.Assert(_enumerator != null);
+ }
+
+ bool gotNextValue = _enumerator.MoveNext();
+
+ // If we got the next value,
+ // save it off so that Current can later return it.
+ if (gotNextValue)
+ {
+ // Have to handle differently, since inserted values are just a T, while
+ // original value are a Pair<T,T>, where Pair.Right is the current value
+ TrackedCollection<T>.ValueEl el = (TrackedCollection<T>.ValueEl)_enumerator.Current;
+
+ if (el.isInserted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollectionEnumerator", "MoveNext: current ({0}) is inserted", _current);
+ _current = el.insertedValue;
+ }
+ else
+ {
+ _current = el.originalValue.Right;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollectionEnumerator", "MoveNext: current ({0}) is original", _current);
+ }
+ }
+ else
+ {
+ // Nothing more to enumerate
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollectionEnumerator", "MoveNext: nothing more to enumerate");
+
+ _endReached = true;
+ }
+
+ return gotNextValue;
+ }
+
+ bool IEnumerator.MoveNext()
+ {
+ return MoveNext();
+ }
+
+ public void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollectionEnumerator", "Reset");
+
+ CheckDisposed();
+ CheckChanged();
+
+ _endReached = false;
+ _enumerator = null;
+ }
+
+ void IEnumerator.Reset()
+ {
+ Reset();
+ }
+
+ public void Dispose()
+ {
+ _disposed = true;
+ }
+
+ //
+ // Internal constructors
+ //
+ internal TrackedCollectionEnumerator(string outerClassName, TrackedCollection<T> trackedCollection, List<TrackedCollection<T>.ValueEl> combinedValues)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "TrackedCollectionEnumerator", "Ctor");
+
+ _outerClassName = outerClassName;
+ _trackedCollection = trackedCollection;
+ _combinedValues = combinedValues;
+ }
+
+ //
+ // Private implementation
+ //
+
+ // Have we been disposed?
+ private bool _disposed = false;
+
+ // The name of our outer class. Used when throwing an ObjectDisposedException.
+ private string _outerClassName;
+
+ private List<TrackedCollection<T>.ValueEl> _combinedValues = null;
+
+ // The value we're currently positioned at
+ private T _current;
+
+ // The enumerator for our inner list, combinedValues.
+ private IEnumerator _enumerator = null;
+
+ // True when we reach the end of combinedValues (no more values to enumerate in the TrackedCollection)
+ private bool _endReached = false;
+
+ // When this enumerator was constructed, to detect changes made to the TrackedCollection after it was constructed
+ private DateTime _creationTime = DateTime.UtcNow;
+ private TrackedCollection<T> _trackedCollection = null;
+
+ private void CheckDisposed()
+ {
+ if (_disposed)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "TrackedCollectionEnumerator", "CheckDisposed: accessing disposed object");
+ throw new ObjectDisposedException(_outerClassName);
+ }
+ }
+
+ private void CheckChanged()
+ {
+ // Make sure the app hasn't changed our underlying list
+ if (_trackedCollection.LastChange > _creationTime)
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Warn,
+ "TrackedCollectionEnumerator",
+ "CheckChanged: has changed (last change={0}, creation={1})",
+ _trackedCollection.LastChange,
+ _creationTime);
+
+ throw new InvalidOperationException(StringResources.TrackedCollectionEnumHasChanged);
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/UnknownPrincipal.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/UnknownPrincipal.cs
new file mode 100644
index 0000000000..b2c31c3db1
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/UnknownPrincipal.cs
@@ -0,0 +1,61 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+using System.Security.Permissions;
+using System.Security.Principal;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Principal" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ [DirectoryRdnPrefix("CN")]
+ internal class UnknownPrincipal : Principal
+ {
+ //
+ // Public constructors
+ //
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ private UnknownPrincipal(PrincipalContext context)
+ {
+ if (context == null)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ this.ContextRaw = context;
+ this.unpersisted = true;
+ }
+
+ //
+ // Internal "constructor": Used for constructing UnknownPrincipal
+ //
+ static internal UnknownPrincipal CreateUnknownPrincipal(PrincipalContext ctx, byte[] sid, string name)
+ {
+ UnknownPrincipal up = new UnknownPrincipal(ctx);
+ up.unpersisted = false;
+ up.fakePrincipal = true;
+
+ // Set the display name on the object
+ up.LoadValueIntoProperty(PropertyNames.PrincipalDisplayName, name);
+
+ // Set the display name on the object
+ up.LoadValueIntoProperty(PropertyNames.PrincipalName, name);
+
+ // SID IdentityClaim
+ SecurityIdentifier sidObj = new SecurityIdentifier(Utils.ConvertSidToSDDL(sid));
+
+ // Set the display name on the object
+ up.LoadValueIntoProperty(PropertyNames.PrincipalSid, sidObj);
+ return up;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/UrnScheme.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/UrnScheme.cs
new file mode 100644
index 0000000000..183412930c
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/UrnScheme.cs
@@ -0,0 +1,19 @@
+// 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.Collections.Generic;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ static internal class UrnScheme
+ {
+ public const string GuidScheme = IdentityTypeStringMap.Guid;
+ public const string SidScheme = IdentityTypeStringMap.Sid;
+ public const string DistinguishedNameScheme = IdentityTypeStringMap.DistinguishedName;
+ public const string SamAccountScheme = IdentityTypeStringMap.SamAccount;
+ public const string UpnScheme = IdentityTypeStringMap.Upn;
+ public const string NameScheme = IdentityTypeStringMap.Name;
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/User.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/User.cs
new file mode 100644
index 0000000000..9f5da3a85f
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/User.cs
@@ -0,0 +1,474 @@
+// 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.Diagnostics;
+using System.Collections.Generic;
+using System.Security.Permissions;
+using System.Security.Principal;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="AuthenticablePrincipal" />
+ // </SecurityKernel>
+#pragma warning disable 618 // Have not migrated to v4 transparency yet
+ [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ [DirectoryRdnPrefix("CN")]
+ public class UserPrincipal : AuthenticablePrincipal
+ {
+ //
+ // Public constructors
+ //
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ public UserPrincipal(PrincipalContext context) : base(context)
+ {
+ if (context == null)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ this.ContextRaw = context;
+ this.unpersisted = true;
+ }
+
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Unrestricted = true)]
+ public UserPrincipal(PrincipalContext context, string samAccountName, string password, bool enabled) : this(context)
+ {
+ if (samAccountName == null || password == null)
+ throw new ArgumentException(StringResources.NullArguments);
+
+ if (Context.ContextType != ContextType.ApplicationDirectory)
+ this.SamAccountName = samAccountName;
+
+ this.Name = samAccountName;
+ this.SetPassword(password);
+ this.Enabled = enabled;
+ }
+
+ //
+ // Public properties
+ //
+
+ // GivenName
+ private string _givenName = null; // the actual property value
+ private LoadState _givenNameChanged = LoadState.NotSet; // change-tracking
+
+ public string GivenName
+ {
+ get
+ {
+ return HandleGet<string>(ref _givenName, PropertyNames.UserGivenName, ref _givenNameChanged);
+ }
+
+ set
+ {
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.UserGivenName))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _givenName, value, ref _givenNameChanged,
+ PropertyNames.UserGivenName);
+ }
+ }
+
+ // MiddleName
+ private string _middleName = null; // the actual property value
+ private LoadState _middleNameChanged = LoadState.NotSet; // change-tracking
+
+ public string MiddleName
+ {
+ get
+ {
+ return HandleGet<string>(ref _middleName, PropertyNames.UserMiddleName, ref _middleNameChanged);
+ }
+
+ set
+ {
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.UserMiddleName))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _middleName, value, ref _middleNameChanged,
+ PropertyNames.UserMiddleName);
+ }
+ }
+
+ // Surname
+ private string _surname = null; // the actual property value
+ private LoadState _surnameChanged = LoadState.NotSet; // change-tracking
+
+ public string Surname
+ {
+ get
+ {
+ return HandleGet<string>(ref _surname, PropertyNames.UserSurname, ref _surnameChanged);
+ }
+
+ set
+ {
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.UserSurname))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _surname, value, ref _surnameChanged,
+ PropertyNames.UserSurname);
+ }
+ }
+
+ // EmailAddress
+ private string _emailAddress = null; // the actual property value
+ private LoadState _emailAddressChanged = LoadState.NotSet; // change-tracking
+
+ public string EmailAddress
+ {
+ get
+ {
+ return HandleGet<string>(ref _emailAddress, PropertyNames.UserEmailAddress, ref _emailAddressChanged);
+ }
+
+ set
+ {
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.UserEmailAddress))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _emailAddress, value, ref _emailAddressChanged,
+ PropertyNames.UserEmailAddress);
+ }
+ }
+
+ // VoiceTelephoneNumber
+ private string _voiceTelephoneNumber = null; // the actual property value
+ private LoadState _voiceTelephoneNumberChanged = LoadState.NotSet; // change-tracking
+
+ public string VoiceTelephoneNumber
+ {
+ get
+ {
+ return HandleGet<string>(ref _voiceTelephoneNumber, PropertyNames.UserVoiceTelephoneNumber, ref _voiceTelephoneNumberChanged);
+ }
+
+ set
+ {
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.UserVoiceTelephoneNumber))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _voiceTelephoneNumber, value, ref _voiceTelephoneNumberChanged,
+ PropertyNames.UserVoiceTelephoneNumber);
+ }
+ }
+
+ // EmployeeId
+ private string _employeeID = null; // the actual property value
+ private LoadState _employeeIDChanged = LoadState.NotSet; // change-tracking
+
+ public string EmployeeId
+ {
+ get
+ {
+ return HandleGet<string>(ref _employeeID, PropertyNames.UserEmployeeID, ref _employeeIDChanged);
+ }
+
+ set
+ {
+ if (!GetStoreCtxToUse().IsValidProperty(this, PropertyNames.UserEmployeeID))
+ throw new InvalidOperationException(StringResources.InvalidPropertyForStore);
+
+ HandleSet<string>(ref _employeeID, value, ref _employeeIDChanged,
+ PropertyNames.UserEmployeeID);
+ }
+ }
+
+ public override AdvancedFilters AdvancedSearchFilter { get { return rosf; } }
+
+ public static UserPrincipal Current
+ {
+ [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ get
+ {
+ // We have to do this inline because declarative CAS is not allowed on properties.
+ DirectoryServicesPermission dSPerm = new DirectoryServicesPermission();
+ dSPerm.Demand();
+
+ PrincipalContext context;
+
+ // Get the correct PrincipalContext to query against, depending on whether we're running
+ // as a local or domain user
+ if (Utils.IsSamUser())
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "User", "Current: is local user");
+
+#if PAPI_REGSAM
+ context = new PrincipalContext(ContextType.Machine);
+#else
+ // This implementation doesn't support Reg-SAM/MSAM (machine principals)
+ throw new NotSupportedException(StringResources.UserLocalNotSupportedOnPlatform);
+#endif // PAPI_REGSAM
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "User", "Current: is not local user");
+
+#if PAPI_AD
+ context = new PrincipalContext(ContextType.Domain);
+#else
+ // This implementation doesn't support AD (domain principals)
+ throw new NotSupportedException(StringResources.UserDomainNotSupportedOnPlatform);
+#endif // PAPI_AD
+ }
+
+ // Construct a query for the current user, using a SID IdentityClaim
+
+ IntPtr pSid = IntPtr.Zero;
+ UserPrincipal user = null;
+
+ try
+ {
+ pSid = Utils.GetCurrentUserSid();
+ byte[] sid = Utils.ConvertNativeSidToByteArray(pSid);
+ SecurityIdentifier sidObj = new SecurityIdentifier(sid, 0);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "User", "Current: using SID " + sidObj.ToString());
+
+ user = UserPrincipal.FindByIdentity(context, IdentityType.Sid, sidObj.ToString());
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ System.Runtime.InteropServices.Marshal.FreeHGlobal(pSid);
+ }
+
+ // We're running as the user, we know they must exist, but perhaps we don't have access
+ // to their user object
+ if (user == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "User", "Current: found no user");
+ throw new NoMatchingPrincipalException(StringResources.UserCouldNotFindCurrent);
+ }
+
+ return user;
+ }
+ }
+
+ //
+ // Public methods
+ //
+
+ public static new PrincipalSearchResult<UserPrincipal> FindByLockoutTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByLockoutTime<UserPrincipal>(context, time, type);
+ }
+
+ public static new PrincipalSearchResult<UserPrincipal> FindByLogonTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByLogonTime<UserPrincipal>(context, time, type);
+ }
+
+ public static new PrincipalSearchResult<UserPrincipal> FindByExpirationTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByExpirationTime<UserPrincipal>(context, time, type);
+ }
+
+ public static new PrincipalSearchResult<UserPrincipal> FindByBadPasswordAttempt(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByBadPasswordAttempt<UserPrincipal>(context, time, type);
+ }
+
+ public static new PrincipalSearchResult<UserPrincipal> FindByPasswordSetTime(PrincipalContext context, DateTime time, MatchType type)
+ {
+ return FindByPasswordSetTime<UserPrincipal>(context, time, type);
+ }
+
+ public static new UserPrincipal FindByIdentity(PrincipalContext context, string identityValue)
+ {
+ return (UserPrincipal)FindByIdentityWithType(context, typeof(UserPrincipal), identityValue);
+ }
+
+ public static new UserPrincipal FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
+ {
+ return (UserPrincipal)FindByIdentityWithType(context, typeof(UserPrincipal), identityType, identityValue);
+ }
+
+ public PrincipalSearchResult<Principal> GetAuthorizationGroups()
+ {
+ return new PrincipalSearchResult<Principal>(GetAuthorizationGroupsHelper());
+ }
+
+ //
+ // Internal "constructor": Used for constructing Users returned by a query
+ //
+ static internal UserPrincipal MakeUser(PrincipalContext ctx)
+ {
+ UserPrincipal u = new UserPrincipal(ctx);
+ u.unpersisted = false;
+
+ return u;
+ }
+
+ //
+ // Private implementation
+ //
+
+ private ResultSet GetAuthorizationGroupsHelper()
+ {
+ // Make sure we're not disposed or deleted.
+ CheckDisposedOrDeleted();
+
+ // Unpersisted principals are not members of any group
+ if (this.unpersisted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "User", "GetAuthorizationGroupsHelper: unpersisted, using EmptySet");
+ return new EmptySet();
+ }
+
+ StoreCtx storeCtx = GetStoreCtxToUse();
+ Debug.Assert(storeCtx != null);
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "User",
+ "GetAuthorizationGroupsHelper: retrieving AZ groups from StoreCtx of type=" + storeCtx.GetType().ToString() +
+ ", base path=" + storeCtx.BasePath);
+
+ ResultSet resultSet = storeCtx.GetGroupsMemberOfAZ(this);
+
+ return resultSet;
+ }
+
+ //
+ // Load/Store implementation
+ //
+
+ //
+ // Loading with query results
+ //
+ internal override void LoadValueIntoProperty(string propertyName, object value)
+ {
+ if (value == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "User", "LoadValueIntoProperty: name=" + propertyName + " value= null");
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "User", "LoadValueIntoProperty: name=" + propertyName + " value=" + value.ToString());
+ }
+
+ switch (propertyName)
+ {
+ case (PropertyNames.UserGivenName):
+ _givenName = (string)value;
+ _givenNameChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.UserMiddleName):
+ _middleName = (string)value;
+ _middleNameChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.UserSurname):
+ _surname = (string)value;
+ _surnameChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.UserEmailAddress):
+ _emailAddress = (string)value;
+ _emailAddressChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.UserVoiceTelephoneNumber):
+ _voiceTelephoneNumber = (string)value;
+ _voiceTelephoneNumberChanged = LoadState.Loaded;
+ break;
+
+ case (PropertyNames.UserEmployeeID):
+ _employeeID = (string)value;
+ _employeeIDChanged = LoadState.Loaded;
+ break;
+
+ default:
+ base.LoadValueIntoProperty(propertyName, value);
+ break;
+ }
+ }
+
+ //
+ // Getting changes to persist (or to build a query from a QBE filter)
+ //
+
+ // Given a property name, returns true if that property has changed since it was loaded, false otherwise.
+ internal override bool GetChangeStatusForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "User", "GetChangeStatusForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case (PropertyNames.UserGivenName):
+ return _givenNameChanged == LoadState.Changed;
+
+ case (PropertyNames.UserMiddleName):
+ return _middleNameChanged == LoadState.Changed;
+
+ case (PropertyNames.UserSurname):
+ return _surnameChanged == LoadState.Changed;
+
+ case (PropertyNames.UserEmailAddress):
+ return _emailAddressChanged == LoadState.Changed;
+
+ case (PropertyNames.UserVoiceTelephoneNumber):
+ return _voiceTelephoneNumberChanged == LoadState.Changed;
+
+ case (PropertyNames.UserEmployeeID):
+ return _employeeIDChanged == LoadState.Changed;
+
+ default:
+ return base.GetChangeStatusForProperty(propertyName);
+ }
+ }
+
+ // Given a property name, returns the current value for the property.
+ internal override object GetValueForProperty(string propertyName)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "User", "GetValueForProperty: name=" + propertyName);
+
+ switch (propertyName)
+ {
+ case (PropertyNames.UserGivenName):
+ return _givenName;
+
+ case (PropertyNames.UserMiddleName):
+ return _middleName;
+
+ case (PropertyNames.UserSurname):
+ return _surname;
+
+ case (PropertyNames.UserEmailAddress):
+ return _emailAddress;
+
+ case (PropertyNames.UserVoiceTelephoneNumber):
+ return _voiceTelephoneNumber;
+
+ case (PropertyNames.UserEmployeeID):
+ return _employeeID;
+
+ default:
+ return base.GetValueForProperty(propertyName);
+ }
+ }
+
+ // Reset all change-tracking status for all properties on the object to "unchanged".
+ internal override void ResetAllChangeStatus()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "User", "ResetAllChangeStatus");
+
+ _givenNameChanged = (_givenNameChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet; ;
+ _middleNameChanged = (_middleNameChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet; ;
+ _surnameChanged = (_surnameChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet; ;
+ _emailAddressChanged = (_emailAddressChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet; ;
+ _voiceTelephoneNumberChanged = (_voiceTelephoneNumberChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet; ;
+ _employeeIDChanged = (_employeeIDChanged == LoadState.Changed) ? LoadState.Loaded : LoadState.NotSet; ;
+
+ base.ResetAllChangeStatus();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Utils.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Utils.cs
new file mode 100644
index 0000000000..464a8911f1
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Utils.cs
@@ -0,0 +1,1000 @@
+// 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.Diagnostics;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Collections.Generic;
+using System.Net;
+using System.Security.Principal;
+using System.Security;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ internal class Utils
+ {
+ // To stop the compiler from autogenerating a constructor for this class
+ private Utils() { }
+
+ //
+ // byte utilities
+ //
+
+ /// <summary>
+ /// Performs bytewise comparison of two byte[] arrays
+ /// </summary>
+ /// <param name="src">Array to compare</param>
+ /// <param name="tgt">Array to compare against src</param>
+ /// <returns>true if identical, false otherwise</returns>
+ internal static bool AreBytesEqual(byte[] src, byte[] tgt)
+ {
+ if (src.Length != tgt.Length)
+ return false;
+
+ for (int i = 0; i < src.Length; i++)
+ {
+ if (src[i] != tgt[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ internal static void ClearBit(ref int value, uint bitmask)
+ {
+ value = (int)(((uint)value) & ((uint)(~bitmask)));
+ }
+
+ internal static void SetBit(ref int value, uint bitmask)
+ {
+ value = (int)(((uint)value) | ((uint)bitmask));
+ }
+
+ // {0xa2, 0x3f,...} --> "a23f..."
+ internal static string ByteArrayToString(byte[] byteArray)
+ {
+ StringBuilder stringizedArray = new StringBuilder();
+ foreach (byte b in byteArray)
+ {
+ stringizedArray.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+ }
+
+ return stringizedArray.ToString();
+ }
+
+ // Use this for ldap search filter string...
+ internal static string SecurityIdentifierToLdapHexFilterString(SecurityIdentifier sid)
+ {
+ return (ADUtils.HexStringToLdapHexString(SecurityIdentifierToLdapHexBindingString(sid)));
+ }
+
+ // use this for binding string...
+ internal static string SecurityIdentifierToLdapHexBindingString(SecurityIdentifier sid)
+ {
+ byte[] sidB = new byte[sid.BinaryLength];
+ sid.GetBinaryForm(sidB, 0);
+ StringBuilder stringizedBinarySid = new StringBuilder();
+ foreach (byte b in sidB)
+ {
+ stringizedBinarySid.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+ }
+ return stringizedBinarySid.ToString();
+ }
+
+ internal static byte[] StringToByteArray(string s)
+ {
+ if (s.Length % 2 != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "Utils", "StringToByteArray: string has bad length " + s.Length);
+ return null;
+ }
+
+ byte[] bytes = new byte[s.Length / 2];
+
+ for (int i = 0; i < (s.Length) / 2; i++)
+ {
+ char firstChar = s[i * 2];
+ char secondChar = s[(i * 2) + 1];
+
+ if (((firstChar >= '0' && firstChar <= '9') || (firstChar >= 'A' && firstChar <= 'F') || (firstChar >= 'a' && firstChar <= 'f')) &&
+ ((secondChar >= '0' && secondChar <= '9') || (secondChar >= 'A' && secondChar <= 'F') || (secondChar >= 'a' && secondChar <= 'f')))
+ {
+ byte b = Byte.Parse(s.Substring(i * 2, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
+ bytes[i] = b;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "Utils", "StringToByteArray: invalid string: " + s);
+ return null;
+ }
+ }
+
+ return bytes;
+ }
+
+ //
+ // SID Utilities
+ //
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ConvertSidToStringSid(System.IntPtr,System.String&amp;):System.Boolean" />
+ //<SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ //<ReferencesCritical Name="Method: ConvertByteArrayToIntPtr(Byte[]):IntPtr" Ring="1" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ internal static string ConvertSidToSDDL(byte[] sid)
+ {
+ string sddlSid = null;
+
+ // To put the byte[] SID into SDDL, we use ConvertSidToStringSid.
+ // Calling that requires we first copy the SID into native memory.
+ IntPtr pSid = IntPtr.Zero;
+
+ try
+ {
+ pSid = ConvertByteArrayToIntPtr(sid);
+
+ if (UnsafeNativeMethods.ConvertSidToStringSid(pSid, ref sddlSid))
+ {
+ return sddlSid;
+ }
+ else
+ {
+ int lastErrorCode = Marshal.GetLastWin32Error();
+
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Warn,
+ "Utils",
+ "ConvertSidToSDDL: ConvertSidToStringSid failed, " + lastErrorCode);
+ return null;
+ }
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pSid);
+ }
+ }
+
+ // The caller must call Marshal.FreeHGlobal on the returned
+ // value to free it.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Marshal.AllocHGlobal(System.Int32):System.IntPtr" />
+ // <SatisfiesLinkDemand Name="Marshal.Copy(System.Byte[],System.Int32,System.IntPtr,System.Int32):System.Void" />
+ // <SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static IntPtr ConvertByteArrayToIntPtr(byte[] bytes)
+ {
+ IntPtr pBytes = IntPtr.Zero;
+
+ pBytes = Marshal.AllocHGlobal(bytes.Length);
+
+ try
+ {
+ Marshal.Copy(bytes, 0, pBytes, bytes.Length);
+ }
+ catch (Exception e)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "ConvertByteArrayToIntPtr: caught exception of type "
+ + e.GetType().ToString() +
+ " and message " + e.Message);
+
+ Marshal.FreeHGlobal(pBytes);
+ throw;
+ }
+
+ Debug.Assert(pBytes != IntPtr.Zero);
+ return pBytes;
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetLengthSid(System.IntPtr):System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.Copy(System.IntPtr,System.Byte[],System.Int32,System.Int32):System.Void" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ internal static byte[] ConvertNativeSidToByteArray(IntPtr pSid)
+ {
+ int sidLength = UnsafeNativeMethods.GetLengthSid(pSid);
+ byte[] sid = new byte[sidLength];
+ Marshal.Copy(pSid, sid, 0, sidLength);
+
+ return sid;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ // <ReferencesCritical Name="Method: ConvertByteArrayToIntPtr(Byte[]):IntPtr" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static SidType ClassifySID(byte[] sid)
+ {
+ IntPtr pSid = IntPtr.Zero;
+
+ try
+ {
+ pSid = ConvertByteArrayToIntPtr(sid);
+
+ return ClassifySID(pSid);
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pSid);
+ }
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.IsValidSid(System.IntPtr):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetSidIdentifierAuthority(System.IntPtr):System.IntPtr" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetSidSubAuthority(System.IntPtr,System.Int32):System.IntPtr" />
+ //<SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ //<SatisfiesLinkDemand Name="Marshal.ReadInt32(System.IntPtr):System.Int32" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ internal static SidType ClassifySID(IntPtr pSid)
+ {
+ Debug.Assert(UnsafeNativeMethods.IsValidSid(pSid));
+
+ // Get the issuing authority and the first RID
+ IntPtr pIdentAuth = UnsafeNativeMethods.GetSidIdentifierAuthority(pSid);
+
+ UnsafeNativeMethods.SID_IDENTIFIER_AUTHORITY identAuth =
+ (UnsafeNativeMethods.SID_IDENTIFIER_AUTHORITY)Marshal.PtrToStructure(pIdentAuth, typeof(UnsafeNativeMethods.SID_IDENTIFIER_AUTHORITY));
+
+ IntPtr pRid = UnsafeNativeMethods.GetSidSubAuthority(pSid, 0);
+ int rid = Marshal.ReadInt32(pRid);
+
+ // These bit signify that the sid was issued by ADAM. If so then it can't be a fake sid.
+ if ((identAuth.b3 & 0xF0) == 0x10)
+ return SidType.RealObject;
+
+ // Is it S-1-5-...?
+ if (!(identAuth.b1 == 0) &&
+ (identAuth.b2 == 0) &&
+ (identAuth.b3 == 0) &&
+ (identAuth.b4 == 0) &&
+ (identAuth.b5 == 0) &&
+ (identAuth.b6 == 5))
+ {
+ // No, so it can't be a account or builtin SID.
+ // Probably something like \Everyone or \LOCAL.
+ return SidType.FakeObject;
+ }
+
+ switch (rid)
+ {
+ case 21:
+ // Account SID
+ return SidType.RealObject;
+
+ case 32:
+ // BUILTIN SID
+ return SidType.RealObjectFakeDomain;
+
+ default:
+ return SidType.FakeObject;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+
+ internal static int GetLastRidFromSid(IntPtr pSid)
+ {
+ IntPtr pRidCount = UnsafeNativeMethods.GetSidSubAuthorityCount(pSid);
+ int ridCount = Marshal.ReadByte(pRidCount);
+ IntPtr pLastRid = UnsafeNativeMethods.GetSidSubAuthority(pSid, ridCount - 1);
+ int lastRid = Marshal.ReadInt32(pLastRid);
+
+ return lastRid;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ // <ReferencesCritical Name="Method: ConvertByteArrayToIntPtr(Byte[]):IntPtr" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static int GetLastRidFromSid(byte[] sid)
+ {
+ IntPtr pSid = IntPtr.Zero;
+
+ try
+ {
+ pSid = Utils.ConvertByteArrayToIntPtr(sid);
+ int rid = GetLastRidFromSid(pSid);
+
+ return rid;
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pSid);
+ }
+ }
+
+ //
+ //
+ //
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.EqualDomainSid(System.IntPtr,System.IntPtr,System.Boolean&):System.Boolean" />
+ // <SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static bool IsSamUser()
+ {
+ //
+ // Basic algorithm
+ //
+ // Get SID of current user (via OpenThreadToken/GetTokenInformation/CloseHandle for TokenUser)
+ //
+ // Is the user SID of the form S-1-5-21-... (does GetSidIdentityAuthority(u) == 5 and GetSidSubauthority(u, 0) == 21)?
+ // If NO ---> is local user
+ // If YES --->
+ // Get machine domain SID (via LsaOpenPolicy/LsaQueryInformationPolicy for PolicyAccountDomainInformation/LsaClose)
+ // Does EqualDomainSid indicate the current user SID and the machine domain SID have the same domain?
+ // If YES -->
+ // IS the local machine a DC
+ // If NO --> is local user
+ // If YES --> is _not_ local user
+ // If NO --> is _not_ local user
+ //
+
+ IntPtr pCopyOfUserSid = IntPtr.Zero;
+ IntPtr pMachineDomainSid = IntPtr.Zero;
+
+ try
+ {
+ // Get the user's SID
+ pCopyOfUserSid = GetCurrentUserSid();
+
+ // Is it of S-1-5-21 form: Is the issuing authority NT_AUTHORITY and the RID NT_NOT_UNIQUE?
+ SidType sidType = ClassifySID(pCopyOfUserSid);
+
+ if (sidType == SidType.RealObject)
+ {
+ // It's a domain SID. Now, is the domain portion for the local machine, or something else?
+
+ // Get the machine domain SID
+ pMachineDomainSid = GetMachineDomainSid();
+
+ // Does the user SID have the same domain as the machine SID?
+ bool sameDomain = false;
+ bool success = UnsafeNativeMethods.EqualDomainSid(pCopyOfUserSid, pMachineDomainSid, ref sameDomain);
+
+ // Since both pCopyOfUserSid and pMachineDomainSid should always be account SIDs
+ Debug.Assert(success == true);
+
+ // If user SID is the same domain as the machine domain, and the machine is not a DC then the user is a local (machine) user
+ return sameDomain ? !IsMachineDC(null) : false;
+ }
+ else
+ {
+ // It's not a domain SID, must be local (e.g., NT AUTHORITY\foo, or BUILTIN\foo)
+ return true;
+ }
+ }
+ finally
+ {
+ if (pCopyOfUserSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pCopyOfUserSid);
+
+ if (pMachineDomainSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pMachineDomainSid);
+ }
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetCurrentThread():System.IntPtr" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.OpenThreadToken(System.IntPtr,System.Int32,System.Boolean,System.IntPtr&amp;):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetCurrentProcess():System.IntPtr" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.OpenProcessToken(System.IntPtr,System.Int32,System.IntPtr&amp;):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetTokenInformation(System.IntPtr,System.Int32,System.IntPtr,System.Int32,System.Int32&amp;):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.IsValidSid(System.IntPtr):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetLengthSid(System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.CopySid(System.Int32,System.IntPtr,System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.CloseHandle(System.IntPtr):System.Boolean" />
+ //<SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.AllocHGlobal(System.Int32):System.IntPtr" />
+ //<SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ //<SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ internal static IntPtr GetCurrentUserSid()
+ {
+ IntPtr pTokenHandle = IntPtr.Zero;
+ IntPtr pBuffer = IntPtr.Zero;
+
+ try
+ {
+ //
+ // Get the current user's SID
+ //
+ int error = 0;
+
+ // Get the current thread's token
+ if (!UnsafeNativeMethods.OpenThreadToken(
+ UnsafeNativeMethods.GetCurrentThread(),
+ 0x8, // TOKEN_QUERY
+ true,
+ ref pTokenHandle
+ ))
+ {
+ if ((error = Marshal.GetLastWin32Error()) == 1008) // ERROR_NO_TOKEN
+ {
+ Debug.Assert(pTokenHandle == IntPtr.Zero);
+
+ // Current thread doesn't have a token, try the process
+ if (!UnsafeNativeMethods.OpenProcessToken(
+ UnsafeNativeMethods.GetCurrentProcess(),
+ 0x8, // TOKEN_QUERY
+ ref pTokenHandle
+ ))
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: OpenProcessToken failed, gle=" + lastError);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.UnableToOpenToken,
+ lastError));
+ }
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: OpenThreadToken failed, gle=" + error);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.UnableToOpenToken,
+ error));
+ }
+ }
+
+ Debug.Assert(pTokenHandle != IntPtr.Zero);
+
+ int neededBufferSize = 0;
+
+ // Retrieve the user info from the current thread's token
+ // First, determine how big a buffer we need.
+ bool success = UnsafeNativeMethods.GetTokenInformation(
+ pTokenHandle,
+ 1, // TokenUser
+ IntPtr.Zero,
+ 0,
+ ref neededBufferSize);
+
+ int getTokenInfoError = 0;
+ if ((getTokenInfoError = Marshal.GetLastWin32Error()) != 122) // ERROR_INSUFFICIENT_BUFFER
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: GetTokenInformation (1st try) failed, gle=" + getTokenInfoError);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveTokenInfo, getTokenInfoError));
+ }
+
+ // Allocate the necessary buffer.
+ Debug.Assert(neededBufferSize > 0);
+ pBuffer = Marshal.AllocHGlobal(neededBufferSize);
+
+ // Load the user info into the buffer
+ success = UnsafeNativeMethods.GetTokenInformation(
+ pTokenHandle,
+ 1, // TokenUser
+ pBuffer,
+ neededBufferSize,
+ ref neededBufferSize);
+
+ if (!success)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "Utils",
+ "GetCurrentUserSid: GetTokenInformation (2nd try) failed, neededBufferSize=" + neededBufferSize + ", gle=" + lastError);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveTokenInfo, lastError));
+ }
+
+ // Retrieve the user's SID from the user info
+ UnsafeNativeMethods.TOKEN_USER tokenUser = (UnsafeNativeMethods.TOKEN_USER)Marshal.PtrToStructure(pBuffer, typeof(UnsafeNativeMethods.TOKEN_USER));
+ IntPtr pUserSid = tokenUser.sidAndAttributes.pSid; // this is a reference into the NATIVE memory (into pBuffer)
+
+ Debug.Assert(UnsafeNativeMethods.IsValidSid(pUserSid));
+
+ // Now we make a copy of the SID to return
+ int userSidLength = UnsafeNativeMethods.GetLengthSid(pUserSid);
+ IntPtr pCopyOfUserSid = Marshal.AllocHGlobal(userSidLength);
+ success = UnsafeNativeMethods.CopySid(userSidLength, pCopyOfUserSid, pUserSid);
+ if (!success)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "Utils",
+ "GetCurrentUserSid: CopySid failed, errorcode=" + lastError);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveTokenInfo, lastError));
+ }
+
+ return pCopyOfUserSid;
+ }
+ finally
+ {
+ if (pTokenHandle != IntPtr.Zero)
+ UnsafeNativeMethods.CloseHandle(pTokenHandle);
+
+ if (pBuffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(pBuffer);
+ }
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LsaOpenPolicy(System.IntPtr,System.IntPtr,System.Int32,System.IntPtr&amp;):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="SafeNativeMethods.LsaNtStatusToWinError(System.Int32):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LsaQueryInformationPolicy(System.IntPtr,System.Int32,System.IntPtr&amp;):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.IsValidSid(System.IntPtr):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetLengthSid(System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.CopySid(System.Int32,System.IntPtr,System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LsaClose(System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LsaFreeMemory(System.IntPtr):System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.SizeOf(System.Type):System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.AllocHGlobal(System.Int32):System.IntPtr" />
+ //<SatisfiesLinkDemand Name="Marshal.StructureToPtr(System.Object,System.IntPtr,System.Boolean):System.Void" />
+ //<SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ //<SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ internal static IntPtr GetMachineDomainSid()
+ {
+ IntPtr pPolicyHandle = IntPtr.Zero;
+ IntPtr pBuffer = IntPtr.Zero;
+ IntPtr pOA = IntPtr.Zero;
+
+ try
+ {
+ UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES oa = new UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES();
+
+ pOA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES)));
+ Marshal.StructureToPtr(oa, pOA, false);
+ int err = UnsafeNativeMethods.LsaOpenPolicy(
+ IntPtr.Zero,
+ pOA,
+ 1, // POLICY_VIEW_LOCAL_INFORMATION
+ ref pPolicyHandle);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetMachineDomainSid: LsaOpenPolicy failed, gle=" + SafeNativeMethods.LsaNtStatusToWinError(err));
+
+ throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
+ StringResources.UnableToRetrievePolicy,
+ SafeNativeMethods.LsaNtStatusToWinError(err)));
+ }
+
+ Debug.Assert(pPolicyHandle != IntPtr.Zero);
+ err = UnsafeNativeMethods.LsaQueryInformationPolicy(
+ pPolicyHandle,
+ 5, // PolicyAccountDomainInformation
+ ref pBuffer);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetMachineDomainSid: LsaQueryInformationPolicy failed, gle=" + SafeNativeMethods.LsaNtStatusToWinError(err));
+
+ throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture,
+ StringResources.UnableToRetrievePolicy,
+ SafeNativeMethods.LsaNtStatusToWinError(err)));
+ }
+
+ Debug.Assert(pBuffer != IntPtr.Zero);
+ UnsafeNativeMethods.POLICY_ACCOUNT_DOMAIN_INFO info = (UnsafeNativeMethods.POLICY_ACCOUNT_DOMAIN_INFO)
+ Marshal.PtrToStructure(pBuffer, typeof(UnsafeNativeMethods.POLICY_ACCOUNT_DOMAIN_INFO));
+
+ Debug.Assert(UnsafeNativeMethods.IsValidSid(info.domainSid));
+
+ // Now we make a copy of the SID to return
+ int sidLength = UnsafeNativeMethods.GetLengthSid(info.domainSid);
+ IntPtr pCopyOfSid = Marshal.AllocHGlobal(sidLength);
+ bool success = UnsafeNativeMethods.CopySid(sidLength, pCopyOfSid, info.domainSid);
+ if (!success)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ GlobalDebug.WriteLineIf(GlobalDebug.Error,
+ "Utils",
+ "GetMachineDomainSid: CopySid failed, errorcode=" + lastError);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrievePolicy, lastError));
+ }
+
+ return pCopyOfSid;
+ }
+ finally
+ {
+ if (pPolicyHandle != IntPtr.Zero)
+ UnsafeNativeMethods.LsaClose(pPolicyHandle);
+
+ if (pBuffer != IntPtr.Zero)
+ UnsafeNativeMethods.LsaFreeMemory(pBuffer);
+
+ if (pOA != IntPtr.Zero)
+ Marshal.FreeHGlobal(pOA);
+ }
+ }
+
+ // Returns name in the form "domain\user"
+ //<SecurityKernel Critical="True" Ring="0">
+ //<Asserts Name="Declarative: [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)]" />
+ //</SecurityKernel>
+ [System.Security.Permissions.SecurityPermission(
+ System.Security.Permissions.SecurityAction.Assert,
+ Flags = System.Security.Permissions.SecurityPermissionFlag.ControlPrincipal)]
+ [System.Security.SecuritySafeCritical]
+
+ internal static string GetNT4UserName()
+ {
+ using (WindowsIdentity currentIdentity = System.Security.Principal.WindowsIdentity.GetCurrent())
+ {
+ string s = currentIdentity.Name;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "GetNT4UserName: name is " + s);
+ return s;
+ }
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<Asserts Name="Declarative: [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)]" />
+ //</SecurityKernel>
+ [System.Security.Permissions.EnvironmentPermission(
+ System.Security.Permissions.SecurityAction.Assert,
+ Unrestricted = true)]
+ [System.Security.SecuritySafeCritical]
+
+ internal static string GetComputerFlatName()
+ {
+ //string s = System.Windows.Forms.SystemInformation.ComputerName;
+ string s = Environment.MachineName;
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "GetComputerFlatName: name is " + s);
+
+ return s;
+ }
+
+ //
+ // Interop support
+ //
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.DsGetDcName(System.String,System.String,System.IntPtr,System.String,System.Int32,System.IntPtr&amp;):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.NetApiBufferFree(System.IntPtr):System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ internal static UnsafeNativeMethods.DomainControllerInfo GetDcName(string computerName, string domainName, string siteName, int flags)
+ {
+ IntPtr domainControllerInfoPtr = IntPtr.Zero;
+
+ try
+ {
+ int err = UnsafeNativeMethods.DsGetDcName(computerName, domainName, IntPtr.Zero, siteName, flags, out domainControllerInfoPtr);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetDcName: DsGetDcName failed, err=" + err);
+ throw new PrincipalOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.UnableToRetrieveDomainInfo,
+ err));
+ }
+
+ UnsafeNativeMethods.DomainControllerInfo domainControllerInfo =
+ (UnsafeNativeMethods.DomainControllerInfo)Marshal.PtrToStructure(domainControllerInfoPtr, typeof(UnsafeNativeMethods.DomainControllerInfo));
+
+ return domainControllerInfo;
+ }
+ finally
+ {
+ if (domainControllerInfoPtr != IntPtr.Zero)
+ UnsafeNativeMethods.NetApiBufferFree(domainControllerInfoPtr);
+ }
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LookupAccountSid(System.String,System.IntPtr,System.Text.StringBuilder,System.Int32&amp;,System.Text.StringBuilder,System.Int32&amp;,System.Int32&amp;):System.Boolean" />
+ //<SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ //<ReferencesCritical Name="Method: ConvertByteArrayToIntPtr(Byte[]):IntPtr" Ring="1" />
+ //<ReferencesCritical Name="Method: BeginImpersonation(NetCred, IntPtr&amp;):Boolean" Ring="1" />
+ //<ReferencesCritical Name="Method: EndImpersonation(IntPtr):Void" Ring="1" />
+ //</SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static int LookupSid(string serverName, NetCred credentials, byte[] sid, out string name, out string domainName, out int accountUsage)
+ {
+ IntPtr pSid = IntPtr.Zero;
+
+ int nameLength = 0;
+ int domainNameLength = 0;
+
+ StringBuilder sbName;
+ StringBuilder sbDomainName;
+
+ accountUsage = 0;
+ name = null;
+ domainName = null;
+
+ IntPtr hUser = IntPtr.Zero;
+
+ try
+ {
+ pSid = ConvertByteArrayToIntPtr(sid);
+
+ Utils.BeginImpersonation(credentials, out hUser);
+
+ // hUser could be null if no credentials were specified
+ Debug.Assert(hUser != IntPtr.Zero ||
+ (credentials == null || (credentials.UserName == null && credentials.Password == null)));
+
+ bool f = UnsafeNativeMethods.LookupAccountSid(serverName, pSid, null, ref nameLength, null, ref domainNameLength, ref accountUsage);
+
+ int lastErr = Marshal.GetLastWin32Error();
+ if (lastErr != 122) // ERROR_INSUFFICIENT_BUFFER
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (1st try) failed, gle=" + lastErr);
+ return lastErr;
+ }
+
+ Debug.Assert(f == false); // should never succeed, with a 0 buffer size
+
+ Debug.Assert(nameLength > 0);
+ Debug.Assert(domainNameLength > 0);
+
+ sbName = new StringBuilder(nameLength);
+ sbDomainName = new StringBuilder(domainNameLength);
+
+ f = UnsafeNativeMethods.LookupAccountSid(serverName, pSid, sbName, ref nameLength, sbDomainName, ref domainNameLength, ref accountUsage);
+
+ if (f == false)
+ {
+ lastErr = Marshal.GetLastWin32Error();
+ Debug.Assert(lastErr != 0);
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (2nd try) failed, gle=" + lastErr);
+ return lastErr;
+ }
+
+ name = sbName.ToString();
+ domainName = sbDomainName.ToString();
+
+ return 0;
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pSid);
+
+ if (hUser != IntPtr.Zero)
+ Utils.EndImpersonation(hUser);
+ }
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<SatisfiesLinkDemand Name="GroupPrincipal.MakeGroup(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.GroupPrincipal" />
+ //<SatisfiesLinkDemand Name="Principal.LoadValueIntoProperty(System.String,System.Object):System.Void" />
+ //<ReferencesCritical Name="Method: ClassifySID(Byte[]):SidType" Ring="1" />
+ //<ReferencesCritical Name="Method: LookupSid(String, NetCred, Byte[], String&amp;, String&amp;, Int32&amp;):Int32" Ring="1" />
+ //<ReferencesCritical Name="Method: GroupPrincipal.MakeGroup(System.DirectoryServices.AccountManagement.PrincipalContext):System.DirectoryServices.AccountManagement.GroupPrincipal" Ring="1" />
+ //<ReferencesCritical Name="Method: ConvertSidToSDDL(Byte[]):String" Ring="1" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ static internal Principal ConstructFakePrincipalFromSID(
+ byte[] sid,
+ PrincipalContext ctx,
+ string serverName,
+ NetCred credentials,
+ string authorityName)
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "Utils",
+ "ConstructFakePrincipalFromSID: Build principal for SID={0}, server={1}, authority={2}",
+ Utils.ByteArrayToString(sid),
+ (serverName != null ? serverName : "NULL"),
+ (authorityName != null ? authorityName : "NULL"));
+
+ Debug.Assert(ClassifySID(sid) == SidType.FakeObject);
+
+ // Get the name for it
+ string nt4Name = "";
+
+ int accountUsage = 0;
+ string name;
+ string domainName;
+
+ int err = Utils.LookupSid(serverName, credentials, sid, out name, out domainName, out accountUsage);
+ if (err == 0)
+ {
+ // If it failed, we'll just live without a name
+ //Debug.Assert(accountUsage == 5 /*WellKnownGroup*/);
+ nt4Name = (!String.IsNullOrEmpty(domainName) ? domainName + "\\" : "") + name;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Warn,
+ "Utils",
+ "ConstructFakePrincipalFromSID: LookupSid failed (ignoring), serverName=" + serverName + ", err=" + err);
+ }
+
+ // Since LookupAccountSid indicates all of the NT AUTHORITY, etc., SIDs are WellKnownGroups,
+ // we'll map them all to Group.
+
+ // Create a Principal object to represent it
+ GroupPrincipal g = GroupPrincipal.MakeGroup(ctx);
+
+ g.fakePrincipal = true;
+ g.unpersisted = false;
+
+ // Set the display name on the object
+ g.LoadValueIntoProperty(PropertyNames.PrincipalDisplayName, nt4Name);
+
+ // Set the display name on the object
+ g.LoadValueIntoProperty(PropertyNames.PrincipalName, name);
+
+ // Set the display name on the object
+ g.LoadValueIntoProperty(PropertyNames.PrincipalSamAccountName, name);
+
+ // SID IdentityClaim
+ SecurityIdentifier sidObj = new SecurityIdentifier(Utils.ConvertSidToSDDL(sid));
+
+ // Set the display name on the object
+ g.LoadValueIntoProperty(PropertyNames.PrincipalSid, sidObj);
+
+ g.LoadValueIntoProperty(PropertyNames.GroupIsSecurityGroup, true);
+ return g;
+ }
+
+ //
+ // Impersonation
+ //
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LogonUser(System.String,System.String,System.String,System.Int32,System.Int32,System.IntPtr&amp;):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ImpersonateLoggedOnUser(System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.CloseHandle(System.IntPtr):System.Boolean" />
+ //<SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
+ //<ReferencesCritical Name="Method: NetCred.get_ParsedUserName():System.String" Ring="2" />
+ //<ReferencesCritical Name="Method: NetCred.get_Domain():System.String" Ring="2" />
+ //</SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static bool BeginImpersonation(NetCred credential, out IntPtr hUserToken)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "Entering BeginImpersonation");
+
+ hUserToken = IntPtr.Zero;
+ IntPtr hToken = IntPtr.Zero;
+
+ // default credential is specified, no need to do impersonation
+ if (credential == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "BeginImpersonation: nothing to impersonate");
+ return false;
+ }
+
+ // Retrive the parsed username which has had the domain removed because LogonUser
+ // expects creds this way.
+ string userName = credential.ParsedUserName;
+ string password = credential.Password;
+ string domainName = credential.Domain;
+
+ // no need to do impersonation as username and password are both null
+ if (userName == null && password == null)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "BeginImpersonation: nothing to impersonate (2)");
+ return false;
+ }
+
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "BeginImpersonation: trying to impersonate " + userName);
+
+ int result = UnsafeNativeMethods.LogonUser(
+ userName,
+ domainName,
+ password,
+ 9, /* LOGON32_LOGON_NEW_CREDENTIALS */
+ 3, /* LOGON32_PROVIDER_WINNT50 */
+ ref hToken);
+ // check the result
+ if (result == 0)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "BeginImpersonation: LogonUser failed, gle=" + lastError);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.UnableToImpersonateCredentials,
+ lastError));
+ }
+
+ result = UnsafeNativeMethods.ImpersonateLoggedOnUser(hToken);
+ if (result == 0)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "BeginImpersonation: ImpersonateLoggedOnUser failed, gle=" + lastError);
+
+ // Close the token the was created above....
+ UnsafeNativeMethods.CloseHandle(hToken);
+
+ throw new PrincipalOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ StringResources.UnableToImpersonateCredentials,
+ lastError));
+ }
+
+ hUserToken = hToken;
+ return true;
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.RevertToSelf():System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.CloseHandle(System.IntPtr):System.Boolean" />
+ //</SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static void EndImpersonation(IntPtr hUserToken)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "Entering EndImpersonation");
+
+ UnsafeNativeMethods.RevertToSelf();
+ UnsafeNativeMethods.CloseHandle(hUserToken);
+ }
+
+ // <SecurityKernel TreatAsSafe="Directly applied from MetaData" Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.DsRoleGetPrimaryDomainInformation(System.IntPtr,System.DirectoryServices.AccountManagement.UnsafeNativeMethods+DSROLE_PRIMARY_DOMAIN_INFO_LEVEL,System.IntPtr&):System.Int32" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.DsRoleGetPrimaryDomainInformation(System.String,System.DirectoryServices.AccountManagement.UnsafeNativeMethods+DSROLE_PRIMARY_DOMAIN_INFO_LEVEL,System.IntPtr&):System.Int32" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.DsRoleFreeMemory(System.IntPtr):System.Int32" />
+ // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ internal static bool IsMachineDC(String computerName)
+ {
+ IntPtr dsRoleInfoPtr = IntPtr.Zero;
+ int err = -1;
+
+ try
+ {
+ if (null == computerName)
+ err = UnsafeNativeMethods.DsRoleGetPrimaryDomainInformation(IntPtr.Zero, UnsafeNativeMethods.DSROLE_PRIMARY_DOMAIN_INFO_LEVEL.DsRolePrimaryDomainInfoBasic, out dsRoleInfoPtr);
+ else
+ err = UnsafeNativeMethods.DsRoleGetPrimaryDomainInformation(computerName, UnsafeNativeMethods.DSROLE_PRIMARY_DOMAIN_INFO_LEVEL.DsRolePrimaryDomainInfoBasic, out dsRoleInfoPtr);
+
+ if (err != 0)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "IsMachineDC: DsRoleGetPrimaryDomainInformation failed, err=" + err);
+ throw new PrincipalOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ StringResources.UnableToRetrieveDomainInfo,
+ err));
+ }
+
+ UnsafeNativeMethods.DSROLE_PRIMARY_DOMAIN_INFO_BASIC dsRolePrimaryDomainInfo =
+ (UnsafeNativeMethods.DSROLE_PRIMARY_DOMAIN_INFO_BASIC)Marshal.PtrToStructure(dsRoleInfoPtr, typeof(UnsafeNativeMethods.DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
+
+ return (dsRolePrimaryDomainInfo.MachineRole == UnsafeNativeMethods.DSROLE_MACHINE_ROLE.DsRole_RoleBackupDomainController ||
+ dsRolePrimaryDomainInfo.MachineRole == UnsafeNativeMethods.DSROLE_MACHINE_ROLE.DsRole_RolePrimaryDomainController);
+ }
+ finally
+ {
+ if (dsRoleInfoPtr != IntPtr.Zero)
+ UnsafeNativeMethods.DsRoleFreeMemory(dsRoleInfoPtr);
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueCollection.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueCollection.cs
new file mode 100644
index 0000000000..f3823a4a26
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueCollection.cs
@@ -0,0 +1,528 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ public class PrincipalValueCollection<T> : IList<T>, IList
+ // T must be a ValueType or immutable ref type (such as string)
+ {
+ //
+ // IList
+ //
+ bool IList.IsFixedSize
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.get_IsFixedSize():System.Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return IsFixedSize;
+ }
+ }
+
+ bool IList.IsReadOnly
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.get_IsReadOnly():System.Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return IsReadOnly;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.get_Count():System.Int32" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ int IList.Add(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _inner.Add((T)value);
+ return Count;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.Clear():System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ void IList.Clear()
+ {
+ Clear();
+ }
+
+ bool IList.Contains(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return _inner.Contains((T)value);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.IndexOf(T):System.Int32" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ int IList.IndexOf(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return IndexOf((T)value);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.Insert(System.Int32,T):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ void IList.Insert(int index, object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ Insert(index, (T)value);
+ }
+
+ void IList.Remove(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _inner.Remove((T)value);
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.RemoveAt(System.Int32):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ void IList.RemoveAt(int index)
+ {
+ RemoveAt(index);
+ }
+
+ object IList.this[int index]
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.get_Item(System.Int32):T" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return this[index];
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.set_Item(System.Int32,T):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ this[index] = (T)value;
+ }
+ }
+
+ //
+ // ICollection
+ //
+ void ICollection.CopyTo(Array array, int index)
+ {
+ ((ICollection)_inner).CopyTo(array, index);
+ }
+
+ int ICollection.Count
+ {
+ get
+ {
+ return _inner.Count;
+ }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.get_IsSynchronized():System.Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return IsSynchronized;
+ }
+ }
+
+ object ICollection.SyncRoot
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.get_SyncRoot():System.Object" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return SyncRoot;
+ }
+ }
+
+ public bool IsSynchronized
+ {
+ get
+ {
+ return ((ICollection)_inner).IsSynchronized;
+ }
+ }
+
+ public object SyncRoot
+ {
+ get
+ {
+ return this;
+ }
+ }
+
+ //
+ // IEnumerable
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="PrincipalValueCollection`1<T>.GetEnumerator():System.Collections.Generic.IEnumerator`1<T>" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return (IEnumerator)GetEnumerator();
+ }
+
+ //
+ // IList<T>
+ //
+ public bool IsFixedSize
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ // Adds obj to the end of the list by inserting it into insertedValues.
+ public void Add(T value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _inner.Add(value);
+ }
+
+ public void Clear()
+ {
+ _inner.Clear();
+ }
+
+ public bool Contains(T value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return _inner.Contains(value);
+ }
+
+ public int IndexOf(T value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ int index = 0;
+
+ foreach (TrackedCollection<T>.ValueEl el in _inner.combinedValues)
+ {
+ if (el.isInserted && el.insertedValue.Equals(value))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "IndexOf: found {0} on inserted at {1}", value, index);
+ return index;
+ }
+
+ if (!el.isInserted && el.originalValue.Right.Equals(value))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "IndexOf: found {0} on original at {1}", value, index);
+ return index;
+ }
+
+ index++;
+ }
+
+ return -1;
+ }
+
+ public void Insert(int index, T value)
+ {
+ _inner.MarkChange();
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if ((index < 0) || (index > _inner.combinedValues.Count))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalValueCollection", "Insert({0}): out of range (count={1})", index, _inner.combinedValues.Count);
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ TrackedCollection<T>.ValueEl el = new TrackedCollection<T>.ValueEl();
+ el.isInserted = true;
+ el.insertedValue = value;
+
+ _inner.combinedValues.Insert(index, el);
+ }
+
+ public bool Remove(T value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return _inner.Remove(value);
+ }
+
+ public void RemoveAt(int index)
+ {
+ _inner.MarkChange();
+
+ if ((index < 0) || (index >= _inner.combinedValues.Count))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalValueCollection", "RemoveAt({0}): out of range (count={1})", index, _inner.combinedValues.Count);
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ TrackedCollection<T>.ValueEl el = _inner.combinedValues[index];
+
+ if (el.isInserted)
+ {
+ // We're removing an inserted value.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "RemoveAt({0}): removing inserted", index);
+ _inner.combinedValues.RemoveAt(index);
+ }
+ else
+ {
+ // We're removing an original value.
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "RemoveAt({0}): removing original", index);
+ Pair<T, T> pair = _inner.combinedValues[index].originalValue;
+ _inner.combinedValues.RemoveAt(index);
+ _inner.removedValues.Add(pair.Left);
+ }
+ }
+
+ public T this[int index]
+ {
+ get
+ {
+ if ((index < 0) || (index >= _inner.combinedValues.Count))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalValueCollection", "this[{0}].get: out of range (count={1})", index, _inner.combinedValues.Count);
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ TrackedCollection<T>.ValueEl el = _inner.combinedValues[index];
+
+ if (el.isInserted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "this[{0}].get: is inserted {1}", index, el.insertedValue);
+ return el.insertedValue;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "this[{0}].get: is original {1}", index, el.originalValue.Right);
+ return el.originalValue.Right; // Right == current value
+ }
+ }
+
+ set
+ {
+ _inner.MarkChange();
+
+ if ((index < 0) || (index >= _inner.combinedValues.Count))
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalValueCollection", "this[{0}].set: out of range (count={1})", index, _inner.combinedValues.Count);
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ TrackedCollection<T>.ValueEl el = _inner.combinedValues[index];
+
+ if (el.isInserted)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "this[{0}].set: is inserted {1}", index, value);
+ el.insertedValue = value;
+ }
+ else
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "this[{0}].set: is original {1}", index, value);
+ el.originalValue.Right = value;
+ }
+ }
+ }
+
+ //
+ // ICollection<T>
+ //
+ public void CopyTo(T[] array, int index)
+ {
+ ((ICollection)this).CopyTo((Array)array, index);
+ }
+
+ public int Count
+ {
+ get
+ {
+ return _inner.Count;
+ }
+ }
+
+ //
+ // IEnumerable<T>
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="ValueCollectionEnumerator`1<T>..ctor(System.DirectoryServices.AccountManagement.TrackedCollection`1<T>,System.Collections.Generic.List`1<System.DirectoryServices.AccountManagement.TrackedCollection`1+ValueEl>)" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public IEnumerator<T> GetEnumerator()
+ {
+ return new ValueCollectionEnumerator<T>(_inner, _inner.combinedValues);
+ }
+
+ //
+ // Private implementation
+ //
+ private TrackedCollection<T> _inner = new TrackedCollection<T>();
+
+ //
+ // Internal constructor
+ //
+ internal PrincipalValueCollection()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "Ctor");
+
+ // Nothing to do here
+ }
+
+ //
+ // Load/Store implementation
+ //
+
+ internal void Load(List<T> values)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "Load, count={0}", values.Count);
+
+ // To support reload
+ _inner.combinedValues.Clear();
+ _inner.removedValues.Clear();
+
+ foreach (T value in values)
+ {
+ // If T was a mutable reference type, would need to make a copy of value
+ // for the left-side of the Pair, so that changes to the value in the
+ // right-side wouldn't also change the left-side value (due to aliasing).
+ // However, we constrain T to be either a value type or a immutable ref type (e.g., string)
+ // to avoid this problem.
+ TrackedCollection<T>.ValueEl el = new TrackedCollection<T>.ValueEl();
+ el.isInserted = false;
+ el.originalValue = new Pair<T, T>(value, value);
+
+ _inner.combinedValues.Add(el);
+ }
+ }
+
+ internal List<T> Inserted
+ {
+ get
+ {
+ return _inner.Inserted;
+ }
+ }
+
+ internal List<T> Removed
+ {
+ get
+ {
+ return _inner.Removed;
+ }
+ }
+
+ internal List<Pair<T, T>> ChangedValues
+ {
+ get
+ {
+ return _inner.ChangedValues;
+ }
+ }
+
+ internal bool Changed
+ {
+ get
+ {
+ return _inner.Changed;
+ }
+ }
+
+ // Resets the change-tracking of the collection to 'unchanged', by clearing out the removedValues,
+ // changing inserted values into original values, and for all Pairs<T,T> in originalValues for which
+ // the left-side does not equal the right-side, copying the right-side over the left-side
+ internal void ResetTracking()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalValueCollection", "Entering ResetTracking");
+
+ _inner.removedValues.Clear();
+
+ foreach (TrackedCollection<T>.ValueEl el in _inner.combinedValues)
+ {
+ if (el.isInserted)
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "PrincipalValueCollection",
+ "ResetTracking: moving {0} (type {1}) from inserted to original",
+ el.insertedValue,
+ el.insertedValue.GetType());
+
+ el.isInserted = false;
+ el.originalValue = new Pair<T, T>(el.insertedValue, el.insertedValue);
+ //el.insertedValue = T.default;
+ }
+ else
+ {
+ Pair<T, T> pair = el.originalValue;
+
+ if (!pair.Left.Equals(pair.Right))
+ {
+ GlobalDebug.WriteLineIf(
+ GlobalDebug.Info,
+ "PrincipalValueCollection",
+ "ResetTracking: found changed original, left={0}, right={1}, type={2}",
+ pair.Left,
+ pair.Right,
+ pair.Left.GetType());
+
+ pair.Left = pair.Right;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueCollectionEnumerator.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueCollectionEnumerator.cs
new file mode 100644
index 0000000000..aad16659bc
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueCollectionEnumerator.cs
@@ -0,0 +1,97 @@
+// 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.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [DirectoryServicesPermission(System.Security.Permissions.SecurityAction.LinkDemand, Unrestricted = true)]
+ internal class ValueCollectionEnumerator<T> : IEnumerator<T>, IEnumerator
+ // T must be a ValueType
+ {
+ //
+ // Public properties
+ //
+
+ public T Current
+ {
+ get
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering Current");
+ return _inner.Current;
+ }
+ }
+
+ object IEnumerator.Current
+ {
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="ValueCollectionEnumerator`1<T>.get_Current():T" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ get
+ {
+ return Current;
+ }
+ }
+
+ //
+ // Public methods
+ //
+
+ public bool MoveNext()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering MoveNext");
+ return _inner.MoveNext();
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="ValueCollectionEnumerator`1<T>.MoveNext():System.Boolean" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ bool IEnumerator.MoveNext()
+ {
+ return MoveNext();
+ }
+
+ public void Reset()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering Reset");
+ _inner.Reset();
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="ValueCollectionEnumerator`1<T>.Reset():System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ void IEnumerator.Reset()
+ {
+ Reset();
+ }
+
+ public void Dispose()
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering Dispose");
+ _inner.Dispose();
+ }
+
+ //
+ // Internal constructors
+ //
+ internal ValueCollectionEnumerator(TrackedCollection<T> trackingList, List<TrackedCollection<T>.ValueEl> combinedValues)
+ {
+ GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Ctor");
+ _inner = new TrackedCollectionEnumerator<T>("ValueCollectionEnumerator", trackingList, combinedValues);
+ }
+
+ //
+ // Private implementation
+ //
+
+ private TrackedCollectionEnumerator<T> _inner;
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueList.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueList.cs
new file mode 100644
index 0000000000..8dda349922
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueList.cs
@@ -0,0 +1,409 @@
+using System;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Identity.Principals
+{
+ public class PrincipalValueCollection<T> : IList<T>, IList
+ // T must be a ValueType or immutable ref type (such as string)
+ {
+ //
+ // IList
+ //
+ bool IList.IsFixedSize
+ {
+ get
+ {
+ return IsFixedSize;
+ }
+ }
+
+ bool IList.IsReadOnly
+ {
+ get
+ {
+ return IsReadOnly;
+ }
+ }
+
+ int IList.Add(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return inner.Add((T) value);
+ }
+
+ void IList.Clear()
+ {
+ Clear();
+ }
+
+ bool IList.Contains(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return inner.Contains((T) value);
+ }
+
+ int IList.IndexOf(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return IndexOf((T) value);
+ }
+
+ void IList.Insert(int index, object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ Insert(index, (T) value);
+ }
+
+ void IList.Remove(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ inner.Remove((T) value);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ RemoveAt(index);
+ }
+
+ object IList.this[int index]
+ {
+ get
+ {
+ return this[index];
+ }
+
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ this[index] = (T) value;
+ }
+ }
+
+ //
+ // ICollection
+ //
+ void ICollection.CopyTo(Array array, int index)
+ {
+ ((ICollection)inner).CopyTo(array, index);
+ }
+
+ int ICollection.Count
+ {
+ get
+ {
+ return inner.Count;
+ }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return ((ICollection)inner).IsSynchronized;
+ }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ return this;
+ }
+ }
+
+ //
+ // IEnumerable
+ //
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return (IEnumerator) GetEnumerator();
+ }
+
+
+ //
+ // IList<T>
+ //
+ public bool IsFixedSize
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ // Adds obj to the end of the list by inserting it into insertedValues.
+ public int Add(T value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return inner.Add(value);
+ }
+
+ public void Clear()
+ {
+ inner.Clear();
+ }
+
+ public bool Contains(T value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return inner.Contains(value);
+ }
+
+ public int IndexOf(T value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ int index = 0;
+
+ foreach (TrackedCollection<T>.ValueEl el in inner.combinedValues)
+ {
+ if (el.isInserted && el.insertedValue.Equals(value))
+ return index;
+
+ if (!el.isInserted && el.originalValue.Right.Equals(value))
+ return index;
+
+ index++;
+ }
+
+ return -1;
+ }
+
+ public void Insert(int index, T value)
+ {
+ inner.MarkChange();
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if ((index < 0) || (index > inner.combinedValues.Count))
+ throw new ArgumentOutOfRangeException("index");
+
+ TrackedCollection<T>.ValueEl el = new TrackedCollection<T>.ValueEl();
+ el.isInserted = true;
+ el.insertedValue = value;
+
+ inner.combinedValues.Insert(index, el);
+ }
+
+ public bool Remove(T value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return inner.Remove(value);
+ }
+
+ public void RemoveAt(int index)
+ {
+ inner.MarkChange();
+
+ if ((index < 0) || (index >= inner.combinedValues.Count))
+ throw new ArgumentOutOfRangeException("index");
+
+ TrackedCollection<T>.ValueEl el = inner.combinedValues[index];
+
+ if (el.isInserted)
+ {
+ // We're removing an inserted value.
+ inner.combinedValues.RemoveAt(index);
+ }
+ else
+ {
+ // We're removing an original value.
+ Pair<T,T> pair = inner.combinedValues[index].originalValue;
+ inner.combinedValues.RemoveAt(index);
+ inner.removedValues.Add(pair.Left);
+ }
+ }
+
+ public T this[int index]
+ {
+ get
+ {
+ if ((index < 0) || (index >= inner.combinedValues.Count))
+ throw new ArgumentOutOfRangeException("index");
+
+ TrackedCollection<T>.ValueEl el = inner.combinedValues[index];
+
+ if (el.isInserted)
+ {
+ return el.insertedValue;
+ }
+ else
+ {
+ return el.originalValue.Right; // Right == current value
+ }
+ }
+
+ set
+ {
+ inner.MarkChange();
+
+ if ((index < 0) || (index >= inner.combinedValues.Count))
+ throw new ArgumentOutOfRangeException("index");
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ TrackedCollection<T>.ValueEl el = inner.combinedValues[index];
+
+ if (el.isInserted)
+ {
+ el.insertedValue = value;
+ }
+ else
+ {
+ el.originalValue.Right = value;
+ }
+ }
+ }
+
+ //
+ // ICollection<T>
+ //
+ public void CopyTo(T[] array, int index)
+ {
+ ((ICollection)this).CopyTo((Array) array, index);
+ }
+
+ public int Count
+ {
+ get
+ {
+ return inner.Count;
+ }
+ }
+
+ //
+ // IEnumerable<T>
+ //
+ public IEnumerator<T> GetEnumerator()
+ {
+ return new ValueCollectionEnumerator<T>(inner, inner.combinedValues);
+ }
+
+ //
+ // Private implementation
+ //
+ TrackedCollection<T> inner = new TrackedCollection<T>();
+
+ //
+ // Internal constructor
+ //
+ internal PrincipalValueCollection()
+ {
+ // Nothing to do here
+ }
+
+ //
+ // Load/Store implementation
+ //
+
+ internal void Load(List<T> values)
+ {
+ // To support reload
+ inner.combinedValues.Clear();
+ inner.removedValues.Clear();
+
+
+ foreach (T value in values)
+ {
+ // If T was a mutable reference type, would need to make a copy of value
+ // for the left-side of the Pair, so that changes to the value in the
+ // right-side wouldn't also change the left-side value (due to aliasing).
+ // However, we constrain T to be either a value type or a immutable ref type (e.g., string)
+ // to avoid this problem.
+ TrackedCollection<T>.ValueEl el = new TrackedCollection<T>.ValueEl();
+ el.isInserted = false;
+ el.originalValue = new Pair<T,T>(value, value);
+
+ inner.combinedValues.Add(el);
+ }
+ }
+
+ internal List<T> Inserted
+ {
+ get
+ {
+ return inner.Inserted;
+ }
+ }
+
+ internal List<T> Removed
+ {
+ get
+ {
+ return inner.Removed;
+ }
+ }
+
+ internal List<Pair<T,T>> ChangedValues
+ {
+ get
+ {
+ return inner.ChangedValues;
+ }
+ }
+
+ internal bool Changed
+ {
+ get
+ {
+ return inner.Changed;
+ }
+ }
+
+ // Resets the change-tracking of the collection to 'unchanged', by clearing out the removedValues,
+ // changing inserted values into original values, and for all Pairs<T,T> in originalValues for which
+ // the left-side does not equal the right-side, copying the right-side over the left-side
+ internal void ResetTracking()
+ {
+ inner.removedValues.Clear();
+
+ foreach (TrackedCollection<T>.ValueEl el in inner.combinedValues)
+ {
+ if (el.isInserted)
+ {
+ el.isInserted = false;
+ el.originalValue = new Pair<T,T>(el.insertedValue, el.insertedValue);
+ el.insertedValue = T.default;
+ }
+ else
+ {
+ Pair<T,T> pair = el.originalValue;
+
+ if (!pair.Left.Equals(pair.Right))
+ pair.Left = pair.Right;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueListEnumerator.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueListEnumerator.cs
new file mode 100644
index 0000000000..e25caf35c0
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/ValueListEnumerator.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Identity.Principals
+{
+ public class ValueCollectionEnumerator<T> : IEnumerator<T>, IEnumerator
+ // T must be a ValueType
+ {
+
+ //
+ // Public properties
+ //
+
+ public T Current
+ {
+ get
+ {
+ return inner.Current;
+ }
+ }
+
+
+
+ object IEnumerator.Current
+ {
+ get
+ {
+ return Current;
+ }
+ }
+
+ //
+ // Public methods
+ //
+
+ public bool MoveNext()
+ {
+ return inner.MoveNext();
+ }
+
+ bool IEnumerator.MoveNext()
+ {
+ return MoveNext();
+ }
+
+ public void Reset()
+ {
+ inner.Reset();
+ }
+
+ void IEnumerator.Reset()
+ {
+ Reset();
+ }
+
+ public void Dispose()
+ {
+ inner.Dispose();
+ }
+
+ //
+ // Internal constructors
+ //
+ internal ValueCollectionEnumerator(TrackedCollection<T> trackingList, List<TrackedCollection<T>.ValueEl> combinedValues)
+ {
+ inner = new TrackedCollectionEnumerator<T>("ValueCollectionEnumerator", trackingList, combinedValues);
+ }
+
+ //
+ // Private implementation
+ //
+
+ TrackedCollectionEnumerator<T> inner;
+
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/config.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/config.cs
new file mode 100644
index 0000000000..c7f1c392fb
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/config.cs
@@ -0,0 +1,37 @@
+
+
+//
+// This file controls whether we're building for Longhorn or Whidbey.
+// There are four #define constants which control which protocol stacks will be included
+// in the API:
+//
+// PAPI_AD Active Directory
+// PAPI_REGSAM Registry-SAM
+// PAPI_MSAM Machine SAM (implies PAPI_REGSAM as well)
+//
+// The desired combination of these, in turn, is selected by specifying either FLAVOR_LONGHORN
+// or FLAVOR_WHIDBEY.
+//
+
+// Given the flavor of the API we're building, select the appropriate protocol stacks to include
+#if FLAVOR_LONGHORN
+
+ #define PAPI_AD
+ #define PAPI_MSAM
+
+#elif FLAVOR_WHIDBEY
+
+ #define PAPI_AD
+ #define PAPI_REGSAM
+
+#else
+
+ #error "Must define either FLAVOR_LONGHORN or FLAVOR_WHIDBEY"
+
+#endif
+
+// MSAM is built on top of Reg-SAM. If we're building PAPI_MSAM, need to enable PAPI_REGSAM as well.
+#if PAPI_MSAM
+ #define PAPI_REGSAM
+#endif
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/constants.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/constants.cs
new file mode 100644
index 0000000000..c50a3bef5b
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/constants.cs
@@ -0,0 +1,159 @@
+// 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.Collections;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ // This enum tracks the load state of our principal side data cache.
+ // NotSet = default value,
+ // Loaded = Value from store was set into cache date, Data in cache matches data in store.
+ // Changed = User has modifed the cache value but is has not been pushed to the store yet
+ internal enum LoadState
+ {
+ NotSet = 0,
+ Loaded,
+ Changed
+ }
+
+ // These are the default options used when a user does not specify a context option to connect to the store.
+ internal static class DefaultContextOptions
+ {
+ internal static ContextOptions MachineDefaultContextOption = ContextOptions.Negotiate;
+ internal static ContextOptions ADDefaultContextOption = ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing;
+ }
+
+ internal class LdapConstants
+ {
+ public static int LDAP_SSL_PORT = 636;
+ public static int LDAP_PORT = 389;
+ internal static DateTime defaultUtcTime = new DateTime(1601, 1, 1, 0, 0, 0);
+ private LdapConstants() { }
+ }
+ // The string constants used internally to specify each property
+ internal class PropertyNames
+ {
+ private PropertyNames() { }
+ // Principal
+ internal const string PrincipalDisplayName = "Principal.DisplayName";
+ internal const string PrincipalDescription = "Principal.Description";
+ internal const string PrincipalSamAccountName = "Principal.SamAccountName";
+ internal const string PrincipalUserPrincipalName = "Principal.UserPrincipalName";
+ internal const string PrincipalGuid = "Principal.Guid";
+ internal const string PrincipalSid = "Principal.Sid";
+ internal const string PrincipalIdentityClaims = "Principal.IdentityClaims";
+ internal const string PrincipalDistinguishedName = "Principal.DistinguishedName";
+ internal const string PrincipalStructuralObjectClass = "Principal.StructuralObjectClass";
+ internal const string PrincipalName = "Principal.Name";
+ internal const string PrincipalExtensionCache = "Principal.ExtensionCache";
+
+ // AuthenticablePrincipal
+ internal const string AuthenticablePrincipalEnabled = "AuthenticablePrincipal.Enabled";
+ internal const string AuthenticablePrincipalCertificates = "AuthenticablePrincipal.Certificates";
+
+ // Group
+ internal const string GroupIsSecurityGroup = "GroupPrincipal.IsSecurityGroup";
+ internal const string GroupGroupScope = "GroupPrincipal.GroupScope";
+ internal const string GroupMembers = "GroupPrincipal.Members";
+
+ // User
+ internal const string UserGivenName = "UserPrincipal.GivenName";
+ internal const string UserMiddleName = "UserPrincipal.MiddleName";
+ internal const string UserSurname = "UserPrincipal.Surname";
+ internal const string UserEmailAddress = "UserPrincipal.EmailAddress";
+ internal const string UserVoiceTelephoneNumber = "UserPrincipal.VoiceTelephoneNumber";
+ internal const string UserEmployeeID = "UserPrincipal.EmployeeId";
+
+ // Computer
+ internal const string ComputerServicePrincipalNames = "ComputerPrincipal.ServicePrincipalNames";
+
+ // AccountInfo
+ internal const string AcctInfoPrefix = "AuthenticablePrincipal.AccountInfo";
+ internal const string AcctInfoAcctLockoutTime = "AuthenticablePrincipal.AccountInfo.AccountLockoutTime";
+ internal const string AcctInfoLastLogon = "AuthenticablePrincipal.AccountInfo.LastLogon";
+ internal const string AcctInfoPermittedWorkstations = "AuthenticablePrincipal.AccountInfo.PermittedWorkstations";
+ internal const string AcctInfoPermittedLogonTimes = "AuthenticablePrincipal.AccountInfo.PermittedLogonTimes";
+ internal const string AcctInfoExpirationDate = "AuthenticablePrincipal.AccountInfo.AccountExpirationDate";
+ internal const string AcctInfoSmartcardRequired = "AuthenticablePrincipal.AccountInfo.SmartcardLogonRequired";
+ internal const string AcctInfoDelegationPermitted = "AuthenticablePrincipal.AccountInfo.DelegationPermitted";
+ internal const string AcctInfoBadLogonCount = "AuthenticablePrincipal.AccountInfo.BadLogonCount";
+ internal const string AcctInfoHomeDirectory = "AuthenticablePrincipal.AccountInfo.HomeDirectory";
+ internal const string AcctInfoHomeDrive = "AuthenticablePrincipal.AccountInfo.HomeDrive";
+ internal const string AcctInfoScriptPath = "AuthenticablePrincipal.AccountInfo.ScriptPath";
+ // This property is not publically exposed but is used be a ReadOnlySearchFilter.
+ internal const string AcctInfoExpiredAccount = "AuthenticablePrincipal.AccountInfoExpired";
+
+ // PasswordInfo
+ internal const string PwdInfoPrefix = "AuthenticablePrincipal.PasswordInfo";
+ internal const string PwdInfoLastPasswordSet = "AuthenticablePrincipal.PasswordInfo.LastPasswordSet";
+ internal const string PwdInfoLastBadPasswordAttempt = "AuthenticablePrincipal.PasswordInfo.LastBadPasswordAttempt";
+ internal const string PwdInfoPasswordNotRequired = "AuthenticablePrincipal.PasswordInfo.PasswordNotRequired";
+ internal const string PwdInfoPasswordNeverExpires = "AuthenticablePrincipal.PasswordInfo.PasswordNeverExpires";
+ internal const string PwdInfoCannotChangePassword = "AuthenticablePrincipal.PasswordInfo.UserCannotChangePassword";
+ internal const string PwdInfoAllowReversiblePasswordEncryption = "AuthenticablePrincipal.PasswordInfo.AllowReversiblePasswordEncryption";
+
+ // these two are not publicly exposed properties, but are used internally to track ResetPassword/ExpirePasswordNow
+ // operations against unpersisted principals, so that they can be performed once the principal has been Saved
+ internal const string PwdInfoPassword = "AuthenticablePrincipal.PasswordInfo.Password";
+ internal const string PwdInfoExpireImmediately = "AuthenticablePrincipal.PasswordInfo.ExpireImmediately";
+ }
+
+ // Given an internal property name (from PropertyNames), returns the external form of the name for use in error-reporting
+ internal class PropertyNamesExternal
+ {
+ private PropertyNamesExternal() { }
+
+ private static int s_acctInfoPrefixLength = PropertyNames.AcctInfoPrefix.Length;
+ private static int s_pwdInfoPrefixLength = PropertyNames.PwdInfoPrefix.Length;
+
+ internal static string GetExternalForm(string propertyName)
+ {
+ if (propertyName.StartsWith(PropertyNames.AcctInfoPrefix, StringComparison.Ordinal))
+ {
+ return "AuthenticablePrincipal" + propertyName.Substring(s_acctInfoPrefixLength);
+ }
+ else if (propertyName.StartsWith(PropertyNames.PwdInfoPrefix, StringComparison.Ordinal))
+ {
+ return "AuthenticablePrincipal" + propertyName.Substring(s_pwdInfoPrefixLength);
+ }
+ else
+ {
+ return propertyName;
+ }
+ }
+ }
+
+ // The list of properties considered referential (they refer to or contain Principal objects)
+ //
+ // At present, referential properties are the following:
+ //
+ // Group.Members
+ //
+ internal class ReferentialProperties
+ {
+ private ReferentialProperties() { }
+
+ // Maps from Type of the Principal object --> ArrayList of the object's referential property names
+ // (expressed as strings from the PropertyNames class)
+ internal static readonly Hashtable Properties;
+
+ static ReferentialProperties()
+ {
+ Properties = new Hashtable();
+
+ // Referential properties for groups
+ ArrayList groupList = new ArrayList(1);
+ groupList.Add(PropertyNames.GroupMembers);
+
+ Properties[typeof(GroupPrincipal)] = groupList;
+
+ // Referential properties for users
+ // None at this time.
+
+ // Referential properties for computers
+ // None at this time.
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/exceptions.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/exceptions.cs
new file mode 100644
index 0000000000..1821a9d595
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/exceptions.cs
@@ -0,0 +1,357 @@
+// 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.Diagnostics;
+using System.Runtime.Serialization;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Security.Authentication;
+using System.Security.Permissions;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ [Serializable()]
+ abstract public class PrincipalException : SystemException
+ {
+ internal PrincipalException() : base() { }
+
+ internal PrincipalException(string message) : base(message) { }
+
+ internal PrincipalException(string message, Exception innerException) :
+ base(message, innerException)
+ { }
+
+ internal PrincipalException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ { }
+ }
+
+ [Serializable()]
+ public class MultipleMatchesException : PrincipalException
+ {
+ public MultipleMatchesException() : base() { }
+
+ public MultipleMatchesException(string message) : base(message) { }
+
+ public MultipleMatchesException(string message, Exception innerException) :
+ base(message, innerException)
+ { }
+
+ protected MultipleMatchesException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ { }
+ }
+
+ [Serializable()]
+ public class NoMatchingPrincipalException : PrincipalException
+ {
+ public NoMatchingPrincipalException() : base() { }
+
+ public NoMatchingPrincipalException(string message) : base(message) { }
+
+ public NoMatchingPrincipalException(string message, Exception innerException) :
+ base(message, innerException)
+ { }
+
+ protected NoMatchingPrincipalException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ { }
+ }
+
+ [Serializable()]
+ public class PasswordException : PrincipalException
+ {
+ public PasswordException() : base() { }
+
+ public PasswordException(string message) : base(message) { }
+
+ public PasswordException(string message, Exception innerException) :
+ base(message, innerException)
+ { }
+
+ protected PasswordException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ { }
+ }
+
+ [Serializable()]
+ public class PrincipalExistsException : PrincipalException
+ {
+ public PrincipalExistsException() : base() { }
+
+ public PrincipalExistsException(string message) : base(message) { }
+
+ public PrincipalExistsException(string message, Exception innerException) :
+ base(message, innerException)
+ { }
+
+ protected PrincipalExistsException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ { }
+ }
+
+ [Serializable()]
+ public class PrincipalServerDownException : PrincipalException
+ {
+ private int _errorCode = 0;
+ private string _serverName = null;
+
+ public PrincipalServerDownException() : base() { }
+
+ public PrincipalServerDownException(string message) : base(message) { }
+
+ public PrincipalServerDownException(string message, Exception innerException) :
+ base(message, innerException)
+ { }
+
+ public PrincipalServerDownException(string message, int errorCode) : base(message)
+ {
+ _errorCode = errorCode;
+ }
+ public PrincipalServerDownException(string message, Exception innerException, int errorCode) : base(message, innerException)
+ {
+ _errorCode = errorCode;
+ }
+ public PrincipalServerDownException(string message, Exception innerException, int errorCode, string serverName) : base(message, innerException)
+ {
+ _errorCode = errorCode;
+ _serverName = serverName;
+ }
+
+ protected PrincipalServerDownException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ {
+ _errorCode = info.GetInt32("errorCode");
+ _serverName = (string)info.GetValue("serverName", typeof(String));
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Exception.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ [SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("errorCode", _errorCode);
+ info.AddValue("serverName", _serverName, typeof(String));
+ base.GetObjectData(info, context);
+ }
+ }
+
+ [Serializable()]
+ public class PrincipalOperationException : PrincipalException
+ {
+ private int _errorCode = 0;
+
+ public PrincipalOperationException() : base() { }
+
+ public PrincipalOperationException(string message) : base(message) { }
+
+ public PrincipalOperationException(string message, Exception innerException) :
+ base(message, innerException)
+ { }
+
+ public PrincipalOperationException(string message, int errorCode) : base(message)
+ {
+ _errorCode = errorCode;
+ }
+ public PrincipalOperationException(string message, Exception innerException, int errorCode) : base(message, innerException)
+ {
+ _errorCode = errorCode;
+ }
+
+ protected PrincipalOperationException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ {
+ _errorCode = info.GetInt32("errorCode");
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Exception.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ [SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("errorCode", _errorCode);
+ base.GetObjectData(info, context);
+ }
+
+ public int ErrorCode
+ {
+ get
+ {
+ return _errorCode;
+ }
+ }
+ }
+
+ internal class ExceptionHelper
+ {
+ // Put a private constructor because this class should only be used as static methods
+ private ExceptionHelper() { }
+
+ private static int s_ERROR_NOT_ENOUGH_MEMORY = 8; // map to outofmemory exception
+ private static int s_ERROR_OUTOFMEMORY = 14; // map to outofmemory exception
+ private static int s_ERROR_DS_DRA_OUT_OF_MEM = 8446; // map to outofmemory exception
+ private static int s_ERROR_NO_SUCH_DOMAIN = 1355; // map to ActiveDirectoryServerDownException
+ private static int s_ERROR_ACCESS_DENIED = 5; // map to UnauthorizedAccessException
+ private static int s_ERROR_NO_LOGON_SERVERS = 1311; // map to ActiveDirectoryServerDownException
+ private static int s_ERROR_DS_DRA_ACCESS_DENIED = 8453; // map to UnauthorizedAccessException
+ private static int s_RPC_S_OUT_OF_RESOURCES = 1721; // map to outofmemory exception
+ internal static int RPC_S_SERVER_UNAVAILABLE = 1722; // map to ActiveDirectoryServerDownException
+ internal static int RPC_S_CALL_FAILED = 1726; // map to ActiveDirectoryServerDownException
+ // internal static int ERROR_DS_DRA_BAD_DN = 8439; //fix error CS0414: Warning as Error: is assigned but its value is never used
+ // internal static int ERROR_DS_NAME_UNPARSEABLE = 8350; //fix error CS0414: Warning as Error: is assigned but its value is never used
+ // internal static int ERROR_DS_UNKNOWN_ERROR = 8431; //fix error CS0414: Warning as Error: is assigned but its value is never used
+
+ // public static uint ERROR_HRESULT_ACCESS_DENIED = 0x80070005; //fix error CS0414: Warning as Error: is assigned but its value is never used
+ public static uint ERROR_HRESULT_LOGON_FAILURE = 0x8007052E;
+ public static uint ERROR_HRESULT_CONSTRAINT_VIOLATION = 0x8007202f;
+ public static uint ERROR_LOGON_FAILURE = 0x31;
+ // public static uint ERROR_LDAP_INVALID_CREDENTIALS = 49; //fix error CS0414: Warning as Error: is assigned but its value is never used
+ //
+ // This method maps some common COM Hresults to
+ // existing clr exceptions
+ //
+
+ internal static Exception GetExceptionFromCOMException(COMException e)
+ {
+ Exception exception;
+ int errorCode = e.ErrorCode;
+ string errorMessage = e.Message;
+
+ //
+ // Check if we can throw a more specific exception
+ //
+ if (errorCode == unchecked((int)0x80070005))
+ {
+ //
+ // Access Denied
+ //
+ exception = new UnauthorizedAccessException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x800708c5) || errorCode == unchecked((int)0x80070056) || errorCode == unchecked((int)0x8007052))
+ {
+ //
+ // Password does not meet complexity requirements or old password does not match or policy restriction has been enforced.
+ //
+ exception = new PasswordException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x800708b0) || errorCode == unchecked((int)0x80071392))
+ {
+ //
+ // Principal already exists
+ //
+ exception = new PrincipalExistsException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x8007052e))
+ {
+ //
+ // Logon Failure
+ //
+ exception = new AuthenticationException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x8007202f))
+ {
+ //
+ // Constraint Violation
+ //
+ exception = new InvalidOperationException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x80072035))
+ {
+ //
+ // Unwilling to perform
+ //
+ exception = new InvalidOperationException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x80070008))
+ {
+ //
+ // No Memory
+ //
+ exception = new OutOfMemoryException();
+ }
+ else if ((errorCode == unchecked((int)0x8007203a)) || (errorCode == unchecked((int)0x8007200e)) || (errorCode == unchecked((int)0x8007200f)))
+ {
+ exception = new PrincipalServerDownException(errorMessage, e, errorCode, null);
+ }
+ else
+ {
+ //
+ // Wrap the exception in a generic OperationException
+ //
+ exception = new PrincipalOperationException(errorMessage, e, errorCode);
+ }
+
+ return exception;
+ }
+
+ // <SecurityKernel Critical="True" Ring="2">
+ // <ReferencesCritical Name="Method: GetExceptionFromErrorCode(Int32, String):Exception" Ring="2" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ internal static Exception GetExceptionFromErrorCode(int errorCode)
+ {
+ return GetExceptionFromErrorCode(errorCode, null);
+ }
+
+ // <SecurityKernel Critical="True" Ring="1">
+ // <ReferencesCritical Name="Method: GetErrorMessage(Int32, Boolean):String" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static Exception GetExceptionFromErrorCode(int errorCode, string targetName)
+ {
+ string errorMsg = GetErrorMessage(errorCode, false);
+
+ if ((errorCode == s_ERROR_ACCESS_DENIED) || (errorCode == s_ERROR_DS_DRA_ACCESS_DENIED))
+
+ return new UnauthorizedAccessException(errorMsg);
+
+ else if ((errorCode == s_ERROR_NOT_ENOUGH_MEMORY) || (errorCode == s_ERROR_OUTOFMEMORY) || (errorCode == s_ERROR_DS_DRA_OUT_OF_MEM) || (errorCode == s_RPC_S_OUT_OF_RESOURCES))
+
+ return new OutOfMemoryException();
+
+ else if ((errorCode == s_ERROR_NO_LOGON_SERVERS) || (errorCode == s_ERROR_NO_SUCH_DOMAIN) || (errorCode == RPC_S_SERVER_UNAVAILABLE) || (errorCode == RPC_S_CALL_FAILED))
+ {
+ return new PrincipalServerDownException(errorMsg, errorCode);
+ }
+ else
+ {
+ return new PrincipalOperationException(errorMsg, errorCode);
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.FormatMessageW(System.Int32,System.IntPtr,System.Int32,System.Int32,System.Text.StringBuilder,System.Int32,System.IntPtr):System.Int32" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static string GetErrorMessage(int errorCode, bool hresult)
+ {
+ uint temp = (uint)errorCode;
+ if (!hresult)
+ {
+ temp = ((((temp) & 0x0000FFFF) | (7 << 16) | 0x80000000));
+ }
+ string errorMsg = "";
+ StringBuilder sb = new StringBuilder(256);
+ int result = UnsafeNativeMethods.FormatMessageW(UnsafeNativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS |
+ UnsafeNativeMethods.FORMAT_MESSAGE_FROM_SYSTEM |
+ UnsafeNativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ IntPtr.Zero, (int)temp, 0, sb, sb.Capacity + 1, IntPtr.Zero);
+ if (result != 0)
+ {
+ errorMsg = sb.ToString(0, result);
+ }
+ else
+ {
+ errorMsg = StringResources.DSUnknown + Convert.ToString(temp, 16);
+ }
+
+ return errorMsg;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/interopt.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/interopt.cs
new file mode 100644
index 0000000000..be7bbf7ea9
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/interopt.cs
@@ -0,0 +1,872 @@
+// 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.AccountManagement
+{
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+
+ internal class Constants
+ {
+ private Constants() { }
+ internal static Byte[] GUID_USERS_CONTAINER_BYTE = new Byte[] { 0xa9, 0xd1, 0xca, 0x15, 0x76, 0x88, 0x11, 0xd1, 0xad, 0xed, 0x00, 0xc0, 0x4f, 0xd8, 0xd5, 0xcd };
+ internal static Byte[] GUID_COMPUTRS_CONTAINER_BYTE = new Byte[] { 0xaa, 0x31, 0x28, 0x25, 0x76, 0x88, 0x11, 0xd1, 0xad, 0xed, 0x00, 0xc0, 0x4f, 0xd8, 0xd5, 0xcd };
+ internal static Byte[] GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER_BYTE = new Byte[] { 0x22, 0xb7, 0x0c, 0x67, 0xd5, 0x6e, 0x4e, 0xfb, 0x91, 0xe9, 0x30, 0x0f, 0xca, 0x3d, 0xc1, 0xaa };
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute]
+ internal class SafeNativeMethods
+ {
+ // To stop the compiler from autogenerating a constructor for this class
+ private SafeNativeMethods() { }
+
+ [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCurrentThreadId", CharSet = CharSet.Unicode)]
+ static extern public int GetCurrentThreadId();
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaNtStatusToWinError", CharSet = CharSet.Unicode)]
+ static extern public int LsaNtStatusToWinError(int ntStatus);
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute]
+ internal class UnsafeNativeMethods
+ {
+ // To stop the compiler from autogenerating a constructor for this class
+ private UnsafeNativeMethods() { }
+
+ [DllImport(ExternDll.Activeds, ExactSpelling = true, EntryPoint = "ADsOpenObject", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ private static extern int IntADsOpenObject(string path, string userName, string password, int flags, [In, Out] ref Guid iid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppObject);
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="IntADsOpenObject(String, String, String, Int32, Guid&, Object&):Int32" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ public static int ADsOpenObject(string path, string userName, string password, int flags, [In, Out] ref Guid iid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppObject)
+ {
+ try
+ {
+ return IntADsOpenObject(path, userName, password, flags, ref iid, out ppObject);
+ }
+ catch (EntryPointNotFoundException)
+ {
+ throw new InvalidOperationException(StringResources.AdsiNotInstalled);
+ }
+ }
+
+ //
+ // ADSI Interopt
+ //
+
+ internal enum ADS_PASSWORD_ENCODING_ENUM
+ {
+ ADS_PASSWORD_ENCODE_REQUIRE_SSL = 0,
+ ADS_PASSWORD_ENCODE_CLEAR = 1
+ }
+
+ internal enum ADS_OPTION_ENUM
+ {
+ ADS_OPTION_SERVERNAME = 0,
+ ADS_OPTION_REFERRALS = 1,
+ ADS_OPTION_PAGE_SIZE = 2,
+ ADS_OPTION_SECURITY_MASK = 3,
+ ADS_OPTION_MUTUAL_AUTH_STATUS = 4,
+ ADS_OPTION_QUOTA = 5,
+ ADS_OPTION_PASSWORD_PORTNUMBER = 6,
+ ADS_OPTION_PASSWORD_METHOD = 7,
+ ADS_OPTION_ACCUMULATIVE_MODIFICATION = 8,
+ ADS_OPTION_SKIP_SID_LOOKUP = 9
+ }
+
+ [ComImport, Guid("7E99C0A2-F935-11D2-BA96-00C04FB6D0D1"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ public interface IADsDNWithBinary
+ {
+ object BinaryValue { get; set; }
+ string DNString { get; set; }
+ }
+
+ [ComImport, Guid("9068270b-0939-11D1-8be1-00c04fd8d503"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ public interface IADsLargeInteger
+ {
+ int HighPart { get; set; }
+ int LowPart { get; set; }
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute]
+ [ComImport, Guid("927971f5-0939-11d1-8be1-00c04fd8d503")]
+ public class ADsLargeInteger
+ {
+ }
+
+ [ComImport, Guid("46f14fda-232b-11d1-a808-00c04fd8d5a8"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ public interface IAdsObjectOptions
+ {
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object GetOption(
+ [In]
+ int option);
+
+ void PutOption(
+ [In]
+ int option,
+ [In, MarshalAs(UnmanagedType.Struct)]
+ Object vProp);
+ }
+
+ [ComImport, Guid("FD8256D0-FD15-11CE-ABC4-02608C9E7553"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ public interface IADs
+ {
+ string Name
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Class
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string GUID
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string ADsPath
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Parent
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Schema
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ void GetInfo();
+
+ void SetInfo();
+
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object Get(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string bstrName);
+
+ void Put(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string bstrName,
+ [In, MarshalAs(UnmanagedType.Struct)]
+ Object vProp);
+
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object GetEx(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ String bstrName);
+
+ void PutEx(
+ [In, MarshalAs(UnmanagedType.U4)]
+ int lnControlCode,
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string bstrName,
+ [In, MarshalAs(UnmanagedType.Struct)]
+ Object vProp);
+
+ void GetInfoEx(
+ [In, MarshalAs(UnmanagedType.Struct)]
+ Object vProperties,
+ [In, MarshalAs(UnmanagedType.U4)]
+ int lnReserved);
+ }
+
+ [ComImport, Guid("27636b00-410f-11cf-b1ff-02608c9e7553"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ public interface IADsGroup
+ {
+ string Name
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Class
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string GUID
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string ADsPath
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Parent
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Schema
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ void GetInfo();
+
+ void SetInfo();
+
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object Get(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string bstrName);
+
+ void Put(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string bstrName,
+ [In, MarshalAs(UnmanagedType.Struct)]
+ Object vProp);
+
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object GetEx(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ String bstrName);
+
+ void PutEx(
+ [In, MarshalAs(UnmanagedType.U4)]
+ int lnControlCode,
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string bstrName,
+ [In, MarshalAs(UnmanagedType.Struct)]
+ Object vProp);
+
+ void GetInfoEx(
+ [In, MarshalAs(UnmanagedType.Struct)]
+ Object vProperties,
+ [In, MarshalAs(UnmanagedType.U4)]
+ int lnReserved);
+
+ string Description
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ IADsMembers Members();
+
+ bool IsMember([In, MarshalAs(UnmanagedType.BStr)] string bstrMember);
+
+ void Add([In, MarshalAs(UnmanagedType.BStr)] string bstrNewItem);
+
+ void Remove([In, MarshalAs(UnmanagedType.BStr)] string bstrItemToBeRemoved);
+ }
+
+ [ComImport, Guid("451a0030-72ec-11cf-b03b-00aa006e0975"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ public interface IADsMembers
+ {
+ int Count
+ {
+ [return: MarshalAs(UnmanagedType.U4)]
+ get;
+ }
+
+ object _NewEnum
+ {
+ [return: MarshalAs(UnmanagedType.Interface)]
+ get;
+ }
+
+ object Filter
+ {
+ [return: MarshalAs(UnmanagedType.Struct)]
+ get;
+ [param: MarshalAs(UnmanagedType.Struct)]
+ set;
+ }
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute]
+ [ComImport, Guid("080d0d78-f421-11d0-a36e-00c04fb950dc")]
+ public class Pathname
+ {
+ }
+
+ [ComImport, Guid("d592aed4-f420-11d0-a36e-00c04fb950dc"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ public interface IADsPathname
+ {
+ void Set(
+ [In, MarshalAs(UnmanagedType.BStr)] string bstrADsPath,
+ [In, MarshalAs(UnmanagedType.U4)] int lnSetType
+ );
+
+ void SetDisplayType(
+ [In, MarshalAs(UnmanagedType.U4)] int lnDisplayType
+ );
+
+ [return: MarshalAs(UnmanagedType.BStr)]
+ string Retrieve(
+ [In, MarshalAs(UnmanagedType.U4)] int lnFormatType
+ );
+
+ [return: MarshalAs(UnmanagedType.U4)]
+ int GetNumElements();
+
+ [return: MarshalAs(UnmanagedType.BStr)]
+ string
+ GetElement(
+ [In, MarshalAs(UnmanagedType.U4)] int lnElementIndex
+ );
+
+ void AddLeafElement(
+ [In, MarshalAs(UnmanagedType.BStr)] string bstrLeafElement
+ );
+
+ void RemoveLeafElement();
+
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object CopyPath();
+
+ [return: MarshalAs(UnmanagedType.BStr)]
+ string GetEscapedElement(
+ [In, MarshalAs(UnmanagedType.U4)] int lnReserved,
+ [In, MarshalAs(UnmanagedType.BStr)] string bstrInStr
+ );
+
+ int EscapedMode
+ {
+ [return: MarshalAs(UnmanagedType.U4)]
+ get;
+ [param: MarshalAs(UnmanagedType.U4)]
+ set;
+ }
+ }
+
+ //
+ // DSInteropt
+ //
+
+ /*
+ typedef enum
+ {
+ DsRole_RoleStandaloneWorkstation,
+ DsRole_RoleMemberWorkstation,
+ DsRole_RoleStandaloneServer,
+ DsRole_RoleMemberServer,
+ DsRole_RoleBackupDomainController,
+ DsRole_RolePrimaryDomainController,
+ DsRole_WorkstationWithSharedAccountDomain,
+ DsRole_ServerWithSharedAccountDomain,
+ DsRole_MemberWorkstationWithSharedAccountDomain,
+ DsRole_MemberServerWithSharedAccountDomain
+ }DSROLE_MACHINE_ROLE;
+ */
+
+ public enum DSROLE_MACHINE_ROLE
+ {
+ DsRole_RoleStandaloneWorkstation,
+ DsRole_RoleMemberWorkstation,
+ DsRole_RoleStandaloneServer,
+ DsRole_RoleMemberServer,
+ DsRole_RoleBackupDomainController,
+ DsRole_RolePrimaryDomainController,
+ DsRole_WorkstationWithSharedAccountDomain,
+ DsRole_ServerWithSharedAccountDomain,
+ DsRole_MemberWorkstationWithSharedAccountDomain,
+ DsRole_MemberServerWithSharedAccountDomain
+ }
+
+ /*
+ typedef enum
+ {
+ DsRolePrimaryDomainInfoBasic,
+ DsRoleUpgradeStatus,
+ DsRoleOperationState,
+ DsRolePrimaryDomainInfoBasicEx
+ }DSROLE_PRIMARY_DOMAIN_INFO_LEVEL;
+ */
+
+ public enum DSROLE_PRIMARY_DOMAIN_INFO_LEVEL
+ {
+ DsRolePrimaryDomainInfoBasic = 1,
+ DsRoleUpgradeStatus = 2,
+ DsRoleOperationState = 3,
+ DsRolePrimaryDomainInfoBasicEx = 4
+ }
+
+ /*
+ typedef struct _DSROLE_PRIMARY_DOMAIN_INFO_BASIC {
+ DSROLE_MACHINE_ROLE MachineRole;
+ ULONG Flags;
+ LPWSTR DomainNameFlat;
+ LPWSTR DomainNameDns;
+ LPWSTR DomainForestName;
+ GUID DomainGuid;
+ } DSROLE_PRIMARY_DOMAIN_INFO_BASIC, *PDSROLE_PRIMARY_DOMAIN_INFO_BASIC;
+ */
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class DSROLE_PRIMARY_DOMAIN_INFO_BASIC
+ {
+ public DSROLE_MACHINE_ROLE MachineRole;
+ public uint Flags;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string DomainNameFlat;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string DomainNameDns;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string DomainForestName;
+ public Guid DomainGuid = new Guid();
+ }
+
+ /*
+ DWORD DsRoleGetPrimaryDomainInformation(
+ LPCWSTR lpServer,
+ DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
+ PBYTE* Buffer
+ ); */
+
+ [DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsRoleGetPrimaryDomainInformation", CharSet = CharSet.Unicode)]
+ public static extern int DsRoleGetPrimaryDomainInformation(
+ [MarshalAs(UnmanagedType.LPTStr)] string lpServer,
+ [In] DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
+ out IntPtr Buffer);
+
+ [DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsRoleGetPrimaryDomainInformation", CharSet = CharSet.Unicode)]
+ public static extern int DsRoleGetPrimaryDomainInformation(
+ [In] IntPtr lpServer,
+ [In] DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
+ out IntPtr Buffer);
+
+ /*typedef struct _DOMAIN_CONTROLLER_INFO {
+ LPTSTR DomainControllerName;
+ LPTSTR DomainControllerAddress;
+ ULONG DomainControllerAddressType;
+ GUID DomainGuid;
+ LPTSTR DomainName;
+ LPTSTR DnsForestName;
+ ULONG Flags;
+ LPTSTR DcSiteName;
+ LPTSTR ClientSiteName;
+ } DOMAIN_CONTROLLER_INFO, *PDOMAIN_CONTROLLER_INFO; */
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class DomainControllerInfo
+ {
+ public string DomainControllerName = null;
+ public string DomainControllerAddress = null;
+ public int DomainControllerAddressType = 0;
+ public Guid DomainGuid = new Guid();
+ public string DomainName = null;
+ public string DnsForestName = null;
+ public int Flags = 0;
+ public string DcSiteName = null;
+ public string ClientSiteName = null;
+ }
+
+ /*
+ void DsRoleFreeMemory(
+ PVOID Buffer
+ );
+ */
+ [DllImport("Netapi32.dll")]
+ public static extern int DsRoleFreeMemory(
+ [In] IntPtr buffer);
+
+ /*DWORD DsGetDcName(
+ LPCTSTR ComputerName,
+ LPCTSTR DomainName,
+ GUID* DomainGuid,
+ LPCTSTR SiteName,
+ ULONG Flags,
+ PDOMAIN_CONTROLLER_INFO* DomainControllerInfo
+ );*/
+ [DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsGetDcNameW", CharSet = CharSet.Unicode)]
+ public static extern int DsGetDcName(
+ [In] string computerName,
+ [In] string domainName,
+ [In] IntPtr domainGuid,
+ [In] string siteName,
+ [In] int flags,
+ [Out] out IntPtr domainControllerInfo);
+
+ /* typedef struct _WKSTA_INFO_100 {
+ DWORD wki100_platform_id;
+ LMSTR wki100_computername;
+ LMSTR wki100_langroup;
+ DWORD wki100_ver_major;
+ DWORD wki100_ver_minor;
+ } WKSTA_INFO_100, *PWKSTA_INFO_100; */
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class WKSTA_INFO_100
+ {
+ public int wki100_platform_id = 0;
+ public string wki100_computername = null;
+ public string wki100_langroup = null;
+ public int wki100_ver_major = 0;
+ public int wki100_ver_minor = 0;
+ };
+
+ [DllImport("netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "NetWkstaGetInfo", CharSet = CharSet.Unicode)]
+ public static extern int NetWkstaGetInfo(string server, int level, ref IntPtr buffer);
+
+ [DllImport("Netapi32.dll")]
+ public static extern int NetApiBufferFree(
+ [In] IntPtr buffer);
+
+ //
+ // SID
+ //
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "ConvertSidToStringSidW", CharSet = CharSet.Unicode)]
+ public static extern bool ConvertSidToStringSid(IntPtr sid, ref string stringSid);
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ConvertStringSidToSidW", CharSet = CharSet.Unicode)]
+ public static extern bool ConvertStringSidToSid(string stringSid, ref IntPtr sid);
+
+ [DllImport("advapi32.dll")]
+ public static extern int GetLengthSid(IntPtr sid);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ public static extern bool IsValidSid(IntPtr sid);
+
+ [DllImport("advapi32.dll")]
+ public static extern IntPtr GetSidIdentifierAuthority(IntPtr sid);
+
+ [DllImport("advapi32.dll")]
+ public static extern IntPtr GetSidSubAuthority(IntPtr sid, int index);
+
+ [DllImport("advapi32.dll")]
+ public static extern IntPtr GetSidSubAuthorityCount(IntPtr sid);
+
+ [DllImport("advapi32.dll")]
+ public static extern bool EqualDomainSid(IntPtr pSid1, IntPtr pSid2, ref bool equal);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ public static extern bool CopySid(int destinationLength, IntPtr pSidDestination, IntPtr pSidSource);
+
+ [DllImport("kernel32.dll")]
+ public static extern IntPtr LocalFree(IntPtr ptr);
+
+ [DllImport("Credui.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "CredUIParseUserNameW", CharSet = CharSet.Unicode)]
+ public static extern int CredUIParseUserName(
+ string pszUserName,
+ StringBuilder pszUser,
+ System.UInt32 ulUserMaxChars,
+ StringBuilder pszDomain,
+ System.UInt32 ulDomainMaxChars
+ );
+
+ // These contants were taken from the wincred.h file
+ public const int CRED_MAX_USERNAME_LENGTH = 514;
+ public const int CRED_MAX_DOMAIN_TARGET_LENGTH = 338;
+
+ /*
+ BOOL LookupAccountSid(
+ LPCTSTR lpSystemName,
+ PSID lpSid,
+ LPTSTR lpName,
+ LPDWORD cchName,
+ LPTSTR lpReferencedDomainName,
+ LPDWORD cchReferencedDomainName,
+ PSID_NAME_USE peUse
+ );
+
+ */
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "LookupAccountSidW", CharSet = CharSet.Unicode)]
+ public static extern bool LookupAccountSid(
+ string computerName,
+ IntPtr sid,
+ StringBuilder name,
+ ref int nameLength,
+ StringBuilder domainName,
+ ref int domainNameLength,
+ ref int usage);
+
+ //
+ // AuthZ functions
+ //
+
+ internal sealed class AUTHZ_RM_FLAG
+ {
+ private AUTHZ_RM_FLAG() { }
+ public static int AUTHZ_RM_FLAG_NO_AUDIT = 0x1;
+ public static int AUTHZ_RM_FLAG_INITIALIZE_UNDER_IMPERSONATION = 0x2;
+ public static int AUTHZ_VALID_RM_INIT_FLAGS = (AUTHZ_RM_FLAG_NO_AUDIT | AUTHZ_RM_FLAG_INITIALIZE_UNDER_IMPERSONATION);
+ }
+
+ [DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeResourceManager", CharSet = CharSet.Unicode)]
+ static extern public bool AuthzInitializeResourceManager(
+ int flags,
+ IntPtr pfnAccessCheck,
+ IntPtr pfnComputeDynamicGroups,
+ IntPtr pfnFreeDynamicGroups,
+ string name,
+ out IntPtr rm
+ );
+
+ /*
+ BOOL WINAPI AuthzInitializeContextFromSid(
+ DWORD Flags,
+ PSID UserSid,
+ AUTHZ_RESOURCE_MANAGER_HANDLE AuthzResourceManager,
+ PLARGE_INTEGER pExpirationTime,
+ LUID Identifier,
+ PVOID DynamicGroupArgs,
+ PAUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContext
+ );
+ */
+ [DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeContextFromSid", CharSet = CharSet.Unicode)]
+ static extern public bool AuthzInitializeContextFromSid(
+ int Flags,
+ IntPtr UserSid,
+ IntPtr AuthzResourceManager,
+ IntPtr pExpirationTime,
+ LUID Identitifier,
+ IntPtr DynamicGroupArgs,
+ out IntPtr pAuthzClientContext
+ );
+
+ /*
+ [DllImport("authz.dll", SetLastError=true, CallingConvention=CallingConvention.StdCall, EntryPoint="AuthzInitializeContextFromToken", CharSet=CharSet.Unicode)]
+ static extern public bool AuthzInitializeContextFromToken(
+ int Flags,
+ IntPtr TokenHandle,
+ IntPtr AuthzResourceManager,
+ IntPtr pExpirationTime,
+ LUID Identitifier,
+ IntPtr DynamicGroupArgs,
+ out IntPtr pAuthzClientContext
+ );
+ */
+ [DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzGetInformationFromContext", CharSet = CharSet.Unicode)]
+ static extern public bool AuthzGetInformationFromContext(
+ IntPtr hAuthzClientContext,
+ int InfoClass,
+ int BufferSize,
+ out int pSizeRequired,
+ IntPtr Buffer
+ );
+
+ [DllImport("authz.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzFreeContext", CharSet = CharSet.Unicode)]
+ static extern public bool AuthzFreeContext(
+ IntPtr AuthzClientContext
+ );
+
+ [DllImport("authz.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzFreeResourceManager", CharSet = CharSet.Unicode)]
+ static extern public bool AuthzFreeResourceManager(
+ IntPtr rm
+ );
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public struct LUID
+ {
+ public int low;
+ public int high;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class TOKEN_GROUPS
+ {
+ public int groupCount = 0;
+ public IntPtr groups = IntPtr.Zero;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class SID_AND_ATTR
+ {
+ public IntPtr pSid = IntPtr.Zero;
+ public int attrs = 0;
+ }
+
+ //
+ // Token
+ //
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class TOKEN_USER
+ {
+ public SID_AND_ATTR sidAndAttributes = new SID_AND_ATTR();
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class SID_IDENTIFIER_AUTHORITY
+ {
+ public byte b1 = 0;
+ public byte b2 = 0;
+ public byte b3 = 0;
+ public byte b4 = 0;
+ public byte b5 = 0;
+ public byte b6 = 0;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class LSA_OBJECT_ATTRIBUTES
+ {
+ public int length = 0;
+ public IntPtr rootDirectory = IntPtr.Zero;
+ public IntPtr objectName = IntPtr.Zero;
+ public int attributes = 0;
+ public IntPtr securityDescriptor = IntPtr.Zero;
+ public IntPtr securityQualityOfService = IntPtr.Zero;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class POLICY_ACCOUNT_DOMAIN_INFO
+ {
+ public LSA_UNICODE_STRING domainName = new LSA_UNICODE_STRING();
+ public IntPtr domainSid = IntPtr.Zero;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class LSA_UNICODE_STRING
+ {
+ public ushort length = 0;
+ public ushort maximumLength = 0;
+ public IntPtr buffer = IntPtr.Zero;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class LSA_UNICODE_STRING_Managed
+ {
+ public ushort length = 0;
+ public ushort maximumLength = 0;
+ public string buffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class LSA_TRANSLATED_NAME
+ {
+ public int use = 0;
+ public LSA_UNICODE_STRING name = new LSA_UNICODE_STRING();
+ public int domainIndex = 0;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class LSA_REFERENCED_DOMAIN_LIST
+ {
+ // To stop the compiler from autogenerating a constructor for this class
+ private LSA_REFERENCED_DOMAIN_LIST() { }
+
+ public int entries = 0;
+ public IntPtr domains = IntPtr.Zero;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public sealed class LSA_TRUST_INFORMATION
+ {
+ public LSA_UNICODE_STRING name = new LSA_UNICODE_STRING();
+ private IntPtr _pSid = IntPtr.Zero;
+ }
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "OpenThreadToken", CharSet = CharSet.Unicode)]
+ static extern public bool OpenThreadToken(
+ IntPtr threadHandle,
+ int desiredAccess,
+ bool openAsSelf,
+ ref IntPtr tokenHandle
+ );
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "OpenProcessToken", CharSet = CharSet.Unicode)]
+ static extern public bool OpenProcessToken(
+ IntPtr processHandle,
+ int desiredAccess,
+ ref IntPtr tokenHandle
+ );
+
+ [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "CloseHandle", CharSet = CharSet.Unicode)]
+ static extern public bool CloseHandle(IntPtr handle);
+
+ [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCurrentThread", CharSet = CharSet.Unicode)]
+ static extern public IntPtr GetCurrentThread();
+
+ [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCurrentProcess", CharSet = CharSet.Unicode)]
+ static extern public IntPtr GetCurrentProcess();
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "GetTokenInformation", CharSet = CharSet.Unicode)]
+ static extern public bool GetTokenInformation(
+ IntPtr tokenHandle,
+ int tokenInformationClass,
+ IntPtr buffer,
+ int bufferSize,
+ ref int returnLength
+ );
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaOpenPolicy", CharSet = CharSet.Unicode)]
+ static extern public int LsaOpenPolicy(
+ IntPtr lsaUnicodeString,
+ IntPtr lsaObjectAttributes,
+ int desiredAccess,
+ ref IntPtr policyHandle);
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaQueryInformationPolicy", CharSet = CharSet.Unicode)]
+ static extern public int LsaQueryInformationPolicy(
+ IntPtr policyHandle,
+ int policyInformationClass,
+ ref IntPtr buffer
+ );
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaLookupSids", CharSet = CharSet.Unicode)]
+ public static extern int LsaLookupSids(
+ IntPtr policyHandle,
+ int count,
+ IntPtr[] sids,
+ out IntPtr referencedDomains,
+ out IntPtr names
+ );
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaFreeMemory", CharSet = CharSet.Unicode)]
+ static extern public int LsaFreeMemory(IntPtr buffer);
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaClose", CharSet = CharSet.Unicode)]
+ static extern public int LsaClose(IntPtr policyHandle);
+
+ //
+ // Impersonation
+ //
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "LogonUserW", CharSet = CharSet.Unicode)]
+ static extern public int LogonUser(
+ string lpszUsername,
+ string lpszDomain,
+ string lpszPassword,
+ int dwLogonType,
+ int dwLogonProvider,
+ ref IntPtr phToken);
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "ImpersonateLoggedOnUser", CharSet = CharSet.Unicode)]
+ static extern public int ImpersonateLoggedOnUser(IntPtr hToken);
+
+ [DllImport("Advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "RevertToSelf", CharSet = CharSet.Unicode)]
+ static extern public int RevertToSelf();
+
+ public const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100,
+ FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200,
+ FORMAT_MESSAGE_FROM_STRING = 0x00000400,
+ FORMAT_MESSAGE_FROM_HMODULE = 0x00000800,
+ FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000,
+ FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000,
+ FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF;
+
+ [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ public static extern int FormatMessageW(int dwFlags, IntPtr lpSource, int dwMessageId,
+ int dwLanguageId, StringBuilder lpBuffer, int nSize, IntPtr arguments);
+ }
+}
+
diff --git a/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/testobj.cs b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/testobj.cs
new file mode 100644
index 0000000000..0292d2b0a0
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/testobj.cs
@@ -0,0 +1,426 @@
+#if TESTHOOK
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ public class TestHook
+ {
+ static public void TestADStoreKeys()
+ {
+ // GUID-based ADStoreKeys
+ Guid adGuid1 = Guid.NewGuid();
+ Guid adGuid2 = Guid.NewGuid();
+
+ ADStoreKey key1a = new ADStoreKey(adGuid1);
+ ADStoreKey key1b = new ADStoreKey(adGuid1);
+ ADStoreKey key2 = new ADStoreKey(adGuid2);
+
+ Debug.Assert(key1a.Equals(key1b));
+ Debug.Assert(!key1a.Equals(key2));
+
+ Debug.Assert(key1a.GetHashCode() == key1b.GetHashCode());
+ Debug.Assert(key1a.GetHashCode() != key2.GetHashCode());
+
+ // SID-based ADStoreKeys
+ string mach1 = "machine1";
+ string mach1a = "machine1";
+ string mach2 = "machine2";
+
+ byte[] sid1a = new byte[]{0x1, 0x2, 0x3};
+ byte[] sid1b = new byte[]{0x1, 0x2, 0x3};
+ byte[] sid2 = new byte[]{0x10, 0x20, 0x30};
+
+ ADStoreKey key3a = new ADStoreKey(mach1, sid1a);
+ ADStoreKey key3b = new ADStoreKey(mach1, sid1a);
+ ADStoreKey key3c = new ADStoreKey(mach1a, sid1b);
+ ADStoreKey key4 = new ADStoreKey(mach2, sid2);
+ ADStoreKey key5 = new ADStoreKey(mach1, sid2);
+
+ Debug.Assert(key3a.Equals(key3b));
+ Debug.Assert(key3a.Equals(key3c));
+
+ Debug.Assert(!key3a.Equals(key4));
+ Debug.Assert(!key3a.Equals(key5));
+
+ Debug.Assert(!key3a.Equals(key1a));
+ Debug.Assert(!key1a.Equals(key3a));
+
+ Debug.Assert(key3a.GetHashCode() != key4.GetHashCode());
+
+ // Shouldn't matter, since SAMStoreKey should make a copy of the byte[] sid
+ sid1b[1] = 0xf;
+ Debug.Assert(key3a.Equals(key3b));
+ Debug.Assert(key3a.Equals(key3c));
+
+ }
+
+ static public void TestSAMStoreKeys()
+ {
+ string mach1 = "machine1";
+ string mach1a = "machine1";
+ string mach2 = "machine2";
+
+ byte[] sid1a = new byte[]{0x1, 0x2, 0x3};
+ byte[] sid1b = new byte[]{0x1, 0x2, 0x3};
+ byte[] sid2 = new byte[]{0x10, 0x20, 0x30};
+
+ SAMStoreKey key1a = new SAMStoreKey(mach1, sid1a);
+ SAMStoreKey key1b = new SAMStoreKey(mach1, sid1a);
+ SAMStoreKey key1c = new SAMStoreKey(mach1a, sid1b);
+ SAMStoreKey key2 = new SAMStoreKey(mach2, sid2);
+ SAMStoreKey key3 = new SAMStoreKey(mach1, sid2);
+
+ Debug.Assert(key1a.Equals(key1b));
+ Debug.Assert(key1a.Equals(key1c));
+
+ Debug.Assert(!key1a.Equals(key2));
+ Debug.Assert(!key1a.Equals(key3));
+
+ Debug.Assert(key1a.GetHashCode() != key2.GetHashCode());
+
+ // Shouldn't matter, since SAMStoreKey should make a copy of the byte[] sid
+ sid1b[1] = 0xf;
+ Debug.Assert(key1a.Equals(key1b));
+ Debug.Assert(key1a.Equals(key1c));
+
+ }
+
+ //
+ // ValueCollection
+ //
+ static public PrincipalValueCollection<T> ValueCollectionConstruct<T>()
+ {
+ return new PrincipalValueCollection<T>();
+ }
+
+ static public void ValueCollectionLoad<T>(PrincipalValueCollection<T> trackList, List<T> initial)
+ {
+ trackList.Load(initial);
+ }
+
+ static public List<T> ValueCollectionInserted<T>(PrincipalValueCollection<T> trackList)
+ {
+ return trackList.Inserted;
+ }
+
+ static public List<T> ValueCollectionRemoved<T>(PrincipalValueCollection<T> trackList)
+ {
+ return trackList.Removed;
+ }
+
+ static public List<T> ValueCollectionChangedValues<T>(PrincipalValueCollection<T> trackList, out List<T> rightOut)
+ {
+ // We'd like to just return the List<Pair<T,T>>, but Pair<T,T> isn't a public class
+ List<T> left = new List<T>();
+ List<T> right = new List<T>();
+ List<Pair<T,T>> pairList = trackList.ChangedValues;
+
+ foreach (Pair<T,T> pair in pairList)
+ {
+ left.Add(pair.Left);
+ right.Add(pair.Right);
+ }
+
+ rightOut = right;
+ return left;
+ }
+
+ static public bool ValueCollectionChanged<T>(PrincipalValueCollection<T> trackList)
+ {
+ return trackList.Changed;
+ }
+
+ static public void ValueCollectionResetTracking<T>(PrincipalValueCollection<T> trackList)
+ {
+ trackList.ResetTracking();
+ }
+
+ //
+ // IdentityClaimCollection
+ //
+ static public IdentityClaimCollection ICCConstruct()
+ {
+ Group g = new Group();
+ return new IdentityClaimCollection(g);
+ }
+
+ static public IdentityClaimCollection ICCConstruct2()
+ {
+ Group g = new Group();
+ g.Context = PrincipalContext.Test;
+ return new IdentityClaimCollection(g);
+ }
+
+ static public IdentityClaimCollection ICCConstructAlt()
+ {
+ Group g = new Group();
+ g.Context = PrincipalContext.TestAltValidation;
+ return new IdentityClaimCollection(g);
+ }
+
+ static public IdentityClaimCollection ICCConstructNoTimeLimited()
+ {
+ Group g = new Group();
+ g.Context = PrincipalContext.TestNoTimeLimited;
+ return new IdentityClaimCollection(g);
+ }
+
+ static public void ICCLoad(IdentityClaimCollection trackList, List<IdentityClaim> initial)
+ {
+ trackList.Load(initial);
+ }
+
+ static public List<IdentityClaim> ICCInserted(IdentityClaimCollection trackList)
+ {
+ return trackList.Inserted;
+ }
+
+ static public List<IdentityClaim> ICCRemoved(IdentityClaimCollection trackList)
+ {
+ return trackList.Removed;
+ }
+
+ static public List<IdentityClaim> ICCChangedValues(IdentityClaimCollection trackList, out List<IdentityClaim> rightOut)
+ {
+ // We'd like to just return the List<Pair<T,T>>, but Pair<T,T> isn't a public class
+ List<IdentityClaim> left = new List<IdentityClaim>();
+ List<IdentityClaim> right = new List<IdentityClaim>();
+ List<Pair<IdentityClaim,IdentityClaim>> pairList = trackList.ChangedValues;
+
+ foreach (Pair<IdentityClaim,IdentityClaim> pair in pairList)
+ {
+ left.Add(pair.Left);
+ right.Add(pair.Right);
+ }
+
+ rightOut = right;
+ return left;
+ }
+
+ static public bool ICCChanged(IdentityClaimCollection trackList)
+ {
+ return trackList.Changed;
+ }
+
+ static public void ICCResetTracking(IdentityClaimCollection trackList)
+ {
+ trackList.ResetTracking();
+ }
+
+ //
+ // PrincipalCollection
+ //
+ static public Group MakeAGroup(string s)
+ {
+ Group g = new Group(PrincipalContext.Test);
+ g.DisplayName = s;
+ g.Key = new TestStoreKey(s);
+ return g;
+ }
+
+ static public PrincipalCollection MakePrincipalCollection()
+ {
+ BookmarkableResultSet rs = PrincipalContext.Test.QueryCtx.GetGroupMembership(null, false);
+ PrincipalCollection mc = new PrincipalCollection(rs, new Group());
+ return mc;
+ }
+
+ static public List<Principal> MCInserted(PrincipalCollection trackList)
+ {
+ return trackList.Inserted;
+ }
+
+ static public List<Principal> MCRemoved(PrincipalCollection trackList)
+ {
+ return trackList.Removed;
+ }
+
+ static public bool MCChanged(PrincipalCollection trackList)
+ {
+ return trackList.Changed;
+ }
+
+ static public void MCResetTracking(PrincipalCollection trackList)
+ {
+ trackList.ResetTracking();
+ }
+
+ //
+ // AuthenticablePrincipal
+ //
+ static public User APGetNoninsertedAP()
+ {
+ User u = new User(PrincipalContext.Test);
+ u.unpersisted = false;
+ return u;
+ }
+
+ static public void APInitNested(AuthenticablePrincipal ap)
+ {
+ ap.LoadValueIntoProperty(PropertyNames.PwdInfoCannotChangePassword, true);
+ ap.LoadValueIntoProperty(PropertyNames.AcctInfoBadLogonCount, 3);
+ }
+
+ static public void APLoadValue(AuthenticablePrincipal ap, string name, object value)
+ {
+ ap.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool APGetChangeStatus(AuthenticablePrincipal ap, string name)
+ {
+ return ap.GetChangeStatusForProperty(name);
+ }
+
+ static public object APGetValue(AuthenticablePrincipal ap, string name)
+ {
+ return ap.GetValueForProperty(name);
+ }
+
+ static public void APResetChanges(AuthenticablePrincipal ap)
+ {
+ ap.ResetAllChangeStatus();
+ }
+
+ //
+ // PasswordInfo
+ //
+ static public PasswordInfo ExtractPI(AuthenticablePrincipal ap)
+ {
+ Type t = typeof(AuthenticablePrincipal);
+
+ return (PasswordInfo) t.InvokeMember(
+ "PasswordInfo",
+ BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,
+ null,
+ ap,
+ new object[]{},
+ CultureInfo.InvariantCulture);
+ }
+
+ static public void PILoadValue(PasswordInfo pi, string name, object value)
+ {
+ pi.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool PIGetChangeStatus(PasswordInfo pi, string name)
+ {
+ return pi.GetChangeStatusForProperty(name);
+ }
+
+ static public object PIGetValue(PasswordInfo pi, string name)
+ {
+ return pi.GetValueForProperty(name);
+ }
+
+ static public void PIResetChanges(PasswordInfo pi)
+ {
+ pi.ResetAllChangeStatus();
+ }
+
+ //
+ // AccountInfo
+ //
+ static public AccountInfo ExtractAI(AuthenticablePrincipal ap)
+ {
+ Type t = typeof(AuthenticablePrincipal);
+
+ return (AccountInfo) t.InvokeMember(
+ "AccountInfo",
+ BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,
+ null,
+ ap,
+ new object[]{},
+ CultureInfo.InvariantCulture);
+ }
+
+ static public void AILoadValue(AccountInfo ai, string name, object value)
+ {
+ ai.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool AIGetChangeStatus(AccountInfo ai, string name)
+ {
+ return ai.GetChangeStatusForProperty(name);
+ }
+
+ static public object AIGetValue(AccountInfo ai, string name)
+ {
+ return ai.GetValueForProperty(name);
+ }
+
+ static public void AIResetChanges(AccountInfo ai)
+ {
+ ai.ResetAllChangeStatus();
+ }
+
+ //
+ // User
+ //
+ static public void UserLoadValue(User u, string name, object value)
+ {
+ u.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool UserGetChangeStatus(User u, string name)
+ {
+ return u.GetChangeStatusForProperty(name);
+ }
+
+ static public object UserGetValue(User u, string name)
+ {
+ return u.GetValueForProperty(name);
+ }
+
+ static public void UserResetChanges(User u)
+ {
+ u.ResetAllChangeStatus();
+ }
+
+ static public Group GroupGetNonInsertedGroup()
+ {
+ Group g = new Group(PrincipalContext.Test);
+ g.unpersisted = false;
+ return g;
+ }
+
+ //
+ // Computer
+ //
+ static public void ComputerLoadValue(Computer computer, string name, object value)
+ {
+ computer.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool ComputerGetChangeStatus(Computer computer, string name)
+ {
+ return computer.GetChangeStatusForProperty(name);
+ }
+
+ static public object ComputerGetValue(Computer computer, string name)
+ {
+ return computer.GetValueForProperty(name);
+ }
+
+ static public void ComputerResetChanges(Computer computer)
+ {
+ computer.ResetAllChangeStatus();
+ }
+
+ //
+ // QBE
+ //
+ static public void BuildQbeFilter(Principal p)
+ {
+ PrincipalContext ctx = PrincipalContext.Test;
+ ((TestStoreCtx)ctx.QueryCtx).CallBuildQbeFilterDescription(p);
+ }
+ }
+
+}
+
+#endif // TESTHOOK
diff --git a/src/System.DirectoryServices.AccountManagement/tests/AuthoringTests.txt b/src/System.DirectoryServices.AccountManagement/tests/AuthoringTests.txt
new file mode 100644
index 0000000000..8035b87c8b
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/AuthoringTests.txt
@@ -0,0 +1,135 @@
+==========================================================================
+ Visual Studio Team System: Overview of Authoring and Running Tests
+==========================================================================
+
+This overview describes the features for authoring and running tests in
+Visual Studio Team System and Visual Studio Team Edition for Software Testers.
+
+Opening Tests
+-------------
+To open a test, open a test project or a test metadata file (a file with
+extension .vsmdi) that contains the definition of the test. You can find
+test projects and metadata files in Solution Explorer.
+
+Viewing Tests
+-------------
+To see which tests are available to you, open the Test View window. Or,
+if you have installed Team Edition for Software Testers, you can also open
+the Test List Editor window to view tests.
+
+To open the Test View window, click the Test menu, point to Windows, and
+then click Test View. To open the Test List Editor window (if you have
+installed Team Edition for Software Testers), click Test, point to Windows,
+and then click Test List Editor.
+
+Running Tests
+-------------
+You can run tests from the Test View window and the Test List Editor window.
+See Viewing Tests to learn how to open these windows. To run one or more
+tests displayed in the Test View window, first select the tests in that
+window; to select multiple tests, hold either the Shift or CTRL key while
+clicking tests. Then click the Run Tests button in the Test View window
+toolbar.
+
+If you have installed Visual Studio Team Edition for Software Testers, you can
+also use the Test List Editor window to run tests. To run tests in Test List Editor,
+select the check box next to each test that you want to run. Then click the
+Run Tests button in the Test List Editor window toolbar.
+
+Viewing Test Results
+--------------------
+When you run a test or a series of tests, the results of the test run will be
+shown in the Test Results window. Each individual test in the run is shown on
+a separate line so that you can see its status. The window contains an
+embedded status bar in the top half of the window that provides you with
+summary details of the complete test run.
+
+To see more detailed results for a particular test result, double-click it in
+the Test Results window. This opens a window that provides more information
+about the particular test result, such as any specific error messages returned
+by the test.
+
+Changing the way that tests are run
+-----------------------------------
+Each time you run one or more tests, a collection of settings is used to
+determine how those tests are run. These settings are contained in a “test
+settings” file.
+
+Here is a partial list of the changes you can make with a test settings file:
+
+ - Change the naming scheme for each test run.
+ - Change the test controller that the tests are run on so that you can run
+ tests remotely.
+ - Gather code coverage data for the code being tested so that you can see
+ which lines of code are covered by your tests.
+ - Enable and disable test deployment.
+ - Specify additional files to deploy before tests are run.
+ - Select a different host, ASP.NET, for running ASP.NET unit tests.
+ - Select a different host, the smart device test host, for running smart device unit tests.
+ - Set various properties for the test agents that run your tests.
+ - Specify to use data collectors that can collect various information as
+ the tests are running.
+ - Run custom scripts at the start and end of each test run so that you can
+ set up the test environment exactly as required each time tests are run.
+ - Set time limits for tests and test runs.
+ - Set the browser mix and the number of times to repeat Web tests in the
+ test run.
+
+By default, a test settings file is created whenever you create a new test
+project. You make changes to this file by double-clicking it in Solution
+Explorer and then changing the test settings. (Test settings files have the
+extension .testsettings.)
+
+A solution can contain multiple test settings files. Only one of those
+files, known as the “Active” test settings file, is used to determine the
+settings that are currently used for test runs. You select the active test
+settings by clicking Select Active Test Settings on the Test menu.
+
+-------------------------------------------------------------------------------
+
+Test Types
+----------
+Using Visual Studio Team Edition for Software Testers, you can create a number
+of different test types:
+
+Unit test: Use a unit test to create a programmatic test in C++, Visual C# or
+Visual Basic that exercises source code. A unit test calls the methods of a
+class, passing suitable parameters, and verifies that the returned value is
+what you expect.
+There are three specialized variants of unit tests:
+ - Data-driven unit tests are created when you configure a unit test to be
+ called repeatedly for each row of a data source. The data from each row
+ is used by the unit test as input data.
+ - ASP.NET unit tests are unit tests that exercise code in an ASP.NET Web
+ application.
+ - Smart device unit tests are unit tests that are deployed to a smart device
+ or emulator and then executed by the smart device test host.
+
+Web Test: Web tests consist of an ordered series of HTTP requests that you
+record in a browser session using Microsoft Internet Explorer. You can have
+the test report specific details about the pages or sites it requests, such
+as whether a particular page contains a specified string.
+
+Load Test: You use a load test to encapsulate non-manual tests, such as
+unit, Web, and generic tests, and then run them simultaneously by using
+virtual users. Running these tests under load generates test results,
+including performance and other counters, in tables and in graphs.
+
+Generic test: A generic test is an existing program wrapped to function as a
+test in Visual Studio. The following are examples of tests or programs that
+you can turn into generic tests:
+ - An existing test that uses process exit codes to communicate whether the
+ test passed or failed. 0 indicates passing and any other value indicates
+ a failure.
+ - A general program to obtain specific functionality during a test scenario.
+ - A test or program that uses a special XML file (called a “summary results
+ file”), to communicate detailed results.
+
+Manual test: The manual test type is used when the test tasks are to be
+completed by a test engineer as opposed to an automated script.
+
+Ordered test: Use an ordered test to execute a set of tests in an order you
+specify.
+
+-------------------------------------------------------------------------------
+
diff --git a/src/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs b/src/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs
new file mode 100644
index 0000000000..fbc978cfab
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs
@@ -0,0 +1,76 @@
+// 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.DirectoryServices.AccountManagement;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace AccountManagementUnitTests
+{
+ /// <summary>
+ ///This is a test class for ComputerPrincipalTest and is intended
+ ///to contain all ComputerPrincipalTest Unit Tests
+ ///</summary>
+ [TestClass()]
+ public class ComputerPrincipalTest : PrincipalTest
+ {
+ #region Additional test attributes
+ //
+ //You can use the following additional attributes as you write your tests:
+ //
+ //Use ClassInitialize to run code before running the first test in the class
+ //[ClassInitialize()]
+ //public static void MyClassInitialize(TestContext testContext)
+ //{
+ //}
+ //
+ //Use ClassCleanup to run code after all tests in a class have run
+ //[ClassCleanup()]
+ //public static void MyClassCleanup()
+ //{
+ //}
+ //
+ //Use TestInitialize to run code before running each test
+ //[TestInitialize()]
+ //public void MyTestInitialize()
+ //{
+ //}
+ //
+ //Use TestCleanup to run code after each test has run
+ //[TestCleanup()]
+ //public void MyTestCleanup()
+ //{
+ //}
+ //
+ #endregion
+
+ /// <summary>
+ ///A test for ComputerPrincipal Constructor
+ ///</summary>
+ [TestMethod()]
+ public void ComputerPrincipalConstructorTest()
+ {
+ ComputerPrincipal computer = new ComputerPrincipal(domainContext);
+ computer.Dispose();
+ Assert.Inconclusive("TODO: Implement code to verify target");
+ }
+
+ internal override Principal CreatePrincipal(PrincipalContext context, string name)
+ {
+ ComputerPrincipal computer = new ComputerPrincipal(context);
+ computer.Name = name;
+ return computer;
+ }
+
+ internal override Principal CreateExtendedPrincipal(PrincipalContext context, string name)
+ {
+ Assert.Inconclusive("TODO: Implement code to verify target");
+ throw new System.NotImplementedException();
+ }
+
+ internal override Principal FindExtendedPrincipal(PrincipalContext context, string name)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs b/src/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs
new file mode 100644
index 0000000000..eb74f28ef6
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs
@@ -0,0 +1,69 @@
+// 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.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.DirectoryServices.AccountManagement;
+
+namespace AccountManagementUnitTests
+{
+ [DirectoryRdnPrefix("CN")]
+ [DirectoryObjectClass("User")]
+ public class ExtendedUserPrincipal : UserPrincipal, IExtendedPrincipalTest
+ {
+ public ExtendedUserPrincipal(PrincipalContext context)
+ : base(context)
+ {
+ }
+
+ // Implement the overloaded search method FindByIdentity.
+ public static new ExtendedUserPrincipal FindByIdentity(PrincipalContext context,
+ string identityValue)
+ {
+ return (ExtendedUserPrincipal)FindByIdentityWithType(context,
+ typeof(ExtendedUserPrincipal),
+ identityValue);
+ }
+
+ [DirectoryProperty("jpegPhoto")]
+ public byte[] ByteArrayExtension
+ {
+ get
+ {
+ return (byte[])this.ExtensionGet("jpegPhoto")[0];
+ }
+
+ set
+ {
+ this.ExtensionSet("jpegPhoto", value);
+ }
+ }
+
+ public object ObjectExtension
+ {
+ get
+ {
+ throw new System.NotImplementedException();
+ }
+ set
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+
+ public object[] ObjectArrayExtension
+ {
+ get
+ {
+ throw new System.NotImplementedException();
+ }
+ set
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs b/src/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs
new file mode 100644
index 0000000000..a8589c12a5
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs
@@ -0,0 +1,110 @@
+// 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.DirectoryServices.AccountManagement;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+
+namespace AccountManagementUnitTests
+{
+ /// <summary>
+ ///This is a test class for GroupPrincipalTest and is intended
+ ///to contain all GroupPrincipalTest Unit Tests
+ ///</summary>
+ [TestClass()]
+ public class GroupPrincipalTest : PrincipalTest
+ {
+ #region Additional test attributes
+ //
+ //You can use the following additional attributes as you write your tests:
+ //
+ //Use ClassInitialize to run code before running the first test in the class
+ //[ClassInitialize()]
+ //public static void MyClassInitialize(TestContext testContext)
+ //{
+ //}
+ //
+ //Use ClassCleanup to run code after all tests in a class have run
+ //[ClassCleanup()]
+ //public static void MyClassCleanup()
+ //{
+ //}
+ //
+ //Use TestInitialize to run code before running each test
+ //[TestInitialize()]
+ //public void MyTestInitialize()
+ //{
+ //}
+ //
+ //Use TestCleanup to run code after each test has run
+ //[TestCleanup()]
+ //public void MyTestCleanup()
+ //{
+ //}
+ //
+ #endregion
+
+
+ /// <summary>
+ ///A test for GroupPrincipal Constructor
+ ///</summary>
+ [TestMethod()]
+ public void GroupPrincipalConstructorTest()
+ {
+ GroupPrincipal group = new GroupPrincipal(domainContext);
+ group.Dispose();
+ Assert.Inconclusive("TODO: Implement code to verify target");
+ }
+
+ internal override Principal CreatePrincipal(PrincipalContext context, string name)
+ {
+ return new GroupPrincipal(context, name);
+ }
+
+ /// <summary>
+ /// Testing IsMemberOf including large groups
+ /// Right now I assume max is 1500 but test might be modified to test different settings
+ /// Also assuming that the group and members were created - this should be done dynamically (but have to think about test performance, we don't want it to delay all tests)
+ /// Maybe it's better to test ADStoreCtx.IsMemberOfInStore directly? (and also SAMStoreCTX - I still don't know what are the behavioural differences)
+ ///</summary>
+ [TestMethod()]
+ public void IsMemberOfTest()
+ {
+ using (GroupPrincipal group = GroupPrincipal.FindByIdentity(domainContext, "TestLargeGroup"))
+ {
+ //CreateManyUsersInGroup(group);
+
+ Assert.IsTrue(UserPrincipal.FindByIdentity(domainContext, "user1499-LargeGroup").IsMemberOf(group));
+ Assert.IsTrue(UserPrincipal.FindByIdentity(domainContext, "user1500-LargeGroup").IsMemberOf(group));
+ Assert.IsTrue(UserPrincipal.FindByIdentity(domainContext, "user1501-LargeGroup").IsMemberOf(group));
+ Assert.IsTrue(UserPrincipal.FindByIdentity(domainContext, "user3000-LargeGroup").IsMemberOf(group));
+ Assert.IsTrue(UserPrincipal.FindByIdentity(domainContext, "user3001-LargeGroup").IsMemberOf(group));
+ Assert.IsFalse(UserPrincipal.FindByIdentity(domainContext, "userNotInLargeGroup").IsMemberOf(group));
+ }
+ }
+
+ private void CreateManyUsersInGroup(GroupPrincipal group)
+ {
+ for (int i = 1; i < 3002; i++)
+ {
+ string name = String.Format("user{0:0000}-LargeGroup", i);
+ UserPrincipal user = new UserPrincipal(domainContext, name, "Adrumble@6", false);
+ user.Save();
+ group.Members.Add(user);
+ }
+ group.Save();
+ }
+
+ internal override Principal CreateExtendedPrincipal(PrincipalContext context, string name)
+ {
+ Assert.Inconclusive("TODO: Implement code to verify target");
+ throw new System.NotImplementedException();
+ }
+
+ internal override Principal FindExtendedPrincipal(PrincipalContext context, string name)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs b/src/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs
new file mode 100644
index 0000000000..ccf3973100
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs
@@ -0,0 +1,200 @@
+// 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.AccountManagement;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace AccountManagementUnitTests
+{
+ /// <summary>
+ ///This is a test class for PrincipalTest and is intended
+ ///to contain all PrincipalTest Unit Tests
+ ///</summary>
+ [TestClass()]
+ abstract public class PrincipalTest
+ {
+ private TestContext _testContextInstance;
+ protected PrincipalContext domainContext;
+
+ /// <summary>
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///</summary>
+ public TestContext TestContext
+ {
+ get
+ {
+ return _testContextInstance;
+ }
+ set
+ {
+ _testContextInstance = value;
+ }
+ }
+
+ #region Additional test attributes
+
+ [TestInitialize()]
+ public void PrincipalTestInitialize()
+ {
+ RefreshContext();
+ }
+
+ private void RefreshContext()
+ {
+ string username = "Administrator";
+ string password = "Adrumble@6";
+
+ //TODO: don't assume it exists, create it if its not
+ string OU = "Tests";
+ string baseDomain = System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split(new char[] { '\\' })[1] + "-TEST";
+ string domain = String.Format("{0}.nttest.microsoft.com", baseDomain);
+ string container = String.Format("ou={0},dc={1},dc=nttest,dc=microsoft,dc=com", OU, baseDomain);
+
+ if (domainContext != null)
+ {
+ domainContext.Dispose();
+ }
+
+ domainContext = new PrincipalContext(ContextType.Domain, domain, container, username, password);
+ }
+
+ //Use ClassCleanup to run code after all tests in a class have run
+ [TestCleanup()]
+ public void PrincipalTestCleanup()
+ {
+ if (domainContext != null)
+ {
+ domainContext.Dispose();
+ }
+ }
+
+ //Use TestInitialize to run code before running each test
+ //[TestInitialize()]
+ //public void MyTestInitialize()
+ //{
+ //}
+ //
+ //Use TestCleanup to run code after each test has run
+ //[TestCleanup()]
+ //public void MyTestCleanup()
+ //{
+ //}
+ //
+ #endregion
+
+ /// <summary>
+ /// testing user creation
+ /// right now we just test that if trying to add an existing user it causes it to be deleted
+ [TestMethod()]
+ public void AddExistingPrincipal()
+ {
+ // use new GUID for the user name so we be sure this user does not exist yet
+ string name = Guid.NewGuid().ToString();
+ using (Principal principal = CreatePrincipal(domainContext, name))
+ {
+ principal.Save();
+ }
+
+ Assert.IsNotNull(Principal.FindByIdentity(domainContext, name), "Could not create principal");
+
+ // this previously caused the user to be deleted. it is still expected to throw an exception, but not delete the user
+ bool exceptionThrown = false;
+ try
+ {
+ using (Principal principal = CreatePrincipal(domainContext, name))
+ {
+ principal.Save();
+ }
+ }
+ catch (PrincipalExistsException)
+ {
+ exceptionThrown = true;
+ }
+
+ // validate that we correctly throw an exception when trying to add an existing principal
+ Assert.IsTrue(exceptionThrown);
+
+ // validate that we did not delete incorrectly delete the first principal
+ using (Principal principal2 = Principal.FindByIdentity(domainContext, name))
+ {
+ Assert.IsNotNull(principal2, "Existing principal was deleted");
+
+ // explicitly delete the user and check it was really deleted
+ principal2.Delete();
+ }
+
+ // ensure we cleaned up the test principal
+ Assert.IsNull(Principal.FindByIdentity(domainContext, name), "Cleanup failed - principal still exists");
+ }
+
+
+ /// <summary>
+ ///
+ /// </summary>
+ [TestMethod()]
+ public void TestExtendedPrincipal()
+ {
+ // to improve this, we might want to generate random sequences
+ byte[] writtenArray = { 10, 20, 30 };
+ byte[] readArray;
+
+ string name = Guid.NewGuid().ToString();
+ using (Principal principal = CreateExtendedPrincipal(domainContext, name))
+ {
+ IExtendedPrincipalTest extendedPrincipal = (IExtendedPrincipalTest)principal;
+ extendedPrincipal.ByteArrayExtension = writtenArray;
+ principal.Save();
+ }
+
+ RefreshContext();
+
+ using (Principal principal = FindExtendedPrincipal(domainContext, name))
+ {
+ IExtendedPrincipalTest extendedPrincipal = (IExtendedPrincipalTest)principal;
+ readArray = extendedPrincipal.ByteArrayExtension;
+ principal.Delete();
+ }
+
+ CollectionAssert.AreEqual(writtenArray, readArray);
+ }
+
+ private void RefreshDomainContext()
+ {
+ domainContext.Dispose();
+ }
+
+ /// <summary>
+ /// derived classes will create concrete instances
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ internal abstract Principal CreatePrincipal(PrincipalContext context, string name);
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ internal abstract Principal CreateExtendedPrincipal(PrincipalContext context, string name);
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ internal abstract Principal FindExtendedPrincipal(PrincipalContext context, string name);
+ }
+
+ internal interface IExtendedPrincipalTest
+ {
+ object ObjectExtension { get; set; }
+ byte[] ByteArrayExtension { get; set; }
+ object[] ObjectArrayExtension { get; set; }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/tests/Properties/AssemblyInfo.cs b/src/System.DirectoryServices.AccountManagement/tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..f0f5d27a15
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,31 @@
+// 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.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AccountManagementUnitTests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("MSIT")]
+[assembly: AssemblyProduct("AccountManagementUnitTests")]
+[assembly: AssemblyCopyright("Copyright \u00A9 MSIT 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj b/src/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj
new file mode 100644
index 0000000000..01bdda83c3
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <Configuration Condition="'$(Configuration)'==''">Windows_Debug</Configuration>
+ </PropertyGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
+ <ProjectGuid>{57E8F8D4-0766-4CC7-B3F9-B243B81DB6A5}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AssemblyName>System.DirectoryServices.AccountManagement.Tests</AssemblyName>
+ <NugetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.7</NugetTargetMoniker>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\pkg\System.DirectoryServices.AccountManagement.pkgproj">
+ <Project>{879c23dc-d828-4dfb-8e92-abbc11b71035}</Project>
+ <UndefineProperties>%(ProjectReference.UndefineProperties);TargetGroup</UndefineProperties>
+ <Name>System.DirectoryServices.AccountManagement</Name>
+ <Private>True</Private>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup Condition="'$(TargetGroup)'==''">
+ <Compile Include="ComputerPrincipalTest.cs" />
+ <Compile Include="ExtendedUserPrincipal.cs" />
+ <Compile Include="GroupPrincipalTest.cs" />
+ <Compile Include="PrincipalTest.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="UserPrincipalTest.cs" />
+ <Content Include="AuthoringTests.txt" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.builds b/src/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.builds
new file mode 100644
index 0000000000..cfd0983ca2
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.builds
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!-- Disabling the builds for DirectoryServices until we get it up and running. This excludes it from being built by build.cmd
+ <Project Include="System.DirectoryServices.AccountManagement.Tests.csproj">
+ <OSGroup>Windows_NT</OSGroup>
+ </Project>
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs b/src/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs
new file mode 100644
index 0000000000..fb64457049
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs
@@ -0,0 +1,106 @@
+// 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.DirectoryServices.AccountManagement;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace AccountManagementUnitTests
+{
+ /// <summary>
+ ///This is a test class for UserPrincipalTest and is intended
+ ///to contain all UserPrincipalTest Unit Tests
+ ///</summary>
+ [TestClass()]
+ public class UserPrincipalTest : PrincipalTest
+ {
+ #region Additional test attributes
+ //
+ //You can use the following additional attributes as you write your tests:
+ //
+ //Use ClassInitialize to run code before running the first test in the class
+ //[ClassInitialize()]
+ //public static void MyClassInitialize(TestContext testContext)
+ //{
+ //}
+ //
+ //Use ClassCleanup to run code after all tests in a class have run
+ //[ClassCleanup()]
+ //public static void MyClassCleanup()
+ //{
+ //}
+ //
+ //Use TestInitialize to run code before running each test
+ //[TestInitialize()]
+ //public void MyTestInitialize()
+ //{
+ //}
+ //
+ //Use TestCleanup to run code after each test has run
+ //[TestCleanup()]
+ //public void MyTestCleanup()
+ //{
+ //}
+ //
+ #endregion
+
+ internal override Principal CreatePrincipal(PrincipalContext context, string name)
+ {
+ UserPrincipal user = new UserPrincipal(context);
+ user.Name = name;
+ return user;
+ }
+
+ internal override Principal CreateExtendedPrincipal(PrincipalContext context, string name)
+ {
+ ExtendedUserPrincipal user = new ExtendedUserPrincipal(context);
+ user.Name = name;
+ return user;
+ }
+
+ internal override Principal FindExtendedPrincipal(PrincipalContext context, string name)
+ {
+ return ExtendedUserPrincipal.FindByIdentity(context, name);
+ }
+
+ /// <summary>
+ ///A test for UserPrincipal Constructor
+ ///</summary>
+ [TestMethod()]
+ public void UserPrincipalConstructorTest()
+ {
+ UserPrincipal user = new UserPrincipal(domainContext);
+ user.Dispose();
+ Assert.Inconclusive("TODO: Implement code to verify target");
+ }
+
+ [TestMethod()]
+ public void ComputedUACCheck()
+ {
+ string username = "Administrator";
+ string password = "Adrumble@6";
+ //TODO: don't assume it exists, create it if its not
+ string OU = "TestNull";
+ string baseDomain = System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split(new char[] { '\\' })[1] + "-TEST";
+ string domain = System.String.Format("{0}.nttest.microsoft.com", baseDomain);
+ string container = System.String.Format("ou={0},dc={1},dc=nttest,dc=microsoft,dc=com", OU, baseDomain);
+
+ PrincipalContext context = new PrincipalContext(ContextType.Domain, domain, container, username, password);
+ UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "good");
+
+ // set the wrong password to force account lockout
+ // Is there a way of doing it programmatically except for NetUserSetInfo? (managed code)
+ context.ValidateCredentials("good", "wrong password");
+
+ //verify that the account is locked out
+ Assert.IsTrue(user.IsAccountLockedOut(), "trying wrong credentials did not lock the account");
+
+ // if uac is not set correctly, this call might clear the lockout
+ user.SmartcardLogonRequired = false;
+ user.Save();
+
+ //verify that the account is still locked out
+ Assert.IsTrue(user.IsAccountLockedOut(), "the account is no longer locked out after writing setting SmartCardLogonRequired");
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.AccountManagement/tests/testobj.cs b/src/System.DirectoryServices.AccountManagement/tests/testobj.cs
new file mode 100644
index 0000000000..71eb00ea01
--- /dev/null
+++ b/src/System.DirectoryServices.AccountManagement/tests/testobj.cs
@@ -0,0 +1,449 @@
+/*++
+
+Copyright (c) 2004 Microsoft Corporation
+
+Module Name:
+
+ testobj.cs
+
+Abstract:
+
+ Exposes test hooks.
+
+ Only present in TESTHOOK builds.
+
+History:
+
+ 06-May-2004 MattRim Created
+
+--*/
+
+#if TESTHOOK
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Globalization;
+
+namespace System.DirectoryServices.AccountManagement
+{
+ public class TestHook
+ {
+ static public void TestADStoreKeys()
+ {
+ // GUID-based ADStoreKeys
+ Guid adGuid1 = Guid.NewGuid();
+ Guid adGuid2 = Guid.NewGuid();
+
+ ADStoreKey key1a = new ADStoreKey(adGuid1);
+ ADStoreKey key1b = new ADStoreKey(adGuid1);
+ ADStoreKey key2 = new ADStoreKey(adGuid2);
+
+ Debug.Assert(key1a.Equals(key1b));
+ Debug.Assert(!key1a.Equals(key2));
+
+ Debug.Assert(key1a.GetHashCode() == key1b.GetHashCode());
+ Debug.Assert(key1a.GetHashCode() != key2.GetHashCode());
+
+ // SID-based ADStoreKeys
+ string mach1 = "machine1";
+ string mach1a = "machine1";
+ string mach2 = "machine2";
+
+ byte[] sid1a = new byte[]{0x1, 0x2, 0x3};
+ byte[] sid1b = new byte[]{0x1, 0x2, 0x3};
+ byte[] sid2 = new byte[]{0x10, 0x20, 0x30};
+
+ ADStoreKey key3a = new ADStoreKey(mach1, sid1a);
+ ADStoreKey key3b = new ADStoreKey(mach1, sid1a);
+ ADStoreKey key3c = new ADStoreKey(mach1a, sid1b);
+ ADStoreKey key4 = new ADStoreKey(mach2, sid2);
+ ADStoreKey key5 = new ADStoreKey(mach1, sid2);
+
+ Debug.Assert(key3a.Equals(key3b));
+ Debug.Assert(key3a.Equals(key3c));
+
+ Debug.Assert(!key3a.Equals(key4));
+ Debug.Assert(!key3a.Equals(key5));
+
+ Debug.Assert(!key3a.Equals(key1a));
+ Debug.Assert(!key1a.Equals(key3a));
+
+ Debug.Assert(key3a.GetHashCode() != key4.GetHashCode());
+
+ // Shouldn't matter, since SAMStoreKey should make a copy of the byte[] sid
+ sid1b[1] = 0xf;
+ Debug.Assert(key3a.Equals(key3b));
+ Debug.Assert(key3a.Equals(key3c));
+
+ }
+
+ static public void TestSAMStoreKeys()
+ {
+ string mach1 = "machine1";
+ string mach1a = "machine1";
+ string mach2 = "machine2";
+
+ byte[] sid1a = new byte[]{0x1, 0x2, 0x3};
+ byte[] sid1b = new byte[]{0x1, 0x2, 0x3};
+ byte[] sid2 = new byte[]{0x10, 0x20, 0x30};
+
+ SAMStoreKey key1a = new SAMStoreKey(mach1, sid1a);
+ SAMStoreKey key1b = new SAMStoreKey(mach1, sid1a);
+ SAMStoreKey key1c = new SAMStoreKey(mach1a, sid1b);
+ SAMStoreKey key2 = new SAMStoreKey(mach2, sid2);
+ SAMStoreKey key3 = new SAMStoreKey(mach1, sid2);
+
+ Debug.Assert(key1a.Equals(key1b));
+ Debug.Assert(key1a.Equals(key1c));
+
+ Debug.Assert(!key1a.Equals(key2));
+ Debug.Assert(!key1a.Equals(key3));
+
+ Debug.Assert(key1a.GetHashCode() != key2.GetHashCode());
+
+ // Shouldn't matter, since SAMStoreKey should make a copy of the byte[] sid
+ sid1b[1] = 0xf;
+ Debug.Assert(key1a.Equals(key1b));
+ Debug.Assert(key1a.Equals(key1c));
+
+ }
+
+ //
+ // ValueCollection
+ //
+ static public PrincipalValueCollection<T> ValueCollectionConstruct<T>()
+ {
+ return new PrincipalValueCollection<T>();
+ }
+
+ static public void ValueCollectionLoad<T>(PrincipalValueCollection<T> trackList, List<T> initial)
+ {
+ trackList.Load(initial);
+ }
+
+ static public List<T> ValueCollectionInserted<T>(PrincipalValueCollection<T> trackList)
+ {
+ return trackList.Inserted;
+ }
+
+ static public List<T> ValueCollectionRemoved<T>(PrincipalValueCollection<T> trackList)
+ {
+ return trackList.Removed;
+ }
+
+ static public List<T> ValueCollectionChangedValues<T>(PrincipalValueCollection<T> trackList, out List<T> rightOut)
+ {
+ // We'd like to just return the List<Pair<T,T>>, but Pair<T,T> isn't a public class
+ List<T> left = new List<T>();
+ List<T> right = new List<T>();
+ List<Pair<T,T>> pairList = trackList.ChangedValues;
+
+ foreach (Pair<T,T> pair in pairList)
+ {
+ left.Add(pair.Left);
+ right.Add(pair.Right);
+ }
+
+ rightOut = right;
+ return left;
+ }
+
+ static public bool ValueCollectionChanged<T>(PrincipalValueCollection<T> trackList)
+ {
+ return trackList.Changed;
+ }
+
+ static public void ValueCollectionResetTracking<T>(PrincipalValueCollection<T> trackList)
+ {
+ trackList.ResetTracking();
+ }
+
+
+ //
+ // IdentityClaimCollection
+ //
+ static public IdentityClaimCollection ICCConstruct()
+ {
+ Group g = new Group();
+ return new IdentityClaimCollection(g);
+ }
+
+ static public IdentityClaimCollection ICCConstruct2()
+ {
+ Group g = new Group();
+ g.Context = PrincipalContext.Test;
+ return new IdentityClaimCollection(g);
+ }
+
+ static public IdentityClaimCollection ICCConstructAlt()
+ {
+ Group g = new Group();
+ g.Context = PrincipalContext.TestAltValidation;
+ return new IdentityClaimCollection(g);
+ }
+
+ static public IdentityClaimCollection ICCConstructNoTimeLimited()
+ {
+ Group g = new Group();
+ g.Context = PrincipalContext.TestNoTimeLimited;
+ return new IdentityClaimCollection(g);
+ }
+
+ static public void ICCLoad(IdentityClaimCollection trackList, List<IdentityClaim> initial)
+ {
+ trackList.Load(initial);
+ }
+
+ static public List<IdentityClaim> ICCInserted(IdentityClaimCollection trackList)
+ {
+ return trackList.Inserted;
+ }
+
+ static public List<IdentityClaim> ICCRemoved(IdentityClaimCollection trackList)
+ {
+ return trackList.Removed;
+ }
+
+ static public List<IdentityClaim> ICCChangedValues(IdentityClaimCollection trackList, out List<IdentityClaim> rightOut)
+ {
+ // We'd like to just return the List<Pair<T,T>>, but Pair<T,T> isn't a public class
+ List<IdentityClaim> left = new List<IdentityClaim>();
+ List<IdentityClaim> right = new List<IdentityClaim>();
+ List<Pair<IdentityClaim,IdentityClaim>> pairList = trackList.ChangedValues;
+
+ foreach (Pair<IdentityClaim,IdentityClaim> pair in pairList)
+ {
+ left.Add(pair.Left);
+ right.Add(pair.Right);
+ }
+
+ rightOut = right;
+ return left;
+ }
+
+ static public bool ICCChanged(IdentityClaimCollection trackList)
+ {
+ return trackList.Changed;
+ }
+
+ static public void ICCResetTracking(IdentityClaimCollection trackList)
+ {
+ trackList.ResetTracking();
+ }
+
+
+ //
+ // PrincipalCollection
+ //
+ static public Group MakeAGroup(string s)
+ {
+ Group g = new Group(PrincipalContext.Test);
+ g.DisplayName = s;
+ g.Key = new TestStoreKey(s);
+ return g;
+ }
+
+ static public PrincipalCollection MakePrincipalCollection()
+ {
+ BookmarkableResultSet rs = PrincipalContext.Test.QueryCtx.GetGroupMembership(null, false);
+ PrincipalCollection mc = new PrincipalCollection(rs, new Group());
+ return mc;
+ }
+
+ static public List<Principal> MCInserted(PrincipalCollection trackList)
+ {
+ return trackList.Inserted;
+ }
+
+ static public List<Principal> MCRemoved(PrincipalCollection trackList)
+ {
+ return trackList.Removed;
+ }
+
+ static public bool MCChanged(PrincipalCollection trackList)
+ {
+ return trackList.Changed;
+ }
+
+ static public void MCResetTracking(PrincipalCollection trackList)
+ {
+ trackList.ResetTracking();
+ }
+
+ //
+ // AuthenticablePrincipal
+ //
+ static public User APGetNoninsertedAP()
+ {
+ User u = new User(PrincipalContext.Test);
+ u.unpersisted = false;
+ return u;
+ }
+
+ static public void APInitNested(AuthenticablePrincipal ap)
+ {
+ ap.LoadValueIntoProperty(PropertyNames.PwdInfoCannotChangePassword, true);
+ ap.LoadValueIntoProperty(PropertyNames.AcctInfoBadLogonCount, 3);
+ }
+
+ static public void APLoadValue(AuthenticablePrincipal ap, string name, object value)
+ {
+ ap.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool APGetChangeStatus(AuthenticablePrincipal ap, string name)
+ {
+ return ap.GetChangeStatusForProperty(name);
+ }
+
+ static public object APGetValue(AuthenticablePrincipal ap, string name)
+ {
+ return ap.GetValueForProperty(name);
+ }
+
+ static public void APResetChanges(AuthenticablePrincipal ap)
+ {
+ ap.ResetAllChangeStatus();
+ }
+
+
+ //
+ // PasswordInfo
+ //
+ static public PasswordInfo ExtractPI(AuthenticablePrincipal ap)
+ {
+ Type t = typeof(AuthenticablePrincipal);
+
+ return (PasswordInfo) t.InvokeMember(
+ "PasswordInfo",
+ BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,
+ null,
+ ap,
+ new object[]{},
+ CultureInfo.InvariantCulture);
+ }
+
+ static public void PILoadValue(PasswordInfo pi, string name, object value)
+ {
+ pi.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool PIGetChangeStatus(PasswordInfo pi, string name)
+ {
+ return pi.GetChangeStatusForProperty(name);
+ }
+
+ static public object PIGetValue(PasswordInfo pi, string name)
+ {
+ return pi.GetValueForProperty(name);
+ }
+
+ static public void PIResetChanges(PasswordInfo pi)
+ {
+ pi.ResetAllChangeStatus();
+ }
+
+ //
+ // AccountInfo
+ //
+ static public AccountInfo ExtractAI(AuthenticablePrincipal ap)
+ {
+ Type t = typeof(AuthenticablePrincipal);
+
+ return (AccountInfo) t.InvokeMember(
+ "AccountInfo",
+ BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,
+ null,
+ ap,
+ new object[]{},
+ CultureInfo.InvariantCulture);
+ }
+
+ static public void AILoadValue(AccountInfo ai, string name, object value)
+ {
+ ai.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool AIGetChangeStatus(AccountInfo ai, string name)
+ {
+ return ai.GetChangeStatusForProperty(name);
+ }
+
+ static public object AIGetValue(AccountInfo ai, string name)
+ {
+ return ai.GetValueForProperty(name);
+ }
+
+ static public void AIResetChanges(AccountInfo ai)
+ {
+ ai.ResetAllChangeStatus();
+ }
+
+ //
+ // User
+ //
+ static public void UserLoadValue(User u, string name, object value)
+ {
+ u.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool UserGetChangeStatus(User u, string name)
+ {
+ return u.GetChangeStatusForProperty(name);
+ }
+
+ static public object UserGetValue(User u, string name)
+ {
+ return u.GetValueForProperty(name);
+ }
+
+ static public void UserResetChanges(User u)
+ {
+ u.ResetAllChangeStatus();
+ }
+
+ static public Group GroupGetNonInsertedGroup()
+ {
+ Group g = new Group(PrincipalContext.Test);
+ g.unpersisted = false;
+ return g;
+ }
+
+ //
+ // Computer
+ //
+ static public void ComputerLoadValue(Computer computer, string name, object value)
+ {
+ computer.LoadValueIntoProperty(name, value);
+ }
+
+ static public bool ComputerGetChangeStatus(Computer computer, string name)
+ {
+ return computer.GetChangeStatusForProperty(name);
+ }
+
+ static public object ComputerGetValue(Computer computer, string name)
+ {
+ return computer.GetValueForProperty(name);
+ }
+
+ static public void ComputerResetChanges(Computer computer)
+ {
+ computer.ResetAllChangeStatus();
+ }
+
+ //
+ // QBE
+ //
+ static public void BuildQbeFilter(Principal p)
+ {
+ PrincipalContext ctx = PrincipalContext.Test;
+ ((TestStoreCtx)ctx.QueryCtx).CallBuildQbeFilterDescription(p);
+ }
+ }
+
+}
+
+#endif // TESTHOOK
diff --git a/src/System.DirectoryServices.Protocols/System.DirectoryServices.Protocols.sln b/src/System.DirectoryServices.Protocols/System.DirectoryServices.Protocols.sln
new file mode 100644
index 0000000000..b6ef10acac
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/System.DirectoryServices.Protocols.sln
@@ -0,0 +1,82 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.DirectoryServices.Protocols", "src\System.DirectoryServices.Protocols.csproj", "{879C23DC-D828-4DFB-8E92-ABBC11B71035}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{E37A8E5B-B822-436D-84FD-99EE46C0733F}"
+ ProjectSection(SolutionItems) = preProject
+ ref\project.lock.json = ref\project.lock.json
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.DirectoryServices.Protocols", "ref\System.DirectoryServices.Protocols.csproj", "{2F7F1E21-0277-436B-85B8-E8FFA902FA66}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AD3CFC4E-B3AE-4931-B631-C39216ABD115}"
+ ProjectSection(SolutionItems) = preProject
+ src\System.DirectoryServices.Protocols.builds = src\System.DirectoryServices.Protocols.builds
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ net46_Debug|Any CPU = net46_Debug|Any CPU
+ net46_Release|Any CPU = net46_Release|Any CPU
+ Release|Any CPU = Release|Any CPU
+ Unix_Debug|Any CPU = Unix_Debug|Any CPU
+ Unix_Release|Any CPU = Unix_Release|Any CPU
+ Windows_Debug|Any CPU = Windows_Debug|Any CPU
+ Windows_netcore50_Debug|Any CPU = Windows_netcore50_Debug|Any CPU
+ Windows_netcore50_Release|Any CPU = Windows_netcore50_Release|Any CPU
+ Windows_Release|Any CPU = Windows_Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Debug|Any CPU.ActiveCfg = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Debug|Any CPU.ActiveCfg = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Release|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035} = {AD3CFC4E-B3AE-4931-B631-C39216ABD115}
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66} = {E37A8E5B-B822-436D-84FD-99EE46C0733F}
+ EndGlobalSection
+EndGlobal
diff --git a/src/System.DirectoryServices.Protocols/dir.props b/src/System.DirectoryServices.Protocols/dir.props
new file mode 100644
index 0000000000..503cf86a87
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/dir.props
@@ -0,0 +1,7 @@
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\dir.props" />
+ <PropertyGroup>
+ <AssemblyVersion>4.1.0.0</AssemblyVersion>
+ </PropertyGroup>
+</Project>
+
diff --git a/src/System.DirectoryServices.Protocols/pkg/System.DirectoryServices.Protocols.builds b/src/System.DirectoryServices.Protocols/pkg/System.DirectoryServices.Protocols.builds
new file mode 100644
index 0000000000..f0b07ae454
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/pkg/System.DirectoryServices.Protocols.builds
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!--
+ <Project Include="System.DirectoryServices.Protocols.pkgproj"/>
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.DirectoryServices.Protocols/pkg/System.DirectoryServices.Protocols.pkgproj b/src/System.DirectoryServices.Protocols/pkg/System.DirectoryServices.Protocols.pkgproj
new file mode 100644
index 0000000000..39f0ecf225
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/pkg/System.DirectoryServices.Protocols.pkgproj
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <ProjectReference Include="..\ref\System.DirectoryServices.Protocols.csproj">
+ <SupportedFramework>netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ </ProjectReference>
+ <ProjectReference Include="..\src\System.DirectoryServices.Protocols.builds" />
+ <InboxOnTargetFramework Include="MonoAndroid10" />
+ <InboxOnTargetFramework Include="MonoTouch10" />
+ <InboxOnTargetFramework Include="xamarinios10" />
+ <InboxOnTargetFramework Include="xamarinmac20" />
+ <InboxOnTargetFramework Include="xamarintvos10" />
+ <InboxOnTargetFramework Include="xamarinwatchos10" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs b/src/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs
new file mode 100644
index 0000000000..d3da1f8534
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs
@@ -0,0 +1,8 @@
+// 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.
+// ------------------------------------------------------------------------------
+// Changes to this file must follow the http://aka.ms/api-review process.
+// ------------------------------------------------------------------------------
+
+
diff --git a/src/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.csproj b/src/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.csproj
new file mode 100644
index 0000000000..495b218a9e
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.csproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="System.DirectoryServices.Protocols.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.DirectoryServices.Protocols/src/Resources/System.DirectoryServices.Protocols.txt b/src/System.DirectoryServices.Protocols/src/Resources/System.DirectoryServices.Protocols.txt
new file mode 100644
index 0000000000..e539641367
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/Resources/System.DirectoryServices.Protocols.txt
@@ -0,0 +1,132 @@
+
+; Resources for System.DirectoryServices component
+; Copyright (c) 2000 Microsoft Corporation
+
+; Exceptions messages
+
+DsmlNonHttpUri=The URI that is supplied must be either "http" or "https".
+NoNegativeTime=A negative value is not permitted for the time limit.
+NoNegativeSizeLimit=A negative value is not permitted for the size limit.
+InvalidDocument=The DSML document could not be parsed.
+MissingSessionId=The server failed to return a session identifier.
+MissingResponse=The server failed to return a DirectoryResponse.
+ErrorResponse=An ErrorResponse DSML element was returned.
+BadControl=The server returned an invalid DSML control.
+NullDirectoryAttribute=A null reference cannot be added to DirectoryAttribute or DirectoryAttributeModification objects.
+NullDirectoryAttributeCollection=A null reference cannot be added to DirectoryAttributeCollection or DirectoryAttributeModificationCollection objects.
+WhiteSpaceServerName=Server names cannot contain a space character.
+DirectoryAttributeConversion=A DirectoryAttribute value can only be converted between byte array and string.
+WrongNumValuesCompare=Only one value can be specified for the compare operation.
+WrongAssertionCompare=The assertion is null and is invalid for the compare operation.
+DefaultOperationsError=An unspecified operation error occurred.
+BadSearchLDAPFilter=The LDAP filter string is invalid.
+ReadOnlyProperty=The property is read-only.
+MissingOperationResponseResultCode=The operation response is missing the result code.
+MissingSearchResultEntryDN=The distinguished name is missing in the SearchResultEntry of the search response.
+MissingSearchResultEntryAttributeName=The search result is missing the attribute name.
+BadOperationResponseResultCode=The server returned an unknown result code "{0}".
+MissingErrorResponseType=The error response is missing the type attribute.
+ErrorResponseInvalidValue=The error response contains an invalid type attribute "{0}".
+NotSupportOnDsmlErrRes=This property is not supported on a DsmlErrorResponse.
+BadBase64Value=The value is invalid base-64-encoded data.
+WrongAuthType=The DsmlSoapHttpConnection does not support "{0}" authentication type.
+SessionInUse=An active session already exists for this connection.
+ReadOnlyDocument=The document is read-only.
+NotWellFormedResponse=The response from the server is not a well-formed DSML document.
+NoCurrentSession=No active session exists for this connection.
+UnknownResponseElement=The server returned an unknown response element.
+InvalidClientCertificates=ClientCertificates can contain only zero or one certificate.
+InvalidAuthCredential=The user name and password must be null when the authentication type is anonymous.
+InvalidLdapSearchRequestFilter=The LDAP connection only accepts SearchRequest objects that have string type filters.
+PartialResultsNotSupported=Retrieval of partial results set is supported only by the SearchRequest object.
+BerConverterNotMatch=The "format" string argument and the passed in "value" argument do not match.
+BerConverterUndefineChar=The "format" string contains an invalid character.
+BerConversionError=An error occurred during the BER conversion.
+TLSStopFailure=The Stop TLS operation failed.
+NoPartialResults=The LDAP connection cannot retrieve a partial result set.
+
+DefaultLdapError=The LDAP server returned an unknown error.
+LDAP_PARTIAL_RESULTS=Only partial results and referrals were received.
+LDAP_IS_LEAF=The object is a leaf.
+LDAP_SORT_CONTROL_MISSING=The search requires a SORT control.
+LDAP_OFFSET_RANGE_ERROR=The search results exceed the specified offset range.
+LDAP_RESULTS_TOO_LARGE=The returned results are too large.
+LDAP_SERVER_DOWN=The LDAP server is unavailable.
+LDAP_LOCAL_ERROR=A local error occurred.
+LDAP_ENCODING_ERROR=An encoding error occurred.
+LDAP_DECODING_ERROR=A decoding error occurred.
+LDAP_TIMEOUT=The operation was aborted because the client side timeout limit was exceeded.
+LDAP_AUTH_UNKNOWN=An unknown authentication error occurred.
+LDAP_FILTER_ERROR=The search filter is invalid.
+LDAP_USER_CANCELLED=The user cancelled the operation.
+LDAP_PARAM_ERROR=A bad parameter was passed to a routine.
+LDAP_NO_MEMORY=There is not enough memory to perform the task.
+LDAP_CONNECT_ERROR=The connection cannot be established.
+LDAP_NOT_SUPPORTED=The feature is not supported.
+LDAP_NO_RESULTS_RETURNED=No results were returned.
+LDAP_CONTROL_NOT_FOUND=The specified control was not found.
+LDAP_MORE_RESULTS_TO_RETURN=More results will be returned.
+LDAP_CLIENT_LOOP=A client loop was detected.
+LDAP_REFERRAL_LIMIT_EXCEEDED=The referral limit has been exceeded.
+LDAP_INVALID_CREDENTIALS=The supplied credential is invalid.
+LDAP_SUCCESS=The call completed successfully.
+NoSessionIDReturned=The server failed to return a session identifier.
+LDAP_OPERATIONS_ERROR=An operation error occurred.
+LDAP_PROTOCOL_ERROR=A protocol error occurred.
+LDAP_TIMELIMIT_EXCEEDED=The time limit set by the server-side time limit parameter was exceeded.
+LDAP_SIZELIMIT_EXCEEDED=The size limit was exceeded
+LDAP_COMPARE_FALSE=The attribute and known values do not match.
+LDAP_COMPARE_TRUE=The attribute and known values match.
+LDAP_AUTH_METHOD_NOT_SUPPORTED=The authentication method is not supported.
+LDAP_STRONG_AUTH_REQUIRED=Strong authentication is required for this operation.
+LDAP_REFERRAL=A referral was returned from the server.
+LDAP_ADMIN_LIMIT_EXCEEDED=The administration limit on the server was exceeded.
+LDAP_UNAVAILABLE_CRIT_EXTENSION=The server does not support the control. The control is critical.
+LDAP_CONFIDENTIALITY_REQUIRED=Confidentiality is required for this operation.
+LDAP_SASL_BIND_IN_PROGRESS=A SASL bind is in progress.
+LDAP_NO_SUCH_ATTRIBUTE=The requested attribute does not exist.
+LDAP_UNDEFINED_TYPE=The type is not defined.
+LDAP_INAPPROPRIATE_MATCHING=The matching rule does not apply to the specified attribute type.
+LDAP_CONSTRAINT_VIOLATION=A value in the request is invalid.
+LDAP_ATTRIBUTE_OR_VALUE_EXISTS=The attribute exists or the value has been assigned.
+LDAP_INVALID_SYNTAX=The syntax is invalid.
+LDAP_NO_SUCH_OBJECT=The object does not exist.
+LDAP_ALIAS_PROBLEM=The alias is invalid.
+LDAP_INVALID_DN_SYNTAX=The distinguished name contains invalid syntax.
+LDAP_ALIAS_DEREF_PROBLEM=An error occurred when dereferencing the alias.
+LDAP_INAPPROPRIATE_AUTH=The authentication that was provided was not appropriate.
+LDAP_INSUFFICIENT_RIGHTS=The user has insufficient access rights.
+LDAP_BUSY=The server is busy.
+LDAP_UNAVAILABLE=The server is unavailable.
+LDAP_UNWILLING_TO_PERFORM=The server cannot handle directory requests.
+LDAP_LOOP_DETECT=The chain of referrals has looped back to a referring server.
+LDAP_NAMING_VIOLATION=A naming violation occurred.
+LDAP_OBJECT_CLASS_VIOLATION=An object class violation occurred.
+LDAP_NOT_ALLOWED_ON_NONLEAF=This operation is not allowed on a non-leaf object.
+LDAP_NOT_ALLOWED_ON_RDN=This operation is not allowed on a relative distinguished name.
+LDAP_ALREADY_EXISTS=The object exists.
+LDAP_NO_OBJECT_CLASS_MODS=The request is attempting to modify an object class that cannot be modified.
+LDAP_AFFECTS_MULTIPLE_DSAS=Multiple directory service agents are affected.
+LDAP_VIRTUAL_LIST_VIEW_ERROR=An error occurred when attempting to perform a requested Virtual List View operation.
+LDAP_OTHER=An unknown error occurred.
+LDAP_SEND_TIMEOUT=The operation was aborted because the send timeout limit was exceeded.
+InvalidAsyncResult=The async result is invalid.
+
+ValidDirectoryAttributeType=The "value" parameter must be a string or byte[] type.
+ValidFilterType=The "filter" parameter must be a string or DsmlDocument type.
+ValidValuesType=The "values" parameter must be a string[], byte[][], or Uri[] type.
+ValidValueType=The value must be a string, byte[], or Uri type.
+SupportedPlatforms=System.DirectoryServices.Protocols namespace is only supported on Windows 2000 and later operating systems.
+TLSNotSupported=Transport layer security is not supported on Windows 2000.
+InvalidValueType=The specified parameter should be a "{0}" type.
+ValidValue=The value must be greater than or equal to 0.
+ContainNullControl=The collection cannot contain a null DirectoryControl object.
+InvalidFilterType=The filter type "{0}" is invalid.
+NotReturnedAsyncResult=The value "{0}" is not the return value from BeginSendRequest.
+DsmlAuthRequestNotSupported=LdapConnection object does not support DsmlAuthRequest.
+CallBackIsNull=Callback function can not be null when partial result processing is in ReturnPartialResultsAndNotifyCallback mode.
+NullValueArray=The array should not contain null reference.
+NonCLSException=A non-CLSCompliant exception is thrown.
+ConcurrentBindNotSupport=Fast concurrent bind is only supported on Windows 2003 and later operating systems.
+TimespanExceedMax=The value exceeds the maximum allowed.
+InvliadRequestType=The specified request is not supported.
diff --git a/src/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.builds b/src/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.builds
new file mode 100644
index 0000000000..2f37b5f289
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.builds
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!-- Disabling the builds for DirectoryServices until we get it up and running. This excludes it from being built by build.cmd
+ <Project Include="System.DirectoryServices.Protocols.csproj">
+ <OSGroup>Windows_NT</OSGroup>
+ </Project>
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project>
+
diff --git a/src/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj
new file mode 100644
index 0000000000..2e75030d9f
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <Configuration Condition="'$(Configuration)'=='' AND '$(TargetGroup)' == ''">Windows_Debug</Configuration>
+ </PropertyGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <ProjectGuid>{879C23DC-D828-4DFB-8E92-ABBC11B71035}</ProjectGuid>
+ <AssemblyName>System.DirectoryServices.Protocols</AssemblyName>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <NoWarn>$(NoWarn);0649</NoWarn>
+ <NuGetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ <GeneratePlatformNotSupportedAssembly Condition="'$(TargetsUnix)' == 'true'">true</GeneratePlatformNotSupportedAssembly>
+ </PropertyGroup>
+ <!-- Help VS understand available configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
+ <ItemGroup>
+ <Compile Include="System\DirectoryServices\Protocols\externdll.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\AuthTypes.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\BerConverter.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DereferenceAlias.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DirectoryAttribute.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DirectoryAttributeOperation.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DirectoryConnection.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DirectoryControl.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DirectoryException.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DirectoryIdentifier.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DirectoryOperation.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DirectoryRequest.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\DirectoryResponse.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\PartialResultsCollection.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\ReferralChasingOption.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\ResultCode.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\SearchResults.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\common\SearchScope.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\adreqresp2.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\DsmlAsyncResult.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\DsmlConstants.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\DsmlDirectoryIdentifier.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\DsmlDocument.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\DsmlDocumentProcessing.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\DsmlException.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\dsmlfilterwriter.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\DsmlSoapConnection.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\DsmlSoapHttpConnection.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\filterparser.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\dsml\utils.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\ldap\LdapAsyncResult.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\ldap\LdapConnection.cs" />
+ <Compile Include="System\DirectoryServices\Protocols\ldap\LdapDirectoryIdentifier.cs" />
+ <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" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ExternDll.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ExternDll.cs
new file mode 100644
index 0000000000..6877ccedf6
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ExternDll.cs
@@ -0,0 +1,83 @@
+// 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
+{
+ internal static class ExternDll
+ {
+#if FEATURE_PAL && !SILVERLIGHT
+
+#if !PLATFORM_UNIX
+ internal const String DLLPREFIX = "";
+ internal const String DLLSUFFIX = ".dll";
+#else // !PLATFORM_UNIX
+#if __APPLE__
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".dylib";
+#elif _AIX
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".a";
+#elif __hppa__ || IA64
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".sl";
+#else
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".so";
+#endif
+#endif // !PLATFORM_UNIX
+
+ public const string Kernel32 = DLLPREFIX + "rotor_pal" + DLLSUFFIX;
+ public const string User32 = DLLPREFIX + "rotor_pal" + DLLSUFFIX;
+ public const string Mscoree = DLLPREFIX + "sscoree" + DLLSUFFIX;
+
+#elif FEATURE_PAL && SILVERLIGHT
+
+ public const string Kernel32 = "coreclr";
+ public const string User32 = "coreclr";
+
+#else
+ public const string Activeds = "activeds.dll";
+ public const string Advapi32 = "advapi32.dll";
+ public const string Comctl32 = "comctl32.dll";
+ public const string Comdlg32 = "comdlg32.dll";
+ public const string Gdi32 = "gdi32.dll";
+ public const string Gdiplus = "gdiplus.dll";
+ public const string Hhctrl = "hhctrl.ocx";
+ public const string Imm32 = "imm32.dll";
+ public const string Kernel32 = "kernel32.dll";
+ public const string Loadperf = "Loadperf.dll";
+ public const string Mscoree = "mscoree.dll";
+ public const string Clr = "clr.dll";
+ public const string Msi = "msi.dll";
+ public const string Mqrt = "mqrt.dll";
+ public const string Ntdll = "ntdll.dll";
+ public const string Ole32 = "ole32.dll";
+ public const string Oleacc = "oleacc.dll";
+ public const string Oleaut32 = "oleaut32.dll";
+ public const string Olepro32 = "olepro32.dll";
+ public const string PerfCounter = "perfcounter.dll";
+ public const string Powrprof = "Powrprof.dll";
+ public const string Psapi = "psapi.dll";
+ public const string Shell32 = "shell32.dll";
+ public const string User32 = "user32.dll";
+ public const string Uxtheme = "uxtheme.dll";
+ public const string WinMM = "winmm.dll";
+ public const string Winspool = "winspool.drv";
+ public const string Wtsapi32 = "wtsapi32.dll";
+ public const string Version = "version.dll";
+ public const string Vsassert = "vsassert.dll";
+ public const string Fxassert = "Fxassert.dll";
+ public const string Shlwapi = "shlwapi.dll";
+ public const string Crypt32 = "crypt32.dll";
+
+ // system.data specific
+ internal const string Odbc32 = "odbc32.dll";
+ internal const string SNI = "System.Data.dll";
+
+ // system.data.oracleclient specific
+ internal const string OciDll = "oci.dll";
+ internal const string OraMtsDll = "oramts.dll";
+#endif //!FEATURE_PAL
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/AuthTypes.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/AuthTypes.cs
new file mode 100644
index 0000000000..a8dad8a7d3
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/AuthTypes.cs
@@ -0,0 +1,29 @@
+// 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
+{
+ using System;
+
+ public enum AuthType
+ {
+ Anonymous = 0,
+ Basic = 1,
+ Negotiate = 2,
+ Ntlm = 3,
+ Digest = 4,
+ Sicily = 5,
+ Dpa = 6,
+ Msn = 7,
+ External = 8,
+ Kerberos = 9
+ }
+
+ public enum PartialResultProcessing
+ {
+ NoPartialResultSupport,
+ ReturnPartialResults,
+ ReturnPartialResultsAndNotifyCallback
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs
new file mode 100644
index 0000000000..8e4e555e5a
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs
@@ -0,0 +1,631 @@
+// 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
+{
+ using System;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Text;
+
+ public sealed class BerConverter
+ {
+ private BerConverter() { }
+
+ public static byte[] Encode(string format, params object[] value)
+ {
+ Utility.CheckOSVersion();
+
+ if (format == null)
+ throw new ArgumentNullException("format");
+
+ // no need to turn on invalid encoding detection as we just do string->byte[] conversion.
+ UTF8Encoding utf8Encoder = new UTF8Encoding();
+ byte[] encodingResult = null;
+ // value is allowed to be null in certain scenario, so if it is null, just set it to empty array.
+ if (value == null)
+ value = new object[0];
+
+ Debug.WriteLine("Begin encoding\n");
+
+ // allocate the berelement
+ BerSafeHandle berElement = new BerSafeHandle();
+
+ int valueCount = 0;
+ int error = 0;
+ for (int formatCount = 0; formatCount < format.Length; formatCount++)
+ {
+ char fmt = format[formatCount];
+ if (fmt == '{' || fmt == '}' || fmt == '[' || fmt == ']' || fmt == 'n')
+ {
+ // no argument needed
+ error = Wldap32.ber_printf_emptyarg(berElement, new string(fmt, 1));
+ }
+ else if (fmt == 't' || fmt == 'i' || fmt == 'e')
+ {
+ 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(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ if (!(value[valueCount] is int))
+ {
+ // argument is wrong
+ Debug.WriteLine("type should be int\n");
+ throw new ArgumentException(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ // one int argument
+ error = Wldap32.ber_printf_int(berElement, new string(fmt, 1), (int)value[valueCount]);
+
+ // increase the value count
+ valueCount++;
+ }
+ else if (fmt == 'b')
+ {
+ 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(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ if (!(value[valueCount] is bool))
+ {
+ // argument is wrong
+ Debug.WriteLine("type should be boolean\n");
+ throw new ArgumentException(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ // one int argument
+ error = Wldap32.ber_printf_int(berElement, new string(fmt, 1), (bool)value[valueCount] ? 1 : 0);
+
+ // increase the value count
+ valueCount++;
+ }
+ else if (fmt == 's')
+ {
+ 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(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ if (value[valueCount] != null && !(value[valueCount] is string))
+ {
+ // argument is wrong
+ Debug.WriteLine("type should be string, but receiving value has type of ");
+ Debug.WriteLine(value[valueCount].GetType());
+ throw new ArgumentException(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ // one string argument
+ byte[] tempValue = null;
+ if (value[valueCount] != null)
+ {
+ tempValue = utf8Encoder.GetBytes((string)value[valueCount]);
+ }
+ error = EncodingByteArrayHelper(berElement, tempValue, 'o');
+
+ // increase the value count
+ valueCount++;
+ }
+ else if (fmt == 'o' || fmt == 'X')
+ {
+ // we need to have one arguments
+ 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(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ if (value[valueCount] != null && !(value[valueCount] is byte[]))
+ {
+ // argument is wrong
+ Debug.WriteLine("type should be byte[], but receiving value has type of ");
+ Debug.WriteLine(value[valueCount].GetType());
+ throw new ArgumentException(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ byte[] tempValue = (byte[])value[valueCount];
+ error = EncodingByteArrayHelper(berElement, tempValue, fmt);
+
+ valueCount++;
+ }
+ else if (fmt == 'v')
+ {
+ // we need to have one arguments
+ 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(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ if (value[valueCount] != null && !(value[valueCount] is string[]))
+ {
+ // argument is wrong
+ Debug.WriteLine("type should be string[], but receiving value has type of ");
+ Debug.WriteLine(value[valueCount].GetType());
+ throw new ArgumentException(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ string[] stringValues = (string[])value[valueCount];
+ byte[][] tempValues = null;
+ if (stringValues != null)
+ {
+ tempValues = new byte[stringValues.Length][];
+ for (int i = 0; i < stringValues.Length; i++)
+ {
+ string s = stringValues[i];
+ if (s == null)
+ tempValues[i] = null;
+ else
+ {
+ tempValues[i] = utf8Encoder.GetBytes(s);
+ }
+ }
+ }
+
+ error = EncodingMultiByteArrayHelper(berElement, tempValues, 'V');
+
+ valueCount++;
+ }
+ else if (fmt == 'V')
+ {
+ // we need to have one arguments
+ 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(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ if (value[valueCount] != null && !(value[valueCount] is byte[][]))
+ {
+ // argument is wrong
+ Debug.WriteLine("type should be byte[][], but receiving value has type of ");
+ Debug.WriteLine(value[valueCount].GetType());
+ throw new ArgumentException(Res.GetString(Res.BerConverterNotMatch));
+ }
+
+ byte[][] tempValue = (byte[][])value[valueCount];
+
+ error = EncodingMultiByteArrayHelper(berElement, tempValue, fmt);
+
+ valueCount++;
+ }
+ else
+ {
+ Debug.WriteLine("Format string contains undefined character: ");
+ Debug.WriteLine(new string(fmt, 1));
+ throw new ArgumentException(Res.GetString(Res.BerConverterUndefineChar));
+ }
+
+ // process the return value
+ if (error == -1)
+ {
+ Debug.WriteLine("ber_printf failed\n");
+ throw new BerConversionException();
+ }
+ }
+
+ // get the binary value back
+ berval binaryValue = new berval();
+ IntPtr flattenptr = (IntPtr)0;
+
+ try
+ {
+ // 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);
+
+ if (error == -1)
+ {
+ Debug.WriteLine("ber_flatten failed\n");
+ throw new BerConversionException();
+ }
+
+ if (flattenptr != (IntPtr)0)
+ {
+ Marshal.PtrToStructure(flattenptr, binaryValue);
+ }
+
+ if (binaryValue == null || binaryValue.bv_len == 0)
+ {
+ encodingResult = new byte[0];
+ }
+ else
+ {
+ encodingResult = new byte[binaryValue.bv_len];
+
+ Marshal.Copy(binaryValue.bv_val, encodingResult, 0, binaryValue.bv_len);
+ }
+ }
+ finally
+ {
+ if (flattenptr != (IntPtr)0)
+ Wldap32.ber_bvfree(flattenptr);
+ }
+
+ return encodingResult;
+ }
+
+ public static object[] Decode(string format, byte[] value)
+ {
+ bool decodeSucceeded;
+ object[] decodeResult = TryDecode(format, value, out decodeSucceeded);
+ if (decodeSucceeded)
+ return decodeResult;
+ else
+ throw new BerConversionException();
+ }
+
+ internal static object[] TryDecode(string format, byte[] value, out bool decodeSucceeded)
+ {
+ Utility.CheckOSVersion();
+
+ if (format == null)
+ throw new ArgumentNullException("format");
+
+ Debug.WriteLine("Begin decoding\n");
+
+ UTF8Encoding utf8Encoder = new UTF8Encoding(false, true);
+ berval berValue = new berval();
+ ArrayList resultList = new ArrayList();
+ BerSafeHandle berElement = null;
+
+ object[] decodeResult = null;
+ decodeSucceeded = false;
+
+ if (value == null)
+ {
+ berValue.bv_len = 0;
+ berValue.bv_val = (IntPtr)0;
+ }
+ else
+ {
+ berValue.bv_len = value.Length;
+ berValue.bv_val = Marshal.AllocHGlobal(value.Length);
+ Marshal.Copy(value, 0, berValue.bv_val, value.Length);
+ }
+
+ try
+ {
+ berElement = new BerSafeHandle(berValue);
+ }
+ finally
+ {
+ if (berValue.bv_val != (IntPtr)0)
+ Marshal.FreeHGlobal(berValue.bv_val);
+ }
+
+ int error = 0;
+
+ for (int formatCount = 0; formatCount < format.Length; formatCount++)
+ {
+ char fmt = format[formatCount];
+ if (fmt == '{' || fmt == '}' || fmt == '[' || fmt == ']' || fmt == 'n' || fmt == 'x')
+ {
+ error = Wldap32.ber_scanf(berElement, new string(fmt, 1));
+
+ if (error != 0)
+ 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);
+
+ if (error == 0)
+ {
+ if (fmt == 'b')
+ {
+ // should return a bool
+ bool boolResult = false;
+ if (result == 0)
+ boolResult = false;
+ else
+ boolResult = true;
+ resultList.Add(boolResult);
+ }
+ else
+ {
+ resultList.Add(result);
+ }
+ }
+ else
+ Debug.WriteLine("ber_scanf for format character 'i', 'e' or 'b' failed");
+ }
+ else if (fmt == 'a')
+ {
+ // return a string
+ byte[] byteArray = DecodingByteArrayHelper(berElement, 'O', ref error);
+ if (error == 0)
+ {
+ string s = null;
+ if (byteArray != null)
+ s = utf8Encoder.GetString(byteArray);
+
+ resultList.Add(s);
+ }
+ }
+ else if (fmt == 'O')
+ {
+ // return berval
+ byte[] byteArray = DecodingByteArrayHelper(berElement, fmt, ref error);
+ if (error == 0)
+ {
+ // add result to the list
+ resultList.Add(byteArray);
+ }
+ }
+ else if (fmt == 'B')
+ {
+ // return a bitstring and its length
+ IntPtr ptrResult = (IntPtr)0;
+ int length = 0;
+ error = Wldap32.ber_scanf_bitstring(berElement, "B", ref ptrResult, ref length);
+
+ if (error == 0)
+ {
+ byte[] byteArray = null;
+ if (ptrResult != (IntPtr)0)
+ {
+ 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
+ }
+ else if (fmt == 'v')
+ {
+ //null terminate strings
+ byte[][] byteArrayresult = null;
+ string[] stringArray = null;
+
+ byteArrayresult = DecodingMultiByteArrayHelper(berElement, 'V', ref error);
+ if (error == 0)
+ {
+ if (byteArrayresult != null)
+ {
+ stringArray = new string[byteArrayresult.Length];
+ for (int i = 0; i < byteArrayresult.Length; i++)
+ {
+ if (byteArrayresult[i] == null)
+ {
+ stringArray[i] = null;
+ }
+ else
+ {
+ stringArray[i] = utf8Encoder.GetString(byteArrayresult[i]);
+ }
+ }
+ }
+
+ resultList.Add(stringArray);
+ }
+ }
+ else if (fmt == 'V')
+ {
+ byte[][] result = null;
+
+ result = DecodingMultiByteArrayHelper(berElement, fmt, ref error);
+ if (error == 0)
+ {
+ resultList.Add(result);
+ }
+ }
+ else
+ {
+ Debug.WriteLine("Format string contains undefined character\n");
+ throw new ArgumentException(Res.GetString(Res.BerConverterUndefineChar));
+ }
+
+ if (error != 0)
+ {
+ // decode failed, just return
+ return decodeResult;
+ }
+ }
+
+ decodeResult = new object[resultList.Count];
+ for (int count = 0; count < resultList.Count; count++)
+ {
+ decodeResult[count] = resultList[count];
+ }
+
+ decodeSucceeded = true;
+ return decodeResult;
+ }
+
+ private static int EncodingByteArrayHelper(BerSafeHandle berElement, byte[] tempValue, char fmt)
+ {
+ int error = 0;
+
+ // one byte array, one int arguments
+ if (tempValue != null)
+ {
+ 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);
+ }
+ else
+ {
+ error = Wldap32.ber_printf_bytearray(berElement, new string(fmt, 1), new HGlobalMemHandle((IntPtr)0), 0);
+ }
+
+ return error;
+ }
+
+ private static byte[] DecodingByteArrayHelper(BerSafeHandle berElement, char fmt, ref int error)
+ {
+ error = 0;
+ IntPtr result = (IntPtr)0;
+ berval binaryValue = new berval();
+ byte[] byteArray = null;
+
+ // 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);
+
+ try
+ {
+ if (error == 0)
+ {
+ if (result != (IntPtr)0)
+ {
+ Marshal.PtrToStructure(result, binaryValue);
+
+ byteArray = new byte[binaryValue.bv_len];
+ Marshal.Copy(binaryValue.bv_val, byteArray, 0, binaryValue.bv_len);
+ }
+ }
+ else
+ Debug.WriteLine("ber_scanf for format character 'O' failed");
+ }
+ finally
+ {
+ if (result != (IntPtr)0)
+ Wldap32.ber_bvfree(result);
+ }
+
+ return byteArray;
+ }
+
+ private static int EncodingMultiByteArrayHelper(BerSafeHandle berElement, byte[][] tempValue, char fmt)
+ {
+ IntPtr berValArray = (IntPtr)0;
+ IntPtr tempPtr = (IntPtr)0;
+ SafeBerval[] managedBerVal = null;
+ int error = 0;
+
+ try
+ {
+ if (tempValue != null)
+ {
+ int i = 0;
+ berValArray = Utility.AllocHGlobalIntPtrArray(tempValue.Length + 1);
+ int structSize = Marshal.SizeOf(typeof(SafeBerval));
+ managedBerVal = new SafeBerval[tempValue.Length];
+
+ for (i = 0; i < tempValue.Length; i++)
+ {
+ byte[] byteArray = tempValue[i];
+
+ // construct the managed berval
+ managedBerVal[i] = new SafeBerval();
+
+ if (byteArray == null)
+ {
+ managedBerVal[i].bv_len = 0;
+ managedBerVal[i].bv_val = (IntPtr)0;
+ }
+ else
+ {
+ managedBerVal[i].bv_len = byteArray.Length;
+ managedBerVal[i].bv_val = Marshal.AllocHGlobal(byteArray.Length);
+ Marshal.Copy(byteArray, 0, managedBerVal[i].bv_val, byteArray.Length);
+ }
+
+ // allocate memory for the unmanaged structure
+ IntPtr valPtr = Marshal.AllocHGlobal(structSize);
+ Marshal.StructureToPtr(managedBerVal[i], valPtr, false);
+
+ tempPtr = (IntPtr)((long)berValArray + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, valPtr);
+ }
+
+ tempPtr = (IntPtr)((long)berValArray + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
+ }
+
+ error = Wldap32.ber_printf_berarray(berElement, new string(fmt, 1), berValArray);
+
+ GC.KeepAlive(managedBerVal);
+ }
+ finally
+ {
+ if (berValArray != (IntPtr)0)
+ {
+ for (int i = 0; i < tempValue.Length; i++)
+ {
+ IntPtr ptr = Marshal.ReadIntPtr(berValArray, Marshal.SizeOf(typeof(IntPtr)) * i);
+ if (ptr != (IntPtr)0)
+ Marshal.FreeHGlobal(ptr);
+ }
+ Marshal.FreeHGlobal(berValArray);
+ }
+ }
+
+ return error;
+ }
+
+ private static byte[][] DecodingMultiByteArrayHelper(BerSafeHandle berElement, char fmt, ref int error)
+ {
+ error = 0;
+ // several berval
+ IntPtr ptrResult = (IntPtr)0;
+ int i = 0;
+ ArrayList binaryList = new ArrayList();
+ IntPtr tempPtr = (IntPtr)0;
+ byte[][] result = null;
+
+ try
+ {
+ error = Wldap32.ber_scanf_ptr(berElement, new string(fmt, 1), ref ptrResult);
+
+ if (error == 0)
+ {
+ if (ptrResult != (IntPtr)0)
+ {
+ tempPtr = Marshal.ReadIntPtr(ptrResult);
+ while (tempPtr != (IntPtr)0)
+ {
+ berval ber = new berval();
+ Marshal.PtrToStructure(tempPtr, ber);
+
+ byte[] berArray = new byte[ber.bv_len];
+ Marshal.Copy(ber.bv_val, berArray, 0, ber.bv_len);
+
+ binaryList.Add(berArray);
+
+ i++;
+ tempPtr = Marshal.ReadIntPtr(ptrResult, i * Marshal.SizeOf(typeof(IntPtr)));
+ }
+
+ result = new byte[binaryList.Count][];
+ for (int j = 0; j < binaryList.Count; j++)
+ {
+ result[j] = (byte[])binaryList[j];
+ }
+ }
+ }
+ else
+ Debug.WriteLine("ber_scanf for format character 'V' failed");
+ }
+ finally
+ {
+ if (ptrResult != (IntPtr)0)
+ {
+ Wldap32.ber_bvecfree(ptrResult);
+ }
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DereferenceAlias.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DereferenceAlias.cs
new file mode 100644
index 0000000000..0ffe1b6ef7
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DereferenceAlias.cs
@@ -0,0 +1,14 @@
+// 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 enum DereferenceAlias
+ {
+ Never = 0,
+ InSearching = 1,
+ FindingBaseObject = 2,
+ Always = 3
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryAttribute.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryAttribute.cs
new file mode 100644
index 0000000000..178cf8729b
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryAttribute.cs
@@ -0,0 +1,708 @@
+// 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
+{
+ using System;
+ using System.Xml;
+ using System.Collections;
+ using System.ComponentModel;
+ using System.Globalization;
+ using System.Diagnostics;
+ using System.Text;
+
+ public class DirectoryAttribute : CollectionBase
+ {
+ private string _attributeName = "";
+ internal bool isSearchResult = false;
+ // does not request Unicode byte order mark prefix be emitted, but turn on error detection
+ private static UTF8Encoding s_utf8EncoderWithErrorDetection = new UTF8Encoding(false, true);
+ // with no error detection on
+ private static UTF8Encoding s_encoder = new UTF8Encoding();
+
+ public DirectoryAttribute()
+ {
+ Utility.CheckOSVersion();
+ }
+
+ public DirectoryAttribute(string name, string value) : this(name, (object)value)
+ {
+ }
+
+ public DirectoryAttribute(string name, byte[] value) : this(name, (object)value)
+ {
+ }
+
+ public DirectoryAttribute(string name, Uri value) : this(name, (object)value)
+ {
+ }
+
+ internal DirectoryAttribute(string name, object value) : this()
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ // set the name
+ Name = name;
+
+ // set the value;
+ Add(value);
+ }
+
+ public DirectoryAttribute(string name, params object[] values) : this()
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (values == null)
+ throw new ArgumentNullException("values");
+
+ // set the name
+ Name = name;
+
+ // set the value;
+ for (int i = 0; i < values.Length; i++)
+ {
+ Add(values[i]);
+ }
+ }
+
+ internal DirectoryAttribute(XmlElement node)
+ {
+ // retrieve attribute name
+ string primaryXPath = "@dsml:name";
+ string secondaryXPath = "@name";
+ XmlNamespaceManager dsmlNS = NamespaceUtils.GetDsmlNamespaceManager();
+
+ XmlAttribute attrName = (XmlAttribute)node.SelectSingleNode(primaryXPath, dsmlNS);
+
+ if (attrName == null)
+ {
+ // try it without the namespace qualifier, in case the sender omitted it
+ attrName = (XmlAttribute)node.SelectSingleNode(secondaryXPath, dsmlNS);
+
+ if (attrName == null)
+ {
+ // the element doesn't have a associated dn
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.MissingSearchResultEntryAttributeName));
+ }
+
+ _attributeName = attrName.Value;
+ }
+ else
+ {
+ _attributeName = attrName.Value;
+ }
+
+ // retrieve attribute value
+ XmlNodeList nodeList = node.SelectNodes("dsml:value", dsmlNS);
+
+ if (nodeList.Count != 0)
+ {
+ foreach (XmlNode valueNode in nodeList)
+ {
+ Debug.Assert(valueNode is XmlElement);
+
+ XmlAttribute valueType = (XmlAttribute)valueNode.SelectSingleNode("@xsi:type", dsmlNS);
+
+ if (valueType == null)
+ {
+ // value type is string
+ Add(valueNode.InnerText);
+ }
+ else
+ {
+ // value type is string
+ if (string.Compare(valueType.Value, "xsd:string", StringComparison.OrdinalIgnoreCase) == 0)
+ Add(valueNode.InnerText);
+ else if (string.Compare(valueType.Value, "xsd:base64Binary", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ string base64EncodedValue = valueNode.InnerText;
+ byte[] binaryValue;
+ try
+ {
+ binaryValue = System.Convert.FromBase64String(base64EncodedValue);
+ }
+ catch (FormatException)
+ {
+ // server returned invalid base64
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.BadBase64Value));
+ }
+
+ Add(binaryValue);
+ }
+ else if (string.Compare(valueType.Value, "xsd:anyURI", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ Uri uri = new Uri(valueNode.InnerText);
+ Add(uri);
+ }
+ }
+ }
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ return _attributeName;
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _attributeName = value;
+ }
+ }
+
+ public object[] GetValues(Type valuesType)
+ {
+ // user wants to return binary value
+ if (valuesType == typeof(byte[]))
+ {
+ int count = List.Count;
+ byte[][] results = new byte[count][];
+
+ for (int i = 0; i < count; i++)
+ {
+ if (List[i] is string)
+ results[i] = s_encoder.GetBytes((string)List[i]);
+ else if (List[i] is byte[])
+ {
+ results[i] = (byte[])List[i];
+ }
+ else
+ throw new NotSupportedException(Res.GetString(Res.DirectoryAttributeConversion));
+ }
+
+ return results;
+ }
+ // user wants to return string value
+ else if (valuesType == typeof(string))
+ {
+ int count = List.Count;
+ string[] results = new string[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ if (List[i] is string)
+ results[i] = (string)List[i];
+ else if (List[i] is byte[])
+ results[i] = s_encoder.GetString((byte[])List[i]);
+ else
+ throw new NotSupportedException(Res.GetString(Res.DirectoryAttributeConversion));
+ }
+
+ return results;
+ }
+ else
+ throw new ArgumentException(Res.GetString(Res.ValidDirectoryAttributeType), "valuesType");
+ }
+
+ public object this[int index]
+ {
+ get
+ {
+ if (!isSearchResult)
+ {
+ return List[index];
+ }
+ else
+ {
+ byte[] temp = List[index] as byte[];
+ if (temp != null)
+ {
+ try
+ {
+ return s_utf8EncoderWithErrorDetection.GetString(temp);
+ }
+ catch (ArgumentException)
+ {
+ return List[index];
+ }
+ }
+ else
+ {
+ // should not happen
+ return List[index];
+ }
+ }
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ else if ((value is string) || (value is byte[]) || (value is Uri))
+ List[index] = value;
+ else
+ throw new ArgumentException(Res.GetString(Res.ValidValueType), "value");
+ }
+ }
+
+ public int Add(byte[] value)
+ {
+ return Add((object)value);
+ }
+
+ public int Add(string value)
+ {
+ return Add((object)value);
+ }
+
+ public int Add(Uri value)
+ {
+ return Add((object)value);
+ }
+
+ internal int Add(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!(value is string) && !(value is byte[]) && !(value is Uri))
+ throw new ArgumentException(Res.GetString(Res.ValidValueType), "value");
+
+ return List.Add(value);
+ }
+
+ public void AddRange(object[] values)
+ {
+ if (values == null)
+ throw new ArgumentNullException("values");
+
+ if (!(values is string[]) && !(values is byte[][]) && !(values is Uri[]))
+ throw new ArgumentException(Res.GetString(Res.ValidValuesType), "values");
+
+ for (int i = 0; i < values.Length; i++)
+ if (values[i] == null)
+ throw new ArgumentException(Res.GetString(Res.NullValueArray), "values");
+
+ InnerList.AddRange(values);
+ }
+
+ public bool Contains(object value)
+ {
+ return List.Contains(value);
+ }
+
+ public void CopyTo(object[] array, int index)
+ {
+ List.CopyTo(array, index);
+ }
+
+ public int IndexOf(object value)
+ {
+ return List.IndexOf(value);
+ }
+
+ public void Insert(int index, byte[] value)
+ {
+ Insert(index, (object)value);
+ }
+
+ public void Insert(int index, string value)
+ {
+ Insert(index, (object)value);
+ }
+
+ public void Insert(int index, Uri value)
+ {
+ Insert(index, (object)value);
+ }
+
+ private void Insert(int index, object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ List.Insert(index, value);
+ }
+
+ public void Remove(object value)
+ {
+ List.Remove(value);
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!(value is string) && !(value is byte[]) && !(value is Uri))
+ throw new ArgumentException(Res.GetString(Res.ValidValueType), "value");
+ }
+
+ internal void ToXmlNodeCommon(XmlElement elemBase)
+ {
+ XmlDocument doc = elemBase.OwnerDocument;
+
+ XmlAttribute attrName = doc.CreateAttribute("name", null);
+ attrName.InnerText = Name;
+ elemBase.Attributes.Append(attrName);
+
+ // now create <value> child elements for each attribute value
+ if (Count != 0)
+ {
+ foreach (object o in InnerList)
+ {
+ XmlElement elemValue = doc.CreateElement("value", DsmlConstants.DsmlUri);
+
+ // Do the proper encoding, based on whether the object is a byte array
+ // or something else (encoded as a string)
+ if (o is byte[])
+ {
+ // base64 binary encoding
+ elemValue.InnerText = System.Convert.ToBase64String((byte[])o);
+
+ // append the "xsi:type=xsd:base64Binary" tag
+ XmlAttribute attrXsiType = doc.CreateAttribute("xsi:type", DsmlConstants.XsiUri);
+ attrXsiType.InnerText = "xsd:base64Binary";
+ elemValue.Attributes.Append(attrXsiType);
+ }
+ else if (o is Uri)
+ {
+ elemValue.InnerText = o.ToString();
+
+ // append the "xsi:type=xsd:anyURI" tag
+ XmlAttribute attrXsiType = doc.CreateAttribute("xsi:type", DsmlConstants.XsiUri);
+ attrXsiType.InnerText = "xsd:anyURI";
+ elemValue.Attributes.Append(attrXsiType);
+ }
+ else
+ {
+ // string encoding
+ elemValue.InnerText = o.ToString();
+
+ // append the space tag
+ if (elemValue.InnerText.StartsWith(" ", StringComparison.Ordinal) || elemValue.InnerText.EndsWith(" ", StringComparison.Ordinal))
+ {
+ XmlAttribute attrXsiType = doc.CreateAttribute("xml:space");
+ attrXsiType.InnerText = "preserve";
+ elemValue.Attributes.Append(attrXsiType);
+ }
+ }
+
+ elemBase.AppendChild(elemValue);
+ }
+ }
+ }
+
+ internal XmlElement ToXmlNode(XmlDocument doc, string elementName)
+ {
+ // create the <attr> element
+ XmlElement elemAttr = doc.CreateElement(elementName, DsmlConstants.DsmlUri);
+
+ // attach the "name" attribute and the <value> child elements
+ ToXmlNodeCommon(elemAttr);
+
+ return elemAttr;
+ }
+ }
+
+ public class DirectoryAttributeModification : DirectoryAttribute
+ {
+ private DirectoryAttributeOperation _attributeOperation = DirectoryAttributeOperation.Replace;
+
+ public DirectoryAttributeModification()
+ {
+ }
+
+ public DirectoryAttributeOperation Operation
+ {
+ get
+ {
+ return _attributeOperation;
+ }
+ set
+ {
+ if (value < DirectoryAttributeOperation.Add || value > DirectoryAttributeOperation.Replace)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(DirectoryAttributeOperation));
+
+ _attributeOperation = value;
+ }
+ }
+
+ internal XmlElement ToXmlNode(XmlDocument doc)
+ {
+ // create the <modification> element
+ XmlElement elemAttrMod = doc.CreateElement("modification", DsmlConstants.DsmlUri);
+
+ // attach the "name" attribute and the <value> child elements
+ ToXmlNodeCommon(elemAttrMod);
+
+ // attach the "operation" attribute
+ XmlAttribute attrName = doc.CreateAttribute("operation", null);
+
+ switch (Operation)
+ {
+ case DirectoryAttributeOperation.Replace:
+ attrName.InnerText = "replace";
+ break;
+
+ case DirectoryAttributeOperation.Add:
+ attrName.InnerText = "add";
+ break;
+
+ case DirectoryAttributeOperation.Delete:
+ attrName.InnerText = "delete";
+ break;
+
+ default:
+ throw new InvalidEnumArgumentException("Operation", (int)Operation, typeof(DirectoryAttributeOperation));
+ }
+
+ elemAttrMod.Attributes.Append(attrName);
+
+ return elemAttrMod;
+ }
+ }
+
+ public class SearchResultAttributeCollection : DictionaryBase
+ {
+ internal SearchResultAttributeCollection() { }
+
+ public DirectoryAttribute this[string attributeName]
+ {
+ get
+ {
+ if (attributeName == null)
+ throw new ArgumentNullException("attributeName");
+
+ object objectName = attributeName.ToLower(CultureInfo.InvariantCulture);
+ return (DirectoryAttribute)InnerHashtable[objectName];
+ }
+ }
+
+ public ICollection AttributeNames
+ {
+ get { return Dictionary.Keys; }
+ }
+
+ public ICollection Values
+ {
+ get
+ {
+ return Dictionary.Values;
+ }
+ }
+
+ internal void Add(string name, DirectoryAttribute value)
+ {
+ Dictionary.Add(name.ToLower(CultureInfo.InvariantCulture), value);
+ }
+
+ public bool Contains(string attributeName)
+ {
+ if (attributeName == null)
+ throw new ArgumentNullException("attributeName");
+
+ object objectName = attributeName.ToLower(CultureInfo.InvariantCulture);
+ return Dictionary.Contains(objectName);
+ }
+
+ public void CopyTo(DirectoryAttribute[] array, int index)
+ {
+ Dictionary.Values.CopyTo((Array)array, index);
+ }
+ }
+
+ public class DirectoryAttributeCollection : CollectionBase
+ {
+ public DirectoryAttributeCollection()
+ {
+ Utility.CheckOSVersion();
+ }
+
+ public DirectoryAttribute this[int index]
+ {
+ get
+ {
+ return (DirectoryAttribute)List[index];
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+
+ List[index] = value;
+ }
+ }
+
+ public int Add(DirectoryAttribute attribute)
+ {
+ if (attribute == null)
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+
+ return List.Add(attribute);
+ }
+
+ public void AddRange(DirectoryAttribute[] attributes)
+ {
+ if (attributes == null)
+ throw new ArgumentNullException("attributes");
+
+ foreach (DirectoryAttribute c in attributes)
+ {
+ if (c == null)
+ {
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+ }
+ }
+
+ InnerList.AddRange(attributes);
+ }
+
+ public void AddRange(DirectoryAttributeCollection attributeCollection)
+ {
+ if (attributeCollection == null)
+ {
+ throw new ArgumentNullException("attributeCollection");
+ }
+ int currentCount = attributeCollection.Count;
+ for (int i = 0; i < currentCount; i = ((i) + (1)))
+ {
+ this.Add(attributeCollection[i]);
+ }
+ }
+
+ public bool Contains(DirectoryAttribute value)
+ {
+ return List.Contains(value);
+ }
+
+ public void CopyTo(DirectoryAttribute[] array, int index)
+ {
+ List.CopyTo(array, index);
+ }
+
+ public int IndexOf(DirectoryAttribute value)
+ {
+ return List.IndexOf(value);
+ }
+
+ public void Insert(int index, DirectoryAttribute value)
+ {
+ if (value == null)
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+
+ List.Insert(index, value);
+ }
+
+ public void Remove(DirectoryAttribute value)
+ {
+ List.Remove(value);
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null)
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+
+ if (!(value is DirectoryAttribute))
+ throw new ArgumentException(Res.GetString(Res.InvalidValueType, "DirectoryAttribute"), "value");
+ }
+ }
+
+ public class DirectoryAttributeModificationCollection : CollectionBase
+ {
+ public DirectoryAttributeModificationCollection()
+ {
+ Utility.CheckOSVersion();
+ }
+
+ public DirectoryAttributeModification this[int index]
+ {
+ get
+ {
+ return (DirectoryAttributeModification)List[index];
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+
+ List[index] = value;
+ }
+ }
+
+ public int Add(DirectoryAttributeModification attribute)
+ {
+ if (attribute == null)
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+
+ return List.Add(attribute);
+ }
+
+ public void AddRange(DirectoryAttributeModification[] attributes)
+ {
+ if (attributes == null)
+ throw new ArgumentNullException("attributes");
+
+ foreach (DirectoryAttributeModification c in attributes)
+ {
+ if (c == null)
+ {
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+ }
+ }
+
+ InnerList.AddRange(attributes);
+ }
+
+ public void AddRange(DirectoryAttributeModificationCollection attributeCollection)
+ {
+ if (attributeCollection == null)
+ {
+ throw new ArgumentNullException("attributeCollection");
+ }
+ int currentCount = attributeCollection.Count;
+ for (int i = 0; i < currentCount; i = ((i) + (1)))
+ {
+ this.Add(attributeCollection[i]);
+ }
+ }
+
+ public bool Contains(DirectoryAttributeModification value)
+ {
+ return List.Contains(value);
+ }
+
+ public void CopyTo(DirectoryAttributeModification[] array, int index)
+ {
+ List.CopyTo(array, index);
+ }
+
+ public int IndexOf(DirectoryAttributeModification value)
+ {
+ return List.IndexOf(value);
+ }
+
+ public void Insert(int index, DirectoryAttributeModification value)
+ {
+ if (value == null)
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+
+ List.Insert(index, value);
+ }
+
+ public void Remove(DirectoryAttributeModification value)
+ {
+ List.Remove(value);
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null)
+ throw new ArgumentException(Res.GetString(Res.NullDirectoryAttributeCollection));
+
+ if (!(value is DirectoryAttributeModification))
+ throw new ArgumentException(Res.GetString(Res.InvalidValueType, "DirectoryAttributeModification"), "value");
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryAttributeOperation.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryAttributeOperation.cs
new file mode 100644
index 0000000000..6c4b7cf8a9
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryAttributeOperation.cs
@@ -0,0 +1,13 @@
+// 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 enum DirectoryAttributeOperation
+ {
+ Add = 0,
+ Delete = 1,
+ Replace = 2
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryConnection.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryConnection.cs
new file mode 100644
index 0000000000..35322d910a
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryConnection.cs
@@ -0,0 +1,85 @@
+// 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
+{
+ using System;
+ using System.Net;
+ using System.Security.Cryptography.X509Certificates;
+ using System.Security.Permissions;
+
+ public abstract class DirectoryConnection
+ {
+ //
+ // Private/protected
+ //
+ internal NetworkCredential directoryCredential = null;
+ internal X509CertificateCollection certificatesCollection = null;
+ internal TimeSpan connectionTimeOut = new TimeSpan(0, 0, 30);
+ internal DirectoryIdentifier directoryIdentifier = null;
+
+ protected DirectoryConnection()
+ {
+ Utility.CheckOSVersion();
+
+ certificatesCollection = new X509CertificateCollection();
+ }
+
+ public virtual DirectoryIdentifier Directory
+ {
+ get
+ {
+ return directoryIdentifier;
+ }
+ }
+
+ public X509CertificateCollection ClientCertificates
+ {
+ get
+ {
+ return certificatesCollection;
+ }
+ }
+
+ public virtual TimeSpan Timeout
+ {
+ get
+ {
+ return connectionTimeOut;
+ }
+ set
+ {
+ if (value < TimeSpan.Zero)
+ {
+ throw new ArgumentException(Res.GetString(Res.NoNegativeTime), "value");
+ }
+
+ connectionTimeOut = value;
+ }
+ }
+
+ public virtual NetworkCredential Credential
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ EnvironmentPermission(SecurityAction.Assert, Unrestricted = true),
+ SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
+ ]
+ set
+ {
+ directoryCredential = (value != null) ? new NetworkCredential(value.UserName, value.Password, value.Domain) : null;
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public abstract DirectoryResponse SendRequest(DirectoryRequest request);
+
+ internal NetworkCredential GetCredential()
+ {
+ return directoryCredential;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryControl.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryControl.cs
new file mode 100644
index 0000000000..a2d2c551d7
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryControl.cs
@@ -0,0 +1,1507 @@
+// 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
+{
+ using System;
+ using System.Xml;
+ using System.Collections;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Text;
+ using System.Runtime.InteropServices;
+ using System.Security.Principal;
+
+ public enum ExtendedDNFlag
+ {
+ HexString = 0,
+ StandardString = 1
+ }
+
+ [Flags]
+ public enum SecurityMasks
+ {
+ None = 0,
+ Owner = 1,
+ Group = 2,
+ Dacl = 4,
+ Sacl = 8
+ }
+
+ [Flags]
+ public enum DirectorySynchronizationOptions : long
+ {
+ None = 0,
+ ObjectSecurity = 0x1,
+ ParentsFirst = 0x0800,
+ PublicDataOnly = 0x2000,
+ IncrementalValues = 0x80000000
+ }
+
+ public enum SearchOption
+ {
+ DomainScope = 1,
+ PhantomRoot = 2
+ }
+
+ internal class UtilityHandle
+ {
+ private static ConnectionHandle s_handle = new ConnectionHandle();
+
+ public static ConnectionHandle GetHandle()
+ {
+ return s_handle;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public class SortKey
+ {
+ private string _name = null;
+ private string _rule = null;
+ private bool _order = false;
+
+ public SortKey()
+ {
+ Utility.CheckOSVersion();
+ }
+
+ public SortKey(string attributeName, string matchingRule, bool reverseOrder)
+ {
+ Utility.CheckOSVersion();
+
+ AttributeName = attributeName;
+ _rule = matchingRule;
+ _order = reverseOrder;
+ }
+
+ public string AttributeName
+ {
+ get
+ {
+ return _name;
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _name = value;
+ }
+ }
+
+ public string MatchingRule
+ {
+ get
+ {
+ return _rule;
+ }
+ set
+ {
+ _rule = value;
+ }
+ }
+
+ public bool ReverseOrder
+ {
+ get
+ {
+ return _order;
+ }
+
+ set
+ {
+ _order = value;
+ }
+ }
+ }
+
+ public class DirectoryControl
+ {
+ // control value
+ internal byte[] directoryControlValue = null;
+ // oid of the control
+ private string _directoryControlType = "";
+ // criticality of the control
+ private bool _directoryControlCriticality = true;
+ // whether it is a server side control or not
+ private bool _directoryControlServerSide = true;
+
+ public DirectoryControl(string type, byte[] value, bool isCritical, bool serverSide)
+ {
+ Utility.CheckOSVersion();
+
+ _directoryControlType = type;
+ if (type == null)
+ throw new ArgumentNullException("type");
+
+ if (value != null)
+ {
+ directoryControlValue = new byte[value.Length];
+ for (int i = 0; i < value.Length; i++)
+ directoryControlValue[i] = value[i];
+ }
+ _directoryControlCriticality = isCritical;
+ _directoryControlServerSide = serverSide;
+ }
+
+ internal DirectoryControl(XmlElement el)
+ {
+ XmlNamespaceManager ns = NamespaceUtils.GetDsmlNamespaceManager();
+
+ //
+ // Populate the control's criticality
+ //
+ XmlAttribute attrCriticality = (XmlAttribute)el.SelectSingleNode("@dsml:criticality", ns);
+
+ if (attrCriticality == null)
+ {
+ // try it without the namespace qualifier, in case the sender omitted it
+ attrCriticality = (XmlAttribute)el.SelectSingleNode("@criticality", ns);
+ }
+
+ if (attrCriticality == null)
+ {
+ // DSML v2 defaults criticality to false if not present in the XML
+ _directoryControlCriticality = false;
+ }
+ else
+ {
+ string s = attrCriticality.Value;
+
+ if ((s == "true") ||
+ (s == "1"))
+ {
+ _directoryControlCriticality = true;
+ }
+ else if ((s == "false") ||
+ (s == "0"))
+ {
+ _directoryControlCriticality = false;
+ }
+ else
+ {
+ Debug.WriteLine("Processing response, the control has wrong value of crticality specified");
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.BadControl));
+ }
+ }
+
+ //
+ // Populate the control's name (Type)
+ //
+ XmlAttribute attrType = (XmlAttribute)el.SelectSingleNode("@dsml:type", ns);
+
+ if (attrType == null)
+ {
+ // try it without the namespace qualifier, in case the sender omitted it
+ attrType = (XmlAttribute)el.SelectSingleNode("@type", ns);
+ }
+
+ if (attrType == null)
+ {
+ // DSML v2 requires the control to specify a type
+ Debug.WriteLine("Processing response, the control does not have oid defined");
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.BadControl));
+ }
+ else
+ {
+ _directoryControlType = attrType.Value;
+ }
+
+ //
+ // Populate the control's value
+ //
+ XmlElement elemValue = (XmlElement)el.SelectSingleNode("dsml:controlValue", ns);
+
+ if (elemValue != null)
+ {
+ try
+ {
+ this.directoryControlValue = System.Convert.FromBase64String(elemValue.InnerText);
+ }
+ catch (FormatException)
+ {
+ Debug.WriteLine("Processing response, converting control value failed");
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.BadControl));
+ }
+ }
+ }
+
+ public virtual byte[] GetValue()
+ {
+ if (directoryControlValue == null)
+ return new byte[0];
+ else
+ {
+ byte[] tempValue = new byte[directoryControlValue.Length];
+ for (int i = 0; i < directoryControlValue.Length; i++)
+ tempValue[i] = directoryControlValue[i];
+ return tempValue;
+ }
+ }
+
+ public string Type
+ {
+ get
+ {
+ return _directoryControlType;
+ }
+ }
+
+ public bool IsCritical
+ {
+ get
+ {
+ return _directoryControlCriticality;
+ }
+ set
+ {
+ _directoryControlCriticality = value;
+ }
+ }
+
+ public bool ServerSide
+ {
+ get
+ {
+ return _directoryControlServerSide;
+ }
+ set
+ {
+ _directoryControlServerSide = value;
+ }
+ }
+
+ // Returns an XmlElement representing this control,
+ // in DSML v2 format.
+ internal XmlElement ToXmlNode(XmlDocument doc)
+ {
+ // create the <control> element
+ XmlElement elem = doc.CreateElement("control", DsmlConstants.DsmlUri);
+
+ // attach the "type" and "criticality" attributes to the <control> element
+ XmlAttribute attrType = doc.CreateAttribute("type", null);
+ attrType.InnerText = Type;
+ elem.Attributes.Append(attrType);
+
+ XmlAttribute attrCrit = doc.CreateAttribute("criticality", null);
+ attrCrit.InnerText = IsCritical ? "true" : "false";
+ elem.Attributes.Append(attrCrit);
+
+ byte[] controlValue = GetValue();
+ if (controlValue.Length != 0)
+ {
+ // create the <controlValue> element
+ XmlElement elemValue = doc.CreateElement("controlValue", DsmlConstants.DsmlUri);
+
+ // append the "xsi:type=xsd:base64Binary" attribute to <controlValue>
+ XmlAttribute attrXsiType = doc.CreateAttribute("xsi:type", DsmlConstants.XsiUri);
+ attrXsiType.InnerText = "xsd:base64Binary";
+ elemValue.Attributes.Append(attrXsiType);
+
+ // add in the base-64 encoded value itself
+ string base64value = System.Convert.ToBase64String(controlValue);
+ elemValue.InnerText = base64value;
+
+ // attach the <controlValue> element to the <control> element
+ elem.AppendChild(elemValue);
+ }
+
+ return elem;
+ }
+
+ internal static void TransformControls(DirectoryControl[] controls)
+ {
+ for (int i = 0; i < controls.Length; i++)
+ {
+ Debug.Assert(controls[i] != null);
+ byte[] value = controls[i].GetValue();
+ // if it is a page control
+ if (controls[i].Type == "1.2.840.113556.1.4.319")
+ {
+ object[] result = BerConverter.Decode("{iO}", value);
+ Debug.Assert((result != null) && (result.Length == 2));
+
+ int size = (int)result[0];
+ byte[] cookie = (byte[])result[1];
+ // user expects cookie with length 0 as paged search is done.
+ if (cookie == null)
+ cookie = new byte[0];
+
+ PageResultResponseControl pageControl = new PageResultResponseControl(size, cookie, controls[i].IsCritical, controls[i].GetValue());
+ controls[i] = pageControl;
+ }
+ else if (controls[i].Type == "1.2.840.113556.1.4.1504")
+ {
+ // asq control
+ object[] o = null;
+ if (Utility.IsWin2kOS)
+ o = BerConverter.Decode("{i}", value);
+ else
+ o = BerConverter.Decode("{e}", value);
+ Debug.Assert((o != null) && (o.Length == 1));
+
+ int result = (int)o[0];
+ AsqResponseControl asq = new AsqResponseControl(result, controls[i].IsCritical, controls[i].GetValue());
+ controls[i] = asq;
+ }
+ else if (controls[i].Type == "1.2.840.113556.1.4.841")
+ {
+ //dirsync control
+ object[] o = BerConverter.Decode("{iiO}", value);
+ Debug.Assert(o != null && o.Length == 3);
+
+ int moreData = (int)o[0];
+ int count = (int)o[1];
+ byte[] dirsyncCookie = (byte[])o[2];
+
+ DirSyncResponseControl dirsync = new DirSyncResponseControl(dirsyncCookie, (moreData == 0 ? false : true), count, controls[i].IsCritical, controls[i].GetValue());
+ controls[i] = dirsync;
+ }
+ else if (controls[i].Type == "1.2.840.113556.1.4.474")
+ {
+ object[] o = null;
+ int result = 0;
+ string attribute = null;
+ bool decodeSucceeded;
+ //sort control
+
+ if (Utility.IsWin2kOS)
+ // win2k berencoding does not understand enumeration
+ o = BerConverter.TryDecode("{ia}", value, out decodeSucceeded);
+ else
+ o = BerConverter.TryDecode("{ea}", value, out decodeSucceeded);
+
+ // decode might fail as AD for example never returns attribute name, we don't want to unnecessarily throw and catch exception
+ if (decodeSucceeded)
+ {
+ Debug.Assert(o != null && o.Length == 2);
+ result = (int)o[0];
+ attribute = (string)o[1];
+ }
+ else
+ {
+ // decoding might fail as attribute is optional
+ if (Utility.IsWin2kOS)
+ // win2k berencoding does not understand enumeration
+ o = BerConverter.Decode("{i}", value);
+ else
+ o = BerConverter.Decode("{e}", value);
+ Debug.Assert(o != null && o.Length == 1);
+
+ result = (int)o[0];
+ }
+
+ SortResponseControl sort = new SortResponseControl((ResultCode)result, attribute, controls[i].IsCritical, controls[i].GetValue());
+ controls[i] = sort;
+ }
+ else if (controls[i].Type == "2.16.840.1.113730.3.4.10")
+ {
+ int position;
+ int count;
+ int result;
+ byte[] context = null;
+ object[] o = null;
+ bool decodeSucceeded = false;
+
+ if (Utility.IsWin2kOS)
+ // win2k berencoding does not understand enumeration
+ o = BerConverter.TryDecode("{iiiO}", value, out decodeSucceeded);
+ else
+ o = BerConverter.TryDecode("{iieO}", value, out decodeSucceeded);
+
+ if (decodeSucceeded)
+ {
+ Debug.Assert(o != null && o.Length == 4);
+ position = (int)o[0];
+ count = (int)o[1];
+ result = (int)o[2];
+ context = (byte[])o[3];
+ }
+ else
+ {
+ if (Utility.IsWin2kOS)
+ // win2k berencoding does not understand enumeration
+ o = BerConverter.Decode("{iii}", value);
+ else
+ o = BerConverter.Decode("{iie}", value);
+ Debug.Assert(o != null && o.Length == 3);
+ position = (int)o[0];
+ count = (int)o[1];
+ result = (int)o[2];
+ }
+
+ VlvResponseControl vlv = new VlvResponseControl(position, count, context, (ResultCode)result, controls[i].IsCritical, controls[i].GetValue());
+ controls[i] = vlv;
+ }
+ }
+ }
+ }
+
+ public class AsqRequestControl : DirectoryControl
+ {
+ private string _name;
+ public AsqRequestControl() : base("1.2.840.113556.1.4.1504", null, true, true)
+ {
+ }
+
+ public AsqRequestControl(string attributeName) : this()
+ {
+ _name = attributeName;
+ }
+
+ public string AttributeName
+ {
+ get
+ {
+ return _name;
+ }
+ set
+ {
+ _name = value;
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ this.directoryControlValue = BerConverter.Encode("{s}", new object[] { _name });
+ return base.GetValue();
+ }
+ }
+
+ public class AsqResponseControl : DirectoryControl
+ {
+ private ResultCode _result;
+
+ internal AsqResponseControl(int result, bool criticality, byte[] controlValue) : base("1.2.840.113556.1.4.1504", controlValue, criticality, true)
+ {
+ _result = (ResultCode)result;
+ }
+
+ public ResultCode Result
+ {
+ get
+ {
+ return _result;
+ }
+ }
+ }
+
+ public class CrossDomainMoveControl : DirectoryControl
+ {
+ private string _dcName = null;
+ public CrossDomainMoveControl() : base("1.2.840.113556.1.4.521", null, true, true)
+ {
+ }
+
+ public CrossDomainMoveControl(string targetDomainController) : this()
+ {
+ _dcName = targetDomainController;
+ }
+
+ public string TargetDomainController
+ {
+ get
+ {
+ return _dcName;
+ }
+ set
+ {
+ _dcName = value;
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ if (_dcName != null)
+ {
+ UTF8Encoding encoder = new UTF8Encoding();
+ byte[] bytes = encoder.GetBytes(_dcName);
+
+ // allocate large enough space for the '\0' character
+ this.directoryControlValue = new byte[bytes.Length + 2];
+ for (int i = 0; i < bytes.Length; i++)
+ this.directoryControlValue[i] = bytes[i];
+ }
+ return base.GetValue();
+ }
+ }
+
+ public class DomainScopeControl : DirectoryControl
+ {
+ public DomainScopeControl() : base("1.2.840.113556.1.4.1339", null, true, true)
+ {
+ }
+ }
+
+ public class ExtendedDNControl : DirectoryControl
+ {
+ private ExtendedDNFlag _format = ExtendedDNFlag.HexString;
+
+ public ExtendedDNControl() : base("1.2.840.113556.1.4.529", null, true, true)
+ {
+ }
+
+ public ExtendedDNControl(ExtendedDNFlag flag) : this()
+ {
+ Flag = flag;
+ }
+
+ public ExtendedDNFlag Flag
+ {
+ get
+ {
+ return _format;
+ }
+ set
+ {
+ if (value < ExtendedDNFlag.HexString || value > ExtendedDNFlag.StandardString)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(ExtendedDNFlag));
+
+ _format = value;
+ }
+ }
+ public override byte[] GetValue()
+ {
+ this.directoryControlValue = BerConverter.Encode("{i}", new object[] { (int)_format });
+ return base.GetValue();
+ }
+ }
+
+ public class LazyCommitControl : DirectoryControl
+ {
+ public LazyCommitControl() : base("1.2.840.113556.1.4.619", null, true, true) { }
+ }
+
+ public class DirectoryNotificationControl : DirectoryControl
+ {
+ public DirectoryNotificationControl() : base("1.2.840.113556.1.4.528", null, true, true) { }
+ }
+
+ public class PermissiveModifyControl : DirectoryControl
+ {
+ public PermissiveModifyControl() : base("1.2.840.113556.1.4.1413", null, true, true) { }
+ }
+
+ public class SecurityDescriptorFlagControl : DirectoryControl
+ {
+ private SecurityMasks _flag = SecurityMasks.None;
+
+ public SecurityDescriptorFlagControl() : base("1.2.840.113556.1.4.801", null, true, true) { }
+
+ public SecurityDescriptorFlagControl(SecurityMasks masks) : this()
+ {
+ SecurityMasks = masks;
+ }
+
+ public SecurityMasks SecurityMasks
+ {
+ get
+ {
+ return _flag;
+ }
+ set
+ {
+ // we don't do validation to the dirsync flag here as underneath API does not check for it and we don't want to put
+ // unnecessary limitation on it.
+
+ _flag = value;
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ this.directoryControlValue = BerConverter.Encode("{i}", new object[] { (int)_flag });
+ return base.GetValue();
+ }
+ }
+
+ public class SearchOptionsControl : DirectoryControl
+ {
+ private SearchOption _flag = SearchOption.DomainScope;
+ public SearchOptionsControl() : base("1.2.840.113556.1.4.1340", null, true, true) { }
+
+ public SearchOptionsControl(SearchOption flags) : this()
+ {
+ SearchOption = flags;
+ }
+
+ public SearchOption SearchOption
+ {
+ get
+ {
+ return _flag;
+ }
+ set
+ {
+ if (value < SearchOption.DomainScope || value > SearchOption.PhantomRoot)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(SearchOption));
+
+ _flag = value;
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ this.directoryControlValue = BerConverter.Encode("{i}", new object[] { (int)_flag });
+ return base.GetValue();
+ }
+ }
+
+ public class ShowDeletedControl : DirectoryControl
+ {
+ public ShowDeletedControl() : base("1.2.840.113556.1.4.417", null, true, true) { }
+ }
+
+ public class TreeDeleteControl : DirectoryControl
+ {
+ public TreeDeleteControl() : base("1.2.840.113556.1.4.805", null, true, true) { }
+ }
+
+ public class VerifyNameControl : DirectoryControl
+ {
+ private string _name = null;
+ private int _flag = 0;
+
+ public VerifyNameControl() : base("1.2.840.113556.1.4.1338", null, true, true) { }
+
+ public VerifyNameControl(string serverName) : this()
+ {
+ if (serverName == null)
+ throw new ArgumentNullException("serverName");
+
+ _name = serverName;
+ }
+
+ public VerifyNameControl(string serverName, int flag) : this(serverName)
+ {
+ _flag = flag;
+ }
+
+ public string ServerName
+ {
+ get
+ {
+ return _name;
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _name = value;
+ }
+ }
+
+ public int Flag
+ {
+ get
+ {
+ return _flag;
+ }
+ set
+ {
+ _flag = value;
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ byte[] tmpValue = null;
+ if (ServerName != null)
+ {
+ UnicodeEncoding unicode = new UnicodeEncoding();
+ tmpValue = unicode.GetBytes(ServerName);
+ }
+ this.directoryControlValue = BerConverter.Encode("{io}", new object[] { _flag, tmpValue });
+ return base.GetValue();
+ }
+ }
+
+ public class DirSyncRequestControl : DirectoryControl
+ {
+ private byte[] _dirsyncCookie = null;
+ private DirectorySynchronizationOptions _flag = DirectorySynchronizationOptions.None;
+ private int _count = 1048576;
+
+ public DirSyncRequestControl() : base("1.2.840.113556.1.4.841", null, true, true) { }
+ public DirSyncRequestControl(byte[] cookie) : this()
+ {
+ _dirsyncCookie = cookie;
+ }
+
+ public DirSyncRequestControl(byte[] cookie, DirectorySynchronizationOptions option) : this(cookie)
+ {
+ Option = option;
+ }
+
+ public DirSyncRequestControl(byte[] cookie, DirectorySynchronizationOptions option, int attributeCount) : this(cookie, option)
+ {
+ AttributeCount = attributeCount;
+ }
+
+ public byte[] Cookie
+ {
+ get
+ {
+ if (_dirsyncCookie == null)
+ return new byte[0];
+ else
+ {
+ byte[] tempCookie = new byte[_dirsyncCookie.Length];
+ for (int i = 0; i < tempCookie.Length; i++)
+ tempCookie[i] = _dirsyncCookie[i];
+
+ return tempCookie;
+ }
+ }
+ set
+ {
+ _dirsyncCookie = value;
+ }
+ }
+
+ public DirectorySynchronizationOptions Option
+ {
+ get
+ {
+ return _flag;
+ }
+ set
+ {
+ // we don't do validation to the dirsync flag here as underneath API does not check for it and we don't want to put
+ // unnecessary limitation on it.
+
+ _flag = value;
+ }
+ }
+
+ public int AttributeCount
+ {
+ get
+ {
+ return _count;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.ValidValue), "value");
+
+ _count = value;
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ object[] o = new object[] { (int)_flag, _count, _dirsyncCookie };
+ this.directoryControlValue = BerConverter.Encode("{iio}", o);
+ return base.GetValue();
+ }
+ }
+
+ public class DirSyncResponseControl : DirectoryControl
+ {
+ private byte[] _dirsyncCookie = null;
+ private bool _moreResult = false;
+ private int _size = 0;
+
+ internal DirSyncResponseControl(byte[] cookie, bool moreData, int resultSize, bool criticality, byte[] controlValue) : base("1.2.840.113556.1.4.841", controlValue, criticality, true)
+ {
+ _dirsyncCookie = cookie;
+ _moreResult = moreData;
+ _size = resultSize;
+ }
+
+ public byte[] Cookie
+ {
+ get
+ {
+ if (_dirsyncCookie == null)
+ return new byte[0];
+ else
+ {
+ byte[] tempCookie = new byte[_dirsyncCookie.Length];
+ for (int i = 0; i < tempCookie.Length; i++)
+ tempCookie[i] = _dirsyncCookie[i];
+
+ return tempCookie;
+ }
+ }
+ }
+
+ public bool MoreData
+ {
+ get
+ {
+ return _moreResult;
+ }
+ }
+
+ public int ResultSize
+ {
+ get
+ {
+ return _size;
+ }
+ }
+ }
+
+ public class PageResultRequestControl : DirectoryControl
+ {
+ private int _size = 512;
+ private byte[] _pageCookie = null;
+
+ public PageResultRequestControl() : base("1.2.840.113556.1.4.319", null, true, true) { }
+
+ public PageResultRequestControl(int pageSize) : this()
+ {
+ PageSize = pageSize;
+ }
+
+ public PageResultRequestControl(byte[] cookie) : this()
+ {
+ _pageCookie = cookie;
+ }
+
+ public int PageSize
+ {
+ get
+ {
+ return _size;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.ValidValue), "value");
+
+ _size = value;
+ }
+ }
+
+ public byte[] Cookie
+ {
+ get
+ {
+ if (_pageCookie == null)
+ return new byte[0];
+
+ byte[] tempCookie = new byte[_pageCookie.Length];
+ for (int i = 0; i < _pageCookie.Length; i++)
+ tempCookie[i] = _pageCookie[i];
+
+ return tempCookie;
+ }
+ set
+ {
+ _pageCookie = value;
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ object[] o = new object[] { _size, _pageCookie };
+ this.directoryControlValue = BerConverter.Encode("{io}", o);
+ return base.GetValue();
+ }
+ }
+
+ public class PageResultResponseControl : DirectoryControl
+ {
+ private byte[] _pageCookie = null;
+ private int _count = 0;
+ internal PageResultResponseControl(int count, byte[] cookie, bool criticality, byte[] controlValue) : base("1.2.840.113556.1.4.319", controlValue, criticality, true)
+ {
+ _count = count;
+ _pageCookie = cookie;
+ }
+
+ public byte[] Cookie
+ {
+ get
+ {
+ if (_pageCookie == null)
+ return new byte[0];
+ else
+ {
+ byte[] tempCookie = new byte[_pageCookie.Length];
+ for (int i = 0; i < _pageCookie.Length; i++)
+ {
+ tempCookie[i] = _pageCookie[i];
+ }
+ return tempCookie;
+ }
+ }
+ }
+
+ public int TotalCount
+ {
+ get
+ {
+ return _count;
+ }
+ }
+ }
+
+ public class SortRequestControl : DirectoryControl
+ {
+ private SortKey[] _keys = new SortKey[0];
+ public SortRequestControl(params SortKey[] sortKeys) : base("1.2.840.113556.1.4.473", null, true, true)
+ {
+ if (sortKeys == null)
+ throw new ArgumentNullException("sortKeys");
+
+ for (int i = 0; i < sortKeys.Length; i++)
+ {
+ if (sortKeys[i] == null)
+ throw new ArgumentException(Res.GetString(Res.NullValueArray), "sortKeys");
+ }
+
+ _keys = new SortKey[sortKeys.Length];
+ for (int i = 0; i < sortKeys.Length; i++)
+ {
+ _keys[i] = new SortKey(sortKeys[i].AttributeName, sortKeys[i].MatchingRule, sortKeys[i].ReverseOrder);
+ }
+ }
+
+ public SortRequestControl(string attributeName, bool reverseOrder) : this(attributeName, null, reverseOrder)
+ {
+ }
+
+ public SortRequestControl(string attributeName, string matchingRule, bool reverseOrder) : base("1.2.840.113556.1.4.473", null, true, true)
+ {
+ SortKey key = new SortKey(attributeName, matchingRule, reverseOrder);
+ _keys = new SortKey[1];
+ _keys[0] = key;
+ }
+
+ public SortKey[] SortKeys
+ {
+ get
+ {
+ if (_keys == null)
+ return new SortKey[0];
+ else
+ {
+ SortKey[] tempKeys = new SortKey[_keys.Length];
+ for (int i = 0; i < _keys.Length; i++)
+ {
+ tempKeys[i] = new SortKey(_keys[i].AttributeName, _keys[i].MatchingRule, _keys[i].ReverseOrder);
+ }
+
+ return tempKeys;
+ }
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ for (int i = 0; i < value.Length; i++)
+ {
+ if (value[i] == null)
+ throw new ArgumentException(Res.GetString(Res.NullValueArray), "value");
+ }
+
+ _keys = new SortKey[value.Length];
+ for (int i = 0; i < value.Length; i++)
+ {
+ _keys[i] = new SortKey(value[i].AttributeName, value[i].MatchingRule, value[i].ReverseOrder);
+ }
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ IntPtr control = (IntPtr)0;
+ int structSize = Marshal.SizeOf(typeof(SortKey));
+ int keyCount = _keys.Length;
+ IntPtr memHandle = Utility.AllocHGlobalIntPtrArray(keyCount + 1);
+
+ try
+ {
+ IntPtr tempPtr = (IntPtr)0;
+ IntPtr sortPtr = (IntPtr)0;
+ int i = 0;
+ for (i = 0; i < keyCount; i++)
+ {
+ sortPtr = Marshal.AllocHGlobal(structSize);
+ Marshal.StructureToPtr(_keys[i], sortPtr, false);
+ tempPtr = (IntPtr)((long)memHandle + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, sortPtr);
+ }
+ tempPtr = (IntPtr)((long)memHandle + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
+
+ bool critical = IsCritical;
+ int error = Wldap32.ldap_create_sort_control(UtilityHandle.GetHandle(), memHandle, critical ? (byte)1 : (byte)0, ref control);
+
+ if (error != 0)
+ {
+ if (Utility.IsLdapError((LdapError)error))
+ {
+ string errorMessage = LdapErrorMappings.MapResultCode(error);
+ throw new LdapException(error, errorMessage);
+ }
+ else
+ throw new LdapException(error);
+ }
+
+ LdapControl managedControl = new LdapControl();
+ Marshal.PtrToStructure(control, managedControl);
+ berval value = managedControl.ldctl_value;
+ // reinitialize the value
+ directoryControlValue = null;
+ if (value != null)
+ {
+ directoryControlValue = new byte[value.bv_len];
+ Marshal.Copy(value.bv_val, directoryControlValue, 0, value.bv_len);
+ }
+ }
+ finally
+ {
+ if (control != (IntPtr)0)
+ Wldap32.ldap_control_free(control);
+
+ if (memHandle != (IntPtr)0)
+ {
+ //release the memory from the heap
+ for (int i = 0; i < keyCount; i++)
+ {
+ IntPtr tempPtr = Marshal.ReadIntPtr(memHandle, Marshal.SizeOf(typeof(IntPtr)) * i);
+ if (tempPtr != (IntPtr)0)
+ {
+ // free the marshalled name
+ IntPtr ptr = Marshal.ReadIntPtr(tempPtr);
+ if (ptr != (IntPtr)0)
+ Marshal.FreeHGlobal(ptr);
+ // free the marshalled rule
+ ptr = Marshal.ReadIntPtr(tempPtr, Marshal.SizeOf(typeof(IntPtr)));
+ if (ptr != (IntPtr)0)
+ Marshal.FreeHGlobal(ptr);
+
+ Marshal.FreeHGlobal(tempPtr);
+ }
+ }
+ Marshal.FreeHGlobal(memHandle);
+ }
+ }
+
+ return base.GetValue();
+ }
+ }
+
+ public class SortResponseControl : DirectoryControl
+ {
+ private ResultCode _result;
+ private string _name;
+
+ internal SortResponseControl(ResultCode result, string attributeName, bool critical, byte[] value) : base("1.2.840.113556.1.4.474", value, critical, true)
+ {
+ _result = result;
+ _name = attributeName;
+ }
+
+ public ResultCode Result
+ {
+ get
+ {
+ return _result;
+ }
+ }
+
+ public string AttributeName
+ {
+ get
+ {
+ return _name;
+ }
+ }
+ }
+
+ public class VlvRequestControl : DirectoryControl
+ {
+ private int _before = 0;
+ private int _after = 0;
+ private int _offset = 0;
+ private int _estimateCount = 0;
+ private byte[] _target = null;
+ private byte[] _context = null;
+
+ public VlvRequestControl() : base("2.16.840.1.113730.3.4.9", null, true, true) { }
+
+ public VlvRequestControl(int beforeCount, int afterCount, int offset) : this()
+ {
+ BeforeCount = beforeCount;
+ AfterCount = afterCount;
+ Offset = offset;
+ }
+
+ public VlvRequestControl(int beforeCount, int afterCount, string target) : this()
+ {
+ BeforeCount = beforeCount;
+ AfterCount = afterCount;
+ if (target != null)
+ {
+ UTF8Encoding encoder = new UTF8Encoding();
+ byte[] bytes = encoder.GetBytes(target);
+ _target = bytes;
+ }
+ }
+
+ public VlvRequestControl(int beforeCount, int afterCount, byte[] target) : this()
+ {
+ BeforeCount = beforeCount;
+ AfterCount = afterCount;
+ Target = target;
+ }
+
+ public int BeforeCount
+ {
+ get
+ {
+ return _before;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.ValidValue), "value");
+
+ _before = value;
+ }
+ }
+
+ public int AfterCount
+ {
+ get
+ {
+ return _after;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.ValidValue), "value");
+
+ _after = value;
+ }
+ }
+
+ public int Offset
+ {
+ get
+ {
+ return _offset;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.ValidValue), "value");
+
+ _offset = value;
+ }
+ }
+
+ public int EstimateCount
+ {
+ get
+ {
+ return _estimateCount;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.ValidValue), "value");
+
+ _estimateCount = value;
+ }
+ }
+
+ public byte[] Target
+ {
+ get
+ {
+ if (_target == null)
+ return new byte[0];
+ else
+ {
+ byte[] tempContext = new byte[_target.Length];
+ for (int i = 0; i < tempContext.Length; i++)
+ {
+ tempContext[i] = _target[i];
+ }
+
+ return tempContext;
+ }
+ }
+ set
+ {
+ _target = value;
+ }
+ }
+
+ public byte[] ContextId
+ {
+ get
+ {
+ if (_context == null)
+ return new byte[0];
+ else
+ {
+ byte[] tempContext = new byte[_context.Length];
+ for (int i = 0; i < tempContext.Length; i++)
+ {
+ tempContext[i] = _context[i];
+ }
+
+ return tempContext;
+ }
+ }
+ set
+ {
+ _context = value;
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ StringBuilder seq = new StringBuilder(10);
+ ArrayList objList = new ArrayList();
+
+ // first encode the before and the after count.
+ seq.Append("{ii");
+ objList.Add(BeforeCount);
+ objList.Add(AfterCount);
+
+ // encode Target if it is not null
+ if (Target.Length != 0)
+ {
+ seq.Append("t");
+ objList.Add(0x80 | 0x1);
+ seq.Append("o");
+ objList.Add(Target);
+ }
+ else
+ {
+ seq.Append("t{");
+ objList.Add(0xa0);
+ seq.Append("ii");
+ objList.Add(Offset);
+ objList.Add(EstimateCount);
+ seq.Append("}");
+ }
+
+ // encode the contextID if present
+ if (ContextId.Length != 0)
+ {
+ seq.Append("o");
+ objList.Add(ContextId);
+ }
+
+ seq.Append("}");
+ object[] values = new object[objList.Count];
+ for (int i = 0; i < objList.Count; i++)
+ {
+ values[i] = objList[i];
+ }
+
+ directoryControlValue = BerConverter.Encode(seq.ToString(), values);
+ return base.GetValue();
+ }
+ }
+
+ public class VlvResponseControl : DirectoryControl
+ {
+ private int _position = 0;
+ private int _count = 0;
+ private byte[] _context = null;
+ private ResultCode _result;
+
+ internal VlvResponseControl(int targetPosition, int count, byte[] context, ResultCode result, bool criticality, byte[] value) : base("2.16.840.1.113730.3.4.10", value, criticality, true)
+ {
+ _position = targetPosition;
+ _count = count;
+ _context = context;
+ _result = result;
+ }
+
+ public int TargetPosition
+ {
+ get
+ {
+ return _position;
+ }
+ }
+
+ public int ContentCount
+ {
+ get
+ {
+ return _count;
+ }
+ }
+
+ public byte[] ContextId
+ {
+ get
+ {
+ if (_context == null)
+ return new byte[0];
+ else
+ {
+ byte[] tempContext = new byte[_context.Length];
+ for (int i = 0; i < tempContext.Length; i++)
+ {
+ tempContext[i] = _context[i];
+ }
+
+ return tempContext;
+ }
+ }
+ }
+
+ public ResultCode Result
+ {
+ get
+ {
+ return _result;
+ }
+ }
+ }
+
+ public class QuotaControl : DirectoryControl
+ {
+ private byte[] _sid = null;
+
+ public QuotaControl() : base("1.2.840.113556.1.4.1852", null, true, true) { }
+
+ public QuotaControl(SecurityIdentifier querySid) : this()
+ {
+ QuerySid = querySid;
+ }
+
+ public SecurityIdentifier QuerySid
+ {
+ get
+ {
+ if (_sid == null)
+ return null;
+ else
+ {
+ return new SecurityIdentifier(_sid, 0);
+ }
+ }
+ set
+ {
+ if (value == null)
+ _sid = null;
+ else
+ {
+ _sid = new byte[value.BinaryLength];
+ value.GetBinaryForm(_sid, 0);
+ }
+ }
+ }
+
+ public override byte[] GetValue()
+ {
+ this.directoryControlValue = BerConverter.Encode("{o}", new object[] { _sid });
+ return base.GetValue();
+ }
+ }
+
+ public class DirectoryControlCollection : CollectionBase
+ {
+ public DirectoryControlCollection()
+ {
+ Utility.CheckOSVersion();
+ }
+
+ public DirectoryControl this[int index]
+ {
+ get
+ {
+ return (DirectoryControl)List[index];
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ List[index] = value;
+ }
+ }
+
+ public int Add(DirectoryControl control)
+ {
+ if (control == null)
+ throw new ArgumentNullException("control");
+
+ return List.Add(control);
+ }
+
+ public void AddRange(DirectoryControl[] controls)
+ {
+ if (controls == null)
+ throw new ArgumentNullException("controls");
+
+ foreach (DirectoryControl c in controls)
+ {
+ if (c == null)
+ {
+ throw new ArgumentException(Res.GetString(Res.ContainNullControl), "controls");
+ }
+ }
+
+ InnerList.AddRange(controls);
+ }
+
+ public void AddRange(DirectoryControlCollection controlCollection)
+ {
+ if (controlCollection == null)
+ {
+ throw new ArgumentNullException("controlCollection");
+ }
+ int currentCount = controlCollection.Count;
+ for (int i = 0; i < currentCount; i = ((i) + (1)))
+ {
+ this.Add(controlCollection[i]);
+ }
+ }
+
+ public bool Contains(DirectoryControl value)
+ {
+ return List.Contains(value);
+ }
+
+ public void CopyTo(DirectoryControl[] array, int index)
+ {
+ List.CopyTo(array, index);
+ }
+
+ public int IndexOf(DirectoryControl value)
+ {
+ return List.IndexOf(value);
+ }
+
+ public void Insert(int index, DirectoryControl value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ List.Insert(index, value);
+ }
+
+ public void Remove(DirectoryControl value)
+ {
+ List.Remove(value);
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ if (!(value is DirectoryControl))
+ throw new ArgumentException(Res.GetString(Res.InvalidValueType, "DirectoryControl"), "value");
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryException.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryException.cs
new file mode 100644
index 0000000000..6a79d3befb
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryException.cs
@@ -0,0 +1,96 @@
+// 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
+{
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+
+ [Serializable]
+ public class DirectoryException : Exception
+ {
+ protected DirectoryException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+
+ public DirectoryException(string message, Exception inner) : base(message, inner)
+ {
+ Utility.CheckOSVersion();
+ }
+
+ public DirectoryException(string message) : base(message)
+ {
+ Utility.CheckOSVersion();
+ }
+
+ public DirectoryException() : base()
+ {
+ Utility.CheckOSVersion();
+ }
+ }
+
+ [Serializable]
+ public class DirectoryOperationException : DirectoryException, ISerializable
+ {
+ internal DirectoryResponse response = null;
+ protected DirectoryOperationException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+
+ public DirectoryOperationException() : base() { }
+
+ public DirectoryOperationException(string message) : base(message) { }
+
+ public DirectoryOperationException(string message, Exception inner) : base(message, inner) { }
+
+ public DirectoryOperationException(DirectoryResponse response) : base(Res.GetString(Res.DefaultOperationsError))
+ {
+ this.response = response;
+ }
+
+ public DirectoryOperationException(DirectoryResponse response, string message) : base(message)
+ {
+ this.response = response;
+ }
+
+ public DirectoryOperationException(DirectoryResponse response, string message, Exception inner) : base(message, inner)
+ {
+ this.response = response;
+ }
+
+ public DirectoryResponse Response
+ {
+ get
+ {
+ return response;
+ }
+ }
+
+ [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ }
+ }
+
+ [Serializable]
+ public class BerConversionException : DirectoryException
+ {
+ protected BerConversionException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+
+ public BerConversionException() : base(Res.GetString(Res.BerConversionError))
+ {
+ }
+
+ public BerConversionException(string message) : base(message)
+ {
+ }
+
+ public BerConversionException(string message, Exception inner) : base(message, inner)
+ {
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryIdentifier.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryIdentifier.cs
new file mode 100644
index 0000000000..727ae4f4af
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryIdentifier.cs
@@ -0,0 +1,16 @@
+// 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
+{
+ using System;
+
+ public abstract class DirectoryIdentifier
+ {
+ protected DirectoryIdentifier()
+ {
+ Utility.CheckOSVersion();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryOperation.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryOperation.cs
new file mode 100644
index 0000000000..09e668ab19
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryOperation.cs
@@ -0,0 +1,16 @@
+// 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
+{
+ using System;
+ using System.Xml;
+
+ public abstract class DirectoryOperation
+ {
+ internal string directoryRequestID = null;
+
+ protected DirectoryOperation() { }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryRequest.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryRequest.cs
new file mode 100644
index 0000000000..e6c14d83ab
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryRequest.cs
@@ -0,0 +1,1038 @@
+// 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
+{
+ using System;
+ using System.Xml;
+ using System.Collections;
+ using System.IO;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.Collections.Specialized;
+ using System.Security.Permissions;
+
+ public abstract class DirectoryRequest : DirectoryOperation
+ {
+ internal DirectoryControlCollection directoryControlCollection = null;
+
+ internal DirectoryRequest()
+ {
+ Utility.CheckOSVersion();
+
+ directoryControlCollection = new DirectoryControlCollection();
+ }
+
+ public string RequestId
+ {
+ get
+ {
+ return directoryRequestID;
+ }
+ set
+ {
+ directoryRequestID = value;
+ }
+ }
+
+ public DirectoryControlCollection Controls
+ {
+ get
+ {
+ return directoryControlCollection;
+ }
+ }
+
+ //
+ // Internal
+ //
+
+ // Returns a XmlElement representing this object
+ // in DSML v2 format
+ internal XmlElement ToXmlNodeHelper(XmlDocument doc)
+ {
+ return ToXmlNode(doc);
+ }
+
+ // Overloaded to implement the operation-specific portion of transforming
+ // an object into its DSML v2 XML representation.
+ protected abstract XmlElement ToXmlNode(XmlDocument doc);
+
+ // Produces a XmlElement containing all the attributes/elements common
+ // to DSML v2 requests
+ internal XmlElement CreateRequestElement(XmlDocument doc,
+ string requestName,
+ bool includeDistinguishedName,
+ string distinguishedName)
+ {
+ // Create the element to represent the request
+ XmlElement elem = doc.CreateElement(requestName, DsmlConstants.DsmlUri);
+
+ if (includeDistinguishedName)
+ {
+ XmlAttribute attrDn = doc.CreateAttribute("dn", null);
+ attrDn.InnerText = distinguishedName;
+ elem.Attributes.Append(attrDn);
+ }
+
+ // Attach the requestID to the request
+ if (directoryRequestID != null)
+ {
+ XmlAttribute attrReqID = doc.CreateAttribute("requestID", null);
+ attrReqID.InnerText = directoryRequestID;
+ elem.Attributes.Append(attrReqID);
+ }
+
+ // Attach the controls to the request
+ // (controls are always the first child elements)
+ if (directoryControlCollection != null)
+ {
+ foreach (DirectoryControl control in directoryControlCollection)
+ {
+ XmlElement elControl = control.ToXmlNode(doc);
+ elem.AppendChild(elControl);
+ }
+ }
+
+ return elem;
+ }
+ }
+
+ public class DeleteRequest : DirectoryRequest
+ {
+ //
+ // Public
+ //
+
+ public DeleteRequest() { }
+
+ public DeleteRequest(string distinguishedName)
+ {
+ _dn = distinguishedName;
+ }
+
+ // Member properties
+ public string DistinguishedName
+ {
+ get
+ {
+ return _dn;
+ }
+
+ set
+ {
+ _dn = value;
+ }
+ }
+
+ //
+ // Private/protected
+ //
+
+ private string _dn;
+
+ protected override XmlElement ToXmlNode(XmlDocument doc)
+ {
+ XmlElement elem = CreateRequestElement(doc, "delRequest", true, _dn);
+
+ return elem;
+ }
+ }
+
+ public class AddRequest : DirectoryRequest
+ {
+ //
+ // Public
+ //
+
+ public AddRequest()
+ {
+ _attributeList = new DirectoryAttributeCollection();
+ }
+
+ public AddRequest(string distinguishedName, params DirectoryAttribute[] attributes) : this()
+ {
+ // Store off the distinguished name
+ _dn = distinguishedName;
+
+ if (attributes != null)
+ {
+ for (int i = 0; i < attributes.Length; i++)
+ {
+ _attributeList.Add(attributes[i]);
+ }
+ }
+ }
+
+ public AddRequest(string distinguishedName, string objectClass) : this()
+ {
+ // parameter validation
+ if (objectClass == null)
+ throw new ArgumentNullException("objectClass");
+
+ // Store off the distinguished name
+ _dn = distinguishedName;
+
+ // Store off the objectClass in an object class attribute
+ DirectoryAttribute objClassAttr = new DirectoryAttribute();
+
+ objClassAttr.Name = "objectClass";
+ objClassAttr.Add(objectClass);
+ _attributeList.Add(objClassAttr);
+ }
+
+ // Properties
+ public string DistinguishedName
+ {
+ get
+ {
+ return _dn;
+ }
+
+ set
+ {
+ _dn = value;
+ }
+ }
+
+ public DirectoryAttributeCollection Attributes
+ {
+ get
+ {
+ return _attributeList;
+ }
+ }
+
+ //
+ // Private/protected
+ //
+
+ private string _dn;
+ private DirectoryAttributeCollection _attributeList;
+
+ protected override XmlElement ToXmlNode(XmlDocument doc)
+ {
+ XmlElement elem = CreateRequestElement(doc, "addRequest", true, _dn);
+
+ // Add in the attributes
+ if (_attributeList != null)
+ {
+ foreach (DirectoryAttribute attr in _attributeList)
+ {
+ XmlElement elAttr = ((DirectoryAttribute)attr).ToXmlNode(doc, "attr");
+ elem.AppendChild(elAttr);
+ }
+ }
+
+ return elem;
+ }
+ }
+
+ public class ModifyRequest : DirectoryRequest
+ {
+ //
+ // Public
+ //
+ public ModifyRequest()
+ {
+ _attributeModificationList = new DirectoryAttributeModificationCollection();
+ }
+
+ public ModifyRequest(string distinguishedName, params DirectoryAttributeModification[] modifications) : this()
+ {
+ // Store off the distinguished name
+ _dn = distinguishedName;
+
+ // Store off the initial list of modifications
+ _attributeModificationList.AddRange(modifications);
+ }
+
+ public ModifyRequest(string distinguishedName, DirectoryAttributeOperation operation, string attributeName, params object[] values) : this()
+ {
+ // Store off the distinguished name
+ _dn = distinguishedName;
+
+ // validate the attributeName
+ if (attributeName == null)
+ throw new ArgumentNullException("attributeName");
+
+ DirectoryAttributeModification mod = new DirectoryAttributeModification();
+ mod.Operation = operation;
+ mod.Name = attributeName;
+ if (values != null)
+ {
+ for (int i = 0; i < values.Length; i++)
+ mod.Add(values[i]);
+ }
+
+ _attributeModificationList.Add(mod);
+ }
+
+ // Properties
+ public string DistinguishedName
+ {
+ get
+ {
+ return _dn;
+ }
+
+ set
+ {
+ _dn = value;
+ }
+ }
+
+ public DirectoryAttributeModificationCollection Modifications
+ {
+ get
+ {
+ return _attributeModificationList;
+ }
+ }
+
+ //
+ // Private/protected
+ //
+
+ private string _dn;
+ private DirectoryAttributeModificationCollection _attributeModificationList;
+
+ protected override XmlElement ToXmlNode(XmlDocument doc)
+ {
+ XmlElement elem = CreateRequestElement(doc, "modifyRequest", true, _dn);
+
+ // Add in the attributes
+
+ if (_attributeModificationList != null)
+ {
+ foreach (DirectoryAttributeModification attr in _attributeModificationList)
+ {
+ XmlElement elAttr = attr.ToXmlNode(doc);
+ elem.AppendChild(elAttr);
+ }
+ }
+
+ return elem;
+ }
+ }
+
+ public class CompareRequest : DirectoryRequest
+ {
+ //
+ // Public
+ //
+ public CompareRequest() { }
+
+ public CompareRequest(string distinguishedName, string attributeName, string value)
+ {
+ CompareRequestHelper(distinguishedName, attributeName, value);
+ }
+
+ public CompareRequest(string distinguishedName, string attributeName, byte[] value)
+ {
+ CompareRequestHelper(distinguishedName, attributeName, value);
+ }
+
+ public CompareRequest(string distinguishedName, string attributeName, Uri value)
+ {
+ CompareRequestHelper(distinguishedName, attributeName, value);
+ }
+
+ public CompareRequest(string distinguishedName, DirectoryAttribute assertion)
+ {
+ if (assertion == null)
+ throw new ArgumentNullException("assertion");
+
+ if (assertion.Count != 1)
+ throw new ArgumentException(Res.GetString(Res.WrongNumValuesCompare));
+
+ CompareRequestHelper(distinguishedName, assertion.Name, assertion[0]);
+ }
+
+ private void CompareRequestHelper(string distinguishedName, string attributeName, object value)
+ {
+ // parameter validation
+ if (attributeName == null)
+ throw new ArgumentNullException("attributeName");
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ // store off the DN
+ _dn = distinguishedName;
+
+ // store off the attribute name and value
+ _attribute.Name = attributeName;
+ _attribute.Add(value);
+ }
+
+ // Properties
+ public string DistinguishedName
+ {
+ get
+ {
+ return _dn;
+ }
+
+ set
+ {
+ _dn = value;
+ }
+ }
+
+ public DirectoryAttribute Assertion
+ {
+ get
+ {
+ return _attribute;
+ }
+ }
+
+ //
+ // Private/protected
+ //
+
+ private string _dn;
+ private DirectoryAttribute _attribute = new DirectoryAttribute();
+
+ protected override XmlElement ToXmlNode(XmlDocument doc)
+ {
+ XmlElement elem = CreateRequestElement(doc, "compareRequest", true, _dn);
+
+ // add in the attribute
+ if (_attribute.Count != 1)
+ throw new ArgumentException(Res.GetString(Res.WrongNumValuesCompare));
+
+ XmlElement elAttr = _attribute.ToXmlNode(doc, "assertion");
+ elem.AppendChild(elAttr);
+
+ return elem;
+ }
+ }
+
+ public class ModifyDNRequest : DirectoryRequest
+ {
+ //
+ // Public
+ //
+ public ModifyDNRequest() { }
+
+ public ModifyDNRequest(string distinguishedName,
+ string newParentDistinguishedName,
+ string newName)
+ {
+ // store off the DN
+ _dn = distinguishedName;
+
+ _newSuperior = newParentDistinguishedName;
+ _newRDN = newName;
+ }
+
+ // Properties
+ public string DistinguishedName
+ {
+ get
+ {
+ return _dn;
+ }
+
+ set
+ {
+ _dn = value;
+ }
+ }
+
+ public string NewParentDistinguishedName
+ {
+ get
+ {
+ return _newSuperior;
+ }
+
+ set
+ {
+ _newSuperior = value;
+ }
+ }
+
+ public string NewName
+ {
+ get
+ {
+ return _newRDN;
+ }
+
+ set
+ {
+ _newRDN = value;
+ }
+ }
+
+ public bool DeleteOldRdn
+ {
+ get
+ {
+ return _deleteOldRDN;
+ }
+
+ set
+ {
+ _deleteOldRDN = value;
+ }
+ }
+
+ //
+ // Private/protected
+ //
+
+ private string _dn;
+ private string _newSuperior;
+ private string _newRDN;
+ private bool _deleteOldRDN = true;
+
+ protected override XmlElement ToXmlNode(XmlDocument doc)
+ {
+ XmlElement elem = CreateRequestElement(doc, "modDNRequest", true, _dn);
+
+ // "newrdn" attribute (required)
+ XmlAttribute attrNewRDN = doc.CreateAttribute("newrdn", null);
+ attrNewRDN.InnerText = _newRDN;
+ elem.Attributes.Append(attrNewRDN);
+
+ // "deleteoldrdn" attribute (optional, but we'll always include it)
+ XmlAttribute attrDeleteOldRDN = doc.CreateAttribute("deleteoldrdn", null);
+ attrDeleteOldRDN.InnerText = _deleteOldRDN ? "true" : "false";
+ elem.Attributes.Append(attrDeleteOldRDN);
+
+ // "newSuperior" attribute (optional)
+ if (_newSuperior != null)
+ {
+ XmlAttribute attrNewSuperior = doc.CreateAttribute("newSuperior", null);
+ attrNewSuperior.InnerText = _newSuperior;
+ elem.Attributes.Append(attrNewSuperior);
+ }
+
+ return elem;
+ }
+ }
+
+ /// <summary>
+ /// The representation of a <extendedRequest>
+ /// </summary>
+ public class ExtendedRequest : DirectoryRequest
+ {
+ //
+ // Public
+ //
+ public ExtendedRequest() { }
+
+ public ExtendedRequest(string requestName)
+ {
+ _requestName = requestName;
+ }
+
+ public ExtendedRequest(string requestName, byte[] requestValue) : this(requestName)
+ {
+ _requestValue = requestValue;
+ }
+
+ // Properties
+ public string RequestName
+ {
+ get
+ {
+ return _requestName;
+ }
+
+ set
+ {
+ _requestName = value;
+ }
+ }
+
+ public byte[] RequestValue
+ {
+ get
+ {
+ if (_requestValue == null)
+ return new byte[0];
+ else
+ {
+ byte[] tempValue = new byte[_requestValue.Length];
+ for (int i = 0; i < _requestValue.Length; i++)
+ tempValue[i] = _requestValue[i];
+
+ return tempValue;
+ }
+ }
+
+ set
+ {
+ _requestValue = value;
+ }
+ }
+
+ //
+ // Private/protected
+ //
+
+ private string _requestName;
+ private byte[] _requestValue = null;
+
+ protected override XmlElement ToXmlNode(XmlDocument doc)
+ {
+ XmlElement elem = CreateRequestElement(doc, "extendedRequest", false, null);
+
+ // <requestName>
+ XmlElement elemName = doc.CreateElement("requestName", DsmlConstants.DsmlUri);
+ elemName.InnerText = _requestName;
+ elem.AppendChild(elemName);
+
+ // <requestValue> (optional)
+ if (_requestValue != null)
+ {
+ XmlElement elemValue = doc.CreateElement("requestValue", DsmlConstants.DsmlUri);
+ elemValue.InnerText = System.Convert.ToBase64String(_requestValue);
+
+ // attach the "xsi:type = xsd:base64Binary" attribute
+ XmlAttribute attrXsiType = doc.CreateAttribute("xsi:type", DsmlConstants.XsiUri);
+ attrXsiType.InnerText = "xsd:base64Binary";
+ elemValue.Attributes.Append(attrXsiType);
+
+ elem.AppendChild(elemValue);
+ }
+
+ return elem;
+ }
+ }
+
+ public class SearchRequest : DirectoryRequest
+ {
+ //
+ // Public
+ //
+ public SearchRequest()
+ {
+ _directoryAttributes = new StringCollection();
+ }
+
+ public SearchRequest(string distinguishedName,
+ XmlDocument filter,
+ SearchScope searchScope,
+ params string[] attributeList) : this()
+ {
+ _dn = distinguishedName;
+
+ if (attributeList != null)
+ {
+ for (int i = 0; i < attributeList.Length; i++)
+ _directoryAttributes.Add(attributeList[i]);
+ }
+
+ // validate the scope parameter
+ Scope = searchScope;
+
+ Filter = filter;
+ }
+
+ public SearchRequest(string distinguishedName,
+ string ldapFilter,
+ SearchScope searchScope,
+ params string[] attributeList) : this()
+ {
+ _dn = distinguishedName;
+
+ if (attributeList != null)
+ {
+ for (int i = 0; i < attributeList.Length; i++)
+ _directoryAttributes.Add(attributeList[i]);
+ }
+
+ Scope = searchScope;
+
+ Filter = ldapFilter;
+ }
+
+ // Properties
+ public string DistinguishedName
+ {
+ get
+ {
+ return _dn;
+ }
+
+ set
+ {
+ _dn = value;
+ }
+ }
+
+ public StringCollection Attributes
+ {
+ get
+ {
+ return _directoryAttributes;
+ }
+ }
+
+ public object Filter
+ {
+ get
+ {
+ return _directoryFilter;
+ }
+
+ set
+ {
+ // do we need to validate the filter here?
+ if ((value is string) || (value is XmlDocument) || (value == null))
+ _directoryFilter = value;
+ else
+ throw new ArgumentException(Res.GetString(Res.ValidFilterType), "value");
+ }
+ }
+
+ public SearchScope Scope
+ {
+ get
+ {
+ return _directoryScope;
+ }
+
+ set
+ {
+ if (value < SearchScope.Base || value > SearchScope.Subtree)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(SearchScope));
+
+ _directoryScope = value;
+ }
+ }
+
+ public DereferenceAlias Aliases
+ {
+ get
+ {
+ return _directoryRefAlias;
+ }
+
+ set
+ {
+ if (value < DereferenceAlias.Never || value > DereferenceAlias.Always)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(DereferenceAlias));
+
+ _directoryRefAlias = value;
+ }
+ }
+
+ public int SizeLimit
+ {
+ get
+ {
+ return _directorySizeLimit;
+ }
+
+ set
+ {
+ if (value < 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.NoNegativeSizeLimit), "value");
+ }
+
+ _directorySizeLimit = value;
+ }
+ }
+
+ public TimeSpan TimeLimit
+ {
+ get
+ {
+ return _directoryTimeLimit;
+ }
+
+ set
+ {
+ if (value < TimeSpan.Zero)
+ {
+ throw new ArgumentException(Res.GetString(Res.NoNegativeTime), "value");
+ }
+
+ // prevent integer overflow
+ if (value.TotalSeconds > Int32.MaxValue)
+ throw new ArgumentException(Res.GetString(Res.TimespanExceedMax), "value");
+
+ _directoryTimeLimit = value;
+ }
+ }
+
+ public bool TypesOnly
+ {
+ get
+ {
+ return _directoryTypesOnly;
+ }
+
+ set
+ {
+ _directoryTypesOnly = value;
+ }
+ }
+
+ //
+ // Private/protected
+ //
+
+ private string _dn = null;
+ private StringCollection _directoryAttributes = new StringCollection();
+ private object _directoryFilter = null;
+ private SearchScope _directoryScope = SearchScope.Subtree;
+ private DereferenceAlias _directoryRefAlias = DereferenceAlias.Never;
+ private int _directorySizeLimit = 0;
+ private TimeSpan _directoryTimeLimit = new TimeSpan(0);
+ private bool _directoryTypesOnly = false;
+
+ protected override XmlElement ToXmlNode(XmlDocument doc)
+ {
+ XmlElement elem = CreateRequestElement(doc, "searchRequest", true, _dn);
+
+ // attach the "scope" attribute (required)
+ XmlAttribute attrScope = doc.CreateAttribute("scope", null);
+
+ switch (_directoryScope)
+ {
+ case SearchScope.Subtree:
+ attrScope.InnerText = "wholeSubtree";
+ break;
+
+ case SearchScope.OneLevel:
+ attrScope.InnerText = "singleLevel";
+ break;
+
+ case SearchScope.Base:
+ attrScope.InnerText = "baseObject";
+ break;
+
+ default:
+ Debug.Assert(false, "Unknown DsmlSearchScope type");
+ break;
+ }
+
+ elem.Attributes.Append(attrScope);
+
+ // attach the "derefAliases" attribute (required)
+ XmlAttribute attrDerefAliases = doc.CreateAttribute("derefAliases", null);
+
+ switch (_directoryRefAlias)
+ {
+ case DereferenceAlias.Never:
+ attrDerefAliases.InnerText = "neverDerefAliases";
+ break;
+
+ case DereferenceAlias.InSearching:
+ attrDerefAliases.InnerText = "derefInSearching";
+ break;
+
+ case DereferenceAlias.FindingBaseObject:
+ attrDerefAliases.InnerText = "derefFindingBaseObj";
+ break;
+
+ case DereferenceAlias.Always:
+ attrDerefAliases.InnerText = "derefAlways";
+ break;
+
+ default:
+ Debug.Assert(false, "Unknown DsmlDereferenceAlias type");
+ break;
+ }
+
+ elem.Attributes.Append(attrDerefAliases);
+
+ // attach the "sizeLimit" attribute (optional)
+ XmlAttribute attrSizeLimit = doc.CreateAttribute("sizeLimit", null);
+ attrSizeLimit.InnerText = _directorySizeLimit.ToString(CultureInfo.InvariantCulture);
+ elem.Attributes.Append(attrSizeLimit);
+
+ // attach the "timeLimit" attribute (optional)
+ XmlAttribute attrTimeLimit = doc.CreateAttribute("timeLimit", null);
+ attrTimeLimit.InnerText = (_directoryTimeLimit.Ticks / TimeSpan.TicksPerSecond).ToString(CultureInfo.InvariantCulture);
+ elem.Attributes.Append(attrTimeLimit);
+
+ // attach the "typesOnly" attribute (optional, defaults to false)
+ XmlAttribute attrTypesOnly = doc.CreateAttribute("typesOnly", null);
+ attrTypesOnly.InnerText = _directoryTypesOnly ? "true" : "false";
+ elem.Attributes.Append(attrTypesOnly);
+
+ // add in the <filter> element (required)
+ XmlElement elemFilter = doc.CreateElement("filter", DsmlConstants.DsmlUri);
+
+ if (Filter != null)
+ {
+ StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
+ XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
+
+ try
+ {
+ if (Filter is XmlDocument)
+ {
+ if (((XmlDocument)Filter).NamespaceURI.Length == 0)
+ {
+ // namespaceURI is not explicitly specified
+ CopyFilter((XmlDocument)Filter, xmlWriter);
+ elemFilter.InnerXml = stringWriter.ToString();
+ }
+ else
+ {
+ elemFilter.InnerXml = ((XmlDocument)Filter).OuterXml;
+ }
+ }
+ else if (Filter is string)
+ {
+ //
+ // Search Filter
+ // We make use of the code from DSDE, which requires an intermediary
+ // trip through the ADFilter representation. Although ADFilter is unnecessary
+ // for our purposes, this enables us to use the same exact code as
+ // DSDE, without having to maintain a second copy of it.
+ //
+
+ // AD filter currently does not support filter without paranthesis, so adding it explicitly
+ string tempFilter = (string)Filter;
+ if (!tempFilter.StartsWith("(", StringComparison.Ordinal) && !tempFilter.EndsWith(")", StringComparison.Ordinal))
+ {
+ tempFilter = tempFilter.Insert(0, "(");
+ tempFilter = String.Concat(tempFilter, ")");
+ }
+
+ // Convert LDAP filter string to ADFilter representation
+ ADFilter adfilter = FilterParser.ParseFilterString(tempFilter);
+
+ if (adfilter == null)
+ {
+ // The LDAP filter string didn't parse correctly
+ throw new ArgumentException(Res.GetString(Res.BadSearchLDAPFilter));
+ }
+
+ // Convert ADFilter representation to a DSML filter string
+ // Ideally, we'd skip the intemediary string, but the DSDE conversion
+ // routines expect a XmlWriter, and the only XmlWriter available
+ // is the XmlTextWriter, which produces text.
+ DSMLFilterWriter filterwriter = new DSMLFilterWriter();
+
+ filterwriter.WriteFilter(adfilter, false, xmlWriter, DsmlConstants.DsmlUri);
+
+ elemFilter.InnerXml = stringWriter.ToString();
+ }
+ else
+ Debug.Assert(false, "Unknown filter type");
+ }
+ finally
+ {
+ // close this stream and the underlying stream.
+ xmlWriter.Close();
+ }
+ }
+ else
+ {
+ // default filter: (objectclass=*)
+ elemFilter.InnerXml = DsmlConstants.DefaultSearchFilter;
+ }
+
+ elem.AppendChild(elemFilter);
+
+ // add in the <attributes> element (optional)
+ if (_directoryAttributes != null && _directoryAttributes.Count != 0)
+ {
+ // create and attach the <attributes> element
+ XmlElement elemAttributes = doc.CreateElement("attributes", DsmlConstants.DsmlUri);
+ elem.AppendChild(elemAttributes);
+
+ // create and attach the <attribute> elements under the <attributes> element
+ foreach (string attrName in _directoryAttributes)
+ {
+ // DsmlAttribute objects know how to persist themself in the right
+ // XML format, so we'll make use of that here rather than
+ // duplicating the code
+ DirectoryAttribute attr = new DirectoryAttribute();
+ attr.Name = attrName;
+ XmlElement elemAttr = attr.ToXmlNode(doc, "attribute");
+ elemAttributes.AppendChild(elemAttr);
+ }
+ }
+
+ return elem;
+ }
+
+ private void CopyFilter(XmlNode node, XmlTextWriter writer)
+ {
+ for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling)
+ if (n != null)
+ CopyXmlTree(n, writer);
+ }
+
+ private void CopyXmlTree(XmlNode node, XmlTextWriter writer)
+ {
+ switch (node.NodeType)
+ {
+ case XmlNodeType.Element:
+ writer.WriteStartElement(node.LocalName, DsmlConstants.DsmlUri);
+ foreach (XmlAttribute att in node.Attributes)
+ {
+ writer.WriteAttributeString(att.LocalName, att.Value);
+ }
+
+ for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling)
+ {
+ CopyXmlTree(n, writer);
+ }
+ writer.WriteEndElement();
+
+ break;
+ default:
+ writer.WriteRaw(node.OuterXml);
+ break;
+ }
+ }
+ }
+}
+
+namespace System.DirectoryServices.Protocols
+{
+ using System;
+ using System.Xml;
+
+ public class DsmlAuthRequest : DirectoryRequest
+ {
+ private string _directoryPrincipal = "";
+
+ public DsmlAuthRequest() { }
+
+ public DsmlAuthRequest(string principal)
+ {
+ _directoryPrincipal = principal;
+ }
+
+ public string Principal
+ {
+ get
+ {
+ return _directoryPrincipal;
+ }
+ set
+ {
+ _directoryPrincipal = value;
+ }
+ }
+
+ protected override XmlElement ToXmlNode(XmlDocument doc)
+ {
+ XmlElement elem = CreateRequestElement(doc, "authRequest", false, null);
+
+ XmlAttribute attrPrincipal = doc.CreateAttribute("principal", null);
+ attrPrincipal.InnerText = Principal;
+ elem.Attributes.Append(attrPrincipal);
+
+ return elem;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryResponse.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryResponse.cs
new file mode 100644
index 0000000000..98ce611316
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryResponse.cs
@@ -0,0 +1,767 @@
+// 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
+{
+ using System;
+ using System.Net;
+ using System.Xml;
+ using System.IO;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Globalization;
+
+ public abstract class DirectoryResponse : DirectoryOperation
+ {
+ internal XmlNode dsmlNode = null;
+ internal XmlNamespaceManager dsmlNS = null;
+ internal bool dsmlRequest = false;
+
+ internal string dn = null;
+ internal DirectoryControl[] directoryControls = null;
+ internal ResultCode result = (ResultCode)(-1);
+ internal string directoryMessage = null;
+ internal Uri[] directoryReferral = null;
+
+ private string _requestID = null;
+
+ internal DirectoryResponse(XmlNode node)
+ {
+ Debug.Assert(node != null);
+
+ dsmlNode = node;
+
+ dsmlNS = NamespaceUtils.GetDsmlNamespaceManager();
+
+ dsmlRequest = true;
+ }
+
+ internal DirectoryResponse(string dn, DirectoryControl[] controls, ResultCode result, string message, Uri[] referral)
+ {
+ this.dn = dn;
+ this.directoryControls = controls;
+ this.result = result;
+ this.directoryMessage = message;
+ this.directoryReferral = referral;
+ }
+
+ public string RequestId
+ {
+ get
+ {
+ // this is a dsml request
+ if (dsmlRequest && (_requestID == null))
+ {
+ // Locate the requestID attribute
+ XmlAttribute attrReqID = (XmlAttribute)dsmlNode.SelectSingleNode("@dsml:requestID", dsmlNS);
+
+ if (attrReqID == null)
+ {
+ // try it without the namespace qualifier, in case the sender omitted it
+ attrReqID = (XmlAttribute)dsmlNode.SelectSingleNode("@requestID", dsmlNS);
+ }
+
+ if (attrReqID != null)
+ {
+ _requestID = attrReqID.Value;
+ }
+ }
+
+ return _requestID;
+ }
+ }
+
+ public virtual string MatchedDN
+ {
+ get
+ {
+ if (dsmlRequest && (dn == null))
+ {
+ dn = MatchedDNHelper("@dsml:matchedDN", "@matchedDN");
+ }
+
+ return dn;
+ }
+ }
+
+ public virtual DirectoryControl[] Controls
+ {
+ get
+ {
+ if (dsmlRequest && (directoryControls == null))
+ {
+ directoryControls = ControlsHelper("dsml:control");
+ }
+
+ if (directoryControls == null)
+ return new DirectoryControl[0];
+ else
+ {
+ DirectoryControl[] tempControls = new DirectoryControl[directoryControls.Length];
+ for (int i = 0; i < directoryControls.Length; i++)
+ tempControls[i] = new DirectoryControl(directoryControls[i].Type, directoryControls[i].GetValue(), directoryControls[i].IsCritical, directoryControls[i].ServerSide);
+
+ DirectoryControl.TransformControls(tempControls);
+
+ return tempControls;
+ }
+ }
+ }
+
+ public virtual ResultCode ResultCode
+ {
+ get
+ {
+ if (dsmlRequest && ((int)result == -1))
+ {
+ result = ResultCodeHelper("dsml:resultCode/@dsml:code", "dsml:resultCode/@code");
+ }
+
+ return result;
+ }
+ }
+
+ public virtual string ErrorMessage
+ {
+ get
+ {
+ if (dsmlRequest && (directoryMessage == null))
+ {
+ directoryMessage = ErrorMessageHelper("dsml:errorMessage");
+ }
+
+ return directoryMessage;
+ }
+ }
+
+ public virtual Uri[] Referral
+ {
+ get
+ {
+ if (dsmlRequest && (directoryReferral == null))
+ {
+ directoryReferral = ReferralHelper("dsml:referral");
+ }
+
+ if (directoryReferral == null)
+ return new Uri[0];
+ else
+ {
+ Uri[] tempReferral = new Uri[directoryReferral.Length];
+ for (int i = 0; i < directoryReferral.Length; i++)
+ {
+ tempReferral[i] = new Uri(directoryReferral[i].AbsoluteUri);
+ }
+ return tempReferral;
+ }
+ }
+ }
+
+ //
+ // Private/protected
+ //
+
+ // Methods used to implement the above properties
+ internal string MatchedDNHelper(string primaryXPath, string secondaryXPath)
+ {
+ // Locate the matchedDN attribute
+ XmlAttribute attrMatchedDN = (XmlAttribute)dsmlNode.SelectSingleNode(primaryXPath, dsmlNS);
+
+ if (attrMatchedDN == null)
+ {
+ // try it without the namespace qualifier, in case the sender omitted it
+ attrMatchedDN = (XmlAttribute)dsmlNode.SelectSingleNode(secondaryXPath, dsmlNS);
+
+ if (attrMatchedDN == null)
+ {
+ // the element doesn't have a associated dn
+ return null;
+ }
+
+ return attrMatchedDN.Value;
+ }
+ else
+ {
+ return attrMatchedDN.Value;
+ }
+ }
+
+ internal DirectoryControl[] ControlsHelper(string primaryXPath)
+ {
+ // Get the set of control nodes
+ XmlNodeList nodeList = dsmlNode.SelectNodes(primaryXPath, dsmlNS);
+
+ if (nodeList.Count == 0)
+ {
+ // the server returned no controls
+ return new DirectoryControl[0];
+ }
+
+ // Build the DirectoryControl array
+ DirectoryControl[] controls = new DirectoryControl[nodeList.Count];
+ int index = 0;
+
+ foreach (XmlNode node in nodeList)
+ {
+ Debug.Assert(node is XmlElement);
+
+ controls[index] = new DirectoryControl((XmlElement)node);
+ index++;
+ }
+
+ return controls;
+ }
+
+ internal ResultCode ResultCodeHelper(string primaryXPath, string secondaryXPath)
+ {
+ // Retrieve the result code attribute
+ XmlAttribute attrResultCode = (XmlAttribute)dsmlNode.SelectSingleNode(primaryXPath, dsmlNS);
+
+ if (attrResultCode == null)
+ {
+ // try it without the namespace qualifier, in case the sender omitted it
+ attrResultCode = (XmlAttribute)dsmlNode.SelectSingleNode(secondaryXPath, dsmlNS);
+
+ if (attrResultCode == null)
+ {
+ // the resultCode is not optional
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.MissingOperationResponseResultCode));
+ }
+ }
+
+ // Validate the result code
+ string resCodeString = attrResultCode.Value;
+ int resCodeInt;
+
+ try
+ {
+ resCodeInt = int.Parse(resCodeString, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ }
+ catch (FormatException)
+ {
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.BadOperationResponseResultCode, resCodeString));
+ }
+ catch (OverflowException)
+ {
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.BadOperationResponseResultCode, resCodeString));
+ }
+
+ if (!Utility.IsResultCode((ResultCode)resCodeInt))
+ {
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.BadOperationResponseResultCode, resCodeString));
+ }
+
+ // Transform the result code into an LDAPResultCode
+ ResultCode resCode = (ResultCode)resCodeInt;
+
+ return resCode;
+ }
+
+ internal string ErrorMessageHelper(string primaryXPath)
+ {
+ XmlElement elMessage = (XmlElement)dsmlNode.SelectSingleNode(primaryXPath, dsmlNS);
+
+ if (elMessage != null)
+ {
+ return elMessage.InnerText;
+ }
+ else
+ {
+ // server didn't return a errorMessage
+ return null;
+ }
+ }
+
+ internal Uri[] ReferralHelper(string primaryXPath)
+ {
+ // Get the set of referral nodes
+ XmlNodeList nodeList = dsmlNode.SelectNodes(primaryXPath, dsmlNS);
+
+ if (nodeList.Count == 0)
+ {
+ // the server returned no referrals
+ return new Uri[0];
+ }
+
+ // Build the Uri array
+ Uri[] uris = new Uri[nodeList.Count];
+ int index = 0;
+
+ foreach (XmlNode node in nodeList)
+ {
+ uris[index] = new Uri(node.InnerText);
+ index++;
+ }
+
+ return uris;
+ }
+ }
+
+ public class DeleteResponse : DirectoryResponse
+ {
+ internal DeleteResponse(XmlNode node) : base(node) { }
+ internal DeleteResponse(string dn, DirectoryControl[] controls, ResultCode result, string message, Uri[] referral) : base(dn, controls, result, message, referral) { }
+ }
+
+ /// <summary>
+ /// The AddResponse class for representing <addResponse>
+ /// </summary>
+ public class AddResponse : DirectoryResponse
+ {
+ internal AddResponse(XmlNode node) : base(node) { }
+ internal AddResponse(string dn, DirectoryControl[] controls, ResultCode result, string message, Uri[] referral) : base(dn, controls, result, message, referral) { }
+ }
+
+ /// <summary>
+ /// The ModifyResponse class for representing <modifyResponse>
+ /// </summary>
+ public class ModifyResponse : DirectoryResponse
+ {
+ internal ModifyResponse(XmlNode node) : base(node) { }
+ internal ModifyResponse(string dn, DirectoryControl[] controls, ResultCode result, string message, Uri[] referral) : base(dn, controls, result, message, referral) { }
+ }
+
+ /// <summary>
+ /// The ModifyDnResponse class for representing <modDNResponse>
+ /// </summary>
+ public class ModifyDNResponse : DirectoryResponse
+ {
+ internal ModifyDNResponse(XmlNode node) : base(node) { }
+ internal ModifyDNResponse(string dn, DirectoryControl[] controls, ResultCode result, string message, Uri[] referral) : base(dn, controls, result, message, referral) { }
+ }
+
+ /// <summary>
+ /// The CompareResponse class for representing <compareResponse>
+ /// </summary>
+ public class CompareResponse : DirectoryResponse
+ {
+ internal CompareResponse(XmlNode node) : base(node) { }
+ internal CompareResponse(string dn, DirectoryControl[] controls, ResultCode result, string message, Uri[] referral) : base(dn, controls, result, message, referral) { }
+ }
+
+ /// <summary>
+ /// The ExtendedResponse class for representing <extendedResponse>
+ /// </summary>
+ public class ExtendedResponse : DirectoryResponse
+ {
+ internal string name = null;
+ internal byte[] value = null;
+
+ internal ExtendedResponse(XmlNode node) : base(node) { }
+ internal ExtendedResponse(string dn, DirectoryControl[] controls, ResultCode result, string message, Uri[] referral) : base(dn, controls, result, message, referral) { }
+
+ //
+ // Public
+ //
+
+ // Properties
+ public string ResponseName
+ {
+ get
+ {
+ if (dsmlRequest && (name == null))
+ {
+ XmlElement elRespName = (XmlElement)dsmlNode.SelectSingleNode("dsml:responseName", dsmlNS);
+
+ if (elRespName != null)
+ {
+ name = elRespName.InnerText;
+ }
+ }
+
+ return name;
+ }
+ }
+
+ public byte[] ResponseValue
+ {
+ get
+ {
+ if (dsmlRequest && (value == null))
+ {
+ XmlElement elRespValue = (XmlElement)dsmlNode.SelectSingleNode("dsml:response", dsmlNS);
+
+ if (elRespValue != null)
+ {
+ // server returns a response value
+ string base64EncodedValue = elRespValue.InnerText;
+
+ try
+ {
+ value = System.Convert.FromBase64String(base64EncodedValue);
+ }
+ catch (FormatException)
+ {
+ // server returned invalid base64
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.BadBase64Value));
+ }
+ }
+ }
+
+ if (value == null)
+ return new byte[0];
+ else
+ {
+ byte[] tmpValue = new byte[value.Length];
+ for (int i = 0; i < value.Length; i++)
+ {
+ tmpValue[i] = value[i];
+ }
+ return tmpValue;
+ }
+ }
+ }
+ }
+
+ public class SearchResponse : DirectoryResponse
+ {
+ private SearchResultReferenceCollection _referenceCollection = new SearchResultReferenceCollection();
+ private SearchResultEntryCollection _entryCollection = new SearchResultEntryCollection();
+ internal bool searchDone = false;
+
+ internal SearchResponse(XmlNode node) : base(node) { }
+ internal SearchResponse(string dn, DirectoryControl[] controls, ResultCode result, string message, Uri[] referral) : base(dn, controls, result, message, referral) { }
+
+ public override string MatchedDN
+ {
+ get
+ {
+ if (dsmlRequest && (dn == null))
+ {
+ dn = MatchedDNHelper("dsml:searchResultDone/@dsml:matchedDN",
+ "dsml:searchResultDone/@matchedDN");
+ }
+
+ return dn;
+ }
+ }
+
+ public override DirectoryControl[] Controls
+ {
+ get
+ {
+ DirectoryControl[] controls = null;
+ if (dsmlRequest && (directoryControls == null))
+ {
+ directoryControls = ControlsHelper("dsml:searchResultDone/dsml:control");
+ }
+
+ if (directoryControls == null)
+ return new DirectoryControl[0];
+ else
+ {
+ controls = new DirectoryControl[directoryControls.Length];
+ for (int i = 0; i < directoryControls.Length; i++)
+ {
+ controls[i] = new DirectoryControl(directoryControls[i].Type, directoryControls[i].GetValue(), directoryControls[i].IsCritical, directoryControls[i].ServerSide);
+ }
+ }
+
+ DirectoryControl.TransformControls(controls);
+
+ return controls;
+ }
+ }
+
+ public override ResultCode ResultCode
+ {
+ get
+ {
+ if (dsmlRequest && ((int)result == -1))
+ {
+ result = ResultCodeHelper("dsml:searchResultDone/dsml:resultCode/@dsml:code",
+ "dsml:searchResultDone/dsml:resultCode/@code");
+ }
+
+ return result;
+ }
+ }
+
+ public override string ErrorMessage
+ {
+ get
+ {
+ if (dsmlRequest && (directoryMessage == null))
+ {
+ directoryMessage = ErrorMessageHelper("dsml:searchResultDone/dsml:errorMessage");
+ }
+
+ return directoryMessage;
+ }
+ }
+
+ public override Uri[] Referral
+ {
+ get
+ {
+ if (dsmlRequest && (directoryReferral == null))
+ {
+ directoryReferral = ReferralHelper("dsml:searchResultDone/dsml:referral");
+ }
+
+ if (directoryReferral == null)
+ return new Uri[0];
+ else
+ {
+ Uri[] tempReferral = new Uri[directoryReferral.Length];
+ for (int i = 0; i < directoryReferral.Length; i++)
+ {
+ tempReferral[i] = new Uri(directoryReferral[i].AbsoluteUri);
+ }
+ return tempReferral;
+ }
+ }
+ }
+
+ public SearchResultReferenceCollection References
+ {
+ get
+ {
+ if (dsmlRequest && (_referenceCollection.Count == 0))
+ {
+ _referenceCollection = ReferenceHelper();
+ }
+
+ return _referenceCollection;
+ }
+ }
+
+ public SearchResultEntryCollection Entries
+ {
+ get
+ {
+ if (dsmlRequest && (_entryCollection.Count == 0))
+ {
+ _entryCollection = EntryHelper();
+ }
+
+ return _entryCollection;
+ }
+ }
+
+ internal void SetReferences(SearchResultReferenceCollection col)
+ {
+ _referenceCollection = col;
+ }
+
+ internal void SetEntries(SearchResultEntryCollection col)
+ {
+ _entryCollection = col;
+ }
+
+ private SearchResultReferenceCollection ReferenceHelper()
+ {
+ SearchResultReferenceCollection refCollection = new SearchResultReferenceCollection();
+
+ // Get the set of control nodes
+ XmlNodeList nodeList = dsmlNode.SelectNodes("dsml:searchResultReference", dsmlNS);
+
+ if (nodeList.Count != 0)
+ {
+ foreach (XmlNode node in nodeList)
+ {
+ Debug.Assert(node is XmlElement);
+
+ SearchResultReference attribute = new SearchResultReference((XmlElement)node);
+ refCollection.Add(attribute);
+ }
+ }
+
+ return refCollection;
+ }
+
+ private SearchResultEntryCollection EntryHelper()
+ {
+ SearchResultEntryCollection resultCollection = new SearchResultEntryCollection();
+
+ // Get the set of control nodes
+ XmlNodeList nodeList = dsmlNode.SelectNodes("dsml:searchResultEntry", dsmlNS);
+
+ if (nodeList.Count != 0)
+ {
+ foreach (XmlNode node in nodeList)
+ {
+ Debug.Assert(node is XmlElement);
+
+ SearchResultEntry attribute = new SearchResultEntry((XmlElement)node);
+ resultCollection.Add(attribute);
+ }
+ }
+
+ return resultCollection;
+ }
+ }
+}
+
+namespace System.DirectoryServices.Protocols
+{
+ using System;
+ using System.Net;
+ using System.Xml;
+ using System.IO;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Globalization;
+
+ public class DsmlErrorResponse : DirectoryResponse
+ {
+ private string _message = null;
+ private string _detail = null;
+ private ErrorResponseCategory _category = (ErrorResponseCategory)(-1);
+
+ internal DsmlErrorResponse(XmlNode node) : base(node) { }
+
+ //
+ // Public
+ //
+
+ // Properties
+ public string Message
+ {
+ get
+ {
+ if (_message == null)
+ {
+ XmlElement elMessage = (XmlElement)dsmlNode.SelectSingleNode("dsml:message", dsmlNS);
+
+ if (elMessage != null)
+ {
+ _message = elMessage.InnerText;
+ }
+ }
+
+ return _message;
+ }
+ }
+
+ public string Detail
+ {
+ get
+ {
+ if (_detail == null)
+ {
+ XmlElement elDetail = (XmlElement)dsmlNode.SelectSingleNode("dsml:detail", dsmlNS);
+
+ if (elDetail != null)
+ {
+ _detail = elDetail.InnerXml;
+ }
+ }
+
+ return _detail;
+ }
+ }
+
+ public ErrorResponseCategory Type
+ {
+ get
+ {
+ if ((int)_category == -1)
+ {
+ XmlAttribute attrType = (XmlAttribute)dsmlNode.SelectSingleNode("@dsml:type", dsmlNS);
+
+ if (attrType == null)
+ {
+ // try it without the namespace qualifier, in case the sender omitted it
+ attrType = (XmlAttribute)dsmlNode.SelectSingleNode("@type", dsmlNS);
+ }
+
+ // verify we got a "type" attribute
+ if (attrType == null)
+ {
+ // the "type" attribute is not optional
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.MissingErrorResponseType));
+ }
+
+ // map the "type" attribute to a ErrorResponseCategory
+ switch (attrType.Value)
+ {
+ case "notAttempted":
+ _category = ErrorResponseCategory.NotAttempted;
+ break;
+
+ case "couldNotConnect":
+ _category = ErrorResponseCategory.CouldNotConnect;
+ break;
+
+ case "connectionClosed":
+ _category = ErrorResponseCategory.ConnectionClosed;
+ break;
+
+ case "malformedRequest":
+ _category = ErrorResponseCategory.MalformedRequest;
+ break;
+
+ case "gatewayInternalError":
+ _category = ErrorResponseCategory.GatewayInternalError;
+ break;
+
+ case "authenticationFailed":
+ _category = ErrorResponseCategory.AuthenticationFailed;
+ break;
+
+ case "unresolvableURI":
+ _category = ErrorResponseCategory.UnresolvableUri;
+ break;
+
+ case "other":
+ _category = ErrorResponseCategory.Other;
+ break;
+
+ default:
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.ErrorResponseInvalidValue, attrType.Value));
+ }
+ }
+
+ return _category;
+ }
+ }
+
+ public override string MatchedDN
+ {
+ get
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportOnDsmlErrRes));
+ }
+ }
+
+ public override DirectoryControl[] Controls
+ {
+ get
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportOnDsmlErrRes));
+ }
+ }
+
+ public override ResultCode ResultCode
+ {
+ get
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportOnDsmlErrRes));
+ }
+ }
+
+ public override string ErrorMessage
+ {
+ get
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportOnDsmlErrRes));
+ }
+ }
+
+ public override Uri[] Referral
+ {
+ get
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportOnDsmlErrRes));
+ }
+ }
+ }
+
+ public class DsmlAuthResponse : DirectoryResponse
+ {
+ internal DsmlAuthResponse(XmlNode node) : base(node) { }
+ }
+}
+
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/PartialResultsCollection.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/PartialResultsCollection.cs
new file mode 100644
index 0000000000..b11679ed8a
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/PartialResultsCollection.cs
@@ -0,0 +1,42 @@
+// 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
+{
+ using System;
+ using System.Collections;
+
+ public class PartialResultsCollection : ReadOnlyCollectionBase
+ {
+ internal PartialResultsCollection() { }
+
+ public object this[int index]
+ {
+ get
+ {
+ return InnerList[index];
+ }
+ }
+
+ internal int Add(object value)
+ {
+ return InnerList.Add(value);
+ }
+
+ public bool Contains(object value)
+ {
+ return InnerList.Contains(value);
+ }
+
+ public int IndexOf(object value)
+ {
+ return InnerList.IndexOf(value);
+ }
+
+ public void CopyTo(object[] values, int index)
+ {
+ InnerList.CopyTo(values, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/ReferralChasingOption.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/ReferralChasingOption.cs
new file mode 100644
index 0000000000..dc9c6d08d9
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/ReferralChasingOption.cs
@@ -0,0 +1,16 @@
+// 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
+{
+ [Flags]
+ public enum ReferralChasingOptions
+ {
+ None = 0,
+ Subordinate = 0x20,
+ External = 0x40,
+ All = Subordinate | External
+ }
+}
+
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/ResultCode.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/ResultCode.cs
new file mode 100644
index 0000000000..05bcc7852f
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/ResultCode.cs
@@ -0,0 +1,126 @@
+// 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
+{
+ using System;
+ using System.Collections;
+
+ public enum ResultCode
+ {
+ Success = 0,
+ OperationsError = 1,
+ ProtocolError = 2,
+ TimeLimitExceeded = 3,
+ SizeLimitExceeded = 4,
+ CompareFalse = 5,
+ CompareTrue = 6,
+ AuthMethodNotSupported = 7,
+ StrongAuthRequired = 8,
+ ReferralV2 = 9,
+ Referral = 10,
+ AdminLimitExceeded = 11,
+ UnavailableCriticalExtension = 12,
+ ConfidentialityRequired = 13,
+ SaslBindInProgress = 14,
+ NoSuchAttribute = 16,
+ UndefinedAttributeType = 17,
+ InappropriateMatching = 18,
+ ConstraintViolation = 19,
+ AttributeOrValueExists = 20,
+ InvalidAttributeSyntax = 21,
+ NoSuchObject = 32,
+ AliasProblem = 33,
+ InvalidDNSyntax = 34,
+ AliasDereferencingProblem = 36,
+ InappropriateAuthentication = 48,
+ InsufficientAccessRights = 50,
+ Busy = 51,
+ Unavailable = 52,
+ UnwillingToPerform = 53,
+ LoopDetect = 54,
+ SortControlMissing = 60,
+ OffsetRangeError = 61,
+ NamingViolation = 64,
+ ObjectClassViolation = 65,
+ NotAllowedOnNonLeaf = 66,
+ NotAllowedOnRdn = 67,
+ EntryAlreadyExists = 68,
+ ObjectClassModificationsProhibited = 69,
+ ResultsTooLarge = 70,
+ AffectsMultipleDsas = 71,
+ VirtualListViewError = 76,
+ Other = 80
+ }
+
+ internal class OperationErrorMappings
+ {
+ private static Hashtable s_resultCodeHash = null;
+
+ static OperationErrorMappings()
+ {
+ s_resultCodeHash = new Hashtable();
+
+ s_resultCodeHash.Add(ResultCode.Success, Res.GetString(Res.LDAP_SUCCESS));
+ s_resultCodeHash.Add(ResultCode.OperationsError, Res.GetString(Res.LDAP_OPERATIONS_ERROR));
+ s_resultCodeHash.Add(ResultCode.ProtocolError, Res.GetString(Res.LDAP_PROTOCOL_ERROR));
+ s_resultCodeHash.Add(ResultCode.TimeLimitExceeded, Res.GetString(Res.LDAP_TIMELIMIT_EXCEEDED));
+ s_resultCodeHash.Add(ResultCode.SizeLimitExceeded, Res.GetString(Res.LDAP_SIZELIMIT_EXCEEDED));
+ s_resultCodeHash.Add(ResultCode.CompareFalse, Res.GetString(Res.LDAP_COMPARE_FALSE));
+ s_resultCodeHash.Add(ResultCode.CompareTrue, Res.GetString(Res.LDAP_COMPARE_TRUE));
+ s_resultCodeHash.Add(ResultCode.AuthMethodNotSupported, Res.GetString(Res.LDAP_AUTH_METHOD_NOT_SUPPORTED));
+ s_resultCodeHash.Add(ResultCode.StrongAuthRequired, Res.GetString(Res.LDAP_STRONG_AUTH_REQUIRED));
+ s_resultCodeHash.Add(ResultCode.ReferralV2, Res.GetString(Res.LDAP_PARTIAL_RESULTS));
+ s_resultCodeHash.Add(ResultCode.Referral, Res.GetString(Res.LDAP_REFERRAL));
+ s_resultCodeHash.Add(ResultCode.AdminLimitExceeded, Res.GetString(Res.LDAP_ADMIN_LIMIT_EXCEEDED));
+ s_resultCodeHash.Add(ResultCode.UnavailableCriticalExtension, Res.GetString(Res.LDAP_UNAVAILABLE_CRIT_EXTENSION));
+ s_resultCodeHash.Add(ResultCode.ConfidentialityRequired, Res.GetString(Res.LDAP_CONFIDENTIALITY_REQUIRED));
+ s_resultCodeHash.Add(ResultCode.SaslBindInProgress, Res.GetString(Res.LDAP_SASL_BIND_IN_PROGRESS));
+ s_resultCodeHash.Add(ResultCode.NoSuchAttribute, Res.GetString(Res.LDAP_NO_SUCH_ATTRIBUTE));
+ s_resultCodeHash.Add(ResultCode.UndefinedAttributeType, Res.GetString(Res.LDAP_UNDEFINED_TYPE));
+ s_resultCodeHash.Add(ResultCode.InappropriateMatching, Res.GetString(Res.LDAP_INAPPROPRIATE_MATCHING));
+ s_resultCodeHash.Add(ResultCode.ConstraintViolation, Res.GetString(Res.LDAP_CONSTRAINT_VIOLATION));
+ s_resultCodeHash.Add(ResultCode.AttributeOrValueExists, Res.GetString(Res.LDAP_ATTRIBUTE_OR_VALUE_EXISTS));
+ s_resultCodeHash.Add(ResultCode.InvalidAttributeSyntax, Res.GetString(Res.LDAP_INVALID_SYNTAX));
+ s_resultCodeHash.Add(ResultCode.NoSuchObject, Res.GetString(Res.LDAP_NO_SUCH_OBJECT));
+ s_resultCodeHash.Add(ResultCode.AliasProblem, Res.GetString(Res.LDAP_ALIAS_PROBLEM));
+ s_resultCodeHash.Add(ResultCode.InvalidDNSyntax, Res.GetString(Res.LDAP_INVALID_DN_SYNTAX));
+ s_resultCodeHash.Add(ResultCode.AliasDereferencingProblem, Res.GetString(Res.LDAP_ALIAS_DEREF_PROBLEM));
+ s_resultCodeHash.Add(ResultCode.InappropriateAuthentication, Res.GetString(Res.LDAP_INAPPROPRIATE_AUTH));
+ s_resultCodeHash.Add(ResultCode.InsufficientAccessRights, Res.GetString(Res.LDAP_INSUFFICIENT_RIGHTS));
+ s_resultCodeHash.Add(ResultCode.Busy, Res.GetString(Res.LDAP_BUSY));
+ s_resultCodeHash.Add(ResultCode.Unavailable, Res.GetString(Res.LDAP_UNAVAILABLE));
+ s_resultCodeHash.Add(ResultCode.UnwillingToPerform, Res.GetString(Res.LDAP_UNWILLING_TO_PERFORM));
+ s_resultCodeHash.Add(ResultCode.LoopDetect, Res.GetString(Res.LDAP_LOOP_DETECT));
+ s_resultCodeHash.Add(ResultCode.SortControlMissing, Res.GetString(Res.LDAP_SORT_CONTROL_MISSING));
+ s_resultCodeHash.Add(ResultCode.OffsetRangeError, Res.GetString(Res.LDAP_OFFSET_RANGE_ERROR));
+ s_resultCodeHash.Add(ResultCode.NamingViolation, Res.GetString(Res.LDAP_NAMING_VIOLATION));
+ s_resultCodeHash.Add(ResultCode.ObjectClassViolation, Res.GetString(Res.LDAP_OBJECT_CLASS_VIOLATION));
+ s_resultCodeHash.Add(ResultCode.NotAllowedOnNonLeaf, Res.GetString(Res.LDAP_NOT_ALLOWED_ON_NONLEAF));
+ s_resultCodeHash.Add(ResultCode.NotAllowedOnRdn, Res.GetString(Res.LDAP_NOT_ALLOWED_ON_RDN));
+ s_resultCodeHash.Add(ResultCode.EntryAlreadyExists, Res.GetString(Res.LDAP_ALREADY_EXISTS));
+ s_resultCodeHash.Add(ResultCode.ObjectClassModificationsProhibited, Res.GetString(Res.LDAP_NO_OBJECT_CLASS_MODS));
+ s_resultCodeHash.Add(ResultCode.ResultsTooLarge, Res.GetString(Res.LDAP_RESULTS_TOO_LARGE));
+ s_resultCodeHash.Add(ResultCode.AffectsMultipleDsas, Res.GetString(Res.LDAP_AFFECTS_MULTIPLE_DSAS));
+ s_resultCodeHash.Add(ResultCode.VirtualListViewError, Res.GetString(Res.LDAP_VIRTUAL_LIST_VIEW_ERROR));
+ s_resultCodeHash.Add(ResultCode.Other, Res.GetString(Res.LDAP_OTHER));
+ }
+
+ static public string MapResultCode(int errorCode)
+ {
+ return (string)s_resultCodeHash[(ResultCode)errorCode];
+ }
+ }
+
+ internal enum LdapOperation
+ {
+ LdapAdd = 0,
+ LdapModify = 1,
+ LdapSearch = 2,
+ LdapDelete = 3,
+ LdapModifyDn = 4,
+ LdapCompare = 5,
+ LdapExtendedRequest = 6
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/SearchResults.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/SearchResults.cs
new file mode 100644
index 0000000000..652dfa4984
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/SearchResults.cs
@@ -0,0 +1,368 @@
+// 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
+{
+ using System;
+ using System.Net;
+ using System.Xml;
+ using System.IO;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Globalization;
+
+ public class SearchResultReference
+ {
+ private XmlNode _dsmlNode = null;
+ private XmlNamespaceManager _dsmlNS = null;
+ private bool _dsmlRequest = false;
+
+ private Uri[] _resultReferences = null;
+ private DirectoryControl[] _resultControls = null;
+
+ internal SearchResultReference(XmlNode node)
+ {
+ Debug.Assert(node != null);
+
+ _dsmlNode = node;
+
+ _dsmlNS = NamespaceUtils.GetDsmlNamespaceManager();
+
+ _dsmlRequest = true;
+ }
+
+ internal SearchResultReference(Uri[] uris)
+ {
+ _resultReferences = uris;
+ }
+
+ public Uri[] Reference
+ {
+ get
+ {
+ if (_dsmlRequest && (_resultReferences == null))
+ _resultReferences = UriHelper();
+
+ if (_resultReferences == null)
+ return new Uri[0];
+ else
+ {
+ Uri[] tempUri = new Uri[_resultReferences.Length];
+ for (int i = 0; i < _resultReferences.Length; i++)
+ {
+ tempUri[i] = new Uri(_resultReferences[i].AbsoluteUri);
+ }
+ return tempUri;
+ }
+ }
+ }
+
+ public DirectoryControl[] Controls
+ {
+ get
+ {
+ DirectoryControl[] controls = null;
+ if (_dsmlRequest && _resultControls == null)
+ {
+ _resultControls = ControlsHelper();
+ }
+
+ if (_resultControls == null)
+ return new DirectoryControl[0];
+ else
+ {
+ controls = new DirectoryControl[_resultControls.Length];
+ for (int i = 0; i < _resultControls.Length; i++)
+ {
+ controls[i] = new DirectoryControl(_resultControls[i].Type, _resultControls[i].GetValue(), _resultControls[i].IsCritical, _resultControls[i].ServerSide);
+ }
+ }
+
+ DirectoryControl.TransformControls(controls);
+
+ return controls;
+ }
+ }
+
+ private Uri[] UriHelper()
+ {
+ XmlNodeList nodeList = _dsmlNode.SelectNodes("dsml:ref", _dsmlNS);
+
+ if (nodeList.Count == 0)
+ {
+ // the server returned no controls
+ return new Uri[0];
+ }
+
+ Uri[] references = new Uri[nodeList.Count];
+ int index = 0;
+
+ foreach (XmlNode node in nodeList)
+ {
+ Debug.Assert(node is XmlElement);
+
+ references[index] = new Uri((string)node.InnerText);
+ index++;
+ }
+
+ return references;
+ }
+
+ private DirectoryControl[] ControlsHelper()
+ {
+ XmlNodeList nodeList = _dsmlNode.SelectNodes("dsml:control", _dsmlNS);
+
+ if (nodeList.Count == 0)
+ {
+ // the server returned no controls
+ return new DirectoryControl[0];
+ }
+
+ // Build the DirectoryControl array
+ DirectoryControl[] controls = new DirectoryControl[nodeList.Count];
+ int index = 0;
+
+ foreach (XmlNode node in nodeList)
+ {
+ Debug.Assert(node is XmlElement);
+
+ controls[index] = new DirectoryControl((XmlElement)node);
+ index++;
+ }
+
+ return controls;
+ }
+ }
+
+ public class SearchResultReferenceCollection : ReadOnlyCollectionBase
+ {
+ internal SearchResultReferenceCollection()
+ {
+ }
+
+ public SearchResultReference this[int index]
+ {
+ get
+ {
+ return (SearchResultReference)InnerList[index];
+ }
+ }
+
+ internal int Add(SearchResultReference reference)
+ {
+ return InnerList.Add(reference);
+ }
+
+ public bool Contains(SearchResultReference value)
+ {
+ return InnerList.Contains(value);
+ }
+
+ public int IndexOf(SearchResultReference value)
+ {
+ return InnerList.IndexOf(value);
+ }
+
+ public void CopyTo(SearchResultReference[] values, int index)
+ {
+ InnerList.CopyTo(values, index);
+ }
+
+ internal void Clear()
+ {
+ InnerList.Clear();
+ }
+ }
+
+ public class SearchResultEntry
+ {
+ private XmlNode _dsmlNode = null;
+ private XmlNamespaceManager _dsmlNS = null;
+ private bool _dsmlRequest = false;
+
+ private string _distinguishedName = null;
+ private SearchResultAttributeCollection _attributes = new SearchResultAttributeCollection();
+ private DirectoryControl[] _resultControls = null;
+
+ internal SearchResultEntry(XmlNode node)
+ {
+ Debug.Assert(node != null);
+
+ _dsmlNode = node;
+
+ _dsmlNS = NamespaceUtils.GetDsmlNamespaceManager();
+
+ _dsmlRequest = true;
+ }
+
+ internal SearchResultEntry(string dn, SearchResultAttributeCollection attrs)
+ {
+ _distinguishedName = dn;
+ _attributes = attrs;
+ }
+
+ internal SearchResultEntry(string dn)
+ {
+ _distinguishedName = dn;
+ }
+
+ public string DistinguishedName
+ {
+ get
+ {
+ if (_dsmlRequest && _distinguishedName == null)
+ _distinguishedName = DNHelper("@dsml:dn", "@dn");
+
+ return _distinguishedName;
+ }
+ }
+
+ public SearchResultAttributeCollection Attributes
+ {
+ get
+ {
+ if (_dsmlRequest && (_attributes.Count == 0))
+ _attributes = AttributesHelper();
+
+ return _attributes;
+ }
+ }
+
+ public DirectoryControl[] Controls
+ {
+ get
+ {
+ DirectoryControl[] controls = null;
+ if (_dsmlRequest && (_resultControls == null))
+ {
+ _resultControls = ControlsHelper();
+ }
+
+ if (_resultControls == null)
+ return new DirectoryControl[0];
+ else
+ {
+ controls = new DirectoryControl[_resultControls.Length];
+ for (int i = 0; i < _resultControls.Length; i++)
+ {
+ controls[i] = new DirectoryControl(_resultControls[i].Type, _resultControls[i].GetValue(), _resultControls[i].IsCritical, _resultControls[i].ServerSide);
+ }
+ }
+
+ DirectoryControl.TransformControls(controls);
+
+ return controls;
+ }
+ }
+
+ private string DNHelper(string primaryXPath, string secondaryXPath)
+ {
+ XmlAttribute attrDN = (XmlAttribute)_dsmlNode.SelectSingleNode(primaryXPath, _dsmlNS);
+
+ if (attrDN == null)
+ {
+ // try it without the namespace qualifier, in case the sender omitted it
+ attrDN = (XmlAttribute)_dsmlNode.SelectSingleNode(secondaryXPath, _dsmlNS);
+
+ if (attrDN == null)
+ {
+ // the element doesn't have a associated dn
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.MissingSearchResultEntryDN));
+ }
+
+ return attrDN.Value;
+ }
+ else
+ {
+ return attrDN.Value;
+ }
+ }
+
+ private SearchResultAttributeCollection AttributesHelper()
+ {
+ SearchResultAttributeCollection attributes = new SearchResultAttributeCollection();
+
+ XmlNodeList nodeList = _dsmlNode.SelectNodes("dsml:attr", _dsmlNS);
+
+ if (nodeList.Count != 0)
+ {
+ foreach (XmlNode node in nodeList)
+ {
+ Debug.Assert(node is XmlElement);
+
+ DirectoryAttribute attribute = new DirectoryAttribute((XmlElement)node);
+ attributes.Add(attribute.Name, attribute);
+ }
+ }
+
+ return attributes;
+ }
+
+ private DirectoryControl[] ControlsHelper()
+ {
+ XmlNodeList nodeList = _dsmlNode.SelectNodes("dsml:control", _dsmlNS);
+
+ if (nodeList.Count == 0)
+ {
+ // the server returned no controls
+ return new DirectoryControl[0];
+ }
+
+ // Build the DirectoryControl array
+ DirectoryControl[] controls = new DirectoryControl[nodeList.Count];
+ int index = 0;
+
+ foreach (XmlNode node in nodeList)
+ {
+ Debug.Assert(node is XmlElement);
+
+ controls[index] = new DirectoryControl((XmlElement)node);
+ index++;
+ }
+
+ return controls;
+ }
+ }
+
+ public class SearchResultEntryCollection : ReadOnlyCollectionBase
+ {
+ internal SearchResultEntryCollection()
+ {
+ }
+
+ public SearchResultEntry this[int index]
+ {
+ get
+ {
+ return (SearchResultEntry)InnerList[index];
+ }
+ }
+
+ internal int Add(SearchResultEntry entry)
+ {
+ return InnerList.Add(entry);
+ }
+
+ public bool Contains(SearchResultEntry value)
+ {
+ return InnerList.Contains(value);
+ }
+
+ public int IndexOf(SearchResultEntry value)
+ {
+ return InnerList.IndexOf(value);
+ }
+
+ public void CopyTo(SearchResultEntry[] values, int index)
+ {
+ InnerList.CopyTo(values, index);
+ }
+
+ internal void Clear()
+ {
+ InnerList.Clear();
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/SearchScope.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/SearchScope.cs
new file mode 100644
index 0000000000..1a7c846c46
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/SearchScope.cs
@@ -0,0 +1,13 @@
+// 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 enum SearchScope
+ {
+ Base = 0,
+ OneLevel = 1,
+ Subtree = 2
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlAsyncResult.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlAsyncResult.cs
new file mode 100644
index 0000000000..41659027a1
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlAsyncResult.cs
@@ -0,0 +1,108 @@
+// 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
+{
+ using System;
+ using System.Threading;
+ using System.Net;
+ using System.Text;
+ using System.IO;
+ using Microsoft.Win32.SafeHandles;
+
+ internal class DsmlAsyncResult : IAsyncResult
+ {
+ private DsmlAsyncWaitHandle _asyncWaitHandle = null;
+ internal AsyncCallback callback = null;
+ internal bool completed = false;
+ private bool _completedSynchronously = false;
+ internal ManualResetEvent manualResetEvent = null;
+ private object _stateObject = null;
+ internal RequestState resultObject = null;
+ internal bool hasValidRequest = false;
+
+ public DsmlAsyncResult(AsyncCallback callbackRoutine, object state)
+ {
+ _stateObject = state;
+ callback = callbackRoutine;
+ manualResetEvent = new ManualResetEvent(false);
+ }
+
+ object IAsyncResult.AsyncState
+ {
+ get { return _stateObject; }
+ }
+
+ WaitHandle IAsyncResult.AsyncWaitHandle
+ {
+ get
+ {
+ if (null == _asyncWaitHandle)
+ {
+ _asyncWaitHandle = new DsmlAsyncWaitHandle(manualResetEvent.SafeWaitHandle);
+ }
+
+ return (WaitHandle)_asyncWaitHandle;
+ }
+ }
+
+ bool IAsyncResult.CompletedSynchronously
+ {
+ get { return _completedSynchronously; }
+ }
+
+ bool IAsyncResult.IsCompleted
+ {
+ get { return completed; }
+ }
+
+ public override int GetHashCode()
+ {
+ return manualResetEvent.GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if ((!(o is DsmlAsyncResult)) || (o == null))
+ {
+ return false;
+ }
+
+ return (this == (DsmlAsyncResult)o);
+ }
+
+ sealed internal class DsmlAsyncWaitHandle : WaitHandle
+ {
+ public DsmlAsyncWaitHandle(SafeWaitHandle handle) : base()
+ {
+ this.SafeWaitHandle = handle;
+ }
+
+ ~DsmlAsyncWaitHandle()
+ {
+ this.SafeWaitHandle = null;
+ }
+ }
+ }
+
+ internal class RequestState
+ {
+ public const int bufferSize = 1024;
+ public StringBuilder responseString = new StringBuilder(1024);
+ public string requestString = null;
+ public HttpWebRequest request = null;
+ public Stream requestStream = null;
+ public Stream responseStream = null;
+ public byte[] bufferRead = null;
+ public UTF8Encoding encoder = new UTF8Encoding();
+ public DsmlAsyncResult dsmlAsync = null;
+ internal bool abortCalled = false;
+ internal Exception exception = null;
+
+ public RequestState()
+ {
+ bufferRead = new byte[bufferSize];
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlConstants.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlConstants.cs
new file mode 100644
index 0000000000..516fca70f8
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlConstants.cs
@@ -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.
+
+namespace System.DirectoryServices.Protocols
+{
+ internal class DsmlConstants
+ {
+ private DsmlConstants() { }
+
+ // XML namespace URIs
+ public const string DsmlUri = "urn:oasis:names:tc:DSML:2:0:core";
+ public const string XsiUri = "http://www.w3.org/2001/XMLSchema-instance";
+ public const string XsdUri = "http://www.w3.org/2001/XMLSchema";
+ public const string SoapUri = "http://schemas.xmlsoap.org/soap/envelope/";
+ public const string ADSessionUri = "urn:schema-microsoft-com:activedirectory:dsmlv2";
+
+ // default search filter
+ public const string DefaultSearchFilter = "<present name='objectClass' xmlns=\"" + DsmlUri + "\"/>";
+
+ // HTTP method
+ public const string HttpPostMethod = "POST";
+
+ // SOAP elements
+ public const string SOAPEnvelopeBegin = "<se:Envelope xmlns:se=\"" + SoapUri + "\">";
+ public const string SOAPEnvelopeEnd = "</se:Envelope>";
+ public const string SOAPBodyBegin = "<se:Body xmlns=\"" + DsmlUri + "\">";
+ public const string SOAPBodyEnd = "</se:Body>";
+ public const string SOAPHeaderBegin = "<se:Header>";
+ public const string SOAPHeaderEnd = "</se:Header>";
+
+ public const string SOAPSession1 = "<ad:Session xmlns:ad=\"" + ADSessionUri + "\" ad:SessionID=\"";
+ public const string SOAPSession2 = "\" se:mustUnderstand=\"1\"/>";
+
+ public const string SOAPBeginSession = "<ad:BeginSession xmlns:ad=\"" + ADSessionUri + "\" se:mustUnderstand=\"1\"/>";
+
+ public const string SOAPEndSession1 = "<ad:EndSession xmlns:ad=\"" + ADSessionUri + "\" ad:SessionID=\"";
+ public const string SOAPEndSession2 = "\" se:mustUnderstand=\"1\"/>";
+
+ // DSML v2 Response Elements
+ public const string DsmlErrorResponse = "errorResponse";
+ public const string DsmlSearchResponse = "searchResponse";
+ public const string DsmlModifyResponse = "modifyResponse";
+ public const string DsmlAddResponse = "addResponse";
+ public const string DsmlDelResponse = "delResponse";
+ public const string DsmlModDNResponse = "modDNResponse";
+ public const string DsmlCompareResponse = "compareResponse";
+ public const string DsmlExtendedResponse = "extendedResponse";
+ public const string DsmlAuthResponse = "authResponse";
+
+ public const string AttrTypePrefixedName = "xsi:type";
+ public const string AttrBinaryTypePrefixedValue = "xsd:base64Binary";
+ public const string AttrDsmlAttrName = "name";
+ public const string ElementDsmlAttrValue = "value";
+ public const string ElementSearchReqFilter = "filter";
+
+ public const string ElementSearchReqFilterAnd = "and";
+ public const string ElementSearchReqFilterOr = "or";
+ public const string ElementSearchReqFilterNot = "not";
+ public const string ElementSearchReqFilterSubstr = "substrings";
+ public const string ElementSearchReqFilterEqual = "equalityMatch";
+ public const string ElementSearchReqFilterGrteq = "greaterOrEqual";
+ public const string ElementSearchReqFilterLesseq = "lessOrEqual";
+ public const string ElementSearchReqFilterApprox = "approxMatch";
+ public const string ElementSearchReqFilterPresent = "present";
+ public const string ElementSearchReqFilterExtenmatch = "extensibleMatch";
+ public const string ElementSearchReqFilterExtenmatchValue = "value";
+
+ public const string AttrSearchReqFilterPresentName = "name";
+ public const string AttrSearchReqFilterExtenmatchName = "name";
+ public const string AttrSearchReqFilterExtenmatchMatchrule = "matchingRule";
+ public const string AttrSearchReqFilterExtenmatchDnattr = "dnAttributes";
+
+ public const string AttrSearchReqFilterSubstrName = "name";
+ public const string ElementSearchReqFilterSubstrInit = "initial";
+ public const string ElementSearchReqFilterSubstrAny = "any";
+ public const string ElementSearchReqFilterSubstrFinal = "final";
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDirectoryIdentifier.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDirectoryIdentifier.cs
new file mode 100644
index 0000000000..1e382cd07d
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDirectoryIdentifier.cs
@@ -0,0 +1,40 @@
+// 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
+{
+ using System;
+ using System.Globalization;
+
+ public class DsmlDirectoryIdentifier : DirectoryIdentifier
+ {
+ // private members
+ private Uri _uri = null;
+
+ public DsmlDirectoryIdentifier(Uri serverUri)
+ {
+ if (serverUri == null)
+ {
+ throw new ArgumentNullException("serverUri");
+ }
+
+ // Is it a http or https Uri?
+ if ((String.Compare(serverUri.Scheme, "http", StringComparison.OrdinalIgnoreCase) != 0) &&
+ (String.Compare(serverUri.Scheme, "https", StringComparison.OrdinalIgnoreCase) != 0))
+ {
+ throw new ArgumentException(Res.GetString(Res.DsmlNonHttpUri));
+ }
+
+ _uri = serverUri;
+ }
+
+ public Uri ServerUri
+ {
+ get
+ {
+ return _uri;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDocument.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDocument.cs
new file mode 100644
index 0000000000..446665d5d2
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDocument.cs
@@ -0,0 +1,751 @@
+// 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
+{
+ using System;
+ using System.Collections;
+ using System.Xml;
+ using System.Diagnostics;
+ using System.Net;
+ using System.IO;
+ using System.Text;
+ using System.ComponentModel;
+
+ public abstract class DsmlDocument
+ {
+ internal string dsmlRequestID = null;
+ public abstract XmlDocument ToXml();
+ }
+
+ public class DsmlRequestDocument : DsmlDocument, IList, IEnumerable
+ {
+ private DsmlDocumentProcessing _docProcessing = DsmlDocumentProcessing.Sequential;
+ private DsmlResponseOrder _resOrder = DsmlResponseOrder.Sequential;
+ private DsmlErrorProcessing _errProcessing = DsmlErrorProcessing.Exit;
+ private ArrayList _dsmlRequests;
+
+ public DsmlRequestDocument()
+ {
+ Utility.CheckOSVersion();
+
+ _dsmlRequests = new ArrayList();
+ }
+
+ public DsmlDocumentProcessing DocumentProcessing
+ {
+ get
+ {
+ return _docProcessing;
+ }
+ set
+ {
+ if (value < DsmlDocumentProcessing.Sequential || value > DsmlDocumentProcessing.Parallel)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(DsmlDocumentProcessing));
+
+ _docProcessing = value;
+ }
+ }
+
+ public DsmlResponseOrder ResponseOrder
+ {
+ get
+ {
+ return _resOrder;
+ }
+ set
+ {
+ if (value < DsmlResponseOrder.Sequential || value > DsmlResponseOrder.Unordered)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(DsmlResponseOrder));
+
+ _resOrder = value;
+ }
+ }
+
+ public DsmlErrorProcessing ErrorProcessing
+ {
+ get
+ {
+ return _errProcessing;
+ }
+ set
+ {
+ if (value < DsmlErrorProcessing.Resume || value > DsmlErrorProcessing.Exit)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(DsmlErrorProcessing));
+
+ _errProcessing = value;
+ }
+ }
+
+ public string RequestId
+ {
+ get
+ {
+ return dsmlRequestID;
+ }
+ set
+ {
+ dsmlRequestID = value;
+ }
+ }
+
+ bool IList.IsFixedSize
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ bool IList.IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ return _dsmlRequests.SyncRoot;
+ }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return _dsmlRequests.IsSynchronized;
+ }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _dsmlRequests.GetEnumerator();
+ }
+
+ protected bool IsFixedSize
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ protected bool IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ protected object SyncRoot
+ {
+ get
+ {
+ return _dsmlRequests.SyncRoot;
+ }
+ }
+
+ protected bool IsSynchronized
+ {
+ get
+ {
+ return _dsmlRequests.IsSynchronized;
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ return _dsmlRequests.Count;
+ }
+ }
+
+ int ICollection.Count
+ {
+ get
+ {
+ return _dsmlRequests.Count;
+ }
+ }
+
+ public DirectoryRequest this[int index]
+ {
+ get
+ {
+ return (DirectoryRequest)_dsmlRequests[index];
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _dsmlRequests[index] = value;
+ }
+ }
+
+ object IList.this[int index]
+ {
+ get
+ {
+ return this[index];
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!(value is DirectoryRequest))
+ throw new ArgumentException(Res.GetString(Res.InvalidValueType, "DirectoryRequest"), "value");
+
+ _dsmlRequests[index] = (DirectoryRequest)value;
+ }
+ }
+
+ public int Add(DirectoryRequest request)
+ {
+ if (request == null)
+ throw new ArgumentNullException("request");
+
+ return _dsmlRequests.Add(request);
+ }
+
+ int IList.Add(object request)
+ {
+ if (request == null)
+ throw new ArgumentNullException("request");
+
+ if (!(request is DirectoryRequest))
+ throw new ArgumentException(Res.GetString(Res.InvalidValueType, "DirectoryRequest"), "request");
+
+ return Add((DirectoryRequest)request);
+ }
+
+ public void Clear()
+ {
+ _dsmlRequests.Clear();
+ }
+
+ void IList.Clear()
+ {
+ Clear();
+ }
+
+ public bool Contains(DirectoryRequest value)
+ {
+ return _dsmlRequests.Contains(value);
+ }
+
+ bool IList.Contains(Object value)
+ {
+ return Contains((DirectoryRequest)value);
+ }
+
+ public int IndexOf(DirectoryRequest value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return _dsmlRequests.IndexOf(value);
+ }
+
+ int IList.IndexOf(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return IndexOf((DirectoryRequest)value);
+ }
+
+ public void Insert(int index, DirectoryRequest value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _dsmlRequests.Insert(index, value);
+ }
+
+ void IList.Insert(int index, object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!(value is DirectoryRequest))
+ throw new ArgumentException(Res.GetString(Res.InvalidValueType, "DirectoryRequest"), "value");
+
+ Insert(index, (DirectoryRequest)value);
+ }
+
+ public void Remove(DirectoryRequest value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _dsmlRequests.Remove(value);
+ }
+
+ void IList.Remove(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ Remove((DirectoryRequest)value);
+ }
+
+ public void RemoveAt(int index)
+ {
+ _dsmlRequests.RemoveAt(index);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ RemoveAt(index);
+ }
+
+ public void CopyTo(DirectoryRequest[] value, int i)
+ {
+ _dsmlRequests.CopyTo(value, i);
+ }
+
+ void ICollection.CopyTo(Array value, int i)
+ {
+ _dsmlRequests.CopyTo(value, i);
+ }
+
+ public override XmlDocument ToXml()
+ {
+ XmlDocument xmldoc = new XmlDocument();
+
+ // create the batchRequest root element
+ StartBatchRequest(xmldoc);
+
+ // persist each operation under the batchRequest
+ foreach (DirectoryRequest el in _dsmlRequests)
+ {
+ xmldoc.DocumentElement.AppendChild(el.ToXmlNodeHelper(xmldoc));
+ }
+
+ return xmldoc;
+ }
+
+ private void StartBatchRequest(XmlDocument xmldoc)
+ {
+ //
+ // Start with the common information
+ // We'll make DSMLv2 the default namespace
+ //
+ string emptyLoad = "<batchRequest " +
+ "xmlns=\"" + DsmlConstants.DsmlUri + "\" " +
+ "xmlns:xsd=\"" + DsmlConstants.XsdUri + "\" " +
+ "xmlns:xsi=\"" + DsmlConstants.XsiUri + "\" />";
+ xmldoc.LoadXml(emptyLoad);
+
+ //
+ // Add in the DSML v2 processing directives
+ //
+ XmlAttribute attr;
+
+ // DocumentProcessing
+ attr = xmldoc.CreateAttribute("processing", null);
+ switch (_docProcessing)
+ {
+ case DsmlDocumentProcessing.Sequential:
+ attr.InnerText = "sequential";
+ break;
+
+ case DsmlDocumentProcessing.Parallel:
+ attr.InnerText = "parallel";
+ break;
+
+ default:
+ Debug.Assert(false, "Unknown DocumentProcessing type");
+ break;
+ }
+
+ xmldoc.DocumentElement.Attributes.Append(attr);
+
+ // ResponseOrder
+ attr = xmldoc.CreateAttribute("responseOrder", null);
+ switch (_resOrder)
+ {
+ case DsmlResponseOrder.Sequential:
+ attr.InnerText = "sequential";
+ break;
+
+ case DsmlResponseOrder.Unordered:
+ attr.InnerText = "unordered";
+ break;
+
+ default:
+ Debug.Assert(false, "Unknown ResponseOrder type");
+ break;
+ }
+
+ xmldoc.DocumentElement.Attributes.Append(attr);
+
+ // ErrorProcessing
+ attr = xmldoc.CreateAttribute("onError", null);
+ switch (_errProcessing)
+ {
+ case DsmlErrorProcessing.Exit:
+ attr.InnerText = "exit";
+ break;
+
+ case DsmlErrorProcessing.Resume:
+ attr.InnerText = "resume";
+ break;
+
+ default:
+ Debug.Assert(false, "Unknown ErrorProcessing type");
+ break;
+ }
+
+ xmldoc.DocumentElement.Attributes.Append(attr);
+
+ //
+ // RequestID
+ //
+ if (dsmlRequestID != null)
+ {
+ attr = xmldoc.CreateAttribute("requestID", null);
+ attr.InnerText = dsmlRequestID;
+ xmldoc.DocumentElement.Attributes.Append(attr);
+ }
+ }
+ }
+
+ public class DsmlResponseDocument : DsmlDocument, ICollection, IEnumerable
+ {
+ private ArrayList _dsmlResponse;
+ private XmlDocument _dsmlDocument = null;
+ private XmlElement _dsmlBatchResponse = null;
+
+ private XmlNamespaceManager _dsmlNS = null;
+
+ private DsmlResponseDocument()
+ {
+ _dsmlResponse = new ArrayList();
+ }
+
+ internal DsmlResponseDocument(HttpWebResponse resp, string xpathToResponse) : this()
+ {
+ // Our caller (the DsmlConnection-derived class) passes us the XPath telling us
+ // how to locate the batchResponse element. This permits us to work with
+ // different transport protocols.
+
+ // Get the response stream
+ Stream respStream = resp.GetResponseStream();
+ StreamReader respStreamReader = new StreamReader(respStream);
+
+ try
+ {
+ // Load the response from the stream into the XmlDocument
+ _dsmlDocument = new XmlDocument();
+
+ try
+ {
+ _dsmlDocument.Load(respStreamReader);
+ }
+ catch (XmlException)
+ {
+ // The server didn't return well-formed XML to us
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.NotWellFormedResponse));
+ }
+
+ // Locate the batchResponse element within the response document
+ _dsmlNS = NamespaceUtils.GetDsmlNamespaceManager();
+ _dsmlBatchResponse = (XmlElement)_dsmlDocument.SelectSingleNode(xpathToResponse, _dsmlNS);
+
+ if (_dsmlBatchResponse == null)
+ {
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.NotWellFormedResponse));
+ }
+
+ // parse the response and put it in our internal store
+ XmlNodeList nodeList = _dsmlBatchResponse.ChildNodes;
+
+ // Unfortunately, we can't just index into the XmlNodeList,
+ // because it's a list of all the nodes, not just the elements.
+ // We're interested in the Nth element, not the Nth node.
+
+ foreach (XmlNode node in nodeList)
+ {
+ if (node.NodeType == XmlNodeType.Element)
+ {
+ Debug.Assert(node is XmlElement);
+
+ DirectoryResponse el = ConstructElement((XmlElement)node);
+ _dsmlResponse.Add(el);
+ }
+ }
+ }
+ finally
+ {
+ respStreamReader.Close();
+ }
+ }
+
+ internal DsmlResponseDocument(StringBuilder responseString, string xpathToResponse) : this()
+ {
+ _dsmlDocument = new XmlDocument();
+
+ try
+ {
+ _dsmlDocument.LoadXml(responseString.ToString());
+ }
+ catch (XmlException)
+ {
+ // The server didn't return well-formed XML to us
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.NotWellFormedResponse));
+ }
+
+ // Locate the batchResponse element within the response document
+ _dsmlNS = NamespaceUtils.GetDsmlNamespaceManager();
+ _dsmlBatchResponse = (XmlElement)_dsmlDocument.SelectSingleNode(xpathToResponse, _dsmlNS);
+
+ if (_dsmlBatchResponse == null)
+ {
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.NotWellFormedResponse));
+ }
+
+ // parse the response and put it in our internal store
+ XmlNodeList nodeList = _dsmlBatchResponse.ChildNodes;
+
+ // Unfortunately, we can't just index into the XmlNodeList,
+ // because it's a list of all the nodes, not just the elements.
+ // We're interested in the Nth element, not the Nth node.
+
+ foreach (XmlNode node in nodeList)
+ {
+ if (node.NodeType == XmlNodeType.Element)
+ {
+ Debug.Assert(node is XmlElement);
+
+ DirectoryResponse el = ConstructElement((XmlElement)node);
+ _dsmlResponse.Add(el);
+ }
+ }
+ }
+
+ private DsmlResponseDocument(string responseString) : this(new StringBuilder(responseString), "se:Envelope/se:Body/dsml:batchResponse")
+ {
+ }
+
+ public bool IsErrorResponse
+ {
+ get
+ {
+ // check whether there is a DsmlErrorResponse object
+ foreach (DirectoryResponse res in _dsmlResponse)
+ {
+ if (res is DsmlErrorResponse)
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ public bool IsOperationError
+ {
+ get
+ {
+ foreach (DirectoryResponse res in _dsmlResponse)
+ {
+ if (!(res is DsmlErrorResponse))
+ {
+ ResultCode result = res.ResultCode;
+ if (ResultCode.Success != result &&
+ ResultCode.CompareTrue != result &&
+ ResultCode.CompareFalse != result &&
+ ResultCode.Referral != result &&
+ ResultCode.ReferralV2 != result)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public string RequestId
+ {
+ get
+ {
+ // Locate the requestID attribute on the batchResponse element
+ XmlAttribute attrReqID = (XmlAttribute)_dsmlBatchResponse.SelectSingleNode("@dsml:requestID", _dsmlNS);
+
+ if (attrReqID == null)
+ {
+ // try it without the namespace qualifier, in case the sender omitted it
+ attrReqID = (XmlAttribute)_dsmlBatchResponse.SelectSingleNode("@requestID", _dsmlNS);
+
+ if (attrReqID == null)
+ {
+ // server didn't return a requestID
+ return null;
+ }
+
+ return attrReqID.Value;
+ }
+ else
+ {
+ return attrReqID.Value;
+ }
+ }
+ }
+
+ internal string ResponseString
+ {
+ get
+ {
+ if (_dsmlDocument != null)
+ return _dsmlDocument.InnerXml;
+ else
+ return null;
+ }
+ }
+
+ // methods
+ public override XmlDocument ToXml()
+ {
+ // returns a copy of the current document
+
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(_dsmlBatchResponse.OuterXml);
+
+ return doc;
+ }
+
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ return _dsmlResponse.SyncRoot;
+ }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return _dsmlResponse.IsSynchronized;
+ }
+ }
+
+ int ICollection.Count
+ {
+ get
+ {
+ return _dsmlResponse.Count;
+ }
+ }
+
+ void ICollection.CopyTo(Array value, int i)
+ {
+ _dsmlResponse.CopyTo(value, i);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _dsmlResponse.GetEnumerator();
+ }
+
+ protected object SyncRoot
+ {
+ get
+ {
+ return _dsmlResponse.SyncRoot;
+ }
+ }
+
+ protected bool IsSynchronized
+ {
+ get
+ {
+ return _dsmlResponse.IsSynchronized;
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ return _dsmlResponse.Count;
+ }
+ }
+
+ public DirectoryResponse this[int index]
+ {
+ get
+ {
+ return (DirectoryResponse)_dsmlResponse[index];
+ }
+ }
+
+ public void CopyTo(DirectoryResponse[] value, int i)
+ {
+ _dsmlResponse.CopyTo(value, i);
+ }
+
+ private DirectoryResponse ConstructElement(XmlElement node)
+ {
+ DirectoryResponse el = null;
+
+ Debug.Assert(node != null);
+
+ switch (node.LocalName)
+ {
+ case DsmlConstants.DsmlErrorResponse:
+ el = new DsmlErrorResponse(node);
+ break;
+
+ case DsmlConstants.DsmlSearchResponse:
+ el = new SearchResponse(node);
+ break;
+
+ case DsmlConstants.DsmlModifyResponse:
+ el = new ModifyResponse(node);
+ break;
+
+ case DsmlConstants.DsmlAddResponse:
+ el = new AddResponse(node);
+ break;
+
+ case DsmlConstants.DsmlDelResponse:
+ el = new DeleteResponse(node);
+ break;
+
+ case DsmlConstants.DsmlModDNResponse:
+ el = new ModifyDNResponse(node);
+ break;
+
+ case DsmlConstants.DsmlCompareResponse:
+ el = new CompareResponse(node);
+ break;
+
+ case DsmlConstants.DsmlExtendedResponse:
+ el = new ExtendedResponse(node);
+ break;
+
+ case DsmlConstants.DsmlAuthResponse:
+ el = new DsmlAuthResponse(node);
+ break;
+ default:
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.UnknownResponseElement));
+ }
+
+ Debug.Assert(el != null);
+
+ return el;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDocumentProcessing.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDocumentProcessing.cs
new file mode 100644
index 0000000000..b81fc09a2b
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlDocumentProcessing.cs
@@ -0,0 +1,36 @@
+// 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 enum DsmlDocumentProcessing
+ {
+ Sequential = 0,
+ Parallel = 1
+ }
+
+ public enum DsmlResponseOrder
+ {
+ Sequential = 0,
+ Unordered = 1
+ }
+
+ public enum DsmlErrorProcessing
+ {
+ Resume = 0,
+ Exit = 1
+ }
+
+ public enum ErrorResponseCategory
+ {
+ NotAttempted = 0,
+ CouldNotConnect = 1,
+ ConnectionClosed = 2,
+ MalformedRequest = 3,
+ GatewayInternalError = 4,
+ AuthenticationFailed = 5,
+ UnresolvableUri = 6,
+ Other = 7
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlException.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlException.cs
new file mode 100644
index 0000000000..583df3a237
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlException.cs
@@ -0,0 +1,55 @@
+// 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
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+
+ [Serializable]
+ public class DsmlInvalidDocumentException : DirectoryException
+ {
+ public DsmlInvalidDocumentException() : base(Res.GetString(Res.InvalidDocument)) { }
+ public DsmlInvalidDocumentException(string message) : base(message) { }
+ public DsmlInvalidDocumentException(string message, Exception inner) : base(message, inner) { }
+ protected DsmlInvalidDocumentException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+ }
+
+ [Serializable]
+ public class ErrorResponseException : DirectoryException, ISerializable
+ {
+ private DsmlErrorResponse _errorResponse = null;
+ protected ErrorResponseException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+
+ public ErrorResponseException() : base() { }
+
+ public ErrorResponseException(string message) : base(message) { }
+
+ public ErrorResponseException(string message, Exception inner) : base(message, inner) { }
+
+ public ErrorResponseException(DsmlErrorResponse response) : this(response, Res.GetString(Res.ErrorResponse), null) { }
+
+ public ErrorResponseException(DsmlErrorResponse response, string message) : this(response, message, null) { }
+
+ public ErrorResponseException(DsmlErrorResponse response, string message, Exception inner) : base(message, inner)
+ {
+ _errorResponse = response;
+ }
+
+ public DsmlErrorResponse Response
+ {
+ get
+ {
+ return _errorResponse;
+ }
+ }
+
+ [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlSoapConnection.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlSoapConnection.cs
new file mode 100644
index 0000000000..6d7df9a204
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlSoapConnection.cs
@@ -0,0 +1,45 @@
+// 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
+{
+ using System;
+ using System.Net;
+ using System.Security.Cryptography.X509Certificates;
+ using System.Xml;
+ using System.Security.Permissions;
+
+ public abstract class DsmlSoapConnection : DirectoryConnection
+ {
+ internal XmlNode soapHeaders = null;
+
+ protected DsmlSoapConnection() { }
+
+ public abstract string SessionId
+ {
+ get;
+ }
+
+ public XmlNode SoapRequestHeader
+ {
+ get
+ {
+ return soapHeaders;
+ }
+ set
+ {
+ soapHeaders = value;
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public abstract void BeginSession();
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public abstract void EndSession();
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlSoapHttpConnection.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlSoapHttpConnection.cs
new file mode 100644
index 0000000000..ac4b2e6588
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/DsmlSoapHttpConnection.cs
@@ -0,0 +1,823 @@
+// 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
+{
+ using System;
+ using System.Net;
+ using System.Security.Cryptography.X509Certificates;
+ using System.Xml;
+ using System.IO;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Text;
+ using System.Collections;
+ using System.Threading;
+ using System.Security.Permissions;
+ using System.Net.NetworkInformation;
+
+ public class DsmlSoapHttpConnection : DsmlSoapConnection
+ {
+ private HttpWebRequest _dsmlHttpConnection = null;
+ private string _dsmlSoapAction = "\"#batchRequest\"";
+ private AuthType _dsmlAuthType = AuthType.Negotiate;
+ private string _dsmlSessionID = null;
+ private Hashtable _httpConnectionTable = null;
+ private string _debugResponse = null;
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DsmlSoapHttpConnection(Uri uri) : this(new DsmlDirectoryIdentifier(uri))
+ {
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true),
+ WebPermission(SecurityAction.Assert, Unrestricted = true)
+ ]
+ public DsmlSoapHttpConnection(DsmlDirectoryIdentifier identifier)
+ {
+ if (identifier == null)
+ throw new ArgumentNullException("identifier");
+
+ directoryIdentifier = identifier;
+ _dsmlHttpConnection = (HttpWebRequest)WebRequest.Create(((DsmlDirectoryIdentifier)directoryIdentifier).ServerUri);
+ Hashtable tempTable = new Hashtable();
+ _httpConnectionTable = Hashtable.Synchronized(tempTable);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true),
+ EnvironmentPermission(SecurityAction.Assert, Unrestricted = true),
+ SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
+ ]
+ public DsmlSoapHttpConnection(DsmlDirectoryIdentifier identifier, NetworkCredential credential) : this(identifier)
+ {
+ directoryCredential = (credential != null) ? new NetworkCredential(credential.UserName, credential.Password, credential.Domain) : null;
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DsmlSoapHttpConnection(DsmlDirectoryIdentifier identifier, NetworkCredential credential, AuthType authType) : this(identifier, credential)
+ {
+ AuthType = authType;
+ }
+
+ public override TimeSpan Timeout
+ {
+ get
+ {
+ return connectionTimeOut;
+ }
+ set
+ {
+ if (value < TimeSpan.Zero)
+ {
+ throw new ArgumentException(Res.GetString(Res.NoNegativeTime), "value");
+ }
+
+ // prevent integer overflow
+ if (value.TotalMilliseconds > Int32.MaxValue)
+ throw new ArgumentException(Res.GetString(Res.TimespanExceedMax), "value");
+
+ connectionTimeOut = value;
+ }
+ }
+
+ public string SoapActionHeader
+ {
+ get
+ {
+ return _dsmlSoapAction;
+ }
+ set
+ {
+ _dsmlSoapAction = value;
+ }
+ }
+
+ public AuthType AuthType
+ {
+ get
+ {
+ return _dsmlAuthType;
+ }
+ set
+ {
+ if (value < AuthType.Anonymous || value > AuthType.Kerberos)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(AuthType));
+
+ if ((value != AuthType.Anonymous) && (value != AuthType.Ntlm) && (value != AuthType.Basic) && (value != AuthType.Negotiate) && (value != AuthType.Digest))
+ {
+ throw new ArgumentException(Res.GetString(Res.WrongAuthType, value), "value");
+ }
+
+ _dsmlAuthType = value;
+ }
+ }
+
+ public override string SessionId
+ {
+ get
+ {
+ return _dsmlSessionID;
+ }
+ }
+
+ private string ResponseString
+ {
+ get
+ {
+ return _debugResponse;
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ WebPermission(SecurityAction.Assert, Unrestricted = true),
+ NetworkInformationPermission(SecurityAction.Assert, Unrestricted = true)
+ ]
+ public override void BeginSession()
+ {
+ // make sure a session isn't already active
+ if (_dsmlSessionID != null)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SessionInUse));
+ }
+
+ try
+ {
+ //
+ // Request
+ //
+
+ // Do the generic preparation of the request
+ PrepareHttpWebRequest(_dsmlHttpConnection);
+
+ // Get the stream we're going to write to
+ StreamWriter reqWriter = GetWebRequestStreamWriter();
+
+ try
+ {
+ // write out the EndSession request
+ reqWriter.Write(DsmlConstants.SOAPEnvelopeBegin);
+
+ reqWriter.Write(DsmlConstants.SOAPHeaderBegin);
+ reqWriter.Write(DsmlConstants.SOAPBeginSession); // BeginSession
+ // other user provided soap headers
+ if (soapHeaders != null)
+ reqWriter.Write(soapHeaders.OuterXml);
+ reqWriter.Write(DsmlConstants.SOAPHeaderEnd);
+
+ reqWriter.Write(DsmlConstants.SOAPBodyBegin);
+ reqWriter.Write(new DsmlRequestDocument().ToXml().InnerXml); // empty batchRequest
+ reqWriter.Write(DsmlConstants.SOAPBodyEnd);
+
+ reqWriter.Write(DsmlConstants.SOAPEnvelopeEnd);
+
+ // Close out the stream
+ reqWriter.Flush();
+ }
+ finally
+ {
+ reqWriter.BaseStream.Close();
+ reqWriter.Close();
+ }
+
+ //
+ // Response
+ //
+
+ // Actually send the request and get the response
+ HttpWebResponse dsmlResponse = (HttpWebResponse)_dsmlHttpConnection.GetResponse();
+ // N.B.: we deliberately permit any exception to bubble up to the caller
+
+ try
+ {
+ // extract the sessionID from the successful response
+ _dsmlSessionID = ExtractSessionID(dsmlResponse);
+ }
+ finally
+ {
+ dsmlResponse.Close();
+ }
+ }
+ finally
+ {
+ // create a fresh HttpWebRequest for the next operation
+ // (HttpWebRequest objects can only be used once)
+ _dsmlHttpConnection = (HttpWebRequest)WebRequest.Create(((DsmlDirectoryIdentifier)directoryIdentifier).ServerUri);
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ WebPermission(SecurityAction.Assert, Unrestricted = true),
+ NetworkInformationPermission(SecurityAction.Assert, Unrestricted = true)
+ ]
+ public override void EndSession()
+ {
+ // make sure we have a session
+ if (_dsmlSessionID == null)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.NoCurrentSession));
+ }
+
+ //
+ // Request
+ //
+
+ try
+ {
+ try
+ {
+ // Do the generic preparation of the request
+ PrepareHttpWebRequest(_dsmlHttpConnection);
+
+ // Get the stream we're going to write to
+ StreamWriter reqWriter = GetWebRequestStreamWriter();
+
+ try
+ {
+ // write out the EndSession request
+ reqWriter.Write(DsmlConstants.SOAPEnvelopeBegin);
+
+ reqWriter.Write(DsmlConstants.SOAPHeaderBegin);
+ reqWriter.Write(DsmlConstants.SOAPEndSession1); // EndSession
+ reqWriter.Write(_dsmlSessionID);
+ reqWriter.Write(DsmlConstants.SOAPEndSession2);
+ if (soapHeaders != null)
+ reqWriter.Write(soapHeaders.OuterXml);
+ reqWriter.Write(DsmlConstants.SOAPHeaderEnd);
+
+ reqWriter.Write(DsmlConstants.SOAPBodyBegin);
+ reqWriter.Write(new DsmlRequestDocument().ToXml().InnerXml); // empty batchRequest
+ reqWriter.Write(DsmlConstants.SOAPBodyEnd);
+
+ reqWriter.Write(DsmlConstants.SOAPEnvelopeEnd);
+
+ // Close out the stream
+ reqWriter.Flush();
+ }
+ finally
+ {
+ reqWriter.BaseStream.Close();
+ reqWriter.Close();
+ }
+
+ //
+ // Response
+ //
+
+ // Actually send the request and get the response
+ HttpWebResponse dsmlResponse = (HttpWebResponse)_dsmlHttpConnection.GetResponse();
+ // N.B.: we deliberately permit any exception to bubble up to the caller
+
+ dsmlResponse.Close();
+ }
+ catch (WebException e)
+ {
+ // Null out dsmlSessionID if applicable and rethrow exception
+
+ // Based on the nature of the exception, we have to decide whether
+ // or not we're still in a session. For example, if we failed because
+ // we couldn't connect to the server, the session must still be active.
+ // If the server failed the request (e.g., because it timed out the
+ // session and no longer recognizes our sessionID as value), the session
+ // is not active.
+ if ((e.Status != WebExceptionStatus.ConnectFailure) &&
+ (e.Status != WebExceptionStatus.NameResolutionFailure) &&
+ (e.Status != WebExceptionStatus.ProxyNameResolutionFailure) &&
+ (e.Status != WebExceptionStatus.SendFailure) &&
+ (e.Status != WebExceptionStatus.TrustFailure))
+ {
+ // It wasn't one of the exceptions where we failed to send the
+ // request to the server, so we have to assume the session may
+ // now be closed
+ _dsmlSessionID = null;
+ }
+
+ throw;
+ }
+
+ // Note, we don't actually process the contents of the response here.
+ // If there was an error, the server would have returned a SOAP Fault, and we'd
+ // have thrown an exception when we called GetResponse
+ _dsmlSessionID = null;
+ }
+ finally
+ {
+ // create a fresh HttpWebRequest for the next operation
+ // (HttpWebRequest objects can only be used once)
+ _dsmlHttpConnection = (HttpWebRequest)WebRequest.Create(((DsmlDirectoryIdentifier)directoryIdentifier).ServerUri);
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public override DirectoryResponse SendRequest(DirectoryRequest request)
+ {
+ if (request == null)
+ throw new ArgumentNullException("request");
+
+ DsmlRequestDocument doc = new DsmlRequestDocument();
+ doc.Add(request);
+
+ DsmlResponseDocument response = SendRequestHelper(doc.ToXml().InnerXml);
+
+ if (response.Count == 0)
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.MissingResponse));
+
+ DirectoryResponse result = response[0];
+
+ if (result is DsmlErrorResponse)
+ {
+ // need to throw ErrorResponseException
+ ErrorResponseException e = new ErrorResponseException((DsmlErrorResponse)result);
+ throw e;
+ }
+ else
+ {
+ ResultCode error = result.ResultCode;
+ if (error == ResultCode.Success || error == ResultCode.CompareFalse || error == ResultCode.CompareTrue || error == ResultCode.Referral || error == ResultCode.ReferralV2)
+ return result;
+ else
+ {
+ throw new DirectoryOperationException(result, OperationErrorMappings.MapResultCode((int)error));
+ }
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public DsmlResponseDocument SendRequest(DsmlRequestDocument request)
+ {
+ if (request == null)
+ throw new ArgumentNullException("request");
+
+ DsmlResponseDocument responseDoc = SendRequestHelper(request.ToXml().InnerXml);
+ if (request.Count > 0 && responseDoc.Count == 0)
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.MissingResponse));
+
+ return responseDoc;
+ }
+
+ [
+ WebPermission(SecurityAction.Assert, Unrestricted = true),
+ NetworkInformationPermission(SecurityAction.Assert, Unrestricted = true)
+ ]
+ private DsmlResponseDocument SendRequestHelper(string reqstring)
+ {
+ //
+ // Request
+ //
+ StringBuilder requestBuffer = new StringBuilder(1024);
+
+ try
+ {
+ // Do the generic preparation of the request
+ PrepareHttpWebRequest(_dsmlHttpConnection);
+
+ // Get the stream we're going to write to
+ StreamWriter reqWriter = GetWebRequestStreamWriter();
+
+ try
+ {
+ // Begin the SOAP Envelope, attaching the sessionID if applicable
+ BeginSOAPRequest(ref requestBuffer);
+
+ // Write out the actual DSML v2 request
+ requestBuffer.Append(reqstring);
+
+ // Finish writing the SOAP Envelope
+ EndSOAPRequest(ref requestBuffer);
+
+ reqWriter.Write(requestBuffer.ToString());
+
+ // Close out the stream
+ reqWriter.Flush();
+ }
+ finally
+ {
+ reqWriter.BaseStream.Close();
+ reqWriter.Close();
+ }
+
+ //
+ // Response
+ //
+
+ // Actually send the request to the server, and retrieve the response
+ // N.B.: we deliberately permit any exception to bubble up to the caller
+ HttpWebResponse dsmlResponse = (HttpWebResponse)_dsmlHttpConnection.GetResponse();
+ DsmlResponseDocument dsmlResponseDoc;
+
+ try
+ {
+ // Process the response
+ dsmlResponseDoc = new DsmlResponseDocument(
+ dsmlResponse,
+ "se:Envelope/se:Body/dsml:batchResponse"
+ );
+ _debugResponse = dsmlResponseDoc.ResponseString;
+ }
+ finally
+ {
+ dsmlResponse.Close();
+ }
+
+ return dsmlResponseDoc;
+ }
+ finally
+ {
+ // create a fresh HttpWebRequest for the next operation
+ // (HttpWebRequest objects can only be used once)
+ _dsmlHttpConnection = (HttpWebRequest)WebRequest.Create(((DsmlDirectoryIdentifier)directoryIdentifier).ServerUri);
+ }
+ }
+
+ [EnvironmentPermission(SecurityAction.Assert, Unrestricted = true)]
+ private void PrepareHttpWebRequest(HttpWebRequest dsmlConnection)
+ {
+ // set the credentials appropriately
+ if (directoryCredential == null)
+ {
+ // default credentials
+ dsmlConnection.Credentials = CredentialCache.DefaultCredentials;
+ }
+ else
+ {
+ // use the caller's explicit credentials and authType
+ string authenticationType = "negotiate";
+ if (_dsmlAuthType == AuthType.Ntlm)
+ authenticationType = "NTLM";
+ else if (_dsmlAuthType == AuthType.Basic)
+ authenticationType = "basic";
+ else if (_dsmlAuthType == AuthType.Anonymous)
+ authenticationType = "anonymous";
+ else if (_dsmlAuthType == AuthType.Digest)
+ authenticationType = "digest";
+
+ CredentialCache ccache = new CredentialCache();
+ ccache.Add(dsmlConnection.RequestUri, authenticationType, directoryCredential);
+ dsmlConnection.Credentials = ccache;
+ }
+
+ // set the client certificates
+ foreach (X509Certificate cert in ClientCertificates)
+ {
+ dsmlConnection.ClientCertificates.Add(cert);
+ }
+
+ // set the timeout
+ if (connectionTimeOut.Ticks != 0)
+ {
+ dsmlConnection.Timeout = (int)(connectionTimeOut.Ticks / TimeSpan.TicksPerMillisecond);
+ }
+
+ // set the SOAPAction header
+ if (_dsmlSoapAction != null)
+ {
+ WebHeaderCollection headers = dsmlConnection.Headers;
+ headers.Set("SOAPAction", _dsmlSoapAction);
+ }
+
+ // set the other headers
+ dsmlConnection.Method = DsmlConstants.HttpPostMethod;
+ }
+
+ private StreamWriter GetWebRequestStreamWriter()
+ {
+ Stream reqStream = _dsmlHttpConnection.GetRequestStream();
+ // N.B.: we deliberately permit any exception to bubble up to the caller
+ StreamWriter reqWriter = new StreamWriter(reqStream);
+
+ return reqWriter;
+ }
+
+ /// <summary>
+ /// This method writes the SOAP Envelope and Body to the stream.
+ /// If also attaches the SOAP Header for the sessionID, if
+ /// applicable.
+ /// </summary>
+ private void BeginSOAPRequest(ref StringBuilder buffer)
+ {
+ buffer.Append(DsmlConstants.SOAPEnvelopeBegin);
+
+ if (_dsmlSessionID != null || soapHeaders != null)
+ {
+ buffer.Append(DsmlConstants.SOAPHeaderBegin);
+ if (_dsmlSessionID != null)
+ {
+ buffer.Append(DsmlConstants.SOAPSession1);
+ buffer.Append(_dsmlSessionID);
+ buffer.Append(DsmlConstants.SOAPSession2);
+ }
+ if (soapHeaders != null)
+ {
+ buffer.Append(soapHeaders.OuterXml);
+ }
+ buffer.Append(DsmlConstants.SOAPHeaderEnd);
+ }
+
+ buffer.Append(DsmlConstants.SOAPBodyBegin);
+ }
+
+ /// <summary>
+ /// This method writes the closing elements of the SOAP Envelope
+ /// and Body to the stream.
+ /// </summary>
+ private void EndSOAPRequest(ref StringBuilder buffer)
+ {
+ buffer.Append(DsmlConstants.SOAPBodyEnd);
+ buffer.Append(DsmlConstants.SOAPEnvelopeEnd);
+ }
+
+ /// <summary>
+ /// This method extracts the sessionID value from the Session header
+ /// of a response
+ /// </summary>
+ private string ExtractSessionID(HttpWebResponse resp)
+ {
+ // Transform the response into an XmlDocument
+ Stream respStream = resp.GetResponseStream();
+ StreamReader respReader = new StreamReader(respStream);
+
+ try
+ {
+ XmlDocument respXml = new XmlDocument();
+
+ try
+ {
+ respXml.Load(respReader);
+ }
+ catch (XmlException)
+ {
+ // The server didn't return well-formed XML to us
+ throw new DsmlInvalidDocumentException();
+ }
+
+ // Locate the SessionID attribute node
+ XmlNamespaceManager ns = NamespaceUtils.GetDsmlNamespaceManager();
+ XmlAttribute node = (XmlAttribute)respXml.SelectSingleNode("se:Envelope/se:Header/ad:Session/@ad:SessionID", ns);
+
+ if (node == null)
+ {
+ // try it without the namespace qualifier on the attribute, since default namespaces don't
+ // apply to attributes
+ node = (XmlAttribute)respXml.SelectSingleNode("se:Envelope/se:Header/ad:Session/@SessionID", ns);
+
+ if (node == null)
+ {
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.NoSessionIDReturned));
+ }
+ }
+
+ return node.Value;
+ }
+ finally
+ {
+ respReader.Close();
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ WebPermission(SecurityAction.Assert, Unrestricted = true),
+ NetworkInformationPermission(SecurityAction.Assert, Unrestricted = true)
+ ]
+ public IAsyncResult BeginSendRequest(DsmlRequestDocument request, AsyncCallback callback, object state)
+ {
+ if (request == null)
+ throw new ArgumentNullException("request");
+
+ // construct the new httpwebrequest object
+ HttpWebRequest asyncConnection = (HttpWebRequest)WebRequest.Create(((DsmlDirectoryIdentifier)directoryIdentifier).ServerUri);
+ // Do the generic preparation of the request
+ PrepareHttpWebRequest(asyncConnection);
+
+ // construct the request string
+ StringBuilder requestStringBuffer = new StringBuilder(1024);
+ // Begin the SOAP Envelope, attaching the sessionID if applicable
+ BeginSOAPRequest(ref requestStringBuffer);
+ // append the document
+ requestStringBuffer.Append(request.ToXml().InnerXml);
+ // Finish writing the SOAP Envelope
+ EndSOAPRequest(ref requestStringBuffer);
+
+ // construct the state object
+ RequestState rs = new RequestState();
+ rs.request = asyncConnection;
+ rs.requestString = requestStringBuffer.ToString();
+
+ // construct the async object
+ DsmlAsyncResult asyncResult = new DsmlAsyncResult(callback, state);
+ asyncResult.resultObject = rs;
+ // give hint about whether this is an empty request or not so later we could validate the response
+ if (request.Count > 0)
+ asyncResult.hasValidRequest = true;
+
+ // result object needs to have a handle on the waitobject, so later it could wake up the EndSendRequest call
+ rs.dsmlAsync = asyncResult;
+
+ // add connection-async pair to our table
+ _httpConnectionTable.Add(asyncResult, asyncConnection);
+
+ // begin the requeststream call
+ asyncConnection.BeginGetRequestStream(new AsyncCallback(RequestStreamCallback), rs);
+
+ // return the asyncResult
+ return (IAsyncResult)asyncResult;
+ }
+
+ private static void RequestStreamCallback(IAsyncResult asyncResult)
+ {
+ // get our state object back
+ RequestState rs = (RequestState)asyncResult.AsyncState;
+ HttpWebRequest request = rs.request;
+
+ try
+ {
+ rs.requestStream = request.EndGetRequestStream(asyncResult);
+
+ // get the request string
+ byte[] info = rs.encoder.GetBytes(rs.requestString);
+
+ // begin asynchronous write
+ rs.requestStream.BeginWrite(info, 0, info.Length, new AsyncCallback(WriteCallback), rs);
+ }
+ catch (Exception e)
+ {
+ // exception occurs, we need to catch it here, close the request stream and properly set the exception and call wakeup routine
+ if (rs.requestStream != null)
+ rs.requestStream.Close();
+ rs.exception = e;
+ WakeupRoutine(rs);
+ }
+ }
+
+ private static void WriteCallback(IAsyncResult asyncResult)
+ {
+ // get our state object back
+ RequestState rs = (RequestState)asyncResult.AsyncState;
+ try
+ {
+ rs.requestStream.EndWrite(asyncResult);
+
+ // begin to get response
+ rs.request.BeginGetResponse(new AsyncCallback(ResponseCallback), rs);
+ }
+ catch (Exception e)
+ {
+ // exception occurs, we need to catch it here and properly set the exception and call wakeup routine
+ rs.exception = e;
+ WakeupRoutine(rs);
+ }
+ finally
+ {
+ rs.requestStream.Close();
+ }
+ }
+
+ private static void ResponseCallback(IAsyncResult asyncResult)
+ {
+ // get our state object back
+ RequestState rs = (RequestState)asyncResult.AsyncState;
+ WebResponse resp = null;
+
+ try
+ {
+ resp = rs.request.EndGetResponse(asyncResult);
+
+ rs.responseStream = resp.GetResponseStream();
+
+ // begin to read
+ rs.responseStream.BeginRead(rs.bufferRead, 0, RequestState.bufferSize, new AsyncCallback(ReadCallback), rs);
+ }
+ catch (Exception e)
+ {
+ // exception occurs, we need to catch it here, close the response stream and properly set the exception and call wakeup routine
+ if (rs.responseStream != null)
+ rs.responseStream.Close();
+ rs.exception = e;
+ WakeupRoutine(rs);
+ }
+ }
+
+ private static void ReadCallback(IAsyncResult asyncResult)
+ {
+ // get our state object back
+ RequestState rs = (RequestState)asyncResult.AsyncState;
+ int count = 0;
+ string s = null;
+
+ try
+ {
+ count = rs.responseStream.EndRead(asyncResult);
+ if (count > 0)
+ {
+ // still more to read
+ s = rs.encoder.GetString(rs.bufferRead);
+ int val = Math.Min(s.Length, count);
+ rs.responseString.Append(s, 0, val);
+
+ rs.responseStream.BeginRead(rs.bufferRead, 0, RequestState.bufferSize, new AsyncCallback(ReadCallback), rs);
+ }
+ else
+ {
+ // have retrieved all the response, close the stream
+ rs.responseStream.Close();
+
+ WakeupRoutine(rs);
+ }
+ }
+ catch (Exception e)
+ {
+ // exception occurs, need to close the stream
+ rs.responseStream.Close();
+
+ // exception occurs, we need to catch it here and properly set the exception and call wakeup routine
+ rs.exception = e;
+ WakeupRoutine(rs);
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public void Abort(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+
+ if (!(asyncResult is DsmlAsyncResult))
+ throw new ArgumentException(Res.GetString(Res.NotReturnedAsyncResult, "asyncResult"));
+
+ if (!_httpConnectionTable.Contains(asyncResult))
+ throw new ArgumentException(Res.GetString(Res.InvalidAsyncResult));
+
+ HttpWebRequest request = (HttpWebRequest)(_httpConnectionTable[asyncResult]);
+
+ // remove the asyncResult from our connection table
+ _httpConnectionTable.Remove(asyncResult);
+
+ // cancel the request
+ request.Abort();
+
+ DsmlAsyncResult result = (DsmlAsyncResult)asyncResult;
+ result.resultObject.abortCalled = true;
+ }
+
+ public DsmlResponseDocument EndSendRequest(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+
+ if (!(asyncResult is DsmlAsyncResult))
+ throw new ArgumentException(Res.GetString(Res.NotReturnedAsyncResult, "asyncResult"));
+
+ if (!_httpConnectionTable.Contains(asyncResult))
+ throw new ArgumentException(Res.GetString(Res.InvalidAsyncResult));
+
+ // remove the asyncResult from our connection table
+ _httpConnectionTable.Remove(asyncResult);
+
+ DsmlAsyncResult result = (DsmlAsyncResult)asyncResult;
+ asyncResult.AsyncWaitHandle.WaitOne();
+
+ // Process the response
+
+ // see if any exception occurs, if yes, then throw the exception
+ if (result.resultObject.exception != null)
+ throw result.resultObject.exception;
+
+ DsmlResponseDocument dsmlResponseDoc = new DsmlResponseDocument(
+ result.resultObject.responseString,
+ "se:Envelope/se:Body/dsml:batchResponse"
+ );
+ _debugResponse = dsmlResponseDoc.ResponseString;
+
+ // validate the response
+ if (result.hasValidRequest && dsmlResponseDoc.Count == 0)
+ throw new DsmlInvalidDocumentException(Res.GetString(Res.MissingResponse));
+
+ return dsmlResponseDoc;
+ }
+
+ private static void WakeupRoutine(RequestState rs)
+ {
+ // signal waitable object, indicate operation completed and fire callback
+ rs.dsmlAsync.manualResetEvent.Set();
+ rs.dsmlAsync.completed = true;
+ if (rs.dsmlAsync.callback != null && !rs.abortCalled)
+ {
+ rs.dsmlAsync.callback((IAsyncResult)rs.dsmlAsync);
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/adreqresp2.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/adreqresp2.cs
new file mode 100644
index 0000000000..09f11ceb62
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/adreqresp2.cs
@@ -0,0 +1,112 @@
+// 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
+{
+ using System;
+ using System.Collections;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+
+ //ADSearch Operation related classes
+ internal class ADFilter
+ {
+ public ADFilter()
+ {
+ Filter = new FilterContent();
+ }
+
+ public FilterType Type;
+ public FilterContent Filter;
+
+ public enum FilterType
+ {
+ And, Or, Not,
+ EqualityMatch, Substrings, GreaterOrEqual,
+ LessOrEqual, Present, ApproxMatch, ExtensibleMatch
+ }
+
+ public struct FilterContent
+ {
+ public ArrayList And; //type ADFilter
+
+ public ArrayList Or; //type ADFilter
+
+ public ADFilter Not;
+
+ public ADAttribute EqualityMatch;
+
+ public ADSubstringFilter Substrings;
+
+ public ADAttribute GreaterOrEqual;
+
+ public ADAttribute LessOrEqual;
+
+ public string Present;
+
+ public ADAttribute ApproxMatch;
+
+ public ADExtenMatchFilter ExtensibleMatch;
+ }
+ }
+
+ internal class ADExtenMatchFilter
+ {
+ public ADExtenMatchFilter()
+ {
+ Value = null;
+ DNAttributes = false;
+ }
+
+ public string Name;
+ public ADValue Value;
+ public bool DNAttributes;
+ public string MatchingRule;
+ }
+
+ internal class ADSubstringFilter
+ {
+ public ADSubstringFilter()
+ {
+ Initial = null;
+ Final = null;
+ Any = new ArrayList();
+ }
+
+ public string Name;
+ public ADValue Initial;
+ public ADValue Final;
+ public ArrayList Any;
+ }
+ //end ADSearchOperation classes
+
+ internal class ADAttribute
+ {
+ public ADAttribute()
+ {
+ Values = new ArrayList();
+ }
+
+ public override int GetHashCode()
+ {
+ return Name.GetHashCode();
+ }
+
+ public string Name;
+ public ArrayList Values; //type ADValue
+ }
+
+ internal class ADValue
+ {
+ public ADValue()
+ {
+ IsBinary = false;
+ BinaryVal = null;
+ }
+
+ public bool IsBinary;
+ public string StringVal;
+ public byte[] BinaryVal; //to store base64 encoded data
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/dsmlfilterwriter.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/dsmlfilterwriter.cs
new file mode 100644
index 0000000000..f792135950
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/dsmlfilterwriter.cs
@@ -0,0 +1,237 @@
+// 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
+{
+ using System;
+ using System.Collections;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+ using System.Xml;
+ using System.Diagnostics;
+
+ internal class DSMLFilterWriter
+ {
+ protected void WriteValue(string valueElt, ADValue value, XmlWriter mXmlWriter, string strNamespace)
+ {
+ if (strNamespace != null)
+ {
+ mXmlWriter.WriteStartElement(valueElt, strNamespace);
+ }
+ else
+ {
+ mXmlWriter.WriteStartElement(valueElt);
+ }
+
+ if (value.IsBinary && value.BinaryVal != null)
+ {
+ mXmlWriter.WriteAttributeString("xsi", "type", DsmlConstants.XsiUri,
+ DsmlConstants.AttrBinaryTypePrefixedValue);
+ mXmlWriter.WriteBase64(value.BinaryVal, 0, value.BinaryVal.Length);
+ }
+ else
+ {
+ //note that the WriteString method handles a null argument correctly
+ mXmlWriter.WriteString(value.StringVal);
+ }
+
+ mXmlWriter.WriteEndElement();
+ }
+
+ protected void WriteAttrib(string attrName, ADAttribute attrib, XmlWriter mXmlWriter, string strNamespace)
+ {
+ if (strNamespace != null)
+ {
+ mXmlWriter.WriteStartElement(attrName, strNamespace);
+ }
+ else
+ {
+ mXmlWriter.WriteStartElement(attrName);
+ }
+
+ mXmlWriter.WriteAttributeString(DsmlConstants.AttrDsmlAttrName, attrib.Name);
+
+ foreach (ADValue val in attrib.Values)
+ {
+ WriteValue(DsmlConstants.ElementDsmlAttrValue, val, mXmlWriter, strNamespace);
+ }
+
+ mXmlWriter.WriteEndElement();
+ }
+
+ public void WriteFilter(ADFilter filter, bool filterTags, XmlWriter mXmlWriter, string strNamespace)
+ {
+ if (filterTags)
+ {
+ if (strNamespace != null)
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilter, strNamespace);
+ }
+ else
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilter);
+ }
+ }
+
+ switch (filter.Type)
+ {
+ case ADFilter.FilterType.And:
+ if (strNamespace != null)
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterAnd, strNamespace);
+ }
+ else
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterAnd);
+ }
+
+ foreach (object andClause in filter.Filter.And)
+ {
+ WriteFilter((ADFilter)andClause, false, mXmlWriter, strNamespace);
+ }
+ mXmlWriter.WriteEndElement();
+ break;
+ case ADFilter.FilterType.Or:
+ if (strNamespace != null)
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterOr, strNamespace);
+ }
+ else
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterOr);
+ }
+
+ foreach (object orClause in filter.Filter.Or)
+ {
+ WriteFilter((ADFilter)orClause, false, mXmlWriter, strNamespace);
+ }
+ mXmlWriter.WriteEndElement();
+ break;
+ case ADFilter.FilterType.Not:
+ if (strNamespace != null)
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterNot, strNamespace);
+ }
+ else
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterNot);
+ }
+
+ WriteFilter(filter.Filter.Not, false, mXmlWriter, strNamespace);
+ mXmlWriter.WriteEndElement();
+ break;
+ case ADFilter.FilterType.EqualityMatch:
+ WriteAttrib(DsmlConstants.ElementSearchReqFilterEqual,
+ filter.Filter.EqualityMatch, mXmlWriter, strNamespace);
+ break;
+ case ADFilter.FilterType.Present:
+ if (strNamespace != null)
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterPresent, strNamespace);
+ }
+ else
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterPresent);
+ }
+ mXmlWriter.WriteAttributeString(DsmlConstants.AttrSearchReqFilterPresentName,
+ filter.Filter.Present);
+ mXmlWriter.WriteEndElement();
+ break;
+ case ADFilter.FilterType.GreaterOrEqual:
+ WriteAttrib(DsmlConstants.ElementSearchReqFilterGrteq,
+ filter.Filter.GreaterOrEqual, mXmlWriter, strNamespace);
+ break;
+ case ADFilter.FilterType.LessOrEqual:
+ WriteAttrib(DsmlConstants.ElementSearchReqFilterLesseq,
+ filter.Filter.LessOrEqual, mXmlWriter, strNamespace);
+ break;
+ case ADFilter.FilterType.ApproxMatch:
+ WriteAttrib(DsmlConstants.ElementSearchReqFilterApprox,
+ filter.Filter.ApproxMatch, mXmlWriter, strNamespace);
+ break;
+ case ADFilter.FilterType.ExtensibleMatch:
+ ADExtenMatchFilter exten = filter.Filter.ExtensibleMatch;
+
+ if (strNamespace != null)
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterExtenmatch, strNamespace);
+ }
+ else
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterExtenmatch);
+ }
+
+ if ((exten.Name != null) && (exten.Name.Length != 0))
+ {
+ mXmlWriter.WriteAttributeString(
+ DsmlConstants.AttrSearchReqFilterExtenmatchName, exten.Name);
+ }
+
+ if ((exten.MatchingRule != null) && (exten.MatchingRule.Length != 0))
+ {
+ mXmlWriter.WriteAttributeString(
+ DsmlConstants.AttrSearchReqFilterExtenmatchMatchrule, exten.MatchingRule);
+ }
+
+ mXmlWriter.WriteAttributeString(
+ DsmlConstants.AttrSearchReqFilterExtenmatchDnattr,
+ XmlConvert.ToString(exten.DNAttributes));
+
+ WriteValue(DsmlConstants.ElementSearchReqFilterExtenmatchValue, exten.Value, mXmlWriter, strNamespace);
+ mXmlWriter.WriteEndElement();
+ break;
+ case ADFilter.FilterType.Substrings:
+ //handle <substrings>
+ ADSubstringFilter substr = filter.Filter.Substrings;
+
+ if (strNamespace != null)
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterSubstr, strNamespace);
+ }
+ else
+ {
+ mXmlWriter.WriteStartElement(DsmlConstants.ElementSearchReqFilterSubstr);
+ }
+
+ mXmlWriter.WriteAttributeString(DsmlConstants.AttrSearchReqFilterSubstrName,
+ substr.Name);
+
+ if (substr.Initial != null)
+ {
+ WriteValue(DsmlConstants.ElementSearchReqFilterSubstrInit,
+ substr.Initial, mXmlWriter, strNamespace);
+ }
+
+ if (substr.Any != null)
+ {
+ foreach (object sub in substr.Any)
+ {
+ WriteValue(DsmlConstants.ElementSearchReqFilterSubstrAny,
+ (ADValue)sub, mXmlWriter, strNamespace);
+ }
+ }
+
+ if (substr.Final != null)
+ {
+ WriteValue(DsmlConstants.ElementSearchReqFilterSubstrFinal,
+ substr.Final, mXmlWriter, strNamespace);
+ }
+
+ mXmlWriter.WriteEndElement();
+ break;
+
+ default:
+ Debug.Fail("Invalid substring filter");
+
+ //just in case ... this will be caught by the caller
+ throw new ArgumentException(Res.GetString(Res.InvalidFilterType, filter.Type));
+ }
+
+ if (filterTags)
+ {
+ mXmlWriter.WriteEndElement(); //</filter>
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/filterparser.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/filterparser.cs
new file mode 100644
index 0000000000..2fe716dce4
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/filterparser.cs
@@ -0,0 +1,431 @@
+// 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
+{
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Text.RegularExpressions;
+ using System.Globalization;
+ using System.Text;
+
+ /// <summary>
+ /// Utility class to perform conversion of an string representation of
+ /// na LDAP filter to ADFilter.
+ /// </summary>
+ internal class FilterParser
+ {
+ public static ADFilter ParseFilterString(string filter)
+ {
+ Debug.Assert(filter != null);
+
+ //perfomr the matthing. On success all info we are interested in
+ //will be stored in the named captures.
+ try
+ {
+ Match m = s_mFilter.Match(filter);
+ if (!m.Success)
+ {
+ return null;
+ }
+
+ ADFilter result = new ADFilter();
+ if (m.Groups["item"].ToString().Length != 0)
+ {
+ //we have am "item"filter which can be
+ //of type "present", "simple", "substring", or "extensible"
+
+ if (m.Groups["present"].ToString().Length != 0)
+ {
+ //present filter, e.g. (objectClass=*)
+ result.Type = ADFilter.FilterType.Present;
+
+ Debug.Assert(m.Groups["presentattr"].ToString().Length != 0);
+ result.Filter.Present = m.Groups["presentattr"].ToString();
+ }
+ else if (m.Groups["simple"].ToString().Length != 0)
+ {
+ //simple filter, e.g. (simpleattr =|~=|>=|<= simplevalue)
+ ADAttribute simple = new ADAttribute();
+
+ if (m.Groups["simplevalue"].ToString().Length != 0)
+ {
+ ADValue val = StringFilterValueToADValue(m.Groups["simplevalue"].ToString());
+ simple.Values.Add(val);
+ }
+
+ simple.Name = m.Groups["simpleattr"].ToString();
+
+ //the variours types of relationships we might have
+ switch (m.Groups["filtertype"].ToString())
+ {
+ case "=":
+ result.Type = ADFilter.FilterType.EqualityMatch;
+ result.Filter.EqualityMatch = simple;
+ break;
+ case "~=":
+ result.Type = ADFilter.FilterType.ApproxMatch;
+ result.Filter.ApproxMatch = simple;
+ break;
+ case "<=":
+ result.Type = ADFilter.FilterType.LessOrEqual;
+ result.Filter.LessOrEqual = simple;
+ break;
+ case ">=":
+ result.Type = ADFilter.FilterType.GreaterOrEqual;
+ result.Filter.GreaterOrEqual = simple;
+ break;
+ default:
+ //this should not occur
+ Debug.Fail("FilterParser.ParseFilterString: Invalid simple filter");
+
+ //treat like a parse error
+ return null;
+ }
+ }
+ else if (m.Groups["substr"].ToString().Length != 0)
+ {
+ //we have a substring filter. Get the various parts of it
+ result.Type = ADFilter.FilterType.Substrings;
+
+ ADSubstringFilter substr = new ADSubstringFilter();
+
+ substr.Initial = StringFilterValueToADValue(m.Groups["initialvalue"].ToString());
+ substr.Final = StringFilterValueToADValue(m.Groups["finalvalue"].ToString());
+
+ if (m.Groups["anyvalue"].ToString().Length != 0)
+ {
+ foreach (Capture c in m.Groups["anyvalue"].Captures)
+ {
+ substr.Any.Add(StringFilterValueToADValue(c.ToString()));
+ }
+ }
+
+ substr.Name = m.Groups["substrattr"].ToString();
+ result.Filter.Substrings = substr;
+ }
+ else if (m.Groups["extensible"].ToString().Length != 0)
+ {
+ //extensible filter
+ result.Type = ADFilter.FilterType.ExtensibleMatch;
+
+ ADExtenMatchFilter exten = new ADExtenMatchFilter();
+
+ exten.Value = StringFilterValueToADValue(m.Groups["extenvalue"].ToString());
+ exten.DNAttributes = (m.Groups["dnattr"].ToString().Length != 0);
+ exten.Name = m.Groups["extenattr"].ToString();
+ exten.MatchingRule = m.Groups["matchrule"].ToString();
+
+ result.Filter.ExtensibleMatch = exten;
+ }
+ else
+ {
+ //this should not occur
+ Debug.Fail("Invalid item filter");
+
+ //treat like a parse error
+ return null;
+ }
+ }
+ else
+ {
+ //compound recursive filter
+
+ //extract the filter lists
+ ArrayList filters = new ArrayList();
+ string filterList = m.Groups["filterlist"].ToString().Trim();
+
+ while (filterList.Length > 0)
+ {
+ if (filterList[0] != '(')
+ {
+ //this is a parse error: invalid filter
+ return null;
+ }
+
+ int strIdx = 1;
+ int left = 1; //count opening brackest
+ bool gotSubfilter = false;
+
+ while (strIdx < filterList.Length && !gotSubfilter)
+ {
+ if (filterList[strIdx] == '(')
+ {
+ left++;
+ }
+
+ if (filterList[strIdx] == ')')
+ {
+ if (left < 1)
+ {
+ //unbalanced parenthesis
+ return null;
+ }
+ else if (left == 1)
+ {
+ //the end of the subfilter
+ gotSubfilter = true;
+ }
+ else
+ {
+ left--;
+ }
+ }
+
+ strIdx++;
+ }
+
+ if (!gotSubfilter)
+ {
+ //the filter list did not consist entirely of subfilters
+ return null;
+ }
+
+ filters.Add(filterList.Substring(0, strIdx));
+ filterList = filterList.Substring(strIdx).TrimStart();
+ }
+
+ ADFilter eltFilter = null;
+ switch (m.Groups["filtercomp"].ToString())
+ {
+ case "|":
+ result.Type = ADFilter.FilterType.Or;
+ result.Filter.Or = new ArrayList();
+ foreach (String f in filters)
+ {
+ eltFilter = ParseFilterString(f);
+ if (eltFilter == null)
+ {
+ return null;
+ }
+
+ result.Filter.Or.Add(eltFilter);
+ }
+
+ if (result.Filter.Or.Count < 1)
+ {
+ return null;
+ }
+
+ break;
+ case "&":
+ result.Type = ADFilter.FilterType.And;
+ result.Filter.And = new ArrayList();
+ foreach (String f in filters)
+ {
+ eltFilter = ParseFilterString(f);
+ if (eltFilter == null)
+ {
+ return null;
+ }
+
+ result.Filter.And.Add(eltFilter);
+ }
+
+ if (result.Filter.And.Count < 1)
+ {
+ return null;
+ }
+
+ break;
+ case "!":
+ result.Type = ADFilter.FilterType.Not;
+ eltFilter = ParseFilterString((string)filters[0]);
+ //Note that for ease of defining the filter grammar we allow
+ //more than one filter after '!'. We catch this here
+ if (filters.Count > 1 || eltFilter == null)
+ {
+ return null;
+ }
+
+ result.Filter.Not = eltFilter;
+ break;
+
+ default:
+ //this should not occur
+ Debug.Fail("Invalid filter composition");
+
+ //treat like a parse error
+ return null;
+ }
+ }
+
+ return result;
+ }//end of try
+ catch (RegexMatchTimeoutException)
+ {
+ Debug.WriteLine("The input filter String: {0} exceeded the regex match timeout of {1} seconds.", filter, mFilterTimeOutInSeconds);
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Converts the string representation of a filter value to the appropriate ADvalue
+ /// </summary>
+ /// <remarks>
+ /// If at least 1 binary escaping (e.g. \20) exists in the string representation
+ /// then the value is converted to binary. Any string portions are converted
+ /// to binary UTF8 encoding.
+ /// </remarks>
+ /// <param name="strVal"> String representation of the filter. </param>
+ /// <returns>Returns a properly initialized ADValue </returns>
+ protected static ADValue StringFilterValueToADValue(string strVal)
+ {
+ if (strVal == null || strVal.Length == 0)
+ {
+ return null;
+ }
+
+ ADValue val = new ADValue();
+
+ //The idea is that if we have at least 1 escaped binary value
+ // like \20 we will convert the entire value to binary
+ // something like \30va\2c\lue will be converted as follows:
+ // 30,UTF8 binary representation of "va", 2c, UTF8 bin representation of "lue"
+ String[] parts = strVal.Split(new char[] { '\\' });
+
+ if (parts.Length == 1)
+ {
+ //we have no binary data in the value
+ val.IsBinary = false;
+ val.StringVal = strVal;
+ val.BinaryVal = null;
+ }
+ else
+ {
+ ArrayList binChunks = new ArrayList(parts.Length);
+ UTF8Encoding utf8 = new UTF8Encoding();
+
+ //there is at least 1 binary value
+ //for something like "\30va\2c\lue" we will have
+ //parts = {"", "30va", "2c", "lue"}
+ val.IsBinary = true;
+ val.StringVal = null;
+
+ if (parts[0].Length != 0)
+ {
+ //parts[0] is either empty of doesn't have 2 char hex prefix
+ binChunks.Add(utf8.GetBytes(parts[0]));
+ }
+
+ for (int i = 1; i < parts.Length; i++)
+ {
+ //we must have a 2 character hex prefix
+ Debug.Assert(parts[i].Length >= 2,
+ "FilterParser.ProcessStringFilterValue: Unexpected value. " +
+ "The the value matching regular expression must be incorrect");
+
+ string hexPrefix = parts[i].Substring(0, 2);
+
+ //handle the prefix
+ binChunks.Add(new Byte[] { Byte.Parse(hexPrefix, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture) });
+
+ if (parts[i].Length > 2)
+ {
+ //handle the string portion
+ binChunks.Add(utf8.GetBytes(parts[i].Substring(2)));
+ }
+ }
+
+ //now we have all the binary chunks. Put them together
+ //figure out the size we need
+ int lenghtNeeded = 0;
+ foreach (Byte[] chunk in binChunks)
+ {
+ lenghtNeeded += chunk.Length;
+ }
+
+ val.BinaryVal = new Byte[lenghtNeeded];
+
+ //do the actual copying
+ int currIdx = 0;
+ foreach (Byte[] chunk in binChunks)
+ {
+ chunk.CopyTo(val.BinaryVal, currIdx);
+ currIdx += chunk.Length;
+ }
+ }
+
+ return val;
+ }
+
+ //The filter timeout in seconds. Necessary to avoid ReDoS attacks on the regexes used in this filter.
+ //If no match was found within the timeout value, the pattern-matching method times out and RegexMatchTimeoutException is thrown.
+ //Timeout value of 3 seconds should be sufficient for most filter strings.
+ private const UInt32 mFilterTimeOutInSeconds = 3;
+
+ //the filter regEx that does most of the work for us
+ private static Regex s_mFilter = new Regex(mFilterRE, RegexOptions.ExplicitCapture, TimeSpan.FromSeconds(mFilterTimeOutInSeconds));
+
+ //The filter grammar
+ //This is nothing more but a regular expression representation of the LDAP filter
+ //grammar in RFC2254
+ //
+ //filter = "(" filtercomp ")"
+ //filtercomp = and / or / not / item
+ //and = "&" filterlist
+ //or = "|" filterlist
+ //not = "!" filter
+ //filterlist = 1*filter
+ //item = simple / present / substring / extensible
+ //simple = attr filtertype value
+ //filtertype = equal / approx / greater / less
+ //equal = "="
+ //approx = "~="
+ //greater = ">="
+ //less = "<="
+ //extensible = attr [":dn"] [":" matchingrule] ":=" value
+ // / [":dn"] ":" matchingrule ":=" value
+ //present = attr "=*"
+ //substring = attr "=" [initial] any [final]
+ //initial = value
+ //any = "*" *(value "*")
+ //final = value
+ //attr = AttributeDescription from Section 4.1.5 of RFC2251
+ //matchingrule = MatchingRuleId from Section 4.1.9 of RFC2251
+ //value = AttributeValue from Section 4.1.6 of RFC2251
+
+ //In order to allow whitespacing between elements and to avoid more \s* elements
+ //then necessary we always put '\s*' on the RIGHT of any element. The only exception is
+ //the the filter element which allows for white space on both sides.
+
+ private const string mAttrRE = @"(([0-2](\.[0-9]+)+)|([a-zA-Z]+([a-zA-Z0-9]|[-])*))(;([a-zA-Z0-9]|[-])+)*";
+ private const string mValueRE = @"(([^\*\(\)\\])|(\\[a-fA-F0-9][a-fA-F0-9]))+?";
+
+ //extensible filter grammar
+ private const string mExtenAttrRE = @"(?<extenattr>" + mAttrRE + @")\s*";
+ private const string mExtenValueRE = @"(?<extenvalue>" + mValueRE + @")\s*";
+ private const string mDNAttrRE = @"(?<dnattr>\:dn){0,1}\s*";
+
+ //matc rule grammar
+ private const string mMatchRuleOptionalRE = @"(\:(?<matchrule>([a-zA-Z][a-zA-Z0-9]*)|([0-9]+(\.[0-9]+)+))){0,1}\s*";
+ private const string mMatchRuleRE = @"(\:(?<matchrule>([a-zA-Z][a-zA-Z0-9]*)|([0-9]+(\.[0-9]+)+)))\s*";
+ private const string mExtenRE = @"(?<extensible>((" + mExtenAttrRE + mDNAttrRE + mMatchRuleOptionalRE + @")|" +
+ @"(" + mDNAttrRE + mMatchRuleRE + @"))\:\=\s*" + mExtenValueRE + @")\s*";
+
+ // substr filter grammar
+ private const string mSubstrAttrRE = @"(?<substrattr>" + mAttrRE + @")\s*";
+ private const string mInitialRE = @"\s*(?<initialvalue>" + mValueRE + @"){0,1}\s*";
+ private const string mFinalRE = @"\s*(?<finalvalue>" + mValueRE + @"){0,1}\s*";
+ private const string mAnyRE = @"(\*\s*((?<anyvalue>" + mValueRE + @")\*\s*)*)";
+ private const string mSubstrRE = @"(?<substr>" + mSubstrAttrRE + @"\=\s*" +
+ mInitialRE + mAnyRE + mFinalRE + @")\s*";
+
+ // simple filter grammar
+ private const string mSimpleValueRE = @"(?<simplevalue>" + mValueRE + @")\s*";
+ private const string mSimpleAttrRE = @"(?<simpleattr>" + mAttrRE + @")\s*";
+ private const string mFiltertypeRE = @"(?<filtertype>\=|\~\=|\>\=|\<\=)\s*";
+ private const string mSimpleRE = @"(?<simple>" + mSimpleAttrRE + mFiltertypeRE + mSimpleValueRE + @")\s*";
+
+ //present filter grammar
+ private const string mPresentRE = @"(?<present>(?<presentattr>" + mAttrRE + @")\=\*)\s*";
+
+ //highlevel filter grammar
+ private const string mItemRE = @"(?<item>" + mSimpleRE + "|" + mPresentRE + "|" + mSubstrRE + "|" + mExtenRE + @")\s*";
+ private const string mFiltercompRE = @"(?<filtercomp>\!|\&|\|)\s*";
+ private const string mFilterlistRE = @"(?<filterlist>.+)\s*"; //needs postprocessing
+ private const string mFilterRE = @"^\s*\(\s*((" + mFiltercompRE + mFilterlistRE + ")|(" + mItemRE + @"))\)\s*$";
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/utils.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/utils.cs
new file mode 100644
index 0000000000..ee5e4081d9
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/dsml/utils.cs
@@ -0,0 +1,136 @@
+// 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
+{
+ using System;
+ using System.Xml;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+
+ internal class NamespaceUtils
+ {
+ private NamespaceUtils() { }
+
+ private static XmlNamespaceManager s_xmlNamespace = new XmlNamespaceManager(new NameTable());
+
+ static NamespaceUtils()
+ {
+ s_xmlNamespace.AddNamespace("se", DsmlConstants.SoapUri);
+ s_xmlNamespace.AddNamespace("dsml", DsmlConstants.DsmlUri);
+ s_xmlNamespace.AddNamespace("ad", DsmlConstants.ADSessionUri);
+ s_xmlNamespace.AddNamespace("xsd", DsmlConstants.XsdUri);
+ s_xmlNamespace.AddNamespace("xsi", DsmlConstants.XsiUri);
+ }
+
+ /// <summary>
+ /// This is the common namespace manager we use everywhere we need a XmlNamespaceManager.
+ /// For example, every XPath selection should use this to provide its XmlNamespaceManager,
+ /// when defining a XPath query string. This ensures that XPath query strings can be
+ /// passed between different classes in the API, without worrying that they may
+ /// use different prefixes to represent the same namespace.
+ /// </summary>
+ static public XmlNamespaceManager GetDsmlNamespaceManager()
+ {
+ return s_xmlNamespace;
+ }
+ }
+
+ internal class Utility
+ {
+ private static bool s_platformSupported = false;
+ private static bool s_isWin2kOS = false;
+ private static bool s_isWin2k3Above = false;
+
+ static Utility()
+ {
+ // check the platform first
+ // S.DS.Protocols only supported on W2K above
+ //
+ OperatingSystem osVersion = Environment.OSVersion;
+ if ((osVersion.Platform == PlatformID.Win32NT) && (osVersion.Version.Major >= 5))
+ {
+ s_platformSupported = true;
+ if (osVersion.Version.Major == 5 && osVersion.Version.Minor == 0)
+ s_isWin2kOS = true;
+
+ // win2k3's major version is 5, minor version is 2
+ if (osVersion.Version.Major > 5 || osVersion.Version.Minor >= 2)
+ s_isWin2k3Above = true;
+ }
+ }
+
+ internal static void CheckOSVersion()
+ {
+ if (!s_platformSupported)
+ throw new PlatformNotSupportedException(Res.GetString(Res.SupportedPlatforms));
+ }
+
+ internal static bool IsWin2kOS
+ {
+ get
+ {
+ return s_isWin2kOS;
+ }
+ }
+
+ internal static bool IsWin2k3AboveOS
+ {
+ get
+ {
+ return s_isWin2k3Above;
+ }
+ }
+
+ internal static bool IsLdapError(LdapError error)
+ {
+ if (error == LdapError.IsLeaf || error == LdapError.InvalidCredentials || error == LdapError.SendTimeOut)
+ return true;
+
+ if (error >= LdapError.ServerDown && error <= LdapError.ReferralLimitExceeded)
+ return true;
+
+ return false;
+ }
+
+ internal static bool IsResultCode(ResultCode code)
+ {
+ if (code >= ResultCode.Success && code <= ResultCode.SaslBindInProgress)
+ return true;
+
+ if (code >= ResultCode.NoSuchAttribute && code <= ResultCode.InvalidAttributeSyntax)
+ return true;
+
+ if (code >= ResultCode.NoSuchObject && code <= ResultCode.InvalidDNSyntax)
+ return true;
+
+ if (code >= ResultCode.InsufficientAccessRights && code <= ResultCode.LoopDetect)
+ return true;
+
+ if (code >= ResultCode.NamingViolation && code <= ResultCode.AffectsMultipleDsas)
+ return true;
+
+ if (code == ResultCode.AliasDereferencingProblem || code == ResultCode.InappropriateAuthentication || code == ResultCode.SortControlMissing || code == ResultCode.OffsetRangeError || code == ResultCode.VirtualListViewError || code == ResultCode.Other)
+ return true;
+
+ return false;
+ }
+
+ internal static IntPtr AllocHGlobalIntPtrArray(int size)
+ {
+ IntPtr intPtrArray = (IntPtr)0;
+ checked
+ {
+ intPtrArray = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * size);
+ for (int i = 0; i < size; i++)
+ {
+ IntPtr tempPtr = (IntPtr)((long)intPtrArray + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, IntPtr.Zero);
+ }
+ }
+ return intPtrArray;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapAsyncResult.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapAsyncResult.cs
new file mode 100644
index 0000000000..8a0e66be42
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapAsyncResult.cs
@@ -0,0 +1,130 @@
+// 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
+{
+ using System;
+ using System.Threading;
+ using System.Net;
+ using System.Text;
+ using System.IO;
+ using Microsoft.Win32.SafeHandles;
+
+ internal class LdapAsyncResult : IAsyncResult
+ {
+ private LdapAsyncWaitHandle _asyncWaitHandle = null;
+ internal AsyncCallback callback = null;
+ internal bool completed = false;
+ private bool _completedSynchronously = false;
+ internal ManualResetEvent manualResetEvent = null;
+ private object _stateObject = null;
+ internal LdapRequestState resultObject = null;
+ internal bool partialResults = false;
+
+ public LdapAsyncResult(AsyncCallback callbackRoutine, object state, bool partialResults)
+ {
+ _stateObject = state;
+ callback = callbackRoutine;
+ manualResetEvent = new ManualResetEvent(false);
+ this.partialResults = partialResults;
+ }
+
+ object IAsyncResult.AsyncState
+ {
+ get { return _stateObject; }
+ }
+
+ WaitHandle IAsyncResult.AsyncWaitHandle
+ {
+ get
+ {
+ if (null == _asyncWaitHandle)
+ {
+ _asyncWaitHandle = new LdapAsyncWaitHandle(manualResetEvent.SafeWaitHandle);
+ }
+
+ return (WaitHandle)_asyncWaitHandle;
+ }
+ }
+
+ bool IAsyncResult.CompletedSynchronously
+ {
+ get { return _completedSynchronously; }
+ }
+
+ bool IAsyncResult.IsCompleted
+ {
+ get { return completed; }
+ }
+
+ public override int GetHashCode()
+ {
+ return manualResetEvent.GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if ((!(o is LdapAsyncResult)) || (o == null))
+ {
+ return false;
+ }
+
+ return (this == (LdapAsyncResult)o);
+ }
+
+ sealed internal class LdapAsyncWaitHandle : WaitHandle
+ {
+ public LdapAsyncWaitHandle(SafeWaitHandle handle) : base()
+ {
+ this.SafeWaitHandle = handle;
+ }
+
+ ~LdapAsyncWaitHandle()
+ {
+ this.SafeWaitHandle = null;
+ }
+ }
+ }
+
+ internal class LdapRequestState
+ {
+ internal DirectoryResponse response = null;
+ internal LdapAsyncResult ldapAsync = null;
+ internal Exception exception = null;
+ internal bool abortCalled = false;
+
+ public LdapRequestState() { }
+ }
+
+ internal enum ResultsStatus
+ {
+ PartialResult = 0,
+ CompleteResult = 1,
+ Done = 2
+ }
+
+ internal class LdapPartialAsyncResult : LdapAsyncResult
+ {
+ internal LdapConnection con;
+ internal int messageID = -1;
+ internal bool partialCallback;
+ internal ResultsStatus resultStatus = ResultsStatus.PartialResult;
+ internal TimeSpan requestTimeout;
+
+ internal SearchResponse response = null;
+ internal Exception exception = null;
+ internal DateTime startTime;
+
+ public LdapPartialAsyncResult(int messageID, AsyncCallback callbackRoutine, object state, bool partialResults, LdapConnection con, bool partialCallback, TimeSpan requestTimeout) : base(callbackRoutine, state, partialResults)
+ {
+ this.messageID = messageID;
+ this.con = con;
+ this.partialResults = true;
+ this.partialCallback = partialCallback;
+ this.requestTimeout = requestTimeout;
+ this.startTime = DateTime.Now;
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs
new file mode 100644
index 0000000000..7c56ed041c
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs
@@ -0,0 +1,1897 @@
+// 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.
+
+#pragma warning disable 618
+[assembly: System.Net.WebPermission(System.Security.Permissions.SecurityAction.RequestMinimum, Unrestricted = true)]
+[assembly: System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.RequestMinimum, UnmanagedCode = true)]
+[assembly: System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.RequestMinimum, SkipVerification = true)]
+[assembly: System.Security.Permissions.EnvironmentPermission(System.Security.Permissions.SecurityAction.RequestMinimum, Unrestricted = true)]
+[assembly: System.Net.NetworkInformation.NetworkInformationPermission(System.Security.Permissions.SecurityAction.RequestMinimum, Unrestricted = true)]
+
+#pragma warning restore 618
+
+namespace System.DirectoryServices.Protocols
+{
+ using System;
+ using System.Net;
+ using System.Collections;
+ using System.ComponentModel;
+ using System.Text;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using System.Xml;
+ using System.Threading;
+ using System.Security.Cryptography.X509Certificates;
+ using System.DirectoryServices;
+ using System.Security.Permissions;
+
+ internal delegate DirectoryResponse GetLdapResponseCallback(int messageId, LdapOperation operation, ResultAll resultType, TimeSpan requestTimeout, bool exceptionOnTimeOut);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate bool QUERYCLIENTCERT(IntPtr Connection, IntPtr trusted_CAs, ref IntPtr certificateHandle);
+
+ public class LdapConnection : DirectoryConnection, IDisposable
+ {
+ internal enum LdapResult
+ {
+ LDAP_RES_SEARCH_RESULT = 0x65,
+ LDAP_RES_SEARCH_ENTRY = 0x64,
+ LDAP_RES_MODIFY = 0x67,
+ LDAP_RES_ADD = 0x69,
+ LDAP_RES_DELETE = 0x6b,
+ LDAP_RES_MODRDN = 0x6d,
+ LDAP_RES_COMPARE = 0x6f,
+ LDAP_RES_REFERRAL = 0x73,
+ LDAP_RES_EXTENDED = 0x78
+ }
+
+ private const int LDAP_MOD_BVALUES = 0x80;
+ private AuthType _connectionAuthType = AuthType.Negotiate;
+ private LdapSessionOptions _options = null;
+ internal ConnectionHandle ldapHandle = null;
+ internal bool disposed = false;
+ private bool _bounded = false;
+ private bool _needRebind = false;
+ internal static Hashtable handleTable = null;
+ internal static object objectLock = null;
+ private GetLdapResponseCallback _fd = null;
+ private static Hashtable s_asyncResultTable = null;
+ private static LdapPartialResultsProcessor s_partialResultsProcessor = null;
+ private static ManualResetEvent s_waitHandle = null;
+ private static PartialResultsRetriever s_retriever = null;
+ private bool _setFQDNDone = false;
+ internal bool automaticBind = true;
+ internal bool needDispose = true;
+ private bool _connected = false;
+ internal QUERYCLIENTCERT clientCertificateRoutine = null;
+
+ static LdapConnection()
+ {
+ handleTable = new Hashtable();
+ // initialize the lock
+ objectLock = new Object();
+
+ Hashtable tempAsyncTable = new Hashtable();
+ s_asyncResultTable = Hashtable.Synchronized(tempAsyncTable);
+
+ s_waitHandle = new ManualResetEvent(false);
+
+ s_partialResultsProcessor = new LdapPartialResultsProcessor(s_waitHandle);
+
+ s_retriever = new PartialResultsRetriever(s_waitHandle, s_partialResultsProcessor);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true),
+ ]
+ public LdapConnection(string server) : this(new LdapDirectoryIdentifier(server))
+ {
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public LdapConnection(LdapDirectoryIdentifier identifier) : this(identifier, null, AuthType.Negotiate)
+ {
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public LdapConnection(LdapDirectoryIdentifier identifier, NetworkCredential credential) : this(identifier, credential, AuthType.Negotiate)
+ {
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true),
+ EnvironmentPermission(SecurityAction.Assert, Unrestricted = true),
+ SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
+ ]
+ public LdapConnection(LdapDirectoryIdentifier identifier, NetworkCredential credential, AuthType authType)
+ {
+ _fd = new GetLdapResponseCallback(ConstructResponse);
+ directoryIdentifier = identifier;
+ directoryCredential = (credential != null) ? new NetworkCredential(credential.UserName, credential.Password, credential.Domain) : null;
+
+ _connectionAuthType = authType;
+
+ if (authType < AuthType.Anonymous || authType > AuthType.Kerberos)
+ throw new InvalidEnumArgumentException("authType", (int)authType, typeof(AuthType));
+
+ // if user wants to do anonymous bind, but specifies credential, error out
+ if (AuthType == AuthType.Anonymous && (directoryCredential != null && ((directoryCredential.Password != null && directoryCredential.Password.Length != 0) || (directoryCredential.UserName != null && directoryCredential.UserName.Length != 0))))
+ throw new ArgumentException(Res.GetString(Res.InvalidAuthCredential));
+
+ Init();
+ _options = new LdapSessionOptions(this);
+ clientCertificateRoutine = new QUERYCLIENTCERT(ProcessClientCertificate);
+ }
+
+ internal LdapConnection(LdapDirectoryIdentifier identifier, NetworkCredential credential, AuthType authType, IntPtr handle)
+ {
+ directoryIdentifier = identifier;
+ needDispose = false;
+ ldapHandle = new ConnectionHandle(handle, needDispose);
+ directoryCredential = credential;
+ _connectionAuthType = authType;
+ _options = new LdapSessionOptions(this);
+ clientCertificateRoutine = new QUERYCLIENTCERT(ProcessClientCertificate);
+ }
+
+ ~LdapConnection()
+ {
+ Dispose(false);
+ }
+
+ public override TimeSpan Timeout
+ {
+ get
+ {
+ return connectionTimeOut;
+ }
+ set
+ {
+ if (value < TimeSpan.Zero)
+ {
+ throw new ArgumentException(Res.GetString(Res.NoNegativeTime), "value");
+ }
+
+ // prevent integer overflow
+ if (value.TotalSeconds > Int32.MaxValue)
+ throw new ArgumentException(Res.GetString(Res.TimespanExceedMax), "value");
+
+ connectionTimeOut = value;
+ }
+ }
+
+ public AuthType AuthType
+ {
+ get
+ {
+ return _connectionAuthType;
+ }
+ set
+ {
+ if (value < AuthType.Anonymous || value > AuthType.Kerberos)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(AuthType));
+
+ // if the change is made after we have bound to the server and value is really changed, set the flag to indicate the need to do rebind
+ if (_bounded && (value != _connectionAuthType))
+ {
+ _needRebind = true;
+ }
+
+ _connectionAuthType = value;
+ }
+ }
+
+ public LdapSessionOptions SessionOptions
+ {
+ get
+ {
+ return _options;
+ }
+ }
+
+ public override NetworkCredential Credential
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ EnvironmentPermission(SecurityAction.Assert, Unrestricted = true),
+ SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
+ ]
+ set
+ {
+ if (_bounded && !SameCredential(directoryCredential, value))
+ _needRebind = true;
+
+ directoryCredential = (value != null) ? new NetworkCredential(value.UserName, value.Password, value.Domain) : null;
+ }
+ }
+
+ public bool AutoBind
+ {
+ get
+ {
+ return automaticBind;
+ }
+ set
+ {
+ automaticBind = value;
+ }
+ }
+
+ internal bool NeedDispose
+ {
+ get
+ {
+ return needDispose;
+ }
+ set
+ {
+ if (null != ldapHandle)
+ {
+ ldapHandle.needDispose = value;
+ }
+ needDispose = value;
+ }
+ }
+
+ internal void Init()
+ {
+ string hostname = null;
+ string[] servers = (directoryIdentifier == null ? null : ((LdapDirectoryIdentifier)directoryIdentifier).Servers);
+ if (servers != null && servers.Length != 0)
+ {
+ StringBuilder temp = new StringBuilder(200);
+ for (int i = 0; i < servers.Length; i++)
+ {
+ if (servers[i] != null)
+ {
+ temp.Append(servers[i]);
+ if (i < servers.Length - 1)
+ temp.Append(" ");
+ }
+ }
+ if (temp.Length != 0)
+ hostname = temp.ToString();
+ }
+
+ // 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);
+ }
+
+ // create a WeakReference object with the target of ldapHandle and put it into our handle table.
+ lock (objectLock)
+ {
+ if (handleTable[ldapHandle.DangerousGetHandle()] != null)
+ handleTable.Remove(ldapHandle.DangerousGetHandle());
+
+ handleTable.Add(ldapHandle.DangerousGetHandle(), new WeakReference(this));
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public override DirectoryResponse SendRequest(DirectoryRequest request)
+ {
+ // no request specific timeout is specified, use the connection timeout
+ return SendRequest(request, connectionTimeOut);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public DirectoryResponse SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
+ {
+ if (this.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (request == null)
+ throw new ArgumentNullException("request");
+
+ if (request is DsmlAuthRequest)
+ throw new NotSupportedException(Res.GetString(Res.DsmlAuthRequestNotSupported));
+
+ int messageID = 0;
+ int error = SendRequestHelper(request, ref messageID);
+
+ LdapOperation operation = LdapOperation.LdapSearch;
+ if (request is DeleteRequest)
+ operation = LdapOperation.LdapDelete;
+ else if (request is AddRequest)
+ operation = LdapOperation.LdapAdd;
+ else if (request is ModifyRequest)
+ operation = LdapOperation.LdapModify;
+ else if (request is SearchRequest)
+ operation = LdapOperation.LdapSearch;
+ else if (request is ModifyDNRequest)
+ operation = LdapOperation.LdapModifyDn;
+ else if (request is CompareRequest)
+ operation = LdapOperation.LdapCompare;
+ else if (request is ExtendedRequest)
+ operation = LdapOperation.LdapExtendedRequest;
+
+ if (error == 0 && messageID != -1)
+ {
+ return ConstructResponse(messageID, operation, ResultAll.LDAP_MSG_ALL, requestTimeout, true);
+ }
+ else
+ {
+ if (error == 0)
+ {
+ // success code but message is -1, unexpected
+ error = Wldap32.LdapGetLastError();
+ }
+
+ throw ConstructException(error, operation);
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public IAsyncResult BeginSendRequest(DirectoryRequest request, PartialResultProcessing partialMode, AsyncCallback callback, object state)
+ {
+ return BeginSendRequest(request, connectionTimeOut, partialMode, callback, state);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public IAsyncResult BeginSendRequest(DirectoryRequest request, TimeSpan requestTimeout, PartialResultProcessing partialMode, AsyncCallback callback, object state)
+ {
+ int messageID = 0;
+ int error = 0;
+
+ if (this.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // parameter validation
+ if (request == null)
+ throw new ArgumentNullException("request");
+
+ if (partialMode < PartialResultProcessing.NoPartialResultSupport || partialMode > PartialResultProcessing.ReturnPartialResultsAndNotifyCallback)
+ throw new InvalidEnumArgumentException("partialMode", (int)partialMode, typeof(PartialResultProcessing));
+
+ if (partialMode != PartialResultProcessing.NoPartialResultSupport && !(request is SearchRequest))
+ throw new NotSupportedException(Res.GetString(Res.PartialResultsNotSupported));
+
+ if (partialMode == PartialResultProcessing.ReturnPartialResultsAndNotifyCallback && (callback == null))
+ throw new ArgumentException(Res.GetString(Res.CallBackIsNull), "callback");
+
+ error = SendRequestHelper(request, ref messageID);
+
+ LdapOperation operation = LdapOperation.LdapSearch;
+ if (request is DeleteRequest)
+ operation = LdapOperation.LdapDelete;
+ else if (request is AddRequest)
+ operation = LdapOperation.LdapAdd;
+ else if (request is ModifyRequest)
+ operation = LdapOperation.LdapModify;
+ else if (request is SearchRequest)
+ operation = LdapOperation.LdapSearch;
+ else if (request is ModifyDNRequest)
+ operation = LdapOperation.LdapModifyDn;
+ else if (request is CompareRequest)
+ operation = LdapOperation.LdapCompare;
+ else if (request is ExtendedRequest)
+ operation = LdapOperation.LdapExtendedRequest;
+
+ if (error == 0 && messageID != -1)
+ {
+ if (partialMode == PartialResultProcessing.NoPartialResultSupport)
+ {
+ LdapRequestState rs = new LdapRequestState();
+ LdapAsyncResult asyncResult = new LdapAsyncResult(callback, state, false);
+
+ rs.ldapAsync = asyncResult;
+ asyncResult.resultObject = rs;
+
+ s_asyncResultTable.Add(asyncResult, messageID);
+
+ _fd.BeginInvoke(messageID, operation, ResultAll.LDAP_MSG_ALL, requestTimeout, true, new AsyncCallback(ResponseCallback), rs);
+
+ return (IAsyncResult)asyncResult;
+ }
+ else
+ {
+ // the user registers to retrieve partial results
+ bool partialCallback = false;
+ if (partialMode == PartialResultProcessing.ReturnPartialResultsAndNotifyCallback)
+ partialCallback = true;
+ LdapPartialAsyncResult asyncResult = new LdapPartialAsyncResult(messageID, callback, state, true, this, partialCallback, requestTimeout);
+ s_partialResultsProcessor.Add(asyncResult);
+
+ return (IAsyncResult)asyncResult;
+ }
+ }
+ else
+ {
+ if (error == 0)
+ {
+ // success code but message is -1, unexpected
+ error = Wldap32.LdapGetLastError();
+ }
+
+ throw ConstructException(error, operation);
+ }
+ }
+
+ private void ResponseCallback(IAsyncResult asyncResult)
+ {
+ LdapRequestState rs = (LdapRequestState)asyncResult.AsyncState;
+
+ try
+ {
+ DirectoryResponse response = _fd.EndInvoke(asyncResult);
+ rs.response = response;
+ }
+ catch (Exception e)
+ {
+ rs.exception = e;
+ rs.response = null;
+ }
+
+ // signal waitable object, indicate operation completed and fire callback
+ rs.ldapAsync.manualResetEvent.Set();
+ rs.ldapAsync.completed = true;
+ if (rs.ldapAsync.callback != null && !rs.abortCalled)
+ {
+ rs.ldapAsync.callback((IAsyncResult)rs.ldapAsync);
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public void Abort(IAsyncResult asyncResult)
+ {
+ if (this.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+
+ if (!(asyncResult is LdapAsyncResult))
+ throw new ArgumentException(Res.GetString(Res.NotReturnedAsyncResult, "asyncResult"));
+
+ int messageId = -1;
+
+ LdapAsyncResult result = (LdapAsyncResult)asyncResult;
+
+ if (!result.partialResults)
+ {
+ if (!s_asyncResultTable.Contains(asyncResult))
+ throw new ArgumentException(Res.GetString(Res.InvalidAsyncResult));
+
+ messageId = (int)(s_asyncResultTable[asyncResult]);
+
+ // remove the asyncResult from our connection table
+ s_asyncResultTable.Remove(asyncResult);
+ }
+ else
+ {
+ s_partialResultsProcessor.Remove((LdapPartialAsyncResult)asyncResult);
+ messageId = ((LdapPartialAsyncResult)asyncResult).messageID;
+ }
+
+ // cancel the request
+ Wldap32.ldap_abandon(ldapHandle, messageId);
+
+ LdapRequestState rs = result.resultObject;
+ if (rs != null)
+ rs.abortCalled = true;
+ }
+
+ public PartialResultsCollection GetPartialResults(IAsyncResult asyncResult)
+ {
+ if (this.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+
+ if (!(asyncResult is LdapAsyncResult))
+ throw new ArgumentException(Res.GetString(Res.NotReturnedAsyncResult, "asyncResult"));
+
+ if (!(asyncResult is LdapPartialAsyncResult))
+ throw new InvalidOperationException(Res.GetString(Res.NoPartialResults));
+
+ return s_partialResultsProcessor.GetPartialResults((LdapPartialAsyncResult)asyncResult);
+ }
+
+ public DirectoryResponse EndSendRequest(IAsyncResult asyncResult)
+ {
+ if (this.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+
+ if (!(asyncResult is LdapAsyncResult))
+ throw new ArgumentException(Res.GetString(Res.NotReturnedAsyncResult, "asyncResult"));
+
+ LdapAsyncResult result = (LdapAsyncResult)asyncResult;
+
+ if (!result.partialResults)
+ {
+ // not a partial results
+ if (!s_asyncResultTable.Contains(asyncResult))
+ throw new ArgumentException(Res.GetString(Res.InvalidAsyncResult));
+
+ // remove the asyncResult from our connection table
+ s_asyncResultTable.Remove(asyncResult);
+
+ asyncResult.AsyncWaitHandle.WaitOne();
+
+ if (result.resultObject.exception != null)
+ throw result.resultObject.exception;
+ else
+ return result.resultObject.response;
+ }
+ else
+ {
+ // deal with partial results
+ s_partialResultsProcessor.NeedCompleteResult((LdapPartialAsyncResult)asyncResult);
+ asyncResult.AsyncWaitHandle.WaitOne();
+
+ return s_partialResultsProcessor.GetCompleteResult((LdapPartialAsyncResult)asyncResult);
+ }
+ }
+
+ private int SendRequestHelper(DirectoryRequest request, ref int messageID)
+ {
+ IntPtr serverControlArray = (IntPtr)0;
+ LdapControl[] managedServerControls = null;
+ IntPtr clientControlArray = (IntPtr)0;
+ LdapControl[] managedClientControls = null;
+
+ string strValue = null;
+
+ ArrayList ptrToFree = new ArrayList();
+ LdapMod[] modifications = null;
+ IntPtr modArray = (IntPtr)0;
+ int addModCount = 0;
+
+ berval berValuePtr = null;
+
+ IntPtr searchAttributes = (IntPtr)0;
+ DereferenceAlias searchAliases;
+ int attributeCount = 0;
+
+ int error = 0;
+
+ // connect to the server first if have not done so
+ if (!_connected)
+ {
+ Connect();
+ _connected = true;
+ }
+
+ //do Bind if user has not turned off automatic bind, have not done so or there is a need to do rebind, also connectionless LDAP does not need to do bind
+ if (AutoBind && (!_bounded || _needRebind) && ((LdapDirectoryIdentifier)Directory).Connectionless != true)
+ {
+ Debug.WriteLine("rebind occurs\n");
+ Bind();
+ }
+
+ try
+ {
+ IntPtr controlPtr = (IntPtr)0;
+ IntPtr tempPtr = (IntPtr)0;
+
+ // build server control
+ managedServerControls = BuildControlArray(request.Controls, true);
+ int structSize = Marshal.SizeOf(typeof(LdapControl));
+
+ if (managedServerControls != null)
+ {
+ serverControlArray = Utility.AllocHGlobalIntPtrArray(managedServerControls.Length + 1);
+ for (int i = 0; i < managedServerControls.Length; i++)
+ {
+ controlPtr = Marshal.AllocHGlobal(structSize);
+ Marshal.StructureToPtr(managedServerControls[i], controlPtr, false);
+ tempPtr = (IntPtr)((long)serverControlArray + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, controlPtr);
+ }
+ tempPtr = (IntPtr)((long)serverControlArray + Marshal.SizeOf(typeof(IntPtr)) * managedServerControls.Length);
+ Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
+ }
+
+ // build client control
+ managedClientControls = BuildControlArray(request.Controls, false);
+ if (managedClientControls != null)
+ {
+ clientControlArray = Utility.AllocHGlobalIntPtrArray(managedClientControls.Length + 1);
+ for (int i = 0; i < managedClientControls.Length; i++)
+ {
+ controlPtr = Marshal.AllocHGlobal(structSize);
+ Marshal.StructureToPtr(managedClientControls[i], controlPtr, false);
+ tempPtr = (IntPtr)((long)clientControlArray + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, controlPtr);
+ }
+ tempPtr = (IntPtr)((long)clientControlArray + Marshal.SizeOf(typeof(IntPtr)) * managedClientControls.Length);
+ Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
+ }
+
+ if (request is DeleteRequest)
+ {
+ // it is an delete operation
+ error = Wldap32.ldap_delete_ext(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);
+ }
+ else if (request is CompareRequest)
+ {
+ // it is a compare request
+ DirectoryAttribute assertion = ((CompareRequest)request).Assertion;
+ if (assertion == null)
+ throw new ArgumentException(Res.GetString(Res.WrongAssertionCompare));
+
+ if (assertion.Count != 1)
+ throw new ArgumentException(Res.GetString(Res.WrongNumValuesCompare));
+
+ // process the attribute
+ byte[] byteArray = assertion[0] as byte[];
+ if (byteArray != null)
+ {
+ if (byteArray != null && byteArray.Length != 0)
+ {
+ berValuePtr = new berval();
+ berValuePtr.bv_len = byteArray.Length;
+ berValuePtr.bv_val = Marshal.AllocHGlobal(byteArray.Length);
+ Marshal.Copy(byteArray, 0, berValuePtr.bv_val, byteArray.Length);
+ }
+ }
+ else
+ {
+ strValue = assertion[0].ToString();
+ }
+
+ // it is a compare request
+ error = Wldap32.ldap_compare(ldapHandle,
+ ((CompareRequest)request).DistinguishedName,
+ assertion.Name,
+ strValue,
+ berValuePtr,
+ serverControlArray, clientControlArray, ref messageID);
+ }
+ else if (request is AddRequest || request is ModifyRequest)
+ {
+ // build the attributes
+
+ if (request is AddRequest)
+ modifications = BuildAttributes(((AddRequest)request).Attributes, ptrToFree);
+ else
+ modifications = BuildAttributes(((ModifyRequest)request).Modifications, ptrToFree);
+
+ addModCount = (modifications == null ? 1 : modifications.Length + 1);
+ modArray = Utility.AllocHGlobalIntPtrArray(addModCount);
+ int modStructSize = Marshal.SizeOf(typeof(LdapMod));
+ int i = 0;
+ for (i = 0; i < addModCount - 1; i++)
+ {
+ controlPtr = Marshal.AllocHGlobal(modStructSize);
+ Marshal.StructureToPtr(modifications[i], controlPtr, false);
+ tempPtr = (IntPtr)((long)modArray + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, controlPtr);
+ }
+ tempPtr = (IntPtr)((long)modArray + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
+
+ if (request is AddRequest)
+ {
+ error = Wldap32.ldap_add(ldapHandle,
+ ((AddRequest)request).DistinguishedName,
+ modArray,
+ serverControlArray, clientControlArray, ref messageID);
+ }
+ else
+ {
+ error = Wldap32.ldap_modify(ldapHandle,
+ ((ModifyRequest)request).DistinguishedName,
+ modArray,
+ serverControlArray, clientControlArray, ref messageID);
+ }
+ }
+ else if (request is ExtendedRequest)
+ {
+ string name = ((ExtendedRequest)request).RequestName;
+ byte[] val = ((ExtendedRequest)request).RequestValue;
+
+ // process the requestvalue
+ if (val != null && val.Length != 0)
+ {
+ berValuePtr = new berval();
+ berValuePtr.bv_len = val.Length;
+ berValuePtr.bv_val = Marshal.AllocHGlobal(val.Length);
+ Marshal.Copy(val, 0, berValuePtr.bv_val, val.Length);
+ }
+
+ error = Wldap32.ldap_extended_operation(ldapHandle,
+ name,
+ berValuePtr,
+ serverControlArray, clientControlArray, ref messageID);
+ }
+ else if (request is SearchRequest)
+ {
+ // processing the filter
+ SearchRequest searchRequest = (SearchRequest)request;
+ object filter = searchRequest.Filter;
+ if (filter != null)
+ {
+ // LdapConnection only supports ldap filter
+ if (filter is XmlDocument)
+ throw new ArgumentException(Res.GetString(Res.InvalidLdapSearchRequestFilter));
+ }
+ string searchRequestFilter = (string)filter;
+
+ // processing the attributes
+ attributeCount = (searchRequest.Attributes == null ? 0 : searchRequest.Attributes.Count);
+ if (attributeCount != 0)
+ {
+ searchAttributes = Utility.AllocHGlobalIntPtrArray(attributeCount + 1);
+ int i = 0;
+ for (i = 0; i < attributeCount; i++)
+ {
+ controlPtr = Marshal.StringToHGlobalUni(searchRequest.Attributes[i]);
+ tempPtr = (IntPtr)((long)searchAttributes + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, controlPtr);
+ }
+ tempPtr = (IntPtr)((long)searchAttributes + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
+ }
+
+ // processing the scope
+ int searchScope = (int)searchRequest.Scope;
+
+ // processing the timelimit
+ int searchTimeLimit = (int)(searchRequest.TimeLimit.Ticks / TimeSpan.TicksPerSecond);
+
+ // processing the alias
+ searchAliases = _options.DerefAlias;
+ _options.DerefAlias = searchRequest.Aliases;
+
+ try
+ {
+ error = Wldap32.ldap_search(ldapHandle,
+ searchRequest.DistinguishedName,
+ searchScope,
+ searchRequestFilter,
+ searchAttributes,
+ searchRequest.TypesOnly,
+ serverControlArray,
+ clientControlArray,
+ searchTimeLimit,
+ searchRequest.SizeLimit,
+ ref messageID);
+ }
+ finally
+ {
+ // revert back
+ _options.DerefAlias = searchAliases;
+ }
+ }
+ else
+ {
+ throw new NotSupportedException(Res.GetString(Res.InvliadRequestType));
+ }
+
+ // the asynchronous call itself timeout, this actually means that we time out the LDAP_OPT_SEND_TIMEOUT specified in the session option
+ // wldap32 does not differentiate that, but the application caller actually needs this information to determin what to do with the error code
+ if (error == (int)LdapError.TimeOut)
+ error = (int)LdapError.SendTimeOut;
+
+ return error;
+ }
+ finally
+ {
+ GC.KeepAlive(modifications);
+
+ if (serverControlArray != (IntPtr)0)
+ {
+ //release the memory from the heap
+ for (int i = 0; i < managedServerControls.Length; i++)
+ {
+ IntPtr tempPtr = Marshal.ReadIntPtr(serverControlArray, Marshal.SizeOf(typeof(IntPtr)) * i);
+ if (tempPtr != (IntPtr)0)
+ Marshal.FreeHGlobal(tempPtr);
+ }
+ Marshal.FreeHGlobal(serverControlArray);
+ }
+
+ if (managedServerControls != null)
+ {
+ for (int i = 0; i < managedServerControls.Length; i++)
+ {
+ if (managedServerControls[i].ldctl_oid != (IntPtr)0)
+ Marshal.FreeHGlobal(managedServerControls[i].ldctl_oid);
+
+ if (managedServerControls[i].ldctl_value != null)
+ {
+ if (managedServerControls[i].ldctl_value.bv_val != (IntPtr)0)
+ Marshal.FreeHGlobal(managedServerControls[i].ldctl_value.bv_val);
+ }
+ }
+ }
+
+ if (clientControlArray != (IntPtr)0)
+ {
+ // release the memory from the heap
+ for (int i = 0; i < managedClientControls.Length; i++)
+ {
+ IntPtr tempPtr = Marshal.ReadIntPtr(clientControlArray, Marshal.SizeOf(typeof(IntPtr)) * i);
+ if (tempPtr != (IntPtr)0)
+ Marshal.FreeHGlobal(tempPtr);
+ }
+ Marshal.FreeHGlobal(clientControlArray);
+ }
+
+ if (managedClientControls != null)
+ {
+ for (int i = 0; i < managedClientControls.Length; i++)
+ {
+ if (managedClientControls[i].ldctl_oid != (IntPtr)0)
+ Marshal.FreeHGlobal(managedClientControls[i].ldctl_oid);
+
+ if (managedClientControls[i].ldctl_value != null)
+ {
+ if (managedClientControls[i].ldctl_value.bv_val != (IntPtr)0)
+ Marshal.FreeHGlobal(managedClientControls[i].ldctl_value.bv_val);
+ }
+ }
+ }
+
+ if (modArray != (IntPtr)0)
+ {
+ // release the memory from the heap
+ for (int i = 0; i < addModCount - 1; i++)
+ {
+ IntPtr tempPtr = Marshal.ReadIntPtr(modArray, Marshal.SizeOf(typeof(IntPtr)) * i);
+ if (tempPtr != (IntPtr)0)
+ Marshal.FreeHGlobal(tempPtr);
+ }
+ Marshal.FreeHGlobal(modArray);
+ }
+
+ // free the pointers
+ for (int x = 0; x < ptrToFree.Count; x++)
+ {
+ IntPtr tempPtr = (IntPtr)ptrToFree[x];
+ Marshal.FreeHGlobal(tempPtr);
+ }
+
+ if (berValuePtr != null)
+ {
+ if (berValuePtr.bv_val != (IntPtr)0)
+ Marshal.FreeHGlobal(berValuePtr.bv_val);
+ }
+
+ if (searchAttributes != (IntPtr)0)
+ {
+ for (int i = 0; i < attributeCount; i++)
+ {
+ IntPtr tempPtr = Marshal.ReadIntPtr(searchAttributes, Marshal.SizeOf(typeof(IntPtr)) * i);
+ if (tempPtr != (IntPtr)0)
+ Marshal.FreeHGlobal(tempPtr);
+ }
+ Marshal.FreeHGlobal(searchAttributes);
+ }
+ }
+ }
+
+ private bool ProcessClientCertificate(IntPtr ldapHandle, IntPtr CAs, ref IntPtr certificate)
+ {
+ ArrayList list = new ArrayList();
+ byte[][] certAuthorities = null;
+ int count = ClientCertificates == null ? 0 : ClientCertificates.Count;
+
+ if (count == 0 && _options.clientCertificateDelegate == null)
+ {
+ return false;
+ }
+
+ // if user specify certificate through property and not though option, we don't need to check CA
+ if (_options.clientCertificateDelegate == null)
+ {
+ certificate = ClientCertificates[0].Handle;
+ return true;
+ }
+
+ // processing the CA
+ if (CAs != (IntPtr)0)
+ {
+ SecPkgContext_IssuerListInfoEx trustedCAs = (SecPkgContext_IssuerListInfoEx)Marshal.PtrToStructure(CAs, typeof(SecPkgContext_IssuerListInfoEx));
+ int issuerNumber = trustedCAs.cIssuers;
+ IntPtr tempPtr = (IntPtr)0;
+ for (int i = 0; i < issuerNumber; i++)
+ {
+ tempPtr = (IntPtr)((long)trustedCAs.aIssuers + Marshal.SizeOf(typeof(CRYPTOAPI_BLOB)) * i);
+ CRYPTOAPI_BLOB info = (CRYPTOAPI_BLOB)Marshal.PtrToStructure(tempPtr, typeof(CRYPTOAPI_BLOB));
+ int dataLength = info.cbData;
+ byte[] context = new byte[dataLength];
+ Marshal.Copy(info.pbData, context, 0, dataLength);
+ list.Add(context);
+ }
+ }
+
+ if (list.Count != 0)
+ {
+ certAuthorities = new byte[list.Count][];
+ for (int i = 0; i < list.Count; i++)
+ {
+ certAuthorities[i] = (byte[])list[i];
+ }
+ }
+
+ X509Certificate cert = _options.clientCertificateDelegate(this, certAuthorities);
+ if (cert != null)
+ {
+ certificate = cert.Handle;
+ return true;
+ }
+ else
+ {
+ certificate = (IntPtr)0;
+ return false;
+ }
+ }
+
+ private void Connect()
+ {
+ int error = 0;
+ string errorMessage;
+
+ // currently ldap does not accept more than one certificate, so check here
+ if (ClientCertificates.Count > 1)
+ throw new InvalidOperationException(Res.GetString(Res.InvalidClientCertificates));
+
+ // 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);
+ if (certerror != (int)ResultCode.Success)
+ {
+ if (Utility.IsLdapError((LdapError)certerror))
+ {
+ string certerrorMessage = LdapErrorMappings.MapResultCode(certerror);
+ throw new LdapException(certerror, certerrorMessage);
+ }
+ else
+ throw new LdapException(certerror);
+ }
+ // when certificate is specified, automatic bind is disabled
+ automaticBind = false;
+ }
+
+ // set the LDAP_OPT_AREC_EXCLUSIVE flag if necessary
+ if (((LdapDirectoryIdentifier)Directory).FullyQualifiedDnsHostName && !_setFQDNDone)
+ {
+ SessionOptions.FQDN = true;
+ _setFQDNDone = true;
+ }
+
+ // connect explicitly to the server
+ LDAP_TIMEVAL timeout = new LDAP_TIMEVAL();
+ timeout.tv_sec = (int)(connectionTimeOut.Ticks / TimeSpan.TicksPerSecond);
+ Debug.Assert(!ldapHandle.IsInvalid);
+ error = Wldap32.ldap_connect(ldapHandle, timeout);
+ // failed, throw exception
+ if (error != (int)ResultCode.Success)
+ {
+ if (Utility.IsLdapError((LdapError)error))
+ {
+ errorMessage = LdapErrorMappings.MapResultCode(error);
+ throw new LdapException(error, errorMessage);
+ }
+ else
+ throw new LdapException(error);
+ }
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public void Bind()
+ {
+ BindHelper(directoryCredential, false /* no need to reset credential */);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public void Bind(NetworkCredential newCredential)
+ {
+ BindHelper(newCredential, true /* need to reset credential */);
+ }
+
+ [
+ EnvironmentPermission(SecurityAction.Assert, Unrestricted = true),
+ SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
+ ]
+ private void BindHelper(NetworkCredential newCredential, bool needSetCredential)
+ {
+ int error = 0;
+ string errorMessage;
+ string username;
+ string domainname;
+ string password;
+ NetworkCredential tempCredential = null;
+
+ // if already disposed, we need to throw exception
+ if (this.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // if user wants to do anonymous bind, but specifies credential, error out
+ if (AuthType == AuthType.Anonymous && (newCredential != null && ((newCredential.Password != null && newCredential.Password.Length != 0) || (newCredential.UserName != null && newCredential.UserName.Length != 0))))
+ throw new InvalidOperationException(Res.GetString(Res.InvalidAuthCredential));
+
+ // set the credential
+ if (needSetCredential)
+ directoryCredential = tempCredential = (newCredential != null ? new NetworkCredential(newCredential.UserName, newCredential.Password, newCredential.Domain) : null);
+ else
+ tempCredential = directoryCredential;
+
+ // connect to the server first
+ if (!_connected)
+ {
+ Connect();
+ _connected = true;
+ }
+
+ // bind to the server
+ if (tempCredential != null && tempCredential.UserName.Length == 0 && tempCredential.Password.Length == 0 && tempCredential.Domain.Length == 0)
+ {
+ // default credential
+ username = null;
+ domainname = null;
+ password = null;
+ }
+ else
+ {
+ username = (tempCredential == null) ? null : tempCredential.UserName;
+ domainname = (tempCredential == null) ? null : tempCredential.Domain;
+ password = (tempCredential == null) ? null : tempCredential.Password;
+ }
+
+ if (AuthType == AuthType.Anonymous)
+ error = Wldap32.ldap_simple_bind_s(ldapHandle, null, null);
+ else if (AuthType == AuthType.Basic)
+ {
+ StringBuilder tempdn = new StringBuilder(100);
+ if (domainname != null && domainname.Length != 0)
+ {
+ tempdn.Append(domainname);
+ tempdn.Append("\\");
+ }
+ tempdn.Append(username);
+ error = Wldap32.ldap_simple_bind_s(ldapHandle, tempdn.ToString(), password);
+ }
+ else
+ {
+ SEC_WINNT_AUTH_IDENTITY_EX cred = new SEC_WINNT_AUTH_IDENTITY_EX();
+ cred.version = Wldap32.SEC_WINNT_AUTH_IDENTITY_VERSION;
+ cred.length = Marshal.SizeOf(typeof(SEC_WINNT_AUTH_IDENTITY_EX));
+ cred.flags = Wldap32.SEC_WINNT_AUTH_IDENTITY_UNICODE;
+ if (AuthType == AuthType.Kerberos)
+ {
+ cred.packageList = Wldap32.MICROSOFT_KERBEROS_NAME_W;
+ cred.packageListLength = cred.packageList.Length;
+ }
+
+ if (tempCredential != null)
+ {
+ cred.user = username;
+ cred.userLength = (username == null ? 0 : username.Length);
+ cred.domain = domainname;
+ cred.domainLength = (domainname == null ? 0 : domainname.Length);
+ cred.password = password;
+ cred.passwordLength = (password == null ? 0 : password.Length);
+ }
+
+ BindMethod method = BindMethod.LDAP_AUTH_NEGOTIATE;
+ switch (AuthType)
+ {
+ case AuthType.Negotiate:
+ method = BindMethod.LDAP_AUTH_NEGOTIATE;
+ break;
+ case AuthType.Kerberos:
+ method = BindMethod.LDAP_AUTH_NEGOTIATE;
+ break;
+ case AuthType.Ntlm:
+ method = BindMethod.LDAP_AUTH_NTLM;
+ break;
+ case AuthType.Digest:
+ method = BindMethod.LDAP_AUTH_DIGEST;
+ break;
+ case AuthType.Sicily:
+ method = BindMethod.LDAP_AUTH_SICILY;
+ break;
+ case AuthType.Dpa:
+ method = BindMethod.LDAP_AUTH_DPA;
+ break;
+ case AuthType.Msn:
+ method = BindMethod.LDAP_AUTH_MSN;
+ break;
+ case AuthType.External:
+ method = BindMethod.LDAP_AUTH_EXTERNAL;
+ 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);
+ }
+ }
+
+ // failed, throw exception
+ if (error != (int)ResultCode.Success)
+ {
+ if (Utility.IsResultCode((ResultCode)error))
+ {
+ errorMessage = OperationErrorMappings.MapResultCode(error);
+ throw new DirectoryOperationException(null, errorMessage);
+ }
+ else if (Utility.IsLdapError((LdapError)error))
+ {
+ errorMessage = LdapErrorMappings.MapResultCode(error);
+ string serverErrorMessage = _options.ServerErrorMessage;
+ if ((serverErrorMessage != null) && (serverErrorMessage.Length > 0))
+ {
+ throw new LdapException(error, errorMessage, serverErrorMessage);
+ }
+ else
+ {
+ throw new LdapException(error, errorMessage);
+ }
+ }
+ else
+ throw new LdapException(error);
+ }
+
+ // we successfully bind to the server
+ _bounded = true;
+ // rebind has been done
+ _needRebind = false;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // free other state (managed objects)
+
+ // we need to remove the handle from the handle table
+ lock (objectLock)
+ {
+ if (null != ldapHandle)
+ {
+ handleTable.Remove(ldapHandle.DangerousGetHandle());
+ }
+ }
+ }
+ // free your own state (unmanaged objects)
+
+ // close the ldap connection
+ if (needDispose && ldapHandle != null && !ldapHandle.IsInvalid)
+ ldapHandle.Dispose();
+ ldapHandle = null;
+
+ disposed = true;
+
+ Debug.WriteLine("Connection object is disposed\n");
+ }
+
+ internal LdapControl[] BuildControlArray(DirectoryControlCollection controls, bool serverControl)
+ {
+ int count = 0;
+ LdapControl[] managedControls = null;
+
+ if (controls != null && controls.Count != 0)
+ {
+ ArrayList controlList = new ArrayList();
+ foreach (DirectoryControl col in controls)
+ {
+ if (serverControl == true)
+ {
+ if (col.ServerSide)
+ controlList.Add(col);
+ }
+ else
+ {
+ if (!col.ServerSide)
+ controlList.Add(col);
+ }
+ }
+ if (controlList.Count != 0)
+ {
+ count = controlList.Count;
+
+ managedControls = new LdapControl[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ managedControls[i] = new LdapControl();
+ // get the control type
+ managedControls[i].ldctl_oid = Marshal.StringToHGlobalUni(((DirectoryControl)controlList[i]).Type);
+ //get the control cricality
+ managedControls[i].ldctl_iscritical = ((DirectoryControl)controlList[i]).IsCritical;
+ // get the control value
+ DirectoryControl tempControl = (DirectoryControl)controlList[i];
+ byte[] byteControlValue = tempControl.GetValue();
+ if (byteControlValue == null || byteControlValue.Length == 0)
+ {
+ // treat the control value as null
+ managedControls[i].ldctl_value = new berval();
+ managedControls[i].ldctl_value.bv_len = 0;
+ managedControls[i].ldctl_value.bv_val = (IntPtr)0;
+ }
+ else
+ {
+ managedControls[i].ldctl_value = new berval();
+ managedControls[i].ldctl_value.bv_len = byteControlValue.Length;
+ managedControls[i].ldctl_value.bv_val = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(byte)) * managedControls[i].ldctl_value.bv_len);
+ Marshal.Copy(byteControlValue, 0, managedControls[i].ldctl_value.bv_val, managedControls[i].ldctl_value.bv_len);
+ }
+ }
+ }
+ }
+
+ return managedControls;
+ }
+
+ internal LdapMod[] BuildAttributes(CollectionBase directoryAttributes, ArrayList ptrToFree)
+ {
+ LdapMod[] attributes = null;
+ UTF8Encoding encoder = new UTF8Encoding();
+ DirectoryAttributeCollection attributeCollection = null;
+ DirectoryAttributeModificationCollection modificationCollection = null;
+ DirectoryAttribute modAttribute = null;
+
+ if (directoryAttributes != null && directoryAttributes.Count != 0)
+ {
+ if (directoryAttributes is DirectoryAttributeModificationCollection)
+ {
+ modificationCollection = (DirectoryAttributeModificationCollection)directoryAttributes;
+ }
+ else
+ {
+ attributeCollection = (DirectoryAttributeCollection)directoryAttributes;
+ }
+
+ attributes = new LdapMod[directoryAttributes.Count];
+ for (int i = 0; i < directoryAttributes.Count; i++)
+ {
+ // get the managed attribute first
+ if (attributeCollection != null)
+ modAttribute = attributeCollection[i];
+ else
+ modAttribute = modificationCollection[i];
+
+ attributes[i] = new LdapMod();
+
+ // operation type
+ if (modAttribute is DirectoryAttributeModification)
+ {
+ attributes[i].type = (int)((DirectoryAttributeModification)modAttribute).Operation;
+ }
+ else
+ {
+ attributes[i].type = (int)DirectoryAttributeOperation.Add;
+ }
+ // we treat all the values as binary
+ attributes[i].type |= (int)LDAP_MOD_BVALUES;
+
+ //attribute name
+ attributes[i].attribute = Marshal.StringToHGlobalUni(modAttribute.Name);
+
+ // values
+ int valuesCount = 0;
+ berval[] berValues = null;
+ if (modAttribute.Count > 0)
+ {
+ valuesCount = modAttribute.Count;
+ berValues = new berval[valuesCount];
+ for (int j = 0; j < valuesCount; j++)
+ {
+ byte[] byteArray = null;
+ if (modAttribute[j] is string)
+ byteArray = encoder.GetBytes((string)modAttribute[j]);
+ else if (modAttribute[j] is Uri)
+ byteArray = encoder.GetBytes(((Uri)modAttribute[j]).ToString());
+ else
+ byteArray = (byte[])modAttribute[j];
+
+ berValues[j] = new berval();
+ berValues[j].bv_len = byteArray.Length;
+ berValues[j].bv_val = Marshal.AllocHGlobal(berValues[j].bv_len);
+ // need to free the memory allocated on the heap when we are done
+ ptrToFree.Add(berValues[j].bv_val);
+ Marshal.Copy(byteArray, 0, berValues[j].bv_val, berValues[j].bv_len);
+ }
+ }
+
+ attributes[i].values = Utility.AllocHGlobalIntPtrArray(valuesCount + 1);
+ int structSize = Marshal.SizeOf(typeof(berval));
+ IntPtr controlPtr = (IntPtr)0;
+ IntPtr tempPtr = (IntPtr)0;
+ int m = 0;
+ for (m = 0; m < valuesCount; m++)
+ {
+ controlPtr = Marshal.AllocHGlobal(structSize);
+ // need to free the memory allocated on the heap when we are done
+ ptrToFree.Add(controlPtr);
+ Marshal.StructureToPtr(berValues[m], controlPtr, false);
+ tempPtr = (IntPtr)((long)attributes[i].values + Marshal.SizeOf(typeof(IntPtr)) * m);
+ Marshal.WriteIntPtr(tempPtr, controlPtr);
+ }
+ tempPtr = (IntPtr)((long)attributes[i].values + Marshal.SizeOf(typeof(IntPtr)) * m);
+ Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
+ }
+ }
+
+ return attributes;
+ }
+
+ internal DirectoryResponse ConstructResponse(int messageId, LdapOperation operation, ResultAll resultType, TimeSpan requestTimeOut, bool exceptionOnTimeOut)
+ {
+ int error;
+ LDAP_TIMEVAL timeout = new LDAP_TIMEVAL();
+ timeout.tv_sec = (int)(requestTimeOut.Ticks / TimeSpan.TicksPerSecond);
+ IntPtr ldapResult = (IntPtr)0;
+ DirectoryResponse response = null;
+
+ IntPtr requestName = (IntPtr)0;
+ IntPtr requestValue = (IntPtr)0;
+
+ IntPtr entryMessage = (IntPtr)0;
+
+ bool needAbandon = true;
+
+ // processing for the partial results retrieval
+ if (resultType != ResultAll.LDAP_MSG_ALL)
+ {
+ // we need to have 0 timeout as we are polling for the results and don't want to wait
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ if (resultType == ResultAll.LDAP_MSG_POLLINGALL)
+ resultType = ResultAll.LDAP_MSG_ALL;
+
+ // when doing partial results retrieving, if ldap_result failed, we don't do ldap_abandon here.
+ needAbandon = false;
+ }
+
+ error = Wldap32.ldap_result(ldapHandle, messageId, (int)resultType, timeout, ref ldapResult);
+ if (error != -1 && error != 0)
+ {
+ // parsing the result
+ int serverError = 0;
+ try
+ {
+ int resulterror = 0;
+ string responseDn = null;
+ string responseMessage = null;
+ Uri[] responseReferral = null;
+ DirectoryControl[] responseControl = null;
+
+ // ldap_parse_result skips over messages of type LDAP_RES_SEARCH_ENTRY and LDAP_RES_SEARCH_REFERRAL
+ if (error != (int)LdapResult.LDAP_RES_SEARCH_ENTRY && error != (int)LdapResult.LDAP_RES_REFERRAL)
+ resulterror = ConstructParsedResult(ldapResult, ref serverError, ref responseDn, ref responseMessage, ref responseReferral, ref responseControl);
+
+ if (resulterror == 0)
+ {
+ resulterror = serverError;
+
+ if (error == (int)LdapResult.LDAP_RES_ADD)
+ response = new AddResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
+ else if (error == (int)LdapResult.LDAP_RES_MODIFY)
+ response = new ModifyResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
+ else if (error == (int)LdapResult.LDAP_RES_DELETE)
+ response = new DeleteResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
+ else if (error == (int)LdapResult.LDAP_RES_MODRDN)
+ response = new ModifyDNResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
+ else if (error == (int)LdapResult.LDAP_RES_COMPARE)
+ response = new CompareResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
+ else if (error == (int)LdapResult.LDAP_RES_EXTENDED)
+ {
+ 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*/);
+ if (resulterror == 0)
+ {
+ string name = null;
+ if (requestName != (IntPtr)0)
+ {
+ name = Marshal.PtrToStringUni(requestName);
+ }
+
+ berval val = null;
+ byte[] requestValueArray = null;
+ if (requestValue != (IntPtr)0)
+ {
+ val = new berval();
+ Marshal.PtrToStructure(requestValue, val);
+ if (val.bv_len != 0 && val.bv_val != (IntPtr)0)
+ {
+ requestValueArray = new byte[val.bv_len];
+ Marshal.Copy(val.bv_val, requestValueArray, 0, val.bv_len);
+ }
+ }
+
+ ((ExtendedResponse)response).name = name;
+ ((ExtendedResponse)response).value = requestValueArray;
+ }
+ }
+ }
+ else if (error == (int)LdapResult.LDAP_RES_SEARCH_RESULT ||
+ error == (int)LdapResult.LDAP_RES_SEARCH_ENTRY ||
+ error == (int)LdapResult.LDAP_RES_REFERRAL)
+ {
+ response = new SearchResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
+
+ //set the flag here so our partial result processor knows whether the search is done or not
+ if (error == (int)LdapResult.LDAP_RES_SEARCH_RESULT)
+ {
+ ((SearchResponse)response).searchDone = true;
+ }
+
+ SearchResultEntryCollection searchResultEntries = new SearchResultEntryCollection();
+ SearchResultReferenceCollection searchResultReferences = new SearchResultReferenceCollection();
+
+ // parsing the resultentry
+ entryMessage = Wldap32.ldap_first_entry(ldapHandle, ldapResult);
+
+ int entrycount = 0;
+ while (entryMessage != (IntPtr)0)
+ {
+ SearchResultEntry entry = ConstructEntry(entryMessage);
+ if (entry != null)
+ searchResultEntries.Add(entry);
+
+ entrycount++;
+ entryMessage = Wldap32.ldap_next_entry(ldapHandle, entryMessage);
+ }
+
+ // parsing the reference
+ IntPtr referenceMessage = Wldap32.ldap_first_reference(ldapHandle, ldapResult);
+
+ while (referenceMessage != (IntPtr)0)
+ {
+ SearchResultReference reference = ConstructReference(referenceMessage);
+ if (reference != null)
+ searchResultReferences.Add(reference);
+
+ referenceMessage = Wldap32.ldap_next_reference(ldapHandle, referenceMessage);
+ }
+
+ ((SearchResponse)response).SetEntries(searchResultEntries);
+ ((SearchResponse)response).SetReferences(searchResultReferences);
+ }
+
+ if (resulterror != (int)ResultCode.Success && resulterror != (int)ResultCode.CompareFalse && resulterror != (int)ResultCode.CompareTrue && resulterror != (int)ResultCode.Referral && resulterror != (int)ResultCode.ReferralV2)
+ {
+ // throw operation exception
+ if (Utility.IsResultCode((ResultCode)resulterror))
+ {
+ throw new DirectoryOperationException(response, OperationErrorMappings.MapResultCode(resulterror));
+ }
+ else
+ // should not occur
+ throw new DirectoryOperationException(response);
+ }
+
+ return response;
+ }
+ else
+ {
+ // fall over, throw the exception beow
+ error = resulterror;
+ }
+ }
+ finally
+ {
+ if (requestName != (IntPtr)0)
+ Wldap32.ldap_memfree(requestName);
+
+ if (requestValue != (IntPtr)0)
+ Wldap32.ldap_memfree(requestValue);
+
+ if (ldapResult != (IntPtr)0)
+ {
+ Wldap32.ldap_msgfree(ldapResult);
+ }
+ }
+ }
+ else
+ {
+ // ldap_result failed
+ if (error == 0)
+ {
+ if (exceptionOnTimeOut)
+ {
+ // client side timeout
+ error = (int)LdapError.TimeOut;
+ }
+ else
+ {
+ // if we don't throw exception on time out (notification search for example), we just return empty resposne
+ return null;
+ }
+ }
+ else
+ {
+ error = Wldap32.LdapGetLastError();
+ }
+
+ // abandon the request
+ if (needAbandon)
+ Wldap32.ldap_abandon(ldapHandle, messageId);
+ }
+
+ // throw proper exception here
+ throw ConstructException(error, operation);
+ }
+
+ internal unsafe int ConstructParsedResult(IntPtr ldapResult, ref int serverError, ref string responseDn, ref string responseMessage, ref Uri[] responseReferral, ref DirectoryControl[] responseControl)
+ {
+ IntPtr dn = (IntPtr)0;
+ IntPtr message = (IntPtr)0;
+ IntPtr referral = (IntPtr)0;
+ IntPtr control = (IntPtr)0;
+ int resulterror = 0;
+
+ try
+ {
+ resulterror = Wldap32.ldap_parse_result(ldapHandle, ldapResult, ref serverError, ref dn, ref message, ref referral, ref control, 0 /* not free it */);
+
+ if (resulterror == 0)
+ {
+ // parsing dn
+ responseDn = Marshal.PtrToStringUni(dn);
+
+ // parsing message
+ responseMessage = Marshal.PtrToStringUni(message);
+
+ // parsing referral
+ if (referral != (IntPtr)0)
+ {
+ char** tempPtr = (char**)referral;
+ char* singleReferral = tempPtr[0];
+ int i = 0;
+ ArrayList referralList = new ArrayList();
+ while (singleReferral != null)
+ {
+ string s = Marshal.PtrToStringUni((IntPtr)singleReferral);
+ referralList.Add(s);
+
+ i++;
+ singleReferral = tempPtr[i];
+ }
+
+ if (referralList.Count > 0)
+ {
+ responseReferral = new Uri[referralList.Count];
+ for (int j = 0; j < referralList.Count; j++)
+ responseReferral[j] = new Uri((string)referralList[j]);
+ }
+ }
+
+ // parsing control
+ if (control != (IntPtr)0)
+ {
+ int i = 0;
+ IntPtr tempControlPtr = control;
+ IntPtr singleControl = Marshal.ReadIntPtr(tempControlPtr, 0);
+ ArrayList controlList = new ArrayList();
+ while (singleControl != (IntPtr)0)
+ {
+ DirectoryControl directoryControl = ConstructControl(singleControl);
+ controlList.Add(directoryControl);
+
+ i++;
+ singleControl = Marshal.ReadIntPtr(tempControlPtr, i * Marshal.SizeOf(typeof(IntPtr)));
+ }
+
+ responseControl = new DirectoryControl[controlList.Count];
+ controlList.CopyTo(responseControl);
+ }
+ }
+ else
+ {
+ // 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 */);
+ if (tmpResult != 0)
+ {
+ resulterror = tmpResult;
+ }
+ }
+ }
+ }
+ finally
+ {
+ if (dn != (IntPtr)0)
+ {
+ Wldap32.ldap_memfree(dn);
+ }
+
+ if (message != (IntPtr)0)
+ Wldap32.ldap_memfree(message);
+
+ if (referral != (IntPtr)0)
+ Wldap32.ldap_value_free(referral);
+
+ if (control != (IntPtr)0)
+ Wldap32.ldap_controls_free(control);
+ }
+
+ return resulterror;
+ }
+
+ internal SearchResultEntry ConstructEntry(IntPtr entryMessage)
+ {
+ IntPtr dn = (IntPtr)0;
+ string entryDn = null;
+ IntPtr attribute = (IntPtr)0;
+ IntPtr address = (IntPtr)0;
+ SearchResultAttributeCollection attributes = null;
+
+ try
+ {
+ // get the dn
+ dn = Wldap32.ldap_get_dn(ldapHandle, entryMessage);
+ if (dn != (IntPtr)0)
+ {
+ entryDn = Marshal.PtrToStringUni(dn);
+ Wldap32.ldap_memfree(dn);
+ dn = (IntPtr)0;
+ }
+
+ SearchResultEntry resultEntry = new SearchResultEntry(entryDn);
+ attributes = resultEntry.Attributes;
+
+ // get attributes
+ attribute = Wldap32.ldap_first_attribute(ldapHandle, entryMessage, ref address);
+
+ int tempcount = 0;
+ while (attribute != (IntPtr)0)
+ {
+ DirectoryAttribute attr = ConstructAttribute(entryMessage, attribute);
+ attributes.Add(attr.Name, attr);
+
+ Wldap32.ldap_memfree(attribute);
+ tempcount++;
+ attribute = Wldap32.ldap_next_attribute(ldapHandle, entryMessage, address);
+ }
+
+ if (address != (IntPtr)0)
+ {
+ Wldap32.ber_free(address, 0);
+ address = (IntPtr)0;
+ }
+
+ return resultEntry;
+ }
+ finally
+ {
+ if (dn != (IntPtr)0)
+ {
+ Wldap32.ldap_memfree(dn);
+ }
+
+ if (attribute != (IntPtr)0)
+ Wldap32.ldap_memfree(attribute);
+
+ if (address != (IntPtr)0)
+ {
+ Wldap32.ber_free(address, 0);
+ }
+ }
+ }
+
+ internal DirectoryAttribute ConstructAttribute(IntPtr entryMessage, IntPtr attributeName)
+ {
+ DirectoryAttribute attribute = new DirectoryAttribute();
+ attribute.isSearchResult = true;
+
+ // get name
+ string name = Marshal.PtrToStringUni(attributeName);
+ attribute.Name = name;
+
+ // get values
+ IntPtr valuesArray = Wldap32.ldap_get_values_len(ldapHandle, entryMessage, name);
+ try
+ {
+ IntPtr tempPtr = (IntPtr)0;
+ int count = 0;
+ if (valuesArray != (IntPtr)0)
+ {
+ tempPtr = Marshal.ReadIntPtr(valuesArray, Marshal.SizeOf(typeof(IntPtr)) * count);
+ while (tempPtr != (IntPtr)0)
+ {
+ berval bervalue = new berval();
+ Marshal.PtrToStructure(tempPtr, bervalue);
+ byte[] byteArray = null;
+ if (bervalue.bv_len > 0 && bervalue.bv_val != (IntPtr)0)
+ {
+ byteArray = new byte[bervalue.bv_len];
+ Marshal.Copy(bervalue.bv_val, byteArray, 0, bervalue.bv_len);
+ attribute.Add(byteArray);
+ }
+
+ count++;
+ tempPtr = Marshal.ReadIntPtr(valuesArray, Marshal.SizeOf(typeof(IntPtr)) * count);
+ }
+ }
+ }
+ finally
+ {
+ if (valuesArray != (IntPtr)0)
+ Wldap32.ldap_value_free_len(valuesArray);
+ }
+
+ return attribute;
+ }
+
+ internal SearchResultReference ConstructReference(IntPtr referenceMessage)
+ {
+ SearchResultReference reference = null;
+ ArrayList referralList = new ArrayList();
+ Uri[] uris = null;
+ IntPtr referenceArray = (IntPtr)0;
+
+ int error = Wldap32.ldap_parse_reference(ldapHandle, referenceMessage, ref referenceArray);
+
+ try
+ {
+ if (error == 0)
+ {
+ IntPtr tempPtr = (IntPtr)0;
+ int count = 0;
+ if (referenceArray != (IntPtr)0)
+ {
+ tempPtr = Marshal.ReadIntPtr(referenceArray, Marshal.SizeOf(typeof(IntPtr)) * count);
+ while (tempPtr != (IntPtr)0)
+ {
+ string s = Marshal.PtrToStringUni(tempPtr);
+ referralList.Add(s);
+
+ count++;
+ tempPtr = Marshal.ReadIntPtr(referenceArray, Marshal.SizeOf(typeof(IntPtr)) * count);
+ }
+
+ Wldap32.ldap_value_free(referenceArray);
+ referenceArray = (IntPtr)0;
+ }
+
+ if (referralList.Count > 0)
+ {
+ uris = new Uri[referralList.Count];
+ for (int i = 0; i < referralList.Count; i++)
+ {
+ uris[i] = new Uri((string)referralList[i]);
+ }
+
+ reference = new SearchResultReference(uris);
+ }
+ }
+ }
+ finally
+ {
+ if (referenceArray != (IntPtr)0)
+ Wldap32.ldap_value_free(referenceArray);
+ }
+
+ return reference;
+ }
+
+ private DirectoryException ConstructException(int error, LdapOperation operation)
+ {
+ DirectoryResponse response = null;
+
+ if (Utility.IsResultCode((ResultCode)error))
+ {
+ if (operation == LdapOperation.LdapAdd)
+ response = new AddResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
+ else if (operation == LdapOperation.LdapModify)
+ response = new ModifyResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
+ else if (operation == LdapOperation.LdapDelete)
+ response = new DeleteResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
+ else if (operation == LdapOperation.LdapModifyDn)
+ response = new ModifyDNResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
+ else if (operation == LdapOperation.LdapCompare)
+ response = new CompareResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
+ else if (operation == LdapOperation.LdapSearch)
+ response = new SearchResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
+ else if (operation == LdapOperation.LdapExtendedRequest)
+ response = new ExtendedResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
+
+ string errorMessage = OperationErrorMappings.MapResultCode(error);
+ return new DirectoryOperationException(response, errorMessage);
+ }
+ else
+ {
+ if (Utility.IsLdapError((LdapError)error))
+ {
+ string errorMessage = LdapErrorMappings.MapResultCode(error);
+ string serverErrorMessage = _options.ServerErrorMessage;
+ if ((serverErrorMessage != null) && (serverErrorMessage.Length > 0))
+ {
+ throw new LdapException(error, errorMessage, serverErrorMessage);
+ }
+ else
+ {
+ return new LdapException(error, errorMessage);
+ }
+ }
+ else
+ return new LdapException(error);
+ }
+ }
+
+ private DirectoryControl ConstructControl(IntPtr controlPtr)
+ {
+ LdapControl control = new LdapControl();
+ Marshal.PtrToStructure(controlPtr, control);
+
+ Debug.Assert(control.ldctl_oid != (IntPtr)0);
+ string controlType = Marshal.PtrToStringUni(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);
+
+ bool criticality = control.ldctl_iscritical;
+
+ return new DirectoryControl(controlType, bytes, criticality, true);
+ }
+
+ private bool SameCredential(NetworkCredential oldCredential, NetworkCredential newCredential)
+ {
+ if (oldCredential == null && newCredential == null)
+ return true;
+ else if (oldCredential == null && newCredential != null)
+ return false;
+ else if (oldCredential != null && newCredential == null)
+ return false;
+ else
+ {
+ if (oldCredential.Domain == newCredential.Domain &&
+ oldCredential.UserName == newCredential.UserName &&
+ oldCredential.Password == newCredential.Password)
+ return true;
+ else
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapDirectoryIdentifier.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapDirectoryIdentifier.cs
new file mode 100644
index 0000000000..94b8574100
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapDirectoryIdentifier.cs
@@ -0,0 +1,104 @@
+// 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
+{
+ using System;
+
+ public class LdapDirectoryIdentifier : DirectoryIdentifier
+ {
+ private string[] _servers = null;
+ private bool _fullyQualifiedDnsHostName = false;
+ private bool _connectionless = false;
+ private int _portNumber = 389;
+
+ public LdapDirectoryIdentifier(string server) : this(server != null ? new string[] { server } : null, false, false)
+ {
+ }
+
+ public LdapDirectoryIdentifier(string server, int portNumber) : this(server != null ? new string[] { server } : null, portNumber, false, false)
+ {
+ }
+
+ public LdapDirectoryIdentifier(string server, bool fullyQualifiedDnsHostName, bool connectionless) : this(server != null ? new string[] { server } : null, fullyQualifiedDnsHostName, connectionless)
+ {
+ }
+
+ public LdapDirectoryIdentifier(string server, int portNumber, bool fullyQualifiedDnsHostName, bool connectionless) : this(server != null ? new string[] { server } : null, portNumber, fullyQualifiedDnsHostName, connectionless)
+ {
+ }
+
+ public LdapDirectoryIdentifier(string[] servers, bool fullyQualifiedDnsHostName, bool connectionless)
+ {
+ // validate the servers, we don't allow space in the server name
+ if (servers != null)
+ {
+ _servers = new string[servers.Length];
+ for (int i = 0; i < servers.Length; i++)
+ {
+ if (servers[i] != null)
+ {
+ string trimmedName = servers[i].Trim();
+ string[] result = trimmedName.Split(new char[] { ' ' });
+ if (result.Length > 1)
+ throw new ArgumentException(Res.GetString(Res.WhiteSpaceServerName));
+ _servers[i] = trimmedName;
+ }
+ }
+ }
+ _fullyQualifiedDnsHostName = fullyQualifiedDnsHostName;
+ _connectionless = connectionless;
+ }
+
+ public LdapDirectoryIdentifier(string[] servers, int portNumber, bool fullyQualifiedDnsHostName, bool connectionless) : this(servers, fullyQualifiedDnsHostName, connectionless)
+ {
+ _portNumber = portNumber;
+ }
+
+ public string[] Servers
+ {
+ get
+ {
+ if (_servers == null)
+ return new string[0];
+ else
+ {
+ string[] temporaryServers = new string[_servers.Length];
+ for (int i = 0; i < _servers.Length; i++)
+ {
+ if (_servers[i] != null)
+ temporaryServers[i] = String.Copy(_servers[i]);
+ else
+ temporaryServers[i] = null;
+ }
+ return temporaryServers;
+ }
+ }
+ }
+
+ public bool Connectionless
+ {
+ get
+ {
+ return _connectionless;
+ }
+ }
+
+ public bool FullyQualifiedDnsHostName
+ {
+ get
+ {
+ return _fullyQualifiedDnsHostName;
+ }
+ }
+
+ public int PortNumber
+ {
+ get
+ {
+ return _portNumber;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapException.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapException.cs
new file mode 100644
index 0000000000..0a888be847
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapException.cs
@@ -0,0 +1,191 @@
+// 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
+{
+ using System;
+ using System.Collections;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+
+ internal enum LdapError
+ {
+ IsLeaf = 0x23,
+ InvalidCredentials = 49,
+ ServerDown = 0x51,
+ LocalError = 0x52,
+ EncodingError = 0x53,
+ DecodingError = 0x54,
+ TimeOut = 0x55,
+ AuthUnknown = 0x56,
+ FilterError = 0x57,
+ UserCancelled = 0x58,
+ ParameterError = 0x59,
+ NoMemory = 0x5a,
+ ConnectError = 0x5b,
+ NotSupported = 0x5c,
+ NoResultsReturned = 0x5e,
+ ControlNotFound = 0x5d,
+ MoreResults = 0x5f,
+ ClientLoop = 0x60,
+ ReferralLimitExceeded = 0x61,
+ SendTimeOut = 0x70
+ }
+
+ internal class LdapErrorMappings
+ {
+ private static Hashtable s_resultCodeHash = null;
+
+ static LdapErrorMappings()
+ {
+ s_resultCodeHash = new Hashtable();
+
+ s_resultCodeHash.Add(LdapError.IsLeaf, Res.GetString(Res.LDAP_IS_LEAF));
+ s_resultCodeHash.Add(LdapError.InvalidCredentials, Res.GetString(Res.LDAP_INVALID_CREDENTIALS));
+ s_resultCodeHash.Add(LdapError.ServerDown, Res.GetString(Res.LDAP_SERVER_DOWN));
+ s_resultCodeHash.Add(LdapError.LocalError, Res.GetString(Res.LDAP_LOCAL_ERROR));
+ s_resultCodeHash.Add(LdapError.EncodingError, Res.GetString(Res.LDAP_ENCODING_ERROR));
+ s_resultCodeHash.Add(LdapError.DecodingError, Res.GetString(Res.LDAP_DECODING_ERROR));
+ s_resultCodeHash.Add(LdapError.TimeOut, Res.GetString(Res.LDAP_TIMEOUT));
+ s_resultCodeHash.Add(LdapError.AuthUnknown, Res.GetString(Res.LDAP_AUTH_UNKNOWN));
+ s_resultCodeHash.Add(LdapError.FilterError, Res.GetString(Res.LDAP_FILTER_ERROR));
+ s_resultCodeHash.Add(LdapError.UserCancelled, Res.GetString(Res.LDAP_USER_CANCELLED));
+ s_resultCodeHash.Add(LdapError.ParameterError, Res.GetString(Res.LDAP_PARAM_ERROR));
+ s_resultCodeHash.Add(LdapError.NoMemory, Res.GetString(Res.LDAP_NO_MEMORY));
+ s_resultCodeHash.Add(LdapError.ConnectError, Res.GetString(Res.LDAP_CONNECT_ERROR));
+ s_resultCodeHash.Add(LdapError.NotSupported, Res.GetString(Res.LDAP_NOT_SUPPORTED));
+ s_resultCodeHash.Add(LdapError.NoResultsReturned, Res.GetString(Res.LDAP_NO_RESULTS_RETURNED));
+ s_resultCodeHash.Add(LdapError.ControlNotFound, Res.GetString(Res.LDAP_CONTROL_NOT_FOUND));
+ s_resultCodeHash.Add(LdapError.MoreResults, Res.GetString(Res.LDAP_MORE_RESULTS_TO_RETURN));
+ s_resultCodeHash.Add(LdapError.ClientLoop, Res.GetString(Res.LDAP_CLIENT_LOOP));
+ s_resultCodeHash.Add(LdapError.ReferralLimitExceeded, Res.GetString(Res.LDAP_REFERRAL_LIMIT_EXCEEDED));
+ s_resultCodeHash.Add(LdapError.SendTimeOut, Res.GetString(Res.LDAP_SEND_TIMEOUT));
+ }
+
+ /// <summary>
+ /// This function maps a string containing a DSML v2 errorResult into a LDAPResultCode.
+ /// </summary>
+ static public string MapResultCode(int errorCode)
+ {
+ return (string)s_resultCodeHash[(LdapError)errorCode];
+ }
+ }
+
+ [Serializable]
+ public class LdapException : DirectoryException, ISerializable
+ {
+ private int _errorCode;
+ private string _serverErrorMessage;
+ internal PartialResultsCollection results = new PartialResultsCollection();
+ protected LdapException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+
+ public LdapException() : base() { }
+
+ public LdapException(string message) : base(message) { }
+
+ public LdapException(string message, Exception inner) : base(message, inner) { }
+
+ public LdapException(int errorCode) : base(Res.GetString(Res.DefaultLdapError))
+ {
+ _errorCode = errorCode;
+ }
+
+ public LdapException(int errorCode, string message) : base(message)
+ {
+ _errorCode = errorCode;
+ }
+
+ public LdapException(int errorCode, string message, string serverErrorMessage) : base(message)
+ {
+ _errorCode = errorCode;
+ _serverErrorMessage = serverErrorMessage;
+ }
+
+ public LdapException(int errorCode, string message, Exception inner) : base(message, inner)
+ {
+ _errorCode = errorCode;
+ }
+
+ public int ErrorCode
+ {
+ get
+ {
+ return _errorCode;
+ }
+ }
+
+ public string ServerErrorMessage
+ {
+ get
+ {
+ return _serverErrorMessage;
+ }
+ }
+
+ public PartialResultsCollection PartialResults
+ {
+ get
+ {
+ return this.results;
+ }
+ }
+
+ [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ }
+ }
+
+ [Serializable]
+ public class TlsOperationException : DirectoryOperationException
+ {
+ protected TlsOperationException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+
+ public TlsOperationException() : base() { }
+
+ public TlsOperationException(string message) : base(message) { }
+
+ public TlsOperationException(string message, Exception inner) : base(message, inner) { }
+
+ public TlsOperationException(DirectoryResponse response) : base(response)
+ {
+ }
+
+ public TlsOperationException(DirectoryResponse response, string message) : base(response, message)
+ {
+ }
+
+ public TlsOperationException(DirectoryResponse response, string message, Exception inner) : base(response, message, inner)
+ {
+ }
+ }
+
+ internal class ErrorChecking
+ {
+ public static void CheckAndSetLdapError(int error)
+ {
+ string errorMessage;
+ if (error != (int)ResultCode.Success)
+ {
+ if (Utility.IsResultCode((ResultCode)error))
+ {
+ errorMessage = OperationErrorMappings.MapResultCode(error);
+ throw new DirectoryOperationException(null, errorMessage);
+ }
+ else if (Utility.IsLdapError((LdapError)error))
+ {
+ errorMessage = LdapErrorMappings.MapResultCode(error);
+ throw new LdapException(error, errorMessage);
+ }
+ else
+ throw new LdapException(error);
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapPartialResultsProcessor.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapPartialResultsProcessor.cs
new file mode 100644
index 0000000000..4418bc5e21
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapPartialResultsProcessor.cs
@@ -0,0 +1,354 @@
+// 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
+{
+ using System;
+ using System.Threading;
+ using System.Collections;
+ using System.Diagnostics;
+
+ internal class LdapPartialResultsProcessor
+ {
+ private ArrayList _resultList = null;
+ private ManualResetEvent _workThreadWaitHandle = null;
+ private bool _workToDo = false;
+ private int _currentIndex = 0;
+
+ internal LdapPartialResultsProcessor(ManualResetEvent eventHandle)
+ {
+ _resultList = new ArrayList();
+ _workThreadWaitHandle = eventHandle;
+ }
+
+ public void Add(LdapPartialAsyncResult asyncResult)
+ {
+ lock (this)
+ {
+ _resultList.Add(asyncResult);
+
+ if (!_workToDo)
+ {
+ // need to wake up the workthread if it is not running already
+ _workThreadWaitHandle.Set();
+ _workToDo = true;
+ }
+ }
+ }
+
+ public void Remove(LdapPartialAsyncResult asyncResult)
+ {
+ // called by Abort operation
+ lock (this)
+ {
+ if (!_resultList.Contains(asyncResult))
+ throw new ArgumentException(Res.GetString(Res.InvalidAsyncResult));
+
+ // remove this async operation from the list
+ _resultList.Remove(asyncResult);
+ }
+ }
+
+ public void RetrievingSearchResults()
+ {
+ int count = 0;
+ int i = 0;
+ LdapPartialAsyncResult asyncResult = null;
+ AsyncCallback tmpCallback = null;
+
+ lock (this)
+ {
+ count = _resultList.Count;
+
+ if (count == 0)
+ {
+ // no asynchronous operation pending, begin to wait
+ _workThreadWaitHandle.Reset();
+ _workToDo = false;
+ return;
+ }
+
+ // might have work to do
+ while (true)
+ {
+ if (_currentIndex >= count)
+ {
+ // some element is moved after last iteration
+ _currentIndex = 0;
+ }
+
+ asyncResult = (LdapPartialAsyncResult)_resultList[_currentIndex];
+ i++;
+ _currentIndex++;
+
+ // have work to do
+ if (asyncResult.resultStatus != ResultsStatus.Done)
+ break;
+
+ if (i >= count)
+ {
+ // all the operations are done just waiting for the user to pick up the results
+ _workToDo = false;
+ _workThreadWaitHandle.Reset();
+ return;
+ }
+ }
+
+ // try to get the results availabe for this asynchronous operation
+ GetResultsHelper(asyncResult);
+
+ // if we are done with the asynchronous search, we need to fire callback and signal the waitable object
+ if (asyncResult.resultStatus == ResultsStatus.Done)
+ {
+ asyncResult.manualResetEvent.Set();
+ asyncResult.completed = true;
+ if (asyncResult.callback != null)
+ {
+ tmpCallback = asyncResult.callback;
+ }
+ }
+ else if (asyncResult.callback != null && asyncResult.partialCallback)
+ {
+ // if user specify callback to be called even when partial results become available
+ if (asyncResult.response != null && (asyncResult.response.Entries.Count > 0 || asyncResult.response.References.Count > 0))
+ {
+ tmpCallback = asyncResult.callback;
+ }
+ }
+ }
+
+ if (tmpCallback != null)
+ tmpCallback((IAsyncResult)asyncResult);
+ }
+
+ private void GetResultsHelper(LdapPartialAsyncResult asyncResult)
+ {
+ LdapConnection con = asyncResult.con;
+ IntPtr ldapResult = (IntPtr)0;
+ IntPtr entryMessage = (IntPtr)0;
+ ResultAll resultType = ResultAll.LDAP_MSG_RECEIVED;
+
+ if (asyncResult.resultStatus == ResultsStatus.CompleteResult)
+ resultType = ResultAll.LDAP_MSG_POLLINGALL;
+
+ try
+ {
+ SearchResponse response = (SearchResponse)con.ConstructResponse(asyncResult.messageID, LdapOperation.LdapSearch, resultType, asyncResult.requestTimeout, false);
+ // this should only happen in the polling thread case
+ if (response == null)
+ {
+ // only when request time out has not yet expiered
+ if ((asyncResult.startTime.Ticks + asyncResult.requestTimeout.Ticks) > DateTime.Now.Ticks)
+ {
+ // this is expected, just the client does not have the result yet
+ return;
+ }
+ else
+ {
+ // time out, now we need to throw proper exception
+ throw new LdapException((int)LdapError.TimeOut, LdapErrorMappings.MapResultCode((int)LdapError.TimeOut));
+ }
+ }
+
+ if (asyncResult.response != null)
+ AddResult(asyncResult.response, response);
+ else
+ asyncResult.response = response;
+
+ // if search is done, set the flag
+ if (response.searchDone)
+ asyncResult.resultStatus = ResultsStatus.Done;
+ }
+ catch (Exception e)
+ {
+ if (e is DirectoryOperationException)
+ {
+ SearchResponse response = (SearchResponse)(((DirectoryOperationException)e).Response);
+
+ if (asyncResult.response != null)
+ AddResult(asyncResult.response, response);
+ else
+ asyncResult.response = response;
+
+ // set the response back to the exception so it holds all the results up to now
+ ((DirectoryOperationException)e).response = asyncResult.response;
+ }
+ else if (e is LdapException)
+ {
+ LdapException ldapE = (LdapException)e;
+ LdapError errorCode = (LdapError)ldapE.ErrorCode;
+
+ if (asyncResult.response != null)
+ {
+ // add previous retrieved entries if available
+ if (asyncResult.response.Entries != null)
+ {
+ for (int i = 0; i < asyncResult.response.Entries.Count; i++)
+ {
+ ldapE.results.Add(asyncResult.response.Entries[i]);
+ }
+ }
+
+ // add previous retrieved references if available
+ if (asyncResult.response.References != null)
+ {
+ for (int i = 0; i < asyncResult.response.References.Count; i++)
+ {
+ ldapE.results.Add(asyncResult.response.References[i]);
+ }
+ }
+ }
+ }
+
+ // exception occurs, this operation is done.
+ asyncResult.exception = e;
+ asyncResult.resultStatus = ResultsStatus.Done;
+
+ // need to abandon this request
+ Wldap32.ldap_abandon(con.ldapHandle, asyncResult.messageID);
+ }
+ }
+
+ public void NeedCompleteResult(LdapPartialAsyncResult asyncResult)
+ {
+ lock (this)
+ {
+ if (_resultList.Contains(asyncResult))
+ {
+ // we don't need partial results anymore, polling for complete results
+ if (asyncResult.resultStatus == ResultsStatus.PartialResult)
+ asyncResult.resultStatus = ResultsStatus.CompleteResult;
+ }
+ else
+ throw new ArgumentException(Res.GetString(Res.InvalidAsyncResult));
+ }
+ }
+
+ public PartialResultsCollection GetPartialResults(LdapPartialAsyncResult asyncResult)
+ {
+ lock (this)
+ {
+ if (!_resultList.Contains(asyncResult))
+ throw new ArgumentException(Res.GetString(Res.InvalidAsyncResult));
+
+ if (asyncResult.exception != null)
+ {
+ // remove this async operation
+
+ // the async operation basically failed, we won't do it any more, so throw exception to the user and remove it from the list
+ _resultList.Remove(asyncResult);
+ throw asyncResult.exception;
+ }
+
+ PartialResultsCollection collection = new PartialResultsCollection();
+
+ if (asyncResult.response != null)
+ {
+ if (asyncResult.response.Entries != null)
+ {
+ for (int i = 0; i < asyncResult.response.Entries.Count; i++)
+ collection.Add(asyncResult.response.Entries[i]);
+
+ asyncResult.response.Entries.Clear();
+ }
+
+ if (asyncResult.response.References != null)
+ {
+ for (int i = 0; i < asyncResult.response.References.Count; i++)
+ collection.Add(asyncResult.response.References[i]);
+
+ asyncResult.response.References.Clear();
+ }
+ }
+
+ return collection;
+ }
+ }
+
+ public DirectoryResponse GetCompleteResult(LdapPartialAsyncResult asyncResult)
+ {
+ lock (this)
+ {
+ if (!_resultList.Contains(asyncResult))
+ throw new ArgumentException(Res.GetString(Res.InvalidAsyncResult));
+
+ Debug.Assert(asyncResult.resultStatus == ResultsStatus.Done);
+
+ _resultList.Remove(asyncResult);
+
+ if (asyncResult.exception != null)
+ {
+ throw asyncResult.exception;
+ }
+ else
+ {
+ return asyncResult.response;
+ }
+ }
+ }
+
+ private void AddResult(SearchResponse partialResults, SearchResponse newResult)
+ {
+ if (newResult == null)
+ return;
+
+ if (newResult.Entries != null)
+ {
+ for (int i = 0; i < newResult.Entries.Count; i++)
+ {
+ partialResults.Entries.Add(newResult.Entries[i]);
+ }
+ }
+
+ if (newResult.References != null)
+ {
+ for (int i = 0; i < newResult.References.Count; i++)
+ {
+ partialResults.References.Add(newResult.References[i]);
+ }
+ }
+ }
+ }
+
+ internal class PartialResultsRetriever
+ {
+ private ManualResetEvent _workThreadWaitHandle = null;
+ private Thread _oThread = null;
+ private LdapPartialResultsProcessor _processor = null;
+ internal PartialResultsRetriever(ManualResetEvent eventHandle, LdapPartialResultsProcessor processor)
+ {
+ _workThreadWaitHandle = eventHandle;
+ _processor = processor;
+ _oThread = new Thread(new ThreadStart(ThreadRoutine));
+ _oThread.IsBackground = true;
+
+ // start the thread
+ _oThread.Start();
+ }
+
+ private void ThreadRoutine()
+ {
+ while (true)
+ {
+ // make sure there is work to do
+ _workThreadWaitHandle.WaitOne();
+
+ // do the real work
+ try
+ {
+ _processor.RetrievingSearchResults();
+ }
+ catch (Exception e)
+ {
+ // we catch the exception here as we don't really want our worker thread to die because it
+ // encounter certain exception when processing a single async operation.
+ Debug.WriteLine(e.Message);
+ }
+
+ // Voluntarily gives up the CPU time
+ Thread.Sleep(250);
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs
new file mode 100644
index 0000000000..bfaa4fac36
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs
@@ -0,0 +1,1266 @@
+// 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
+{
+ using System;
+ using System.Net;
+ using System.Security.Cryptography.X509Certificates;
+ using System.ComponentModel;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Text;
+ using System.Diagnostics;
+ using System.Security.Authentication;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+
+ public delegate LdapConnection QueryForConnectionCallback(LdapConnection primaryConnection, LdapConnection referralFromConnection, string newDistinguishedName, LdapDirectoryIdentifier identifier, NetworkCredential credential, long currentUserToken);
+ public delegate bool NotifyOfNewConnectionCallback(LdapConnection primaryConnection, LdapConnection referralFromConnection, string newDistinguishedName, LdapDirectoryIdentifier identifier, LdapConnection newConnection, NetworkCredential credential, long currentUserToken, int errorCodeFromBind);
+ public delegate void DereferenceConnectionCallback(LdapConnection primaryConnection, LdapConnection connectionToDereference);
+ public delegate X509Certificate QueryClientCertificateCallback(LdapConnection connection, byte[][] trustedCAs);
+ public delegate bool VerifyServerCertificateCallback(LdapConnection connection, X509Certificate certificate);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate int QUERYFORCONNECTIONInternal(IntPtr Connection, IntPtr ReferralFromConnection, IntPtr NewDNPtr, string HostName, int PortNumber, SEC_WINNT_AUTH_IDENTITY_EX SecAuthIdentity, Luid CurrentUserToken, ref IntPtr ConnectionToUse);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate bool NOTIFYOFNEWCONNECTIONInternal(IntPtr Connection, IntPtr ReferralFromConnection, IntPtr NewDNPtr, string HostName, IntPtr NewConnection, int PortNumber, SEC_WINNT_AUTH_IDENTITY_EX SecAuthIdentity, Luid CurrentUser, int ErrorCodeFromBind);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate int DEREFERENCECONNECTIONInternal(IntPtr Connection, IntPtr ConnectionToDereference);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate bool VERIFYSERVERCERT(IntPtr Connection, IntPtr pServerCert);
+
+ [Flags]
+ public enum LocatorFlags : long
+ {
+ None = 0,
+ ForceRediscovery = 0x00000001,
+ DirectoryServicesRequired = 0x00000010,
+ DirectoryServicesPreferred = 0x00000020,
+ GCRequired = 0x00000040,
+ PdcRequired = 0x00000080,
+ IPRequired = 0x00000200,
+ KdcRequired = 0x00000400,
+ TimeServerRequired = 0x00000800,
+ WriteableRequired = 0x00001000,
+ GoodTimeServerPreferred = 0x00002000,
+ AvoidSelf = 0x00004000,
+ OnlyLdapNeeded = 0x00008000,
+ IsFlatName = 0x00010000,
+ IsDnsName = 0x00020000,
+ ReturnDnsName = 0x40000000,
+ ReturnFlatName = 0x80000000,
+ }
+
+ public enum SecurityProtocol
+ {
+ Pct1Server = 0x1,
+ Pct1Client = 0x2,
+ Ssl2Server = 0x4,
+ Ssl2Client = 0x8,
+ Ssl3Server = 0x10,
+ Ssl3Client = 0x20,
+ Tls1Server = 0x40,
+ Tls1Client = 0x80
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public class SecurityPackageContextConnectionInformation
+ {
+ private SecurityProtocol _securityProtocol;
+ private CipherAlgorithmType _identifier;
+ private int _strength;
+ private HashAlgorithmType _hashAlgorithm;
+ private int _hashStrength;
+ private int _keyExchangeAlgorithm;
+ private int _exchangeStrength;
+
+ internal SecurityPackageContextConnectionInformation()
+ {
+ }
+
+ public SecurityProtocol Protocol
+ {
+ get
+ {
+ return _securityProtocol;
+ }
+ }
+
+ public CipherAlgorithmType AlgorithmIdentifier
+ {
+ get
+ {
+ return _identifier;
+ }
+ }
+
+ public int CipherStrength
+ {
+ get
+ {
+ return _strength;
+ }
+ }
+
+ public HashAlgorithmType Hash
+ {
+ get
+ {
+ return _hashAlgorithm;
+ }
+ }
+
+ public int HashStrength
+ {
+ get
+ {
+ return _hashStrength;
+ }
+ }
+
+ public int KeyExchangeAlgorithm
+ {
+ get
+ {
+ return _keyExchangeAlgorithm;
+ }
+ }
+
+ public int ExchangeStrength
+ {
+ get
+ {
+ return _exchangeStrength;
+ }
+ }
+ }
+
+ public sealed class ReferralCallback
+ {
+ private QueryForConnectionCallback _query;
+ private NotifyOfNewConnectionCallback _notify;
+ private DereferenceConnectionCallback _dereference;
+
+ public ReferralCallback()
+ {
+ Utility.CheckOSVersion();
+ }
+
+ public QueryForConnectionCallback QueryForConnection
+ {
+ get
+ {
+ return _query;
+ }
+ set
+ {
+ _query = value;
+ }
+ }
+
+ public NotifyOfNewConnectionCallback NotifyNewConnection
+ {
+ get
+ {
+ return _notify;
+ }
+ set
+ {
+ _notify = value;
+ }
+ }
+
+ public DereferenceConnectionCallback DereferenceConnection
+ {
+ get
+ {
+ return _dereference;
+ }
+ set
+ {
+ _dereference = value;
+ }
+ }
+ }
+
+ internal struct SecurityHandle
+ {
+ public IntPtr Lower;
+ public IntPtr Upper;
+ }
+
+ public class LdapSessionOptions
+ {
+ private LdapConnection _connection = null;
+ private ReferralCallback _callbackRoutine = new ReferralCallback();
+ internal QueryClientCertificateCallback clientCertificateDelegate = null;
+ private VerifyServerCertificateCallback _serverCertificateDelegate = null;
+
+ private QUERYFORCONNECTIONInternal _queryDelegate = null;
+ private NOTIFYOFNEWCONNECTIONInternal _notifiyDelegate = null;
+ private DEREFERENCECONNECTIONInternal _dereferenceDelegate = null;
+ private VERIFYSERVERCERT _serverCertificateRoutine = null;
+
+ internal LdapSessionOptions(LdapConnection connection)
+ {
+ _connection = connection;
+ _queryDelegate = new QUERYFORCONNECTIONInternal(ProcessQueryConnection);
+ _notifiyDelegate = new NOTIFYOFNEWCONNECTIONInternal(ProcessNotifyConnection);
+ _dereferenceDelegate = new DEREFERENCECONNECTIONInternal(ProcessDereferenceConnection);
+ _serverCertificateRoutine = new VERIFYSERVERCERT(ProcessServerCertificate);
+ }
+
+ public ReferralChasingOptions ReferralChasing
+ {
+ get
+ {
+ int result = GetIntValueHelper(LdapOption.LDAP_OPT_REFERRALS);
+
+ if (result == 1)
+ return ReferralChasingOptions.All;
+ else
+ return (ReferralChasingOptions)result;
+ }
+ set
+ {
+ if (((value) & (~ReferralChasingOptions.All)) != 0)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(ReferralChasingOptions));
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_REFERRALS, (int)value);
+ }
+ }
+
+ public bool SecureSocketLayer
+ {
+ get
+ {
+ int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_SSL);
+
+ if (outValue == 1)
+ return true;
+ else
+ return false;
+ }
+ set
+ {
+ int temp;
+ if (value)
+ temp = 1;
+ else
+ temp = 0;
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_SSL, temp);
+ }
+ }
+
+ public int ReferralHopLimit
+ {
+ get
+ {
+ return GetIntValueHelper(LdapOption.LDAP_OPT_REFERRAL_HOP_LIMIT);
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.ValidValue), "value");
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_REFERRAL_HOP_LIMIT, value);
+ }
+ }
+
+ public int ProtocolVersion
+ {
+ get
+ {
+ return GetIntValueHelper(LdapOption.LDAP_OPT_VERSION);
+ }
+ set
+ {
+ SetIntValueHelper(LdapOption.LDAP_OPT_VERSION, value);
+ }
+ }
+
+ public string HostName
+ {
+ get
+ {
+ return GetStringValueHelper(LdapOption.LDAP_OPT_HOST_NAME, false);
+ }
+ set
+ {
+ SetStringValueHelper(LdapOption.LDAP_OPT_HOST_NAME, value);
+ }
+ }
+
+ public string DomainName
+ {
+ get
+ {
+ return GetStringValueHelper(LdapOption.LDAP_OPT_DNSDOMAIN_NAME, true);
+ }
+ set
+ {
+ SetStringValueHelper(LdapOption.LDAP_OPT_DNSDOMAIN_NAME, value);
+ }
+ }
+
+ public LocatorFlags LocatorFlag
+ {
+ get
+ {
+ int result = GetIntValueHelper(LdapOption.LDAP_OPT_GETDSNAME_FLAGS);
+
+ return (LocatorFlags)result;
+ }
+ set
+ {
+ // we don't do validation to the dirsync flag here as underneath API does not check for it and we don't want to put
+ // unnecessary limitation on it.
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_GETDSNAME_FLAGS, (int)value);
+ }
+ }
+
+ public bool HostReachable
+ {
+ get
+ {
+ int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_HOST_REACHABLE);
+
+ if (outValue == 1)
+ return true;
+ else
+ return false;
+ }
+ }
+
+ public TimeSpan PingKeepAliveTimeout
+ {
+ get
+ {
+ int result = GetIntValueHelper(LdapOption.LDAP_OPT_PING_KEEP_ALIVE);
+ return new TimeSpan(result * TimeSpan.TicksPerSecond);
+ }
+ set
+ {
+ if (value < TimeSpan.Zero)
+ {
+ throw new ArgumentException(Res.GetString(Res.NoNegativeTime), "value");
+ }
+
+ // prevent integer overflow
+ if (value.TotalSeconds > Int32.MaxValue)
+ {
+ throw new ArgumentException(Res.GetString(Res.TimespanExceedMax), "value");
+ }
+
+ int seconds = (int)(value.Ticks / TimeSpan.TicksPerSecond);
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_PING_KEEP_ALIVE, (int)seconds);
+ }
+ }
+
+ public int PingLimit
+ {
+ get
+ {
+ return GetIntValueHelper(LdapOption.LDAP_OPT_PING_LIMIT);
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.ValidValue), "value");
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_PING_LIMIT, value);
+ }
+ }
+
+ public TimeSpan PingWaitTimeout
+ {
+ get
+ {
+ int result = GetIntValueHelper(LdapOption.LDAP_OPT_PING_WAIT_TIME);
+ return new TimeSpan(result * TimeSpan.TicksPerMillisecond);
+ }
+ set
+ {
+ if (value < TimeSpan.Zero)
+ {
+ throw new ArgumentException(Res.GetString(Res.NoNegativeTime), "value");
+ }
+
+ // prevent integer overflow
+ if (value.TotalMilliseconds > Int32.MaxValue)
+ {
+ throw new ArgumentException(Res.GetString(Res.TimespanExceedMax), "value");
+ }
+
+ int milliseconds = (int)(value.Ticks / TimeSpan.TicksPerMillisecond);
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_PING_WAIT_TIME, (int)milliseconds);
+ }
+ }
+
+ public bool AutoReconnect
+ {
+ get
+ {
+ int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_AUTO_RECONNECT);
+
+ if (outValue == 1)
+ return true;
+ else
+ return false;
+ }
+ set
+ {
+ int temp;
+ if (value)
+ temp = 1;
+ else
+ temp = 0;
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_AUTO_RECONNECT, temp);
+ }
+ }
+
+ public int SspiFlag
+ {
+ get
+ {
+ return GetIntValueHelper(LdapOption.LDAP_OPT_SSPI_FLAGS);
+ }
+ set
+ {
+ SetIntValueHelper(LdapOption.LDAP_OPT_SSPI_FLAGS, value);
+ }
+ }
+
+ public SecurityPackageContextConnectionInformation SslInformation
+ {
+ get
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ SecurityPackageContextConnectionInformation secInfo = new SecurityPackageContextConnectionInformation();
+ int error = Wldap32.ldap_get_option_secInfo(_connection.ldapHandle, LdapOption.LDAP_OPT_SSL_INFO, secInfo);
+ ErrorChecking.CheckAndSetLdapError(error);
+
+ return secInfo;
+ }
+ }
+
+ public object SecurityContext
+ {
+ get
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ SecurityHandle tempHandle = new SecurityHandle();
+
+ int error = Wldap32.ldap_get_option_sechandle(_connection.ldapHandle, LdapOption.LDAP_OPT_SECURITY_CONTEXT, ref tempHandle);
+ ErrorChecking.CheckAndSetLdapError(error);
+
+ return tempHandle;
+ }
+ }
+
+ public bool Signing
+ {
+ get
+ {
+ int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_SIGN);
+
+ if (outValue == 1)
+ return true;
+ else
+ return false;
+ }
+ set
+ {
+ int temp;
+ if (value)
+ temp = 1;
+ else
+ temp = 0;
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_SIGN, temp);
+ }
+ }
+
+ public bool Sealing
+ {
+ get
+ {
+ int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_ENCRYPT);
+
+ if (outValue == 1)
+ return true;
+ else
+ return false;
+ }
+ set
+ {
+ int temp;
+ if (value)
+ temp = 1;
+ else
+ temp = 0;
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_ENCRYPT, temp);
+ }
+ }
+
+ public string SaslMethod
+ {
+ get
+ {
+ return GetStringValueHelper(LdapOption.LDAP_OPT_SASL_METHOD, true);
+ }
+ set
+ {
+ SetStringValueHelper(LdapOption.LDAP_OPT_SASL_METHOD, value);
+ }
+ }
+
+ public bool RootDseCache
+ {
+ get
+ {
+ int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_ROOTDSE_CACHE);
+
+ if (outValue == 1)
+ return true;
+ else
+ return false;
+ }
+ set
+ {
+ int temp;
+ if (value)
+ temp = 1;
+ else
+ temp = 0;
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_ROOTDSE_CACHE, temp);
+ }
+ }
+
+ public bool TcpKeepAlive
+ {
+ get
+ {
+ int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_TCP_KEEPALIVE);
+
+ if (outValue == 1)
+ return true;
+ else
+ return false;
+ }
+ set
+ {
+ int temp;
+ if (value)
+ temp = 1;
+ else
+ temp = 0;
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_TCP_KEEPALIVE, temp);
+ }
+ }
+
+ public TimeSpan SendTimeout
+ {
+ get
+ {
+ int result = GetIntValueHelper(LdapOption.LDAP_OPT_SEND_TIMEOUT);
+ return new TimeSpan(result * TimeSpan.TicksPerSecond);
+ }
+ set
+ {
+ if (value < TimeSpan.Zero)
+ {
+ throw new ArgumentException(Res.GetString(Res.NoNegativeTime), "value");
+ }
+
+ // prevent integer overflow
+ if (value.TotalSeconds > Int32.MaxValue)
+ {
+ throw new ArgumentException(Res.GetString(Res.TimespanExceedMax), "value");
+ }
+
+ int seconds = (int)(value.Ticks / TimeSpan.TicksPerSecond);
+
+ SetIntValueHelper(LdapOption.LDAP_OPT_SEND_TIMEOUT, (int)seconds);
+ }
+ }
+
+ public ReferralCallback ReferralCallback
+ {
+ get
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _callbackRoutine;
+ }
+ set
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ ReferralCallback tempCallback = new ReferralCallback();
+
+ if (value != null)
+ {
+ tempCallback.QueryForConnection = value.QueryForConnection;
+ tempCallback.NotifyNewConnection = value.NotifyNewConnection;
+ tempCallback.DereferenceConnection = value.DereferenceConnection;
+ }
+ else
+ {
+ tempCallback.QueryForConnection = null;
+ tempCallback.NotifyNewConnection = null;
+ tempCallback.DereferenceConnection = null;
+ }
+
+ ProcessCallBackRoutine(tempCallback);
+
+ // set the callback property
+ _callbackRoutine = value;
+ }
+ }
+
+ public QueryClientCertificateCallback QueryClientCertificate
+ {
+ get
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return clientCertificateDelegate;
+ }
+ set
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (value != null)
+ {
+ int certerror = Wldap32.ldap_set_option_clientcert(_connection.ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _connection.clientCertificateRoutine);
+ if (certerror != (int)ResultCode.Success)
+ {
+ if (Utility.IsLdapError((LdapError)certerror))
+ {
+ string certerrorMessage = LdapErrorMappings.MapResultCode(certerror);
+ throw new LdapException(certerror, certerrorMessage);
+ }
+ else
+ throw new LdapException(certerror);
+ }
+ // certificate callback is specified, automatic bind is disabled
+ _connection.automaticBind = false;
+ }
+ clientCertificateDelegate = value;
+ }
+ }
+
+ public VerifyServerCertificateCallback VerifyServerCertificate
+ {
+ get
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _serverCertificateDelegate;
+ }
+ set
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (value != null)
+ {
+ int error = Wldap32.ldap_set_option_servercert(_connection.ldapHandle, LdapOption.LDAP_OPT_SERVER_CERTIFICATE, _serverCertificateRoutine);
+ ErrorChecking.CheckAndSetLdapError(error);
+ }
+ _serverCertificateDelegate = value;
+ }
+ }
+
+ internal string ServerErrorMessage
+ {
+ get
+ {
+ return GetStringValueHelper(LdapOption.LDAP_OPT_SERVER_ERROR, true);
+ }
+ }
+
+ internal DereferenceAlias DerefAlias
+ {
+ get
+ {
+ return (DereferenceAlias)GetIntValueHelper(LdapOption.LDAP_OPT_DEREF);
+ }
+ set
+ {
+ SetIntValueHelper(LdapOption.LDAP_OPT_DEREF, (int)value);
+ }
+ }
+
+ internal bool FQDN
+ {
+ set
+ {
+ // set the value to true
+ SetIntValueHelper(LdapOption.LDAP_OPT_AREC_EXCLUSIVE, 1);
+ }
+ }
+
+ public void FastConcurrentBind()
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int inValue = 1;
+ // bump up the protocol version
+ ProtocolVersion = 3;
+ // do the fast concurrent bind
+ int error = Wldap32.ldap_set_option_int(_connection.ldapHandle, LdapOption.LDAP_OPT_FAST_CONCURRENT_BIND, ref inValue);
+ //we only throw PlatformNotSupportedException when we get parameter error and os is win2k3 below which does not support fast concurrent bind
+ if (error == (int)LdapError.ParameterError && !Utility.IsWin2k3AboveOS)
+ throw new PlatformNotSupportedException(Res.GetString(Res.ConcurrentBindNotSupport));
+ else
+ ErrorChecking.CheckAndSetLdapError(error);
+ }
+
+ public unsafe void StartTransportLayerSecurity(DirectoryControlCollection controls)
+ {
+ IntPtr serverControlArray = (IntPtr)0;
+ LdapControl[] managedServerControls = null;
+ IntPtr clientControlArray = (IntPtr)0;
+ LdapControl[] managedClientControls = null;
+ IntPtr ldapResult = (IntPtr)0;
+ IntPtr referral = (IntPtr)0;
+
+ int serverError = 0;
+ Uri[] responseReferral = null;
+
+ if (Utility.IsWin2kOS)
+ throw new PlatformNotSupportedException(Res.GetString(Res.TLSNotSupported));
+
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ IntPtr controlPtr = (IntPtr)0;
+ IntPtr tempPtr = (IntPtr)0;
+
+ // build server control
+ managedServerControls = _connection.BuildControlArray(controls, true);
+ int structSize = Marshal.SizeOf(typeof(LdapControl));
+ if (managedServerControls != null)
+ {
+ serverControlArray = Utility.AllocHGlobalIntPtrArray(managedServerControls.Length + 1);
+ for (int i = 0; i < managedServerControls.Length; i++)
+ {
+ controlPtr = Marshal.AllocHGlobal(structSize);
+ Marshal.StructureToPtr(managedServerControls[i], controlPtr, false);
+ tempPtr = (IntPtr)((long)serverControlArray + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, controlPtr);
+ }
+
+ tempPtr = (IntPtr)((long)serverControlArray + Marshal.SizeOf(typeof(IntPtr)) * managedServerControls.Length);
+ Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
+ }
+
+ // build client control
+ managedClientControls = _connection.BuildControlArray(controls, false);
+ if (managedClientControls != null)
+ {
+ clientControlArray = Utility.AllocHGlobalIntPtrArray(managedClientControls.Length + 1);
+ for (int i = 0; i < managedClientControls.Length; i++)
+ {
+ controlPtr = Marshal.AllocHGlobal(structSize);
+ Marshal.StructureToPtr(managedClientControls[i], controlPtr, false);
+ tempPtr = (IntPtr)((long)clientControlArray + Marshal.SizeOf(typeof(IntPtr)) * i);
+ Marshal.WriteIntPtr(tempPtr, controlPtr);
+ }
+ tempPtr = (IntPtr)((long)clientControlArray + Marshal.SizeOf(typeof(IntPtr)) * managedClientControls.Length);
+ Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
+ }
+
+ int error = Wldap32.ldap_start_tls(_connection.ldapHandle, ref serverError, ref ldapResult, serverControlArray, clientControlArray);
+ if (ldapResult != (IntPtr)0)
+ {
+ // parsing the referral
+ int resulterror = Wldap32.ldap_parse_result_referral(_connection.ldapHandle, ldapResult, (IntPtr)0, (IntPtr)0, (IntPtr)0, ref referral, (IntPtr)0, 0 /* not free it */);
+ if (resulterror == 0)
+ {
+ // parsing referral
+ if (referral != (IntPtr)0)
+ {
+ char** referralPtr = (char**)referral;
+ char* singleReferral = referralPtr[0];
+ int i = 0;
+ ArrayList referralList = new ArrayList();
+ while (singleReferral != null)
+ {
+ string s = Marshal.PtrToStringUni((IntPtr)singleReferral);
+ referralList.Add(s);
+
+ i++;
+ singleReferral = referralPtr[i];
+ }
+
+ // free heap memory
+ if (referral != (IntPtr)0)
+ {
+ Wldap32.ldap_value_free(referral);
+ referral = (IntPtr)0;
+ }
+
+ if (referralList.Count > 0)
+ {
+ responseReferral = new Uri[referralList.Count];
+ for (int j = 0; j < referralList.Count; j++)
+ responseReferral[j] = new Uri((string)referralList[j]);
+ }
+ }
+ }
+ }
+
+ if (error != (int)ResultCode.Success)
+ {
+ string errorMessage = Res.GetString(Res.DefaultLdapError);
+ if (Utility.IsResultCode((ResultCode)error))
+ {
+ //If the server failed request for whatever reason, the ldap_start_tls returns LDAP_OTHER
+ // and the ServerReturnValue will contain the error code from the server.
+ if (error == (int)ResultCode.Other)
+ error = serverError;
+
+ errorMessage = OperationErrorMappings.MapResultCode(error);
+ ExtendedResponse response = new ExtendedResponse(null, null, (ResultCode)error, errorMessage, responseReferral);
+ response.name = "1.3.6.1.4.1.1466.20037";
+ throw new TlsOperationException(response);
+ }
+ else if (Utility.IsLdapError((LdapError)error))
+ {
+ errorMessage = LdapErrorMappings.MapResultCode(error);
+ throw new LdapException(error, errorMessage);
+ }
+ }
+ }
+ finally
+ {
+ if (serverControlArray != (IntPtr)0)
+ {
+ //release the memory from the heap
+ for (int i = 0; i < managedServerControls.Length; i++)
+ {
+ IntPtr tempPtr = Marshal.ReadIntPtr(serverControlArray, Marshal.SizeOf(typeof(IntPtr)) * i);
+ if (tempPtr != (IntPtr)0)
+ Marshal.FreeHGlobal(tempPtr);
+ }
+ Marshal.FreeHGlobal(serverControlArray);
+ }
+
+ if (managedServerControls != null)
+ {
+ for (int i = 0; i < managedServerControls.Length; i++)
+ {
+ if (managedServerControls[i].ldctl_oid != (IntPtr)0)
+ Marshal.FreeHGlobal(managedServerControls[i].ldctl_oid);
+
+ if (managedServerControls[i].ldctl_value != null)
+ {
+ if (managedServerControls[i].ldctl_value.bv_val != (IntPtr)0)
+ Marshal.FreeHGlobal(managedServerControls[i].ldctl_value.bv_val);
+ }
+ }
+ }
+
+ if (clientControlArray != (IntPtr)0)
+ {
+ // release the memor from the heap
+ for (int i = 0; i < managedClientControls.Length; i++)
+ {
+ IntPtr tempPtr = Marshal.ReadIntPtr(clientControlArray, Marshal.SizeOf(typeof(IntPtr)) * i);
+ if (tempPtr != (IntPtr)0)
+ Marshal.FreeHGlobal(tempPtr);
+ }
+ Marshal.FreeHGlobal(clientControlArray);
+ }
+
+ if (managedClientControls != null)
+ {
+ for (int i = 0; i < managedClientControls.Length; i++)
+ {
+ if (managedClientControls[i].ldctl_oid != (IntPtr)0)
+ Marshal.FreeHGlobal(managedClientControls[i].ldctl_oid);
+
+ if (managedClientControls[i].ldctl_value != null)
+ {
+ if (managedClientControls[i].ldctl_value.bv_val != (IntPtr)0)
+ Marshal.FreeHGlobal(managedClientControls[i].ldctl_value.bv_val);
+ }
+ }
+ }
+
+ if (referral != (IntPtr)0)
+ Wldap32.ldap_value_free(referral);
+ }
+ }
+
+ public void StopTransportLayerSecurity()
+ {
+ if (Utility.IsWin2kOS)
+ throw new PlatformNotSupportedException(Res.GetString(Res.TLSNotSupported));
+
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ byte result = Wldap32.ldap_stop_tls(_connection.ldapHandle);
+ if (result == 0)
+ // caller needs to close this ldap connection
+ throw new TlsOperationException(null, Res.GetString(Res.TLSStopFailure));
+ }
+
+ private int GetIntValueHelper(LdapOption option)
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int outValue = 0;
+ int error = Wldap32.ldap_get_option_int(_connection.ldapHandle, option, ref outValue);
+
+ ErrorChecking.CheckAndSetLdapError(error);
+ return outValue;
+ }
+
+ private void SetIntValueHelper(LdapOption option, int value)
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int temp = value;
+ int error = Wldap32.ldap_set_option_int(_connection.ldapHandle, option, ref temp);
+
+ ErrorChecking.CheckAndSetLdapError(error);
+ }
+
+ private string GetStringValueHelper(LdapOption option, bool releasePtr)
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ IntPtr outValue = new IntPtr(0);
+ int error = Wldap32.ldap_get_option_ptr(_connection.ldapHandle, option, ref outValue);
+ ErrorChecking.CheckAndSetLdapError(error);
+
+ string s = null;
+ if (outValue != (IntPtr)0)
+ s = Marshal.PtrToStringUni(outValue);
+
+ if (releasePtr)
+ Wldap32.ldap_memfree(outValue);
+
+ return s;
+ }
+
+ private void SetStringValueHelper(LdapOption option, string value)
+ {
+ if (_connection.disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ IntPtr inValue = new IntPtr(0);
+ if (value != null)
+ {
+ inValue = Marshal.StringToHGlobalUni(value);
+ }
+
+ try
+ {
+ int error = Wldap32.ldap_set_option_ptr(_connection.ldapHandle, option, ref inValue);
+ ErrorChecking.CheckAndSetLdapError(error);
+ }
+ finally
+ {
+ if (inValue != (IntPtr)0)
+ Marshal.FreeHGlobal(inValue);
+ }
+ }
+
+ private void ProcessCallBackRoutine(ReferralCallback tempCallback)
+ {
+ LdapReferralCallback value = new LdapReferralCallback();
+ value.sizeofcallback = Marshal.SizeOf(typeof(LdapReferralCallback));
+ value.query = tempCallback.QueryForConnection == null ? null : _queryDelegate;
+ value.notify = tempCallback.NotifyNewConnection == null ? null : _notifiyDelegate;
+ value.dereference = tempCallback.DereferenceConnection == null ? null : _dereferenceDelegate;
+
+ int error = Wldap32.ldap_set_option_referral(_connection.ldapHandle, LdapOption.LDAP_OPT_REFERRAL_CALLBACK, ref value);
+ ErrorChecking.CheckAndSetLdapError(error);
+ }
+
+ private int ProcessQueryConnection(IntPtr PrimaryConnection, IntPtr ReferralFromConnection, IntPtr NewDNPtr, string HostName, int PortNumber, SEC_WINNT_AUTH_IDENTITY_EX SecAuthIdentity, Luid CurrentUserToken, ref IntPtr ConnectionToUse)
+ {
+ ConnectionToUse = IntPtr.Zero;
+ string NewDN = null;
+
+ // user must have registered callback function
+ Debug.Assert(_callbackRoutine.QueryForConnection != null);
+
+ // user registers the QUERYFORCONNECTION callback
+ if (_callbackRoutine.QueryForConnection != null)
+ {
+ if (NewDNPtr != (IntPtr)0)
+ NewDN = Marshal.PtrToStringUni(NewDNPtr);
+ StringBuilder target = new StringBuilder();
+ target.Append(HostName);
+ target.Append(":");
+ target.Append(PortNumber);
+ LdapDirectoryIdentifier identifier = new LdapDirectoryIdentifier(target.ToString());
+ NetworkCredential cred = ProcessSecAuthIdentity(SecAuthIdentity);
+ LdapConnection tempReferralConnection = null;
+ WeakReference reference = null;
+
+ // if referrafromconnection handle is valid
+ if (ReferralFromConnection != (IntPtr)0)
+ {
+ lock (LdapConnection.objectLock)
+ {
+ //make sure first whether we have saved it in the handle table before
+ reference = (WeakReference)(LdapConnection.handleTable[ReferralFromConnection]);
+ if (reference != null && reference.IsAlive)
+ {
+ // save this before and object has not been garbage collected yet.
+ tempReferralConnection = (LdapConnection)reference.Target;
+ }
+ else
+ {
+ if (reference != null)
+ {
+ // connection has been garbage collected, we need to remove this one
+ LdapConnection.handleTable.Remove(ReferralFromConnection);
+ }
+ // we don't have it yet, construct a new one
+ tempReferralConnection = new LdapConnection(((LdapDirectoryIdentifier)(_connection.Directory)), _connection.GetCredential(), _connection.AuthType, ReferralFromConnection);
+
+ // save it to the handle table
+ LdapConnection.handleTable.Add(ReferralFromConnection, new WeakReference(tempReferralConnection));
+ }
+ }
+ }
+
+ long tokenValue = (long)((uint)CurrentUserToken.LowPart + (((long)CurrentUserToken.HighPart) << 32));
+
+ LdapConnection con = _callbackRoutine.QueryForConnection(_connection, tempReferralConnection, NewDN, identifier, cred, tokenValue);
+ if (null != con && null != con.ldapHandle && !con.ldapHandle.IsInvalid)
+ {
+ bool success = AddLdapHandleRef(con);
+ if (success)
+ {
+ ConnectionToUse = con.ldapHandle.DangerousGetHandle();
+ }
+ }
+ return 0;
+ }
+ else
+ {
+ // user does not take ownership of the connection
+ return 1;
+ }
+ }
+
+ private bool ProcessNotifyConnection(IntPtr PrimaryConnection, IntPtr ReferralFromConnection, IntPtr NewDNPtr, string HostName, IntPtr NewConnection, int PortNumber, SEC_WINNT_AUTH_IDENTITY_EX SecAuthIdentity, Luid CurrentUser, int ErrorCodeFromBind)
+ {
+ string NewDN = null;
+ if (NewConnection != (IntPtr)0 && _callbackRoutine.NotifyNewConnection != null)
+ {
+ if (NewDNPtr != (IntPtr)0)
+ NewDN = Marshal.PtrToStringUni(NewDNPtr);
+ StringBuilder target = new StringBuilder();
+ target.Append(HostName);
+ target.Append(":");
+ target.Append(PortNumber);
+ LdapDirectoryIdentifier identifier = new LdapDirectoryIdentifier(target.ToString());
+ NetworkCredential cred = ProcessSecAuthIdentity(SecAuthIdentity);
+ LdapConnection tempNewConnection = null;
+ LdapConnection tempReferralConnection = null;
+ WeakReference reference = null;
+
+ lock (LdapConnection.objectLock)
+ {
+ // if referrafromconnection handle is valid
+ if (ReferralFromConnection != (IntPtr)0)
+ {
+ //check whether we have save it in the handle table before
+ reference = (WeakReference)(LdapConnection.handleTable[ReferralFromConnection]);
+ if (reference != null && reference.IsAlive && null != ((LdapConnection)reference.Target).ldapHandle)
+ {
+ // save this before and object has not been garbage collected yet.
+ tempReferralConnection = (LdapConnection)reference.Target;
+ }
+ else
+ {
+ // connection has been garbage collected, we need to remove this one
+ if (reference != null)
+ LdapConnection.handleTable.Remove(ReferralFromConnection);
+
+ // we don't have it yet, construct a new one
+ tempReferralConnection = new LdapConnection(((LdapDirectoryIdentifier)(_connection.Directory)), _connection.GetCredential(), _connection.AuthType, ReferralFromConnection);
+ // save it to the handle table
+ LdapConnection.handleTable.Add(ReferralFromConnection, new WeakReference(tempReferralConnection));
+ }
+ }
+
+ if (NewConnection != (IntPtr)0)
+ {
+ //check whether we have save it in the handle table before
+ reference = (WeakReference)(LdapConnection.handleTable[NewConnection]);
+ if (reference != null && reference.IsAlive && null != ((LdapConnection)reference.Target).ldapHandle)
+ {
+ // save this before and object has not been garbage collected yet.
+ tempNewConnection = (LdapConnection)reference.Target;
+ }
+ else
+ {
+ // connection has been garbage collected, we need to remove this one
+ if (reference != null)
+ LdapConnection.handleTable.Remove(NewConnection);
+
+ // we don't have it yet, construct a new one
+ tempNewConnection = new LdapConnection(identifier, cred, _connection.AuthType, NewConnection);
+ // save it to the handle table
+ LdapConnection.handleTable.Add(NewConnection, new WeakReference(tempNewConnection));
+ }
+ }
+ }
+ long tokenValue = (long)((uint)CurrentUser.LowPart + (((long)CurrentUser.HighPart) << 32));
+
+ bool value = _callbackRoutine.NotifyNewConnection(_connection, tempReferralConnection, NewDN, identifier, tempNewConnection, cred, tokenValue, ErrorCodeFromBind);
+
+ if (value)
+ {
+ value = AddLdapHandleRef(tempNewConnection);
+ if (value)
+ {
+ tempNewConnection.NeedDispose = true;
+ }
+ }
+ return value;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private int ProcessDereferenceConnection(IntPtr PrimaryConnection, IntPtr ConnectionToDereference)
+ {
+ if (ConnectionToDereference != (IntPtr)0 && _callbackRoutine.DereferenceConnection != null)
+ {
+ LdapConnection dereferenceConnection = null;
+ WeakReference reference = null;
+
+ // in most cases it should be in our table
+ lock (LdapConnection.objectLock)
+ {
+ reference = (WeakReference)(LdapConnection.handleTable[ConnectionToDereference]);
+ }
+
+ // not been added to the table before or it is garbage collected, we need to construct it
+ if (reference == null || !reference.IsAlive)
+ dereferenceConnection = new LdapConnection(((LdapDirectoryIdentifier)(_connection.Directory)), _connection.GetCredential(), _connection.AuthType, ConnectionToDereference);
+ else
+ {
+ dereferenceConnection = (LdapConnection)reference.Target;
+ ReleaseLdapHandleRef(dereferenceConnection);
+ }
+ _callbackRoutine.DereferenceConnection(_connection, dereferenceConnection);
+
+ // there is no need to remove the connection object from the handle table, as it will be removed automatically when
+ // connection object is disposed.
+ }
+
+ return 1;
+ }
+
+ private NetworkCredential ProcessSecAuthIdentity(SEC_WINNT_AUTH_IDENTITY_EX SecAuthIdentit)
+ {
+ if (SecAuthIdentit == null)
+ return new NetworkCredential();
+ else
+ {
+ string user = SecAuthIdentit.user;
+ string domain = SecAuthIdentit.domain;
+ string password = SecAuthIdentit.password;
+
+ return new NetworkCredential(user, password, domain);
+ }
+ }
+
+ private bool ProcessServerCertificate(IntPtr Connection, IntPtr pServerCert)
+ {
+ // if callback is not specified by user, it means server certificate is accepted
+ bool value = true;
+ if (_serverCertificateDelegate != null)
+ {
+ IntPtr certPtr = (IntPtr)0;
+ X509Certificate certificate = null;
+ try
+ {
+ Debug.Assert(pServerCert != (IntPtr)0);
+ certPtr = Marshal.ReadIntPtr(pServerCert);
+ certificate = new X509Certificate(certPtr);
+ }
+ finally
+ {
+ Wldap32.CertFreeCRLContext(certPtr);
+ }
+ value = _serverCertificateDelegate(_connection, certificate);
+ }
+ return value;
+ }
+
+ [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+ private static bool AddLdapHandleRef(LdapConnection ldapConnection)
+ {
+ bool success = false;
+ if (null != ldapConnection && null != ldapConnection.ldapHandle && !ldapConnection.ldapHandle.IsInvalid)
+ {
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try { }
+ finally
+ {
+ ldapConnection.ldapHandle.DangerousAddRef(ref success);
+ }
+ }
+ return success;
+ }
+
+ [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+ private static void ReleaseLdapHandleRef(LdapConnection ldapConnection)
+ {
+ if (null != ldapConnection && null != ldapConnection.ldapHandle && !ldapConnection.ldapHandle.IsInvalid)
+ {
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try { }
+ finally
+ {
+ ldapConnection.ldapHandle.DangerousRelease();
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs
new file mode 100644
index 0000000000..3771c40d38
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs
@@ -0,0 +1,108 @@
+// 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
+{
+ using System;
+ using Microsoft.Win32.SafeHandles;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics;
+ using System.Security;
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal sealed class BerSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ internal BerSafeHandle() : base(true)
+ {
+ SetHandle(Wldap32.ber_alloc(1));
+ if (handle == (IntPtr)0)
+ throw new OutOfMemoryException();
+ }
+
+ internal BerSafeHandle(berval value) : base(true)
+ {
+ SetHandle(Wldap32.ber_init(value));
+ if (handle == (IntPtr)0)
+ throw new BerConversionException();
+ }
+
+ override protected bool ReleaseHandle()
+ {
+ Wldap32.ber_free(handle, 1);
+ return true;
+ }
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ sealed internal class HGlobalMemHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ internal HGlobalMemHandle(IntPtr value) : base(true)
+ {
+ SetHandle(value);
+ }
+
+ override protected bool ReleaseHandle()
+ {
+ Marshal.FreeHGlobal(handle);
+ return true;
+ }
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ sealed internal class ConnectionHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ internal bool needDispose = false;
+ internal ConnectionHandle() : base(true)
+ {
+ SetHandle(Wldap32.ldap_init(null, 389));
+
+ if (handle == (IntPtr)0)
+ {
+ 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)0)
+ {
+ 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);
+ }
+ }
+ override protected bool ReleaseHandle()
+ {
+ if (handle != (IntPtr)0)
+ {
+ if (needDispose)
+ {
+ Wldap32.ldap_unbind(handle);
+ }
+ handle = (IntPtr)0;
+ }
+ return true;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs
new file mode 100644
index 0000000000..92994c19b7
--- /dev/null
+++ b/src/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs
@@ -0,0 +1,419 @@
+// 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
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Security;
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal class Luid
+ {
+ internal int lowPart;
+ internal int highPart;
+
+ internal Luid()
+ {
+ }
+
+ public int LowPart
+ {
+ get
+ {
+ return lowPart;
+ }
+ }
+
+ public int HighPart
+ {
+ get
+ {
+ return 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_SIMPLE = 0x80,
+ LDAP_AUTH_SASL = 0x83,
+ 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_ONE = 0,
+ 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)0;
+
+ public berval() { }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class SafeBerval
+ {
+ public int bv_len = 0;
+ public IntPtr bv_val = (IntPtr)0;
+
+ public SafeBerval() { }
+
+ ~SafeBerval()
+ {
+ if (bv_val != (IntPtr)0)
+ Marshal.FreeHGlobal(bv_val);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class LdapControl
+ {
+ public IntPtr ldctl_oid = (IntPtr)0;
+ 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)0;
+ public IntPtr values = (IntPtr)0;
+
+ public LdapMod() { }
+ ~LdapMod()
+ {
+ if (attribute != (IntPtr)0)
+ Marshal.FreeHGlobal(attribute);
+
+ if (values != (IntPtr)0)
+ Marshal.FreeHGlobal(values);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class LdapVlvInfo
+ {
+ private int _version = 1;
+ private int _beforeCount = 0;
+ private int _afterCount = 0;
+ private int _offset = 0;
+ private int _count = 0;
+ private IntPtr _attrvalue = (IntPtr)0;
+ private IntPtr _context = (IntPtr)0;
+ private IntPtr _extraData = (IntPtr)0;
+
+ public LdapVlvInfo(int version, int before, int after, int offset, int count, IntPtr attribute, IntPtr context)
+ {
+ _version = version;
+ _beforeCount = before;
+ _afterCount = after;
+ _offset = offset;
+ _count = count;
+ _attrvalue = attribute;
+ _context = context;
+ }
+ }
+
+ [
+ SuppressUnmanagedCodeSecurityAttribute()
+ ]
+ internal class Wldap32
+ {
+ 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("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_initW", SetLastError = true, CharSet = CharSet.Unicode)]
+ public static extern IntPtr ldap_init(string hostName, int portNumber);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_connect", CharSet = CharSet.Unicode)]
+ public static extern int ldap_connect([In] ConnectionHandle ldapHandle, LDAP_TIMEVAL timeout);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_unbind", CharSet = CharSet.Unicode)]
+ public static extern int ldap_unbind([In] IntPtr ldapHandle);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "LdapGetLastError")]
+ public static extern int LdapGetLastError();
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cldap_openW", SetLastError = true, CharSet = CharSet.Unicode)]
+ public static extern IntPtr cldap_open(string hostName, int portNumber);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_memfreeW", CharSet = CharSet.Unicode)]
+ public static extern void ldap_memfree([In] IntPtr value);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_freeW", CharSet = CharSet.Unicode)]
+ public static extern int ldap_value_free([In] IntPtr value);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_controls_freeW", CharSet = CharSet.Unicode)]
+ public static extern int ldap_controls_free([In] IntPtr value);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_abandon", CharSet = CharSet.Unicode)]
+ public static extern int ldap_abandon([In] ConnectionHandle ldapHandle, [In] int messagId);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_stop_tls_s", CharSet = CharSet.Unicode)]
+ public static extern byte ldap_stop_tls(ConnectionHandle ldapHandle);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_msgfree", CharSet = CharSet.Unicode)]
+ public static extern int ldap_msgfree([In] IntPtr result);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_entry", CharSet = CharSet.Unicode)]
+ public static extern IntPtr ldap_first_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_entry", CharSet = CharSet.Unicode)]
+ public static extern IntPtr ldap_next_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_reference", CharSet = CharSet.Unicode)]
+ public static extern IntPtr ldap_first_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_reference", CharSet = CharSet.Unicode)]
+ public static extern IntPtr ldap_next_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_dnW", CharSet = CharSet.Unicode)]
+ public static extern IntPtr ldap_get_dn([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_free", CharSet = CharSet.Unicode)]
+ public static extern IntPtr ber_free([In] IntPtr berelement, int option);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_free_len", CharSet = CharSet.Unicode)]
+ public static extern IntPtr ldap_value_free_len([In] IntPtr berelement);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_alloc_t", CharSet = CharSet.Unicode)]
+ public static extern IntPtr ber_alloc(int option);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
+ public static extern int ber_printf_emptyarg(BerSafeHandle berElement, string format);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
+ public static extern int ber_printf_int(BerSafeHandle berElement, string format, int value);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
+ public static extern int ber_printf_berarray(BerSafeHandle berElement, string format, IntPtr value);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_flatten", CharSet = CharSet.Unicode)]
+ public static extern int ber_flatten(BerSafeHandle berElement, ref IntPtr value);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_init", CharSet = CharSet.Unicode)]
+ public static extern IntPtr ber_init(berval value);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
+ public static extern int ber_scanf(BerSafeHandle berElement, string format);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
+ public static extern int ber_scanf_int(BerSafeHandle berElement, string format, ref int value);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
+ public static extern int ber_scanf_ptr(BerSafeHandle berElement, string format, ref IntPtr value);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvfree", CharSet = CharSet.Unicode)]
+ public static extern int ber_bvfree(IntPtr value);
+
+ [DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvecfree", CharSet = CharSet.Unicode)]
+ public static extern int ber_bvecfree(IntPtr value);
+
+ [DllImport("wldap32.dll", 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("wldap32.dll", 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("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_result2error", CharSet = CharSet.Unicode)]
+ public static extern int ldap_result2error([In] ConnectionHandle ldapHandle, [In] IntPtr result, int freeIt);
+ }
+}
diff --git a/src/System.DirectoryServices/System.DirectoryServices.sln b/src/System.DirectoryServices/System.DirectoryServices.sln
new file mode 100644
index 0000000000..23b11df655
--- /dev/null
+++ b/src/System.DirectoryServices/System.DirectoryServices.sln
@@ -0,0 +1,82 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.DirectoryServices", "src\System.DirectoryServices.csproj", "{879C23DC-D828-4DFB-8E92-ABBC11B71035}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{E37A8E5B-B822-436D-84FD-99EE46C0733F}"
+ ProjectSection(SolutionItems) = preProject
+ ref\project.lock.json = ref\project.lock.json
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.DirectoryServices", "ref\System.DirectoryServices.csproj", "{2F7F1E21-0277-436B-85B8-E8FFA902FA66}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AD3CFC4E-B3AE-4931-B631-C39216ABD115}"
+ ProjectSection(SolutionItems) = preProject
+ src\System.DirectoryServices.builds = src\System.DirectoryServices.builds
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ net46_Debug|Any CPU = net46_Debug|Any CPU
+ net46_Release|Any CPU = net46_Release|Any CPU
+ Release|Any CPU = Release|Any CPU
+ Unix_Debug|Any CPU = Unix_Debug|Any CPU
+ Unix_Release|Any CPU = Unix_Release|Any CPU
+ Windows_Debug|Any CPU = Windows_Debug|Any CPU
+ Windows_netcore50_Debug|Any CPU = Windows_netcore50_Debug|Any CPU
+ Windows_netcore50_Release|Any CPU = Windows_netcore50_Release|Any CPU
+ Windows_Release|Any CPU = Windows_Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Debug|Any CPU.ActiveCfg = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.net46_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Unix_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Debug|Any CPU.ActiveCfg = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_netcore50_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035}.Windows_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.net46_Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Unix_Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_netcore50_Release|Any CPU.Build.0 = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66}.Windows_Release|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {879C23DC-D828-4DFB-8E92-ABBC11B71035} = {AD3CFC4E-B3AE-4931-B631-C39216ABD115}
+ {2F7F1E21-0277-436B-85B8-E8FFA902FA66} = {E37A8E5B-B822-436D-84FD-99EE46C0733F}
+ EndGlobalSection
+EndGlobal
diff --git a/src/System.DirectoryServices/dir.props b/src/System.DirectoryServices/dir.props
new file mode 100644
index 0000000000..503cf86a87
--- /dev/null
+++ b/src/System.DirectoryServices/dir.props
@@ -0,0 +1,7 @@
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\dir.props" />
+ <PropertyGroup>
+ <AssemblyVersion>4.1.0.0</AssemblyVersion>
+ </PropertyGroup>
+</Project>
+
diff --git a/src/System.DirectoryServices/pkg/System.DirectoryServices.builds b/src/System.DirectoryServices/pkg/System.DirectoryServices.builds
new file mode 100644
index 0000000000..54e41ffa65
--- /dev/null
+++ b/src/System.DirectoryServices/pkg/System.DirectoryServices.builds
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!--
+ <Project Include="System.DirectoryServices.pkgproj"/>
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.DirectoryServices/pkg/System.DirectoryServices.pkgproj b/src/System.DirectoryServices/pkg/System.DirectoryServices.pkgproj
new file mode 100644
index 0000000000..3f8ccefb0e
--- /dev/null
+++ b/src/System.DirectoryServices/pkg/System.DirectoryServices.pkgproj
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <ProjectReference Include="..\ref\System.DirectoryServices.csproj">
+ <SupportedFramework>netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ </ProjectReference>
+ <ProjectReference Include="..\src\System.DirectoryServices.builds" />
+ <InboxOnTargetFramework Include="MonoAndroid10" />
+ <InboxOnTargetFramework Include="MonoTouch10" />
+ <InboxOnTargetFramework Include="xamarinios10" />
+ <InboxOnTargetFramework Include="xamarinmac20" />
+ <InboxOnTargetFramework Include="xamarintvos10" />
+ <InboxOnTargetFramework Include="xamarinwatchos10" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.DirectoryServices/ref/System.DirectoryServices.cs b/src/System.DirectoryServices/ref/System.DirectoryServices.cs
new file mode 100644
index 0000000000..5c2f593e66
--- /dev/null
+++ b/src/System.DirectoryServices/ref/System.DirectoryServices.cs
@@ -0,0 +1,7 @@
+// 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.
+// ------------------------------------------------------------------------------
+// Changes to this file must follow the http://aka.ms/api-review process.
+// ------------------------------------------------------------------------------
+
diff --git a/src/System.DirectoryServices/ref/System.DirectoryServices.csproj b/src/System.DirectoryServices/ref/System.DirectoryServices.csproj
new file mode 100644
index 0000000000..a74906a6eb
--- /dev/null
+++ b/src/System.DirectoryServices/ref/System.DirectoryServices.csproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="System.DirectoryServices.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.DirectoryServices/src/Interop/AdsAuthentication.cs b/src/System.DirectoryServices/src/Interop/AdsAuthentication.cs
new file mode 100644
index 0000000000..2412cf47e8
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsAuthentication.cs
@@ -0,0 +1,20 @@
+// 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.Interop
+{
+ internal enum AdsAuthentication
+ {
+ ADS_SECURE_AUTHENTICATION = 0x1,
+ ADS_USE_ENCRYPTION = 0x2,
+ ADS_USE_SSL = 0x2,
+ ADS_READONLY_SERVER = 0x4,
+ ADS_PROMPT_CREDENTIALS = 0x8,
+ ADS_NO_AUTHENTICATION = 0x10,
+ ADS_FAST_BIND = 0x20,
+ ADS_USE_SIGNING = 0x40,
+ ADS_USE_SEALING = 0x80
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/AdsOptions.cs b/src/System.DirectoryServices/src/Interop/AdsOptions.cs
new file mode 100644
index 0000000000..41566ec617
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsOptions.cs
@@ -0,0 +1,19 @@
+// 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.Interop
+{
+ internal enum AdsOptions
+ {
+ ADS_OPTION_SERVERNAME = 0,
+ ADS_OPTION_REFERRALS = 1,
+ ADS_OPTION_PAGE_SIZE = 2,
+ ADS_OPTION_SECURITY_MASK = 3,
+ ADS_OPTION_MUTUAL_AUTH_STATUS = 4,
+ ADS_OPTION_QUOTA = 5,
+ ADS_OPTION_PASSWORD_PORTNUMBER = 6,
+ ADS_OPTION_PASSWORD_METHOD = 7
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/AdsPropertyOperation.cs b/src/System.DirectoryServices/src/Interop/AdsPropertyOperation.cs
new file mode 100644
index 0000000000..7b9c21d86f
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsPropertyOperation.cs
@@ -0,0 +1,24 @@
+// 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.Interop
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+
+ internal enum AdsPropertyOperation
+ {
+ Clear = 1,
+
+ Update = 2,
+
+ Append = 3,
+
+ Delete = 4
+ }
+}
diff --git a/src/System.DirectoryServices/src/Interop/AdsSearchColumn.cs b/src/System.DirectoryServices/src/Interop/AdsSearchColumn.cs
new file mode 100644
index 0000000000..a7cd9e75d0
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsSearchColumn.cs
@@ -0,0 +1,20 @@
+// 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.Interop
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct AdsSearchColumn
+ {
+ public IntPtr pszAttrName;
+ public int/*AdsType*/ dwADsType;
+ public AdsValue* pADsValues;
+ public int dwNumValues;
+ public IntPtr hReserved;
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/AdsSearchPreferenceInfo.cs b/src/System.DirectoryServices/src/Interop/AdsSearchPreferenceInfo.cs
new file mode 100644
index 0000000000..ef0738d23e
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsSearchPreferenceInfo.cs
@@ -0,0 +1,20 @@
+// 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.Interop
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct AdsSearchPreferenceInfo
+ {
+ public int /*AdsSearchPreferences*/ dwSearchPref;
+ internal int pad;
+ public AdsValue vValue;
+ public int /*AdsStatus*/ dwStatus;
+ internal int pad2;
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/AdsSearchPreferences.cs b/src/System.DirectoryServices/src/Interop/AdsSearchPreferences.cs
new file mode 100644
index 0000000000..804ccb3eb6
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsSearchPreferences.cs
@@ -0,0 +1,30 @@
+// 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.Interop
+{
+ internal enum AdsSearchPreferences
+ {
+ ASYNCHRONOUS = 0,
+ DEREF_ALIASES = 1,
+ SIZE_LIMIT = 2,
+ TIME_LIMIT = 3,
+ ATTRIBTYPES_ONLY = 4,
+ SEARCH_SCOPE = 5,
+ TIMEOUT = 6,
+ PAGESIZE = 7,
+ PAGED_TIME_LIMIT = 8,
+ CHASE_REFERRALS = 9,
+ SORT_ON = 10,
+ CACHE_RESULTS = 11,
+ DIRSYNC = 12,
+ TOMBSTONE = 13,
+ VLV = 14,
+ ATTRIBUTE_QUERY = 15,
+ SECURITY_MASK = 16,
+ DIRSYNC_FLAG = 17,
+ EXTENDED_DN = 18
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/AdsSortKey.cs b/src/System.DirectoryServices/src/Interop/AdsSortKey.cs
new file mode 100644
index 0000000000..edfee10e3f
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsSortKey.cs
@@ -0,0 +1,18 @@
+// 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.Interop
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct AdsSortKey
+ {
+ public IntPtr pszAttrType;
+ public IntPtr pszReserved;
+ public int fReverseOrder;
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/AdsStatus.cs b/src/System.DirectoryServices/src/Interop/AdsStatus.cs
new file mode 100644
index 0000000000..d3d039cfa2
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsStatus.cs
@@ -0,0 +1,14 @@
+// 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.Interop
+{
+ internal enum AdsStatusEnum
+ {
+ ADS_STATUS_S_OK = 0,
+ ADS_STATUS_INVALID_SEARCHPREF = 1,
+ ADS_STATUS_INVALID_SEARCHPREFVALUE = 2
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/AdsType.cs b/src/System.DirectoryServices/src/Interop/AdsType.cs
new file mode 100644
index 0000000000..7cae8ed409
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsType.cs
@@ -0,0 +1,40 @@
+// 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.Interop
+{
+ internal enum AdsType
+ {
+ ADSTYPE_INVALID = 0,
+ ADSTYPE_DN_STRING = 1,
+ ADSTYPE_CASE_EXACT_STRING = 2,
+ ADSTYPE_CASE_IGNORE_STRING = 3,
+ ADSTYPE_PRINTABLE_STRING = 4,
+ ADSTYPE_NUMERIC_STRING = 5,
+ ADSTYPE_BOOLEAN = 6,
+ ADSTYPE_INTEGER = 7,
+ ADSTYPE_OCTET_STRING = 8,
+ ADSTYPE_UTC_TIME = 9,
+ ADSTYPE_LARGE_INTEGER = 10,
+ ADSTYPE_PROV_SPECIFIC = 11,
+ ADSTYPE_OBJECT_CLASS = 12,
+ ADSTYPE_CASEIGNORE_LIST = 13,
+ ADSTYPE_OCTET_LIST = 14,
+ ADSTYPE_PATH = 15,
+ ADSTYPE_POSTALADDRESS = 16,
+ ADSTYPE_TIMESTAMP = 17,
+ ADSTYPE_BACKLINK = 18,
+ ADSTYPE_TYPEDNAME = 19,
+ ADSTYPE_HOLD = 20,
+ ADSTYPE_NETADDRESS = 21,
+ ADSTYPE_REPLICAPOINTER = 22,
+ ADSTYPE_FAXNUMBER = 23,
+ ADSTYPE_EMAIL = 24,
+ ADSTYPE_NT_SECURITY_DESCRIPTOR = 25,
+ ADSTYPE_UNKNOWN = 26,
+ ADSTYPE_DN_WITH_BINARY = 27,
+ ADSTYPE_DN_WITH_STRING = 28
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/AdsValue2.cs b/src/System.DirectoryServices/src/Interop/AdsValue2.cs
new file mode 100644
index 0000000000..ffb35510df
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsValue2.cs
@@ -0,0 +1,47 @@
+// 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.Interop
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct Ads_Pointer
+ {
+ public IntPtr value;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct Ads_OctetString
+ {
+ public int length;
+ public IntPtr value;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct Ads_Generic
+ {
+ public int a;
+ public int b;
+ public int c;
+ public int d;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct AdsValue
+ {
+ [FieldOffset(0)]
+ public int /*AdsType*/ dwType;
+ [FieldOffset(4)]
+ internal int pad;
+ [FieldOffset(8)]
+ public Ads_Pointer pointer;
+ [FieldOffset(8)]
+ public Ads_OctetString octetString;
+ [FieldOffset(8)]
+ public Ads_Generic generic;
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/AdsValueHelper2.cs b/src/System.DirectoryServices/src/Interop/AdsValueHelper2.cs
new file mode 100644
index 0000000000..544d7ea27d
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/AdsValueHelper2.cs
@@ -0,0 +1,287 @@
+// 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.Interop
+{
+ using System;
+ using System.Text;
+ using System.Runtime.InteropServices;
+ using System.Globalization;
+ using System.Security.Permissions;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SystemTime
+ {
+ public ushort wYear;
+ public ushort wMonth;
+ public ushort wDayOfWeek;
+ public ushort wDay;
+ public ushort wHour;
+ public ushort wMinute;
+ public ushort wSecond;
+ public ushort wMilliseconds;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class DnWithBinary
+ {
+ public int dwLength;
+ public IntPtr lpBinaryValue; // GUID of directory object
+ public IntPtr pszDNString; // Distinguished Name
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class DnWithString
+ {
+ public IntPtr pszStringValue; // associated value
+ public IntPtr pszDNString; // Distinguished Name
+ }
+
+ // helper class for dealing with struct AdsValue.
+ internal class AdsValueHelper
+ {
+ public AdsValue adsvalue;
+ private GCHandle _pinnedHandle;
+
+ public AdsValueHelper(AdsValue adsvalue)
+ {
+ this.adsvalue = adsvalue;
+ }
+
+ public AdsValueHelper(object managedValue)
+ {
+ AdsType adsType = GetAdsTypeForManagedType(managedValue.GetType());
+ SetValue(managedValue, adsType);
+ }
+
+ public AdsValueHelper(object managedValue, AdsType adsType)
+ {
+ SetValue(managedValue, adsType);
+ }
+
+ public long LowInt64
+ {
+ get
+ {
+ return (long)((uint)adsvalue.generic.a + (((long)adsvalue.generic.b) << 32));
+ }
+ set
+ {
+ adsvalue.generic.a = (int)(value & 0xFFFFFFFF);
+ adsvalue.generic.b = (int)(value >> 32);
+ }
+ }
+
+ ~AdsValueHelper()
+ {
+ if (_pinnedHandle.IsAllocated)
+ _pinnedHandle.Free();
+ }
+
+ private AdsType GetAdsTypeForManagedType(Type type)
+ {
+ //Consider this code is only excercised by DirectorySearcher
+ //it just translates the types needed by such a component, if more managed
+ //types are to be used in the future, this function needs to be expanded.
+ if (type == typeof(int))
+ return AdsType.ADSTYPE_INTEGER;
+ if (type == typeof(long))
+ return AdsType.ADSTYPE_LARGE_INTEGER;
+ if (type == typeof(bool))
+ return AdsType.ADSTYPE_BOOLEAN;
+
+ return AdsType.ADSTYPE_UNKNOWN;
+ }
+
+ public AdsValue GetStruct()
+ {
+ return adsvalue;
+ }
+
+ private static ushort LowOfInt(int i)
+ {
+ return unchecked((ushort)(i & 0xFFFF));
+ }
+
+ private static ushort HighOfInt(int i)
+ {
+ return unchecked((ushort)((i >> 16) & 0xFFFF));
+ }
+
+ public object GetValue()
+ {
+ switch ((AdsType)adsvalue.dwType)
+ {
+ // Common for DNS and LDAP
+ case AdsType.ADSTYPE_UTC_TIME:
+ {
+ SystemTime st = new SystemTime();
+
+ st.wYear = LowOfInt(adsvalue.generic.a);
+ st.wMonth = HighOfInt(adsvalue.generic.a);
+ st.wDayOfWeek = LowOfInt(adsvalue.generic.b);
+ st.wDay = HighOfInt(adsvalue.generic.b);
+ st.wHour = LowOfInt(adsvalue.generic.c);
+ st.wMinute = HighOfInt(adsvalue.generic.c);
+ st.wSecond = LowOfInt(adsvalue.generic.d);
+ st.wMilliseconds = HighOfInt(adsvalue.generic.d);
+
+ return new DateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+ }
+
+ case AdsType.ADSTYPE_DN_WITH_BINARY:
+ {
+ DnWithBinary dnb = new DnWithBinary();
+ Marshal.PtrToStructure(adsvalue.pointer.value, dnb);
+ byte[] bytes = new byte[dnb.dwLength];
+ Marshal.Copy(dnb.lpBinaryValue, bytes, 0, dnb.dwLength);
+ StringBuilder strb = new StringBuilder();
+ StringBuilder binaryPart = new StringBuilder();
+ for (int i = 0; i < bytes.Length; i++)
+ {
+ string s = bytes[i].ToString("X", CultureInfo.InvariantCulture);
+ if (s.Length == 1)
+ binaryPart.Append("0");
+ binaryPart.Append(s);
+ }
+
+ strb.Append("B:");
+ strb.Append(binaryPart.Length);
+ strb.Append(":");
+ strb.Append(binaryPart.ToString());
+ strb.Append(":");
+ strb.Append(Marshal.PtrToStringUni(dnb.pszDNString));
+ return strb.ToString();
+ }
+
+ case AdsType.ADSTYPE_DN_WITH_STRING:
+ {
+ DnWithString dns = new DnWithString();
+ Marshal.PtrToStructure(adsvalue.pointer.value, dns);
+ string strValue = Marshal.PtrToStringUni(dns.pszStringValue);
+ if (strValue == null)
+ strValue = "";
+
+ StringBuilder strb = new StringBuilder();
+ strb.Append("S:");
+ strb.Append(strValue.Length);
+ strb.Append(":");
+ strb.Append(strValue);
+ strb.Append(":");
+ strb.Append(Marshal.PtrToStringUni(dns.pszDNString));
+ return strb.ToString();
+ }
+
+ case AdsType.ADSTYPE_DN_STRING:
+ case AdsType.ADSTYPE_CASE_EXACT_STRING:
+ case AdsType.ADSTYPE_CASE_IGNORE_STRING:
+ case AdsType.ADSTYPE_PRINTABLE_STRING:
+ case AdsType.ADSTYPE_NUMERIC_STRING:
+ case AdsType.ADSTYPE_OBJECT_CLASS:
+ // string
+ return Marshal.PtrToStringUni(adsvalue.pointer.value);
+
+ case AdsType.ADSTYPE_BOOLEAN:
+ // bool
+ return adsvalue.generic.a != 0;
+
+ case AdsType.ADSTYPE_INTEGER:
+ // int
+ return adsvalue.generic.a;
+
+ case AdsType.ADSTYPE_NT_SECURITY_DESCRIPTOR:
+ case AdsType.ADSTYPE_OCTET_STRING:
+ case AdsType.ADSTYPE_PROV_SPECIFIC:
+ // byte[]
+ int len = adsvalue.octetString.length;
+ byte[] value = new byte[len];
+ Marshal.Copy(adsvalue.octetString.value, value, 0, len);
+ return value;
+
+ case AdsType.ADSTYPE_INVALID:
+ throw new InvalidOperationException(Res.GetString(Res.DSConvertTypeInvalid));
+
+ case AdsType.ADSTYPE_LARGE_INTEGER:
+ return LowInt64;
+
+ // not used in LDAP
+ case AdsType.ADSTYPE_CASEIGNORE_LIST:
+ case AdsType.ADSTYPE_OCTET_LIST:
+ case AdsType.ADSTYPE_PATH:
+ case AdsType.ADSTYPE_POSTALADDRESS:
+ case AdsType.ADSTYPE_TIMESTAMP:
+ case AdsType.ADSTYPE_NETADDRESS:
+ case AdsType.ADSTYPE_FAXNUMBER:
+ case AdsType.ADSTYPE_EMAIL:
+
+ case AdsType.ADSTYPE_BACKLINK:
+ case AdsType.ADSTYPE_HOLD:
+ case AdsType.ADSTYPE_TYPEDNAME:
+ case AdsType.ADSTYPE_REPLICAPOINTER:
+ case AdsType.ADSTYPE_UNKNOWN:
+ return new NotImplementedException(Res.GetString(Res.DSAdsvalueTypeNYI, "0x" + Convert.ToString(adsvalue.dwType, 16)));
+
+ default:
+ return new ArgumentException(Res.GetString(Res.DSConvertFailed, "0x" + Convert.ToString(LowInt64, 16), "0x" + Convert.ToString(adsvalue.dwType, 16)));
+ }
+ }
+
+ public object GetVlvValue()
+ {
+ AdsVLV vlv = new AdsVLV();
+ Marshal.PtrToStructure(adsvalue.octetString.value, vlv);
+ byte[] bytes = null;
+ if (vlv.contextID != (IntPtr)0 && vlv.contextIDlength != 0)
+ {
+ bytes = new byte[vlv.contextIDlength];
+ Marshal.Copy(vlv.contextID, bytes, 0, vlv.contextIDlength);
+ }
+ DirectoryVirtualListView vlvResponse = new DirectoryVirtualListView();
+ vlvResponse.Offset = vlv.offset;
+ vlvResponse.ApproximateTotal = vlv.contentCount;
+ DirectoryVirtualListViewContext context = new DirectoryVirtualListViewContext(bytes);
+ vlvResponse.DirectoryVirtualListViewContext = context;
+
+ return vlvResponse;
+ }
+
+ private unsafe void SetValue(object managedValue, AdsType adsType)
+ {
+ adsvalue = new AdsValue();
+ adsvalue.dwType = (int)adsType;
+ switch (adsType)
+ {
+ case AdsType.ADSTYPE_INTEGER:
+ adsvalue.generic.a = (int)managedValue;
+ adsvalue.generic.b = 0;
+ break;
+ case AdsType.ADSTYPE_LARGE_INTEGER:
+ LowInt64 = (long)managedValue;
+ break;
+ case AdsType.ADSTYPE_BOOLEAN:
+ if ((bool)managedValue)
+ LowInt64 = -1;
+ else
+ LowInt64 = 0;
+ break;
+ case AdsType.ADSTYPE_CASE_IGNORE_STRING:
+ _pinnedHandle = GCHandle.Alloc(managedValue, GCHandleType.Pinned);
+ adsvalue.pointer.value = _pinnedHandle.AddrOfPinnedObject();
+ break;
+ case AdsType.ADSTYPE_PROV_SPECIFIC:
+ byte[] bytes = (byte[])managedValue;
+ // filling in an ADS_PROV_SPECIFIC struct.
+ // 1st dword (our member a) is DWORD dwLength.
+ // 2nd dword (our member b) is byte *lpValue.
+ adsvalue.octetString.length = bytes.Length;
+ _pinnedHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
+ adsvalue.octetString.value = _pinnedHandle.AddrOfPinnedObject();
+ break;
+ default:
+ throw new NotImplementedException(Res.GetString(Res.DSAdsvalueTypeNYI, "0x" + Convert.ToString((int)adsType, 16)));
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/NativeMethods.cs b/src/System.DirectoryServices/src/Interop/NativeMethods.cs
new file mode 100644
index 0000000000..b61d82dd5f
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/NativeMethods.cs
@@ -0,0 +1,32 @@
+// 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.Interop
+{
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Security.Permissions;
+ using System.Collections;
+ using System.IO;
+ using System.Text;
+
+ internal class NativeMethods
+ {
+ public enum AuthenticationModes
+ {
+ SecureAuthentication = 0x1,
+ UseEncryption = 0x2,
+ UseSSL = 0x2,
+ ReadonlyServer = 0x4,
+ // PromptCredentials = 0x8, // Deprecated by ADSI
+ NoAuthentication = 0x10,
+ FastBind = 0x20,
+ UseSigning = 0x40,
+ UseSealing = 0x80,
+ UseDelegation = 0x100,
+ UseServerBinding = 0x200
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Interop/SafeNativeMethods.cs b/src/System.DirectoryServices/src/Interop/SafeNativeMethods.cs
new file mode 100644
index 0000000000..497a833a2d
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/SafeNativeMethods.cs
@@ -0,0 +1,151 @@
+// 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.Interop
+{
+ using System;
+ using System.Text;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+
+ [
+ SuppressUnmanagedCodeSecurityAttribute()
+ ]
+ internal class SafeNativeMethods
+ {
+ [DllImport(ExternDll.Oleaut32, PreserveSig = false)]
+ public static extern void VariantClear(IntPtr pObject);
+ [DllImport(ExternDll.Oleaut32)]
+ public static extern void VariantInit(IntPtr pObject);
+ [DllImport(ExternDll.Activeds)]
+ public static extern bool FreeADsMem(IntPtr pVoid);
+
+ public const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100,
+ FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200,
+ FORMAT_MESSAGE_FROM_STRING = 0x00000400,
+ FORMAT_MESSAGE_FROM_HMODULE = 0x00000800,
+ FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000,
+ FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000,
+ FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF,
+ ERROR_MORE_DATA = 234,
+ ERROR_SUCCESS = 0;
+
+ [DllImport(ExternDll.Activeds, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ public static extern int ADsGetLastError(out int error, StringBuilder errorBuffer,
+ int errorBufferLength, StringBuilder nameBuffer, int nameBufferLength);
+
+ [DllImport(ExternDll.Activeds, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ public static extern int ADsSetLastError(int error, string errorString, string provider);
+
+ [DllImport(ExternDll.Kernel32, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ public static extern int FormatMessageW(int dwFlags, int lpSource, int dwMessageId,
+ int dwLanguageId, StringBuilder lpBuffer, int nSize, int arguments);
+
+ public class EnumVariant
+ {
+ private static readonly object s_noMoreValues = new object();
+ private Object _currentValue = s_noMoreValues;
+ private IEnumVariant _enumerator;
+
+ public EnumVariant(IEnumVariant en)
+ {
+ if (en == null)
+ throw new ArgumentNullException("en");
+ _enumerator = en;
+ }
+
+ /// <include file='doc\SafeNativeMethods.uex' path='docs/doc[@for="SafeNativeMethods.EnumVariant.GetNext"]/*' />
+ /// <devdoc>
+ /// Moves the enumerator to the next value In the list.
+ /// </devdoc>
+ public bool GetNext()
+ {
+ Advance();
+ return _currentValue != s_noMoreValues;
+ }
+
+ /// <include file='doc\SafeNativeMethods.uex' path='docs/doc[@for="SafeNativeMethods.EnumVariant.GetValue"]/*' />
+ /// <devdoc>
+ /// Returns the current value of the enumerator. If GetNext() has never been called,
+ /// or if it has been called but it returned false, will throw an exception.
+ /// </devdoc>
+ public Object GetValue()
+ {
+ if (_currentValue == s_noMoreValues)
+ throw new InvalidOperationException(Res.GetString(Res.DSEnumerator));
+ return _currentValue;
+ }
+
+ /// <include file='doc\SafeNativeMethods.uex' path='docs/doc[@for="SafeNativeMethods.EnumVariant.Reset"]/*' />
+ /// <devdoc>
+ /// Returns the enumerator to the start of the sequence.
+ /// </devdoc>
+ public void Reset()
+ {
+ _enumerator.Reset();
+ _currentValue = s_noMoreValues;
+ }
+
+ /// <include file='doc\SafeNativeMethods.uex' path='docs/doc[@for="SafeNativeMethods.EnumVariant.Advance"]/*' />
+ /// <devdoc>
+ /// Moves the pointer to the next value In the contained IEnumVariant, and
+ /// stores the current value In currentValue.
+ /// </devdoc>
+ private void Advance()
+ {
+ _currentValue = s_noMoreValues;
+ IntPtr addr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Variant)));
+ try
+ {
+ int[] numRead = new int[] { 0 };
+ SafeNativeMethods.VariantInit(addr);
+ _enumerator.Next(1, addr, numRead);
+
+ try
+ {
+ if (numRead[0] > 0)
+ {
+ _currentValue = Marshal.GetObjectForNativeVariant(addr);
+ }
+ }
+ finally
+ {
+ SafeNativeMethods.VariantClear(addr);
+ }
+ }
+ finally
+ {
+ Marshal.FreeCoTaskMem(addr);
+ }
+ }
+ }
+
+ [ComImport(), Guid("00020404-0000-0000-C000-000000000046"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IEnumVariant
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void Next(
+ [In, MarshalAs(UnmanagedType.U4)]
+ int celt,
+ [In, Out]
+ IntPtr rgvar,
+ [Out, MarshalAs(UnmanagedType.LPArray)]
+ int[] pceltFetched);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void Skip(
+ [In, MarshalAs(UnmanagedType.U4)]
+ int celt);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void Reset();
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void Clone(
+ [Out, MarshalAs(UnmanagedType.LPArray)]
+ IEnumVariant[] ppenum);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/Interop/UnsafeNativeMethods.cs b/src/System.DirectoryServices/src/Interop/UnsafeNativeMethods.cs
new file mode 100644
index 0000000000..8018af581c
--- /dev/null
+++ b/src/System.DirectoryServices/src/Interop/UnsafeNativeMethods.cs
@@ -0,0 +1,506 @@
+// 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.Interop
+{
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Collections;
+ using System.IO;
+ using System.Text;
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct Variant
+ {
+ [FieldOffset(0)]
+ public ushort varType;
+ [FieldOffset(2)]
+ public ushort reserved1;
+ [FieldOffset(4)]
+ public ushort reserved2;
+ [FieldOffset(6)]
+ public ushort reserved3;
+ [FieldOffset(8)]
+ public short boolvalue;
+ [FieldOffset(8)]
+ public IntPtr ptr1;
+ [FieldOffset(12)]
+ public IntPtr ptr2;
+ }
+
+ [
+ SuppressUnmanagedCodeSecurityAttribute()
+ ]
+ internal class UnsafeNativeMethods
+ {
+ [DllImport(ExternDll.Activeds, ExactSpelling = true, EntryPoint = "ADsOpenObject", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ private static extern int IntADsOpenObject(string path, string userName, string password, int flags, [In, Out] ref Guid iid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppObject);
+ public static int ADsOpenObject(string path, string userName, string password, int flags, [In, Out] ref Guid iid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppObject)
+ {
+ try
+ {
+ return IntADsOpenObject(path, userName, password, flags, ref iid, out ppObject);
+ }
+ catch (EntryPointNotFoundException)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.DSAdsiNotInstalled));
+ }
+ }
+
+ public interface IAds
+ {
+ string Name
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ }
+
+ string Class
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ }
+
+ string GUID
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ }
+
+ string ADsPath
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ }
+
+ string Parent
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ }
+
+ string Schema
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void GetInfo();
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void SetInfo();
+
+ Object Get(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string bstrName);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void Put(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string bstrName,
+ [In]
+ Object vProp);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [PreserveSig]
+ int GetEx(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ String bstrName,
+ [Out]
+ out object value);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void PutEx(
+ [In, MarshalAs(UnmanagedType.U4)]
+ int lnControlCode,
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string bstrName,
+ [In]
+ Object vProp);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void GetInfoEx(
+ [In]
+ Object vProperties,
+ [In, MarshalAs(UnmanagedType.U4)]
+ int lnReserved);
+ }
+
+ public interface IAdsContainer
+ {
+ int Count
+ {
+ [return: MarshalAs(UnmanagedType.U4)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ }
+
+ object _NewEnum
+ {
+ [return: MarshalAs(UnmanagedType.Interface)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ }
+
+ object Filter
+ {
+ get;
+ set;
+ }
+
+ object Hints
+ {
+ get;
+ set;
+ }
+
+ [return: MarshalAs(UnmanagedType.Interface)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ object GetObject(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string className,
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string relativeName);
+
+ [return: MarshalAs(UnmanagedType.Interface)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ object Create(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string className,
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string relativeName);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void Delete(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string className,
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string relativeName);
+
+ [return: MarshalAs(UnmanagedType.Interface)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ object CopyHere(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string sourceName,
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string newName);
+
+ [return: MarshalAs(UnmanagedType.Interface)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ object MoveHere(
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string sourceName,
+ [In, MarshalAs(UnmanagedType.BStr)]
+ string newName);
+ }
+
+ public interface IAdsDeleteOps
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void DeleteObject(int flags);
+ }
+
+ //
+ // PropertyValue as a co-class that implements the IAdsPropertyValue interface
+ //
+ [ComImport, Guid("7b9e38b0-a97c-11d0-8534-00c04fd8d503")]
+ public class PropertyValue
+ {
+ }
+
+ public interface IADsLargeInteger
+ {
+ int HighPart
+ {
+ get;
+ set;
+ }
+ int LowPart
+ {
+ get;
+ set;
+ }
+ }
+
+ public interface IAdsPropertyValue
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void Clear();
+
+ int ADsType
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ set;
+ }
+
+ string DNString
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ string CaseExactString
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ string CaseIgnoreString
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ string PrintableString
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ string NumericString
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ bool Boolean
+ {
+ get;
+ set;
+ }
+
+ int Integer
+ {
+ get;
+ set;
+ }
+
+ object OctetString
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ set;
+ }
+
+ object SecurityDescriptor
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+
+ set;
+ }
+
+ object LargeInteger
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+
+ set;
+ }
+
+ object UTCTime
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+
+ set;
+ }
+ }
+
+ //
+ // PropertyEntry as a co-class that implements the IAdsPropertyEntry interface
+ //
+ public class PropertyEntry
+ {
+ }
+
+ public interface IAdsPropertyEntry
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void Clear();
+
+ string Name
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ set;
+ }
+
+ int ADsType
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ set;
+ }
+
+ int ControlCode
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ set;
+ }
+
+ object Values
+ {
+ get;
+ set;
+ }
+ }
+
+ public interface IAdsPropertyList
+ {
+ int PropertyCount
+ {
+ [return: MarshalAs(UnmanagedType.U4)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ }
+
+ [return: MarshalAs(UnmanagedType.I4)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [PreserveSig]
+ int Next([Out] out object nextProp);
+
+ void Skip([In] int cElements);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void Reset();
+
+ object Item([In] object varIndex);
+
+ object GetPropertyItem([In, MarshalAs(UnmanagedType.BStr)] string bstrName, int ADsType);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void PutPropertyItem([In] object varData);
+
+ void ResetPropertyItem([In] object varEntry);
+
+ void PurgePropertyList();
+ }
+
+ [ComImport, Guid("109BA8EC-92F0-11D0-A790-00C04FD8D5A8"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IDirectorySearch
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void SetSearchPreference(
+ [In]
+ IntPtr /*ads_searchpref_info * */pSearchPrefs,
+ //ads_searchpref_info[] pSearchPrefs,
+ int dwNumPrefs);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void ExecuteSearch(
+ [In, MarshalAs(UnmanagedType.LPWStr)]
+ string pszSearchFilter,
+ [In, MarshalAs(UnmanagedType.LPArray)]
+ string[] pAttributeNames,
+ [In]
+ int dwNumberAttributes,
+ [Out]
+ out IntPtr hSearchResult);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void AbandonSearch([In] IntPtr hSearchResult);
+
+ [return: MarshalAs(UnmanagedType.U4)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [PreserveSig]
+ int GetFirstRow([In] IntPtr hSearchResult);
+
+ [return: MarshalAs(UnmanagedType.U4)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [PreserveSig]
+ int GetNextRow([In] IntPtr hSearchResult);
+
+ [return: MarshalAs(UnmanagedType.U4)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [PreserveSig]
+ int GetPreviousRow([In] IntPtr hSearchResult);
+
+ [return: MarshalAs(UnmanagedType.U4)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [PreserveSig]
+ int GetNextColumnName(
+ [In] IntPtr hSearchResult,
+ [Out]
+ IntPtr ppszColumnName);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void GetColumn(
+ [In] IntPtr hSearchResult,
+ [In] //, MarshalAs(UnmanagedType.LPWStr)]
+ IntPtr /* char * */ szColumnName,
+ [In]
+ IntPtr pSearchColumn);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void FreeColumn(
+ [In]
+ IntPtr pSearchColumn);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void CloseSearchHandle([In] IntPtr hSearchResult);
+ }
+
+ public interface IAdsObjectOptions
+ {
+ object GetOption(int flag);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void SetOption(int flag, [In] object varValue);
+ }
+
+ // for boolean type, the default marshaller does not work, so need to have specific marshaller. For other types, use the
+ // default marshaller which is more efficient
+
+ public interface IAdsObjectOptions2
+ {
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [PreserveSig]
+ int GetOption(int flag, [Out] out object value);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ void SetOption(int option, Variant value);
+ }
+
+ // IDirecorySearch return codes
+ internal const int S_ADS_NOMORE_ROWS = 0x00005012;
+ internal const int INVALID_FILTER = unchecked((int)0x8007203E);
+ internal const int SIZE_LIMIT_EXCEEDED = unchecked((int)0x80072023);
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/Resources/System.DirectoryServices.txt b/src/System.DirectoryServices/src/Resources/System.DirectoryServices.txt
new file mode 100644
index 0000000000..79ebebbad9
--- /dev/null
+++ b/src/System.DirectoryServices/src/Resources/System.DirectoryServices.txt
@@ -0,0 +1,231 @@
+; Resources for System.DirectoryServices component
+; Copyright (c) 2000 Microsoft Corporation
+
+; Exceptions messages
+
+DSDoesNotImplementIADs=The value provided for adsObject does not implement IADs.
+DSNoObject=There is no such object on the server.
+DSInvalidPath=The path is invalid.
+DSNotAContainer=The Active Directory object located at the path {0} is not a container.
+DSCannotDelete=The object cannot be deleted.
+DSNotInCollection=The given child object cannot be found in the collection.
+DSNoCurrentChild=There is no current child object.
+DSCannotBeIndexed=The entry properties cannot be indexed by number.
+DSCannotCount=The directory cannot report the number of properties.
+DSCannotGetKeys=The directory cannot report the names of available properties.
+DSCannotEmunerate=The entry properties cannot be enumerated. Consider using the entry schema to determine what properties are available.
+DSNoCurrentProperty=No current property exists.
+DSNoCurrentValue=No current value is available.
+DSBadPageSize=The PageSize must be greater than 0 or set to 0 for no paging.
+DSBadSizeLimit=SizeLimit must be greater than or equal to 0.
+DSSearchUnsupported=The provider does not support searching and cannot search {0}.
+DSNoCurrentEntry=No current entry exists.
+DSInvalidSearchFilter=The {0} search filter is invalid.
+DSPropertyNotFound=The property {0} cannot be found in the search results. The property might not exist on the found object, or it might not have been requested in the search query through DirectorySearcher.PropertiesToLoad.
+DSConvertFailed=The ADSVALUE with the union value {0} cannot be converted to the ADSTYPEENUM type {1}.
+DSConvertTypeInvalid=ADSVALUE type is invalid.
+DSAdsvalueTypeNYI=Handling of this ADSVALUE type is not yet implemented (type = {0}).
+DSAdsiNotInstalled=Active Directory Client is not installed on this computer.
+DSNotSet=[Not Set]
+DSEnumerator=Enumerator is positioned before the first item or after the last item.
+DSPathIsNotSet=Path property is not set.
+DSPropertySetSupported=New PropertyValueCollection cannot be set into a DirectoryEntry PropertyCollection.
+DSAddNotSupported=New properties cannot be added to a DirectoryEntry PropertyCollection.
+DSClearNotSupported=DirectoryEntry PropertyCollection cannot be cleared.
+DSRemoveNotSupported=Properties cannot be removed from a DirectoryEntry PropertyCollection.
+DSSearchPreferencesNotAccepted=The value for the property {0} cannot be set.
+DSBeforeCount=Indicates the number of entries, before the target entry, that the client is requesting from the server.
+DSBadBeforeCount=BeforeCount must be greater than or equal to 0.
+DSAfterCount=Indicates the number of entries, after the target entry, that the client is requesting from the server.
+DSBadAfterCount=AfterCount must be greater than or equal to 0.
+DSOffset=On input, indicates the target entry requested offset within the list. On output, indicates the server's best estimate as to the actual offset of the returned target entry position in the list.
+DSBadOffset=Offset must be greater than or equal to 0.
+DSTargetPercentage=Approximate target percentage in the total returned records.
+DSBadTargetPercentage=Target percentage should be in the range of 0 to 100 inclusively.
+DSTarget=Indicates the desired target entry requested by the client.
+DSApproximateTotal=The input value represents the client's estimated value for the content count. The output value is the server estimate of the content count.
+DSBadApproximateTotal=ApproximateTotal must be greater or equal to 0.
+DSDirectoryVirtualListViewContext=Indicates the server-generated context identifier.
+DSVirtualListView=Specifies that the search should use the LDAP virtual list view (VLV) control.
+DSBadPageSizeDirsync=DirectorySynchronization cannot be combined with PageSize.
+DSBadCacheResultsVLV=VirtualListView cannot be combined with CacheResults.
+DSBadDirectorySynchronizationFlag=DirectorySynchronization flag must be the value defined in the DirectorySynchronizationFlag class.
+DSBadASQSearchScope=When AttributeScopeQuery is specified, only SearchScope.Base is supported.
+DSDoesNotImplementIADsObjectOptions=This DirectoryEntry object does not support the Options property.
+DSPropertyValueSupportOneOperation=Only one type of operation can be performed in a sequence.
+ConfigSectionsUnique=The '{0}' section can only appear once in a configuration file.
+Invalid_boolean_attribute=The '{0}' attribute must be set to 'true' or 'false'.
+DSUnknownFailure=An unknown error occurred.
+DSNotSupportOnClient=This property is only supported on computers running Windows XP and later operating systems.
+DSNotSupportOnDC=This property is not supported when targeting Windows Server 2000 domain controllers.
+DirectoryContextNeedHost=The target of the directory context should be an Active Directory domain controller or ADAM instance.
+DSSyncAllFailure=An error occurred when synchronizing the server.
+UnknownTransport="{0}" is an unknown ActiveDirectoryTransportType.
+NotSupportTransportSMTP=ActiveDirectoryTransportType.Smtp not supported.
+CannotDelete=The newly created object has not been committed to the backend store, so it cannot be deleted.
+CannotGetObject=The newly created object has not been committed to the backend store, so GetDirectoryEntry cannot be called.
+DSNotFound=The Specified directory object cannot be found.
+InvalidContextTarget=The target of the directory context is invalid.
+TransportNotFound=The transport "{0}" cannot be found.
+SiteNotExist=The site "{0}" does not exist.
+SiteNotCommitted=The site "{0}" is newly created and has not been committed to the backend store.
+NoCurrentSite=The computer is not in a site.
+SubnetNotCommitted=The subnet "{0}" is newly created and has not been committed to the backend store.
+SiteLinkNotCommitted=The site link "{0}" is newly created and has not been committed to the backend store.
+ConnectionNotCommitted=The replication connection "{0}" is newly created and has not been committed to the backend store.
+AlreadyExistingForestTrust=A forest trust relationship exists between "{0}" and "{1}".
+AlreadyExistingDomainTrust=A domain trust relationship exists between "{0}" and "{1}".
+NotFoundInCollection=Cannot remove "{0}". It was not found in the specified collection.
+AlreadyExistingInCollection=Cannot add "{0}". It currently exists in the specified collection.
+NTDSSiteSetting=The site "{0}" does not contain a nTDSSiteSettings object.
+NotWithinSite=This directory server is not in the current site.
+InvalidTime=The end time must be later than the start time.
+UnableToRetrieveDomainInfo=Information about the domain could not be retrieved ({0}).
+UnableToOpenToken=The thread or process token could not be accessed ({0}).
+UnableToRetrieveTokenInfo=Information from the thread token could not be retrieved ({0}).
+UnableToRetrievePolicy=This computer's policy information could not be retrieved ({0}).
+UpdateAvailableRIDPoolOverflowFailure=Failure in updating rIDAvailablePool value. New value exceeds the maximum limit.
+
+EmptyStringParameter=The specified string parameter is empty.
+SupportedPlatforms=The System.DirectoryServices.ActiveDirectory namespace is only supported on computers running Windows 2000 and later operating systems.
+TargetShouldBeADAMServer=The name specified in the directory context must be an ADAM instance.
+TargetShouldBeDC=The name specified in the directory context must be an Active Directory domain controller.
+TargetShouldBeAppNCDnsName=The name specified in the directory context must be the DNS name of the application partition.
+TargetShouldBeServerORForest=The name specified in the directory context must be an Active Directory domain controller or a forest.
+TargetShouldBeServerORDomain=The name specified in the directory context must be an Active Directory domain controller or a domain.
+TargetShouldBeDomain=The name specified in the directory context must be an Active Directory domain.
+TargetShouldBeForest=The name specified in the directory context must be an Active Directory forest.
+TargetShouldBeConfigSet=The name specified in the directory context must be an ADAM configuration set.
+TargetShouldBeServerORConfigSet=The name specified in the directory context must be an ADAM instance or an ADAM configuration set.
+TargetShouldBeGC=The name specified in the directory context must be a global catalog.
+TargetShouldBeServer=The name specified in the directory context must be an Active Directory domain controller or an ADAM instance.
+NotADOrADAM=The specified name is not a forest, Active Directory domain controller, ADAM instance, or ADAM configuration set.
+ServerNotAReplica=The directory server does not host the specified application partition.
+AppNCNotFound=The specified application partition does not exist.
+ReplicaNotFound=A Directory server that hosts the specified application partition not found.
+GCNotFoundInForest=Global catalog not found in forest "{0}".
+DCNotFoundInDomain=Domain controller not found in the domain "{0}".
+ADAMInstanceNotFoundInConfigSet=ADAM instance not found in configuration set "{0}".
+DCNotFound=Domain controller "{0}" does not exist or cannot be contacted.
+GCNotFound=Global catalog "{0}" does not exist or cannot be contacted.
+AINotFound=ADAM instance "{0}" does not exist or cannot be contacted.
+ServerNotFound=Directory server "{0}" does not exist or cannot be contacted.
+DomainNotFound=The specified domain does not exist or cannot be contacted.
+ForestNotFound=The specified forest does not exist or cannot be contacted.
+ConfigSetNotFound=The specified ADAM configuration set does not exist or cannot be contacted.
+NDNCNotFound=The specified application partition does not exist or cannot be contacted.
+PropertyNotFoundOnObject=Property "{0}" on object "{1}" not found.
+PropertyNotFound=Property "{0}" not found.
+PropertyNotSet=Property "{0}" not set.
+ADAMInstanceNotFound=An ADAM instance could not be found.
+CannotPerformOperationOnUncommittedObject=Operation valid only for objects that exist on the backend store.
+LinkIdNotEvenNumber=Forward linkID must be an even number.
+InvalidServerNameFormat=The server object name has an invalid format.
+NoObjectClassForADPartition=Object class must not be specified for Active Directory application partitions.
+InvalidDNFormat=The specified distinguished name has an invalid format.
+InvalidDnsName=The specified DNS name has an invalid format.
+ApplicationPartitionTypeUnknown=Application partition is neither an Active Directory, nor ADAM application partition.
+UnknownSyntax=Schema property "{0}" has an unknown syntax.
+InvalidMode=The requested mode is invalid.
+NoW2K3DCs=No Windows Server 2003 domain controllers exist in the domain.
+DCInfoNotFound=Domain controller data not found for the specified Active Directory domain controller.
+NoW2K3DCsInForest=No Windows Server 2003 domain controllers exist in the forest.
+SchemaObjectNotCommitted=The schema object "{0}" is newly created and has not been committed to the backend store.
+InvalidFlags=One or more flags are invalid.
+CannotPerformOnGCObject=Cannot perform this operation on a global catalog object.
+CannotPerformOnGC=Cannot perform this operation on the GlobalCatalog class.
+ValueCannotBeModified=The specified value cannot be removed or overwritten. It is inherited from a super class.
+ServerShouldBeW2K3=The Active Directory domain controller must be running Windows Server 2003 operating system or later.
+LinkedPropertyNotFound=Schema property with link id "{0}" not found.
+GCDisabled=Cannot perform this operation on disabled global catalog object.
+PropertyInvalidForADAM=This property is not supported for an ADAM application partition.
+OperationInvalidForADAM=This operation is not supported for an ADAM application partition.
+ContextNotAssociatedWithDomain=Current security context is not associated with an Active Directory domain or forest.
+ComputerNotJoinedToDomain=The local computer is not joined to a domain or the domain cannot be contacted.
+VersionFailure=Failed to get the version of the operating system, error is "{0}".
+NoHostName=Unable to obtain DNS hostname of Active Directory domain controller with ntdsa object name "{0}".
+NoHostNameOrPortNumber=Unable to obtain DNS hostname or port number of ADAM instance with ntdsa object name "{0}".
+NTAuthority=NT AUTHORITY
+Name=Name: "{0}"
+OneLevelPartitionNotSupported=Creation of single level application partition is not supported.
+SiteNameNotFound=Unable to obtain the site name of domain controller "{0}".
+SiteObjectNameNotFound=Unable to obtain the distinguished name of the site object for domain controller "{0}".
+ComputerObjectNameNotFound=Unable to obtain the distinguished name of the computer object of domain controller "{0}".
+ServerObjectNameNotFound=Unable to obtain the distinguished name of the server object of domain controller "{0}".
+NtdsaObjectNameNotFound=Unable to obtain the distinguished name of the ntds settings object of domain controller "{0}".
+NtdsaObjectGuidNotFound=Unable to obtain the guid of the ntds settings object of domain controller "{0}".
+OnlyDomainOrForest=DirectoryContextType.Domain and DirectoryContextType.Forest are the only valid values for contextType when the name of the context is not specified.
+ServerShouldBeDC=The specified directory server must be an Active Directory domain controller.
+ServerShouldBeAI=The specified directory server must be an ADAM instance.
+CannotModifySacl=The system acl cannot be modified as it was not retrieved from the backend store.
+CannotModifyDacl=The discretionary acl cannot be modified as it was not retrieved from the backend store.
+
+ForestTrustCollision=A collision occurred in the forest trust relationship.
+ForestTrustDoesNotExist=A forest trust relationship does not exist between "{0}" and "{1}".
+DomainTrustDoesNotExist=A domain trust relationship does not exist between "{0}" and "{1}".
+WrongForestTrust=A forest trust relationship should not exist between "{0}" and "{1}".
+WrongTrustDirection=The trust relationship between "{0}" and "{1}" is not "{2}".
+NT4NotSupported=Trust relationship with Windows NT 4.0 domain not supported.
+KerberosNotSupported=Operation for Kerberos type trust not supported.
+DSPropertyListUnsupported=The provider does not support retrieval of the security descriptor in binary form.
+DSMultipleSDNotSupported=Multiple security descriptors for an object are not supported.
+DSSDNoValues=ntSecurityDescriptor property exists in cache, but has no values.
+ConnectionSourcServerShouldBeDC=Must be the name of an Active Directory domain controller.
+ConnectionSourcServerShouldBeADAM=Must be the name of an ADAM instance.
+ConnectionSourcServerSameForest=Must be in the same Active Directory forest as the name specified in the directory context.
+ConnectionSourcServerSameConfigSet=Must be in the same ADAM Configuration Set as the name specified in the directory context.
+TrustVerificationNotSupport=Trust verification not supported.
+
+;DescriptionAttribute
+
+DSChildren=The child entries of this node.
+DSGuid=The globally unique identifier of this entry.
+DSName=The name of the object as named with the service.
+DSNativeObject=The native ADSI object.
+DSParent=The parent entry of this node.
+DSPassword=The password to use when authenticating the client.
+DSPath=The path of this DirectoryEntry.
+DSProperties=Indicates the properties of this entry.
+DSSchemaClassName=The name of the schema for this entry.
+DSSchemaEntry=The DirectoryEntry that holds this entry schema.
+DSUsePropertyCache=Specifies whether to use the ADSI property cache.
+DSUsername=The username to use when authenticating the client.
+DSAuthenticationType=Specifies authentication options used in ADSI for binding to directory service objects.
+DSNativeGuid=The GUID text returned by the provider for this directory entry.
+DSCacheResults=Indicates whether the result should be cached on the client computer.
+DSClientTimeout=The maximum time that the client waits for the server to return results.
+DSPropertyNamesOnly=Indicates whether the search should retrieve only the names of requested properties or their names and values.
+DSFilter=Specifies the search criteria for this search.
+DSPageSize=Sets the page size in a paged search.
+DSPropertiesToLoad=The set of properties retrieved during the search.
+DSReferralChasing=Specifies how referrals are chased.
+DSSearchScope=The scope of the search that should be observed by the server.
+DSServerPageTimeLimit=The maximum amount of time that the server should observe for page results (as opposed to the time limit for the entire search).
+DSServerTimeLimit=The maximum amount of time that the server should spend searching.
+DSSizeLimit=The maximum number of objects that the server should return in a search.
+DSSearchRoot=The node in the Active Directory hierarchy at which the search will start.
+DSSort=The property on which the results should be sorted.
+DSSortName=The property name on which the results should be sorted.
+DSSortDirection=The direction in which the results should be sorted.
+DSAsynchronous=Indicates if searches should be performed asynchronously.
+DSTombstone=Indicates if the search should also return deleted objects that match the search filter.
+DSAttributeQuery=Specifies that an attribute-scoped query search should be performed.
+DSDerefAlias=Specifies that aliases of found objects are to be resolved.
+DSSecurityMasks=Specifies that the search should return security access data for the specified attributes.
+DSExtendedDn=Request an extended form of an Active Directory object distinguished name.
+DSDirectorySynchronizationFlag=The flag that directory synchronization search will use.
+DSDirectorySynchronizationCookie=The cookie returned from directory synchronization search.
+DSDirectorySynchronization=Specifies a directory synchronization search, which returns all changes since a specified state.
+DSUnknown=Unknown error (0x{0})
+DSOptions=Gets and Sets the options of this entry.
+DSObjectSecurity=The access control data for this directory entry.
+DirectoryEntryDesc=Encapsulates a node or object in an Active Directory hierarchy.
+DirectorySearcherDesc=Performs queries against Active Directory.
+OnlyAllowSingleDimension=Only single dimensional arrays are supported for the requested action.
+LessThanZero=Number was less than the array's lower bound in the first dimension.
+DestinationArrayNotLargeEnough=Destination array was not long enough. Check destIndex and length, and the array's lower bounds.
+NoNegativeTime=A negative value is not permitted for the replication interval.
+ReplicationIntervalExceedMax=The value exceeds the maximum allowed for replication interval.
+ReplicationIntervalInMinutes=The value can not be represented in whole minutes.
+TimespanExceedMax=The value exceeds the maximum allowed.
+
diff --git a/src/System.DirectoryServices/src/Resources/System/DirectoryServices/DirectoryEntry.bmp b/src/System.DirectoryServices/src/Resources/System/DirectoryServices/DirectoryEntry.bmp
new file mode 100644
index 0000000000..afa62b71ca
--- /dev/null
+++ b/src/System.DirectoryServices/src/Resources/System/DirectoryServices/DirectoryEntry.bmp
Binary files differ
diff --git a/src/System.DirectoryServices/src/Resources/System/DirectoryServices/DirectorySearcher.bmp b/src/System.DirectoryServices/src/Resources/System/DirectoryServices/DirectorySearcher.bmp
new file mode 100644
index 0000000000..d9a3b5070b
--- /dev/null
+++ b/src/System.DirectoryServices/src/Resources/System/DirectoryServices/DirectorySearcher.bmp
Binary files differ
diff --git a/src/System.DirectoryServices/src/System.DirectoryServices.builds b/src/System.DirectoryServices/src/System.DirectoryServices.builds
new file mode 100644
index 0000000000..d4af2f99a7
--- /dev/null
+++ b/src/System.DirectoryServices/src/System.DirectoryServices.builds
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!-- Disabling the builds for DirectoryServices until we get it up and running. This excludes it from being built by build.cmd
+ <Project Include="System.DirectoryServices.csproj">
+ <OSGroup>Windows_NT</OSGroup>
+ </Project>
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project>
+
diff --git a/src/System.DirectoryServices/src/System.DirectoryServices.csproj b/src/System.DirectoryServices/src/System.DirectoryServices.csproj
new file mode 100644
index 0000000000..ac93f453fb
--- /dev/null
+++ b/src/System.DirectoryServices/src/System.DirectoryServices.csproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <Configuration Condition="'$(Configuration)'=='' AND '$(TargetGroup)' == ''">Windows_Debug</Configuration>
+ </PropertyGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <ProjectGuid>{879C23DC-D828-4DFB-8E92-ABBC11B71035}</ProjectGuid>
+ <AssemblyName>System.DirectoryServices</AssemblyName>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <NuGetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ <NoWarn>$(NoWarn);0649</NoWarn>
+ <GeneratePlatformNotSupportedAssembly Condition="'$(TargetsUnix)' == 'true'">true</GeneratePlatformNotSupportedAssembly>
+ </PropertyGroup>
+ <!-- Help VS understand available configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
+ <ItemGroup>
+ <Compile Include="System\DirectoryServices\externdll.cs" />
+ <Compile Include="System\DirectoryServices\PrivilegedConfigurationManager.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectorySecurity.cs" />
+ <Compile Include="System\DirectoryServices\AdsVLV.cs" />
+ <Compile Include="System\DirectoryServices\AuthenticationTypes.cs" />
+ <Compile Include="System\DirectoryServices\BinaryCompatibility.cs" />
+ <Compile Include="System\DirectoryServices\DerefAlias.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryDescriptionAttribute.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryEntries.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryEntry.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryEntryConfiguration.cs" />
+ <Compile Include="System\DirectoryServices\DirectorySearcher.cs" />
+<!-- <Compile Include="System\DirectoryServices\DirectoryServicesPermission.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryServicesPermissionAccess.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryServicesPermissionAttribute.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryServicesPermissionEntry.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryServicesPermissionEntryCollection.cs" /> -->
+ <Compile Include="System\DirectoryServices\DirectorySynchronization.cs" />
+ <Compile Include="System\DirectoryServices\DirectorySynchronizationFlags.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryVirtualListView.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryVirtualListViewContext.cs" />
+ <Compile Include="System\DirectoryServices\ExtendedDn.cs" />
+ <Compile Include="System\DirectoryServices\PasswordEncodingMethod.cs" />
+ <Compile Include="System\DirectoryServices\PropertyCollection.cs" />
+ <Compile Include="System\DirectoryServices\PropertyValueCollection.cs" />
+ <Compile Include="System\DirectoryServices\ReferalChasingOption.cs" />
+ <Compile Include="System\DirectoryServices\ResultPropertyCollection.cs" />
+ <Compile Include="System\DirectoryServices\ResultPropertyValueCollection.cs" />
+ <Compile Include="System\DirectoryServices\SchemaNameCollection.cs" />
+ <Compile Include="System\DirectoryServices\SearchResult.cs" />
+ <Compile Include="System\DirectoryServices\SearchResultCollection.cs" />
+ <Compile Include="System\DirectoryServices\SearchScope.cs" />
+ <Compile Include="System\DirectoryServices\SearchWaitHandler.cs" />
+ <Compile Include="System\DirectoryServices\SecurityMasks.cs" />
+ <Compile Include="System\DirectoryServices\SortDirection.cs" />
+ <Compile Include="System\DirectoryServices\SortOption.cs" />
+ <Compile Include="System\DirectoryServices\DirectoryServicesCOMException.cs" />
+ <Compile Include="System\DirectoryServices\Design\DirectoryEntryConverter.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectoryPartition.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectoryReplicationMetaData.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySchedule.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySchema.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySchemaClass.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySchemaClassCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySchemaProperty.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySchemaPropertyCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySite.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySiteCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySiteLink.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySiteLinkBridge.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySiteLinkCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySubnet.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySubnetCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectorySyntax.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ADAMInstance.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ADAMInstanceCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ADSearcher.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ApplicationPartition.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ApplicationPartitionCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\AttributeMetaData.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\AttributeMetadataCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ConfigSet.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\DirectoryContext.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\DirectoryEntryManager.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\DirectoryServer.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\DirectoryServerCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\Domain.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\DomainCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\DomainController.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\DomainControllerCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\Exception.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\Forest.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ForestTrustCollision.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ForestTrustDomainInfoCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ForestTrustDomainInformation.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ForestTrustRelationshipInformation.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\GlobalCatalog.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\GlobalCatalogCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\Locator.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\LocatorFlag.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\NativeMethods.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\PropertyManager.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReadOnlyActiveDirectorySchemaClassCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReadOnlyActiveDirectorySchemaPropertyCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReadOnlyDirectoryServerCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReadOnlySiteCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReadOnlySiteLinkBridgeCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReadOnlySiteLinkCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReadOnlyStringCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationConnection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationConnectionCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationCursor.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationCursorCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationFailure.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationFailureCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationNeighbor.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationNeighborCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationOperation.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationOperationCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ReplicationOperationInformation.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\ActiveDirectoryInterSiteTransport.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\RoleOwner.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\RoleOwnerCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\SafeHandle.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\SecurityLevel.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\SystemFlag.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\TopLevelName.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\TopLevelNameCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\TrustHelper.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\TrustRelationshipInformation.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\TrustRelationshipInformationCollection.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\UnsafeNativeMethods.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\Utils.cs" />
+ <Compile Include="System\DirectoryServices\ActiveDirectory\WellKnownDN.cs" />
+ <Compile Include="Interop\AdsAuthentication.cs" />
+ <Compile Include="Interop\AdsOptions.cs" />
+ <Compile Include="Interop\AdsPropertyOperation.cs" />
+ <Compile Include="Interop\AdsSearchColumn.cs" />
+ <Compile Include="Interop\AdsSearchPreferenceInfo.cs" />
+ <Compile Include="Interop\AdsSearchPreferences.cs" />
+ <Compile Include="Interop\AdsSortKey.cs" />
+ <Compile Include="Interop\AdsStatus.cs" />
+ <Compile Include="Interop\AdsType.cs" />
+ <Compile Include="Interop\AdsValue2.cs" />
+ <Compile Include="Interop\AdsValueHelper2.cs" />
+ <Compile Include="Interop\NativeMethods.cs" />
+ <Compile Include="Interop\SafeNativeMethods.cs" />
+ <Compile Include="Interop\UnsafeNativeMethods.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs
new file mode 100644
index 0000000000..99e055e6a1
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs
@@ -0,0 +1,957 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Net;
+ using System.Collections;
+ using System.ComponentModel;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class AdamInstance : DirectoryServer
+ {
+ private string[] _becomeRoleOwnerAttrs = null;
+ private bool _disposed = false;
+
+ // for public properties
+ private string _cachedHostName = null;
+ private int _cachedLdapPort = -1;
+ private int _cachedSslPort = -1;
+ private bool _defaultPartitionInitialized = false;
+ private bool _defaultPartitionModified = false;
+ private ConfigurationSet _currentConfigSet = null;
+ private string _cachedDefaultPartition = null;
+ private AdamRoleCollection _cachedRoles = null;
+
+ private IntPtr _ADAMHandle = (IntPtr)0;
+ private IntPtr _authIdentity = IntPtr.Zero;
+ private SyncUpdateCallback _userDelegate = null;
+ private SyncReplicaFromAllServersCallback _syncAllFunctionPointer = null;
+
+ #region constructors
+ internal AdamInstance(DirectoryContext context, string adamInstanceName)
+ : this(context, adamInstanceName, new DirectoryEntryManager(context), true)
+ {
+ }
+
+ internal AdamInstance(DirectoryContext context, string adamInstanceName, DirectoryEntryManager directoryEntryMgr, bool nameIncludesPort)
+ {
+ this.context = context;
+ this.replicaName = adamInstanceName;
+ this.directoryEntryMgr = directoryEntryMgr;
+
+ // initialize the transfer role owner attributes
+ _becomeRoleOwnerAttrs = new String[2];
+ _becomeRoleOwnerAttrs[0] = PropertyManager.BecomeSchemaMaster;
+ _becomeRoleOwnerAttrs[1] = PropertyManager.BecomeDomainMaster;
+
+ // initialize the callback function
+ _syncAllFunctionPointer = new SyncReplicaFromAllServersCallback(SyncAllCallbackRoutine);
+ }
+
+ internal AdamInstance(DirectoryContext context, string adamHostName, DirectoryEntryManager directoryEntryMgr)
+ {
+ this.context = context;
+
+ // the replica name should be in the form dnshostname:port
+ this.replicaName = adamHostName;
+ string portNumber;
+ Utils.SplitServerNameAndPortNumber(context.Name, out portNumber);
+ if (portNumber != null)
+ {
+ this.replicaName = this.replicaName + ":" + portNumber;
+ }
+
+ // initialize the directory entry manager
+ this.directoryEntryMgr = directoryEntryMgr;
+
+ // initialize the transfer role owner attributes
+ _becomeRoleOwnerAttrs = new String[2];
+ _becomeRoleOwnerAttrs[0] = PropertyManager.BecomeSchemaMaster;
+ _becomeRoleOwnerAttrs[1] = PropertyManager.BecomeDomainMaster;
+
+ // initialize the callback function
+ _syncAllFunctionPointer = new SyncReplicaFromAllServersCallback(SyncAllCallbackRoutine);
+ }
+ #endregion constructors
+
+ #region IDisposable
+
+ ~AdamInstance()
+ {
+ // finalizer is called => Dispose has not been called yet.
+ Dispose(false);
+ }
+
+ // private Dispose method
+ protected override void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ try
+ {
+ // if there are any managed or unmanaged
+ // resources to be freed, those should be done here
+ // if disposing = true, only unmanaged resources should
+ // be freed, else both managed and unmanaged.
+ FreeADAMHandle();
+ _disposed = true;
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+
+ public static AdamInstance GetAdamInstance(DirectoryContext context)
+ {
+ DirectoryEntryManager directoryEntryMgr = null;
+ string dnsHostName = null;
+
+ // check that the context is not null
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ // contexttype should be DirectoryServer
+ if (context.ContextType != DirectoryContextType.DirectoryServer)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeADAMServer), "context");
+ }
+
+ // target must be a server
+ if ((!context.isServer()))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AINotFound, context.Name), typeof(AdamInstance), context.Name);
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // bind to the given adam instance
+ try
+ {
+ directoryEntryMgr = new DirectoryEntryManager(context);
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+
+ // This will ensure that we are talking to ADAM instance only
+ if (!Utils.CheckCapability(rootDSE, Capability.ActiveDirectoryApplicationMode))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AINotFound, context.Name), typeof(AdamInstance), context.Name);
+ }
+ dnsHostName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName);
+ }
+ catch (COMException e)
+ {
+ int errorCode = e.ErrorCode;
+
+ if (errorCode == unchecked((int)0x8007203a))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AINotFound, context.Name), typeof(AdamInstance), context.Name);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ return new AdamInstance(context, dnsHostName, directoryEntryMgr);
+ }
+
+ public static AdamInstance FindOne(DirectoryContext context, string partitionName)
+ {
+ // validate parameters (partitionName validated by the call to ConfigSet)
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ // contexttype should be ConfigurationSet
+ if (context.ContextType != DirectoryContextType.ConfigurationSet)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeConfigSet), "context");
+ }
+
+ if (partitionName == null)
+ {
+ throw new ArgumentNullException("partitionName");
+ }
+
+ if (partitionName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partitionName");
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ return ConfigurationSet.FindOneAdamInstance(context, partitionName, null);
+ }
+
+ public static AdamInstanceCollection FindAll(DirectoryContext context, string partitionName)
+ {
+ AdamInstanceCollection adamInstanceCollection = null;
+
+ // validate parameters (partitionName validated by the call to ConfigSet)
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ // contexttype should be ConfigurationSet
+ if (context.ContextType != DirectoryContextType.ConfigurationSet)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeConfigSet), "context");
+ }
+
+ if (partitionName == null)
+ {
+ throw new ArgumentNullException("partitionName");
+ }
+
+ if (partitionName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partitionName");
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ try
+ {
+ adamInstanceCollection = ConfigurationSet.FindAdamInstances(context, partitionName, null);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where we could not find an ADAM instance in that config set (return empty collection)
+ adamInstanceCollection = new AdamInstanceCollection(new ArrayList());
+ }
+
+ return adamInstanceCollection;
+ }
+
+ public void TransferRoleOwnership(AdamRole role)
+ {
+ CheckIfDisposed();
+
+ if (role < AdamRole.SchemaRole || role > AdamRole.NamingRole)
+ {
+ throw new InvalidEnumArgumentException("role", (int)role, typeof(AdamRole));
+ }
+
+ // set the appropriate attribute on the root dse
+ try
+ {
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ rootDSE.Properties[_becomeRoleOwnerAttrs[(int)role]].Value = 1;
+ rootDSE.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ // invalidate the role collection so that it gets loaded again next time
+ _cachedRoles = null;
+ }
+
+ public void SeizeRoleOwnership(AdamRole role)
+ {
+ // set the "fsmoRoleOwner" attribute on the appropriate role object
+ // to the NTDSAObjectName of this ADAM Instance
+ string roleObjectDN = null;
+
+ CheckIfDisposed();
+
+ switch (role)
+ {
+ case AdamRole.SchemaRole:
+ {
+ roleObjectDN = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.SchemaNamingContext);
+ break;
+ }
+ case AdamRole.NamingRole:
+ {
+ roleObjectDN = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer);
+ break;
+ }
+ default:
+ {
+ throw new InvalidEnumArgumentException("role", (int)role, typeof(AdamRole));
+ }
+ }
+
+ DirectoryEntry roleObjectEntry = null;
+ try
+ {
+ roleObjectEntry = DirectoryEntryManager.GetDirectoryEntry(context, roleObjectDN);
+ roleObjectEntry.Properties[PropertyManager.FsmoRoleOwner].Value = NtdsaObjectName;
+ roleObjectEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (roleObjectEntry != null)
+ {
+ roleObjectEntry.Dispose();
+ }
+ }
+
+ // invalidate the role collection so that it gets loaded again next time
+ _cachedRoles = null;
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override void CheckReplicationConsistency()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the handle
+ GetADAMHandle();
+
+ // call private helper function
+ CheckConsistencyHelper(_ADAMHandle, DirectoryContext.ADAMHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationCursorCollection GetReplicationCursors(string partition)
+ {
+ IntPtr info = (IntPtr)0;
+ int context = 0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ // get the handle
+ GetADAMHandle();
+ info = GetReplicationInfoHelper(_ADAMHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_CURSORS_3_FOR_NC, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_CURSORS_FOR_NC, partition, ref advanced, context, DirectoryContext.ADAMHandle);
+ return ConstructReplicationCursors(_ADAMHandle, advanced, info, partition, this, DirectoryContext.ADAMHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationOperationInformation GetReplicationOperationInformation()
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the handle
+ GetADAMHandle();
+ info = GetReplicationInfoHelper(_ADAMHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_PENDING_OPS, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_PENDING_OPS, null, ref advanced, 0, DirectoryContext.ADAMHandle);
+ return ConstructPendingOperations(info, this, DirectoryContext.ADAMHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationNeighborCollection GetReplicationNeighbors(string partition)
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ // get the handle
+ GetADAMHandle();
+ info = GetReplicationInfoHelper(_ADAMHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_NEIGHBORS, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_NEIGHBORS, partition, ref advanced, 0, DirectoryContext.ADAMHandle);
+ return ConstructNeighbors(info, this, DirectoryContext.ADAMHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationNeighborCollection GetAllReplicationNeighbors()
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the handle
+ GetADAMHandle();
+ info = GetReplicationInfoHelper(_ADAMHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_NEIGHBORS, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_NEIGHBORS, null, ref advanced, 0, DirectoryContext.ADAMHandle);
+ return ConstructNeighbors(info, this, DirectoryContext.ADAMHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationFailureCollection GetReplicationConnectionFailures()
+ {
+ return GetReplicationFailures(DS_REPL_INFO_TYPE.DS_REPL_INFO_KCC_DSA_CONNECT_FAILURES);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ActiveDirectoryReplicationMetadata GetReplicationMetadata(string objectPath)
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (objectPath == null)
+ throw new ArgumentNullException("objectPath");
+
+ if (objectPath.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "objectPath");
+
+ // get the handle
+ GetADAMHandle();
+ info = GetReplicationInfoHelper(_ADAMHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_METADATA_2_FOR_OBJ, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_METADATA_FOR_OBJ, objectPath, ref advanced, 0, DirectoryContext.ADAMHandle);
+ return ConstructMetaData(advanced, info, this, DirectoryContext.ADAMHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override void SyncReplicaFromServer(string partition, string sourceServer)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ if (sourceServer == null)
+ throw new ArgumentNullException("sourceServer");
+
+ if (sourceServer.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "sourceServer");
+
+ // get the dsHandle
+ GetADAMHandle();
+ SyncReplicaHelper(_ADAMHandle, true, partition, sourceServer, 0, DirectoryContext.ADAMHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override void TriggerSyncReplicaFromNeighbors(string partition)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ // get the dsHandle
+ GetADAMHandle();
+ SyncReplicaHelper(_ADAMHandle, true, partition, null, DS_REPSYNC_ASYNCHRONOUS_OPERATION | DS_REPSYNC_ALL_SOURCES, DirectoryContext.ADAMHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override void SyncReplicaFromAllServers(string partition, SyncFromAllServersOptions options)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ // get the dsHandle
+ GetADAMHandle();
+ SyncReplicaAllHelper(_ADAMHandle, _syncAllFunctionPointer, partition, options, SyncFromAllServersCallback, DirectoryContext.ADAMHandle);
+ }
+
+ public void Save()
+ {
+ CheckIfDisposed();
+
+ // only thing to be saved is the ntdsa entry (for default partition)
+ if (_defaultPartitionModified)
+ {
+ DirectoryEntry ntdsaEntry = directoryEntryMgr.GetCachedDirectoryEntry(NtdsaObjectName);
+ try
+ {
+ ntdsaEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ // reset the bools associated with this property
+ _defaultPartitionInitialized = false;
+ _defaultPartitionModified = false;
+ }
+
+ #endregion public methods
+
+ #region public properties
+
+ public ConfigurationSet ConfigurationSet
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_currentConfigSet == null)
+ {
+ DirectoryContext configSetContext = Utils.GetNewDirectoryContext(Name, DirectoryContextType.DirectoryServer, context);
+ _currentConfigSet = ConfigurationSet.GetConfigurationSet(configSetContext);
+ }
+ return _currentConfigSet;
+ }
+ }
+
+ public string HostName
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedHostName == null)
+ {
+ DirectoryEntry serverEntry = directoryEntryMgr.GetCachedDirectoryEntry(ServerObjectName);
+ _cachedHostName = (string)PropertyManager.GetPropertyValue(context, serverEntry, PropertyManager.DnsHostName);
+ }
+ return _cachedHostName;
+ }
+ }
+
+ public int LdapPort
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedLdapPort == -1)
+ {
+ DirectoryEntry ntdsaEntry = directoryEntryMgr.GetCachedDirectoryEntry(NtdsaObjectName);
+ _cachedLdapPort = (int)PropertyManager.GetPropertyValue(context, ntdsaEntry, PropertyManager.MsDSPortLDAP);
+ }
+ return _cachedLdapPort;
+ }
+ }
+
+ public int SslPort
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedSslPort == -1)
+ {
+ DirectoryEntry ntdsaEntry = directoryEntryMgr.GetCachedDirectoryEntry(NtdsaObjectName);
+ _cachedSslPort = (int)PropertyManager.GetPropertyValue(context, ntdsaEntry, PropertyManager.MsDSPortSSL);
+ }
+ return _cachedSslPort;
+ }
+ }
+
+ // Abstract Properties
+
+ public AdamRoleCollection Roles
+ {
+ get
+ {
+ CheckIfDisposed();
+ DirectoryEntry schemaEntry = null;
+ DirectoryEntry partitionsEntry = null;
+
+ try
+ {
+ if (_cachedRoles == null)
+ {
+ // check for the fsmoRoleOwner attribute on the Config and Schema objects
+ ArrayList roleList = new ArrayList();
+ schemaEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.SchemaNamingContext));
+
+ if (NtdsaObjectName.Equals((string)PropertyManager.GetPropertyValue(context, schemaEntry, PropertyManager.FsmoRoleOwner)))
+ {
+ roleList.Add(AdamRole.SchemaRole);
+ }
+
+ partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+
+ if (NtdsaObjectName.Equals((string)PropertyManager.GetPropertyValue(context, partitionsEntry, PropertyManager.FsmoRoleOwner)))
+ {
+ roleList.Add(AdamRole.NamingRole);
+ }
+
+ _cachedRoles = new AdamRoleCollection(roleList);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (schemaEntry != null)
+ {
+ schemaEntry.Dispose();
+ }
+ if (partitionsEntry != null)
+ {
+ partitionsEntry.Dispose();
+ }
+ }
+ return _cachedRoles;
+ }
+ }
+
+ public string DefaultPartition
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (!_defaultPartitionInitialized || _defaultPartitionModified)
+ {
+ DirectoryEntry ntdsaEntry = directoryEntryMgr.GetCachedDirectoryEntry(NtdsaObjectName);
+ try
+ {
+ ntdsaEntry.RefreshCache();
+ if (ntdsaEntry.Properties[PropertyManager.MsDSDefaultNamingContext].Value == null)
+ {
+ // property has not been set
+ _cachedDefaultPartition = null;
+ }
+ else
+ {
+ _cachedDefaultPartition = (string)PropertyManager.GetPropertyValue(context, ntdsaEntry, PropertyManager.MsDSDefaultNamingContext);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ _defaultPartitionInitialized = true;
+ }
+ return _cachedDefaultPartition;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ DirectoryEntry ntdsaEntry = directoryEntryMgr.GetCachedDirectoryEntry(NtdsaObjectName);
+ if (value == null)
+ {
+ if (ntdsaEntry.Properties.Contains(PropertyManager.MsDSDefaultNamingContext))
+ {
+ ntdsaEntry.Properties[PropertyManager.MsDSDefaultNamingContext].Clear();
+ }
+ }
+ else
+ {
+ //
+ // should be in DN format
+ //
+ if (!Utils.IsValidDNFormat(value))
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat), "value");
+ }
+
+ // this value should be one of partitions currently being hosted by
+ // this adam instance
+ if (!Partitions.Contains(value))
+ {
+ throw new ArgumentException(Res.GetString(Res.ServerNotAReplica, value), "value");
+ }
+ ntdsaEntry.Properties[PropertyManager.MsDSDefaultNamingContext].Value = value;
+ }
+ _defaultPartitionModified = true;
+ }
+ }
+
+ public override string IPAddress
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true),
+ DnsPermission(SecurityAction.Assert, Unrestricted = true)
+ ]
+ get
+ {
+ CheckIfDisposed();
+ IPHostEntry hostEntry = Dns.GetHostEntry(HostName);
+ if (hostEntry.AddressList.GetLength(0) > 0)
+ {
+ return (hostEntry.AddressList[0]).ToString();
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+ public override String SiteName
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get
+ {
+ CheckIfDisposed();
+ if (cachedSiteName == null)
+ {
+ DirectoryEntry siteEntry = DirectoryEntryManager.GetDirectoryEntry(context, SiteObjectName);
+ try
+ {
+ cachedSiteName = (string)PropertyManager.GetPropertyValue(context, siteEntry, PropertyManager.Cn);
+ }
+ finally
+ {
+ siteEntry.Dispose();
+ }
+ }
+ return cachedSiteName;
+ }
+ }
+
+ internal String SiteObjectName
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (cachedSiteObjectName == null)
+ {
+ // get the site object name from the server object name
+ // CN=server1,CN=Servers,CN=Site1,CN=Sites
+ // the site object name is the third component onwards
+ string[] components = ServerObjectName.Split(new char[] { ',' });
+ if (components.GetLength(0) < 3)
+ {
+ // should not happen
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.InvalidServerNameFormat));
+ }
+ cachedSiteObjectName = components[2];
+ for (int i = 3; i < components.GetLength(0); i++)
+ {
+ cachedSiteObjectName += "," + components[i];
+ }
+ }
+ return cachedSiteObjectName;
+ }
+ }
+
+ internal String ServerObjectName
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (cachedServerObjectName == null)
+ {
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ try
+ {
+ cachedServerObjectName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.ServerName);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+ }
+ return cachedServerObjectName;
+ }
+ }
+
+ internal String NtdsaObjectName
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (cachedNtdsaObjectName == null)
+ {
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ try
+ {
+ cachedNtdsaObjectName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DsServiceName);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+ }
+ return cachedNtdsaObjectName;
+ }
+ }
+
+ internal Guid NtdsaObjectGuid
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (cachedNtdsaObjectGuid == Guid.Empty)
+ {
+ DirectoryEntry ntdsaEntry = directoryEntryMgr.GetCachedDirectoryEntry(NtdsaObjectName);
+ byte[] guidByteArray = (byte[])PropertyManager.GetPropertyValue(context, ntdsaEntry, PropertyManager.ObjectGuid);
+ cachedNtdsaObjectGuid = new Guid(guidByteArray);
+ }
+ return cachedNtdsaObjectGuid;
+ }
+ }
+
+ public override SyncUpdateCallback SyncFromAllServersCallback
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _userDelegate;
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ _userDelegate = value;
+ }
+ }
+
+ public override ReplicationConnectionCollection InboundConnections
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get
+ {
+ return GetInboundConnectionsHelper();
+ }
+ }
+
+ public override ReplicationConnectionCollection OutboundConnections
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get
+ {
+ return GetOutboundConnectionsHelper();
+ }
+ }
+
+ #endregion public properties
+
+ #region private methods
+
+ private ReplicationFailureCollection GetReplicationFailures(DS_REPL_INFO_TYPE type)
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the handle
+ GetADAMHandle();
+ info = GetReplicationInfoHelper(_ADAMHandle, (int)type, (int)type, null, ref advanced, 0, DirectoryContext.ADAMHandle);
+ return ConstructFailures(info, this, DirectoryContext.ADAMHandle);
+ }
+
+ private void GetADAMHandle()
+ {
+ // this part of the code needs to be synchronized
+ lock (this)
+ {
+ if (_ADAMHandle == IntPtr.Zero)
+ {
+ // get the credentials object
+ if (_authIdentity == IntPtr.Zero)
+ {
+ _authIdentity = Utils.GetAuthIdentity(context, DirectoryContext.ADAMHandle);
+ }
+
+ // DSBind, but we need to have port as annotation specified
+ string bindingString = HostName + ":" + LdapPort;
+
+ _ADAMHandle = Utils.GetDSHandle(bindingString, null, _authIdentity, DirectoryContext.ADAMHandle);
+ }
+ }
+ }
+
+ private void FreeADAMHandle()
+ {
+ lock (this)
+ {
+ // DsUnbind
+ Utils.FreeDSHandle(_ADAMHandle, DirectoryContext.ADAMHandle);
+
+ // free the credentials object
+ Utils.FreeAuthIdentity(_authIdentity, DirectoryContext.ADAMHandle);
+ }
+ }
+
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstanceCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstanceCollection.cs
new file mode 100644
index 0000000000..ba67320a7c
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstanceCollection.cs
@@ -0,0 +1,73 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Globalization;
+ using System.Collections;
+
+ public class AdamInstanceCollection : ReadOnlyCollectionBase
+ {
+ internal AdamInstanceCollection() { }
+
+ internal AdamInstanceCollection(ArrayList values)
+ {
+ if (values != null)
+ {
+ InnerList.AddRange(values);
+ }
+ }
+
+ public AdamInstance this[int index]
+ {
+ get
+ {
+ return (AdamInstance)InnerList[index];
+ }
+ }
+
+ public bool Contains(AdamInstance adamInstance)
+ {
+ if (adamInstance == null)
+ {
+ throw new ArgumentNullException("adamInstance");
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ AdamInstance tmp = (AdamInstance)InnerList[i];
+ if (Utils.Compare(tmp.Name, adamInstance.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(AdamInstance adamInstance)
+ {
+ if (adamInstance == null)
+ {
+ throw new ArgumentNullException("adamInstance");
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ AdamInstance tmp = (AdamInstance)InnerList[i];
+ if (Utils.Compare(tmp.Name, adamInstance.Name) == 0)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ public void CopyTo(AdamInstance[] adamInstances, int index)
+ {
+ InnerList.CopyTo(adamInstances, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADSearcher.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADSearcher.cs
new file mode 100644
index 0000000000..6744db670b
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADSearcher.cs
@@ -0,0 +1,88 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections.Specialized;
+ using System.Security.Permissions;
+
+ internal class ADSearcher
+ {
+ private DirectorySearcher _searcher = null;
+ private static TimeSpan s_defaultTimeSpan = new TimeSpan(0, 120, 0);
+
+ public ADSearcher(DirectoryEntry searchRoot, string filter, string[] propertiesToLoad, SearchScope scope)
+ {
+ _searcher = new DirectorySearcher(searchRoot, filter, propertiesToLoad, scope);
+
+ // set all search preferences
+ // don't cache the results on the client
+ _searcher.CacheResults = false;
+ // set the timeout to 2 minutes
+ _searcher.ClientTimeout = s_defaultTimeSpan;
+ _searcher.ServerPageTimeLimit = s_defaultTimeSpan;
+ // Page Size needs to be set so that we
+ // can get all the results even when the number of results
+ // is greater than the server set limit (1000 in Win2000 and 1500 in Win2003)
+ _searcher.PageSize = 512;
+ }
+
+ public ADSearcher(DirectoryEntry searchRoot, string filter, string[] propertiesToLoad, SearchScope scope, bool pagedSearch, bool cacheResults)
+ {
+ _searcher = new DirectorySearcher(searchRoot, filter, propertiesToLoad, scope);
+ // set proper time out
+ _searcher.ClientTimeout = s_defaultTimeSpan;
+ if (pagedSearch)
+ {
+ _searcher.PageSize = 512;
+ _searcher.ServerPageTimeLimit = s_defaultTimeSpan;
+ }
+
+ if (cacheResults)
+ {
+ _searcher.CacheResults = true;
+ }
+ else
+ {
+ _searcher.CacheResults = false;
+ }
+ }
+
+ public SearchResult FindOne()
+ {
+ return _searcher.FindOne();
+ }
+
+ public SearchResultCollection FindAll()
+ {
+ return _searcher.FindAll();
+ }
+
+ public StringCollection PropertiesToLoad
+ {
+ get
+ {
+ return _searcher.PropertiesToLoad;
+ }
+ }
+
+ public string Filter
+ {
+ get
+ {
+ return _searcher.Filter;
+ }
+ set
+ {
+ _searcher.Filter = value;
+ }
+ }
+
+ public void Dispose()
+ {
+ _searcher.Dispose();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryInterSiteTransport.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryInterSiteTransport.cs
new file mode 100644
index 0000000000..9cff0e3ac5
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryInterSiteTransport.cs
@@ -0,0 +1,370 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ActiveDirectoryInterSiteTransport : IDisposable
+ {
+ private DirectoryContext _context = null;
+ private DirectoryEntry _cachedEntry = null;
+ private ActiveDirectoryTransportType _transport;
+ private bool _disposed = false;
+ private bool _linkRetrieved = false;
+ private bool _bridgeRetrieved = false;
+
+ private ReadOnlySiteLinkCollection _siteLinkCollection = new ReadOnlySiteLinkCollection();
+ private ReadOnlySiteLinkBridgeCollection _bridgeCollection = new ReadOnlySiteLinkBridgeCollection();
+
+ internal ActiveDirectoryInterSiteTransport(DirectoryContext context, ActiveDirectoryTransportType transport, DirectoryEntry entry)
+ {
+ _context = context;
+ _transport = transport;
+ _cachedEntry = entry;
+ }
+
+ public static ActiveDirectoryInterSiteTransport FindByTransportType(DirectoryContext context, ActiveDirectoryTransportType transport)
+ {
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // if target is not specified, then we determin the target from the logon credential, so if it is a local user context, it should fail
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ // more validation for the context, if the target is not null, then it should be either forest name or server name
+ if (context.Name != null)
+ {
+ if (!(context.isRootDomain() || context.isServer() || context.isADAMConfigSet()))
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+
+ if (transport < ActiveDirectoryTransportType.Rpc || transport > ActiveDirectoryTransportType.Smtp)
+ throw new InvalidEnumArgumentException("value", (int)transport, typeof(ActiveDirectoryTransportType));
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // bind to the rootdse to get the configurationnamingcontext
+ DirectoryEntry de;
+
+ try
+ {
+ de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ string containerDN = "CN=Inter-Site Transports,CN=Sites," + config;
+ if (transport == ActiveDirectoryTransportType.Rpc)
+ containerDN = "CN=IP," + containerDN;
+ else
+ containerDN = "CN=SMTP," + containerDN;
+ de = DirectoryEntryManager.GetDirectoryEntry(context, containerDN);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ try
+ {
+ de.RefreshCache(new string[] { "options" });
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // if it is ADAM and transport type is SMTP, throw NotSupportedException.
+ DirectoryEntry tmpDE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ if (Utils.CheckCapability(tmpDE, Capability.ActiveDirectoryApplicationMode) && transport == ActiveDirectoryTransportType.Smtp)
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportTransportSMTP));
+ }
+
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.TransportNotFound, transport.ToString()), typeof(ActiveDirectoryInterSiteTransport), transport.ToString());
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ return new ActiveDirectoryInterSiteTransport(context, transport, de);
+ }
+
+ public ActiveDirectoryTransportType TransportType
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _transport;
+ }
+ }
+
+ public bool IgnoreReplicationSchedule
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int option = 0;
+ try
+ {
+ if (_cachedEntry.Properties.Contains("options"))
+ option = (int)_cachedEntry.Properties["options"][0];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+
+ // NTDSTRANSPORT_OPT_IGNORE_SCHEDULES ( 1 << 0 ) Schedules disabled
+ if ((option & 0x1) != 0)
+ return true;
+ else
+ return false;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int option = 0;
+ try
+ {
+ if (_cachedEntry.Properties.Contains("options"))
+ option = (int)_cachedEntry.Properties["options"][0];
+
+ // NTDSTRANSPORT_OPT_IGNORE_SCHEDULES ( 1 << 0 ) Schedules disabled
+ if (value)
+ option |= 0x1;
+ else
+ option &= (~(0x1));
+
+ _cachedEntry.Properties["options"].Value = option;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ }
+
+ public bool BridgeAllSiteLinks
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int option = 0;
+ try
+ {
+ if (_cachedEntry.Properties.Contains("options"))
+ option = (int)_cachedEntry.Properties["options"][0];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+
+ // NTDSTRANSPORT_OPT_BRIDGES_REQUIRED (1 << 1 ) siteLink bridges are required
+ // That is to say, if this bit is set, it means that all site links are not bridged and user needs to create specific bridge
+ if ((option & 0x2) != 0)
+ return false;
+ else
+ return true;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int option = 0;
+ try
+ {
+ if (_cachedEntry.Properties.Contains("options"))
+ option = (int)_cachedEntry.Properties["options"][0];
+
+ // NTDSTRANSPORT_OPT_BRIDGES_REQUIRED (1 << 1 ) siteLink bridges are required, all site links are not bridged
+ // That is to say, if this bit is set, it means that all site links are not bridged and user needs to create specific bridge
+ // if this bit is not set, all the site links are bridged
+ if (value)
+ option &= (~(0x2));
+ else
+ option |= 0x2;
+
+ _cachedEntry.Properties["options"].Value = option;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ }
+
+ public ReadOnlySiteLinkCollection SiteLinks
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!_linkRetrieved)
+ {
+ _siteLinkCollection.Clear();
+
+ ADSearcher adSearcher = new ADSearcher(_cachedEntry,
+ "(&(objectClass=siteLink)(objectCategory=SiteLink))",
+ new string[] { "cn" },
+ SearchScope.OneLevel);
+ SearchResultCollection results = null;
+
+ try
+ {
+ results = adSearcher.FindAll();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+
+ try
+ {
+ foreach (SearchResult result in results)
+ {
+ DirectoryEntry connectionEntry = result.GetDirectoryEntry();
+ string cn = (string)PropertyManager.GetSearchResultPropertyValue(result, PropertyManager.Cn);
+ ActiveDirectorySiteLink link = new ActiveDirectorySiteLink(_context, cn, _transport, true, connectionEntry);
+ _siteLinkCollection.Add(link);
+ }
+ }
+ finally
+ {
+ results.Dispose();
+ }
+
+ _linkRetrieved = true;
+ }
+
+ return _siteLinkCollection;
+ }
+ }
+
+ public ReadOnlySiteLinkBridgeCollection SiteLinkBridges
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!_bridgeRetrieved)
+ {
+ _bridgeCollection.Clear();
+
+ ADSearcher adSearcher = new ADSearcher(_cachedEntry,
+ "(&(objectClass=siteLinkBridge)(objectCategory=SiteLinkBridge))",
+ new string[] { "cn" },
+ SearchScope.OneLevel);
+ SearchResultCollection results = null;
+
+ try
+ {
+ results = adSearcher.FindAll();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+
+ try
+ {
+ foreach (SearchResult result in results)
+ {
+ DirectoryEntry connectionEntry = result.GetDirectoryEntry();
+ string cn = (string)PropertyManager.GetSearchResultPropertyValue(result, PropertyManager.Cn);
+ ActiveDirectorySiteLinkBridge bridge = new ActiveDirectorySiteLinkBridge(_context, cn, _transport, true);
+ bridge.cachedEntry = connectionEntry;
+ _bridgeCollection.Add(bridge);
+ }
+ }
+ finally
+ {
+ results.Dispose();
+ }
+
+ _bridgeRetrieved = true;
+ }
+
+ return _bridgeCollection;
+ }
+ }
+
+ public void Save()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ _cachedEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return DirectoryEntryManager.GetDirectoryEntryInternal(_context, _cachedEntry.Path);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ public override string ToString()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _transport.ToString();
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // free other state (managed objects)
+ if (_cachedEntry != null)
+ _cachedEntry.Dispose();
+ }
+
+ // free your own state (unmanaged objects)
+
+ _disposed = true;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryPartition.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryPartition.cs
new file mode 100644
index 0000000000..c49fd6959d
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryPartition.cs
@@ -0,0 +1,96 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Security.Permissions;
+
+ public abstract class ActiveDirectoryPartition : IDisposable
+ {
+ private bool _disposed = false;
+ internal string partitionName = null;
+ internal DirectoryContext context = null;
+ internal DirectoryEntryManager directoryEntryMgr = null;
+
+ #region constructors
+ protected ActiveDirectoryPartition()
+ {
+ }
+
+ internal ActiveDirectoryPartition(DirectoryContext context, string name)
+ {
+ this.context = context;
+ this.partitionName = name;
+ }
+ #endregion constructors
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ // private Dispose method
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ // check if this is an explicit Dispose
+ // only then clean up the directory entries
+ if (disposing)
+ {
+ // dispose all directory entries
+ foreach (DirectoryEntry entry in directoryEntryMgr.GetCachedDirectoryEntries())
+ {
+ entry.Dispose();
+ }
+ }
+ _disposed = true;
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public abstract DirectoryEntry GetDirectoryEntry();
+
+ #endregion public methods
+
+ #region public properties
+ // Public Properties
+ public string Name
+ {
+ get
+ {
+ CheckIfDisposed();
+ return partitionName;
+ }
+ }
+ #endregion public properties
+
+ #region private methods
+
+ internal void CheckIfDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryReplicationMetaData.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryReplicationMetaData.cs
new file mode 100644
index 0000000000..679530df3c
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryReplicationMetaData.cs
@@ -0,0 +1,103 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+ using System.Globalization;
+
+ public class ActiveDirectoryReplicationMetadata : DictionaryBase
+ {
+ private DirectoryServer _server = null;
+ private Hashtable _nameTable = null;
+ private AttributeMetadataCollection _dataValueCollection = new AttributeMetadataCollection();
+ private ReadOnlyStringCollection _dataNameCollection = new ReadOnlyStringCollection();
+
+ internal ActiveDirectoryReplicationMetadata(DirectoryServer server)
+ {
+ _server = server;
+ Hashtable tempNameTable = new Hashtable();
+ _nameTable = Hashtable.Synchronized(tempNameTable);
+ }
+
+ public AttributeMetadata this[string name]
+ {
+ get
+ {
+ string tempName = name.ToLower(CultureInfo.InvariantCulture);
+ if (Contains(tempName))
+ {
+ return (AttributeMetadata)InnerHashtable[tempName];
+ }
+ else
+ return null;
+ }
+ }
+
+ public ReadOnlyStringCollection AttributeNames
+ {
+ get
+ {
+ return _dataNameCollection;
+ }
+ }
+
+ public AttributeMetadataCollection Values
+ {
+ get
+ {
+ return _dataValueCollection;
+ }
+ }
+
+ public bool Contains(string attributeName)
+ {
+ string tempName = attributeName.ToLower(CultureInfo.InvariantCulture);
+ return Dictionary.Contains(tempName);
+ }
+
+ /// <include file='doc\ResultPropertyCollection.uex' path='docs/doc[@for="ResultPropertyCollection.CopyTo"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public void CopyTo(AttributeMetadata[] array, int index)
+ {
+ Dictionary.Values.CopyTo((Array)array, index);
+ }
+
+ private void Add(string name, AttributeMetadata value)
+ {
+ Dictionary.Add(name.ToLower(CultureInfo.InvariantCulture), value);
+
+ _dataNameCollection.Add(name);
+ _dataValueCollection.Add(value);
+ }
+
+ internal void AddHelper(int count, IntPtr info, bool advanced)
+ {
+ IntPtr addr = (IntPtr)0;
+
+ for (int i = 0; i < count; i++)
+ {
+ if (advanced)
+ {
+ addr = IntPtr.Add(info, Marshal.SizeOf(typeof(int)) * 2 + i * Marshal.SizeOf(typeof(DS_REPL_ATTR_META_DATA_2)));
+
+ AttributeMetadata managedMetaData = new AttributeMetadata(addr, true, _server, _nameTable);
+ Add(managedMetaData.Name, managedMetaData);
+ }
+ else
+ {
+ addr = IntPtr.Add(info, Marshal.SizeOf(typeof(int)) * 2 + i * Marshal.SizeOf(typeof(DS_REPL_ATTR_META_DATA)));
+
+ AttributeMetadata managedMetaData = new AttributeMetadata(addr, false, _server, _nameTable);
+ Add(managedMetaData.Name, managedMetaData);
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchedule.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchedule.cs
new file mode 100644
index 0000000000..a27067ce81
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchedule.cs
@@ -0,0 +1,261 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Globalization;
+ using System.ComponentModel;
+
+ public enum HourOfDay
+ {
+ Zero,
+ One,
+ Two,
+ Three,
+ Four,
+ Five,
+ Six,
+ Seven,
+ Eight,
+ Nine,
+ Ten,
+ Eleven,
+ Twelve,
+ Thirteen,
+ Fourteen,
+ Fifteen,
+ Sixteen,
+ Seventeen,
+ Eighteen,
+ Nineteen,
+ Twenty,
+ TwentyOne,
+ TwentyTwo,
+ TwentyThree
+ }
+
+ public enum MinuteOfHour
+ {
+ Zero = 0,
+ Fifteen = 15,
+ Thirty = 30,
+ FortyFive = 45
+ }
+
+ public class ActiveDirectorySchedule
+ {
+ // 24*7*4 = 672
+ private bool[] _scheduleArray = new bool[672];
+ private long _utcOffSet = 0;
+
+ public ActiveDirectorySchedule()
+ {
+ // need to get the offset between local time and UTC time
+ _utcOffSet = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Ticks / TimeSpan.TicksPerHour;
+ }
+
+ public ActiveDirectorySchedule(ActiveDirectorySchedule schedule) : this()
+ {
+ if (schedule == null)
+ throw new ArgumentNullException();
+
+ bool[] tmpSchedule = schedule._scheduleArray;
+ for (int i = 0; i < 672; i++)
+ _scheduleArray[i] = tmpSchedule[i];
+ }
+
+ internal ActiveDirectorySchedule(bool[] schedule) : this()
+ {
+ for (int i = 0; i < 672; i++)
+ _scheduleArray[i] = schedule[i];
+ }
+
+ public bool[,,] RawSchedule
+ {
+ get
+ {
+ bool[,,] tmp = new bool[7, 24, 4];
+ for (int i = 0; i < 7; i++)
+ for (int j = 0; j < 24; j++)
+ for (int k = 0; k < 4; k++)
+ tmp[i, j, k] = _scheduleArray[i * 24 * 4 + j * 4 + k];
+ return tmp;
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ ValidateRawArray(value);
+
+ for (int i = 0; i < 7; i++)
+ for (int j = 0; j < 24; j++)
+ for (int k = 0; k < 4; k++)
+ _scheduleArray[i * 24 * 4 + j * 4 + k] = value[i, j, k];
+ }
+ }
+
+ public void SetSchedule(DayOfWeek day, HourOfDay fromHour, MinuteOfHour fromMinute, HourOfDay toHour, MinuteOfHour toMinute)
+ {
+ if (day < DayOfWeek.Sunday || day > DayOfWeek.Saturday)
+ throw new InvalidEnumArgumentException("day", (int)day, typeof(DayOfWeek));
+
+ if (fromHour < HourOfDay.Zero || fromHour > HourOfDay.TwentyThree)
+ throw new InvalidEnumArgumentException("fromHour", (int)fromHour, typeof(HourOfDay));
+
+ if (fromMinute != MinuteOfHour.Zero && fromMinute != MinuteOfHour.Fifteen && fromMinute != MinuteOfHour.Thirty && fromMinute != MinuteOfHour.FortyFive)
+ throw new InvalidEnumArgumentException("fromMinute", (int)fromMinute, typeof(MinuteOfHour));
+
+ if (toHour < HourOfDay.Zero || toHour > HourOfDay.TwentyThree)
+ throw new InvalidEnumArgumentException("toHour", (int)toHour, typeof(HourOfDay));
+
+ if (toMinute != MinuteOfHour.Zero && toMinute != MinuteOfHour.Fifteen && toMinute != MinuteOfHour.Thirty && toMinute != MinuteOfHour.FortyFive)
+ throw new InvalidEnumArgumentException("toMinute", (int)toMinute, typeof(MinuteOfHour));
+
+ // end time should be later than the start time
+ if ((int)fromHour * 60 + (int)fromMinute > (int)toHour * 60 + (int)toMinute)
+ throw new ArgumentException(Res.GetString(Res.InvalidTime));
+
+ // set the availability
+ int startPoint = (int)day * 24 * 4 + (int)fromHour * 4 + (int)fromMinute / 15;
+ int endPoint = (int)day * 24 * 4 + (int)toHour * 4 + (int)toMinute / 15;
+ for (int i = startPoint; i <= endPoint; i++)
+ _scheduleArray[i] = true;
+ }
+
+ public void SetSchedule(DayOfWeek[] days, HourOfDay fromHour, MinuteOfHour fromMinute, HourOfDay toHour, MinuteOfHour toMinute)
+ {
+ if (days == null)
+ throw new ArgumentNullException("days");
+
+ for (int i = 0; i < days.Length; i++)
+ {
+ if (days[i] < DayOfWeek.Sunday || days[i] > DayOfWeek.Saturday)
+ throw new InvalidEnumArgumentException("days", (int)days[i], typeof(DayOfWeek));
+ }
+
+ for (int i = 0; i < days.Length; i++)
+ SetSchedule(days[i], fromHour, fromMinute, toHour, toMinute);
+ }
+
+ public void SetDailySchedule(HourOfDay fromHour, MinuteOfHour fromMinute, HourOfDay toHour, MinuteOfHour toMinute)
+ {
+ for (int i = 0; i < 7; i++)
+ {
+ SetSchedule((DayOfWeek)i, fromHour, fromMinute, toHour, toMinute);
+ }
+ }
+
+ public void ResetSchedule()
+ {
+ for (int i = 0; i < 672; i++)
+ _scheduleArray[i] = false;
+ }
+
+ private void ValidateRawArray(bool[,,] array)
+ {
+ if (array.Length != 672)
+ throw new ArgumentException("value");
+
+ int len1 = array.GetLength(0);
+ int len2 = array.GetLength(1);
+ int len3 = array.GetLength(2);
+
+ if (len1 != 7 || len2 != 24 || len3 != 4)
+ throw new ArgumentException("value");
+ }
+
+ internal byte[] GetUnmanagedSchedule()
+ {
+ byte val = 0;
+ int index = 0;
+ byte[] unmanagedSchedule = new byte[188];
+ int unmanagedScheduleIndex = 0;
+
+ // set size
+ unmanagedSchedule[0] = 188;
+ // set number of schedule
+ unmanagedSchedule[8] = 1;
+ // set offset
+ unmanagedSchedule[16] = 20;
+
+ // 20 is the offset in the unmanaged structure where the actual schedule begins
+ for (int i = 20; i < 188; i++)
+ {
+ val = 0;
+ index = (i - 20) * 4;
+
+ if (_scheduleArray[index])
+ val |= 1;
+ if (_scheduleArray[index + 1])
+ val |= 2;
+ if (_scheduleArray[index + 2])
+ val |= 4;
+ if (_scheduleArray[index + 3])
+ val |= 8;
+
+ //recalculate index position taking utc offset into account
+ //ensure circular array in both directions (with index from 20 to 187)
+ unmanagedScheduleIndex = i - (int)_utcOffSet;
+ if (unmanagedScheduleIndex >= 188)
+ {
+ // falling off higher end (move back)
+ unmanagedScheduleIndex = unmanagedScheduleIndex - 188 + 20;
+ }
+ else if (unmanagedScheduleIndex < 20)
+ {
+ // falling off lower end (move forward)
+ unmanagedScheduleIndex = 188 - (20 - unmanagedScheduleIndex);
+ }
+ unmanagedSchedule[unmanagedScheduleIndex] = val;
+ }
+
+ return unmanagedSchedule;
+ }
+
+ internal void SetUnmanagedSchedule(byte[] unmanagedSchedule)
+ {
+ int val = 0;
+ int index = 0;
+ int unmanagedScheduleIndex = 0;
+
+ // 20 is the offset in the unmanaged structure where the actual schedule begins
+ for (int i = 20; i < 188; i++)
+ {
+ val = 0;
+ index = (i - 20) * 4;
+
+ //recalculate index position taking utc offset into account
+ //ensure circular array in both directions (with index from 20 to 187)
+ unmanagedScheduleIndex = i - (int)_utcOffSet;
+ if (unmanagedScheduleIndex >= 188)
+ {
+ // falling off higher end (move back)
+ unmanagedScheduleIndex = unmanagedScheduleIndex - 188 + 20;
+ }
+ else if (unmanagedScheduleIndex < 20)
+ {
+ // falling off lower end (move forward)
+ unmanagedScheduleIndex = 188 - (20 - unmanagedScheduleIndex);
+ }
+ val = unmanagedSchedule[unmanagedScheduleIndex];
+ if ((val & 1) != 0)
+ _scheduleArray[index] = true;
+
+ if ((val & 2) != 0)
+ _scheduleArray[index + 1] = true;
+
+ if ((val & 4) != 0)
+ _scheduleArray[index + 2] = true;
+
+ if ((val & 8) != 0)
+ _scheduleArray[index + 3] = true;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchema.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchema.cs
new file mode 100644
index 0000000000..4e9530000a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchema.cs
@@ -0,0 +1,587 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Text;
+ using System.Collections;
+ using System.ComponentModel;
+ using System.Runtime.InteropServices;
+ using System.Security.Permissions;
+
+ public enum SchemaClassType : int
+ {
+ Type88 = 0,
+ Structural = 1,
+ Abstract = 2,
+ Auxiliary = 3
+ }
+
+ [Flags]
+ public enum PropertyTypes : int
+ {
+ Indexed = 2,
+ InGlobalCatalog = 4
+ }
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ActiveDirectorySchema : ActiveDirectoryPartition
+ {
+ private bool _disposed = false;
+ private DirectoryEntry _schemaEntry = null;
+ private DirectoryEntry _abstractSchemaEntry = null;
+ private DirectoryServer _cachedSchemaRoleOwner = null;
+
+ #region constructors
+ internal ActiveDirectorySchema(DirectoryContext context, string distinguishedName)
+ : base(context, distinguishedName)
+ {
+ this.directoryEntryMgr = new DirectoryEntryManager(context);
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(context, distinguishedName);
+ }
+
+ internal ActiveDirectorySchema(DirectoryContext context, string distinguishedName, DirectoryEntryManager directoryEntryMgr)
+ : base(context, distinguishedName)
+ {
+ this.directoryEntryMgr = directoryEntryMgr;
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(context, distinguishedName);
+ }
+ #endregion constructors
+
+ #region IDisposable
+ // private Dispose method
+ protected override void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ try
+ {
+ // if there are any managed or unmanaged
+ // resources to be freed, those should be done here
+ // if not an explicit dispose only unmanaged resources should
+ // be disposed
+ if (disposing)
+ {
+ // dispose schema entry
+ if (_schemaEntry != null)
+ {
+ _schemaEntry.Dispose();
+ _schemaEntry = null;
+ }
+ // dispose the abstract schema entry
+ if (_abstractSchemaEntry != null)
+ {
+ _abstractSchemaEntry.Dispose();
+ _abstractSchemaEntry = null;
+ }
+ }
+ _disposed = true;
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+ public static ActiveDirectorySchema GetSchema(DirectoryContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ // contexttype should be Forest, DirectoryServer or ConfigurationSet
+ if ((context.ContextType != DirectoryContextType.Forest) &&
+ (context.ContextType != DirectoryContextType.ConfigurationSet) &&
+ (context.ContextType != DirectoryContextType.DirectoryServer))
+ {
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ContextNotAssociatedWithDomain), typeof(ActiveDirectorySchema), null);
+ }
+
+ if (context.Name != null)
+ {
+ // the target should be a valid forest name or a server
+ if (!((context.isRootDomain()) || (context.isADAMConfigSet()) || (context.isServer())))
+ {
+ if (context.ContextType == DirectoryContextType.Forest)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestNotFound), typeof(ActiveDirectorySchema), context.Name);
+ }
+ else if (context.ContextType == DirectoryContextType.ConfigurationSet)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ConfigSetNotFound), typeof(ActiveDirectorySchema), context.Name);
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ServerNotFound, context.Name), typeof(ActiveDirectorySchema), null);
+ }
+ }
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ DirectoryEntryManager directoryEntryMgr = new DirectoryEntryManager(context);
+ string schemaNC = null;
+ try
+ {
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+
+ if ((context.isServer()) && (!Utils.CheckCapability(rootDSE, Capability.ActiveDirectoryOrADAM)))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ServerNotFound, context.Name), typeof(ActiveDirectorySchema), null);
+ }
+
+ schemaNC = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.SchemaNamingContext);
+ }
+ catch (COMException e)
+ {
+ int errorCode = e.ErrorCode;
+
+ if (errorCode == unchecked((int)0x8007203a))
+ {
+ if (context.ContextType == DirectoryContextType.Forest)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestNotFound), typeof(ActiveDirectorySchema), context.Name);
+ }
+ else if (context.ContextType == DirectoryContextType.ConfigurationSet)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ConfigSetNotFound), typeof(ActiveDirectorySchema), context.Name);
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ServerNotFound, context.Name), typeof(ActiveDirectorySchema), null);
+ }
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ if (context.ContextType == DirectoryContextType.ConfigurationSet)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ConfigSetNotFound), typeof(ActiveDirectorySchema), context.Name);
+ }
+ else
+ throw;
+ }
+
+ return new ActiveDirectorySchema(context, schemaNC, directoryEntryMgr);
+ }
+
+ public void RefreshSchema()
+ {
+ CheckIfDisposed();
+
+ // Refresh the schema on the server
+ DirectoryEntry rootDSE = null;
+ try
+ {
+ rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ rootDSE.Properties[PropertyManager.SchemaUpdateNow].Value = 1;
+ rootDSE.CommitChanges();
+
+ // refresh the schema on the client
+ // bind to the abstract schema
+ if (_abstractSchemaEntry == null)
+ {
+ _abstractSchemaEntry = directoryEntryMgr.GetCachedDirectoryEntry("Schema");
+ }
+ _abstractSchemaEntry.RefreshCache();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (rootDSE != null)
+ {
+ rootDSE.Dispose();
+ }
+ }
+ }
+
+ //
+ // This method finds only among non-defunct classes
+ //
+ public ActiveDirectorySchemaClass FindClass(string ldapDisplayName)
+ {
+ CheckIfDisposed();
+ return ActiveDirectorySchemaClass.FindByName(context, ldapDisplayName);
+ }
+
+ //
+ // This method finds only among defunct classes
+ //
+ public ActiveDirectorySchemaClass FindDefunctClass(string commonName)
+ {
+ CheckIfDisposed();
+
+ if (commonName == null)
+ {
+ throw new ArgumentNullException("commonName");
+ }
+
+ if (commonName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "commonName");
+ }
+
+ // this will bind to the schema container and load the properties of this class
+ // (will also check whether or not the class exists)
+ Hashtable propertiesFromServer = ActiveDirectorySchemaClass.GetPropertiesFromSchemaContainer(context, _schemaEntry, commonName, true /* isDefunctOnServer */);
+ ActiveDirectorySchemaClass schemaClass = new ActiveDirectorySchemaClass(context, commonName, propertiesFromServer, _schemaEntry);
+
+ return schemaClass;
+ }
+
+ //
+ // This method returns only non-defunct classes
+ //
+ public ReadOnlyActiveDirectorySchemaClassCollection FindAllClasses()
+ {
+ CheckIfDisposed();
+ string filter = "(&(" + PropertyManager.ObjectCategory + "=classSchema)" +
+ "(!(" + PropertyManager.IsDefunct + "=TRUE)))";
+ return GetAllClasses(context, _schemaEntry, filter);
+ }
+
+ //
+ // This method returns only non-defunct classes of the specified type
+ //
+ public ReadOnlyActiveDirectorySchemaClassCollection FindAllClasses(SchemaClassType type)
+ {
+ CheckIfDisposed();
+
+ // validate the type
+ if (type < SchemaClassType.Type88 || type > SchemaClassType.Auxiliary)
+ {
+ throw new InvalidEnumArgumentException("type", (int)type, typeof(SchemaClassType));
+ }
+
+ string filter = "(&(" + PropertyManager.ObjectCategory + "=classSchema)" +
+ "(" + PropertyManager.ObjectClassCategory + "=" + (int)type + ")" +
+ "(!(" + PropertyManager.IsDefunct + "=TRUE)))";
+ return GetAllClasses(context, _schemaEntry, filter);
+ }
+
+ //
+ // This method returns only defunct classes
+ //
+ public ReadOnlyActiveDirectorySchemaClassCollection FindAllDefunctClasses()
+ {
+ CheckIfDisposed();
+
+ string filter = "(&(" + PropertyManager.ObjectCategory + "=classSchema)" +
+ "(" + PropertyManager.IsDefunct + "=TRUE))";
+ return GetAllClasses(context, _schemaEntry, filter);
+ }
+
+ //
+ // This method finds only among non-defunct properties
+ //
+ public ActiveDirectorySchemaProperty FindProperty(string ldapDisplayName)
+ {
+ CheckIfDisposed();
+ return ActiveDirectorySchemaProperty.FindByName(context, ldapDisplayName);
+ }
+
+ //
+ // This method finds only among defunct properties
+ //
+ public ActiveDirectorySchemaProperty FindDefunctProperty(string commonName)
+ {
+ CheckIfDisposed();
+
+ if (commonName == null)
+ {
+ throw new ArgumentNullException("commonName");
+ }
+
+ if (commonName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "commonName");
+ }
+
+ // this will bind to the schema container and load the properties of this property
+ // (will also check whether or not the property exists)
+ SearchResult propertiesFromServer = ActiveDirectorySchemaProperty.GetPropertiesFromSchemaContainer(context, _schemaEntry, commonName, true /* isDefunctOnServer */);
+ ActiveDirectorySchemaProperty schemaProperty = new ActiveDirectorySchemaProperty(context, commonName, propertiesFromServer, _schemaEntry);
+
+ return schemaProperty;
+ }
+
+ //
+ // This method returns only non-defunct properties
+ //
+ public ReadOnlyActiveDirectorySchemaPropertyCollection FindAllProperties()
+ {
+ CheckIfDisposed();
+
+ string filter = "(&(" + PropertyManager.ObjectCategory + "=attributeSchema)" +
+ "(!(" + PropertyManager.IsDefunct + "=TRUE)))";
+ return GetAllProperties(context, _schemaEntry, filter);
+ }
+
+ //
+ // This method returns only non-defunct properties meeting the specified criteria
+ //
+ public ReadOnlyActiveDirectorySchemaPropertyCollection FindAllProperties(PropertyTypes type)
+ {
+ CheckIfDisposed();
+
+ // check validity of type
+ if ((type & (~(PropertyTypes.Indexed | PropertyTypes.InGlobalCatalog))) != 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidFlags), "type");
+ }
+
+ // start the filter
+ StringBuilder str = new StringBuilder(25);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=attributeSchema)");
+ str.Append("(!(");
+ str.Append(PropertyManager.IsDefunct);
+ str.Append("=TRUE))");
+
+ if (((int)type & (int)PropertyTypes.Indexed) != 0)
+ {
+ str.Append("(");
+ str.Append(PropertyManager.SearchFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SearchFlags.IsIndexed);
+ str.Append(")");
+ }
+
+ if (((int)type & (int)PropertyTypes.InGlobalCatalog) != 0)
+ {
+ str.Append("(");
+ str.Append(PropertyManager.IsMemberOfPartialAttributeSet);
+ str.Append("=TRUE)");
+ }
+
+ str.Append(")"); // end filter
+ return GetAllProperties(context, _schemaEntry, str.ToString());
+ }
+
+ //
+ // This method returns only defunct properties
+ //
+ public ReadOnlyActiveDirectorySchemaPropertyCollection FindAllDefunctProperties()
+ {
+ CheckIfDisposed();
+
+ string filter = "(&(" + PropertyManager.ObjectCategory + "=attributeSchema)" +
+ "(" + PropertyManager.IsDefunct + "=TRUE))";
+ return GetAllProperties(context, _schemaEntry, filter);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override DirectoryEntry GetDirectoryEntry()
+ {
+ CheckIfDisposed();
+ return DirectoryEntryManager.GetDirectoryEntry(context, Name);
+ }
+
+ public static ActiveDirectorySchema GetCurrentSchema()
+ {
+ return ActiveDirectorySchema.GetSchema(new DirectoryContext(DirectoryContextType.Forest));
+ }
+
+ #endregion public methods
+
+ #region public properties
+
+ public DirectoryServer SchemaRoleOwner
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedSchemaRoleOwner == null)
+ {
+ _cachedSchemaRoleOwner = GetSchemaRoleOwner();
+ }
+ return _cachedSchemaRoleOwner;
+ }
+ }
+
+ #endregion public properties
+
+ #region private methods
+ internal static ReadOnlyActiveDirectorySchemaPropertyCollection GetAllProperties(DirectoryContext context, DirectoryEntry schemaEntry, string filter)
+ {
+ ArrayList propertyList = new ArrayList();
+
+ string[] propertiesToLoad = new string[3];
+ propertiesToLoad[0] = PropertyManager.LdapDisplayName;
+ propertiesToLoad[1] = PropertyManager.Cn;
+ propertiesToLoad[2] = PropertyManager.IsDefunct;
+
+ ADSearcher searcher = new ADSearcher(schemaEntry, filter, propertiesToLoad, SearchScope.OneLevel);
+ SearchResultCollection resCol = null;
+ try
+ {
+ resCol = searcher.FindAll();
+ foreach (SearchResult res in resCol)
+ {
+ string ldapDisplayName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.LdapDisplayName);
+ DirectoryEntry directoryEntry = res.GetDirectoryEntry();
+
+ directoryEntry.AuthenticationType = Utils.DefaultAuthType;
+ directoryEntry.Username = context.UserName;
+ directoryEntry.Password = context.Password;
+
+ bool isDefunct = false;
+
+ if ((res.Properties[PropertyManager.IsDefunct] != null) && (res.Properties[PropertyManager.IsDefunct].Count > 0))
+ {
+ isDefunct = (bool)res.Properties[PropertyManager.IsDefunct][0];
+ }
+
+ if (isDefunct)
+ {
+ string commonName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.Cn);
+ propertyList.Add(new ActiveDirectorySchemaProperty(context, commonName, ldapDisplayName, directoryEntry, schemaEntry));
+ }
+ else
+ {
+ propertyList.Add(new ActiveDirectorySchemaProperty(context, ldapDisplayName, directoryEntry, schemaEntry));
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ // dispose off the result collection
+ if (resCol != null)
+ {
+ resCol.Dispose();
+ }
+ }
+
+ return new ReadOnlyActiveDirectorySchemaPropertyCollection(propertyList);
+ }
+
+ internal static ReadOnlyActiveDirectorySchemaClassCollection GetAllClasses(DirectoryContext context, DirectoryEntry schemaEntry, string filter)
+ {
+ ArrayList classList = new ArrayList();
+
+ string[] propertiesToLoad = new string[3];
+ propertiesToLoad[0] = PropertyManager.LdapDisplayName;
+ propertiesToLoad[1] = PropertyManager.Cn;
+ propertiesToLoad[2] = PropertyManager.IsDefunct;
+
+ ADSearcher searcher = new ADSearcher(schemaEntry, filter, propertiesToLoad, SearchScope.OneLevel);
+ SearchResultCollection resCol = null;
+ try
+ {
+ resCol = searcher.FindAll();
+ foreach (SearchResult res in resCol)
+ {
+ string ldapDisplayName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.LdapDisplayName);
+ DirectoryEntry directoryEntry = res.GetDirectoryEntry();
+
+ directoryEntry.AuthenticationType = Utils.DefaultAuthType;
+ directoryEntry.Username = context.UserName;
+ directoryEntry.Password = context.Password;
+
+ bool isDefunct = false;
+
+ if ((res.Properties[PropertyManager.IsDefunct] != null) && (res.Properties[PropertyManager.IsDefunct].Count > 0))
+ {
+ isDefunct = (bool)res.Properties[PropertyManager.IsDefunct][0];
+ }
+
+ if (isDefunct)
+ {
+ string commonName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.Cn);
+ classList.Add(new ActiveDirectorySchemaClass(context, commonName, ldapDisplayName, directoryEntry, schemaEntry));
+ }
+ else
+ {
+ classList.Add(new ActiveDirectorySchemaClass(context, ldapDisplayName, directoryEntry, schemaEntry));
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ // dispose off the result collection
+ if (resCol != null)
+ {
+ resCol.Dispose();
+ }
+ }
+
+ return new ReadOnlyActiveDirectorySchemaClassCollection(classList);
+ }
+
+ private DirectoryServer GetSchemaRoleOwner()
+ {
+ try
+ {
+ _schemaEntry.RefreshCache();
+
+ if (context.isADAMConfigSet())
+ {
+ // ADAM
+ string adamInstName = Utils.GetAdamDnsHostNameFromNTDSA(context, (string)PropertyManager.GetPropertyValue(context, _schemaEntry, PropertyManager.FsmoRoleOwner));
+ DirectoryContext adamInstContext = Utils.GetNewDirectoryContext(adamInstName, DirectoryContextType.DirectoryServer, context);
+ return new AdamInstance(adamInstContext, adamInstName);
+ }
+ else
+ {
+ // could be AD or adam server
+
+ DirectoryServer server = null;
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+
+ if (Utils.CheckCapability(rootDSE, Capability.ActiveDirectory))
+ {
+ string dcName = Utils.GetDnsHostNameFromNTDSA(context, (string)PropertyManager.GetPropertyValue(context, _schemaEntry, PropertyManager.FsmoRoleOwner));
+ DirectoryContext dcContext = Utils.GetNewDirectoryContext(dcName, DirectoryContextType.DirectoryServer, context);
+ server = new DomainController(dcContext, dcName);
+ }
+ else
+ {
+ // ADAM case again
+ string adamInstName = Utils.GetAdamDnsHostNameFromNTDSA(context, (string)PropertyManager.GetPropertyValue(context, _schemaEntry, PropertyManager.FsmoRoleOwner));
+ DirectoryContext adamInstContext = Utils.GetNewDirectoryContext(adamInstName, DirectoryContextType.DirectoryServer, context);
+ server = new AdamInstance(adamInstContext, adamInstName);
+ }
+ return server;
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClass.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClass.cs
new file mode 100644
index 0000000000..eb427387c4
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClass.cs
@@ -0,0 +1,1522 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Text;
+ using System.ComponentModel;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Security.AccessControl;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ActiveDirectorySchemaClass : IDisposable
+ {
+ // private variables
+ private DirectoryEntry _classEntry = null;
+ private DirectoryEntry _schemaEntry = null;
+ private DirectoryEntry _abstractClassEntry = null;
+ private NativeComInterfaces.IAdsClass _iadsClass = null;
+ private DirectoryContext _context = null;
+ internal bool isBound = false;
+ private bool _disposed = false;
+ private ActiveDirectorySchema _schema = null;
+ private bool _propertiesFromSchemaContainerInitialized = false;
+ private bool _isDefunctOnServer = false;
+ private Hashtable _propertyValuesFromServer = null;
+
+ // private variables for all the properties of this class
+ private string _ldapDisplayName = null;
+ private string _commonName = null;
+ private string _oid = null;
+ private string _description = null;
+ private bool _descriptionInitialized = false;
+ private bool _isDefunct = false;
+ private ActiveDirectorySchemaClassCollection _possibleSuperiors = null;
+ private ActiveDirectorySchemaClassCollection _auxiliaryClasses = null;
+ private ReadOnlyActiveDirectorySchemaClassCollection _possibleInferiors = null;
+ private ActiveDirectorySchemaPropertyCollection _mandatoryProperties = null;
+ private ActiveDirectorySchemaPropertyCollection _optionalProperties = null;
+ private ActiveDirectorySchemaClass _subClassOf = null;
+ private SchemaClassType _type = SchemaClassType.Structural;
+ private bool _typeInitialized = false;
+ private byte[] _schemaGuidBinaryForm = null;
+ private string _defaultSDSddlForm = null;
+ private bool _defaultSDSddlFormInitialized = false;
+
+ #region constructors
+ public ActiveDirectorySchemaClass(DirectoryContext context, string ldapDisplayName)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ if (context.Name != null)
+ {
+ // the target should be a valid forest name or a server
+ if (!((context.isRootDomain()) || (context.isADAMConfigSet()) || (context.isServer())))
+ {
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+ }
+
+ if (ldapDisplayName == null)
+ {
+ throw new ArgumentNullException("ldapDisplayName");
+ }
+
+ if (ldapDisplayName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "ldapDisplayName");
+ }
+
+ _context = new DirectoryContext(context);
+
+ // validate the context
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.SchemaNamingContext);
+ _schemaEntry.Bind(true);
+
+ _ldapDisplayName = ldapDisplayName;
+ // the common name will default to the ldap display name
+ _commonName = ldapDisplayName;
+
+ // set the bind flag
+ this.isBound = false;
+ }
+
+ // Internal constructor
+ internal ActiveDirectorySchemaClass(DirectoryContext context, string ldapDisplayName, DirectoryEntry classEntry, DirectoryEntry schemaEntry)
+ {
+ _context = context;
+ _ldapDisplayName = ldapDisplayName;
+ _classEntry = classEntry;
+ _schemaEntry = schemaEntry;
+
+ // this constructor is only called for non-defunct classes
+ _isDefunctOnServer = false;
+ _isDefunct = _isDefunctOnServer;
+
+ // initialize the directory entry for the abstract schema class
+ try
+ {
+ _abstractClassEntry = DirectoryEntryManager.GetDirectoryEntryInternal(context, "LDAP://" + context.GetServerName() + "/schema/" + ldapDisplayName);
+ _iadsClass = (NativeComInterfaces.IAdsClass)_abstractClassEntry.NativeObject;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80005000))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySchemaClass), ldapDisplayName);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ catch (InvalidCastException)
+ {
+ // this means that we found an object but it is not a schema class
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySchemaClass), ldapDisplayName);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ // set the bind flag
+ this.isBound = true;
+ }
+
+ internal ActiveDirectorySchemaClass(DirectoryContext context, string commonName, Hashtable propertyValuesFromServer, DirectoryEntry schemaEntry)
+ {
+ _context = context;
+ _schemaEntry = schemaEntry;
+
+ // all relevant properties have already been retrieved from the server
+ _propertyValuesFromServer = propertyValuesFromServer;
+ Debug.Assert(_propertyValuesFromServer != null);
+ _propertiesFromSchemaContainerInitialized = true;
+ _classEntry = GetSchemaClassDirectoryEntry();
+
+ // names
+ _commonName = commonName;
+ _ldapDisplayName = (string)GetValueFromCache(PropertyManager.LdapDisplayName, true);
+
+ // this constructor is only called for defunct classes
+ _isDefunctOnServer = true;
+ _isDefunct = _isDefunctOnServer;
+
+ // set the bind flag
+ this.isBound = true;
+ }
+
+ internal ActiveDirectorySchemaClass(DirectoryContext context, string commonName, string ldapDisplayName, DirectoryEntry classEntry, DirectoryEntry schemaEntry)
+ {
+ _context = context;
+ _schemaEntry = schemaEntry;
+ _classEntry = classEntry;
+
+ // names
+ _commonName = commonName;
+ _ldapDisplayName = ldapDisplayName;
+
+ // this constructor is only called for defunct classes
+ _isDefunctOnServer = true;
+ _isDefunct = _isDefunctOnServer;
+
+ // set the bind flag
+ this.isBound = true;
+ }
+
+ #endregion constructors
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ // private Dispose method
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ // check if this is an explicit Dispose
+ // only then clean up the directory entries
+ if (disposing)
+ {
+ // dispose schema entry
+ if (_schemaEntry != null)
+ {
+ _schemaEntry.Dispose();
+ _schemaEntry = null;
+ }
+ // dispose class entry
+ if (_classEntry != null)
+ {
+ _classEntry.Dispose();
+ _classEntry = null;
+ }
+ // dispose abstract class entry
+ if (_abstractClassEntry != null)
+ {
+ _abstractClassEntry.Dispose();
+ _abstractClassEntry = null;
+ }
+ // dispose the schema object
+ if (_schema != null)
+ {
+ _schema.Dispose();
+ }
+ }
+ _disposed = true;
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+ public static ActiveDirectorySchemaClass FindByName(DirectoryContext context, string ldapDisplayName)
+ {
+ ActiveDirectorySchemaClass schemaClass = null;
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ if (context.Name != null)
+ {
+ if (!(context.isRootDomain() || context.isServer() || context.isADAMConfigSet()))
+ {
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+ }
+
+ if (ldapDisplayName == null)
+ {
+ throw new ArgumentNullException("ldapDisplayName");
+ }
+
+ if (ldapDisplayName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "ldapDisplayName");
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // create a schema class
+ schemaClass = new ActiveDirectorySchemaClass(context, ldapDisplayName, (DirectoryEntry)null, null);
+
+ return schemaClass;
+ }
+
+ public ReadOnlyActiveDirectorySchemaPropertyCollection GetAllProperties()
+ {
+ CheckIfDisposed();
+
+ ArrayList properties = new ArrayList();
+
+ // get the mandatory properties
+ properties.AddRange(MandatoryProperties);
+ // get the optional properties
+ properties.AddRange(OptionalProperties);
+
+ return new ReadOnlyActiveDirectorySchemaPropertyCollection(properties);
+ }
+
+ public void Save()
+ {
+ CheckIfDisposed();
+
+ if (!isBound)
+ {
+ try
+ {
+ // create a new directory entry for this class
+ if (_schemaEntry == null)
+ {
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
+ }
+
+ // this will create the class and set the CN value
+ string rdn = "CN=" + _commonName;
+ rdn = Utils.GetEscapedPath(rdn);
+ _classEntry = _schemaEntry.Children.Add(rdn, "classSchema");
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, _context.Name));
+ }
+
+ // set the ldap display name property
+ SetProperty(PropertyManager.LdapDisplayName, _ldapDisplayName);
+
+ // set the oid value
+ SetProperty(PropertyManager.GovernsID, _oid);
+
+ // set the description
+ SetProperty(PropertyManager.Description, _description);
+
+ // set the possibleSuperiors property
+ if (_possibleSuperiors != null)
+ {
+ _classEntry.Properties[PropertyManager.PossibleSuperiors].AddRange(_possibleSuperiors.GetMultiValuedProperty());
+ }
+
+ // set the mandatoryProperties property
+ if (_mandatoryProperties != null)
+ {
+ _classEntry.Properties[PropertyManager.MustContain].AddRange(_mandatoryProperties.GetMultiValuedProperty());
+ }
+
+ // set the optionalProperties property
+ if (_optionalProperties != null)
+ {
+ _classEntry.Properties[PropertyManager.MayContain].AddRange(_optionalProperties.GetMultiValuedProperty());
+ }
+
+ // set the subClassOf property
+ if (_subClassOf != null)
+ {
+ SetProperty(PropertyManager.SubClassOf, _subClassOf.Name);
+ }
+ else
+ {
+ // if no super class is specified, set it to "top"
+ SetProperty(PropertyManager.SubClassOf, "top");
+ }
+
+ // set the objectClassCategory property
+ SetProperty(PropertyManager.ObjectClassCategory, _type);
+
+ // set the schemaIDGuid property
+ if (_schemaGuidBinaryForm != null)
+ {
+ SetProperty(PropertyManager.SchemaIDGuid, _schemaGuidBinaryForm);
+ }
+
+ // set the default security descriptor
+ if (_defaultSDSddlForm != null)
+ {
+ SetProperty(PropertyManager.DefaultSecurityDescriptor, _defaultSDSddlForm);
+ }
+ }
+
+ try
+ {
+ // commit the classEntry to server
+ _classEntry.CommitChanges();
+
+ // Refresh the schema cache on the schema role owner
+ if (_schema == null)
+ {
+ ActiveDirectorySchema schemaObject = ActiveDirectorySchema.GetSchema(_context);
+ bool alreadyUsingSchemaRoleOwnerContext = false;
+ DirectoryServer schemaRoleOwner = null;
+
+ try
+ {
+ //
+ // if we are not already talking to the schema role owner, change the context
+ //
+ schemaRoleOwner = schemaObject.SchemaRoleOwner;
+ if (Utils.Compare(schemaRoleOwner.Name, _context.GetServerName()) != 0)
+ {
+ DirectoryContext schemaRoleOwnerContext = Utils.GetNewDirectoryContext(schemaRoleOwner.Name, DirectoryContextType.DirectoryServer, _context);
+ _schema = ActiveDirectorySchema.GetSchema(schemaRoleOwnerContext);
+ }
+ else
+ {
+ alreadyUsingSchemaRoleOwnerContext = true;
+ _schema = schemaObject;
+ }
+ }
+ finally
+ {
+ if (schemaRoleOwner != null)
+ {
+ schemaRoleOwner.Dispose();
+ }
+ if (!alreadyUsingSchemaRoleOwnerContext)
+ {
+ schemaObject.Dispose();
+ }
+ }
+ }
+ _schema.RefreshSchema();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+
+ // now that the changes are committed to the server
+ // update the defunct/non-defunct status of the class on the server
+ _isDefunctOnServer = _isDefunct;
+
+ // invalidate all properties
+ _commonName = null;
+ _oid = null;
+ _description = null;
+ _descriptionInitialized = false;
+ _possibleSuperiors = null;
+ _auxiliaryClasses = null;
+ _possibleInferiors = null;
+ _mandatoryProperties = null;
+ _optionalProperties = null;
+ _subClassOf = null;
+ _typeInitialized = false;
+ _schemaGuidBinaryForm = null;
+ _defaultSDSddlForm = null;
+ _defaultSDSddlFormInitialized = false;
+ _propertiesFromSchemaContainerInitialized = false;
+
+ // set bind flag
+ isBound = true;
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ CheckIfDisposed();
+
+ if (!isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotGetObject));
+ }
+
+ GetSchemaClassDirectoryEntry();
+ Debug.Assert(_classEntry != null);
+
+ return DirectoryEntryManager.GetDirectoryEntryInternal(_context, _classEntry.Path);
+ }
+ #endregion public methods
+
+ #region public properties
+ public string Name
+ {
+ get
+ {
+ CheckIfDisposed();
+ return _ldapDisplayName;
+ }
+ }
+
+ public string CommonName
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (_commonName == null)
+ {
+ // get the property from the server
+ _commonName = (string)GetValueFromCache(PropertyManager.Cn, true);
+ }
+ }
+ return _commonName;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.Cn, value);
+ }
+ _commonName = value;
+ }
+ }
+
+ public string Oid
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (_oid == null)
+ {
+ // get the property from the abstract schema/ schema container
+ // (for non-defunt classes this property is available in the abstract schema)
+ if (!_isDefunctOnServer)
+ {
+ try
+ {
+ _oid = _iadsClass.OID;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ else
+ {
+ _oid = (string)GetValueFromCache(PropertyManager.GovernsID, true);
+ }
+ }
+ }
+ return _oid;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.GovernsID, value);
+ }
+ _oid = value;
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_descriptionInitialized)
+ {
+ // get the property from the server
+ _description = (string)GetValueFromCache(PropertyManager.Description, false);
+ _descriptionInitialized = true;
+ }
+ }
+ return _description;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.Description, value);
+ }
+ _description = value;
+ }
+ }
+
+ public bool IsDefunct
+ {
+ get
+ {
+ CheckIfDisposed();
+ // this is initialized for bound classes in the constructor
+ return _isDefunct;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.IsDefunct, value);
+ }
+ _isDefunct = value;
+ }
+ }
+
+ public ActiveDirectorySchemaClassCollection PossibleSuperiors
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (_possibleSuperiors == null)
+ {
+ if (isBound)
+ {
+ // get the property from the abstract schema/ schema container
+ // (for non-defunt classes this property is available in the abstract schema)
+ if (!_isDefunctOnServer)
+ {
+ ArrayList possibleSuperiorsList = new ArrayList();
+ bool listEmpty = false;
+
+ //
+ // IADsClass.PossibleSuperiors can return either a collection or a string
+ // (if there is only one value)
+ //
+ object value = null;
+ try
+ {
+ value = _iadsClass.PossibleSuperiors;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8000500D))
+ {
+ listEmpty = true;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+
+ if (!listEmpty)
+ {
+ if (value is ICollection)
+ {
+ possibleSuperiorsList.AddRange((ICollection)value);
+ }
+ else
+ {
+ // single value
+ possibleSuperiorsList.Add((string)value);
+ }
+
+ _possibleSuperiors = new ActiveDirectorySchemaClassCollection(_context, this, true /* isBound */, PropertyManager.PossibleSuperiors, possibleSuperiorsList, true /* onlyNames */);
+ }
+ else
+ {
+ // there are no superiors, return an emtpy collection
+ _possibleSuperiors = new ActiveDirectorySchemaClassCollection(_context, this, true /* is Bound */, PropertyManager.PossibleSuperiors, new ArrayList());
+ }
+ }
+ else
+ {
+ ArrayList possibleSuperiorsList = new ArrayList();
+ possibleSuperiorsList.AddRange(GetValuesFromCache(PropertyManager.PossibleSuperiors));
+ possibleSuperiorsList.AddRange(GetValuesFromCache(PropertyManager.SystemPossibleSuperiors));
+
+ _possibleSuperiors = new ActiveDirectorySchemaClassCollection(_context, this, true /* isBound */, PropertyManager.PossibleSuperiors, GetClasses(possibleSuperiorsList));
+ }
+ }
+ else
+ {
+ _possibleSuperiors = new ActiveDirectorySchemaClassCollection(_context, this, false /* is Bound */, PropertyManager.PossibleSuperiors, new ArrayList());
+ }
+ }
+
+ return _possibleSuperiors;
+ }
+ }
+
+ public ReadOnlyActiveDirectorySchemaClassCollection PossibleInferiors
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (_possibleInferiors == null)
+ {
+ if (isBound)
+ {
+ // get the value from the server
+ _possibleInferiors = new ReadOnlyActiveDirectorySchemaClassCollection(GetClasses(GetValuesFromCache(PropertyManager.PossibleInferiors)));
+ }
+ else
+ {
+ _possibleInferiors = new ReadOnlyActiveDirectorySchemaClassCollection(new ArrayList());
+ }
+ }
+ return _possibleInferiors;
+ }
+ }
+
+ public ActiveDirectorySchemaPropertyCollection MandatoryProperties
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (_mandatoryProperties == null)
+ {
+ if (isBound)
+ {
+ // get the property from the abstract schema/ schema container
+ // (for non-defunt classes this property is available in the abstract schema)
+ if (!_isDefunctOnServer)
+ {
+ ArrayList mandatoryPropertiesList = new ArrayList();
+ bool listEmpty = false;
+
+ //
+ // IADsClass.MandatoryProperties can return either a collection or a string
+ // (if there is only one value)
+ //
+ object value = null;
+ try
+ {
+ value = _iadsClass.MandatoryProperties;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8000500D))
+ {
+ listEmpty = true;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+
+ if (!listEmpty)
+ {
+ if (value is ICollection)
+ {
+ mandatoryPropertiesList.AddRange((ICollection)value);
+ }
+ else
+ {
+ // single value
+ mandatoryPropertiesList.Add((string)value);
+ }
+
+ _mandatoryProperties = new ActiveDirectorySchemaPropertyCollection(_context, this, true /* isBound */, PropertyManager.MustContain, mandatoryPropertiesList, true /* onlyNames */);
+ }
+ else
+ {
+ // there are no mandatory properties, return an emtpy collection
+ _mandatoryProperties = new ActiveDirectorySchemaPropertyCollection(_context, this, true /* isBound */, PropertyManager.MustContain, new ArrayList());
+ }
+ }
+ else
+ {
+ string[] propertyNames = new string[2];
+ propertyNames[0] = PropertyManager.SystemMustContain;
+ propertyNames[1] = PropertyManager.MustContain;
+
+ _mandatoryProperties = new ActiveDirectorySchemaPropertyCollection(_context, this, true /* isBound */, PropertyManager.MustContain, GetProperties(GetPropertyValuesRecursively(propertyNames)));
+ }
+ }
+ else
+ {
+ _mandatoryProperties = new ActiveDirectorySchemaPropertyCollection(_context, this, false /* isBound */, PropertyManager.MustContain, new ArrayList());
+ }
+ }
+ return _mandatoryProperties;
+ }
+ }
+
+ public ActiveDirectorySchemaPropertyCollection OptionalProperties
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (_optionalProperties == null)
+ {
+ if (isBound)
+ {
+ // get the property from the abstract schema/ schema container
+ // (for non-defunt classes this property is available in the abstract schema)
+ if (!_isDefunctOnServer)
+ {
+ ArrayList optionalPropertiesList = new ArrayList();
+ bool listEmpty = false;
+
+ //
+ // IADsClass.OptionalProperties can return either a collection or a string
+ // (if there is only one value)
+ //
+ object value = null;
+ try
+ {
+ value = _iadsClass.OptionalProperties;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8000500D))
+ {
+ listEmpty = true;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+
+ if (!listEmpty)
+ {
+ if (value is ICollection)
+ {
+ optionalPropertiesList.AddRange((ICollection)value);
+ }
+ else
+ {
+ // single value
+ optionalPropertiesList.Add((string)value);
+ }
+
+ _optionalProperties = new ActiveDirectorySchemaPropertyCollection(_context, this, true /* isBound */, PropertyManager.MayContain, optionalPropertiesList, true /* onlyNames */);
+ }
+ else
+ {
+ // there are no optional properties, return an emtpy collection
+ _optionalProperties = new ActiveDirectorySchemaPropertyCollection(_context, this, true /* isBound */, PropertyManager.MayContain, new ArrayList());
+ }
+ }
+ else
+ {
+ string[] propertyNames = new string[2];
+ propertyNames[0] = PropertyManager.SystemMayContain;
+ propertyNames[1] = PropertyManager.MayContain;
+
+ ArrayList optionalPropertyList = new ArrayList();
+ foreach (string propertyName in GetPropertyValuesRecursively(propertyNames))
+ {
+ if (!MandatoryProperties.Contains(propertyName))
+ {
+ optionalPropertyList.Add(propertyName);
+ }
+ }
+
+ _optionalProperties = new ActiveDirectorySchemaPropertyCollection(_context, this, true /* isBound */, PropertyManager.MayContain, GetProperties(optionalPropertyList));
+ }
+ }
+ else
+ {
+ _optionalProperties = new ActiveDirectorySchemaPropertyCollection(_context, this, false /* isBound */, PropertyManager.MayContain, new ArrayList());
+ }
+ }
+ return _optionalProperties;
+ }
+ }
+
+ public ActiveDirectorySchemaClassCollection AuxiliaryClasses
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (_auxiliaryClasses == null)
+ {
+ if (isBound)
+ {
+ // get the property from the abstract schema/ schema container
+ // (for non-defunt classes this property is available in the abstract schema)
+ if (!_isDefunctOnServer)
+ {
+ ArrayList auxiliaryClassesList = new ArrayList();
+ bool listEmpty = false;
+
+ //
+ // IADsClass.AuxDerivedFrom can return either a collection or a string
+ // (if there is only one value)
+ //
+ object value = null;
+ try
+ {
+ value = _iadsClass.AuxDerivedFrom;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8000500D))
+ {
+ listEmpty = true;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+
+ if (!listEmpty)
+ {
+ if (value is ICollection)
+ {
+ auxiliaryClassesList.AddRange((ICollection)value);
+ }
+ else
+ {
+ // single value
+ auxiliaryClassesList.Add((string)value);
+ }
+
+ _auxiliaryClasses = new ActiveDirectorySchemaClassCollection(_context, this, true /* isBound */, PropertyManager.AuxiliaryClass, auxiliaryClassesList, true /* onlyNames */);
+ }
+ else
+ {
+ // there are no auxiliary classes, return an emtpy collection
+ _auxiliaryClasses = new ActiveDirectorySchemaClassCollection(_context, this, true /* is Bound */, PropertyManager.AuxiliaryClass, new ArrayList());
+ }
+ }
+ else
+ {
+ string[] propertyNames = new string[2];
+ propertyNames[0] = PropertyManager.AuxiliaryClass;
+ propertyNames[1] = PropertyManager.SystemAuxiliaryClass;
+
+ _auxiliaryClasses = new ActiveDirectorySchemaClassCollection(_context, this, true /* isBound */, PropertyManager.AuxiliaryClass, GetClasses(GetPropertyValuesRecursively(propertyNames)));
+ }
+ }
+ else
+ {
+ _auxiliaryClasses = new ActiveDirectorySchemaClassCollection(_context, this, false /* isBound */, PropertyManager.AuxiliaryClass, new ArrayList());
+ }
+ }
+ return _auxiliaryClasses;
+ }
+ }
+
+ public ActiveDirectorySchemaClass SubClassOf
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (_subClassOf == null)
+ {
+ // get the property from the server
+ _subClassOf = new ActiveDirectorySchemaClass(_context, (string)GetValueFromCache(PropertyManager.SubClassOf, true), (DirectoryEntry)null, _schemaEntry);
+ }
+ }
+ return _subClassOf;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.SubClassOf, value);
+ }
+ _subClassOf = value;
+ }
+ }
+
+ public SchemaClassType Type
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_typeInitialized)
+ {
+ // get the property from the server
+ _type = (SchemaClassType)((int)GetValueFromCache(PropertyManager.ObjectClassCategory, true));
+ _typeInitialized = true;
+ }
+ }
+ return _type;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ // validate the value that is being set
+ if (value < SchemaClassType.Type88 || value > SchemaClassType.Auxiliary)
+ {
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(SchemaClassType));
+ }
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.ObjectClassCategory, value);
+ }
+ _type = value;
+ }
+ }
+
+ public Guid SchemaGuid
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ Guid schemaGuid = Guid.Empty;
+
+ if (isBound)
+ {
+ if (_schemaGuidBinaryForm == null)
+ {
+ // get the property from the server
+ _schemaGuidBinaryForm = (byte[])GetValueFromCache(PropertyManager.SchemaIDGuid, true);
+ }
+ }
+
+ // we cache the byte array and create a new guid each time
+ return new Guid(_schemaGuidBinaryForm);
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.SchemaIDGuid, (value.Equals(Guid.Empty)) ? null : value.ToByteArray());
+ }
+ _schemaGuidBinaryForm = (value.Equals(Guid.Empty)) ? null : value.ToByteArray();
+ }
+ }
+
+ public ActiveDirectorySecurity DefaultObjectSecurityDescriptor
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ ActiveDirectorySecurity defaultObjectSecurityDescriptor = null;
+
+ if (isBound)
+ {
+ if (!_defaultSDSddlFormInitialized)
+ {
+ // get the property from the server
+ _defaultSDSddlForm = (string)GetValueFromCache(PropertyManager.DefaultSecurityDescriptor, false);
+ _defaultSDSddlFormInitialized = true;
+ }
+ }
+
+ // we cache the sddl form and create a ActiveDirectorySecurity object each time
+ if (_defaultSDSddlForm != null)
+ {
+ defaultObjectSecurityDescriptor = new ActiveDirectorySecurity();
+ defaultObjectSecurityDescriptor.SetSecurityDescriptorSddlForm(_defaultSDSddlForm);
+ }
+
+ return defaultObjectSecurityDescriptor;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.DefaultSecurityDescriptor, (value == null) ? null : value.GetSecurityDescriptorSddlForm(AccessControlSections.All));
+ }
+ _defaultSDSddlForm = (value == null) ? null : value.GetSecurityDescriptorSddlForm(AccessControlSections.All);
+ }
+ }
+
+ #endregion public properties
+
+ #region private methods
+
+ private void CheckIfDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+
+ //
+ // This method retrieves the value of a property (single valued) from the values
+ // that were retrieved from the server. The "mustExist" parameter controls whether or
+ // not an exception should be thrown if a value does not exist. If mustExist is true, this
+ // will throw an exception is value does not exist.
+ //
+ private object GetValueFromCache(string propertyName, bool mustExist)
+ {
+ object value = null;
+
+ // retrieve the properties from the server if necessary
+ InitializePropertiesFromSchemaContainer();
+
+ Debug.Assert(_propertyValuesFromServer != null);
+ ArrayList values = (ArrayList)_propertyValuesFromServer[propertyName.ToLower(CultureInfo.InvariantCulture)];
+
+ Debug.Assert(values != null);
+ if (values.Count < 1 && mustExist)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.PropertyNotFound, propertyName));
+ }
+ else if (values.Count > 0)
+ {
+ value = values[0];
+ }
+
+ return value;
+ }
+
+ //
+ // This method retrieves all the values of a property (single valued) from the values
+ // that were retrieved from the server.
+ //
+ private ICollection GetValuesFromCache(string propertyName)
+ {
+ // retrieve the properties from the server if necessary
+ InitializePropertiesFromSchemaContainer();
+
+ Debug.Assert(_propertyValuesFromServer != null);
+ ArrayList values = (ArrayList)_propertyValuesFromServer[propertyName.ToLower(CultureInfo.InvariantCulture)];
+
+ Debug.Assert(values != null);
+ return values;
+ }
+
+ //
+ // Just calls the static method GetPropertiesFromSchemaContainer with the correct context
+ //
+ private void InitializePropertiesFromSchemaContainer()
+ {
+ if (!_propertiesFromSchemaContainerInitialized)
+ {
+ if (_schemaEntry == null)
+ {
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
+ }
+
+ _propertyValuesFromServer = GetPropertiesFromSchemaContainer(_context, _schemaEntry, (_isDefunctOnServer) ? _commonName : _ldapDisplayName, _isDefunctOnServer);
+ _propertiesFromSchemaContainerInitialized = true;
+ }
+ }
+
+ //
+ // This method retrieves properties for this schema class from the schema container
+ // on the server. For non-defunct classes only properties that are not available in the abstract
+ // schema are retrieved. For defunct classes, all the properties are retrieved.
+ // The retrieved values are stored in a class variable "propertyValuesFromServer" which is a
+ // hashtable indexed on the property name.
+ //
+ internal static Hashtable GetPropertiesFromSchemaContainer(DirectoryContext context, DirectoryEntry schemaEntry, string name, bool isDefunctOnServer)
+ {
+ Hashtable propertyValuesFromServer = null;
+
+ //
+ // The properties that are loaded from the schemaContainer for non-defunct classes:
+ // DistinguishedName
+ // CommonName
+ // Description
+ // PossibleInferiors
+ // SubClassOf
+ // Type
+ // SchemaGuid
+ // DefaultObjectSecurityDescriptor
+ // AuxiliaryClasses
+ //
+
+ //
+ // For defunct class we also load the remaining properties
+ // LdapDisplayName
+ // Oid
+ // PossibleSuperiors
+ // MandatoryProperties
+ // OptionalProperties
+ // AuxiliaryClasses
+ //
+
+ // build the filter
+ StringBuilder str = new StringBuilder(15);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=classSchema)");
+ str.Append("(");
+ if (!isDefunctOnServer)
+ {
+ str.Append(PropertyManager.LdapDisplayName);
+ }
+ else
+ {
+ str.Append(PropertyManager.Cn);
+ }
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(name));
+ str.Append(")");
+ if (!isDefunctOnServer)
+ {
+ str.Append("(!(");
+ }
+ else
+ {
+ str.Append("(");
+ }
+ str.Append(PropertyManager.IsDefunct);
+ if (!isDefunctOnServer)
+ {
+ str.Append("=TRUE)))");
+ }
+ else
+ {
+ str.Append("=TRUE))");
+ }
+
+ //
+ // Get all the values using range retrieval
+ //
+ ArrayList propertyNamesWithRangeRetrieval = new ArrayList();
+ ArrayList propertyNamesWithoutRangeRetrieval = new ArrayList();
+
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.DistinguishedName);
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.Cn);
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.Description);
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.PossibleInferiors);
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.SubClassOf);
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.ObjectClassCategory);
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.SchemaIDGuid);
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.DefaultSecurityDescriptor);
+ propertyNamesWithRangeRetrieval.Add(PropertyManager.AuxiliaryClass);
+ propertyNamesWithRangeRetrieval.Add(PropertyManager.SystemAuxiliaryClass);
+ propertyNamesWithRangeRetrieval.Add(PropertyManager.MustContain);
+ propertyNamesWithRangeRetrieval.Add(PropertyManager.SystemMustContain);
+ propertyNamesWithRangeRetrieval.Add(PropertyManager.MayContain);
+ propertyNamesWithRangeRetrieval.Add(PropertyManager.SystemMayContain);
+
+ // if defunct, we need to retrieve all the properties from the server
+ if (isDefunctOnServer)
+ {
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.LdapDisplayName);
+ propertyNamesWithoutRangeRetrieval.Add(PropertyManager.GovernsID);
+ propertyNamesWithRangeRetrieval.Add(PropertyManager.SystemPossibleSuperiors);
+ propertyNamesWithRangeRetrieval.Add(PropertyManager.PossibleSuperiors);
+ }
+
+ try
+ {
+ propertyValuesFromServer = Utils.GetValuesWithRangeRetrieval(schemaEntry, str.ToString(), propertyNamesWithRangeRetrieval, propertyNamesWithoutRangeRetrieval, SearchScope.OneLevel);
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // object is not found since we cannot even find the container in which to search
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySchemaClass), name);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ return propertyValuesFromServer;
+ }
+
+ internal DirectoryEntry GetSchemaClassDirectoryEntry()
+ {
+ if (_classEntry == null)
+ {
+ InitializePropertiesFromSchemaContainer();
+ _classEntry = DirectoryEntryManager.GetDirectoryEntry(_context, (string)GetValueFromCache(PropertyManager.DistinguishedName, true));
+ }
+
+ return _classEntry;
+ }
+
+ private void SetProperty(string propertyName, object value)
+ {
+ // get the distinguished name to construct the directory entry
+ GetSchemaClassDirectoryEntry();
+ Debug.Assert(_classEntry != null);
+
+ try
+ {
+ if ((value == null))
+ {
+ if (_classEntry.Properties.Contains(propertyName))
+ {
+ _classEntry.Properties[propertyName].Clear();
+ }
+ }
+ else
+ {
+ _classEntry.Properties[propertyName].Value = value;
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+
+ //
+ // This method searches in the schema container for all non-defunct classes of the
+ // specified name (ldapDisplayName).
+ //
+ private ArrayList GetClasses(ICollection ldapDisplayNames)
+ {
+ ArrayList classes = new ArrayList();
+ SearchResultCollection resCol = null;
+
+ try
+ {
+ if (ldapDisplayNames.Count < 1)
+ {
+ return classes;
+ }
+
+ if (_schemaEntry == null)
+ {
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
+ }
+
+ // constructing the filter
+ StringBuilder str = new StringBuilder(100);
+
+ if (ldapDisplayNames.Count > 1)
+ {
+ str.Append("(|");
+ }
+ foreach (string ldapDisplayName in ldapDisplayNames)
+ {
+ str.Append("(");
+ str.Append(PropertyManager.LdapDisplayName);
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(ldapDisplayName));
+ str.Append(")");
+ }
+ if (ldapDisplayNames.Count > 1)
+ {
+ str.Append(")");
+ }
+
+ string filter = "(&(" + PropertyManager.ObjectCategory + "=classSchema)" + str.ToString() + "(!(" + PropertyManager.IsDefunct + "=TRUE)))";
+
+ string[] propertiesToLoad = new String[1];
+ propertiesToLoad[0] = PropertyManager.LdapDisplayName;
+
+ ADSearcher searcher = new ADSearcher(_schemaEntry, filter, propertiesToLoad, SearchScope.OneLevel);
+ resCol = searcher.FindAll();
+
+ foreach (SearchResult res in resCol)
+ {
+ string ldapDisplayName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.LdapDisplayName);
+ DirectoryEntry de = res.GetDirectoryEntry();
+
+ de.AuthenticationType = Utils.DefaultAuthType;
+ de.Username = _context.UserName;
+ de.Password = _context.Password;
+
+ ActiveDirectorySchemaClass schemaClass = new ActiveDirectorySchemaClass(_context, ldapDisplayName, de, _schemaEntry);
+
+ classes.Add(schemaClass);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ finally
+ {
+ if (resCol != null)
+ {
+ resCol.Dispose();
+ }
+ }
+
+ return classes;
+ }
+
+ //
+ // This method searches in the schema container for all non-defunct properties of the
+ // specified name (ldapDisplayName).
+ //
+ private ArrayList GetProperties(ICollection ldapDisplayNames)
+ {
+ ArrayList properties = new ArrayList();
+ SearchResultCollection resCol = null;
+
+ try
+ {
+ if (ldapDisplayNames.Count < 1)
+ {
+ return properties;
+ }
+
+ if (_schemaEntry == null)
+ {
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
+ }
+
+ // constructing the filter
+ StringBuilder str = new StringBuilder(100);
+
+ if (ldapDisplayNames.Count > 1)
+ {
+ str.Append("(|");
+ }
+ foreach (string ldapDisplayName in ldapDisplayNames)
+ {
+ str.Append("(");
+ str.Append(PropertyManager.LdapDisplayName);
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(ldapDisplayName));
+ str.Append(")");
+ }
+ if (ldapDisplayNames.Count > 1)
+ {
+ str.Append(")");
+ }
+
+ string filter = "(&(" + PropertyManager.ObjectCategory + "=attributeSchema)" + str.ToString() + "(!(" + PropertyManager.IsDefunct + "=TRUE)))";
+
+ string[] propertiesToLoad = new String[1];
+ propertiesToLoad[0] = PropertyManager.LdapDisplayName;
+
+ ADSearcher searcher = new ADSearcher(_schemaEntry, filter, propertiesToLoad, SearchScope.OneLevel);
+ resCol = searcher.FindAll();
+
+ foreach (SearchResult res in resCol)
+ {
+ string ldapDisplayName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.LdapDisplayName);
+ DirectoryEntry de = res.GetDirectoryEntry();
+
+ de.AuthenticationType = Utils.DefaultAuthType;
+ de.Username = _context.UserName;
+ de.Password = _context.Password;
+
+ ActiveDirectorySchemaProperty schemaProperty = new ActiveDirectorySchemaProperty(_context, ldapDisplayName, de, _schemaEntry);
+
+ properties.Add(schemaProperty);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ finally
+ {
+ if (resCol != null)
+ {
+ resCol.Dispose();
+ }
+ }
+
+ return properties;
+ }
+
+ private ArrayList GetPropertyValuesRecursively(string[] propertyNames)
+ {
+ ArrayList values = new ArrayList();
+
+ // get the properties of the super class
+ try
+ {
+ if (Utils.Compare(SubClassOf.Name, Name) != 0)
+ {
+ foreach (string value in SubClassOf.GetPropertyValuesRecursively(propertyNames))
+ {
+ if (!values.Contains(value))
+ {
+ values.Add(value);
+ }
+ }
+ }
+
+ // get the properties of the auxiliary classes
+ foreach (string auxSchemaClassName in GetValuesFromCache(PropertyManager.AuxiliaryClass))
+ {
+ ActiveDirectorySchemaClass auxSchemaClass = new ActiveDirectorySchemaClass(_context, auxSchemaClassName, (DirectoryEntry)null, null);
+
+ foreach (string property in auxSchemaClass.GetPropertyValuesRecursively(propertyNames))
+ {
+ if (!values.Contains(property))
+ {
+ values.Add(property);
+ }
+ }
+ }
+ foreach (string auxSchemaClassName in GetValuesFromCache(PropertyManager.SystemAuxiliaryClass))
+ {
+ ActiveDirectorySchemaClass auxSchemaClass = new ActiveDirectorySchemaClass(_context, auxSchemaClassName, (DirectoryEntry)null, null);
+
+ foreach (string property in auxSchemaClass.GetPropertyValuesRecursively(propertyNames))
+ {
+ if (!values.Contains(property))
+ {
+ values.Add(property);
+ }
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+
+ foreach (string propertyName in propertyNames)
+ {
+ foreach (string value in GetValuesFromCache(propertyName))
+ {
+ if (!values.Contains(value))
+ {
+ values.Add(value);
+ }
+ }
+ }
+
+ return values;
+ }
+
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClassCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClassCollection.cs
new file mode 100644
index 0000000000..2ae3502309
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaClassCollection.cs
@@ -0,0 +1,374 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+
+ public class ActiveDirectorySchemaClassCollection : CollectionBase
+ {
+ private DirectoryEntry _classEntry = null;
+ private string _propertyName = null;
+ private ActiveDirectorySchemaClass _schemaClass = null;
+ private bool _isBound = false;
+ private DirectoryContext _context = null;
+
+ internal ActiveDirectorySchemaClassCollection(DirectoryContext context,
+ ActiveDirectorySchemaClass schemaClass,
+ bool isBound,
+ string propertyName,
+ ICollection classNames,
+ bool onlyNames)
+ {
+ _schemaClass = schemaClass;
+ _propertyName = propertyName;
+ _isBound = isBound;
+ _context = context;
+
+ foreach (string ldapDisplayName in classNames)
+ {
+ // all properties in writeable class collection are non-defunct
+ // so calling constructor for non-defunct class
+ this.InnerList.Add(new ActiveDirectorySchemaClass(context, ldapDisplayName, (DirectoryEntry)null, null));
+ }
+ }
+
+ internal ActiveDirectorySchemaClassCollection(DirectoryContext context,
+ ActiveDirectorySchemaClass schemaClass,
+ bool isBound,
+ string propertyName,
+ ICollection classes)
+ {
+ _schemaClass = schemaClass;
+ _propertyName = propertyName;
+ _isBound = isBound;
+ _context = context;
+
+ foreach (ActiveDirectorySchemaClass schClass in classes)
+ {
+ this.InnerList.Add(schClass);
+ }
+ }
+
+ public ActiveDirectorySchemaClass this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySchemaClass)List[index];
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!value.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, value.Name));
+ }
+
+ if (!Contains(value))
+ {
+ List[index] = value;
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, value), "value");
+ }
+ }
+ }
+
+ public int Add(ActiveDirectorySchemaClass schemaClass)
+ {
+ if (schemaClass == null)
+ {
+ throw new ArgumentNullException("schemaClass");
+ }
+
+ if (!schemaClass.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaClass.Name));
+ }
+
+ if (!Contains(schemaClass))
+ {
+ return List.Add(schemaClass);
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, schemaClass), "schemaClass");
+ }
+ }
+
+ public void AddRange(ActiveDirectorySchemaClass[] schemaClasses)
+ {
+ if (schemaClasses == null)
+ {
+ throw new ArgumentNullException("schemaClasses");
+ }
+
+ foreach (ActiveDirectorySchemaClass schemaClass in schemaClasses)
+ {
+ if (schemaClass == null)
+ {
+ throw new ArgumentException("schemaClasses");
+ }
+ }
+
+ for (int i = 0; ((i) < (schemaClasses.Length)); i = ((i) + (1)))
+ {
+ this.Add((ActiveDirectorySchemaClass)schemaClasses[i]);
+ }
+ }
+
+ public void AddRange(ActiveDirectorySchemaClassCollection schemaClasses)
+ {
+ if (schemaClasses == null)
+ {
+ throw new ArgumentNullException("schemaClasses");
+ }
+
+ foreach (ActiveDirectorySchemaClass schemaClass in schemaClasses)
+ {
+ if (schemaClass == null)
+ {
+ throw new ArgumentException("schemaClasses");
+ }
+ }
+
+ int currentCount = schemaClasses.Count;
+ for (int i = 0; i < currentCount; i++)
+ {
+ this.Add(schemaClasses[i]);
+ }
+ }
+
+ public void AddRange(ReadOnlyActiveDirectorySchemaClassCollection schemaClasses)
+ {
+ if (schemaClasses == null)
+ {
+ throw new ArgumentNullException("schemaClasses");
+ }
+
+ foreach (ActiveDirectorySchemaClass schemaClass in schemaClasses)
+ {
+ if (schemaClass == null)
+ {
+ throw new ArgumentException("schemaClasses");
+ }
+ }
+
+ int currentCount = schemaClasses.Count;
+ for (int i = 0; i < currentCount; i++)
+ {
+ this.Add(schemaClasses[i]);
+ }
+ }
+
+ public void Remove(ActiveDirectorySchemaClass schemaClass)
+ {
+ if (schemaClass == null)
+ {
+ throw new ArgumentNullException("schemaClass");
+ }
+
+ if (!schemaClass.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaClass.Name));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaClass tmp = (ActiveDirectorySchemaClass)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaClass.Name) == 0)
+ {
+ List.Remove(tmp);
+ return;
+ }
+ }
+ throw new ArgumentException(Res.GetString(Res.NotFoundInCollection, schemaClass), "schemaClass");
+ }
+
+ public void Insert(int index, ActiveDirectorySchemaClass schemaClass)
+ {
+ if (schemaClass == null)
+ {
+ throw new ArgumentNullException("schemaClass");
+ }
+
+ if (!schemaClass.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaClass.Name));
+ }
+
+ if (!Contains(schemaClass))
+ {
+ List.Insert(index, schemaClass);
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, schemaClass), "schemaClass");
+ }
+ }
+
+ public bool Contains(ActiveDirectorySchemaClass schemaClass)
+ {
+ if (schemaClass == null)
+ {
+ throw new ArgumentNullException("schemaClass");
+ }
+
+ if (!schemaClass.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaClass.Name));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaClass tmp = (ActiveDirectorySchemaClass)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaClass.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void CopyTo(ActiveDirectorySchemaClass[] schemaClasses, int index)
+ {
+ List.CopyTo(schemaClasses, index);
+ }
+
+ public int IndexOf(ActiveDirectorySchemaClass schemaClass)
+ {
+ if (schemaClass == null)
+ throw new ArgumentNullException("schemaClass");
+
+ if (!schemaClass.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaClass.Name));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaClass tmp = (ActiveDirectorySchemaClass)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaClass.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ protected override void OnClearComplete()
+ {
+ if (_isBound)
+ {
+ if (_classEntry == null)
+ {
+ _classEntry = _schemaClass.GetSchemaClassDirectoryEntry();
+ }
+
+ try
+ {
+ if (_classEntry.Properties.Contains(_propertyName))
+ {
+ _classEntry.Properties[_propertyName].Clear();
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ }
+
+ protected override void OnInsertComplete(int index, object value)
+ {
+ if (_isBound)
+ {
+ if (_classEntry == null)
+ {
+ _classEntry = _schemaClass.GetSchemaClassDirectoryEntry();
+ }
+
+ try
+ {
+ _classEntry.Properties[_propertyName].Add(((ActiveDirectorySchemaClass)value).Name);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ }
+
+ protected override void OnRemoveComplete(int index, object value)
+ {
+ if (_isBound)
+ {
+ if (_classEntry == null)
+ {
+ _classEntry = _schemaClass.GetSchemaClassDirectoryEntry();
+ }
+
+ // because this collection can contain values from the superior classes,
+ // these values would not exist in the classEntry
+ // and therefore cannot be removed
+ // we need to throw an exception here
+ string valueName = ((ActiveDirectorySchemaClass)value).Name;
+
+ try
+ {
+ if (_classEntry.Properties[_propertyName].Contains(valueName))
+ {
+ _classEntry.Properties[_propertyName].Remove(valueName);
+ }
+ else
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ValueCannotBeModified));
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ }
+
+ protected override void OnSetComplete(int index, object oldValue, object newValue)
+ {
+ if (_isBound)
+ {
+ // remove the old value
+ OnRemoveComplete(index, oldValue);
+ // add the new value
+ OnInsertComplete(index, newValue);
+ }
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ if (!(value is ActiveDirectorySchemaClass))
+ throw new ArgumentException("value");
+
+ if (!((ActiveDirectorySchemaClass)value).isBound)
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, ((ActiveDirectorySchemaClass)value).Name));
+ }
+
+ internal string[] GetMultiValuedProperty()
+ {
+ string[] values = new string[InnerList.Count];
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ values[i] = ((ActiveDirectorySchemaClass)InnerList[i]).Name;
+ }
+ return values;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaProperty.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaProperty.cs
new file mode 100644
index 0000000000..f778ee7cae
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaProperty.cs
@@ -0,0 +1,1451 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Text;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.Runtime.InteropServices;
+ using System.Security.Permissions;
+
+ internal enum SearchFlags : int
+ {
+ None = 0,
+ IsIndexed = 1,
+ IsIndexedOverContainer = 2,
+ IsInAnr = 4,
+ IsOnTombstonedObject = 8,
+ IsTupleIndexed = 32
+ }
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ActiveDirectorySchemaProperty : IDisposable
+ {
+ // private variables
+ private DirectoryEntry _schemaEntry = null;
+ private DirectoryEntry _propertyEntry = null;
+ private DirectoryEntry _abstractPropertyEntry = null;
+ private NativeComInterfaces.IAdsProperty _iadsProperty = null;
+ private DirectoryContext _context = null;
+ internal bool isBound = false;
+ private bool _disposed = false;
+ private ActiveDirectorySchema _schema = null;
+ private bool _propertiesFromSchemaContainerInitialized = false;
+ private bool _isDefunctOnServer = false;
+ private SearchResult _propertyValuesFromServer = null;
+
+ // private variables for caching properties
+ private string _ldapDisplayName = null;
+ private string _commonName = null;
+ private string _oid = null;
+ private ActiveDirectorySyntax _syntax = (ActiveDirectorySyntax)(-1);
+ private bool _syntaxInitialized = false;
+ private string _description = null;
+ private bool _descriptionInitialized = false;
+ private bool _isSingleValued = false;
+ private bool _isSingleValuedInitialized = false;
+ private bool _isInGlobalCatalog = false;
+ private bool _isInGlobalCatalogInitialized = false;
+ private Nullable<Int32> _rangeLower = null;
+ private bool _rangeLowerInitialized = false;
+ private Nullable<Int32> _rangeUpper = null;
+ private bool _rangeUpperInitialized = false;
+ private bool _isDefunct = false;
+ private SearchFlags _searchFlags = SearchFlags.None;
+ private bool _searchFlagsInitialized = false;
+ private ActiveDirectorySchemaProperty _linkedProperty = null;
+ private bool _linkedPropertyInitialized = false;
+ private Nullable<Int32> _linkId = null;
+ private bool _linkIdInitialized = false;
+ private byte[] _schemaGuidBinaryForm = null;
+
+ // OMObjectClass values for the syntax
+ //0x2B0C0287731C00854A
+ private static OMObjectClass s_dnOMObjectClass = new OMObjectClass(new byte[] { 0x2B, 0x0C, 0x02, 0x87, 0x73, 0x1C, 0x00, 0x85, 0x4A });
+ //0x2A864886F7140101010C
+ private static OMObjectClass s_dNWithStringOMObjectClass = new OMObjectClass(new byte[] { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x01, 0x01, 0x01, 0x0C });
+ //0x2A864886F7140101010B
+ private static OMObjectClass s_dNWithBinaryOMObjectClass = new OMObjectClass(new byte[] { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x01, 0x01, 0x01, 0x0B });
+ //0x2A864886F71401010106
+ private static OMObjectClass s_replicaLinkOMObjectClass = new OMObjectClass(new byte[] { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x01, 0x01, 0x01, 0x06 });
+ //0x2B0C0287731C00855C
+ private static OMObjectClass s_presentationAddressOMObjectClass = new OMObjectClass(new byte[] { 0x2B, 0x0C, 0x02, 0x87, 0x73, 0x1C, 0x00, 0x85, 0x5C });
+ //0x2B0C0287731C00853E
+ private static OMObjectClass s_accessPointDnOMObjectClass = new OMObjectClass(new byte[] { 0x2B, 0x0C, 0x02, 0x87, 0x73, 0x1C, 0x00, 0x85, 0x3E });
+ //0x56060102050B1D
+ private static OMObjectClass s_oRNameOMObjectClass = new OMObjectClass(new byte[] { 0x56, 0x06, 0x01, 0x02, 0x05, 0x0B, 0x1D });
+
+ // syntaxes
+ private static int s_syntaxesCount = 23;
+ private static Syntax[] s_syntaxes = {/* CaseExactString */ new Syntax("2.5.5.3", 27, null),
+ /* CaseIgnoreString */ new Syntax("2.5.5.4", 20, null),
+ /* NumericString */ new Syntax("2.5.5.6", 18, null),
+ /* DirectoryString */ new Syntax("2.5.5.12", 64, null),
+ /* OctetString */ new Syntax("2.5.5.10", 4, null),
+ /* SecurityDescriptor */ new Syntax("2.5.5.15", 66, null),
+ /* Int */ new Syntax("2.5.5.9", 2, null),
+ /* Int64 */ new Syntax("2.5.5.16", 65, null),
+ /* Bool */ new Syntax("2.5.5.8", 1, null),
+ /* Oid */ new Syntax("2.5.5.2", 6, null),
+ /* GeneralizedTime */ new Syntax("2.5.5.11", 24, null),
+ /* UtcTime */ new Syntax("2.5.5.11", 23, null),
+ /* DN */ new Syntax("2.5.5.1", 127, s_dnOMObjectClass),
+ /* DNWithBinary */ new Syntax("2.5.5.7", 127, s_dNWithBinaryOMObjectClass),
+ /* DNWithString */ new Syntax("2.5.5.14", 127, s_dNWithStringOMObjectClass),
+ /* Enumeration */ new Syntax("2.5.5.9", 10, null),
+ /* IA5String */ new Syntax("2.5.5.5", 22, null),
+ /* PrintableString */ new Syntax("2.5.5.5", 19, null),
+ /* Sid */ new Syntax("2.5.5.17", 4, null),
+ /* AccessPointDN */ new Syntax("2.5.5.14", 127, s_accessPointDnOMObjectClass),
+ /* ORName */ new Syntax("2.5.5.7", 127, s_oRNameOMObjectClass),
+ /* PresentationAddress */ new Syntax("2.5.5.13", 127, s_presentationAddressOMObjectClass),
+ /* ReplicaLink */ new Syntax("2.5.5.10", 127, s_replicaLinkOMObjectClass)};
+
+ #region constructors
+ public ActiveDirectorySchemaProperty(DirectoryContext context, string ldapDisplayName)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ if (context.Name != null)
+ {
+ // the target should be a valid forest name or a server
+ if (!((context.isRootDomain()) || (context.isADAMConfigSet()) || (context.isServer())))
+ {
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+ }
+
+ if (ldapDisplayName == null)
+ {
+ throw new ArgumentNullException("ldapDisplayName");
+ }
+
+ if (ldapDisplayName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "ldapDisplayName");
+ }
+
+ _context = new DirectoryContext(context);
+
+ // validate the context
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.SchemaNamingContext);
+ _schemaEntry.Bind(true);
+
+ _ldapDisplayName = ldapDisplayName;
+ // common name of the property defaults to the ldap display name
+ _commonName = ldapDisplayName;
+
+ // set the bind flag
+ this.isBound = false;
+ }
+
+ // internal constructor
+ internal ActiveDirectorySchemaProperty(DirectoryContext context, string ldapDisplayName, DirectoryEntry propertyEntry, DirectoryEntry schemaEntry)
+ {
+ _context = context;
+ _ldapDisplayName = ldapDisplayName;
+
+ // common name of the property defaults to the ldap display name
+ _propertyEntry = propertyEntry;
+ _isDefunctOnServer = false;
+ _isDefunct = _isDefunctOnServer;
+
+ try
+ {
+ // initialize the directory entry for the abstract schema class
+ _abstractPropertyEntry = DirectoryEntryManager.GetDirectoryEntryInternal(context, "LDAP://" + context.GetServerName() + "/schema/" + ldapDisplayName);
+ _iadsProperty = (NativeComInterfaces.IAdsProperty)_abstractPropertyEntry.NativeObject;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80005000))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySchemaProperty), ldapDisplayName);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ catch (InvalidCastException)
+ {
+ // this means that we found an object but it is not a schema class
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySchemaProperty), ldapDisplayName);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ // set the bind flag
+ this.isBound = true;
+ }
+
+ internal ActiveDirectorySchemaProperty(DirectoryContext context, string commonName, SearchResult propertyValuesFromServer, DirectoryEntry schemaEntry)
+ {
+ _context = context;
+ _schemaEntry = schemaEntry;
+
+ // all relevant properties have already been retrieved from the server
+ _propertyValuesFromServer = propertyValuesFromServer;
+ Debug.Assert(_propertyValuesFromServer != null);
+ _propertiesFromSchemaContainerInitialized = true;
+ _propertyEntry = GetSchemaPropertyDirectoryEntry();
+
+ // names
+ _commonName = commonName;
+ _ldapDisplayName = (string)GetValueFromCache(PropertyManager.LdapDisplayName, true);
+
+ // this constructor is only called for defunct classes
+ _isDefunctOnServer = true;
+ _isDefunct = _isDefunctOnServer;
+
+ // set the bind flag
+ this.isBound = true;
+ }
+
+ internal ActiveDirectorySchemaProperty(DirectoryContext context, string commonName, string ldapDisplayName, DirectoryEntry propertyEntry, DirectoryEntry schemaEntry)
+ {
+ _context = context;
+ _schemaEntry = schemaEntry;
+ _propertyEntry = propertyEntry;
+
+ // names
+ _commonName = commonName;
+ _ldapDisplayName = ldapDisplayName;
+
+ // this constructor is only called for defunct properties
+ _isDefunctOnServer = true;
+ _isDefunct = _isDefunctOnServer;
+
+ // set the bind flag
+ this.isBound = true;
+ }
+
+ #endregion constructors
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ // private Dispose method
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ // check if this is an explicit Dispose
+ // only then clean up the directory entries
+ if (disposing)
+ {
+ // dispose schema entry
+ if (_schemaEntry != null)
+ {
+ _schemaEntry.Dispose();
+ _schemaEntry = null;
+ }
+ // dispose property entry
+ if (_propertyEntry != null)
+ {
+ _propertyEntry.Dispose();
+ _propertyEntry = null;
+ }
+ // dispose abstract class entry
+ if (_abstractPropertyEntry != null)
+ {
+ _abstractPropertyEntry.Dispose();
+ _abstractPropertyEntry = null;
+ }
+ // dispose the schema object
+ if (_schema != null)
+ {
+ _schema.Dispose();
+ }
+ }
+
+ _disposed = true;
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+ public static ActiveDirectorySchemaProperty FindByName(DirectoryContext context, string ldapDisplayName)
+ {
+ ActiveDirectorySchemaProperty schemaProperty = null;
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ if (context.Name != null)
+ {
+ // the target should be a valid forest name or a server
+ if (!((context.isRootDomain()) || (context.isADAMConfigSet()) || (context.isServer())))
+ {
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+ }
+
+ if (ldapDisplayName == null)
+ {
+ throw new ArgumentNullException("ldapDisplayName");
+ }
+
+ if (ldapDisplayName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "ldapDisplayName");
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // create a schema property
+ schemaProperty = new ActiveDirectorySchemaProperty(context, ldapDisplayName, (DirectoryEntry)null, null);
+
+ return schemaProperty;
+ }
+
+ public void Save()
+ {
+ CheckIfDisposed();
+
+ if (!isBound)
+ {
+ try
+ {
+ // create a new directory entry for this class
+ if (_schemaEntry == null)
+ {
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
+ }
+
+ // this will create the class and set the CN value
+ string rdn = "CN=" + _commonName;
+ rdn = Utils.GetEscapedPath(rdn);
+ _propertyEntry = _schemaEntry.Children.Add(rdn, "attributeSchema");
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, _context.Name));
+ }
+
+ // set the ldap display name property
+ SetProperty(PropertyManager.LdapDisplayName, _ldapDisplayName);
+
+ // set the oid value
+ SetProperty(PropertyManager.AttributeID, _oid);
+
+ // set the syntax
+ if (_syntax != (ActiveDirectorySyntax)(-1))
+ {
+ SetSyntax(_syntax);
+ }
+
+ // set the description
+ SetProperty(PropertyManager.Description, _description);
+
+ // set the isSingleValued attribute
+ _propertyEntry.Properties[PropertyManager.IsSingleValued].Value = _isSingleValued;
+
+ // set the isGlobalCatalogReplicated attribute
+ _propertyEntry.Properties[PropertyManager.IsMemberOfPartialAttributeSet].Value = _isInGlobalCatalog;
+
+ // set the isDefunct attribute
+ _propertyEntry.Properties[PropertyManager.IsDefunct].Value = _isDefunct;
+
+ // set the range lower attribute
+ if (_rangeLower != null)
+ {
+ _propertyEntry.Properties[PropertyManager.RangeLower].Value = (int)_rangeLower.Value;
+ }
+
+ // set the range upper attribute
+ if (_rangeUpper != null)
+ {
+ _propertyEntry.Properties[PropertyManager.RangeUpper].Value = (int)_rangeUpper.Value;
+ }
+
+ // set the searchFlags attribute
+ if (_searchFlags != SearchFlags.None)
+ {
+ _propertyEntry.Properties[PropertyManager.SearchFlags].Value = (int)_searchFlags;
+ }
+
+ // set the link id
+ if (_linkId != null)
+ {
+ _propertyEntry.Properties[PropertyManager.LinkID].Value = (int)_linkId.Value;
+ }
+
+ // set the schemaIDGuid property
+ if (_schemaGuidBinaryForm != null)
+ {
+ SetProperty(PropertyManager.SchemaIDGuid, _schemaGuidBinaryForm);
+ }
+ }
+
+ try
+ {
+ // commit the classEntry to server
+ _propertyEntry.CommitChanges();
+
+ // Refresh the schema cache on the schema role owner
+ if (_schema == null)
+ {
+ ActiveDirectorySchema schemaObject = ActiveDirectorySchema.GetSchema(_context);
+ bool alreadyUsingSchemaRoleOwnerContext = false;
+ DirectoryServer schemaRoleOwner = null;
+
+ try
+ {
+ //
+ // if we are not already talking to the schema role owner, change the context
+ //
+ schemaRoleOwner = schemaObject.SchemaRoleOwner;
+ if (Utils.Compare(schemaRoleOwner.Name, _context.GetServerName()) != 0)
+ {
+ DirectoryContext schemaRoleOwnerContext = Utils.GetNewDirectoryContext(schemaRoleOwner.Name, DirectoryContextType.DirectoryServer, _context);
+ _schema = ActiveDirectorySchema.GetSchema(schemaRoleOwnerContext);
+ }
+ else
+ {
+ alreadyUsingSchemaRoleOwnerContext = true;
+ _schema = schemaObject;
+ }
+ }
+ finally
+ {
+ if (schemaRoleOwner != null)
+ {
+ schemaRoleOwner.Dispose();
+ }
+ if (!alreadyUsingSchemaRoleOwnerContext)
+ {
+ schemaObject.Dispose();
+ }
+ }
+ }
+ _schema.RefreshSchema();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+
+ // now that the changes are committed to the server
+ // update the defunct/non-defunct status of the class on the server
+ _isDefunctOnServer = _isDefunct;
+
+ // invalidate all properties
+ _commonName = null;
+ _oid = null;
+ _syntaxInitialized = false;
+ _descriptionInitialized = false;
+ _isSingleValuedInitialized = false;
+ _isInGlobalCatalogInitialized = false;
+ _rangeLowerInitialized = false;
+ _rangeUpperInitialized = false;
+ _searchFlagsInitialized = false;
+ _linkedPropertyInitialized = false;
+ _linkIdInitialized = false;
+ _schemaGuidBinaryForm = null;
+ _propertiesFromSchemaContainerInitialized = false;
+
+ // set bind flag
+ isBound = true;
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ CheckIfDisposed();
+
+ if (!isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotGetObject));
+ }
+
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ return DirectoryEntryManager.GetDirectoryEntryInternal(_context, _propertyEntry.Path);
+ }
+ #endregion public methods
+
+ #region public properties
+
+ public string Name
+ {
+ get
+ {
+ CheckIfDisposed();
+ return _ldapDisplayName;
+ }
+ }
+
+ public string CommonName
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (_commonName == null)
+ {
+ // get the property from the server
+ _commonName = (string)GetValueFromCache(PropertyManager.Cn, true);
+ }
+ }
+ return _commonName;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (value != null && value.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "value");
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.Cn, value);
+ }
+ _commonName = value;
+ }
+ }
+
+ public string Oid
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (_oid == null)
+ {
+ // get the property from the abstract schema/ schema container
+ // (for non-defunt classes this property is available in the abstract schema)
+ if (!_isDefunctOnServer)
+ {
+ try
+ {
+ _oid = _iadsProperty.OID;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ else
+ {
+ _oid = (string)GetValueFromCache(PropertyManager.AttributeID, true);
+ }
+ }
+ }
+ return _oid;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (value != null && value.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "value");
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.AttributeID, value);
+ }
+ _oid = value;
+ }
+ }
+
+ public ActiveDirectorySyntax Syntax
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_syntaxInitialized)
+ {
+ byte[] omObjectClassBinaryForm = (byte[])GetValueFromCache(PropertyManager.OMObjectClass, false);
+ OMObjectClass omObjectClass = (omObjectClassBinaryForm != null) ? new OMObjectClass(omObjectClassBinaryForm) : null;
+
+ _syntax = MapSyntax((string)GetValueFromCache(PropertyManager.AttributeSyntax, true),
+ (int)GetValueFromCache(PropertyManager.OMSyntax, true),
+ omObjectClass);
+ _syntaxInitialized = true;
+ }
+ }
+ return _syntax;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (value < ActiveDirectorySyntax.CaseExactString || value > ActiveDirectorySyntax.ReplicaLink)
+ {
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(ActiveDirectorySyntax));
+ }
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetSyntax(value);
+ }
+ _syntax = value;
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_descriptionInitialized)
+ {
+ // get the property from the server
+ _description = (string)GetValueFromCache(PropertyManager.Description, false);
+ _descriptionInitialized = true;
+ }
+ }
+ return _description;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (value != null && value.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "value");
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.Description, value);
+ }
+ _description = value;
+ }
+ }
+
+ public bool IsSingleValued
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_isSingleValuedInitialized)
+ {
+ // get the property from the abstract schema/ schema container
+ // (for non-defunt classes this property is available in the abstract schema)
+ if (!_isDefunctOnServer)
+ {
+ try
+ {
+ _isSingleValued = !_iadsProperty.MultiValued;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ else
+ {
+ _isSingleValued = (bool)GetValueFromCache(PropertyManager.IsSingleValued, true);
+ }
+ _isSingleValuedInitialized = true;
+ }
+ }
+ return _isSingleValued;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // get the distinguished name to construct the directory entry
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ // set the value on the directory entry
+ _propertyEntry.Properties[PropertyManager.IsSingleValued].Value = value;
+ }
+ _isSingleValued = value;
+ }
+ }
+
+ public bool IsIndexed
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ return IsSetInSearchFlags(SearchFlags.IsIndexed);
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (value)
+ {
+ SetBitInSearchFlags(SearchFlags.IsIndexed);
+ }
+ else
+ {
+ ResetBitInSearchFlags(SearchFlags.IsIndexed);
+ }
+ }
+ }
+
+ public bool IsIndexedOverContainer
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ return IsSetInSearchFlags(SearchFlags.IsIndexedOverContainer);
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (value)
+ {
+ SetBitInSearchFlags(SearchFlags.IsIndexedOverContainer);
+ }
+ else
+ {
+ ResetBitInSearchFlags(SearchFlags.IsIndexedOverContainer);
+ }
+ }
+ }
+
+ public bool IsInAnr
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ return IsSetInSearchFlags(SearchFlags.IsInAnr);
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (value)
+ {
+ SetBitInSearchFlags(SearchFlags.IsInAnr);
+ }
+ else
+ {
+ ResetBitInSearchFlags(SearchFlags.IsInAnr);
+ }
+ }
+ }
+
+ public bool IsOnTombstonedObject
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ return IsSetInSearchFlags(SearchFlags.IsOnTombstonedObject);
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (value)
+ {
+ SetBitInSearchFlags(SearchFlags.IsOnTombstonedObject);
+ }
+ else
+ {
+ ResetBitInSearchFlags(SearchFlags.IsOnTombstonedObject);
+ }
+ }
+ }
+
+ public bool IsTupleIndexed
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ return IsSetInSearchFlags(SearchFlags.IsTupleIndexed);
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (value)
+ {
+ SetBitInSearchFlags(SearchFlags.IsTupleIndexed);
+ }
+ else
+ {
+ ResetBitInSearchFlags(SearchFlags.IsTupleIndexed);
+ }
+ }
+ }
+
+ public bool IsInGlobalCatalog
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_isInGlobalCatalogInitialized)
+ {
+ // get the property from the server
+ object value = GetValueFromCache(PropertyManager.IsMemberOfPartialAttributeSet, false);
+ _isInGlobalCatalog = (value != null) ? (bool)value : false;
+ _isInGlobalCatalogInitialized = true;
+ }
+ }
+ return _isInGlobalCatalog;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // get the distinguished name to construct the directory entry
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ // set the value on the directory entry
+ _propertyEntry.Properties[PropertyManager.IsMemberOfPartialAttributeSet].Value = value;
+ }
+ _isInGlobalCatalog = value;
+ }
+ }
+
+ public Nullable<Int32> RangeLower
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_rangeLowerInitialized)
+ {
+ // get the property from the server
+ // if the property is not set then we will return null
+ object value = GetValueFromCache(PropertyManager.RangeLower, false);
+ if (value == null)
+ {
+ _rangeLower = null;
+ }
+ else
+ {
+ _rangeLower = (int)value;
+ }
+ _rangeLowerInitialized = true;
+ }
+ }
+ return _rangeLower;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // get the distinguished name to construct the directory entry
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ // set the value on the directory entry
+ if (value == null)
+ {
+ if (_propertyEntry.Properties.Contains(PropertyManager.RangeLower))
+ {
+ _propertyEntry.Properties[PropertyManager.RangeLower].Clear();
+ }
+ }
+ else
+ {
+ _propertyEntry.Properties[PropertyManager.RangeLower].Value = (int)value.Value;
+ }
+ }
+ _rangeLower = value;
+ }
+ }
+
+ public Nullable<Int32> RangeUpper
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_rangeUpperInitialized)
+ {
+ // get the property from the server
+ // if the property is not set then we will return null
+ object value = GetValueFromCache(PropertyManager.RangeUpper, false);
+ if (value == null)
+ {
+ _rangeUpper = null;
+ }
+ else
+ {
+ _rangeUpper = (int)value;
+ }
+ _rangeUpperInitialized = true;
+ }
+ }
+ return _rangeUpper;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // get the distinguished name to construct the directory entry
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ // set the value on the directory entry
+ if (value == null)
+ {
+ if (_propertyEntry.Properties.Contains(PropertyManager.RangeUpper))
+ {
+ _propertyEntry.Properties[PropertyManager.RangeUpper].Clear();
+ }
+ }
+ else
+ {
+ _propertyEntry.Properties[PropertyManager.RangeUpper].Value = (int)value.Value;
+ }
+ }
+ _rangeUpper = value;
+ }
+ }
+
+ public bool IsDefunct
+ {
+ get
+ {
+ CheckIfDisposed();
+ // this is initialized for bound properties in the constructor
+ return _isDefunct;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.IsDefunct, value);
+ }
+ _isDefunct = value;
+ }
+ }
+
+ public ActiveDirectorySchemaProperty Link
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_linkedPropertyInitialized)
+ {
+ object value = GetValueFromCache(PropertyManager.LinkID, false);
+ int tempLinkId = (value != null) ? (int)value : -1;
+
+ if (tempLinkId != -1)
+ {
+ int linkIdToSearch = tempLinkId - 2 * (tempLinkId % 2) + 1;
+
+ try
+ {
+ if (_schemaEntry == null)
+ {
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
+ }
+
+ string filter = "(&(" + PropertyManager.ObjectCategory + "=attributeSchema)" + "(" + PropertyManager.LinkID + "=" + linkIdToSearch + "))";
+ ReadOnlyActiveDirectorySchemaPropertyCollection linkedProperties = ActiveDirectorySchema.GetAllProperties(_context, _schemaEntry, filter);
+
+ if (linkedProperties.Count != 1)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.LinkedPropertyNotFound, linkIdToSearch), typeof(ActiveDirectorySchemaProperty), null);
+ }
+
+ _linkedProperty = linkedProperties[0];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ _linkedPropertyInitialized = true;
+ }
+ }
+ return _linkedProperty;
+ }
+ }
+
+ public Nullable<Int32> LinkId
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ if (!_linkIdInitialized)
+ {
+ object value = GetValueFromCache(PropertyManager.LinkID, false);
+ // if the property was not set we will return null
+ if (value == null)
+ {
+ _linkId = null;
+ }
+ else
+ {
+ _linkId = (int)value;
+ }
+ _linkIdInitialized = true;
+ }
+ }
+ return _linkId;
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // get the distinguished name to construct the directory entry
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ // set the value on the directory entry
+ if (value == null)
+ {
+ if (_propertyEntry.Properties.Contains(PropertyManager.LinkID))
+ {
+ _propertyEntry.Properties[PropertyManager.LinkID].Clear();
+ }
+ }
+ else
+ {
+ _propertyEntry.Properties[PropertyManager.LinkID].Value = (int)value.Value;
+ }
+ }
+ _linkId = value;
+ }
+ }
+
+ public Guid SchemaGuid
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ Guid schemaGuid = Guid.Empty;
+
+ if (isBound)
+ {
+ if (_schemaGuidBinaryForm == null)
+ {
+ // get the property from the server
+ _schemaGuidBinaryForm = (byte[])GetValueFromCache(PropertyManager.SchemaIDGuid, true);
+ }
+ }
+
+ // we cache the byte array and create a new guid each time
+ return new Guid(_schemaGuidBinaryForm);
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (isBound)
+ {
+ // set the value on the directory entry
+ SetProperty(PropertyManager.SchemaIDGuid, (value.Equals(Guid.Empty)) ? null : value.ToByteArray());
+ }
+ _schemaGuidBinaryForm = (value.Equals(Guid.Empty)) ? null : value.ToByteArray();
+ }
+ }
+
+ #endregion public properties
+
+ #region private methods
+
+ private void CheckIfDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+
+ //
+ // This method retrieves the value of a property (single valued) from the values
+ // that were retrieved from the server. The "mustExist" parameter controls whether or
+ // not an exception should be thrown if a value does not exist. If mustExist is true, this
+ // will throw an exception is value does not exist.
+ //
+ private object GetValueFromCache(string propertyName, bool mustExist)
+ {
+ object value = null;
+
+ // retrieve the properties from the server if necessary
+ InitializePropertiesFromSchemaContainer();
+
+ Debug.Assert(_propertyValuesFromServer != null);
+
+ ResultPropertyValueCollection propertyValues = null;
+ try
+ {
+ propertyValues = _propertyValuesFromServer.Properties[propertyName];
+ if ((propertyValues == null) || (propertyValues.Count < 1))
+ {
+ if (mustExist)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.PropertyNotFound, propertyName));
+ }
+ }
+ else
+ {
+ value = propertyValues[0];
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+
+ return value;
+ }
+
+ //
+ // Just calls the static method GetPropertiesFromSchemaContainer with the correct context
+ //
+ private void InitializePropertiesFromSchemaContainer()
+ {
+ if (!_propertiesFromSchemaContainerInitialized)
+ {
+ if (_schemaEntry == null)
+ {
+ _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
+ }
+
+ _propertyValuesFromServer = GetPropertiesFromSchemaContainer(_context, _schemaEntry, (_isDefunctOnServer) ? _commonName : _ldapDisplayName, _isDefunctOnServer);
+ _propertiesFromSchemaContainerInitialized = true;
+ }
+ }
+
+ //
+ // This method retrieves properties for this schema class from the schema container
+ // on the server. For non-defunct classes only properties that are not available in the abstract
+ // schema are retrieved. For defunct classes, all the properties are retrieved.
+ // The retrieved values are stored in a class variable "propertyValuesFromServer" which is a
+ // hashtable indexed on the property name.
+ //
+ internal static SearchResult GetPropertiesFromSchemaContainer(DirectoryContext context, DirectoryEntry schemaEntry, string name, bool isDefunctOnServer)
+ {
+ SearchResult propertyValuesFromServer = null;
+
+ //
+ // The properties that are loaded from the schemaContainer for non-defunct classes:
+ // DistinguishedName
+ // CommonName
+ // Syntax - AttributeSyntax, OMSyntax, OMObjectClass
+ // Description
+ // IsIndexed, IsIndexedOverContainer, IsInAnr, IsOnTombstonedObject, IsTupleIndexed - SearchFlags
+ // IsInGlobalCatalog - IsMemberOfPartialAttributeSet
+ // LinkId (Link)
+ // SchemaGuid - SchemaIdGuid
+ // RangeLower
+ // RangeUpper
+
+ //
+ // For defunct class we also load teh remaining properties
+ // LdapDisplayName
+ // Oid
+ // IsSingleValued
+ //
+
+ // build the filter
+ StringBuilder str = new StringBuilder(15);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=attributeSchema)");
+ str.Append("(");
+ if (!isDefunctOnServer)
+ {
+ str.Append(PropertyManager.LdapDisplayName);
+ }
+ else
+ {
+ str.Append(PropertyManager.Cn);
+ }
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(name));
+ str.Append(")");
+ if (!isDefunctOnServer)
+ {
+ str.Append("(!(");
+ }
+ else
+ {
+ str.Append("(");
+ }
+ str.Append(PropertyManager.IsDefunct);
+ if (!isDefunctOnServer)
+ {
+ str.Append("=TRUE)))");
+ }
+ else
+ {
+ str.Append("=TRUE))");
+ }
+
+ string[] propertiesToLoad = null;
+ if (!isDefunctOnServer)
+ {
+ propertiesToLoad = new string[12];
+
+ propertiesToLoad[0] = PropertyManager.DistinguishedName;
+ propertiesToLoad[1] = PropertyManager.Cn;
+ propertiesToLoad[2] = PropertyManager.AttributeSyntax;
+ propertiesToLoad[3] = PropertyManager.OMSyntax;
+ propertiesToLoad[4] = PropertyManager.OMObjectClass;
+ propertiesToLoad[5] = PropertyManager.Description;
+ propertiesToLoad[6] = PropertyManager.SearchFlags;
+ propertiesToLoad[7] = PropertyManager.IsMemberOfPartialAttributeSet;
+ propertiesToLoad[8] = PropertyManager.LinkID;
+ propertiesToLoad[9] = PropertyManager.SchemaIDGuid;
+ propertiesToLoad[10] = PropertyManager.RangeLower;
+ propertiesToLoad[11] = PropertyManager.RangeUpper;
+ }
+ else
+ {
+ propertiesToLoad = new string[15];
+
+ propertiesToLoad[0] = PropertyManager.DistinguishedName;
+ propertiesToLoad[1] = PropertyManager.Cn;
+ propertiesToLoad[2] = PropertyManager.AttributeSyntax;
+ propertiesToLoad[3] = PropertyManager.OMSyntax;
+ propertiesToLoad[4] = PropertyManager.OMObjectClass;
+ propertiesToLoad[5] = PropertyManager.Description;
+ propertiesToLoad[6] = PropertyManager.SearchFlags;
+ propertiesToLoad[7] = PropertyManager.IsMemberOfPartialAttributeSet;
+ propertiesToLoad[8] = PropertyManager.LinkID;
+ propertiesToLoad[9] = PropertyManager.SchemaIDGuid;
+ propertiesToLoad[10] = PropertyManager.AttributeID;
+ propertiesToLoad[11] = PropertyManager.IsSingleValued;
+ propertiesToLoad[12] = PropertyManager.RangeLower;
+ propertiesToLoad[13] = PropertyManager.RangeUpper;
+ propertiesToLoad[14] = PropertyManager.LdapDisplayName;
+ }
+
+ //
+ // Get all the values (don't need to use range retrieval as there are no multivalued attributes)
+ //
+ ADSearcher searcher = new ADSearcher(schemaEntry, str.ToString(), propertiesToLoad, SearchScope.OneLevel, false /* paged search */, false /* cache results */);
+
+ try
+ {
+ propertyValuesFromServer = searcher.FindOne();
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // object is not found since we cannot even find the container in which to search
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySchemaProperty), name);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ if (propertyValuesFromServer == null)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySchemaProperty), name);
+ }
+
+ return propertyValuesFromServer;
+ }
+
+ internal DirectoryEntry GetSchemaPropertyDirectoryEntry()
+ {
+ if (_propertyEntry == null)
+ {
+ InitializePropertiesFromSchemaContainer();
+ _propertyEntry = DirectoryEntryManager.GetDirectoryEntry(_context, (string)GetValueFromCache(PropertyManager.DistinguishedName, true));
+ }
+
+ return _propertyEntry;
+ }
+
+ ///
+ /// <summary>
+ /// Initializes the search flags attribute value i.e. fetches it from
+ /// the directory, if this object is bound.
+ /// </summary>
+ ///
+ private void InitializeSearchFlags()
+ {
+ if (isBound)
+ {
+ if (!_searchFlagsInitialized)
+ {
+ object value = GetValueFromCache(PropertyManager.SearchFlags, false);
+
+ if (value != null)
+ {
+ _searchFlags = (SearchFlags)((int)value);
+ }
+ _searchFlagsInitialized = true;
+ }
+ }
+ }
+
+ private bool IsSetInSearchFlags(SearchFlags searchFlagBit)
+ {
+ InitializeSearchFlags();
+ return (((int)_searchFlags & (int)searchFlagBit) != 0);
+ }
+
+ private void SetBitInSearchFlags(SearchFlags searchFlagBit)
+ {
+ InitializeSearchFlags();
+ _searchFlags = (SearchFlags)((int)_searchFlags | (int)searchFlagBit);
+
+ if (isBound)
+ {
+ // get the distinguished name to construct the directory entry
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ // set the value on the directory entry
+ _propertyEntry.Properties[PropertyManager.SearchFlags].Value = (int)_searchFlags;
+ }
+ }
+
+ private void ResetBitInSearchFlags(SearchFlags searchFlagBit)
+ {
+ InitializeSearchFlags();
+ _searchFlags = (SearchFlags)((int)_searchFlags & ~((int)searchFlagBit));
+
+ if (isBound)
+ {
+ // get the distinguished name to construct the directory entry
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ // set the value on the directory entry
+ _propertyEntry.Properties[PropertyManager.SearchFlags].Value = (int)_searchFlags;
+ }
+ }
+
+ private void SetProperty(string propertyName, object value)
+ {
+ // get the distinguished name to construct the directory entry
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ if (value == null)
+ {
+ if (_propertyEntry.Properties.Contains(propertyName))
+ {
+ _propertyEntry.Properties[propertyName].Clear();
+ }
+ }
+ else
+ {
+ _propertyEntry.Properties[propertyName].Value = value;
+ }
+ }
+
+ private ActiveDirectorySyntax MapSyntax(string syntaxId, int oMID, OMObjectClass oMObjectClass)
+ {
+ for (int i = 0; i < s_syntaxesCount; i++)
+ {
+ if (s_syntaxes[i].Equals(new Syntax(syntaxId, oMID, oMObjectClass)))
+ {
+ return (ActiveDirectorySyntax)i;
+ }
+ }
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.UnknownSyntax, _ldapDisplayName));
+ }
+
+ private void SetSyntax(ActiveDirectorySyntax syntax)
+ {
+ if ((((int)syntax) < 0) || (((int)syntax) > (s_syntaxesCount - 1)))
+ {
+ throw new InvalidEnumArgumentException("syntax", (int)syntax, typeof(ActiveDirectorySyntax));
+ }
+
+ // get the distinguished name to construct the directory entry
+ GetSchemaPropertyDirectoryEntry();
+ Debug.Assert(_propertyEntry != null);
+
+ _propertyEntry.Properties[PropertyManager.AttributeSyntax].Value = s_syntaxes[(int)syntax].attributeSyntax;
+ _propertyEntry.Properties[PropertyManager.OMSyntax].Value = s_syntaxes[(int)syntax].oMSyntax;
+ OMObjectClass oMObjectClass = s_syntaxes[(int)syntax].oMObjectClass;
+ if (oMObjectClass != null)
+ {
+ _propertyEntry.Properties[PropertyManager.OMObjectClass].Value = oMObjectClass.Data;
+ }
+ }
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaPropertyCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaPropertyCollection.cs
new file mode 100644
index 0000000000..eff28bc028
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySchemaPropertyCollection.cs
@@ -0,0 +1,394 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+
+ public class ActiveDirectorySchemaPropertyCollection : CollectionBase
+ {
+ private DirectoryEntry _classEntry = null;
+ private string _propertyName = null;
+ private ActiveDirectorySchemaClass _schemaClass = null;
+ private bool _isBound = false;
+ private DirectoryContext _context = null;
+
+ internal ActiveDirectorySchemaPropertyCollection(DirectoryContext context,
+ ActiveDirectorySchemaClass schemaClass,
+ bool isBound,
+ string propertyName,
+ ICollection propertyNames,
+ bool onlyNames)
+ {
+ _schemaClass = schemaClass;
+ _propertyName = propertyName;
+ _isBound = isBound;
+ _context = context;
+
+ foreach (string ldapDisplayName in propertyNames)
+ {
+ // all properties in writeable property collection are non-defunct
+ // so calling constructor for non-defunct property
+ this.InnerList.Add(new ActiveDirectorySchemaProperty(context, ldapDisplayName, (DirectoryEntry)null, null));
+ }
+ }
+
+ internal ActiveDirectorySchemaPropertyCollection(DirectoryContext context,
+ ActiveDirectorySchemaClass schemaClass,
+ bool isBound,
+ string propertyName,
+ ICollection properties)
+ {
+ _schemaClass = schemaClass;
+ _propertyName = propertyName;
+ _isBound = isBound;
+ _context = context;
+
+ foreach (ActiveDirectorySchemaProperty schemaProperty in properties)
+ {
+ this.InnerList.Add(schemaProperty);
+ }
+ }
+
+ public ActiveDirectorySchemaProperty this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySchemaProperty)List[index];
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!value.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, value.Name));
+ }
+
+ if (!Contains(value))
+ {
+ List[index] = value;
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, value), "value");
+ }
+ }
+ }
+
+ public int Add(ActiveDirectorySchemaProperty schemaProperty)
+ {
+ if (schemaProperty == null)
+ {
+ throw new ArgumentNullException("schemaProperty");
+ }
+
+ if (!schemaProperty.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaProperty.Name));
+ }
+
+ if (!Contains(schemaProperty))
+ {
+ return List.Add(schemaProperty);
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, schemaProperty), "schemaProperty");
+ }
+ }
+
+ public void AddRange(ActiveDirectorySchemaProperty[] properties)
+ {
+ if (properties == null)
+ {
+ throw new ArgumentNullException("properties");
+ }
+
+ foreach (ActiveDirectorySchemaProperty property in properties)
+ {
+ if (property == null)
+ {
+ throw new ArgumentException("properties");
+ }
+ }
+
+ for (int i = 0; ((i) < (properties.Length)); i = ((i) + (1)))
+ {
+ this.Add((ActiveDirectorySchemaProperty)properties[i]);
+ }
+ }
+
+ public void AddRange(ActiveDirectorySchemaPropertyCollection properties)
+ {
+ if (properties == null)
+ {
+ throw new ArgumentNullException("properties");
+ }
+
+ foreach (ActiveDirectorySchemaProperty property in properties)
+ {
+ if (property == null)
+ {
+ throw new ArgumentException("properties");
+ }
+ }
+
+ int currentCount = properties.Count;
+
+ for (int i = 0; i < currentCount; i++)
+ {
+ this.Add(properties[i]);
+ }
+ }
+
+ public void AddRange(ReadOnlyActiveDirectorySchemaPropertyCollection properties)
+ {
+ if (properties == null)
+ {
+ throw new ArgumentNullException("properties");
+ }
+
+ foreach (ActiveDirectorySchemaProperty property in properties)
+ {
+ if (property == null)
+ {
+ throw new ArgumentException("properties");
+ }
+ }
+
+ int currentCount = properties.Count;
+
+ for (int i = 0; i < currentCount; i++)
+ {
+ this.Add(properties[i]);
+ }
+ }
+
+ public void Remove(ActiveDirectorySchemaProperty schemaProperty)
+ {
+ if (schemaProperty == null)
+ {
+ throw new ArgumentNullException("schemaProperty");
+ }
+
+ if (!schemaProperty.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaProperty.Name));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaProperty tmp = (ActiveDirectorySchemaProperty)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaProperty.Name) == 0)
+ {
+ List.Remove(tmp);
+ return;
+ }
+ }
+ throw new ArgumentException(Res.GetString(Res.NotFoundInCollection, schemaProperty), "schemaProperty");
+ }
+
+ public void Insert(int index, ActiveDirectorySchemaProperty schemaProperty)
+ {
+ if (schemaProperty == null)
+ {
+ throw new ArgumentNullException("schemaProperty");
+ }
+
+ if (!schemaProperty.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaProperty.Name));
+ }
+
+ if (!Contains(schemaProperty))
+ {
+ List.Insert(index, schemaProperty);
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, schemaProperty), "schemaProperty");
+ }
+ }
+
+ public bool Contains(ActiveDirectorySchemaProperty schemaProperty)
+ {
+ if (schemaProperty == null)
+ {
+ throw new ArgumentNullException("schemaProperty");
+ }
+
+ if (!schemaProperty.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaProperty.Name));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaProperty tmp = (ActiveDirectorySchemaProperty)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaProperty.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal bool Contains(string propertyName)
+ {
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaProperty tmp = (ActiveDirectorySchemaProperty)InnerList[i];
+
+ if (Utils.Compare(tmp.Name, propertyName) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void CopyTo(ActiveDirectorySchemaProperty[] properties, int index)
+ {
+ List.CopyTo(properties, index);
+ }
+
+ public int IndexOf(ActiveDirectorySchemaProperty schemaProperty)
+ {
+ if (schemaProperty == null)
+ {
+ throw new ArgumentNullException("schemaProperty");
+ }
+
+ if (!schemaProperty.isBound)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, schemaProperty.Name));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaProperty tmp = (ActiveDirectorySchemaProperty)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaProperty.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ protected override void OnClearComplete()
+ {
+ if (_isBound)
+ {
+ if (_classEntry == null)
+ {
+ _classEntry = _schemaClass.GetSchemaClassDirectoryEntry();
+ }
+
+ try
+ {
+ if (_classEntry.Properties.Contains(_propertyName))
+ {
+ _classEntry.Properties[_propertyName].Clear();
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ }
+
+ protected override void OnInsertComplete(int index, object value)
+ {
+ if (_isBound)
+ {
+ if (_classEntry == null)
+ {
+ _classEntry = _schemaClass.GetSchemaClassDirectoryEntry();
+ }
+
+ try
+ {
+ _classEntry.Properties[_propertyName].Add(((ActiveDirectorySchemaProperty)value).Name);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ }
+
+ protected override void OnRemoveComplete(int index, object value)
+ {
+ if (_isBound)
+ {
+ if (_classEntry == null)
+ {
+ _classEntry = _schemaClass.GetSchemaClassDirectoryEntry();
+ }
+
+ // because this collection can contain values from the superior classes,
+ // these values would not exist in the classEntry
+ // and therefore cannot be removed
+ // we need to throw an exception here
+ string valueName = ((ActiveDirectorySchemaProperty)value).Name;
+
+ try
+ {
+ if (_classEntry.Properties[_propertyName].Contains(valueName))
+ {
+ _classEntry.Properties[_propertyName].Remove(valueName);
+ }
+ else
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ValueCannotBeModified));
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ }
+ protected override void OnSetComplete(int index, object oldValue, object newValue)
+ {
+ if (_isBound)
+ {
+ // remove the old value
+ OnRemoveComplete(index, oldValue);
+
+ // add the new value
+ OnInsertComplete(index, newValue);
+ }
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ if (!(value is ActiveDirectorySchemaProperty))
+ throw new ArgumentException("value");
+
+ if (!((ActiveDirectorySchemaProperty)value).isBound)
+ throw new InvalidOperationException(Res.GetString(Res.SchemaObjectNotCommitted, ((ActiveDirectorySchemaProperty)value).Name));
+ }
+
+ internal string[] GetMultiValuedProperty()
+ {
+ string[] values = new string[InnerList.Count];
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ values[i] = ((ActiveDirectorySchemaProperty)InnerList[i]).Name;
+ }
+ return values;
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySite.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySite.cs
new file mode 100644
index 0000000000..9edd29af18
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySite.cs
@@ -0,0 +1,1502 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.Text;
+ using System.ComponentModel;
+ using System.Security.Permissions;
+
+ [Flags]
+ public enum ActiveDirectorySiteOptions
+ {
+ None = 0,
+ AutoTopologyDisabled = 1,
+ TopologyCleanupDisabled = 2,
+ AutoMinimumHopDisabled = 4,
+ StaleServerDetectDisabled = 8,
+ AutoInterSiteTopologyDisabled = 16,
+ GroupMembershipCachingEnabled = 32,
+ ForceKccWindows2003Behavior = 64,
+ UseWindows2000IstgElection = 128,
+ RandomBridgeHeaderServerSelectionDisabled = 256,
+ UseHashingForReplicationSchedule = 512,
+ RedundantServerTopologyEnabled = 1024
+ }
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ActiveDirectorySite : IDisposable
+ {
+ internal DirectoryContext context = null;
+ private string _name = null;
+ internal DirectoryEntry cachedEntry = null;
+ private DirectoryEntry _ntdsEntry = null;
+ private ActiveDirectorySubnetCollection _subnets = null;
+ private DirectoryServer _topologyGenerator = null;
+ private ReadOnlySiteCollection _adjacentSites = new ReadOnlySiteCollection();
+ private bool _disposed = false;
+ private DomainCollection _domains = new DomainCollection(null);
+ private ReadOnlyDirectoryServerCollection _servers = new ReadOnlyDirectoryServerCollection();
+ private ReadOnlySiteLinkCollection _links = new ReadOnlySiteLinkCollection();
+ private ActiveDirectorySiteOptions _siteOptions = ActiveDirectorySiteOptions.None;
+ private ReadOnlyDirectoryServerCollection _bridgeheadServers = new ReadOnlyDirectoryServerCollection();
+ private DirectoryServerCollection _SMTPBridgeheadServers = null;
+ private DirectoryServerCollection _RPCBridgeheadServers = null;
+ private byte[] _replicationSchedule = null;
+
+ internal bool existing = false;
+ private bool _subnetRetrieved = false;
+ private bool _isADAMServer = false;
+ private bool _checkADAM = false;
+ private bool _topologyTouched = false;
+ private bool _adjacentSitesRetrieved = false;
+ private string _siteDN = null;
+ private bool _domainsRetrieved = false;
+ private bool _serversRetrieved = false;
+ private bool _belongLinksRetrieved = false;
+ private bool _bridgeheadServerRetrieved = false;
+ private bool _SMTPBridgeRetrieved = false;
+ private bool _RPCBridgeRetrieved = false;
+
+ private static int s_ERROR_NO_SITENAME = 1919;
+
+ public static ActiveDirectorySite FindByName(DirectoryContext context, string siteName)
+ {
+ // find an existing site
+ ValidateArgument(context, siteName);
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // bind to the rootdse to get the configurationnamingcontext
+ DirectoryEntry de;
+ string sitedn;
+ try
+ {
+ de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ sitedn = "CN=Sites," + (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ de = DirectoryEntryManager.GetDirectoryEntry(context, sitedn);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ try
+ {
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=site)(objectCategory=site)(name=" + Utils.GetEscapedFilterValue(siteName) + "))",
+ new string[] { "distinguishedName" },
+ SearchScope.OneLevel,
+ false, /* don't need paged search */
+ false /* don't need to cache result */);
+ SearchResult srchResult = adSearcher.FindOne();
+ if (srchResult == null)
+ {
+ // no such site object
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySite), siteName);
+ }
+ // it is an existing site object
+ ActiveDirectorySite site = new ActiveDirectorySite(context, siteName, true);
+ return site;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // object is not found since we cannot even find the container in which to search
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySite), siteName);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ finally
+ {
+ de.Dispose();
+ }
+ }
+
+ public ActiveDirectorySite(DirectoryContext context, string siteName)
+ {
+ ValidateArgument(context, siteName);
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ this.context = context;
+ _name = siteName;
+
+ // bind to the rootdse to get the configurationnamingcontext
+ DirectoryEntry de = null;
+ try
+ {
+ de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ _siteDN = "CN=Sites," + config;
+ // bind to the site container
+ de = DirectoryEntryManager.GetDirectoryEntry(context, _siteDN);
+
+ string rdn = "cn=" + _name;
+ rdn = Utils.GetEscapedPath(rdn);
+ cachedEntry = de.Children.Add(rdn, "site");
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+ finally
+ {
+ if (de != null)
+ de.Dispose();
+ }
+
+ _subnets = new ActiveDirectorySubnetCollection(context, "CN=" + siteName + "," + _siteDN);
+ string transportDN = "CN=IP,CN=Inter-Site Transports," + _siteDN;
+ _RPCBridgeheadServers = new DirectoryServerCollection(context, "CN=" + siteName + "," + _siteDN, transportDN);
+ transportDN = "CN=SMTP,CN=Inter-Site Transports," + _siteDN;
+ _SMTPBridgeheadServers = new DirectoryServerCollection(context, "CN=" + siteName + "," + _siteDN, transportDN);
+ }
+
+ internal ActiveDirectorySite(DirectoryContext context, string siteName, bool existing)
+ {
+ Debug.Assert(existing == true);
+
+ this.context = context;
+ _name = siteName;
+ this.existing = existing;
+
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ _siteDN = "CN=Sites," + (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+
+ cachedEntry = DirectoryEntryManager.GetDirectoryEntry(context, "CN=" + siteName + "," + _siteDN);
+ _subnets = new ActiveDirectorySubnetCollection(context, "CN=" + siteName + "," + _siteDN);
+
+ string transportDN = "CN=IP,CN=Inter-Site Transports," + _siteDN;
+ _RPCBridgeheadServers = new DirectoryServerCollection(context, (string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName), transportDN);
+ transportDN = "CN=SMTP,CN=Inter-Site Transports," + _siteDN;
+ _SMTPBridgeheadServers = new DirectoryServerCollection(context, (string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName), transportDN);
+ }
+
+ public static ActiveDirectorySite GetComputerSite()
+ {
+ // make sure that this is the platform that we support
+ new DirectoryContext(DirectoryContextType.Forest);
+
+ IntPtr ptr = (IntPtr)0;
+
+ int result = UnsafeNativeMethods.DsGetSiteName(null, ref ptr);
+ if (result != 0)
+ {
+ // computer is not in a site
+ if (result == s_ERROR_NO_SITENAME)
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.NoCurrentSite), typeof(ActiveDirectorySite), null);
+ else
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+ else
+ {
+ try
+ {
+ string siteName = Marshal.PtrToStringUni(ptr);
+ Debug.Assert(siteName != null);
+
+ // find the forest this machine belongs to
+ string forestName = Locator.GetDomainControllerInfo(null, null, null, (long)PrivateLocatorFlags.DirectoryServicesRequired).DnsForestName;
+ DirectoryContext currentContext = Utils.GetNewDirectoryContext(forestName, DirectoryContextType.Forest, null);
+
+ // existing site
+ ActiveDirectorySite site = ActiveDirectorySite.FindByName(currentContext, siteName);
+ return site;
+ }
+ finally
+ {
+ if (ptr != (IntPtr)0)
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _name;
+ }
+ }
+
+ public DomainCollection Domains
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ if (!_domainsRetrieved)
+ {
+ // clear it first to be safe in case GetDomains fail in the middle and leave partial results there
+ _domains.Clear();
+ GetDomains();
+ _domainsRetrieved = true;
+ }
+ }
+
+ return _domains;
+ }
+ }
+
+ public ActiveDirectorySubnetCollection Subnets
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ // if asked the first time, we need to properly construct the subnets collection
+ if (!_subnetRetrieved)
+ {
+ _subnets.initialized = false;
+ _subnets.Clear();
+ GetSubnets();
+ _subnetRetrieved = true;
+ }
+ }
+ _subnets.initialized = true;
+
+ return _subnets;
+ }
+ }
+
+ public ReadOnlyDirectoryServerCollection Servers
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ if (!_serversRetrieved)
+ {
+ _servers.Clear();
+ GetServers();
+ _serversRetrieved = true;
+ }
+ }
+
+ return _servers;
+ }
+ }
+
+ public ReadOnlySiteCollection AdjacentSites
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ if (!_adjacentSitesRetrieved)
+ {
+ _adjacentSites.Clear();
+ GetAdjacentSites();
+ _adjacentSitesRetrieved = true;
+ }
+ }
+ return _adjacentSites;
+ }
+ }
+
+ public ReadOnlySiteLinkCollection SiteLinks
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ if (!_belongLinksRetrieved)
+ {
+ _links.Clear();
+ GetLinks();
+ _belongLinksRetrieved = true;
+ }
+ }
+ return _links;
+ }
+ }
+
+ public DirectoryServer InterSiteTopologyGenerator
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ // have not load topology generator information from the directory and user has not set it yet
+ if (_topologyGenerator == null && !_topologyTouched)
+ {
+ bool ISTGExist;
+ try
+ {
+ ISTGExist = NTDSSiteEntry.Properties.Contains("interSiteTopologyGenerator");
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (ISTGExist)
+ {
+ string serverDN = (string)PropertyManager.GetPropertyValue(context, NTDSSiteEntry, PropertyManager.InterSiteTopologyGenerator);
+ string hostname = null;
+ DirectoryEntry tmp = DirectoryEntryManager.GetDirectoryEntry(context, serverDN);
+
+ try
+ {
+ hostname = (string)PropertyManager.GetPropertyValue(context, tmp.Parent, PropertyManager.DnsHostName);
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // indicates a demoted server
+ return null;
+ }
+ }
+ if (IsADAM)
+ {
+ int port = (int)PropertyManager.GetPropertyValue(context, tmp, PropertyManager.MsDSPortLDAP);
+ string fullHostName = hostname;
+ if (port != 389)
+ {
+ fullHostName = hostname + ":" + port;
+ }
+ _topologyGenerator = new AdamInstance(Utils.GetNewDirectoryContext(fullHostName, DirectoryContextType.DirectoryServer, context), fullHostName);
+ }
+ else
+ {
+ _topologyGenerator = new DomainController(Utils.GetNewDirectoryContext(hostname, DirectoryContextType.DirectoryServer, context), hostname);
+ }
+ }
+ }
+ }
+
+ return _topologyGenerator;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (existing)
+ {
+ // for existing site, nTDSSiteSettings needs to exist
+ DirectoryEntry tmp = NTDSSiteEntry;
+ }
+
+ _topologyTouched = true;
+ _topologyGenerator = value;
+ }
+ }
+
+ public ActiveDirectorySiteOptions Options
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ try
+ {
+ if (NTDSSiteEntry.Properties.Contains("options"))
+ {
+ return (ActiveDirectorySiteOptions)NTDSSiteEntry.Properties["options"][0];
+ }
+ else
+ return ActiveDirectorySiteOptions.None;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ else
+ return _siteOptions;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ try
+ {
+ NTDSSiteEntry.Properties["options"].Value = value;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ else
+ _siteOptions = value;
+ }
+ }
+
+ public string Location
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ if (cachedEntry.Properties.Contains("location"))
+ {
+ return (string)cachedEntry.Properties["location"][0];
+ }
+ else
+ return null;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ if (value == null)
+ {
+ if (cachedEntry.Properties.Contains("location"))
+ cachedEntry.Properties["location"].Clear();
+ }
+ else
+ {
+ cachedEntry.Properties["location"].Value = value;
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public ReadOnlyDirectoryServerCollection BridgeheadServers
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!_bridgeheadServerRetrieved)
+ {
+ _bridgeheadServers = GetBridgeheadServers();
+ _bridgeheadServerRetrieved = true;
+ }
+
+ return _bridgeheadServers;
+ }
+ }
+
+ public DirectoryServerCollection PreferredSmtpBridgeheadServers
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ if (!_SMTPBridgeRetrieved)
+ {
+ _SMTPBridgeheadServers.initialized = false;
+ _SMTPBridgeheadServers.Clear();
+ GetPreferredBridgeheadServers(ActiveDirectoryTransportType.Smtp);
+ _SMTPBridgeRetrieved = true;
+ }
+ }
+
+ _SMTPBridgeheadServers.initialized = true;
+
+ return _SMTPBridgeheadServers;
+ }
+ }
+
+ public DirectoryServerCollection PreferredRpcBridgeheadServers
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ if (!_RPCBridgeRetrieved)
+ {
+ _RPCBridgeheadServers.initialized = false;
+ _RPCBridgeheadServers.Clear();
+ GetPreferredBridgeheadServers(ActiveDirectoryTransportType.Rpc);
+ _RPCBridgeRetrieved = true;
+ }
+ }
+ _RPCBridgeheadServers.initialized = true;
+
+ return _RPCBridgeheadServers;
+ }
+ }
+
+ public ActiveDirectorySchedule IntraSiteReplicationSchedule
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ ActiveDirectorySchedule schedule = null;
+
+ if (existing)
+ {
+ // if exists in the cache, return it, otherwise null is returned
+ try
+ {
+ if (NTDSSiteEntry.Properties.Contains("schedule"))
+ {
+ byte[] tmpSchedule = (byte[])NTDSSiteEntry.Properties["schedule"][0];
+ Debug.Assert(tmpSchedule != null && tmpSchedule.Length == 188);
+ schedule = new ActiveDirectorySchedule();
+ schedule.SetUnmanagedSchedule(tmpSchedule);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ else
+ {
+ if (_replicationSchedule != null)
+ {
+ // newly created site, get the schedule if already has been set by the user
+ schedule = new ActiveDirectorySchedule();
+ schedule.SetUnmanagedSchedule(_replicationSchedule);
+ }
+ }
+
+ return schedule;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ try
+ {
+ if (value == null)
+ {
+ // clear it out if existing before
+ if (NTDSSiteEntry.Properties.Contains("schedule"))
+ NTDSSiteEntry.Properties["schedule"].Clear();
+ }
+ else
+ // replace with the new value
+ NTDSSiteEntry.Properties["schedule"].Value = value.GetUnmanagedSchedule();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ else
+ {
+ // clear out the schedule
+ if (value == null)
+ _replicationSchedule = null;
+ else
+ {
+ // replace with the new value
+ _replicationSchedule = value.GetUnmanagedSchedule();
+ }
+ }
+ }
+ }
+
+ private bool IsADAM
+ {
+ get
+ {
+ if (!_checkADAM)
+ {
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ PropertyValueCollection values = null;
+ try
+ {
+ values = de.Properties["supportedCapabilities"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (values.Contains(SupportedCapability.ADAMOid))
+ _isADAMServer = true;
+ }
+
+ return _isADAMServer;
+ }
+ }
+
+ private DirectoryEntry NTDSSiteEntry
+ {
+ get
+ {
+ if (_ntdsEntry == null)
+ {
+ DirectoryEntry tmp = DirectoryEntryManager.GetDirectoryEntry(context, "CN=NTDS Site Settings," + (string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName));
+ try
+ {
+ tmp.RefreshCache();
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ string message = Res.GetString(Res.NTDSSiteSetting, _name);
+ throw new ActiveDirectoryOperationException(message, e, 0x2030);
+ }
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ _ntdsEntry = tmp;
+ }
+
+ return _ntdsEntry;
+ }
+ }
+
+ public void Save()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ // commit changes
+ cachedEntry.CommitChanges();
+
+ foreach (DictionaryEntry e in _subnets.changeList)
+ {
+ try
+ {
+ ((DirectoryEntry)e.Value).CommitChanges();
+ }
+ catch (COMException exception)
+ {
+ // there is a bug in ADSI that when targeting ADAM, permissive modify control is not used.
+ if (exception.ErrorCode != unchecked((int)0x8007200A))
+ throw ExceptionHelper.GetExceptionFromCOMException(exception);
+ }
+ }
+
+ // reset status variables
+ _subnets.changeList.Clear();
+ _subnetRetrieved = false;
+
+ // need to throw better exception for ADAM since its SMTP transport is not available
+ foreach (DictionaryEntry e in _SMTPBridgeheadServers.changeList)
+ {
+ try
+ {
+ ((DirectoryEntry)e.Value).CommitChanges();
+ }
+ catch (COMException exception)
+ {
+ // SMTP transport is not supported on ADAM
+ if (IsADAM && (exception.ErrorCode == unchecked((int)0x8007202F)))
+ throw new NotSupportedException(Res.GetString(Res.NotSupportTransportSMTP));
+
+ // there is a bug in ADSI that when targeting ADAM, permissive modify control is not used.
+ if (exception.ErrorCode != unchecked((int)0x8007200A))
+ throw ExceptionHelper.GetExceptionFromCOMException(exception);
+ }
+ }
+
+ _SMTPBridgeheadServers.changeList.Clear();
+ _SMTPBridgeRetrieved = false;
+
+ foreach (DictionaryEntry e in _RPCBridgeheadServers.changeList)
+ {
+ try
+ {
+ ((DirectoryEntry)e.Value).CommitChanges();
+ }
+ catch (COMException exception)
+ {
+ // there is a bug in ADSI that when targeting ADAM, permissive modify control is not used.
+ if (exception.ErrorCode != unchecked((int)0x8007200A))
+ throw ExceptionHelper.GetExceptionFromCOMException(exception);
+ }
+ }
+
+ _RPCBridgeheadServers.changeList.Clear();
+ _RPCBridgeRetrieved = false;
+
+ if (existing)
+ {
+ // topology generator is changed
+ if (_topologyTouched)
+ {
+ try
+ {
+ DirectoryServer server = InterSiteTopologyGenerator;
+ string ntdsaName = (server is DomainController) ? ((DomainController)server).NtdsaObjectName : ((AdamInstance)server).NtdsaObjectName;
+ NTDSSiteEntry.Properties["interSiteTopologyGenerator"].Value = ntdsaName;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ NTDSSiteEntry.CommitChanges();
+ _topologyTouched = false;
+ }
+ else
+ {
+ try
+ {
+ // create nTDSSiteSettings object
+ DirectoryEntry tmpEntry = cachedEntry.Children.Add("CN=NTDS Site Settings", "nTDSSiteSettings");
+ //set properties on the Site NTDS settings object
+ DirectoryServer replica = InterSiteTopologyGenerator;
+ if (replica != null)
+ {
+ string ntdsaName = (replica is DomainController) ? ((DomainController)replica).NtdsaObjectName : ((AdamInstance)replica).NtdsaObjectName;
+ tmpEntry.Properties["interSiteTopologyGenerator"].Value = ntdsaName;
+ }
+ tmpEntry.Properties["options"].Value = _siteOptions;
+ if (_replicationSchedule != null)
+ {
+ tmpEntry.Properties["schedule"].Value = _replicationSchedule;
+ }
+
+ tmpEntry.CommitChanges();
+ // cached the entry
+ _ntdsEntry = tmpEntry;
+
+ // create servers contain object
+ tmpEntry = cachedEntry.Children.Add("CN=Servers", "serversContainer");
+ tmpEntry.CommitChanges();
+
+ if (!IsADAM)
+ {
+ // create the licensingSiteSettings object
+ tmpEntry = cachedEntry.Children.Add("CN=Licensing Site Settings", "licensingSiteSettings");
+ tmpEntry.CommitChanges();
+ }
+ }
+ finally
+ {
+ // entry is created on the backend store successfully
+ existing = true;
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ public void Delete()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!existing)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotDelete));
+ }
+ else
+ {
+ try
+ {
+ cachedEntry.DeleteTree();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public override string ToString()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _name;
+ }
+
+ private ReadOnlyDirectoryServerCollection GetBridgeheadServers()
+ {
+ NativeComInterfaces.IAdsPathname pathCracker = (NativeComInterfaces.IAdsPathname)new NativeComInterfaces.Pathname();
+ // need to turn off the escaping for name
+ pathCracker.EscapedMode = NativeComInterfaces.ADS_ESCAPEDMODE_OFF_EX;
+
+ ReadOnlyDirectoryServerCollection collection = new ReadOnlyDirectoryServerCollection();
+ if (existing)
+ {
+ Hashtable bridgeHeadTable = new Hashtable();
+ Hashtable nonBridgHeadTable = new Hashtable();
+ Hashtable hostNameTable = new Hashtable();
+ const string ocValue = "CN=Server";
+
+ // get destination bridgehead servers
+
+ // first go to the servers container under the current site and then do a search to get the all server objects.
+ string serverContainer = "CN=Servers," + (string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName);
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, serverContainer);
+
+ try
+ {
+ // go through connection objects and find out its fromServer property.
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(|(objectCategory=server)(objectCategory=NTDSConnection))",
+ new string[] { "fromServer", "distinguishedName", "dNSHostName", "objectCategory" },
+ SearchScope.Subtree,
+ true, /* need paged search */
+ true /* need cached result as we need to go back to the first record */);
+ SearchResultCollection conResults = null;
+ try
+ {
+ conResults = adSearcher.FindAll();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ try
+ {
+ // find out whether fromServer indicates replicating from a server in another site.
+ foreach (SearchResult r in conResults)
+ {
+ string objectCategoryValue = (string)PropertyManager.GetSearchResultPropertyValue(r, PropertyManager.ObjectCategory);
+ if (Utils.Compare(objectCategoryValue, 0, ocValue.Length, ocValue, 0, ocValue.Length) == 0)
+ {
+ hostNameTable.Add((string)PropertyManager.GetSearchResultPropertyValue(r, PropertyManager.DistinguishedName), (string)PropertyManager.GetSearchResultPropertyValue(r, PropertyManager.DnsHostName));
+ }
+ }
+
+ foreach (SearchResult r in conResults)
+ {
+ string objectCategoryValue = (string)PropertyManager.GetSearchResultPropertyValue(r, PropertyManager.ObjectCategory);
+ if (Utils.Compare(objectCategoryValue, 0, ocValue.Length, ocValue, 0, ocValue.Length) != 0)
+ {
+ string fromServer = (string)PropertyManager.GetSearchResultPropertyValue(r, PropertyManager.FromServer);
+
+ // escaping manipulation
+ string fromSite = Utils.GetPartialDN(fromServer, 3);
+ pathCracker.Set(fromSite, NativeComInterfaces.ADS_SETTYPE_DN);
+ fromSite = pathCracker.Retrieve(NativeComInterfaces.ADS_FORMAT_LEAF);
+ Debug.Assert(fromSite != null && Utils.Compare(fromSite, 0, 3, "CN=", 0, 3) == 0);
+ fromSite = fromSite.Substring(3);
+
+ string serverObjectName = Utils.GetPartialDN((string)PropertyManager.GetSearchResultPropertyValue(r, PropertyManager.DistinguishedName), 2);
+ // don't know whether it is a bridgehead server yet.
+ if (!bridgeHeadTable.Contains(serverObjectName))
+ {
+ string hostName = (string)hostNameTable[serverObjectName];
+ // add if not yet done
+ if (!nonBridgHeadTable.Contains(serverObjectName))
+ nonBridgHeadTable.Add(serverObjectName, hostName);
+
+ // check whether from different site
+ if (Utils.Compare((string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.Cn), fromSite) != 0)
+ {
+ // the server is a bridgehead server
+ bridgeHeadTable.Add(serverObjectName, hostName);
+ nonBridgHeadTable.Remove(serverObjectName);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ conResults.Dispose();
+ }
+ }
+ finally
+ {
+ de.Dispose();
+ }
+
+ // get source bridgehead server
+ if (nonBridgHeadTable.Count != 0)
+ {
+ // go to sites container to get all the connecdtion object that replicates from servers in the current sites that have
+ // not been determined whether it is a bridgehead server or not.
+ DirectoryEntry serverEntry = DirectoryEntryManager.GetDirectoryEntry(context, _siteDN);
+ // constructing the filter
+ StringBuilder str = new StringBuilder(100);
+ if (nonBridgHeadTable.Count > 1)
+ str.Append("(|");
+ foreach (DictionaryEntry val in nonBridgHeadTable)
+ {
+ str.Append("(fromServer=");
+ str.Append("CN=NTDS Settings,");
+ str.Append(Utils.GetEscapedFilterValue((string)val.Key));
+ str.Append(")");
+ }
+ if (nonBridgHeadTable.Count > 1)
+ str.Append(")");
+ ADSearcher adSearcher = new ADSearcher(serverEntry,
+ "(&(objectClass=nTDSConnection)(objectCategory=NTDSConnection)" + str.ToString() + ")",
+ new string[] { "fromServer", "distinguishedName" },
+ SearchScope.Subtree);
+ SearchResultCollection conResults = null;
+ try
+ {
+ conResults = adSearcher.FindAll();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ try
+ {
+ foreach (SearchResult r in conResults)
+ {
+ string fromServer = (string)PropertyManager.GetSearchResultPropertyValue(r, PropertyManager.FromServer);
+ string serverObject = fromServer.Substring(17);
+
+ if (nonBridgHeadTable.Contains(serverObject))
+ {
+ string otherSite = Utils.GetPartialDN((string)PropertyManager.GetSearchResultPropertyValue(r, PropertyManager.DistinguishedName), 4);
+ // escaping manipulation
+ pathCracker.Set(otherSite, NativeComInterfaces.ADS_SETTYPE_DN);
+ otherSite = pathCracker.Retrieve(NativeComInterfaces.ADS_FORMAT_LEAF);
+ Debug.Assert(otherSite != null && Utils.Compare(otherSite, 0, 3, "CN=", 0, 3) == 0);
+ otherSite = otherSite.Substring(3);
+
+ // check whether from different sites
+ if (Utils.Compare(otherSite, (string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.Cn)) != 0)
+ {
+ string val = (string)nonBridgHeadTable[serverObject];
+ nonBridgHeadTable.Remove(serverObject);
+ bridgeHeadTable.Add(serverObject, val);
+ }
+ }
+ }
+ }
+ finally
+ {
+ conResults.Dispose();
+ serverEntry.Dispose();
+ }
+ }
+
+ DirectoryEntry ADAMEntry = null;
+ foreach (DictionaryEntry e in bridgeHeadTable)
+ {
+ DirectoryServer replica = null;
+ string host = (string)e.Value;
+ // construct directoryreplica
+ if (IsADAM)
+ {
+ ADAMEntry = DirectoryEntryManager.GetDirectoryEntry(context, "CN=NTDS Settings," + e.Key);
+ int port = (int)PropertyManager.GetPropertyValue(context, ADAMEntry, PropertyManager.MsDSPortLDAP);
+ string fullhost = host;
+ if (port != 389)
+ {
+ fullhost = host + ":" + port;
+ }
+ replica = new AdamInstance(Utils.GetNewDirectoryContext(fullhost, DirectoryContextType.DirectoryServer, context), fullhost);
+ }
+ else
+ {
+ replica = new DomainController(Utils.GetNewDirectoryContext(host, DirectoryContextType.DirectoryServer, context), host);
+ }
+
+ collection.Add(replica);
+ }
+ }
+
+ return collection;
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!existing)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotGetObject));
+ }
+ else
+ {
+ return DirectoryEntryManager.GetDirectoryEntryInternal(context, cachedEntry.Path);
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // free other state (managed objects)
+ if (cachedEntry != null)
+ cachedEntry.Dispose();
+
+ if (_ntdsEntry != null)
+ _ntdsEntry.Dispose();
+ }
+
+ // free your own state (unmanaged objects)
+
+ _disposed = true;
+ }
+
+ private static void ValidateArgument(DirectoryContext context, string siteName)
+ {
+ // basic validation first
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // if target is not specified, then we determin the target from the logon credential, so if it is a local user context, it should fail
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ // more validation for the context, if the target is not null, then it should be either forest name or server name
+ if (context.Name != null)
+ {
+ if (!(context.isRootDomain() || context.isServer() || context.isADAMConfigSet()))
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+
+ if (siteName == null)
+ throw new ArgumentNullException("siteName");
+
+ if (siteName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ private void GetSubnets()
+ {
+ // performs a search to find out the subnets that belong to this site
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ string subnetContainer = "CN=Subnets,CN=Sites," + config;
+ de = DirectoryEntryManager.GetDirectoryEntry(context, subnetContainer);
+
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=subnet)(objectCategory=subnet)(siteObject=" + Utils.GetEscapedFilterValue((string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName)) + "))",
+ new string[] { "cn", "location" },
+ SearchScope.OneLevel
+ );
+ SearchResultCollection results = null;
+
+ try
+ {
+ results = adSearcher.FindAll();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ try
+ {
+ string subnetName = null;
+ foreach (SearchResult result in results)
+ {
+ subnetName = (string)PropertyManager.GetSearchResultPropertyValue(result, PropertyManager.Cn);
+ ActiveDirectorySubnet subnet = new ActiveDirectorySubnet(context, subnetName, null, true);
+ // set the cached entry
+ subnet.cachedEntry = result.GetDirectoryEntry();
+ // set the site info
+ subnet.Site = this;
+
+ _subnets.Add(subnet);
+ }
+ }
+ finally
+ {
+ results.Dispose();
+ de.Dispose();
+ }
+ }
+
+ private void GetAdjacentSites()
+ {
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)de.Properties["configurationNamingContext"][0];
+ string transportContainer = "CN=Inter-Site Transports,CN=Sites," + config;
+ de = DirectoryEntryManager.GetDirectoryEntry(context, transportContainer);
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=siteLink)(objectCategory=SiteLink)(siteList=" + Utils.GetEscapedFilterValue((string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName)) + "))",
+ new string[] { "cn", "distinguishedName" },
+ SearchScope.Subtree);
+ SearchResultCollection results = null;
+
+ try
+ {
+ results = adSearcher.FindAll();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ try
+ {
+ ActiveDirectorySiteLink link = null;
+
+ foreach (SearchResult result in results)
+ {
+ string dn = (string)PropertyManager.GetSearchResultPropertyValue(result, PropertyManager.DistinguishedName);
+ string linkName = (string)PropertyManager.GetSearchResultPropertyValue(result, PropertyManager.Cn);
+ string transportName = (string)Utils.GetDNComponents(dn)[1].Value;
+ ActiveDirectoryTransportType transportType;
+ if (String.Compare(transportName, "IP", StringComparison.OrdinalIgnoreCase) == 0)
+ transportType = ActiveDirectoryTransportType.Rpc;
+ else if (String.Compare(transportName, "SMTP", StringComparison.OrdinalIgnoreCase) == 0)
+ transportType = ActiveDirectoryTransportType.Smtp;
+ else
+ {
+ // should not happen
+ string message = Res.GetString(Res.UnknownTransport, transportName);
+ throw new ActiveDirectoryOperationException(message);
+ }
+
+ try
+ {
+ link = new ActiveDirectorySiteLink(context, linkName, transportType, true, result.GetDirectoryEntry());
+ foreach (ActiveDirectorySite tmpSite in link.Sites)
+ {
+ // don't add itself
+ if (Utils.Compare(tmpSite.Name, Name) == 0)
+ continue;
+
+ if (!_adjacentSites.Contains(tmpSite))
+ _adjacentSites.Add(tmpSite);
+ }
+ }
+ finally
+ {
+ link.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ results.Dispose();
+ de.Dispose();
+ }
+ }
+
+ private void GetLinks()
+ {
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ string transportContainer = "CN=Inter-Site Transports,CN=Sites," + config;
+ de = DirectoryEntryManager.GetDirectoryEntry(context, transportContainer);
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=siteLink)(objectCategory=SiteLink)(siteList=" + Utils.GetEscapedFilterValue((string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName)) + "))",
+ new string[] { "cn", "distinguishedName" },
+ SearchScope.Subtree);
+ SearchResultCollection results = null;
+
+ try
+ {
+ results = adSearcher.FindAll();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ try
+ {
+ foreach (SearchResult result in results)
+ {
+ // construct the sitelinks at the same time
+ DirectoryEntry connectionEntry = result.GetDirectoryEntry();
+ string cn = (string)PropertyManager.GetSearchResultPropertyValue(result, PropertyManager.Cn);
+ string transport = Utils.GetDNComponents((string)PropertyManager.GetSearchResultPropertyValue(result, PropertyManager.DistinguishedName))[1].Value;
+ ActiveDirectorySiteLink link = null;
+ if (String.Compare(transport, "IP", StringComparison.OrdinalIgnoreCase) == 0)
+ link = new ActiveDirectorySiteLink(context, cn, ActiveDirectoryTransportType.Rpc, true, connectionEntry);
+ else if (String.Compare(transport, "SMTP", StringComparison.OrdinalIgnoreCase) == 0)
+ link = new ActiveDirectorySiteLink(context, cn, ActiveDirectoryTransportType.Smtp, true, connectionEntry);
+ else
+ {
+ // should not happen
+ string message = Res.GetString(Res.UnknownTransport, transport);
+ throw new ActiveDirectoryOperationException(message);
+ }
+
+ _links.Add(link);
+ }
+ }
+ finally
+ {
+ results.Dispose();
+ de.Dispose();
+ }
+ }
+
+ private void GetDomains()
+ {
+ // for ADAM, there is no concept of domain, we just return empty collection which is good enough
+ if (!IsADAM)
+ {
+ string serverName = cachedEntry.Options.GetCurrentServerName();
+ DomainController dc = DomainController.GetDomainController(Utils.GetNewDirectoryContext(serverName, DirectoryContextType.DirectoryServer, context));
+ IntPtr handle = dc.Handle;
+
+ Debug.Assert(handle != (IntPtr)0);
+
+ IntPtr info = (IntPtr)0;
+ // call DsReplicaSyncAllW
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsListDomainsInSiteW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsListDomainsInSiteW dsListDomainsInSiteW = (UnsafeNativeMethods.DsListDomainsInSiteW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsListDomainsInSiteW));
+
+ int result = dsListDomainsInSiteW(handle, (string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName), ref info);
+ if (result != 0)
+ throw ExceptionHelper.GetExceptionFromErrorCode(result, serverName);
+
+ try
+ {
+ DS_NAME_RESULT names = new DS_NAME_RESULT();
+ Marshal.PtrToStructure(info, names);
+ int count = names.cItems;
+ IntPtr val = names.rItems;
+ if (count > 0)
+ {
+ Debug.Assert(val != (IntPtr)0);
+ int status = Marshal.ReadInt32(val);
+ IntPtr tmpPtr = (IntPtr)0;
+ for (int i = 0; i < count; i++)
+ {
+ tmpPtr = IntPtr.Add(val, Marshal.SizeOf(typeof(DS_NAME_RESULT_ITEM)) * i);
+ DS_NAME_RESULT_ITEM nameResult = new DS_NAME_RESULT_ITEM();
+ Marshal.PtrToStructure(tmpPtr, nameResult);
+ if (nameResult.status == DS_NAME_ERROR.DS_NAME_NO_ERROR || nameResult.status == DS_NAME_ERROR.DS_NAME_ERROR_DOMAIN_ONLY)
+ {
+ string domainName = Marshal.PtrToStringUni(nameResult.pName);
+ if (domainName != null && domainName.Length > 0)
+ {
+ string d = Utils.GetDnsNameFromDN(domainName);
+ Domain domain = new Domain(Utils.GetNewDirectoryContext(d, DirectoryContextType.Domain, context), d);
+ _domains.Add(domain);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ // call DsFreeNameResultW
+ functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsFreeNameResultW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsFreeNameResultW dsFreeNameResultW = (UnsafeNativeMethods.DsFreeNameResultW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsFreeNameResultW));
+
+ dsFreeNameResultW(info);
+ }
+ }
+ }
+
+ private void GetServers()
+ {
+ ADSearcher adSearcher = new ADSearcher(cachedEntry,
+ "(&(objectClass=server)(objectCategory=server))",
+ new string[] { "dNSHostName" },
+ SearchScope.Subtree);
+ SearchResultCollection results = null;
+ try
+ {
+ results = adSearcher.FindAll();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ try
+ {
+ foreach (SearchResult result in results)
+ {
+ string hostName = (string)PropertyManager.GetSearchResultPropertyValue(result, PropertyManager.DnsHostName);
+ DirectoryEntry de = result.GetDirectoryEntry();
+ DirectoryEntry child = null;
+ DirectoryServer replica = null;
+ // make sure that the server is not demoted
+ try
+ {
+ child = de.Children.Find("CN=NTDS Settings", "nTDSDSA");
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ continue;
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ if (IsADAM)
+ {
+ int port = (int)PropertyManager.GetPropertyValue(context, child, PropertyManager.MsDSPortLDAP);
+ string fullHostName = hostName;
+ if (port != 389)
+ {
+ fullHostName = hostName + ":" + port;
+ }
+ replica = new AdamInstance(Utils.GetNewDirectoryContext(fullHostName, DirectoryContextType.DirectoryServer, context), fullHostName);
+ }
+ else
+ replica = new DomainController(Utils.GetNewDirectoryContext(hostName, DirectoryContextType.DirectoryServer, context), hostName);
+
+ _servers.Add(replica);
+ }
+ }
+ finally
+ {
+ results.Dispose();
+ }
+ }
+
+ private void GetPreferredBridgeheadServers(ActiveDirectoryTransportType transport)
+ {
+ string serverContainerDN = "CN=Servers," + PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName);
+ string transportDN = null;
+ if (transport == ActiveDirectoryTransportType.Smtp)
+ transportDN = "CN=SMTP,CN=Inter-Site Transports," + _siteDN;
+ else
+ transportDN = "CN=IP,CN=Inter-Site Transports," + _siteDN;
+
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, serverContainerDN);
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=server)(objectCategory=Server)(bridgeheadTransportList=" + Utils.GetEscapedFilterValue(transportDN) + "))",
+ new string[] { "dNSHostName", "distinguishedName" },
+ SearchScope.OneLevel);
+ SearchResultCollection results = null;
+
+ try
+ {
+ results = adSearcher.FindAll();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ try
+ {
+ DirectoryEntry ADAMEntry = null;
+ foreach (SearchResult result in results)
+ {
+ string hostName = (string)PropertyManager.GetSearchResultPropertyValue(result, PropertyManager.DnsHostName);
+ DirectoryEntry resultEntry = result.GetDirectoryEntry();
+ DirectoryServer replica = null;
+
+ try
+ {
+ ADAMEntry = resultEntry.Children.Find("CN=NTDS Settings", "nTDSDSA");
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (IsADAM)
+ {
+ int port = (int)PropertyManager.GetPropertyValue(context, ADAMEntry, PropertyManager.MsDSPortLDAP);
+ string fullHostName = hostName;
+ if (port != 389)
+ {
+ fullHostName = hostName + ":" + port;
+ }
+ replica = new AdamInstance(Utils.GetNewDirectoryContext(fullHostName, DirectoryContextType.DirectoryServer, context), fullHostName);
+ }
+ else
+ replica = new DomainController(Utils.GetNewDirectoryContext(hostName, DirectoryContextType.DirectoryServer, context), hostName);
+
+ if (transport == ActiveDirectoryTransportType.Smtp)
+ _SMTPBridgeheadServers.Add(replica);
+ else
+ _RPCBridgeheadServers.Add(replica);
+ }
+ }
+ finally
+ {
+ de.Dispose();
+ results.Dispose();
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteCollection.cs
new file mode 100644
index 0000000000..9c2839a7c8
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteCollection.cs
@@ -0,0 +1,247 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Globalization;
+
+ public class ActiveDirectorySiteCollection : CollectionBase
+ {
+ internal DirectoryEntry de = null;
+ internal bool initialized = false;
+ internal DirectoryContext context = null;
+
+ internal ActiveDirectorySiteCollection() { }
+
+ internal ActiveDirectorySiteCollection(ArrayList sites)
+ {
+ for (int i = 0; i < sites.Count; i++)
+ Add((ActiveDirectorySite)sites[i]);
+ }
+
+ public ActiveDirectorySite this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySite)InnerList[index];
+ }
+ set
+ {
+ ActiveDirectorySite site = (ActiveDirectorySite)value;
+
+ if (site == null)
+ throw new ArgumentNullException("value");
+
+ if (!site.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteNotCommitted, site.Name));
+
+ if (!Contains(site))
+ List[index] = site;
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, site), "value");
+ }
+ }
+
+ public int Add(ActiveDirectorySite site)
+ {
+ if (site == null)
+ throw new ArgumentNullException("site");
+
+ if (!site.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteNotCommitted, site.Name));
+
+ if (!Contains(site))
+ return List.Add(site);
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, site), "site");
+ }
+
+ public void AddRange(ActiveDirectorySite[] sites)
+ {
+ if (sites == null)
+ throw new ArgumentNullException("sites");
+
+ for (int i = 0; ((i) < (sites.Length)); i = ((i) + (1)))
+ this.Add(sites[i]);
+ }
+
+ public void AddRange(ActiveDirectorySiteCollection sites)
+ {
+ if (sites == null)
+ throw new ArgumentNullException("sites");
+
+ int count = sites.Count;
+ for (int i = 0; i < count; i++)
+ this.Add(sites[i]);
+ }
+
+ public bool Contains(ActiveDirectorySite site)
+ {
+ if (site == null)
+ throw new ArgumentNullException("site");
+
+ if (!site.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteNotCommitted, site.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(site.context, site.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySite tmp = (ActiveDirectorySite)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void CopyTo(ActiveDirectorySite[] array, int index)
+ {
+ List.CopyTo(array, index);
+ }
+
+ public int IndexOf(ActiveDirectorySite site)
+ {
+ if (site == null)
+ throw new ArgumentNullException("site");
+
+ if (!site.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteNotCommitted, site.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(site.context, site.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySite tmp = (ActiveDirectorySite)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void Insert(int index, ActiveDirectorySite site)
+ {
+ if (site == null)
+ throw new ArgumentNullException("site");
+
+ if (!site.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteNotCommitted, site.Name));
+
+ if (!Contains(site))
+ List.Insert(index, site);
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, site), "site");
+ }
+
+ public void Remove(ActiveDirectorySite site)
+ {
+ if (site == null)
+ throw new ArgumentNullException("site");
+
+ if (!site.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteNotCommitted, site.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(site.context, site.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySite tmp = (ActiveDirectorySite)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ List.Remove(tmp);
+ return;
+ }
+ }
+
+ // something that does not exist in the collectio
+ throw new ArgumentException(Res.GetString(Res.NotFoundInCollection, site), "site");
+ }
+
+ protected override void OnClearComplete()
+ {
+ // if the property exists, clear it out
+ if (initialized)
+ {
+ try
+ {
+ if (de.Properties.Contains("siteList"))
+ de.Properties["siteList"].Clear();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ protected override void OnInsertComplete(int index, object value)
+ {
+ if (initialized)
+ {
+ ActiveDirectorySite site = (ActiveDirectorySite)value;
+ string dn = (string)PropertyManager.GetPropertyValue(site.context, site.cachedEntry, PropertyManager.DistinguishedName);
+ try
+ {
+ de.Properties["siteList"].Add(dn);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ protected override void OnRemoveComplete(int index, object value)
+ {
+ ActiveDirectorySite site = (ActiveDirectorySite)value;
+ string dn = (string)PropertyManager.GetPropertyValue(site.context, site.cachedEntry, PropertyManager.DistinguishedName);
+ try
+ {
+ de.Properties["siteList"].Remove(dn);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ protected override void OnSetComplete(int index, object oldValue, object newValue)
+ {
+ ActiveDirectorySite newsite = (ActiveDirectorySite)newValue;
+ string newdn = (string)PropertyManager.GetPropertyValue(newsite.context, newsite.cachedEntry, PropertyManager.DistinguishedName);
+ try
+ {
+ de.Properties["siteList"][index] = newdn;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ if (!(value is ActiveDirectorySite))
+ throw new ArgumentException("value");
+
+ if (!((ActiveDirectorySite)value).existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteNotCommitted, ((ActiveDirectorySite)value).Name));
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs
new file mode 100644
index 0000000000..c88e8eb25a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs
@@ -0,0 +1,733 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ActiveDirectorySiteLink : IDisposable
+ {
+ internal DirectoryContext context = null;
+ private string _name = null;
+ private ActiveDirectoryTransportType _transport = ActiveDirectoryTransportType.Rpc;
+ private bool _disposed = false;
+
+ internal bool existing = false;
+ internal DirectoryEntry cachedEntry = null;
+ private const int systemDefaultCost = 0;
+ private TimeSpan _systemDefaultInterval = new TimeSpan(0, 15, 0);
+ private const int appDefaultCost = 100;
+ private const int appDefaultInterval = 180;
+ private ActiveDirectorySiteCollection _sites = new ActiveDirectorySiteCollection();
+ private bool _siteRetrieved = false;
+
+ public ActiveDirectorySiteLink(DirectoryContext context, string siteLinkName) : this(context, siteLinkName, ActiveDirectoryTransportType.Rpc, null)
+ {
+ }
+
+ public ActiveDirectorySiteLink(DirectoryContext context, string siteLinkName, ActiveDirectoryTransportType transport) : this(context, siteLinkName, transport, null)
+ {
+ }
+
+ public ActiveDirectorySiteLink(DirectoryContext context, string siteLinkName, ActiveDirectoryTransportType transport, ActiveDirectorySchedule schedule)
+ {
+ ValidateArgument(context, siteLinkName, transport);
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ this.context = context;
+ _name = siteLinkName;
+ _transport = transport;
+
+ // bind to the rootdse to get the configurationnamingcontext
+ DirectoryEntry de;
+
+ try
+ {
+ de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+
+ string parentDN = null;
+ if (transport == ActiveDirectoryTransportType.Rpc)
+ parentDN = "CN=IP,CN=Inter-Site Transports,CN=Sites," + config;
+ else
+ parentDN = "CN=SMTP,CN=Inter-Site Transports,CN=Sites," + config;
+
+ de = DirectoryEntryManager.GetDirectoryEntry(context, parentDN);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ try
+ {
+ string rdn = "cn=" + _name;
+ rdn = Utils.GetEscapedPath(rdn);
+ cachedEntry = de.Children.Add(rdn, "siteLink");
+ cachedEntry.Properties["cost"].Value = appDefaultCost;
+ cachedEntry.Properties["replInterval"].Value = appDefaultInterval;
+ if (schedule != null)
+ cachedEntry.Properties["schedule"].Value = schedule.GetUnmanagedSchedule();
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // if it is ADAM and transport type is SMTP, throw NotSupportedException.
+ DirectoryEntry tmpDE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ if (Utils.CheckCapability(tmpDE, Capability.ActiveDirectoryApplicationMode) && transport == ActiveDirectoryTransportType.Smtp)
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportTransportSMTP));
+ }
+ }
+
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ de.Dispose();
+ }
+ }
+
+ internal ActiveDirectorySiteLink(DirectoryContext context, string siteLinkName, ActiveDirectoryTransportType transport, bool existing, DirectoryEntry entry)
+ {
+ this.context = context;
+ _name = siteLinkName;
+ _transport = transport;
+ this.existing = existing;
+ this.cachedEntry = entry;
+ }
+
+ public static ActiveDirectorySiteLink FindByName(DirectoryContext context, string siteLinkName)
+ {
+ return FindByName(context, siteLinkName, ActiveDirectoryTransportType.Rpc);
+ }
+
+ public static ActiveDirectorySiteLink FindByName(DirectoryContext context, string siteLinkName, ActiveDirectoryTransportType transport)
+ {
+ ValidateArgument(context, siteLinkName, transport);
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // bind to the rootdse to get the configurationnamingcontext
+ DirectoryEntry de;
+
+ try
+ {
+ de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ string containerDN = "CN=Inter-Site Transports,CN=Sites," + config;
+ if (transport == ActiveDirectoryTransportType.Rpc)
+ containerDN = "CN=IP," + containerDN;
+ else
+ containerDN = "CN=SMTP," + containerDN;
+ de = DirectoryEntryManager.GetDirectoryEntry(context, containerDN);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ try
+ {
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=siteLink)(objectCategory=SiteLink)(name=" + Utils.GetEscapedFilterValue(siteLinkName) + "))",
+ new string[] { "distinguishedName" },
+ SearchScope.OneLevel,
+ false, /* don't need paged search */
+ false /* don't need to cache result */
+ );
+ SearchResult srchResult = adSearcher.FindOne();
+ if (srchResult == null)
+ {
+ // no such sitelink object
+ Exception e = new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySiteLink), siteLinkName);
+ throw e;
+ }
+ else
+ {
+ DirectoryEntry connectionEntry = srchResult.GetDirectoryEntry();
+ // it is an existing site object
+ ActiveDirectorySiteLink link = new ActiveDirectorySiteLink(context, siteLinkName, transport, true, connectionEntry);
+ return link;
+ }
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // if it is ADAM and transport type is SMTP, throw NotSupportedException.
+ DirectoryEntry tmpDE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ if (Utils.CheckCapability(tmpDE, Capability.ActiveDirectoryApplicationMode) && transport == ActiveDirectoryTransportType.Smtp)
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportTransportSMTP));
+ }
+ else
+ {
+ // object is not found since we cannot even find the container in which to search
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySiteLink), siteLinkName);
+ }
+ }
+
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ de.Dispose();
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _name;
+ }
+ }
+
+ public ActiveDirectoryTransportType TransportType
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _transport;
+ }
+ }
+
+ public ActiveDirectorySiteCollection Sites
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (existing)
+ {
+ // if asked the first time, we need to properly construct the site collection
+ if (!_siteRetrieved)
+ {
+ _sites.initialized = false;
+ _sites.Clear();
+ GetSites();
+ _siteRetrieved = true;
+ }
+ }
+ _sites.initialized = true;
+ _sites.de = cachedEntry;
+ _sites.context = context;
+ return _sites;
+ }
+ }
+
+ public int Cost
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ if (cachedEntry.Properties.Contains("cost"))
+ return (int)cachedEntry.Properties["cost"][0];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ // property is not set in the directory, we need to return the system default value
+ return systemDefaultCost;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (value < 0)
+ throw new ArgumentException("value");
+
+ try
+ {
+ cachedEntry.Properties["cost"].Value = value;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public TimeSpan ReplicationInterval
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ if (cachedEntry.Properties.Contains("replInterval"))
+ {
+ int tmpValue = (int)cachedEntry.Properties["replInterval"][0];
+ return new TimeSpan(0, tmpValue, 0);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ return _systemDefaultInterval;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (value < TimeSpan.Zero)
+ throw new ArgumentException(Res.GetString(Res.NoNegativeTime), "value");
+
+ double tmpVal = value.TotalMinutes;
+ if (tmpVal > Int32.MaxValue)
+ throw new ArgumentException(Res.GetString(Res.ReplicationIntervalExceedMax), "value");
+
+ int totalMinutes = (int)tmpVal;
+ if (totalMinutes < tmpVal)
+ throw new ArgumentException(Res.GetString(Res.ReplicationIntervalInMinutes), "value");
+
+ try
+ {
+ cachedEntry.Properties["replInterval"].Value = totalMinutes;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public bool ReciprocalReplicationEnabled
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int options = 0;
+ PropertyValueCollection propValue = null;
+ try
+ {
+ propValue = cachedEntry.Properties["options"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (propValue.Count != 0)
+ {
+ options = (int)propValue[0];
+ }
+
+ //NTDSSITELINK_OPT_TWOWAY_SYNC ( 1 << 1 ) force sync in opposite direction at end of sync
+ if ((options & 0x2) == 0)
+ return false;
+ else
+ return true;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int options = 0;
+ PropertyValueCollection propValue = null;
+
+ try
+ {
+ propValue = cachedEntry.Properties["options"];
+
+ if (propValue.Count != 0)
+ {
+ options = (int)propValue[0];
+ }
+
+ //NTDSSITELINK_OPT_TWOWAY_SYNC ( 1 << 1 ) force sync in opposite direction at end of sync
+ if (value == true)
+ {
+ options |= 0x2;
+ }
+ else
+ {
+ options &= (~(0x2));
+ }
+ cachedEntry.Properties["options"].Value = options;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public bool NotificationEnabled
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int options = 0;
+ PropertyValueCollection propValue = null;
+ try
+ {
+ propValue = cachedEntry.Properties["options"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (propValue.Count != 0)
+ {
+ options = (int)propValue[0];
+ }
+
+ // NTDSSITELINK_OPT_USE_NOTIFY ( 1 << 0 ) Use notification on this link
+ if ((options & 0x1) == 0)
+ return false;
+ else
+ return true;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int options = 0;
+ PropertyValueCollection propValue = null;
+
+ try
+ {
+ propValue = cachedEntry.Properties["options"];
+ if (propValue.Count != 0)
+ {
+ options = (int)propValue[0];
+ }
+
+ // NTDSSITELINK_OPT_USE_NOTIFY ( 1 << 0 ) Use notification on this link
+ if (value)
+ {
+ options |= 0x1;
+ }
+ else
+ {
+ options &= (~(0x1));
+ }
+
+ cachedEntry.Properties["options"].Value = options;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public bool DataCompressionEnabled
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int options = 0;
+ PropertyValueCollection propValue = null;
+
+ try
+ {
+ propValue = cachedEntry.Properties["options"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (propValue.Count != 0)
+ {
+ options = (int)propValue[0];
+ }
+
+ //NTDSSITELINK_OPT_DISABLE_COMPRESSION ( 1 << 2 )
+ // 0 - Compression of replication data across this site link enabled
+ // 1 - Compression of replication data across this site link disabled
+ if ((options & 0x4) == 0)
+ return true;
+ else
+ return false;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ int options = 0;
+ PropertyValueCollection propValue = null;
+
+ try
+ {
+ propValue = cachedEntry.Properties["options"];
+ if (propValue.Count != 0)
+ {
+ options = (int)propValue[0];
+ }
+
+ //NTDSSITELINK_OPT_DISABLE_COMPRESSION ( 1 << 2 )
+ // 0 - Compression of replication data across this site link enabled
+ // 1 - Compression of replication data across this site link disabled
+ if (value == false)
+ {
+ options |= 0x4;
+ }
+ else
+ {
+ options &= (~(0x4));
+ }
+ cachedEntry.Properties["options"].Value = options;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public ActiveDirectorySchedule InterSiteReplicationSchedule
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ ActiveDirectorySchedule schedule = null;
+ try
+ {
+ if (cachedEntry.Properties.Contains("schedule"))
+ {
+ byte[] tmpSchedule = (byte[])cachedEntry.Properties["schedule"][0];
+ Debug.Assert(tmpSchedule != null && tmpSchedule.Length == 188);
+ schedule = new ActiveDirectorySchedule();
+ schedule.SetUnmanagedSchedule(tmpSchedule);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ return schedule;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ if (value == null)
+ {
+ if (cachedEntry.Properties.Contains("schedule"))
+ cachedEntry.Properties["schedule"].Clear();
+ }
+ else
+ {
+ cachedEntry.Properties["schedule"].Value = value.GetUnmanagedSchedule();
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public void Save()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ cachedEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (existing)
+ {
+ _siteRetrieved = false;
+ }
+ else
+ {
+ existing = true;
+ }
+ }
+
+ public void Delete()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!existing)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotDelete));
+ }
+ else
+ {
+ try
+ {
+ cachedEntry.Parent.Children.Remove(cachedEntry);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public override string ToString()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _name;
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!existing)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotGetObject));
+ }
+ else
+ {
+ return DirectoryEntryManager.GetDirectoryEntryInternal(context, cachedEntry.Path);
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // free other state (managed objects)
+ if (cachedEntry != null)
+ cachedEntry.Dispose();
+ }
+
+ // free your own state (unmanaged objects)
+
+ _disposed = true;
+ }
+
+ private static void ValidateArgument(DirectoryContext context, string siteLinkName, ActiveDirectoryTransportType transport)
+ {
+ // basic validation first
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // if target is not specified, then we determin the target from the logon credential, so if it is a local user context, it should fail
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ // more validation for the context, if the target is not null, then it should be either forest name or server name
+ if (context.Name != null)
+ {
+ if (!(context.isRootDomain() || context.isServer() || context.isADAMConfigSet()))
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+
+ if (siteLinkName == null)
+ throw new ArgumentNullException("siteLinkName");
+
+ if (siteLinkName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteLinkName");
+
+ if (transport < ActiveDirectoryTransportType.Rpc || transport > ActiveDirectoryTransportType.Smtp)
+ throw new InvalidEnumArgumentException("value", (int)transport, typeof(ActiveDirectoryTransportType));
+ }
+
+ private void GetSites()
+ {
+ NativeComInterfaces.IAdsPathname pathCracker = null;
+ pathCracker = (NativeComInterfaces.IAdsPathname)new NativeComInterfaces.Pathname();
+ ArrayList propertyList = new ArrayList();
+ // need to turn off the escaping for name
+ pathCracker.EscapedMode = NativeComInterfaces.ADS_ESCAPEDMODE_OFF_EX;
+ string propertyName = "siteList";
+
+ propertyList.Add(propertyName);
+ Hashtable values = Utils.GetValuesWithRangeRetrieval(cachedEntry, "(objectClass=*)", propertyList, SearchScope.Base);
+ ArrayList siteLists = (ArrayList)values[propertyName.ToLower(CultureInfo.InvariantCulture)];
+
+ // somehow no site list
+ if (siteLists == null)
+ return;
+
+ for (int i = 0; i < siteLists.Count; i++)
+ {
+ string dn = (string)siteLists[i];
+
+ // escaping manipulation
+ pathCracker.Set(dn, NativeComInterfaces.ADS_SETTYPE_DN);
+ string rdn = pathCracker.Retrieve(NativeComInterfaces.ADS_FORMAT_LEAF);
+ Debug.Assert(rdn != null && Utils.Compare(rdn, 0, 3, "CN=", 0, 3) == 0);
+ rdn = rdn.Substring(3);
+ ActiveDirectorySite site = new ActiveDirectorySite(context, rdn, true);
+
+ // add to the collection
+ _sites.Add(site);
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkBridge.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkBridge.cs
new file mode 100644
index 0000000000..ff6e7a2b18
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkBridge.cs
@@ -0,0 +1,389 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ActiveDirectorySiteLinkBridge : IDisposable
+ {
+ internal DirectoryContext context = null;
+ private string _name = null;
+ private ActiveDirectoryTransportType _transport = ActiveDirectoryTransportType.Rpc;
+ private bool _disposed = false;
+
+ private bool _existing = false;
+ internal DirectoryEntry cachedEntry = null;
+ private ActiveDirectorySiteLinkCollection _links = new ActiveDirectorySiteLinkCollection();
+ private bool _linksRetrieved = false;
+
+ public ActiveDirectorySiteLinkBridge(DirectoryContext context, string bridgeName) : this(context, bridgeName, ActiveDirectoryTransportType.Rpc)
+ {
+ }
+
+ public ActiveDirectorySiteLinkBridge(DirectoryContext context, string bridgeName, ActiveDirectoryTransportType transport)
+ {
+ ValidateArgument(context, bridgeName, transport);
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ this.context = context;
+ _name = bridgeName;
+ _transport = transport;
+
+ // bind to the rootdse to get the configurationnamingcontext
+ DirectoryEntry de;
+
+ try
+ {
+ de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ string parentDN = null;
+ if (transport == ActiveDirectoryTransportType.Rpc)
+ parentDN = "CN=IP,CN=Inter-Site Transports,CN=Sites," + config;
+ else
+ parentDN = "CN=SMTP,CN=Inter-Site Transports,CN=Sites," + config;
+
+ de = DirectoryEntryManager.GetDirectoryEntry(context, parentDN);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ try
+ {
+ string rdn = "cn=" + _name;
+ rdn = Utils.GetEscapedPath(rdn);
+ cachedEntry = de.Children.Add(rdn, "siteLinkBridge");
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // if it is ADAM and transport type is SMTP, throw NotSupportedException.
+ DirectoryEntry tmpDE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ if (Utils.CheckCapability(tmpDE, Capability.ActiveDirectoryApplicationMode) && transport == ActiveDirectoryTransportType.Smtp)
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportTransportSMTP));
+ }
+ }
+
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ de.Dispose();
+ }
+ }
+
+ internal ActiveDirectorySiteLinkBridge(DirectoryContext context, string bridgeName, ActiveDirectoryTransportType transport, bool existing)
+ {
+ this.context = context;
+ _name = bridgeName;
+ _transport = transport;
+
+ _existing = existing;
+ }
+
+ public static ActiveDirectorySiteLinkBridge FindByName(DirectoryContext context, string bridgeName)
+ {
+ return FindByName(context, bridgeName, ActiveDirectoryTransportType.Rpc);
+ }
+
+ public static ActiveDirectorySiteLinkBridge FindByName(DirectoryContext context, string bridgeName, ActiveDirectoryTransportType transport)
+ {
+ ValidateArgument(context, bridgeName, transport);
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // bind to the rootdse to get the configurationnamingcontext
+ DirectoryEntry de;
+
+ try
+ {
+ de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ string containerDN = "CN=Inter-Site Transports,CN=Sites," + config;
+ if (transport == ActiveDirectoryTransportType.Rpc)
+ containerDN = "CN=IP," + containerDN;
+ else
+ containerDN = "CN=SMTP," + containerDN;
+ de = DirectoryEntryManager.GetDirectoryEntry(context, containerDN);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ try
+ {
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=siteLinkBridge)(objectCategory=SiteLinkBridge)(name=" + Utils.GetEscapedFilterValue(bridgeName) + "))",
+ new string[] { "distinguishedName" },
+ SearchScope.OneLevel,
+ false, /* don't need paged search */
+ false /* don't need to cache result */);
+ SearchResult srchResult = adSearcher.FindOne();
+
+ if (srchResult == null)
+ {
+ // no such site link bridge object
+ Exception e = new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySiteLinkBridge), bridgeName);
+ throw e;
+ }
+ else
+ {
+ DirectoryEntry connectionEntry = srchResult.GetDirectoryEntry();
+ // it is an existing site link bridge object
+ ActiveDirectorySiteLinkBridge bridge = new ActiveDirectorySiteLinkBridge(context, bridgeName, transport, true);
+ bridge.cachedEntry = connectionEntry;
+ return bridge;
+ }
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // if it is ADAM and transport type is SMTP, throw NotSupportedException.
+ DirectoryEntry tmpDE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ if (Utils.CheckCapability(tmpDE, Capability.ActiveDirectoryApplicationMode) && transport == ActiveDirectoryTransportType.Smtp)
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportTransportSMTP));
+ }
+ else
+ {
+ // object is not found since we cannot even find the container in which to search
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySiteLinkBridge), bridgeName);
+ }
+ }
+
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ de.Dispose();
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _name;
+ }
+ }
+
+ public ActiveDirectorySiteLinkCollection SiteLinks
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (_existing)
+ {
+ // if asked the first time, we need to properly construct the subnets collection
+ if (!_linksRetrieved)
+ {
+ _links.initialized = false;
+ _links.Clear();
+ GetLinks();
+ _linksRetrieved = true;
+ }
+ }
+ _links.initialized = true;
+ _links.de = cachedEntry;
+ _links.context = context;
+ return _links;
+ }
+ }
+
+ public ActiveDirectoryTransportType TransportType
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _transport;
+ }
+ }
+
+ public void Save()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ cachedEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (_existing)
+ {
+ // indicates that nex time user asks for SiteLinks property, we might need to fetch it from server
+ _linksRetrieved = false;
+ }
+ else
+ {
+ _existing = true;
+ }
+ }
+
+ public void Delete()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!_existing)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotDelete));
+ }
+ else
+ {
+ try
+ {
+ cachedEntry.Parent.Children.Remove(cachedEntry);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public override string ToString()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _name;
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!_existing)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotGetObject));
+ }
+ else
+ {
+ return DirectoryEntryManager.GetDirectoryEntryInternal(context, cachedEntry.Path);
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // free other state (managed objects)
+ if (cachedEntry != null)
+ cachedEntry.Dispose();
+ }
+
+ // free your own state (unmanaged objects)
+
+ _disposed = true;
+ }
+
+ private static void ValidateArgument(DirectoryContext context, string bridgeName, ActiveDirectoryTransportType transport)
+ {
+ // basic validation first
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // if target is not specified, then we determin the target from the logon credential, so if it is a local user context, it should fail
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ // more validation for the context, if the target is not null, then it should be either forest name or server name
+ if (context.Name != null)
+ {
+ if (!(context.isRootDomain() || context.isServer() || context.isADAMConfigSet()))
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+
+ if (bridgeName == null)
+ throw new ArgumentNullException("bridgeName");
+
+ if (bridgeName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "bridgeName");
+
+ if (transport < ActiveDirectoryTransportType.Rpc || transport > ActiveDirectoryTransportType.Smtp)
+ throw new InvalidEnumArgumentException("value", (int)transport, typeof(ActiveDirectoryTransportType));
+ }
+
+ private void GetLinks()
+ {
+ ArrayList propertyList = new ArrayList();
+ NativeComInterfaces.IAdsPathname pathCracker = null;
+ pathCracker = (NativeComInterfaces.IAdsPathname)new NativeComInterfaces.Pathname();
+ // need to turn off the escaping for name
+ pathCracker.EscapedMode = NativeComInterfaces.ADS_ESCAPEDMODE_OFF_EX;
+ string propertyName = "siteLinkList";
+
+ propertyList.Add(propertyName);
+ Hashtable values = Utils.GetValuesWithRangeRetrieval(cachedEntry, "(objectClass=*)", propertyList, SearchScope.Base);
+ ArrayList siteLinkLists = (ArrayList)values[propertyName.ToLower(CultureInfo.InvariantCulture)];
+
+ // somehow no site link list
+ if (siteLinkLists == null)
+ return;
+
+ // construct the site link object
+ for (int i = 0; i < siteLinkLists.Count; i++)
+ {
+ string dn = (string)siteLinkLists[i];
+ // escaping manipulation
+ pathCracker.Set(dn, NativeComInterfaces.ADS_SETTYPE_DN);
+ string rdn = pathCracker.Retrieve(NativeComInterfaces.ADS_FORMAT_LEAF);
+ Debug.Assert(rdn != null && Utils.Compare(rdn, 0, 3, "CN=", 0, 3) == 0);
+ rdn = rdn.Substring(3);
+ DirectoryEntry entry = DirectoryEntryManager.GetDirectoryEntry(context, dn);
+ ActiveDirectorySiteLink link = new ActiveDirectorySiteLink(context, rdn, _transport, true, entry);
+
+ _links.Add(link);
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkCollection.cs
new file mode 100644
index 0000000000..f464df3ac1
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkCollection.cs
@@ -0,0 +1,241 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Globalization;
+
+ public class ActiveDirectorySiteLinkCollection : CollectionBase
+ {
+ internal DirectoryEntry de = null;
+ internal bool initialized = false;
+ internal DirectoryContext context = null;
+
+ internal ActiveDirectorySiteLinkCollection() { }
+
+ public ActiveDirectorySiteLink this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySiteLink)InnerList[index];
+ }
+ set
+ {
+ ActiveDirectorySiteLink link = (ActiveDirectorySiteLink)value;
+
+ if (link == null)
+ throw new ArgumentNullException("value");
+
+ if (!link.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteLinkNotCommitted, link.Name));
+
+ if (!Contains(link))
+ List[index] = link;
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, link), "value");
+ }
+ }
+
+ public int Add(ActiveDirectorySiteLink link)
+ {
+ if (link == null)
+ throw new ArgumentNullException("link");
+
+ if (!link.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteLinkNotCommitted, link.Name));
+
+ if (!Contains(link))
+ return List.Add(link);
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, link), "link");
+ }
+
+ public void AddRange(ActiveDirectorySiteLink[] links)
+ {
+ if (links == null)
+ throw new ArgumentNullException("links");
+
+ for (int i = 0; i < links.Length; i = i + 1)
+ this.Add(links[i]);
+ }
+
+ public void AddRange(ActiveDirectorySiteLinkCollection links)
+ {
+ if (links == null)
+ throw new ArgumentNullException("links");
+
+ int count = links.Count;
+ for (int i = 0; i < count; i++)
+ this.Add(links[i]);
+ }
+
+ public bool Contains(ActiveDirectorySiteLink link)
+ {
+ if (link == null)
+ throw new ArgumentNullException("link");
+
+ if (!link.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteLinkNotCommitted, link.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(link.context, link.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySiteLink tmp = (ActiveDirectorySiteLink)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void CopyTo(ActiveDirectorySiteLink[] array, int index)
+ {
+ List.CopyTo(array, index);
+ }
+
+ public int IndexOf(ActiveDirectorySiteLink link)
+ {
+ if (link == null)
+ throw new ArgumentNullException("link");
+
+ if (!link.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteLinkNotCommitted, link.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(link.context, link.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySiteLink tmp = (ActiveDirectorySiteLink)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void Insert(int index, ActiveDirectorySiteLink link)
+ {
+ if (link == null)
+ throw new ArgumentNullException("value");
+
+ if (!link.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteLinkNotCommitted, link.Name));
+
+ if (!Contains(link))
+ List.Insert(index, link);
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, link), "link");
+ }
+
+ public void Remove(ActiveDirectorySiteLink link)
+ {
+ if (link == null)
+ throw new ArgumentNullException("link");
+
+ if (!link.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteLinkNotCommitted, link.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(link.context, link.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySiteLink tmp = (ActiveDirectorySiteLink)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ List.Remove(tmp);
+ return;
+ }
+ }
+
+ // something that does not exist in the collectio
+ throw new ArgumentException(Res.GetString(Res.NotFoundInCollection, link), "link");
+ }
+
+ protected override void OnClearComplete()
+ {
+ // if the property exists, clear it out
+ if (initialized)
+ {
+ try
+ {
+ if (de.Properties.Contains("siteLinkList"))
+ de.Properties["siteLinkList"].Clear();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ protected override void OnInsertComplete(int index, object value)
+ {
+ if (initialized)
+ {
+ ActiveDirectorySiteLink link = (ActiveDirectorySiteLink)value;
+ string dn = (string)PropertyManager.GetPropertyValue(link.context, link.cachedEntry, PropertyManager.DistinguishedName);
+ try
+ {
+ de.Properties["siteLinkList"].Add(dn);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ protected override void OnRemoveComplete(int index, object value)
+ {
+ ActiveDirectorySiteLink link = (ActiveDirectorySiteLink)value;
+ string dn = (string)PropertyManager.GetPropertyValue(link.context, link.cachedEntry, PropertyManager.DistinguishedName);
+ try
+ {
+ de.Properties["siteLinkList"].Remove(dn);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ protected override void OnSetComplete(int index, object oldValue, object newValue)
+ {
+ ActiveDirectorySiteLink newLink = (ActiveDirectorySiteLink)newValue;
+ string newdn = (string)PropertyManager.GetPropertyValue(newLink.context, newLink.cachedEntry, PropertyManager.DistinguishedName);
+ try
+ {
+ de.Properties["siteLinkList"][index] = newdn;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ if (!(value is ActiveDirectorySiteLink))
+ throw new ArgumentException("value");
+
+ if (!((ActiveDirectorySiteLink)value).existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteLinkNotCommitted, ((ActiveDirectorySiteLink)value).Name));
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnet.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnet.cs
new file mode 100644
index 0000000000..751b542be4
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnet.cs
@@ -0,0 +1,411 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ActiveDirectorySubnet : IDisposable
+ {
+ private ActiveDirectorySite _site = null;
+ private string _name = null;
+ internal DirectoryContext context = null;
+ private bool _disposed = false;
+
+ internal bool existing = false;
+ internal DirectoryEntry cachedEntry = null;
+
+ public static ActiveDirectorySubnet FindByName(DirectoryContext context, string subnetName)
+ {
+ ValidateArgument(context, subnetName);
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // bind to the rootdse to get the configurationnamingcontext
+ DirectoryEntry de;
+
+ try
+ {
+ de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ string subnetdn = "CN=Subnets,CN=Sites," + config;
+ de = DirectoryEntryManager.GetDirectoryEntry(context, subnetdn);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ try
+ {
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=subnet)(objectCategory=subnet)(name=" + Utils.GetEscapedFilterValue(subnetName) + "))",
+ new string[] { "distinguishedName" },
+ SearchScope.OneLevel,
+ false, /* don't need paged search */
+ false /* don't need to cache result */);
+ SearchResult srchResult = adSearcher.FindOne();
+ if (srchResult == null)
+ {
+ // no such subnet object
+ Exception e = new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySubnet), subnetName);
+ throw e;
+ }
+ else
+ {
+ string siteName = null;
+ DirectoryEntry connectionEntry = srchResult.GetDirectoryEntry();
+ // try to get the site that this subnet lives in
+ if (connectionEntry.Properties.Contains("siteObject"))
+ {
+ NativeComInterfaces.IAdsPathname pathCracker = (NativeComInterfaces.IAdsPathname)new NativeComInterfaces.Pathname();
+ // need to turn off the escaping for name
+ pathCracker.EscapedMode = NativeComInterfaces.ADS_ESCAPEDMODE_OFF_EX;
+
+ string tmp = (string)connectionEntry.Properties["siteObject"][0];
+ // escaping manipulation
+ pathCracker.Set(tmp, NativeComInterfaces.ADS_SETTYPE_DN);
+ string rdn = pathCracker.Retrieve(NativeComInterfaces.ADS_FORMAT_LEAF);
+ Debug.Assert(rdn != null && Utils.Compare(rdn, 0, 3, "CN=", 0, 3) == 0);
+ siteName = rdn.Substring(3);
+ }
+
+ // it is an existing subnet object
+ ActiveDirectorySubnet subnet = null;
+ if (siteName == null)
+ subnet = new ActiveDirectorySubnet(context, subnetName, null, true);
+ else
+ subnet = new ActiveDirectorySubnet(context, subnetName, siteName, true);
+
+ subnet.cachedEntry = connectionEntry;
+ return subnet;
+ }
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // object is not found since we cannot even find the container in which to search
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ActiveDirectorySubnet), subnetName);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ finally
+ {
+ if (de != null)
+ de.Dispose();
+ }
+ }
+
+ public ActiveDirectorySubnet(DirectoryContext context, string subnetName)
+ {
+ ValidateArgument(context, subnetName);
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ this.context = context;
+ _name = subnetName;
+
+ // bind to the rootdse to get the configurationnamingcontext
+ DirectoryEntry de = null;
+
+ try
+ {
+ de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string config = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ConfigurationNamingContext);
+ string subnetn = "CN=Subnets,CN=Sites," + config;
+ // bind to the subnet container
+ de = DirectoryEntryManager.GetDirectoryEntry(context, subnetn);
+
+ string rdn = "cn=" + _name;
+ rdn = Utils.GetEscapedPath(rdn);
+ cachedEntry = de.Children.Add(rdn, "subnet");
+ }
+ catch (COMException e)
+ {
+ ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+ finally
+ {
+ if (de != null)
+ de.Dispose();
+ }
+ }
+
+ public ActiveDirectorySubnet(DirectoryContext context, string subnetName, string siteName) : this(context, subnetName)
+ {
+ if (siteName == null)
+ throw new ArgumentNullException("siteName");
+
+ if (siteName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+
+ // validate that siteName is valid
+ try
+ {
+ _site = ActiveDirectorySite.FindByName(this.context, siteName);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ArgumentException(Res.GetString(Res.SiteNotExist, siteName), "siteName");
+ }
+ }
+
+ internal ActiveDirectorySubnet(DirectoryContext context, string subnetName, string siteName, bool existing)
+ {
+ Debug.Assert(existing == true);
+
+ this.context = context;
+ _name = subnetName;
+
+ if (siteName != null)
+ {
+ try
+ {
+ _site = ActiveDirectorySite.FindByName(context, siteName);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ArgumentException(Res.GetString(Res.SiteNotExist, siteName), "siteName");
+ }
+ }
+
+ this.existing = true;
+ }
+
+ public string Name
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _name;
+ }
+ }
+
+ public ActiveDirectorySite Site
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _site;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (value != null)
+ {
+ // check whether the site exists or not, you can not create a new site and set it to a subnet object with commit change to site object first
+ if (!value.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SiteNotCommitted, value));
+ }
+
+ _site = value;
+ }
+ }
+
+ public string Location
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ if (cachedEntry.Properties.Contains("location"))
+ return (string)cachedEntry.Properties["location"][0];
+ else
+ return null;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // if the value is null, it means that user wants to clear the value
+ try
+ {
+ if (value == null)
+ {
+ if (cachedEntry.Properties.Contains("location"))
+ cachedEntry.Properties["location"].Clear();
+ }
+ else
+ {
+ cachedEntry.Properties["location"].Value = value;
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public void Save()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ if (existing)
+ {
+ // check whether site has been changed or not
+ if (_site == null)
+ {
+ // user wants to remove this subnet object from previous site
+ if (cachedEntry.Properties.Contains("siteObject"))
+ cachedEntry.Properties["siteObject"].Clear();
+ }
+ else
+ {
+ // user configures this subnet object to a particular site
+ cachedEntry.Properties["siteObject"].Value = _site.cachedEntry.Properties["distinguishedName"][0];
+ }
+ cachedEntry.CommitChanges();
+ }
+ else
+ {
+ if (Site != null)
+ cachedEntry.Properties["siteObject"].Add(_site.cachedEntry.Properties["distinguishedName"][0]);
+
+ cachedEntry.CommitChanges();
+
+ // the subnet has been created in the backend store
+ existing = true;
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ public void Delete()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!existing)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotDelete));
+ }
+ else
+ {
+ try
+ {
+ cachedEntry.Parent.Children.Remove(cachedEntry);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public override string ToString()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return Name;
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!existing)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotGetObject));
+ }
+ else
+ {
+ return DirectoryEntryManager.GetDirectoryEntryInternal(context, cachedEntry.Path);
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // free other state (managed objects)
+ if (cachedEntry != null)
+ cachedEntry.Dispose();
+ }
+
+ // free your own state (unmanaged objects)
+
+ _disposed = true;
+ }
+
+ private static void ValidateArgument(DirectoryContext context, string subnetName)
+ {
+ // basic validation first
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // if target is not specified, then we determin the target from the logon credential, so if it is a local user context, it should fail
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ // more validation for the context, if the target is not null, then it should be either forest name or server name
+ if (context.Name != null)
+ {
+ // we only allow target to be forest, server name or ADAM config set
+ if (!(context.isRootDomain() || context.isServer() || context.isADAMConfigSet()))
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+
+ if (subnetName == null)
+ throw new ArgumentNullException("subnetName");
+
+ if (subnetName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "subnetName");
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnetCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnetCollection.cs
new file mode 100644
index 0000000000..9ac84a42d5
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnetCollection.cs
@@ -0,0 +1,294 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+ using System.Text;
+
+ public class ActiveDirectorySubnetCollection : CollectionBase
+ {
+ internal Hashtable changeList = null;
+ internal bool initialized = false;
+ private string _siteDN = null;
+ private DirectoryContext _context = null;
+ private ArrayList _copyList = new ArrayList();
+
+ internal ActiveDirectorySubnetCollection(DirectoryContext context, string siteDN)
+ {
+ _context = context;
+ _siteDN = siteDN;
+
+ Hashtable tempTable = new Hashtable();
+ changeList = Hashtable.Synchronized(tempTable);
+ }
+
+ public ActiveDirectorySubnet this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySubnet)InnerList[index];
+ }
+ set
+ {
+ ActiveDirectorySubnet subnet = (ActiveDirectorySubnet)value;
+
+ if (subnet == null)
+ throw new ArgumentNullException("value");
+
+ if (!subnet.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SubnetNotCommitted, subnet.Name));
+
+ if (!Contains(subnet))
+ List[index] = subnet;
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, subnet), "value");
+ }
+ }
+
+ public int Add(ActiveDirectorySubnet subnet)
+ {
+ if (subnet == null)
+ throw new ArgumentNullException("subnet");
+
+ if (!subnet.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SubnetNotCommitted, subnet.Name));
+
+ if (!Contains(subnet))
+ return List.Add(subnet);
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, subnet), "subnet");
+ }
+
+ public void AddRange(ActiveDirectorySubnet[] subnets)
+ {
+ if (subnets == null)
+ throw new ArgumentNullException("subnets");
+
+ foreach (ActiveDirectorySubnet s in subnets)
+ {
+ if (s == null)
+ {
+ throw new ArgumentException("subnets");
+ }
+ }
+
+ for (int i = 0; ((i) < (subnets.Length)); i = ((i) + (1)))
+ this.Add(subnets[i]);
+ }
+
+ public void AddRange(ActiveDirectorySubnetCollection subnets)
+ {
+ if (subnets == null)
+ throw new ArgumentNullException("subnets");
+
+ int count = subnets.Count;
+ for (int i = 0; i < count; i++)
+ this.Add(subnets[i]);
+ }
+
+ public bool Contains(ActiveDirectorySubnet subnet)
+ {
+ if (subnet == null)
+ throw new ArgumentNullException("subnet");
+
+ if (!subnet.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SubnetNotCommitted, subnet.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySubnet tmp = (ActiveDirectorySubnet)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void CopyTo(ActiveDirectorySubnet[] array, int index)
+ {
+ List.CopyTo(array, index);
+ }
+
+ public int IndexOf(ActiveDirectorySubnet subnet)
+ {
+ if (subnet == null)
+ throw new ArgumentNullException("subnet");
+
+ if (!subnet.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SubnetNotCommitted, subnet.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySubnet tmp = (ActiveDirectorySubnet)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void Insert(int index, ActiveDirectorySubnet subnet)
+ {
+ if (subnet == null)
+ throw new ArgumentNullException("subnet");
+
+ if (!subnet.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SubnetNotCommitted, subnet.Name));
+
+ if (!Contains(subnet))
+ List.Insert(index, subnet);
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, subnet), "subnet");
+ }
+
+ public void Remove(ActiveDirectorySubnet subnet)
+ {
+ if (subnet == null)
+ throw new ArgumentNullException("subnet");
+
+ if (!subnet.existing)
+ throw new InvalidOperationException(Res.GetString(Res.SubnetNotCommitted, subnet.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySubnet tmp = (ActiveDirectorySubnet)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ List.Remove(tmp);
+ return;
+ }
+ }
+
+ // something that does not exist in the collectio
+ throw new ArgumentException(Res.GetString(Res.NotFoundInCollection, subnet), "subnet");
+ }
+
+ protected override void OnClear()
+ {
+ if (initialized)
+ {
+ _copyList.Clear();
+ foreach (object o in List)
+ {
+ _copyList.Add(o);
+ }
+ }
+ }
+
+ protected override void OnClearComplete()
+ {
+ // if the property exists, clear it out
+ if (initialized)
+ {
+ for (int i = 0; i < _copyList.Count; i++)
+ {
+ OnRemoveComplete(i, _copyList[i]);
+ }
+ }
+ }
+
+ protected override void OnInsertComplete(int index, object value)
+ {
+ if (initialized)
+ {
+ ActiveDirectorySubnet subnet = (ActiveDirectorySubnet)value;
+ string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName);
+
+ try
+ {
+ if (changeList.Contains(dn))
+ {
+ ((DirectoryEntry)changeList[dn]).Properties["siteObject"].Value = _siteDN;
+ }
+ else
+ {
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(_context, MakePath(dn));
+ de.Properties["siteObject"].Value = _siteDN;
+ changeList.Add(dn, de);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ }
+
+ protected override void OnRemoveComplete(int index, object value)
+ {
+ ActiveDirectorySubnet subnet = (ActiveDirectorySubnet)value;
+ string dn = (string)PropertyManager.GetPropertyValue(subnet.context, subnet.cachedEntry, PropertyManager.DistinguishedName);
+
+ try
+ {
+ if (changeList.Contains(dn))
+ {
+ ((DirectoryEntry)changeList[dn]).Properties["siteObject"].Clear();
+ }
+ else
+ {
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(_context, MakePath(dn));
+ de.Properties["siteObject"].Clear();
+ changeList.Add(dn, de);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+
+ protected override void OnSetComplete(int index, object oldValue, object newValue)
+ {
+ OnRemoveComplete(index, oldValue);
+ OnInsertComplete(index, newValue);
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ if (!(value is ActiveDirectorySubnet))
+ throw new ArgumentException("value");
+
+ if (!((ActiveDirectorySubnet)value).existing)
+ throw new InvalidOperationException(Res.GetString(Res.SubnetNotCommitted, ((ActiveDirectorySubnet)value).Name));
+ }
+
+ private string MakePath(string subnetDN)
+ {
+ string rdn = Utils.GetRdnFromDN(subnetDN);
+ StringBuilder str = new StringBuilder();
+ for (int i = 0; i < rdn.Length; i++)
+ {
+ if (rdn[i] == '/')
+ {
+ str.Append('\\');
+ }
+
+ str.Append(rdn[i]);
+ }
+
+ return str.ToString() + "," + subnetDN.Substring(rdn.Length + 1);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySyntax.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySyntax.cs
new file mode 100644
index 0000000000..286bf0a6d7
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySyntax.cs
@@ -0,0 +1,108 @@
+// 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.ActiveDirectory
+{
+ using System;
+
+ public enum ActiveDirectorySyntax : int
+ {
+ CaseExactString = 0,
+ CaseIgnoreString = 1,
+ NumericString = 2,
+ DirectoryString = 3,
+ OctetString = 4,
+ SecurityDescriptor = 5,
+ Int = 6,
+ Int64 = 7,
+ Bool = 8,
+ Oid = 9,
+ GeneralizedTime = 10,
+ UtcTime = 11,
+ DN = 12,
+ DNWithBinary = 13,
+ DNWithString = 14,
+ Enumeration = 15,
+ IA5String = 16,
+ PrintableString = 17,
+ Sid = 18,
+ AccessPointDN = 19,
+ ORName = 20,
+ PresentationAddress = 21,
+ ReplicaLink = 22
+ }
+
+ internal class OMObjectClass
+ {
+ public byte[] data = null;
+
+ public OMObjectClass(byte[] data)
+ {
+ this.data = data;
+ }
+
+ public bool Equals(OMObjectClass OMObjectClass)
+ {
+ bool result = true;
+ if (data.Length == OMObjectClass.data.Length)
+ {
+ for (int i = 0; i < data.Length; i++)
+ {
+ if (data[i] != OMObjectClass.data[i])
+ {
+ result = false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ result = false;
+ }
+ return result;
+ }
+
+ public byte[] Data
+ {
+ get
+ {
+ return data;
+ }
+ }
+ }
+
+ internal class Syntax
+ {
+ public string attributeSyntax = null;
+ public int oMSyntax = 0;
+ public OMObjectClass oMObjectClass = null;
+
+ public Syntax(string attributeSyntax, int oMSyntax, OMObjectClass oMObjectClass)
+ {
+ this.attributeSyntax = attributeSyntax;
+ this.oMSyntax = oMSyntax;
+ this.oMObjectClass = oMObjectClass;
+ }
+
+ public bool Equals(Syntax syntax)
+ {
+ bool result = true;
+ if ((!syntax.attributeSyntax.Equals(this.attributeSyntax))
+ || (syntax.oMSyntax != this.oMSyntax))
+ {
+ result = false;
+ }
+ else
+ {
+ if (((this.oMObjectClass != null) && (syntax.oMObjectClass == null))
+ || ((this.oMObjectClass == null) && (syntax.oMObjectClass != null))
+ || ((this.oMObjectClass != null) && (syntax.oMObjectClass != null) && (!this.oMObjectClass.Equals(syntax.oMObjectClass))))
+ {
+ result = false;
+ }
+ }
+ return result;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ApplicationPartition.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ApplicationPartition.cs
new file mode 100644
index 0000000000..7b7b9c0ea2
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ApplicationPartition.cs
@@ -0,0 +1,1281 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Text;
+ using System.Threading;
+ using System.Collections;
+ using System.Globalization;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using System.Security.Permissions;
+
+ internal enum NCFlags : int
+ {
+ InstanceTypeIsNCHead = 1,
+ InstanceTypeIsWriteable = 4
+ }
+
+ internal enum ApplicationPartitionType : int
+ {
+ Unknown = -1,
+ ADApplicationPartition = 0,
+ ADAMApplicationPartition = 1
+ }
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ApplicationPartition : ActiveDirectoryPartition
+ {
+ private bool _disposed = false;
+ private ApplicationPartitionType _appType = (ApplicationPartitionType)(-1);
+ private bool _committed = true;
+ private DirectoryEntry _domainDNSEntry = null;
+ private DirectoryEntry _crossRefEntry = null;
+ private string _dnsName = null;
+ private DirectoryServerCollection _cachedDirectoryServers = null;
+ private bool _securityRefDomainModified = false;
+ private string _securityRefDomain = null;
+
+ #region constructors
+ // Public Constructors
+ public ApplicationPartition(DirectoryContext context, string distinguishedName)
+ {
+ // validate the parameters
+ ValidateApplicationPartitionParameters(context, distinguishedName, null, false);
+
+ // call private function for creating the application partition
+ CreateApplicationPartition(distinguishedName, "domainDns");
+ }
+
+ public ApplicationPartition(DirectoryContext context, string distinguishedName, string objectClass)
+ {
+ // validate the parameters
+ ValidateApplicationPartitionParameters(context, distinguishedName, objectClass, true);
+
+ // call private function for creating the application partition
+ CreateApplicationPartition(distinguishedName, objectClass);
+ }
+
+ // Internal Constructors
+ internal ApplicationPartition(DirectoryContext context, string distinguishedName, string dnsName, ApplicationPartitionType appType, DirectoryEntryManager directoryEntryMgr)
+ : base(context, distinguishedName)
+ {
+ this.directoryEntryMgr = directoryEntryMgr;
+ _appType = appType;
+ _dnsName = dnsName;
+ }
+
+ internal ApplicationPartition(DirectoryContext context, string distinguishedName, string dnsName, DirectoryEntryManager directoryEntryMgr)
+ : this(context, distinguishedName, dnsName, GetApplicationPartitionType(context), directoryEntryMgr)
+ {
+ }
+ #endregion constructors
+
+ #region IDisposable
+ // private Dispose method
+ protected override void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ try
+ {
+ // if there are any managed or unmanaged
+ // resources to be freed, those should be done here
+ // if disposing = true, only unmanaged resources should
+ // be freed, else both managed and unmanaged.
+ if (_crossRefEntry != null)
+ {
+ _crossRefEntry.Dispose();
+ _crossRefEntry = null;
+ }
+ if (_domainDNSEntry != null)
+ {
+ _domainDNSEntry.Dispose();
+ _domainDNSEntry = null;
+ }
+
+ _disposed = true;
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+
+ public static ApplicationPartition GetApplicationPartition(DirectoryContext context)
+ {
+ // validate the context
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ // contexttype should be ApplicationPartiton
+ if (context.ContextType != DirectoryContextType.ApplicationPartition)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeAppNCDnsName), "context");
+ }
+
+ // target must be ndnc dns name
+ if (!context.isNdnc())
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.NDNCNotFound), typeof(ApplicationPartition), context.Name);
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // bind to the application partition head (this will verify credentials)
+ string distinguishedName = Utils.GetDNFromDnsName(context.Name);
+ DirectoryEntryManager directoryEntryMgr = new DirectoryEntryManager(context);
+ DirectoryEntry appNCHead = null;
+
+ try
+ {
+ appNCHead = directoryEntryMgr.GetCachedDirectoryEntry(distinguishedName);
+ // need to force the bind
+ appNCHead.Bind(true);
+ }
+ catch (COMException e)
+ {
+ int errorCode = e.ErrorCode;
+
+ if (errorCode == unchecked((int)0x8007203a))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.NDNCNotFound), typeof(ApplicationPartition), context.Name);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ return new ApplicationPartition(context, distinguishedName, context.Name, ApplicationPartitionType.ADApplicationPartition, directoryEntryMgr);
+ }
+
+ public static ApplicationPartition FindByName(DirectoryContext context, string distinguishedName)
+ {
+ ApplicationPartition partition = null;
+ DirectoryEntryManager directoryEntryMgr = null;
+ DirectoryContext appNCContext = null;
+
+ // check that the argument is not null
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ArgumentException(Res.GetString(Res.ContextNotAssociatedWithDomain), "context");
+ }
+
+ if (context.Name != null)
+ {
+ // the target should be a valid forest name, configset name or a server
+ if (!((context.isRootDomain()) || (context.isADAMConfigSet()) || context.isServer()))
+ {
+ throw new ArgumentException(Res.GetString(Res.NotADOrADAM), "context");
+ }
+ }
+
+ // check that the distingushed name of the application partition is not null or empty
+ if (distinguishedName == null)
+ throw new ArgumentNullException("distinguishedName");
+
+ if (distinguishedName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "distinguishedName");
+
+ if (!Utils.IsValidDNFormat(distinguishedName))
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat), "distinguishedName");
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // search in the partitions container of the forest for
+ // crossRef objects that have their nCName set to the specified distinguishedName
+ directoryEntryMgr = new DirectoryEntryManager(context);
+ DirectoryEntry partitionsEntry = null;
+
+ try
+ {
+ partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this is the case where the context is a config set and we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, context.Name));
+ }
+
+ // build the filter
+ StringBuilder str = new StringBuilder(15);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=crossRef)(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsNC);
+ str.Append(")(!(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.803:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsDomain);
+ str.Append("))(");
+ str.Append(PropertyManager.NCName);
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(distinguishedName));
+ str.Append("))");
+
+ string filter = str.ToString();
+ string[] propertiesToLoad = new string[2];
+
+ propertiesToLoad[0] = PropertyManager.DnsRoot;
+ propertiesToLoad[1] = PropertyManager.NCName;
+
+ ADSearcher searcher = new ADSearcher(partitionsEntry, filter, propertiesToLoad, SearchScope.OneLevel, false /*not paged search*/, false /*no cached results*/);
+ SearchResult res = null;
+
+ try
+ {
+ res = searcher.FindOne();
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // object is not found since we cannot even find the container in which to search
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AppNCNotFound), typeof(ApplicationPartition), distinguishedName);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ finally
+ {
+ partitionsEntry.Dispose();
+ }
+
+ if (res == null)
+ {
+ // the specified application partition could not be found in the given forest
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AppNCNotFound), typeof(ApplicationPartition), distinguishedName);
+ }
+
+ string appNCDnsName = null;
+ try
+ {
+ appNCDnsName = (res.Properties[PropertyManager.DnsRoot].Count > 0) ? (string)res.Properties[PropertyManager.DnsRoot][0] : null;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ // verify that if the target is a server, then this partition is a naming context on it
+ ApplicationPartitionType appType = GetApplicationPartitionType(context);
+ if (context.ContextType == DirectoryContextType.DirectoryServer)
+ {
+ bool hostsCurrentPartition = false;
+ DistinguishedName appNCDN = new DistinguishedName(distinguishedName);
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+
+ try
+ {
+ foreach (string namingContext in rootDSE.Properties[PropertyManager.NamingContexts])
+ {
+ DistinguishedName dn = new DistinguishedName(namingContext);
+
+ if (dn.Equals(appNCDN))
+ {
+ hostsCurrentPartition = true;
+ break;
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+
+ if (!hostsCurrentPartition)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AppNCNotFound), typeof(ApplicationPartition), distinguishedName);
+ }
+
+ appNCContext = context;
+ }
+ else
+ {
+ // we need to find a server which hosts this application partition
+ if (appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ int errorCode = 0;
+ DomainControllerInfo domainControllerInfo;
+
+ errorCode = Locator.DsGetDcNameWrapper(null, appNCDnsName, null, (long)PrivateLocatorFlags.OnlyLDAPNeeded, out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AppNCNotFound), typeof(ApplicationPartition), distinguishedName);
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+
+ Debug.Assert(domainControllerInfo.DomainControllerName.Length > 2, "ApplicationPartition:FindByName - domainControllerInfo.DomainControllerName.Length <= 2");
+ string serverName = domainControllerInfo.DomainControllerName.Substring(2);
+ appNCContext = Utils.GetNewDirectoryContext(serverName, DirectoryContextType.DirectoryServer, context);
+ }
+ else
+ {
+ // this will find an adam instance that hosts this partition and which is alive and responding.
+ string adamInstName = ConfigurationSet.FindOneAdamInstance(context.Name, context, distinguishedName, null).Name;
+ appNCContext = Utils.GetNewDirectoryContext(adamInstName, DirectoryContextType.DirectoryServer, context);
+ }
+ }
+ partition = new ApplicationPartition(appNCContext, (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.NCName), appNCDnsName, appType, directoryEntryMgr);
+
+ return partition;
+ }
+
+ public DirectoryServer FindDirectoryServer()
+ {
+ DirectoryServer directoryServer = null;
+
+ CheckIfDisposed();
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ // AD
+ directoryServer = FindDirectoryServerInternal(null, false);
+ }
+ else
+ {
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+ directoryServer = ConfigurationSet.FindOneAdamInstance(context, Name, null);
+ }
+ return directoryServer;
+ }
+
+ public DirectoryServer FindDirectoryServer(string siteName)
+ {
+ DirectoryServer directoryServer = null;
+
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ // AD
+ directoryServer = FindDirectoryServerInternal(siteName, false);
+ }
+ else
+ {
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+
+ directoryServer = ConfigurationSet.FindOneAdamInstance(context, Name, siteName);
+ }
+ return directoryServer;
+ }
+
+ public DirectoryServer FindDirectoryServer(bool forceRediscovery)
+ {
+ DirectoryServer directoryServer = null;
+
+ CheckIfDisposed();
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ // AD
+ directoryServer = FindDirectoryServerInternal(null, forceRediscovery);
+ }
+ else
+ {
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+
+ // forceRediscovery is ignored for ADAM Application partition
+ directoryServer = ConfigurationSet.FindOneAdamInstance(context, Name, null);
+ }
+ return directoryServer;
+ }
+
+ public DirectoryServer FindDirectoryServer(string siteName, bool forceRediscovery)
+ {
+ DirectoryServer directoryServer = null;
+
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ // AD
+ directoryServer = FindDirectoryServerInternal(siteName, forceRediscovery);
+ }
+ else
+ {
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+
+ // forceRediscovery is ignored for ADAM Application partition
+ directoryServer = ConfigurationSet.FindOneAdamInstance(context, Name, siteName);
+ }
+ return directoryServer;
+ }
+
+ public ReadOnlyDirectoryServerCollection FindAllDirectoryServers()
+ {
+ CheckIfDisposed();
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ // AD
+ return FindAllDirectoryServersInternal(null);
+ }
+ else
+ {
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+
+ ReadOnlyDirectoryServerCollection directoryServers = new ReadOnlyDirectoryServerCollection();
+ directoryServers.AddRange(ConfigurationSet.FindAdamInstances(context, Name, null));
+ return directoryServers;
+ }
+ }
+
+ public ReadOnlyDirectoryServerCollection FindAllDirectoryServers(string siteName)
+ {
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ // AD
+ return FindAllDirectoryServersInternal(siteName);
+ }
+ else
+ {
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+
+ ReadOnlyDirectoryServerCollection directoryServers = new ReadOnlyDirectoryServerCollection();
+ directoryServers.AddRange(ConfigurationSet.FindAdamInstances(context, Name, siteName));
+ return directoryServers;
+ }
+ }
+
+ public ReadOnlyDirectoryServerCollection FindAllDiscoverableDirectoryServers()
+ {
+ CheckIfDisposed();
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ // AD
+ return FindAllDiscoverableDirectoryServersInternal(null);
+ }
+ else
+ {
+ //
+ // throw exception for ADAM
+ //
+ throw new NotSupportedException(Res.GetString(Res.OperationInvalidForADAM));
+ }
+ }
+
+ public ReadOnlyDirectoryServerCollection FindAllDiscoverableDirectoryServers(string siteName)
+ {
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ // AD
+ return FindAllDiscoverableDirectoryServersInternal(siteName);
+ }
+ else
+ {
+ //
+ // throw exception for ADAM
+ //
+ throw new NotSupportedException(Res.GetString(Res.OperationInvalidForADAM));
+ }
+ }
+
+ public void Delete()
+ {
+ CheckIfDisposed();
+
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+
+ // Get the partitions container and delete the crossRef entry for this
+ // application partition
+ DirectoryEntry partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+ try
+ {
+ GetCrossRefEntry();
+ partitionsEntry.Children.Remove(_crossRefEntry);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ partitionsEntry.Dispose();
+ }
+ }
+
+ public void Save()
+ {
+ CheckIfDisposed();
+
+ if (!_committed)
+ {
+ bool createManually = false;
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ try
+ {
+ _domainDNSEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072029))
+ {
+ // inappropriate authentication (we might have fallen back to NTLM)
+ createManually = true;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+ else
+ {
+ // for ADAM we always create the crossRef manually before creating the domainDNS object
+ createManually = true;
+ }
+
+ if (createManually)
+ {
+ // we need to first save the cross ref entry
+ try
+ {
+ InitializeCrossRef(partitionName);
+ _crossRefEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ try
+ {
+ _domainDNSEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ //
+ //delete the crossRef entry
+ //
+ DirectoryEntry partitionsEntry = _crossRefEntry.Parent;
+ try
+ {
+ partitionsEntry.Children.Remove(_crossRefEntry);
+ }
+ catch (COMException e2)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e2);
+ }
+
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ // if the crossRef is created manually we need to refresh the cross ref entry to get the changes that were made
+ // due to the creation of the partition
+ try
+ {
+ _crossRefEntry.RefreshCache();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ // When we create a domainDNS object on DC1 (Naming Master = DC2),
+ // then internally DC1 will contact DC2 to create the disabled crossRef object.
+ // DC2 will force replicate the crossRef object to DC1. DC1 will then create
+ // the domainDNS object and enable the crossRef on DC1 (not DC2).
+ // Here we need to force replicate the enabling of the crossRef to the FSMO (DC2)
+ // so that we can later add replicas (which need to modify an attribute on the crossRef
+ // on DC2, the FSMO, and can only be done if the crossRef on DC2 is enabled)
+ // get the ntdsa name of the server on which the partition is created
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ string primaryServerNtdsaName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DsServiceName);
+
+ // get the DN of the crossRef entry that needs to be replicated to the fsmo role
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ // for AD we may not have the crossRef entry yet
+ GetCrossRefEntry();
+ }
+ string crossRefDN = (string)PropertyManager.GetPropertyValue(context, _crossRefEntry, PropertyManager.DistinguishedName);
+
+ // Now set the operational attribute "replicateSingleObject" on the Rootdse of the fsmo role
+ // to <ntdsa name of the source>:<DN of the crossRef object which needs to be replicated>
+ DirectoryContext fsmoContext = Utils.GetNewDirectoryContext(GetNamingRoleOwner(), DirectoryContextType.DirectoryServer, context);
+ DirectoryEntry fsmoRootDSE = DirectoryEntryManager.GetDirectoryEntry(fsmoContext, WellKnownDN.RootDSE);
+
+ try
+ {
+ fsmoRootDSE.Properties[PropertyManager.ReplicateSingleObject].Value = primaryServerNtdsaName + ":" + crossRefDN;
+ fsmoRootDSE.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ fsmoRootDSE.Dispose();
+ }
+
+ // the partition has been created
+ _committed = true;
+
+ // commit the replica locations information or security reference domain if applicable
+ if ((_cachedDirectoryServers != null) || (_securityRefDomainModified))
+ {
+ if (_cachedDirectoryServers != null)
+ {
+ _crossRefEntry.Properties[PropertyManager.MsDSNCReplicaLocations].AddRange(_cachedDirectoryServers.GetMultiValuedProperty());
+ }
+ if (_securityRefDomainModified)
+ {
+ _crossRefEntry.Properties[PropertyManager.MsDSSDReferenceDomain].Value = _securityRefDomain;
+ }
+ try
+ {
+ _crossRefEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+ else
+ {
+ // just save the crossRef entry for teh directory servers and the
+ // security reference domain information
+ if ((_cachedDirectoryServers != null) || (_securityRefDomainModified))
+ {
+ try
+ {
+ // we should already have the crossRef entries as some attribute on it has already
+ // been modified
+ Debug.Assert(_crossRefEntry != null, "ApplicationPartition::Save - crossRefEntry on already committed partition which is being modified is null.");
+ _crossRefEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ // invalidate cached info
+ _cachedDirectoryServers = null;
+ _securityRefDomainModified = false;
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override DirectoryEntry GetDirectoryEntry()
+ {
+ CheckIfDisposed();
+
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotGetObject));
+ }
+
+ return DirectoryEntryManager.GetDirectoryEntry(context, Name);
+ }
+
+ #endregion public methods
+
+ #region public properties
+
+ public DirectoryServerCollection DirectoryServers
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedDirectoryServers == null)
+ {
+ ReadOnlyDirectoryServerCollection servers = (_committed) ? FindAllDirectoryServers() : new ReadOnlyDirectoryServerCollection();
+ bool isADAM = (_appType == ApplicationPartitionType.ADAMApplicationPartition) ? true : false;
+
+ // Get the cross ref entry if we don't already have it
+ if (_committed)
+ {
+ GetCrossRefEntry();
+ }
+ //
+ // If the application partition is already committed at this point, we pass in the directory entry for teh crossRef, so any modifications
+ // are made directly on the crossRef entry. If at this point we do not have a crossRefEntry, we pass in null, while saving, we get the information
+ // from the collection and set it on the appropriate attribute on the crossRef directory entry.
+ //
+ //
+ _cachedDirectoryServers = new DirectoryServerCollection(context, (_committed) ? _crossRefEntry : null, isADAM, servers);
+ }
+ return _cachedDirectoryServers;
+ }
+ }
+
+ public string SecurityReferenceDomain
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ if (_appType == ApplicationPartitionType.ADAMApplicationPartition)
+ {
+ throw new NotSupportedException(Res.GetString(Res.PropertyInvalidForADAM));
+ }
+
+ if (_committed)
+ {
+ GetCrossRefEntry();
+
+ try
+ {
+ if (_crossRefEntry.Properties[PropertyManager.MsDSSDReferenceDomain].Count > 0)
+ {
+ return (string)_crossRefEntry.Properties[PropertyManager.MsDSSDReferenceDomain].Value;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ else
+ {
+ return _securityRefDomain;
+ }
+ }
+ set
+ {
+ CheckIfDisposed();
+
+ if (_appType == ApplicationPartitionType.ADAMApplicationPartition)
+ {
+ throw new NotSupportedException(Res.GetString(Res.PropertyInvalidForADAM));
+ }
+
+ if (_committed)
+ {
+ GetCrossRefEntry();
+ // modify the security reference domain
+ // this will get committed when the crossRefEntry is committed
+ if (value == null)
+ {
+ if (_crossRefEntry.Properties.Contains(PropertyManager.MsDSSDReferenceDomain))
+ {
+ _crossRefEntry.Properties[PropertyManager.MsDSSDReferenceDomain].Clear();
+ _securityRefDomainModified = true;
+ }
+ }
+ else
+ {
+ _crossRefEntry.Properties[PropertyManager.MsDSSDReferenceDomain].Value = value;
+ _securityRefDomainModified = true;
+ }
+ }
+ else
+ {
+ if (!((_securityRefDomain == null) && (value == null)))
+ {
+ _securityRefDomain = value;
+ _securityRefDomainModified = true;
+ }
+ }
+ }
+ }
+ #endregion public properties
+
+ #region private methods
+ private void ValidateApplicationPartitionParameters(DirectoryContext context, string distinguishedName, string objectClass, bool objectClassSpecified)
+ {
+ // validate context
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ // contexttype should be DirectoryServer
+ if ((context.Name == null) || (!context.isServer()))
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeServer), "context");
+ }
+
+ // check that the distinguished name is not null or empty
+ if (distinguishedName == null)
+ {
+ throw new ArgumentNullException("distinguishedName");
+ }
+
+ if (distinguishedName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "distinguishedName");
+ }
+
+ // initialize private variables
+ this.context = new DirectoryContext(context);
+ this.directoryEntryMgr = new DirectoryEntryManager(this.context);
+
+ // validate the distinguished name
+ // Utils.GetDnsNameFromDN will throw an ArgumentException if the dn is not valid (cannot be syntactically converted to dns name)
+ _dnsName = Utils.GetDnsNameFromDN(distinguishedName);
+ this.partitionName = distinguishedName;
+
+ //
+ // if the partition being created is a one-level partition, we do not support it
+ //
+ Component[] components = Utils.GetDNComponents(distinguishedName);
+ if (components.Length == 1)
+ {
+ throw new NotSupportedException(Res.GetString(Res.OneLevelPartitionNotSupported));
+ }
+
+ // check if the object class can be specified
+ _appType = GetApplicationPartitionType(this.context);
+ if ((_appType == ApplicationPartitionType.ADApplicationPartition) && (objectClassSpecified))
+ {
+ throw new InvalidOperationException(Res.GetString(Res.NoObjectClassForADPartition));
+ }
+ else if (objectClassSpecified)
+ {
+ // ADAM case and objectClass is explicitly specified, so must be validated
+
+ if (objectClass == null)
+ {
+ throw new ArgumentNullException("objectClass");
+ }
+
+ if (objectClass.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "objectClass");
+ }
+ }
+
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ //
+ // the target in the directory context could be the netbios name of the server, so we will get the dns name
+ // (since application partition creation will fail if dns name is not specified)
+ //
+
+ string serverDnsName = null;
+ try
+ {
+ DirectoryEntry rootDSEEntry = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ serverDnsName = (string)PropertyManager.GetPropertyValue(this.context, rootDSEEntry, PropertyManager.DnsHostName);
+ }
+ catch (COMException e)
+ {
+ ExceptionHelper.GetExceptionFromCOMException(this.context, e);
+ }
+
+ this.context = Utils.GetNewDirectoryContext(serverDnsName, DirectoryContextType.DirectoryServer, context);
+ }
+ }
+
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ private void CreateApplicationPartition(string distinguishedName, string objectClass)
+ {
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ //
+ // AD
+ // 1. Bind to the non-existent application partition using the fast bind and delegation option
+ // 2. Get the Parent object and create a new "domainDNS" object under it
+ // 3. Set the instanceType and the description for the application partitin object
+ //
+
+ DirectoryEntry tempEntry = null;
+ DirectoryEntry parent = null;
+
+ try
+ {
+ AuthenticationTypes authType = Utils.DefaultAuthType | AuthenticationTypes.FastBind | AuthenticationTypes.Delegation;
+
+ if (DirectoryContext.ServerBindSupported)
+ {
+ authType |= AuthenticationTypes.ServerBind;
+ }
+
+ tempEntry = new DirectoryEntry("LDAP://" + context.GetServerName() + "/" + distinguishedName, context.UserName, context.Password, authType);
+ parent = tempEntry.Parent;
+ _domainDNSEntry = parent.Children.Add(Utils.GetRdnFromDN(distinguishedName), PropertyManager.DomainDNS);
+ // set the instance type to 5
+ _domainDNSEntry.Properties[PropertyManager.InstanceType].Value = NCFlags.InstanceTypeIsNCHead | NCFlags.InstanceTypeIsWriteable;
+ // mark this as uncommitted
+ _committed = false;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ // dispose all resources
+ if (parent != null)
+ {
+ parent.Dispose();
+ }
+
+ if (tempEntry != null)
+ {
+ tempEntry.Dispose();
+ }
+ }
+ }
+ else
+ {
+ //
+ // ADAM
+ // 1. Bind to the partitions container on the domain naming owner instance
+ // 2. Create a disabled crossRef object for the new application partition
+ // 3. Bind to the target hint and follow the same steps as for AD
+ //
+
+ try
+ {
+ InitializeCrossRef(distinguishedName);
+
+ DirectoryEntry tempEntry = null;
+ DirectoryEntry parent = null;
+
+ try
+ {
+ AuthenticationTypes authType = Utils.DefaultAuthType | AuthenticationTypes.FastBind;
+
+ if (DirectoryContext.ServerBindSupported)
+ {
+ authType |= AuthenticationTypes.ServerBind;
+ }
+ tempEntry = new DirectoryEntry("LDAP://" + context.Name + "/" + distinguishedName, context.UserName, context.Password, authType);
+ parent = tempEntry.Parent;
+ _domainDNSEntry = parent.Children.Add(Utils.GetRdnFromDN(distinguishedName), objectClass);
+
+ // set the instance type to 5
+ _domainDNSEntry.Properties[PropertyManager.InstanceType].Value = NCFlags.InstanceTypeIsNCHead | NCFlags.InstanceTypeIsWriteable;
+
+ // mark this as uncommitted
+ _committed = false;
+ }
+ finally
+ {
+ // dispose all resources
+ if (parent != null)
+ {
+ parent.Dispose();
+ }
+
+ if (tempEntry != null)
+ {
+ tempEntry.Dispose();
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ private void InitializeCrossRef(string distinguishedName)
+ {
+ if (_crossRefEntry != null)
+ // already initialized
+ return;
+
+ DirectoryEntry partitionsEntry = null;
+
+ try
+ {
+ string namingFsmoName = GetNamingRoleOwner();
+ DirectoryContext roleOwnerContext = Utils.GetNewDirectoryContext(namingFsmoName, DirectoryContextType.DirectoryServer, context);
+ partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(roleOwnerContext, WellKnownDN.PartitionsContainer);
+ string uniqueName = "CN={" + Guid.NewGuid() + "}";
+ _crossRefEntry = partitionsEntry.Children.Add(uniqueName, "crossRef");
+
+ string dnsHostName = null;
+ if (_appType == ApplicationPartitionType.ADAMApplicationPartition)
+ {
+ // Bind to rootdse and get the server name
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ string ntdsaName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DsServiceName);
+ dnsHostName = Utils.GetAdamHostNameAndPortsFromNTDSA(context, ntdsaName);
+ }
+ else
+ {
+ // for AD the name in the context will be the dns name of the server
+ dnsHostName = context.Name;
+ }
+
+ // create disabled cross ref object
+ _crossRefEntry.Properties[PropertyManager.DnsRoot].Value = dnsHostName;
+ _crossRefEntry.Properties[PropertyManager.Enabled].Value = false;
+ _crossRefEntry.Properties[PropertyManager.NCName].Value = distinguishedName;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (partitionsEntry != null)
+ {
+ partitionsEntry.Dispose();
+ }
+ }
+ }
+
+ private static ApplicationPartitionType GetApplicationPartitionType(DirectoryContext context)
+ {
+ ApplicationPartitionType type = ApplicationPartitionType.Unknown;
+
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ try
+ {
+ foreach (string supportedCapability in rootDSE.Properties[PropertyManager.SupportedCapabilities])
+ {
+ if (String.Compare(supportedCapability, SupportedCapability.ADOid, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ type = ApplicationPartitionType.ADApplicationPartition;
+ }
+ if (String.Compare(supportedCapability, SupportedCapability.ADAMOid, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ type = ApplicationPartitionType.ADAMApplicationPartition;
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+
+ // should not happen
+ if (type == ApplicationPartitionType.Unknown)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ApplicationPartitionTypeUnknown));
+ }
+ return type;
+ }
+
+ // we always get the crossEntry bound to the FSMO role
+ // this is so that we do not encounter any replication delay related issues
+ internal DirectoryEntry GetCrossRefEntry()
+ {
+ if (_crossRefEntry != null)
+ {
+ return _crossRefEntry;
+ }
+
+ DirectoryEntry partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+ try
+ {
+ _crossRefEntry = Utils.GetCrossRefEntry(context, partitionsEntry, Name);
+ }
+ finally
+ {
+ partitionsEntry.Dispose();
+ }
+ return _crossRefEntry;
+ }
+
+ internal string GetNamingRoleOwner()
+ {
+ string namingFsmo = null;
+ DirectoryEntry partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+ try
+ {
+ if (_appType == ApplicationPartitionType.ADApplicationPartition)
+ {
+ namingFsmo = Utils.GetDnsHostNameFromNTDSA(context, (string)PropertyManager.GetPropertyValue(context, partitionsEntry, PropertyManager.FsmoRoleOwner));
+ }
+ else
+ {
+ namingFsmo = Utils.GetAdamDnsHostNameFromNTDSA(context, (string)PropertyManager.GetPropertyValue(context, partitionsEntry, PropertyManager.FsmoRoleOwner));
+ }
+ }
+ finally
+ {
+ partitionsEntry.Dispose();
+ }
+ return namingFsmo;
+ }
+
+ private DirectoryServer FindDirectoryServerInternal(string siteName, bool forceRediscovery)
+ {
+ DirectoryServer directoryServer = null;
+ LocatorOptions flag = 0;
+ int errorCode = 0;
+ DomainControllerInfo domainControllerInfo;
+
+ if (siteName != null && siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+
+ // set the force rediscovery flag if required
+ if (forceRediscovery)
+ {
+ flag = LocatorOptions.ForceRediscovery;
+ }
+
+ // call DsGetDcName
+ errorCode = Locator.DsGetDcNameWrapper(null, _dnsName, siteName, (long)flag | (long)PrivateLocatorFlags.OnlyLDAPNeeded, out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ReplicaNotFound), typeof(DirectoryServer), null);
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+
+ Debug.Assert(domainControllerInfo.DomainControllerName.Length > 2, "ApplicationPartition:FindDirectoryServerInternal - domainControllerInfo.DomainControllerName.Length <= 2");
+ string dcName = domainControllerInfo.DomainControllerName.Substring(2);
+
+ // create a new context object for the domain controller passing on only the
+ // credentials from the forest context
+ DirectoryContext dcContext = Utils.GetNewDirectoryContext(dcName, DirectoryContextType.DirectoryServer, context);
+
+ directoryServer = new DomainController(dcContext, dcName);
+ return directoryServer;
+ }
+
+ private ReadOnlyDirectoryServerCollection FindAllDirectoryServersInternal(string siteName)
+ {
+ if (siteName != null && siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+
+ ArrayList dcList = new ArrayList();
+ foreach (string dcName in Utils.GetReplicaList(context, Name, siteName, false /* isDefaultNC */, false /* isADAM */, false /* mustBeGC */))
+ {
+ DirectoryContext dcContext = Utils.GetNewDirectoryContext(dcName, DirectoryContextType.DirectoryServer, context);
+ dcList.Add(new DomainController(dcContext, dcName));
+ }
+
+ return new ReadOnlyDirectoryServerCollection(dcList);
+ }
+
+ private ReadOnlyDirectoryServerCollection FindAllDiscoverableDirectoryServersInternal(string siteName)
+ {
+ if (siteName != null && siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ // Check that the application partition has been committed
+ if (!_committed)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOperationOnUncommittedObject));
+ }
+
+ long flag = (long)PrivateLocatorFlags.OnlyLDAPNeeded;
+
+ return new ReadOnlyDirectoryServerCollection(Locator.EnumerateDomainControllers(context, _dnsName, siteName, flag));
+ }
+
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ApplicationPartitionCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ApplicationPartitionCollection.cs
new file mode 100644
index 0000000000..df5a8da288
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ApplicationPartitionCollection.cs
@@ -0,0 +1,73 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+ using System.DirectoryServices;
+
+ public class ApplicationPartitionCollection : ReadOnlyCollectionBase
+ {
+ internal ApplicationPartitionCollection() { }
+
+ internal ApplicationPartitionCollection(ArrayList values)
+ {
+ if (values != null)
+ {
+ InnerList.AddRange(values);
+ }
+ }
+
+ public ApplicationPartition this[int index]
+ {
+ get
+ {
+ return (ApplicationPartition)InnerList[index];
+ }
+ }
+
+ public bool Contains(ApplicationPartition applicationPartition)
+ {
+ if (applicationPartition == null)
+ {
+ throw new ArgumentNullException("applicationPartition");
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ApplicationPartition tmp = (ApplicationPartition)InnerList[i];
+ if (Utils.Compare(tmp.Name, applicationPartition.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(ApplicationPartition applicationPartition)
+ {
+ if (applicationPartition == null)
+ {
+ throw new ArgumentNullException("applicationPartition");
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ApplicationPartition tmp = (ApplicationPartition)InnerList[i];
+ if (Utils.Compare(tmp.Name, applicationPartition.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(ApplicationPartition[] applicationPartitions, int index)
+ {
+ InnerList.CopyTo(applicationPartitions, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/AttributeMetaData.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/AttributeMetaData.cs
new file mode 100644
index 0000000000..8d9f0f2cb7
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/AttributeMetaData.cs
@@ -0,0 +1,136 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+
+ public class AttributeMetadata
+ {
+ private string _pszAttributeName = null;
+ private int _dwVersion;
+ private DateTime _ftimeLastOriginatingChange;
+ private Guid _uuidLastOriginatingDsaInvocationID;
+ private long _usnOriginatingChange;
+ private long _usnLocalChange;
+ private string _pszLastOriginatingDsaDN = null;
+
+ private string _originatingServerName = null;
+ private DirectoryServer _server = null;
+ private Hashtable _nameTable = null;
+ private bool _advanced = false;
+
+ internal AttributeMetadata(IntPtr info, bool advanced, DirectoryServer server, Hashtable table)
+ {
+ if (advanced)
+ {
+ DS_REPL_ATTR_META_DATA_2 attrMetaData = new DS_REPL_ATTR_META_DATA_2();
+ Marshal.PtrToStructure(info, attrMetaData);
+ Debug.Assert(attrMetaData != null);
+
+ _pszAttributeName = Marshal.PtrToStringUni(attrMetaData.pszAttributeName);
+ _dwVersion = attrMetaData.dwVersion;
+ long ftimeChangeValue = (long)((uint)attrMetaData.ftimeLastOriginatingChange1 + (((long)attrMetaData.ftimeLastOriginatingChange2) << 32));
+ _ftimeLastOriginatingChange = DateTime.FromFileTime(ftimeChangeValue);
+ _uuidLastOriginatingDsaInvocationID = attrMetaData.uuidLastOriginatingDsaInvocationID;
+ _usnOriginatingChange = attrMetaData.usnOriginatingChange;
+ _usnLocalChange = attrMetaData.usnLocalChange;
+ _pszLastOriginatingDsaDN = Marshal.PtrToStringUni(attrMetaData.pszLastOriginatingDsaDN);
+ }
+ else
+ {
+ DS_REPL_ATTR_META_DATA attrMetaData = new DS_REPL_ATTR_META_DATA();
+ Marshal.PtrToStructure(info, attrMetaData);
+ Debug.Assert(attrMetaData != null);
+
+ _pszAttributeName = Marshal.PtrToStringUni(attrMetaData.pszAttributeName);
+ _dwVersion = attrMetaData.dwVersion;
+ long ftimeChangeValue = (long)((uint)attrMetaData.ftimeLastOriginatingChange1 + (((long)attrMetaData.ftimeLastOriginatingChange2) << 32));
+ _ftimeLastOriginatingChange = DateTime.FromFileTime(ftimeChangeValue);
+ _uuidLastOriginatingDsaInvocationID = attrMetaData.uuidLastOriginatingDsaInvocationID;
+ _usnOriginatingChange = attrMetaData.usnOriginatingChange;
+ _usnLocalChange = attrMetaData.usnLocalChange;
+ }
+ _server = server;
+ _nameTable = table;
+ _advanced = advanced;
+ }
+
+ public string Name
+ {
+ get
+ {
+ return _pszAttributeName;
+ }
+ }
+
+ public int Version
+ {
+ get
+ {
+ return _dwVersion;
+ }
+ }
+
+ public DateTime LastOriginatingChangeTime
+ {
+ get
+ {
+ return _ftimeLastOriginatingChange;
+ }
+ }
+
+ public Guid LastOriginatingInvocationId
+ {
+ get
+ {
+ return _uuidLastOriginatingDsaInvocationID;
+ }
+ }
+
+ public long OriginatingChangeUsn
+ {
+ get
+ {
+ return _usnOriginatingChange;
+ }
+ }
+
+ public long LocalChangeUsn
+ {
+ get
+ {
+ return _usnLocalChange;
+ }
+ }
+
+ public string OriginatingServer
+ {
+ get
+ {
+ if (_originatingServerName == null)
+ {
+ // check whether we have got it before
+ if (_nameTable.Contains(LastOriginatingInvocationId))
+ {
+ _originatingServerName = (string)_nameTable[LastOriginatingInvocationId];
+ }
+ // do the translation for downlevel platform or kcc is able to do the name translation
+ else if (!_advanced || (_advanced && _pszLastOriginatingDsaDN != null))
+ {
+ _originatingServerName = Utils.GetServerNameFromInvocationID(_pszLastOriginatingDsaDN, LastOriginatingInvocationId, _server);
+
+ // add it to the hashtable
+ _nameTable.Add(LastOriginatingInvocationId, _originatingServerName);
+ }
+ }
+
+ return _originatingServerName;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/AttributeMetadataCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/AttributeMetadataCollection.cs
new file mode 100644
index 0000000000..f84d1b9d8b
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/AttributeMetadataCollection.cs
@@ -0,0 +1,68 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+
+ public class AttributeMetadataCollection : ReadOnlyCollectionBase
+ {
+ internal AttributeMetadataCollection() { }
+
+ public AttributeMetadata this[int index]
+ {
+ get
+ {
+ return (AttributeMetadata)InnerList[index];
+ }
+ }
+
+ public bool Contains(AttributeMetadata metadata)
+ {
+ if (metadata == null)
+ throw new ArgumentNullException("metadata");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ AttributeMetadata tmp = (AttributeMetadata)InnerList[i];
+ string name = tmp.Name;
+
+ if (Utils.Compare(name, metadata.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(AttributeMetadata metadata)
+ {
+ if (metadata == null)
+ throw new ArgumentNullException("metadata");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ AttributeMetadata tmp = (AttributeMetadata)InnerList[i];
+
+ if (Utils.Compare(tmp.Name, metadata.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(AttributeMetadata[] metadata, int index)
+ {
+ InnerList.CopyTo(metadata, index);
+ }
+
+ internal int Add(AttributeMetadata metadata)
+ {
+ return InnerList.Add(metadata);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ConfigSet.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ConfigSet.cs
new file mode 100644
index 0000000000..6937053556
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ConfigSet.cs
@@ -0,0 +1,795 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Text;
+ using System.Collections;
+ using System.ComponentModel;
+ using System.Globalization;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ConfigurationSet
+ {
+ // Private Variables
+ private DirectoryContext _context = null;
+ private DirectoryEntryManager _directoryEntryMgr = null;
+ private bool _disposed = false;
+
+ // variables corresponding to public properties
+ private string _configSetName = null;
+ private ReadOnlySiteCollection _cachedSites = null;
+ private AdamInstanceCollection _cachedADAMInstances = null;
+ private ApplicationPartitionCollection _cachedApplicationPartitions = null;
+ private ActiveDirectorySchema _cachedSchema = null;
+ private AdamInstance _cachedSchemaRoleOwner = null;
+ private AdamInstance _cachedNamingRoleOwner = null;
+ private ReplicationSecurityLevel _cachedSecurityLevel = (ReplicationSecurityLevel)(-1);
+
+ // 4 minutes timeout for locating an ADAM instance in the configset
+ private static TimeSpan s_locationTimeout = new TimeSpan(0, 4, 0);
+
+ #region constructors
+ internal ConfigurationSet(DirectoryContext context, string configSetName, DirectoryEntryManager directoryEntryMgr)
+ {
+ _context = context;
+ _configSetName = configSetName;
+ _directoryEntryMgr = directoryEntryMgr;
+ }
+
+ internal ConfigurationSet(DirectoryContext context, string configSetName)
+ : this(context, configSetName, new DirectoryEntryManager(context))
+ {
+ }
+ #endregion constructors
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ // private Dispose method
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ // check if this is an explicit Dispose
+ // only then clean up the directory entries
+ if (disposing)
+ {
+ // dispose all directory entries
+ foreach (DirectoryEntry entry in _directoryEntryMgr.GetCachedDirectoryEntries())
+ {
+ entry.Dispose();
+ }
+ }
+ _disposed = true;
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+
+ public static ConfigurationSet GetConfigurationSet(DirectoryContext context)
+ {
+ // check that the argument is not null
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // target should ConfigurationSet or DirectoryServer
+ if ((context.ContextType != DirectoryContextType.ConfigurationSet) &&
+ (context.ContextType != DirectoryContextType.DirectoryServer))
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeServerORConfigSet), "context");
+ }
+
+ // target should be an adam config set or server
+ if (((!context.isServer()) && (!context.isADAMConfigSet())))
+ {
+ // the target should be a server or an ADAM Config Set
+ if (context.ContextType == DirectoryContextType.ConfigurationSet)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ConfigSetNotFound), typeof(ConfigurationSet), context.Name);
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AINotFound, context.Name), typeof(ConfigurationSet), null);
+ }
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ //
+ // bind to rootdse of an adam instance (if target is already a server, verify that it is an adam instance)
+ //
+ DirectoryEntryManager directoryEntryMgr = new DirectoryEntryManager(context);
+ DirectoryEntry rootDSE = null;
+ string configSetName = null;
+
+ try
+ {
+ rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ if ((context.isServer()) && (!Utils.CheckCapability(rootDSE, Capability.ActiveDirectoryApplicationMode)))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AINotFound, context.Name), typeof(ConfigurationSet), null);
+ }
+
+ configSetName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.ConfigurationNamingContext);
+ }
+ catch (COMException e)
+ {
+ int errorCode = e.ErrorCode;
+
+ if (errorCode == unchecked((int)0x8007203a))
+ {
+ if (context.ContextType == DirectoryContextType.ConfigurationSet)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ConfigSetNotFound), typeof(ConfigurationSet), context.Name);
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AINotFound, context.Name), typeof(ConfigurationSet), null);
+ }
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ if (context.ContextType == DirectoryContextType.ConfigurationSet)
+ {
+ // this is the case when we could not find an ADAM instance in that config set
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ConfigSetNotFound), typeof(ConfigurationSet), context.Name);
+ }
+ else
+ throw;
+ }
+
+ // return config set object
+ return new ConfigurationSet(context, configSetName, directoryEntryMgr);
+ }
+
+ public AdamInstance FindAdamInstance()
+ {
+ CheckIfDisposed();
+ return FindOneAdamInstance(Name, _context, null, null);
+ }
+
+ public AdamInstance FindAdamInstance(string partitionName)
+ {
+ CheckIfDisposed();
+
+ if (partitionName == null)
+ {
+ throw new ArgumentNullException("partitionName");
+ }
+
+ return FindOneAdamInstance(Name, _context, partitionName, null);
+ }
+
+ public AdamInstance FindAdamInstance(string partitionName, string siteName)
+ {
+ CheckIfDisposed();
+
+ //
+ // null partitionName would signify that we don't care about the partition
+ //
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return FindOneAdamInstance(Name, _context, partitionName, siteName);
+ }
+
+ public AdamInstanceCollection FindAllAdamInstances()
+ {
+ CheckIfDisposed();
+
+ return FindAdamInstances(_context, null, null);
+ }
+
+ public AdamInstanceCollection FindAllAdamInstances(string partitionName)
+ {
+ CheckIfDisposed();
+
+ if (partitionName == null)
+ {
+ throw new ArgumentNullException("partitionName");
+ }
+
+ return FindAdamInstances(_context, partitionName, null);
+ }
+
+ public AdamInstanceCollection FindAllAdamInstances(string partitionName, string siteName)
+ {
+ CheckIfDisposed();
+
+ //
+ // null partitionName would signify that we don't care about the partition
+ //
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return FindAdamInstances(_context, partitionName, siteName);
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ CheckIfDisposed();
+ return DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.ConfigurationNamingContext);
+ }
+
+ public ReplicationSecurityLevel GetSecurityLevel()
+ {
+ CheckIfDisposed();
+ if (_cachedSecurityLevel == (ReplicationSecurityLevel)(-1))
+ {
+ DirectoryEntry configEntry = _directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.ConfigurationNamingContext);
+ _cachedSecurityLevel = (ReplicationSecurityLevel)((int)PropertyManager.GetPropertyValue(_context, configEntry, PropertyManager.MsDSReplAuthenticationMode));
+ }
+ return _cachedSecurityLevel;
+ }
+
+ public void SetSecurityLevel(ReplicationSecurityLevel securityLevel)
+ {
+ CheckIfDisposed();
+ if (securityLevel < ReplicationSecurityLevel.NegotiatePassThrough || securityLevel > ReplicationSecurityLevel.MutualAuthentication)
+ {
+ throw new InvalidEnumArgumentException("securityLevel", (int)securityLevel, typeof(ReplicationSecurityLevel));
+ }
+
+ try
+ {
+ DirectoryEntry configEntry = _directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.ConfigurationNamingContext);
+ configEntry.Properties[PropertyManager.MsDSReplAuthenticationMode].Value = (int)securityLevel;
+ configEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+
+ // invalidate the cached entry
+ _cachedSecurityLevel = (ReplicationSecurityLevel)(-1);
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ #endregion public methods
+
+ #region public properties
+
+ public string Name
+ {
+ get
+ {
+ CheckIfDisposed();
+ return _configSetName;
+ }
+ }
+
+ public ReadOnlySiteCollection Sites
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedSites == null)
+ {
+ _cachedSites = new ReadOnlySiteCollection(GetSites());
+ }
+ return _cachedSites;
+ }
+ }
+
+ public AdamInstanceCollection AdamInstances
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedADAMInstances == null)
+ {
+ _cachedADAMInstances = FindAllAdamInstances();
+ }
+ return _cachedADAMInstances;
+ }
+ }
+
+ public ApplicationPartitionCollection ApplicationPartitions
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedApplicationPartitions == null)
+ {
+ _cachedApplicationPartitions = new ApplicationPartitionCollection(GetApplicationPartitions());
+ }
+ return _cachedApplicationPartitions;
+ }
+ }
+
+ public ActiveDirectorySchema Schema
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedSchema == null)
+ {
+ try
+ {
+ _cachedSchema = new ActiveDirectorySchema(_context, _directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.SchemaNamingContext));
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ return _cachedSchema;
+ }
+ }
+
+ public AdamInstance SchemaRoleOwner
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedSchemaRoleOwner == null)
+ {
+ _cachedSchemaRoleOwner = GetRoleOwner(AdamRole.SchemaRole);
+ }
+ return _cachedSchemaRoleOwner;
+ }
+ }
+
+ public AdamInstance NamingRoleOwner
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedNamingRoleOwner == null)
+ {
+ _cachedNamingRoleOwner = GetRoleOwner(AdamRole.NamingRole);
+ }
+ return _cachedNamingRoleOwner;
+ }
+ }
+
+ #endregion public properties
+
+ #region private methods
+
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ private static DirectoryEntry GetSearchRootEntry(Forest forest)
+ {
+ DirectoryEntry rootEntry;
+ DirectoryContext forestContext = forest.GetDirectoryContext();
+ bool isServer = false;
+ bool isGC = false;
+ AuthenticationTypes authType = Utils.DefaultAuthType;
+
+ if (forestContext.ContextType == DirectoryContextType.DirectoryServer)
+ {
+ //
+ // the forest object was created by specifying a server name
+ // so we will stick to that server for the search. We need to determine
+ // whether or not the server is a DC or GC
+ //
+ isServer = true;
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(forestContext, WellKnownDN.RootDSE);
+ string isGCReady = (string)PropertyManager.GetPropertyValue(forestContext, rootDSE, PropertyManager.IsGlobalCatalogReady);
+ isGC = (Utils.Compare(isGCReady, "TRUE") == 0);
+ }
+
+ if (isServer)
+ {
+ if (DirectoryContext.ServerBindSupported)
+ {
+ authType |= AuthenticationTypes.ServerBind;
+ }
+ if (isGC)
+ {
+ rootEntry = new DirectoryEntry("GC://" + forestContext.GetServerName(), forestContext.UserName, forestContext.Password, authType);
+ }
+ else
+ {
+ rootEntry = new DirectoryEntry("LDAP://" + forestContext.GetServerName(), forestContext.UserName, forestContext.Password, authType);
+ }
+ }
+ else
+ {
+ // need to find any GC in the forest
+ rootEntry = new DirectoryEntry("GC://" + forest.Name, forestContext.UserName, forestContext.Password, authType);
+ }
+
+ return rootEntry;
+ }
+
+ internal static AdamInstance FindAnyAdamInstance(DirectoryContext context)
+ {
+ if (context.ContextType != DirectoryContextType.ConfigurationSet)
+ {
+ // assuming it's an ADAM Instance
+ // check that it is an ADAM server only (not AD)
+ DirectoryEntryManager directoryEntryMgr = new DirectoryEntryManager(context);
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+
+ if (!Utils.CheckCapability(rootDSE, Capability.ActiveDirectoryApplicationMode))
+ {
+ directoryEntryMgr.RemoveIfExists(directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.RootDSE));
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeServerORConfigSet), "context");
+ }
+
+ string dnsHostName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName);
+
+ return new AdamInstance(context, dnsHostName, directoryEntryMgr);
+ }
+
+ // Now this is the case where context is a Config Set
+ // Here we need to search for the service connection points in the forest
+ // (if the forest object was created by specifying the server, we stick to that, else search in a GC)
+ DirectoryEntry rootEntry = GetSearchRootEntry(Forest.GetCurrentForest());
+ ArrayList adamInstanceNames = new ArrayList();
+
+ try
+ {
+ string entryName = (string)rootEntry.Properties["distinguishedName"].Value;
+
+ // Search for computer "serviceConnectionObjects" where the keywords attribute
+ // contains the specified keyword
+ // set up the searcher object
+
+ // build the filter
+ StringBuilder str = new StringBuilder(15);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=serviceConnectionPoint)");
+ str.Append("(");
+ str.Append(PropertyManager.Keywords);
+ str.Append("=1.2.840.113556.1.4.1851)(");
+ str.Append(PropertyManager.Keywords);
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(context.Name)); // target = config set name
+ str.Append("))");
+
+ string filter = str.ToString();
+ string[] propertiesToLoad = new string[1];
+
+ propertiesToLoad[0] = PropertyManager.ServiceBindingInformation;
+
+ ADSearcher searcher = new ADSearcher(rootEntry, filter, propertiesToLoad, SearchScope.Subtree, false /*not paged search*/, false /*no cached results*/);
+ SearchResultCollection resCol = searcher.FindAll();
+
+ try
+ {
+ foreach (SearchResult res in resCol)
+ {
+ // the binding info contains two values
+ // "ldap://hostname:ldapport"
+ // and "ldaps://hostname:sslport"
+ // we need the "hostname:ldapport" value
+ string prefix = "ldap://";
+
+ foreach (string bindingInfo in res.Properties[PropertyManager.ServiceBindingInformation])
+ {
+ if ((bindingInfo.Length > prefix.Length) && (String.Compare(bindingInfo.Substring(0, prefix.Length), prefix, StringComparison.OrdinalIgnoreCase) == 0))
+ {
+ adamInstanceNames.Add(bindingInfo.Substring(prefix.Length));
+ }
+ }
+ }
+ }
+ finally
+ {
+ resCol.Dispose();
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ rootEntry.Dispose();
+ }
+
+ //
+ // we have all the adam instance names in teh form of server:port from the scp
+ // now we need to find one that is alive
+ //
+ return FindAliveAdamInstance(null, context, adamInstanceNames);
+ }
+
+ internal static AdamInstance FindOneAdamInstance(DirectoryContext context, string partitionName, string siteName)
+ {
+ return FindOneAdamInstance(null, context, partitionName, siteName);
+ }
+
+ internal static AdamInstance FindOneAdamInstance(string configSetName, DirectoryContext context, string partitionName, string siteName)
+ {
+ // can expect valid context (non-null)
+ if (partitionName != null && partitionName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partitionName");
+ }
+
+ if (siteName != null && siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ ArrayList ntdsaNames = Utils.GetReplicaList(context, partitionName, siteName, false /* isDefaultNC */, true /* isADAM */, false /* mustBeGC */);
+
+ if (ntdsaNames.Count < 1)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ADAMInstanceNotFound), typeof(AdamInstance), null);
+ }
+
+ return FindAliveAdamInstance(configSetName, context, ntdsaNames);
+ }
+
+ internal static AdamInstanceCollection FindAdamInstances(DirectoryContext context, string partitionName, string siteName)
+ {
+ // can expect valid context (non-null)
+ if (partitionName != null && partitionName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partitionName");
+ }
+
+ if (siteName != null && siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ ArrayList adamInstanceList = new ArrayList();
+
+ foreach (string adamInstanceName in Utils.GetReplicaList(context, partitionName, siteName, false /* isDefaultNC */, true /* isADAM */, false /* mustBeGC */))
+ {
+ DirectoryContext adamInstContext = Utils.GetNewDirectoryContext(adamInstanceName, DirectoryContextType.DirectoryServer, context);
+ adamInstanceList.Add(new AdamInstance(adamInstContext, adamInstanceName));
+ }
+
+ return new AdamInstanceCollection(adamInstanceList);
+ }
+
+ //
+ // The input to this function is a list of adam instance names in the form server:port
+ // This function tries to bind to each of the instances in this list sequentially until one of the following occurs:
+ // 1. An ADAM instance responds to an ldap_bind - we return an ADAMInstance object for that adam instance
+ // 2. We exceed the timeout duration - we return an ActiveDirectoryObjectNotFoundException
+ //
+ internal static AdamInstance FindAliveAdamInstance(string configSetName, DirectoryContext context, ArrayList adamInstanceNames)
+ {
+ bool foundAliveADAMInstance = false;
+ AdamInstance adamInstance = null;
+
+ // record the start time so that we can determine if the timeout duration has been exceeded or not
+ DateTime startTime = DateTime.UtcNow;
+
+ // loop through each adam instance and try to bind to the rootdse
+ foreach (string adamInstanceName in adamInstanceNames)
+ {
+ DirectoryContext adamInstContext = Utils.GetNewDirectoryContext(adamInstanceName, DirectoryContextType.DirectoryServer, context);
+ DirectoryEntryManager directoryEntryMgr = new DirectoryEntryManager(adamInstContext);
+ DirectoryEntry tempRootEntry = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+
+ try
+ {
+ tempRootEntry.Bind(true);
+ adamInstance = new AdamInstance(adamInstContext, adamInstanceName, directoryEntryMgr, true /* nameIncludesPort */);
+ foundAliveADAMInstance = true;
+ }
+ catch (COMException e)
+ {
+ // if this is server down /server busy / server unavailable / timeout exception we should just eat this up and try the next one
+ if ((e.ErrorCode == unchecked((int)0x8007203a)) ||
+ (e.ErrorCode == unchecked((int)0x8007200e)) ||
+ (e.ErrorCode == unchecked((int)0x8007200f)) ||
+ (e.ErrorCode == unchecked((int)0x800705b4)))
+ {
+ // if we are passed the timeout period, we should throw, else do nothing
+ if (DateTime.UtcNow.Subtract(startTime) > s_locationTimeout)
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, (configSetName != null) ? configSetName : context.Name), typeof(AdamInstance), null);
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (foundAliveADAMInstance)
+ {
+ return adamInstance;
+ }
+ }
+
+ // if we reach here, we haven't found an adam instance
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ADAMInstanceNotFoundInConfigSet, (configSetName != null) ? configSetName : context.Name), typeof(AdamInstance), null);
+ }
+
+ /// <returns>Returns a DomainController object for the DC that holds the the specified FSMO role</returns>
+ private AdamInstance GetRoleOwner(AdamRole role)
+ {
+ DirectoryEntry entry = null;
+
+ string adamInstName = null;
+ try
+ {
+ switch (role)
+ {
+ case AdamRole.SchemaRole:
+ {
+ entry = _directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.SchemaNamingContext);
+ break;
+ }
+
+ case AdamRole.NamingRole:
+ {
+ entry = _directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.PartitionsContainer);
+ break;
+ }
+
+ default:
+ // should not happen since we are calling this only internally
+ Debug.Assert(false, "ConfigurationSet.GetRoleOwner: Invalid role type.");
+ break;
+ }
+ entry.RefreshCache();
+ adamInstName = Utils.GetAdamDnsHostNameFromNTDSA(_context, (string)PropertyManager.GetPropertyValue(_context, entry, PropertyManager.FsmoRoleOwner));
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ finally
+ {
+ if (entry != null)
+ {
+ entry.Dispose();
+ }
+ }
+
+ // create a new context object for the adam instance passing on the
+ // credentials from the context
+ DirectoryContext adamInstContext = Utils.GetNewDirectoryContext(adamInstName, DirectoryContextType.DirectoryServer, _context);
+
+ return new AdamInstance(adamInstContext, adamInstName);
+ }
+
+ private ArrayList GetSites()
+ {
+ ArrayList sites = new ArrayList();
+ DirectoryEntry sitesEntry = _directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.SitesContainer);
+
+ // search for all the "site" objects
+ // (one-level search is good enough)
+ // setup the directory searcher object
+ string filter = "(" + PropertyManager.ObjectCategory + "=site)";
+ string[] propertiesToLoad = new string[1];
+
+ propertiesToLoad[0] = PropertyManager.Cn;
+
+ ADSearcher searcher = new ADSearcher(sitesEntry, filter, propertiesToLoad, SearchScope.OneLevel);
+ SearchResultCollection resCol = null;
+
+ try
+ {
+ resCol = searcher.FindAll();
+
+ foreach (SearchResult res in resCol)
+ {
+ // an existing site
+ sites.Add(new ActiveDirectorySite(_context, (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.Cn), true));
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ finally
+ {
+ if (resCol != null)
+ {
+ // call dispose on search result collection
+ resCol.Dispose();
+ }
+ }
+ return sites;
+ }
+
+ private ArrayList GetApplicationPartitions()
+ {
+ ArrayList appNCs = new ArrayList();
+ DirectoryEntry rootDSE = _directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ DirectoryEntry partitionsEntry = _directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.PartitionsContainer);
+
+ // search for all the "crossRef" objects that have the
+ // ADS_SYSTEMFLAG_CR_NTDS_NC set and the SYSTEMFLAG_CR_NTDS_DOMAIN flag not set
+ // (one-level search is good enough)
+ // setup the directory searcher object
+
+ // build the filter
+ StringBuilder str = new StringBuilder(100);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=crossRef)(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsNC);
+ str.Append(")(!(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.803:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsDomain);
+ str.Append(")))");
+
+ string filter = str.ToString();
+ string[] propertiesToLoad = new string[2];
+ propertiesToLoad[0] = PropertyManager.NCName;
+ propertiesToLoad[1] = PropertyManager.MsDSNCReplicaLocations;
+
+ ADSearcher searcher = new ADSearcher(partitionsEntry, filter, propertiesToLoad, SearchScope.OneLevel);
+ SearchResultCollection resCol = null;
+
+ try
+ {
+ resCol = searcher.FindAll();
+
+ string schemaNamingContext = (string)PropertyManager.GetPropertyValue(_context, rootDSE, PropertyManager.SchemaNamingContext);
+ string configurationNamingContext = (string)PropertyManager.GetPropertyValue(_context, rootDSE, PropertyManager.ConfigurationNamingContext);
+
+ foreach (SearchResult res in resCol)
+ {
+ // add the name of the appNC only if it is not
+ // the Schema or Configuration partition
+ string nCName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.NCName);
+
+ if ((!(nCName.Equals(schemaNamingContext))) && (!(nCName.Equals(configurationNamingContext))))
+ {
+ ResultPropertyValueCollection replicaLocations = res.Properties[PropertyManager.MsDSNCReplicaLocations];
+ if (replicaLocations.Count > 0)
+ {
+ string replicaName = Utils.GetAdamDnsHostNameFromNTDSA(_context, (string)replicaLocations[Utils.GetRandomIndex(replicaLocations.Count)]);
+ DirectoryContext appNCContext = Utils.GetNewDirectoryContext(replicaName, DirectoryContextType.DirectoryServer, _context);
+ appNCs.Add(new ApplicationPartition(appNCContext, nCName, null, ApplicationPartitionType.ADAMApplicationPartition, new DirectoryEntryManager(appNCContext)));
+ }
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ finally
+ {
+ if (resCol != null)
+ {
+ // call dispose on search result collection
+ resCol.Dispose();
+ }
+ }
+ return appNCs;
+ }
+
+ private void CheckIfDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryContext.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryContext.cs
new file mode 100644
index 0000000000..6bc6c64bbf
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryContext.cs
@@ -0,0 +1,875 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Net;
+ using System.Globalization;
+ using System.Security.Principal;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using System.ComponentModel;
+ using System.Text;
+ using System.Security.Permissions;
+ using System.IO;
+
+ public enum DirectoryContextType
+ {
+ Domain = 0,
+ Forest = 1,
+ DirectoryServer = 2,
+ ConfigurationSet = 3,
+ ApplicationPartition = 4
+ }
+
+ public class DirectoryContext
+ {
+ private string _name = null;
+ private DirectoryContextType _contextType;
+ private NetworkCredential _credential = null;
+ internal string serverName = null;
+ internal bool usernameIsNull = false;
+ internal bool passwordIsNull = false;
+ private bool _validated = false;
+ private bool _contextIsValid = false;
+
+ private static bool s_platformSupported;
+ private static bool s_serverBindSupported;
+ private static bool s_dnsgetdcSupported;
+ private static bool s_w2k;
+
+ internal static LoadLibrarySafeHandle ADHandle;
+ internal static LoadLibrarySafeHandle ADAMHandle;
+
+ #region constructors
+
+ [EnvironmentPermission(SecurityAction.Assert, Unrestricted = true)]
+ static DirectoryContext()
+ {
+ //
+ // Everything supported until proven otherwise
+ //
+ s_platformSupported = true;
+ s_serverBindSupported = true;
+ s_dnsgetdcSupported = true;
+ s_w2k = false;
+
+ //
+ // S.DS.AD only supported on W2K above
+ //
+ OperatingSystem os = Environment.OSVersion;
+
+ if (os.Platform == PlatformID.Win32NT &&
+ os.Version.Major >= 5)
+ {
+ if (os.Version.Major == 5 && os.Version.Minor == 0)
+ {
+ //
+ // This is W2K: DsGetDcOpen/Next/Close not supported
+ //
+ s_w2k = true;
+ s_dnsgetdcSupported = false;
+
+ //
+ // Now get the service pack information as well to check if ADS_SERVER_BIND
+ // is supported (Could not have used OSVersionInfoEx earlier itself as it is not
+ // supported on all platforms)
+ //
+ OSVersionInfoEx osviex = new OSVersionInfoEx();
+ bool result = NativeMethods.GetVersionEx(osviex);
+ if (!result)
+ {
+ int errorCode = NativeMethods.GetLastError();
+ Debug.Fail(string.Format(CultureInfo.InvariantCulture, "NativeMethods.GetVersionEx (with OSVERSIONINFOEX) failed with error code {0}.", errorCode));
+ throw new SystemException(Res.GetString(Res.VersionFailure, errorCode)); ;
+ }
+
+ if (osviex.servicePackMajor < 3)
+ {
+ //
+ // ADS_SERVER_BIND is not supported on platforms prior to W2K SP3
+ //
+ s_serverBindSupported = false;
+ }
+ }
+
+ // load ntdsapi.dll for AD and ADAM
+ GetLibraryHandle();
+ }
+ else
+ {
+ //
+ // S.DS.AD does not support this platform (< 5.0)
+ //
+ s_platformSupported = false;
+ s_serverBindSupported = false;
+ s_dnsgetdcSupported = false;
+ }
+ }
+
+ internal static bool ServerBindSupported
+ {
+ get
+ {
+ return s_serverBindSupported;
+ }
+ }
+
+ internal static bool DnsgetdcSupported
+ {
+ get
+ {
+ return s_dnsgetdcSupported;
+ }
+ }
+
+ // Internal Constructors
+ internal void InitializeDirectoryContext(DirectoryContextType contextType, string name, string username, string password)
+ {
+ //
+ // Check if the platform is currently supported or not
+ //
+ if (!s_platformSupported)
+ {
+ throw new PlatformNotSupportedException(Res.GetString(Res.SupportedPlatforms));
+ }
+
+ _name = name;
+ _contextType = contextType;
+ _credential = new NetworkCredential(username, password);
+ if (username == null)
+ {
+ usernameIsNull = true;
+ }
+ if (password == null)
+ {
+ passwordIsNull = true;
+ }
+ }
+
+ internal DirectoryContext(DirectoryContextType contextType, string name, DirectoryContext context)
+ {
+ _name = name;
+ _contextType = contextType;
+
+ if (context != null)
+ {
+ _credential = context.Credential;
+ this.usernameIsNull = context.usernameIsNull;
+ this.passwordIsNull = context.passwordIsNull;
+ }
+ else
+ {
+ _credential = new NetworkCredential(null, "", null);
+ this.usernameIsNull = true;
+ this.passwordIsNull = true;
+ }
+ }
+
+ internal DirectoryContext(DirectoryContext context)
+ {
+ _name = context.Name;
+ _contextType = context.ContextType;
+ _credential = context.Credential;
+ this.usernameIsNull = context.usernameIsNull;
+ this.passwordIsNull = context.passwordIsNull;
+ if (context.ContextType != DirectoryContextType.ConfigurationSet)
+ {
+ //
+ // only for configurationset, we select a server, so we should not copy over that
+ // information, for all other types, this is either the same as name of the target or if the target is netbios name
+ // (for domain and forest) it could be the dns name. We should copy over this information.
+ //
+ this.serverName = context.serverName;
+ }
+ }
+ #endregion constructors
+
+ #region public constructors
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectoryContext(DirectoryContextType contextType)
+ {
+ //
+ // this constructor can only be called for DirectoryContextType.Forest or DirectoryContextType.Domain
+ // since all other types require the name to be specified
+ //
+ if (contextType != DirectoryContextType.Domain && contextType != DirectoryContextType.Forest)
+ {
+ throw new ArgumentException(Res.GetString(Res.OnlyDomainOrForest), "contextType");
+ }
+
+ InitializeDirectoryContext(contextType, null, null, null);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectoryContext(DirectoryContextType contextType, string name)
+ {
+ if (contextType < DirectoryContextType.Domain || contextType > DirectoryContextType.ApplicationPartition)
+ {
+ throw new InvalidEnumArgumentException("contextType", (int)contextType, typeof(DirectoryContextType));
+ }
+
+ if (name == null)
+ {
+ throw new ArgumentNullException("name");
+ }
+
+ if (name.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "name");
+ }
+
+ InitializeDirectoryContext(contextType, name, null, null);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectoryContext(DirectoryContextType contextType, string username, string password)
+ {
+ //
+ // this constructor can only be called for DirectoryContextType.Forest or DirectoryContextType.Domain
+ // since all other types require the name to be specified
+ //
+ if (contextType != DirectoryContextType.Domain && contextType != DirectoryContextType.Forest)
+ {
+ throw new ArgumentException(Res.GetString(Res.OnlyDomainOrForest), "contextType");
+ }
+
+ InitializeDirectoryContext(contextType, null, username, password);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectoryContext(DirectoryContextType contextType, string name, string username, string password)
+ {
+ if (contextType < DirectoryContextType.Domain || contextType > DirectoryContextType.ApplicationPartition)
+ {
+ throw new InvalidEnumArgumentException("contextType", (int)contextType, typeof(DirectoryContextType));
+ }
+
+ if (name == null)
+ {
+ throw new ArgumentNullException("name");
+ }
+
+ if (name.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "name");
+ }
+
+ InitializeDirectoryContext(contextType, name, username, password);
+ }
+
+ #endregion public methods
+
+ #region public properties
+
+ public string Name
+ {
+ get
+ {
+ return _name;
+ }
+ }
+
+ public string UserName
+ {
+ get
+ {
+ if (usernameIsNull)
+ {
+ return null;
+ }
+ else
+ {
+ return _credential.UserName;
+ }
+ }
+ }
+
+ internal string Password
+ {
+ [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ get
+ {
+ if (passwordIsNull)
+ {
+ return null;
+ }
+ else
+ {
+ return _credential.Password;
+ }
+ }
+ }
+
+ public DirectoryContextType ContextType
+ {
+ get
+ {
+ return _contextType;
+ }
+ }
+
+ internal NetworkCredential Credential
+ {
+ get
+ {
+ return _credential;
+ }
+ }
+
+ #endregion public properties
+
+ #region private methods
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal static bool IsContextValid(DirectoryContext context, DirectoryContextType contextType)
+ {
+ bool contextIsValid = false;
+
+ if ((contextType == DirectoryContextType.Domain) || ((contextType == DirectoryContextType.Forest) && (context.Name == null)))
+ {
+ string tmpTarget = context.Name;
+
+ if (tmpTarget == null)
+ {
+ // GetLoggedOnDomain returns the dns name of the logged on user's domain
+ context.serverName = GetLoggedOnDomain();
+ contextIsValid = true;
+ }
+ else
+ {
+ // check for domain
+ int errorCode = 0;
+ DomainControllerInfo domainControllerInfo;
+ errorCode = Locator.DsGetDcNameWrapper(null, tmpTarget, null, (long)PrivateLocatorFlags.DirectoryServicesRequired, out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ // try with force rediscovery
+
+ errorCode = Locator.DsGetDcNameWrapper(null, tmpTarget, null, (long)PrivateLocatorFlags.DirectoryServicesRequired | (long)LocatorOptions.ForceRediscovery, out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ contextIsValid = false;
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+ else
+ {
+ Debug.Assert(domainControllerInfo != null);
+ Debug.Assert(domainControllerInfo.DomainName != null);
+ context.serverName = domainControllerInfo.DomainName;
+ contextIsValid = true;
+ }
+ }
+ else if (errorCode == NativeMethods.ERROR_INVALID_DOMAIN_NAME_FORMAT)
+ {
+ // we can get this error if the target it server:port (not a valid domain)
+ contextIsValid = false;
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+ else
+ {
+ Debug.Assert(domainControllerInfo != null);
+ Debug.Assert(domainControllerInfo.DomainName != null);
+ context.serverName = domainControllerInfo.DomainName;
+ contextIsValid = true;
+ }
+ }
+ }
+ else if (contextType == DirectoryContextType.Forest)
+ {
+ Debug.Assert(context.Name != null);
+
+ // check for forest
+ int errorCode = 0;
+ DomainControllerInfo domainControllerInfo;
+ errorCode = Locator.DsGetDcNameWrapper(null, context.Name, null, (long)(PrivateLocatorFlags.GCRequired | PrivateLocatorFlags.DirectoryServicesRequired), out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ // try with force rediscovery
+
+ errorCode = Locator.DsGetDcNameWrapper(null, context.Name, null, (long)((PrivateLocatorFlags.GCRequired | PrivateLocatorFlags.DirectoryServicesRequired)) | (long)LocatorOptions.ForceRediscovery, out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ contextIsValid = false;
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+ else
+ {
+ Debug.Assert(domainControllerInfo != null);
+ Debug.Assert(domainControllerInfo.DnsForestName != null);
+ context.serverName = domainControllerInfo.DnsForestName;
+ contextIsValid = true;
+ }
+ }
+ else if (errorCode == NativeMethods.ERROR_INVALID_DOMAIN_NAME_FORMAT)
+ {
+ // we can get this error if the target it server:port (not a valid forest)
+ contextIsValid = false;
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+ else
+ {
+ Debug.Assert(domainControllerInfo != null);
+ Debug.Assert(domainControllerInfo.DnsForestName != null);
+ context.serverName = domainControllerInfo.DnsForestName;
+ contextIsValid = true;
+ }
+ }
+ else if (contextType == DirectoryContextType.ApplicationPartition)
+ {
+ Debug.Assert(context.Name != null);
+
+ // check for application partition
+ int errorCode = 0;
+ DomainControllerInfo domainControllerInfo;
+ errorCode = Locator.DsGetDcNameWrapper(null, context.Name, null, (long)PrivateLocatorFlags.OnlyLDAPNeeded, out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ // try with force rediscovery
+
+ errorCode = Locator.DsGetDcNameWrapper(null, context.Name, null, (long)PrivateLocatorFlags.OnlyLDAPNeeded | (long)LocatorOptions.ForceRediscovery, out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ contextIsValid = false;
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+ else
+ {
+ contextIsValid = true;
+ }
+ }
+ else if (errorCode == NativeMethods.ERROR_INVALID_DOMAIN_NAME_FORMAT)
+ {
+ // we can get this error if the target it server:port (not a valid application partition)
+ contextIsValid = false;
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+ else
+ {
+ contextIsValid = true;
+ }
+ }
+ else if (contextType == DirectoryContextType.DirectoryServer)
+ {
+ //
+ // if the servername contains a port number, then remove that
+ //
+ string tempServerName = null;
+ string portNumber;
+ tempServerName = Utils.SplitServerNameAndPortNumber(context.Name, out portNumber);
+
+ //
+ // this will validate that the name specified in the context is truely the name of a machine (and not of a domain)
+ //
+ DirectoryEntry de = new DirectoryEntry("WinNT://" + tempServerName + ",computer", context.UserName, context.Password, Utils.DefaultAuthType);
+ try
+ {
+ de.Bind(true);
+ contextIsValid = true;
+ }
+ catch (COMException e)
+ {
+ if ((e.ErrorCode == unchecked((int)0x80070035)) || (e.ErrorCode == unchecked((int)0x80070033)) || (e.ErrorCode == unchecked((int)0x80005000)))
+ {
+ // if this returns bad network path
+ contextIsValid = false;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ finally
+ {
+ de.Dispose();
+ }
+ }
+ else
+ {
+ // no special validation for ConfigurationSet
+ contextIsValid = true;
+ }
+
+ return contextIsValid;
+ }
+
+ internal bool isRootDomain()
+ {
+ if (_contextType != DirectoryContextType.Forest)
+ return false;
+
+ if (!_validated)
+ {
+ _contextIsValid = IsContextValid(this, DirectoryContextType.Forest);
+ _validated = true;
+ }
+ return _contextIsValid;
+ }
+
+ internal bool isDomain()
+ {
+ if (_contextType != DirectoryContextType.Domain)
+ return false;
+
+ if (!_validated)
+ {
+ _contextIsValid = IsContextValid(this, DirectoryContextType.Domain);
+ _validated = true;
+ }
+ return _contextIsValid;
+ }
+
+ internal bool isNdnc()
+ {
+ if (_contextType != DirectoryContextType.ApplicationPartition)
+ return false;
+
+ if (!_validated)
+ {
+ _contextIsValid = IsContextValid(this, DirectoryContextType.ApplicationPartition);
+ _validated = true;
+ }
+ return _contextIsValid;
+ }
+
+ internal bool isServer()
+ {
+ if (_contextType != DirectoryContextType.DirectoryServer)
+ return false;
+
+ if (!_validated)
+ {
+ if (s_w2k)
+ {
+ //
+ // On W2K client we need to validate that it is not a domain or application partition
+ //
+ _contextIsValid = (IsContextValid(this, DirectoryContextType.DirectoryServer) &&
+ (!(IsContextValid(this, DirectoryContextType.Domain))) &&
+ (!(IsContextValid(this, DirectoryContextType.ApplicationPartition))));
+ }
+ else
+ {
+ _contextIsValid = IsContextValid(this, DirectoryContextType.DirectoryServer);
+ }
+ _validated = true;
+ }
+ return _contextIsValid;
+ }
+
+ internal bool isADAMConfigSet()
+ {
+ if (_contextType != DirectoryContextType.ConfigurationSet)
+ return false;
+
+ if (!_validated)
+ {
+ _contextIsValid = IsContextValid(this, DirectoryContextType.ConfigurationSet);
+ _validated = true;
+ }
+ return _contextIsValid;
+ }
+
+ //
+ // this method is called when the forest name is explicitly specified
+ // and we want to check if that matches the current logged on forest
+ //
+ internal bool isCurrentForest()
+ {
+ bool result = false;
+
+ Debug.Assert(_name != null);
+ DomainControllerInfo domainControllerInfo = Locator.GetDomainControllerInfo(null, _name, null, (long)(PrivateLocatorFlags.DirectoryServicesRequired | PrivateLocatorFlags.ReturnDNSName));
+
+ DomainControllerInfo currentDomainControllerInfo;
+ string loggedOnDomain = GetLoggedOnDomain();
+
+ int errorCode = Locator.DsGetDcNameWrapper(null, loggedOnDomain, null, (long)(PrivateLocatorFlags.DirectoryServicesRequired | PrivateLocatorFlags.ReturnDNSName), out currentDomainControllerInfo);
+
+ if (errorCode == 0)
+ {
+ Debug.Assert(domainControllerInfo.DnsForestName != null);
+ Debug.Assert(currentDomainControllerInfo.DnsForestName != null);
+
+ result = (Utils.Compare(domainControllerInfo.DnsForestName, currentDomainControllerInfo.DnsForestName) == 0);
+ }
+ //
+ // if there is no forest associated with the logged on domain, then we return false
+ //
+ else if (errorCode != NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+
+ return result;
+ }
+
+ internal bool useServerBind()
+ {
+ return ((ContextType == DirectoryContextType.DirectoryServer) || (ContextType == DirectoryContextType.ConfigurationSet));
+ }
+
+ internal string GetServerName()
+ {
+ if (serverName == null)
+ {
+ switch (_contextType)
+ {
+ case DirectoryContextType.ConfigurationSet:
+ {
+ AdamInstance adamInst = ConfigurationSet.FindAnyAdamInstance(this);
+ try
+ {
+ serverName = adamInst.Name;
+ }
+ finally
+ {
+ adamInst.Dispose();
+ }
+ break;
+ }
+ case DirectoryContextType.Domain:
+ case DirectoryContextType.Forest:
+ {
+ //
+ // if the target is not specified OR
+ // if the forest name was explicitly specified and the forest is the same as the current forest
+ // we want to find a DC in the current domain
+ //
+ if ((_name == null) || ((_contextType == DirectoryContextType.Forest) && (isCurrentForest())))
+ {
+ serverName = GetLoggedOnDomain();
+ }
+ else
+ {
+ serverName = GetDnsDomainName(_name);
+ }
+ break;
+ }
+ case DirectoryContextType.ApplicationPartition:
+ {
+ // if this is an appNC the target should not be null
+ Debug.Assert(_name != null);
+
+ serverName = _name;
+ break;
+ }
+ case DirectoryContextType.DirectoryServer:
+ {
+ // this should not happen (We should have checks for this earlier itself)
+ Debug.Assert(_name != null);
+ serverName = _name;
+ break;
+ }
+ default:
+ {
+ Debug.Fail("DirectoryContext::GetServerName - Unknown contextType");
+ break;
+ }
+ }
+ }
+
+ return serverName;
+ }
+
+ internal static string GetLoggedOnDomain()
+ {
+ string domainName = null;
+
+ NegotiateCallerNameRequest requestBuffer = new NegotiateCallerNameRequest();
+ int requestBufferLength = (int)Marshal.SizeOf(requestBuffer);
+
+ IntPtr pResponseBuffer = IntPtr.Zero;
+ NegotiateCallerNameResponse responseBuffer = new NegotiateCallerNameResponse();
+ int responseBufferLength;
+ int protocolStatus;
+ int result;
+
+ LsaLogonProcessSafeHandle lsaHandle;
+
+ //
+ // since we are using safe handles, we don't need to explicitly call NativeMethods.LsaDeregisterLogonProcess(lsaHandle)
+ //
+ result = NativeMethods.LsaConnectUntrusted(out lsaHandle);
+
+ if (result == 0)
+ {
+ //
+ // initialize the request buffer
+ //
+ requestBuffer.messageType = NativeMethods.NegGetCallerName;
+
+ result = NativeMethods.LsaCallAuthenticationPackage(lsaHandle, 0, requestBuffer, requestBufferLength, out pResponseBuffer, out responseBufferLength, out protocolStatus);
+
+ try
+ {
+ if (result == 0 && protocolStatus == 0)
+ {
+ Marshal.PtrToStructure(pResponseBuffer, responseBuffer);
+
+ //
+ // callerName is of the form domain\username
+ //
+ Debug.Assert((responseBuffer.callerName != null), "NativeMethods.LsaCallAuthenticationPackage returned null callerName.");
+ int index = responseBuffer.callerName.IndexOf('\\');
+ Debug.Assert((index != -1), "NativeMethods.LsaCallAuthenticationPackage returned callerName not in domain\\username format.");
+ domainName = responseBuffer.callerName.Substring(0, index);
+ }
+ else
+ {
+ if (result == NativeMethods.STATUS_QUOTA_EXCEEDED)
+ {
+ throw new OutOfMemoryException();
+ }
+ else if ((result == 0) && (UnsafeNativeMethods.LsaNtStatusToWinError(protocolStatus) == NativeMethods.ERROR_NO_SUCH_LOGON_SESSION))
+ {
+ // If this is a directory user, extract domain info from username
+ if (!Utils.IsSamUser())
+ {
+ WindowsIdentity identity = WindowsIdentity.GetCurrent();
+
+ int index = identity.Name.IndexOf('\\');
+ Debug.Assert(index != -1);
+ domainName = identity.Name.Substring(0, index);
+ }
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(UnsafeNativeMethods.LsaNtStatusToWinError((result != 0) ? result : protocolStatus));
+ }
+ }
+ }
+ finally
+ {
+ if (pResponseBuffer != IntPtr.Zero)
+ {
+ NativeMethods.LsaFreeReturnBuffer(pResponseBuffer);
+ }
+ }
+ }
+ else if (result == NativeMethods.STATUS_QUOTA_EXCEEDED)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(UnsafeNativeMethods.LsaNtStatusToWinError(result));
+ }
+
+ // If we're running as a local user (i.e. NT AUTHORITY\LOCAL SYSTEM, IIS APPPOOL\APPPoolIdentity, etc.),
+ // domainName will be null and we fall back to the machine's domain
+ domainName = GetDnsDomainName(domainName);
+
+ if (domainName == null)
+ {
+ //
+ // we should never get to this point here since we should have already verified that the context is valid
+ // by the time we get to this point
+ //
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ContextNotAssociatedWithDomain));
+ }
+
+ return domainName;
+ }
+
+ internal static string GetDnsDomainName(string domainName)
+ {
+ DomainControllerInfo domainControllerInfo;
+ int errorCode = 0;
+
+ //
+ // Locator.DsGetDcNameWrapper internally passes the ReturnDNSName flag when calling DsGetDcName
+ //
+ errorCode = Locator.DsGetDcNameWrapper(null, domainName, null, (long)PrivateLocatorFlags.DirectoryServicesRequired, out domainControllerInfo);
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ // try again with force rediscovery
+ errorCode = Locator.DsGetDcNameWrapper(null, domainName, null, (long)((long)PrivateLocatorFlags.DirectoryServicesRequired | (long)LocatorOptions.ForceRediscovery), out domainControllerInfo);
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ return null;
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+
+ Debug.Assert(domainControllerInfo != null);
+ Debug.Assert(domainControllerInfo.DomainName != null);
+
+ return domainControllerInfo.DomainName;
+ }
+
+ [FileIOPermission(SecurityAction.Assert, AllFiles = FileIOPermissionAccess.PathDiscovery)]
+ [EnvironmentPermission(SecurityAction.Assert, Unrestricted = true)]
+ private static void GetLibraryHandle()
+ {
+ // first get AD handle
+ string systemPath = Environment.SystemDirectory;
+ IntPtr tempHandle = UnsafeNativeMethods.LoadLibrary(systemPath + "\\ntdsapi.dll");
+ if (tempHandle == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ else
+ {
+ ADHandle = new LoadLibrarySafeHandle(tempHandle);
+ }
+
+ // not get the ADAM handle
+ // got to the windows\adam directory
+ DirectoryInfo windowsDirectory = Directory.GetParent(systemPath);
+ tempHandle = UnsafeNativeMethods.LoadLibrary(windowsDirectory.FullName + "\\ADAM\\ntdsapi.dll");
+ if (tempHandle == (IntPtr)0)
+ {
+ ADAMHandle = ADHandle;
+ }
+ else
+ {
+ ADAMHandle = new LoadLibrarySafeHandle(tempHandle);
+ }
+ }
+
+ #endregion private methods
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryEntryManager.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryEntryManager.cs
new file mode 100644
index 0000000000..a3a2afbe31
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryEntryManager.cs
@@ -0,0 +1,389 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Net;
+ using System.Collections;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.DirectoryServices;
+ using System.Runtime.InteropServices;
+ using System.Security.Permissions;
+
+ /// <summary>
+ /// Internal class that is used as a key in the hashtable
+ /// of directory entries
+ /// </summary>
+ internal class DistinguishedName
+ {
+ private Component[] _components = null;
+
+ public DistinguishedName(string dn)
+ {
+ _components = Utils.GetDNComponents(dn);
+ }
+
+ public Component[] Components
+ {
+ get
+ {
+ return _components;
+ }
+ }
+
+ public bool Equals(DistinguishedName dn)
+ {
+ bool result = true;
+ if ((dn == null) || (_components.GetLength(0) != dn.Components.GetLength(0)))
+ {
+ result = false;
+ }
+ else
+ {
+ for (int i = 0; i < _components.GetLength(0); i++)
+ {
+ if ((Utils.Compare(_components[i].Name, dn.Components[i].Name) != 0)
+ || (Utils.Compare(_components[i].Value, dn.Components[i].Value) != 0))
+ {
+ result = false;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if ((obj == null) || (!(obj is DistinguishedName)))
+ {
+ return false;
+ }
+ else
+ {
+ return Equals((DistinguishedName)obj);
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ int hashCode = 0;
+ for (int i = 0; i < _components.GetLength(0); i++)
+ {
+ hashCode = hashCode + _components[i].Name.ToUpperInvariant().GetHashCode() + _components[i].Value.ToUpperInvariant().GetHashCode();
+ }
+ return hashCode;
+ }
+
+ public override string ToString()
+ {
+ string dn = _components[0].Name + "=" + _components[0].Value;
+ for (int i = 1; i < _components.GetLength(0); i++)
+ {
+ dn = dn + "," + _components[i].Name + "=" + _components[i].Value;
+ }
+ return dn;
+ }
+ }
+
+ /// <summary>
+ /// This class manages a list of directory entries
+ /// for an object that needs to bind to several
+ /// objects in AD. This maintains a cache of directory entries
+ /// and creates a new directory entry (for a given dn) only if
+ /// it doesn't already exist
+ /// </summary>
+ internal class DirectoryEntryManager
+ {
+ private Hashtable _directoryEntries = new Hashtable();
+ private string _bindingPrefix = null;
+ private DirectoryContext _context = null;
+ private NativeComInterfaces.IAdsPathname _pathCracker = null;
+
+ internal DirectoryEntryManager(DirectoryContext context)
+ {
+ _context = context;
+ _pathCracker = (NativeComInterfaces.IAdsPathname)new NativeComInterfaces.Pathname();
+ _pathCracker.EscapedMode = NativeComInterfaces.ADS_ESCAPEDMODE_ON;
+ }
+
+ internal ICollection GetCachedDirectoryEntries()
+ {
+ return _directoryEntries.Values;
+ }
+
+ internal DirectoryEntry GetCachedDirectoryEntry(WellKnownDN dn)
+ {
+ return GetCachedDirectoryEntry(ExpandWellKnownDN(dn));
+ }
+
+ internal DirectoryEntry GetCachedDirectoryEntry(string distinguishedName)
+ {
+ // check if it's not RootDSE
+ Object dn = distinguishedName;
+
+ if ((String.Compare(distinguishedName, "rootdse", StringComparison.OrdinalIgnoreCase) != 0)
+ && (String.Compare(distinguishedName, "schema", StringComparison.OrdinalIgnoreCase) != 0))
+ {
+ dn = new DistinguishedName(distinguishedName);
+ }
+
+ if (!_directoryEntries.ContainsKey(dn))
+ {
+ // directory entry does not exist
+ // create a new one and cache it
+ DirectoryEntry de = GetNewDirectoryEntry(distinguishedName);
+ // add it to the cache
+ _directoryEntries.Add(dn, de);
+ }
+ return (DirectoryEntry)_directoryEntries[dn];
+ }
+
+ internal void RemoveIfExists(string distinguishedName)
+ {
+ // check if it's not RootDSE
+ Object dn = distinguishedName;
+
+ //
+ // NOTE: Currently only comparing against "rootdse", but in the future if we are going to
+ // remove any other entries that are not in dn format (such as schema), we need to add the
+ // special casing here.
+ //
+
+ if (String.Compare(distinguishedName, "rootdse", StringComparison.OrdinalIgnoreCase) != 0)
+ {
+ dn = new DistinguishedName(distinguishedName);
+ }
+
+ if (_directoryEntries.ContainsKey(dn))
+ {
+ DirectoryEntry tmp = (DirectoryEntry)_directoryEntries[dn];
+ if (tmp != null)
+ {
+ _directoryEntries.Remove(dn);
+ tmp.Dispose();
+ }
+ }
+ }
+
+ private DirectoryEntry GetNewDirectoryEntry(string dn)
+ {
+ if (_bindingPrefix == null)
+ {
+ _bindingPrefix = "LDAP://" + _context.GetServerName() + "/";
+ }
+
+ _pathCracker.Set(dn, NativeComInterfaces.ADS_SETTYPE_DN);
+ string escapedDN = _pathCracker.Retrieve(NativeComInterfaces.ADS_FORMAT_X500_DN);
+
+ return Bind(_bindingPrefix + escapedDN, _context.UserName, _context.Password, _context.useServerBind());
+ }
+
+ internal string ExpandWellKnownDN(WellKnownDN dn)
+ {
+ string distinguishedName = null;
+
+ switch (dn)
+ {
+ case WellKnownDN.RootDSE:
+ {
+ distinguishedName = "RootDSE";
+ break;
+ }
+ case WellKnownDN.RootDomainNamingContext:
+ {
+ DirectoryEntry rootDSE = GetCachedDirectoryEntry("RootDSE");
+
+ distinguishedName = (string)PropertyManager.GetPropertyValue(_context, rootDSE, PropertyManager.RootDomainNamingContext);
+ break;
+ }
+ case WellKnownDN.DefaultNamingContext:
+ {
+ DirectoryEntry rootDSE = GetCachedDirectoryEntry("RootDSE");
+ distinguishedName = (string)PropertyManager.GetPropertyValue(_context, rootDSE, PropertyManager.DefaultNamingContext);
+ break;
+ }
+ case WellKnownDN.SchemaNamingContext:
+ {
+ DirectoryEntry rootDSE = GetCachedDirectoryEntry("RootDSE");
+ distinguishedName = (string)PropertyManager.GetPropertyValue(_context, rootDSE, PropertyManager.SchemaNamingContext);
+ break;
+ }
+ case WellKnownDN.ConfigurationNamingContext:
+ {
+ DirectoryEntry rootDSE = GetCachedDirectoryEntry("RootDSE");
+ distinguishedName = (string)PropertyManager.GetPropertyValue(_context, rootDSE, PropertyManager.ConfigurationNamingContext);
+ break;
+ }
+ case WellKnownDN.PartitionsContainer:
+ {
+ distinguishedName = "CN=Partitions," + ExpandWellKnownDN(WellKnownDN.ConfigurationNamingContext);
+ break;
+ }
+ case WellKnownDN.SitesContainer:
+ {
+ distinguishedName = "CN=Sites," + ExpandWellKnownDN(WellKnownDN.ConfigurationNamingContext);
+ break;
+ }
+ case WellKnownDN.SystemContainer:
+ {
+ distinguishedName = "CN=System," + ExpandWellKnownDN(WellKnownDN.DefaultNamingContext);
+ break;
+ }
+ case WellKnownDN.RidManager:
+ {
+ distinguishedName = "CN=RID Manager$," + ExpandWellKnownDN(WellKnownDN.SystemContainer);
+ break;
+ }
+ case WellKnownDN.Infrastructure:
+ {
+ distinguishedName = "CN=Infrastructure," + ExpandWellKnownDN(WellKnownDN.DefaultNamingContext);
+ break;
+ }
+ default:
+ // should not happen
+ throw new InvalidEnumArgumentException("dn", (int)dn, typeof(WellKnownDN));
+ }
+ return distinguishedName;
+ }
+
+ internal static DirectoryEntry GetDirectoryEntry(DirectoryContext context, WellKnownDN dn)
+ {
+ return GetDirectoryEntry(context, ExpandWellKnownDN(context, dn));
+ }
+
+ internal static DirectoryEntry GetDirectoryEntry(DirectoryContext context, string dn)
+ {
+ string tempBindingPrefix = "LDAP://" + context.GetServerName() + "/";
+
+ NativeComInterfaces.IAdsPathname pathCracker = (NativeComInterfaces.IAdsPathname)new NativeComInterfaces.Pathname();
+ pathCracker.EscapedMode = NativeComInterfaces.ADS_ESCAPEDMODE_ON;
+ pathCracker.Set(dn, NativeComInterfaces.ADS_SETTYPE_DN);
+ string escapedDN = pathCracker.Retrieve(NativeComInterfaces.ADS_FORMAT_X500_DN);
+
+ return Bind(tempBindingPrefix + escapedDN, context.UserName, context.Password, context.useServerBind());
+ }
+
+ internal static DirectoryEntry GetDirectoryEntryInternal(DirectoryContext context, string path)
+ {
+ return Bind(path, context.UserName, context.Password, context.useServerBind());
+ }
+
+ internal static DirectoryEntry Bind(string ldapPath, string username, string password, bool useServerBind)
+ {
+ DirectoryEntry de = null;
+ AuthenticationTypes authType = Utils.DefaultAuthType;
+
+ //
+ // use ServerBind flag is the target is a server and the ServerBind option is supported
+ //
+
+ if (DirectoryContext.ServerBindSupported && useServerBind)
+ {
+ authType |= AuthenticationTypes.ServerBind;
+ }
+
+ de = new DirectoryEntry(ldapPath, username, password, authType);
+ return de;
+ }
+
+ internal static string ExpandWellKnownDN(DirectoryContext context, WellKnownDN dn)
+ {
+ string distinguishedName = null;
+
+ switch (dn)
+ {
+ case WellKnownDN.RootDSE:
+ {
+ distinguishedName = "RootDSE";
+ break;
+ }
+ case WellKnownDN.RootDomainNamingContext:
+ {
+ DirectoryEntry rootDSE = GetDirectoryEntry(context, "RootDSE");
+
+ try
+ {
+ distinguishedName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.RootDomainNamingContext);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+ break;
+ }
+ case WellKnownDN.DefaultNamingContext:
+ {
+ DirectoryEntry rootDSE = GetDirectoryEntry(context, "RootDSE");
+ try
+ {
+ distinguishedName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DefaultNamingContext);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+ break;
+ }
+ case WellKnownDN.SchemaNamingContext:
+ {
+ DirectoryEntry rootDSE = GetDirectoryEntry(context, "RootDSE");
+ try
+ {
+ distinguishedName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.SchemaNamingContext);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+ break;
+ }
+ case WellKnownDN.ConfigurationNamingContext:
+ {
+ DirectoryEntry rootDSE = GetDirectoryEntry(context, "RootDSE");
+ try
+ {
+ distinguishedName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.ConfigurationNamingContext);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+ break;
+ }
+ case WellKnownDN.PartitionsContainer:
+ {
+ distinguishedName = "CN=Partitions," + ExpandWellKnownDN(context, WellKnownDN.ConfigurationNamingContext);
+ break;
+ }
+ case WellKnownDN.SitesContainer:
+ {
+ distinguishedName = "CN=Sites," + ExpandWellKnownDN(context, WellKnownDN.ConfigurationNamingContext);
+ break;
+ }
+ case WellKnownDN.SystemContainer:
+ {
+ distinguishedName = "CN=System," + ExpandWellKnownDN(context, WellKnownDN.DefaultNamingContext);
+ break;
+ }
+ case WellKnownDN.RidManager:
+ {
+ distinguishedName = "CN=RID Manager$," + ExpandWellKnownDN(context, WellKnownDN.SystemContainer);
+ break;
+ }
+ case WellKnownDN.Infrastructure:
+ {
+ distinguishedName = "CN=Infrastructure," + ExpandWellKnownDN(context, WellKnownDN.DefaultNamingContext);
+ break;
+ }
+ default:
+ // should not happen
+ throw new InvalidEnumArgumentException("dn", (int)dn, typeof(WellKnownDN));
+ }
+ return distinguishedName;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServer.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServer.cs
new file mode 100644
index 0000000000..4c176adaaa
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServer.cs
@@ -0,0 +1,955 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public abstract class DirectoryServer : IDisposable
+ {
+ private bool _disposed = false;
+ internal DirectoryContext context = null;
+ internal string replicaName = null;
+ internal DirectoryEntryManager directoryEntryMgr = null;
+
+ // internal variables for the public properties
+ internal bool siteInfoModified = false;
+ internal string cachedSiteName = null;
+ internal string cachedSiteObjectName = null;
+ internal string cachedServerObjectName = null;
+ internal string cachedNtdsaObjectName = null;
+ internal Guid cachedNtdsaObjectGuid = Guid.Empty;
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ internal string cachedIPAddress = null;
+#pragma warning restore 0414
+ internal ReadOnlyStringCollection cachedPartitions = null;
+
+ internal const int DS_REPSYNC_ASYNCHRONOUS_OPERATION = 0x00000001;
+ internal const int DS_REPSYNC_ALL_SOURCES = 0x00000010;
+ internal const int DS_REPSYNCALL_ID_SERVERS_BY_DN = 0x00000004;
+ internal const int DS_REPL_NOTSUPPORTED = 50;
+ private const int DS_REPL_INFO_FLAG_IMPROVE_LINKED_ATTRS = 0x00000001;
+ private ReplicationConnectionCollection _inbound = null;
+ private ReplicationConnectionCollection _outbound = null;
+
+ #region constructors
+ protected DirectoryServer()
+ {
+ }
+ #endregion constructors
+
+ #region IDisposable
+ ~DirectoryServer()
+ {
+ // finalizer is called => Dispose has not been called yet.
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+
+ // Take yourself off of the Finalization queue
+ // to prevent finalization code for this object
+ // from executing a second time.
+ GC.SuppressFinalize(this);
+ }
+
+ // private Dispose method
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ // check if this is an explicit Dispose
+ // only then clean up the directory entries
+ if (disposing)
+ {
+ // dispose all directory entries
+ foreach (DirectoryEntry entry in directoryEntryMgr.GetCachedDirectoryEntries())
+ {
+ entry.Dispose();
+ }
+ }
+ _disposed = true;
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ public void MoveToAnotherSite(string siteName)
+ {
+ CheckIfDisposed();
+
+ // validate siteName
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ if (siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ // the dc is really being moved to a different site
+ if (Utils.Compare(SiteName, siteName) != 0)
+ {
+ DirectoryEntry newParentEntry = null;
+ try
+ {
+ // Bind to the target site's server container
+ // Get the distinguished name for the site
+ string parentDN = "CN=Servers,CN=" + siteName + "," + directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.SitesContainer);
+ newParentEntry = DirectoryEntryManager.GetDirectoryEntry(context, parentDN);
+
+ string serverName = (this is DomainController) ? ((DomainController)this).ServerObjectName : ((AdamInstance)this).ServerObjectName;
+
+ DirectoryEntry serverEntry = directoryEntryMgr.GetCachedDirectoryEntry(serverName);
+
+ // force binding (needed otherwise S.DS throw an exception while releasing the COM interface pointer)
+ string dn = (string)PropertyManager.GetPropertyValue(context, serverEntry, PropertyManager.DistinguishedName);
+
+ // move the object to the servers container of the target site
+ serverEntry.MoveTo(newParentEntry);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (newParentEntry != null)
+ {
+ newParentEntry.Dispose();
+ }
+ }
+
+ // remove stale cached directory entries
+ // invalidate the cached properties that get affected by this
+ siteInfoModified = true;
+ cachedSiteName = null;
+
+ if (cachedSiteObjectName != null)
+ {
+ directoryEntryMgr.RemoveIfExists(cachedSiteObjectName);
+ cachedSiteObjectName = null;
+ }
+
+ if (cachedServerObjectName != null)
+ {
+ directoryEntryMgr.RemoveIfExists(cachedServerObjectName);
+ cachedServerObjectName = null;
+ }
+
+ if (cachedNtdsaObjectName != null)
+ {
+ directoryEntryMgr.RemoveIfExists(cachedNtdsaObjectName);
+ cachedNtdsaObjectName = null;
+ }
+ }
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ CheckIfDisposed();
+ string serverName = (this is DomainController) ? ((DomainController)this).ServerObjectName : ((AdamInstance)this).ServerObjectName;
+ return DirectoryEntryManager.GetDirectoryEntry(context, serverName);
+ }
+
+ #endregion public methods
+
+ #region abstract public methods
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract void CheckReplicationConsistency();
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract ReplicationCursorCollection GetReplicationCursors(string partition);
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract ReplicationOperationInformation GetReplicationOperationInformation();
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract ReplicationNeighborCollection GetReplicationNeighbors(string partition);
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract ReplicationNeighborCollection GetAllReplicationNeighbors();
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract ReplicationFailureCollection GetReplicationConnectionFailures();
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract ActiveDirectoryReplicationMetadata GetReplicationMetadata(string objectPath);
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract void SyncReplicaFromServer(string partition, string sourceServer);
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract void TriggerSyncReplicaFromNeighbors(string partition);
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public abstract void SyncReplicaFromAllServers(string partition, SyncFromAllServersOptions options);
+
+ #endregion abstract public methods
+
+ #region public properties
+
+ public string Name
+ {
+ get
+ {
+ CheckIfDisposed();
+ return replicaName;
+ }
+ }
+
+ public ReadOnlyStringCollection Partitions
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (cachedPartitions == null)
+ {
+ cachedPartitions = new ReadOnlyStringCollection(GetPartitions());
+ }
+ return cachedPartitions;
+ }
+ }
+
+ #endregion public properties
+
+ #region abstract public properties
+ public abstract string IPAddress
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get;
+ }
+ public abstract String SiteName
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get;
+ }
+
+ public abstract SyncUpdateCallback SyncFromAllServersCallback
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get;
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ set;
+ }
+ public abstract ReplicationConnectionCollection InboundConnections
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get;
+ }
+
+ public abstract ReplicationConnectionCollection OutboundConnections
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get;
+ }
+
+ #endregion abstract public properties
+
+ #region private methods
+
+ internal ArrayList GetPartitions()
+ {
+ ArrayList partitionList = new ArrayList();
+ DirectoryEntry rootDSE = null;
+ DirectoryEntry serverNtdsaEntry = null;
+
+ try
+ {
+ // get the writable partitions
+ rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ // don't need range retrieval for root dse attributes
+ foreach (string partition in rootDSE.Properties[PropertyManager.NamingContexts])
+ {
+ partitionList.Add(partition);
+ }
+
+ // also the read only partitions
+ string ntdsaName = (this is DomainController) ? ((DomainController)this).NtdsaObjectName : ((AdamInstance)this).NtdsaObjectName;
+ serverNtdsaEntry = DirectoryEntryManager.GetDirectoryEntry(context, ntdsaName);
+
+ // use range retrieval
+ ArrayList propertyNames = new ArrayList();
+ propertyNames.Add(PropertyManager.HasPartialReplicaNCs);
+
+ Hashtable values = null;
+ try
+ {
+ values = Utils.GetValuesWithRangeRetrieval(serverNtdsaEntry, null, propertyNames, SearchScope.Base);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ ArrayList readOnlyPartitions = (ArrayList)values[PropertyManager.HasPartialReplicaNCs.ToLower(CultureInfo.InvariantCulture)];
+
+ Debug.Assert(readOnlyPartitions != null);
+ foreach (string readOnlyPartition in readOnlyPartitions)
+ {
+ partitionList.Add(readOnlyPartition);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (rootDSE != null)
+ {
+ rootDSE.Dispose();
+ }
+
+ if (serverNtdsaEntry != null)
+ {
+ serverNtdsaEntry.Dispose();
+ }
+ }
+ return partitionList;
+ }
+
+ internal void CheckIfDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+
+ internal DirectoryContext Context
+ {
+ get
+ {
+ return context;
+ }
+ }
+
+ internal void CheckConsistencyHelper(IntPtr dsHandle, LoadLibrarySafeHandle libHandle)
+ {
+ // call DsReplicaConsistencyCheck
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsReplicaConsistencyCheck");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsReplicaConsistencyCheck replicaConsistencyCheck = (UnsafeNativeMethods.DsReplicaConsistencyCheck)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsReplicaConsistencyCheck));
+
+ int result = replicaConsistencyCheck(dsHandle, 0, 0);
+
+ if (result != 0)
+ throw ExceptionHelper.GetExceptionFromErrorCode(result, Name);
+ }
+
+ internal IntPtr GetReplicationInfoHelper(IntPtr dsHandle, int type, int secondaryType, string partition, ref bool advanced, int context, LoadLibrarySafeHandle libHandle)
+ {
+ IntPtr info = (IntPtr)0;
+ int result = 0;
+ bool needToTryAgain = true;
+ IntPtr functionPtr;
+
+ // first try to use the DsReplicaGetInfo2W API which does not exist on win2k machine
+ // call DsReplicaGetInfo2W
+ functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsReplicaGetInfo2W");
+ if (functionPtr == (IntPtr)0)
+ {
+ // a win2k machine which does not have it.
+ functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsReplicaGetInfoW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsReplicaGetInfoW dsReplicaGetInfoW = (UnsafeNativeMethods.DsReplicaGetInfoW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsReplicaGetInfoW));
+ result = dsReplicaGetInfoW(dsHandle, secondaryType, partition, (IntPtr)0, ref info);
+ advanced = false;
+ needToTryAgain = false;
+ }
+ else
+ {
+ UnsafeNativeMethods.DsReplicaGetInfo2W dsReplicaGetInfo2W = (UnsafeNativeMethods.DsReplicaGetInfo2W)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsReplicaGetInfo2W));
+ result = dsReplicaGetInfo2W(dsHandle, type, partition, (IntPtr)0, null, null, 0, context, ref info);
+ }
+
+ // check the result
+ if (needToTryAgain && result == DS_REPL_NOTSUPPORTED)
+ {
+ // this is the case that client is xp/win2k3, dc is win2k
+ functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsReplicaGetInfoW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsReplicaGetInfoW dsReplicaGetInfoW = (UnsafeNativeMethods.DsReplicaGetInfoW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsReplicaGetInfoW));
+
+ result = dsReplicaGetInfoW(dsHandle, secondaryType, partition, (IntPtr)0, ref info);
+ advanced = false;
+ }
+
+ if (result != 0)
+ {
+ if (partition != null)
+ {
+ // this is the case of meta data
+ if (type == (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_METADATA_2_FOR_OBJ)
+ {
+ if (result == ExceptionHelper.ERROR_DS_DRA_BAD_DN || result == ExceptionHelper.ERROR_DS_NAME_UNPARSEABLE)
+ throw new ArgumentException(ExceptionHelper.GetErrorMessage(result, false), "objectPath");
+
+ DirectoryEntry verifyEntry = DirectoryEntryManager.GetDirectoryEntry(this.context, partition);
+ try
+ {
+ verifyEntry.RefreshCache(new string[] { "name" });
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072020) | // dir_error on server side
+ e.ErrorCode == unchecked((int)0x80072030)) // object not exists
+ throw new ArgumentException(Res.GetString(Res.DSNoObject), "objectPath");
+ else if (e.ErrorCode == unchecked((int)0x80005000) | // bad path name
+ e.ErrorCode == unchecked((int)0x80072032)) // ERROR_DS_INVALID_DN_SYNTAX
+ throw new ArgumentException(Res.GetString(Res.DSInvalidPath), "objectPath");
+ }
+ }
+ else
+ {
+ if (!Partitions.Contains(partition))
+ throw new ArgumentException(Res.GetString(Res.ServerNotAReplica), "partition");
+ }
+ }
+
+ throw ExceptionHelper.GetExceptionFromErrorCode(result, Name);
+ }
+
+ return info;
+ }
+
+ internal ReplicationCursorCollection ConstructReplicationCursors(IntPtr dsHandle, bool advanced, IntPtr info, string partition, DirectoryServer server, LoadLibrarySafeHandle libHandle)
+ {
+ int context = 0;
+ int count = 0;
+ ReplicationCursorCollection collection = new ReplicationCursorCollection(server);
+
+ // construct the collection
+ if (advanced)
+ {
+ // using paging to get all the results
+ while (true)
+ {
+ try
+ {
+ if (info != (IntPtr)0)
+ {
+ DS_REPL_CURSORS_3 cursors = new DS_REPL_CURSORS_3();
+ Marshal.PtrToStructure(info, cursors);
+ count = cursors.cNumCursors;
+ if (count > 0)
+ collection.AddHelper(partition, cursors, advanced, info);
+
+ context = cursors.dwEnumerationContext;
+
+ // we already get all the results or there is no result
+ if (context == -1 || count == 0)
+ break;
+ }
+ else
+ {
+ // should not happen, treat as no result is returned.
+ break;
+ }
+ }
+ finally
+ {
+ FreeReplicaInfo(DS_REPL_INFO_TYPE.DS_REPL_INFO_CURSORS_3_FOR_NC, info, libHandle);
+ }
+
+ // get the next batch of results
+ info = GetReplicationInfoHelper(dsHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_CURSORS_3_FOR_NC, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_CURSORS_FOR_NC, partition, ref advanced, context, libHandle);
+ }
+ }
+ else
+ {
+ try
+ {
+ if (info != (IntPtr)0)
+ {
+ // structure of DS_REPL_CURSORS_3 and DS_REPL_CURSORS actually are the same
+ DS_REPL_CURSORS cursors = new DS_REPL_CURSORS();
+ Marshal.PtrToStructure(info, cursors);
+
+ collection.AddHelper(partition, cursors, advanced, info);
+ }
+ }
+ finally
+ {
+ FreeReplicaInfo(DS_REPL_INFO_TYPE.DS_REPL_INFO_CURSORS_FOR_NC, info, libHandle);
+ }
+ }
+
+ return collection;
+ }
+
+ internal ReplicationOperationInformation ConstructPendingOperations(IntPtr info, DirectoryServer server, LoadLibrarySafeHandle libHandle)
+ {
+ ReplicationOperationInformation replicationInfo = new ReplicationOperationInformation();
+ ReplicationOperationCollection collection = new ReplicationOperationCollection(server);
+ replicationInfo.collection = collection;
+ int count = 0;
+
+ try
+ {
+ if (info != (IntPtr)0)
+ {
+ DS_REPL_PENDING_OPS operations = new DS_REPL_PENDING_OPS();
+ Marshal.PtrToStructure(info, operations);
+ count = operations.cNumPendingOps;
+ if (count > 0)
+ {
+ collection.AddHelper(operations, info);
+ replicationInfo.startTime = DateTime.FromFileTime(operations.ftimeCurrentOpStarted);
+ replicationInfo.currentOp = collection.GetFirstOperation();
+ }
+ }
+ }
+ finally
+ {
+ FreeReplicaInfo(DS_REPL_INFO_TYPE.DS_REPL_INFO_PENDING_OPS, info, libHandle);
+ }
+ return replicationInfo;
+ }
+
+ internal ReplicationNeighborCollection ConstructNeighbors(IntPtr info, DirectoryServer server, LoadLibrarySafeHandle libHandle)
+ {
+ ReplicationNeighborCollection collection = new ReplicationNeighborCollection(server);
+ int count = 0;
+
+ try
+ {
+ if (info != (IntPtr)0)
+ {
+ DS_REPL_NEIGHBORS neighbors = new DS_REPL_NEIGHBORS();
+ Marshal.PtrToStructure(info, neighbors);
+ Debug.Assert(neighbors != null);
+ count = neighbors.cNumNeighbors;
+ if (count > 0)
+ collection.AddHelper(neighbors, info);
+ }
+ }
+ finally
+ {
+ FreeReplicaInfo(DS_REPL_INFO_TYPE.DS_REPL_INFO_NEIGHBORS, info, libHandle);
+ }
+ return collection;
+ }
+
+ internal ReplicationFailureCollection ConstructFailures(IntPtr info, DirectoryServer server, LoadLibrarySafeHandle libHandle)
+ {
+ ReplicationFailureCollection collection = new ReplicationFailureCollection(server);
+ int count = 0;
+
+ try
+ {
+ if (info != (IntPtr)0)
+ {
+ DS_REPL_KCC_DSA_FAILURES failures = new DS_REPL_KCC_DSA_FAILURES();
+ Marshal.PtrToStructure(info, failures);
+ count = failures.cNumEntries;
+ if (count > 0)
+ collection.AddHelper(failures, info);
+ }
+ }
+ finally
+ {
+ FreeReplicaInfo(DS_REPL_INFO_TYPE.DS_REPL_INFO_KCC_DSA_CONNECT_FAILURES, info, libHandle);
+ }
+ return collection;
+ }
+
+ internal ActiveDirectoryReplicationMetadata ConstructMetaData(bool advanced, IntPtr info, DirectoryServer server, LoadLibrarySafeHandle libHandle)
+ {
+ ActiveDirectoryReplicationMetadata collection = new ActiveDirectoryReplicationMetadata(server);
+ int count = 0;
+
+ if (advanced)
+ {
+ try
+ {
+ if (info != (IntPtr)0)
+ {
+ DS_REPL_OBJ_META_DATA_2 objMetaData = new DS_REPL_OBJ_META_DATA_2();
+ Marshal.PtrToStructure(info, objMetaData);
+
+ count = objMetaData.cNumEntries;
+ if (count > 0)
+ {
+ collection.AddHelper(count, info, true);
+ }
+ }
+ }
+ finally
+ {
+ FreeReplicaInfo(DS_REPL_INFO_TYPE.DS_REPL_INFO_METADATA_2_FOR_OBJ, info, libHandle);
+ }
+ }
+ else
+ {
+ try
+ {
+ DS_REPL_OBJ_META_DATA objMetadata = new DS_REPL_OBJ_META_DATA();
+ Marshal.PtrToStructure(info, objMetadata);
+
+ count = objMetadata.cNumEntries;
+ if (count > 0)
+ {
+ collection.AddHelper(count, info, false);
+ }
+ }
+ finally
+ {
+ FreeReplicaInfo(DS_REPL_INFO_TYPE.DS_REPL_INFO_METADATA_FOR_OBJ, info, libHandle);
+ }
+ }
+
+ return collection;
+ }
+
+ internal bool SyncAllCallbackRoutine(IntPtr data, IntPtr update)
+ {
+ if (SyncFromAllServersCallback == null)
+ {
+ // user does not specify callback, resume the DsReplicaSyncAll execution
+ return true;
+ }
+ else
+ {
+ // user specifies callback
+ // our callback is invoked, update should not be NULL, do assertion here
+ Debug.Assert(update != (IntPtr)0);
+
+ DS_REPSYNCALL_UPDATE syncAllUpdate = new DS_REPSYNCALL_UPDATE();
+ Marshal.PtrToStructure(update, syncAllUpdate);
+
+ // get the event type
+ SyncFromAllServersEvent eventType = syncAllUpdate.eventType;
+
+ // get the error information
+ IntPtr temp = syncAllUpdate.pErrInfo;
+ SyncFromAllServersOperationException exception = null;
+
+ if (temp != (IntPtr)0)
+ {
+ // error information is available
+ exception = ExceptionHelper.CreateSyncAllException(temp, true);
+ if (exception == null)
+ {
+ // this is the special case that we ingore the failure when SyncAllOptions.CheckServerAlivenessOnly is specified
+ return true;
+ }
+ }
+
+ string targetName = null;
+ string sourceName = null;
+
+ temp = syncAllUpdate.pSync;
+ if (temp != (IntPtr)0)
+ {
+ DS_REPSYNCALL_SYNC sync = new DS_REPSYNCALL_SYNC();
+ Marshal.PtrToStructure(temp, sync);
+
+ targetName = Marshal.PtrToStringUni(sync.pszDstId);
+ sourceName = Marshal.PtrToStringUni(sync.pszSrcId);
+ }
+
+ // invoke the client callback
+ SyncUpdateCallback clientCallback = SyncFromAllServersCallback;
+
+ return clientCallback(eventType, targetName, sourceName, exception);
+ }
+ }
+
+ internal void SyncReplicaAllHelper(IntPtr handle, SyncReplicaFromAllServersCallback syncAllFunctionPointer, string partition, SyncFromAllServersOptions option, SyncUpdateCallback callback, LoadLibrarySafeHandle libHandle)
+ {
+ IntPtr errorInfo = (IntPtr)0;
+
+ if (!Partitions.Contains(partition))
+ throw new ArgumentException(Res.GetString(Res.ServerNotAReplica), "partition");
+
+ // we want to return the dn instead of DNS guid
+ // call DsReplicaSyncAllW
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsReplicaSyncAllW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsReplicaSyncAllW dsReplicaSyncAllW = (UnsafeNativeMethods.DsReplicaSyncAllW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsReplicaSyncAllW));
+
+ int result = dsReplicaSyncAllW(handle, partition, (int)option | DS_REPSYNCALL_ID_SERVERS_BY_DN, syncAllFunctionPointer, (IntPtr)0, ref errorInfo);
+
+ try
+ {
+ // error happens during the synchronization
+ if (errorInfo != (IntPtr)0)
+ {
+ SyncFromAllServersOperationException e = ExceptionHelper.CreateSyncAllException(errorInfo, false);
+ if (e == null)
+ return;
+ else
+ throw e;
+ }
+ else
+ {
+ // API does not return error infor occurred during synchronization, but result is not success.
+ if (result != 0)
+ throw new SyncFromAllServersOperationException(ExceptionHelper.GetErrorMessage(result, false));
+ }
+ }
+ finally
+ {
+ // release the memory
+ if (errorInfo != (IntPtr)0)
+ UnsafeNativeMethods.LocalFree(errorInfo);
+ }
+ }
+
+ private void FreeReplicaInfo(DS_REPL_INFO_TYPE type, IntPtr value, LoadLibrarySafeHandle libHandle)
+ {
+ if (value != (IntPtr)0)
+ {
+ // call DsReplicaFreeInfo
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsReplicaFreeInfo");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsReplicaFreeInfo dsReplicaFreeInfo = (UnsafeNativeMethods.DsReplicaFreeInfo)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsReplicaFreeInfo));
+
+ dsReplicaFreeInfo((int)type, value);
+ }
+ }
+
+ internal void SyncReplicaHelper(IntPtr dsHandle, bool isADAM, string partition, string sourceServer, int option, LoadLibrarySafeHandle libHandle)
+ {
+ int structSize = Marshal.SizeOf(typeof(Guid));
+ IntPtr unmanagedGuid = (IntPtr)0;
+ Guid guid = Guid.Empty;
+ AdamInstance adamServer = null;
+ DomainController dcServer = null;
+
+ unmanagedGuid = Marshal.AllocHGlobal(structSize);
+ try
+ {
+ if (sourceServer != null)
+ {
+ DirectoryContext newContext = Utils.GetNewDirectoryContext(sourceServer, DirectoryContextType.DirectoryServer, context);
+ if (isADAM)
+ {
+ adamServer = AdamInstance.GetAdamInstance(newContext);
+ guid = adamServer.NtdsaObjectGuid;
+ }
+ else
+ {
+ dcServer = DomainController.GetDomainController(newContext);
+ guid = dcServer.NtdsaObjectGuid;
+ }
+
+ Marshal.StructureToPtr(guid, unmanagedGuid, false);
+ }
+
+ // call DsReplicaSyncW
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsReplicaSyncW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsReplicaSyncW dsReplicaSyncW = (UnsafeNativeMethods.DsReplicaSyncW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsReplicaSyncW));
+
+ int result = dsReplicaSyncW(dsHandle, partition, unmanagedGuid, (int)option);
+
+ // check the result
+ if (result != 0)
+ {
+ if (!Partitions.Contains(partition))
+ throw new ArgumentException(Res.GetString(Res.ServerNotAReplica), "partition");
+
+ string serverDownName = null;
+ // this is the error returned when the server that we want to sync from is down
+ if (result == ExceptionHelper.RPC_S_SERVER_UNAVAILABLE)
+ serverDownName = sourceServer;
+ // this is the error returned when the server that we want to get synced is down
+ else if (result == ExceptionHelper.RPC_S_CALL_FAILED)
+ serverDownName = Name;
+
+ throw ExceptionHelper.GetExceptionFromErrorCode(result, serverDownName);
+ }
+ }
+ finally
+ {
+ if (unmanagedGuid != (IntPtr)0)
+ Marshal.FreeHGlobal(unmanagedGuid);
+
+ if (adamServer != null)
+ adamServer.Dispose();
+
+ if (dcServer != null)
+ dcServer.Dispose();
+ }
+ }
+
+ internal ReplicationConnectionCollection GetInboundConnectionsHelper()
+ {
+ if (_inbound == null)
+ {
+ // construct the replicationconnection collection
+ _inbound = new ReplicationConnectionCollection();
+ DirectoryContext newContext = Utils.GetNewDirectoryContext(Name, DirectoryContextType.DirectoryServer, context);
+
+ // this is the first time that user tries to retrieve this property, so get it from the directory
+ string serverName = (this is DomainController) ? ((DomainController)this).ServerObjectName : ((AdamInstance)this).ServerObjectName;
+ string srchDN = "CN=NTDS Settings," + serverName;
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(Utils.GetNewDirectoryContext(Name, DirectoryContextType.DirectoryServer, context), srchDN);
+
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=nTDSConnection)(objectCategory=nTDSConnection))",
+ new string[] { "cn" },
+ SearchScope.OneLevel);
+ SearchResultCollection srchResults = null;
+
+ try
+ {
+ srchResults = adSearcher.FindAll();
+ foreach (SearchResult r in srchResults)
+ {
+ ReplicationConnection con = new ReplicationConnection(newContext, r.GetDirectoryEntry(), (string)PropertyManager.GetSearchResultPropertyValue(r, PropertyManager.Cn));
+ _inbound.Add(con);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(newContext, e);
+ }
+ finally
+ {
+ if (srchResults != null)
+ srchResults.Dispose();
+
+ de.Dispose();
+ }
+ }
+
+ return _inbound;
+ }
+
+ internal ReplicationConnectionCollection GetOutboundConnectionsHelper()
+ {
+ // this is the first time that user tries to retrieve this property, so get it from the directory
+ if (_outbound == null)
+ {
+ // search base is the site container
+ string siteName = (this is DomainController) ? ((DomainController)this).SiteObjectName : ((AdamInstance)this).SiteObjectName;
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(Utils.GetNewDirectoryContext(Name, DirectoryContextType.DirectoryServer, context), siteName);
+
+ string serverName = (this is DomainController) ? ((DomainController)this).ServerObjectName : ((AdamInstance)this).ServerObjectName;
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=nTDSConnection)(objectCategory=nTDSConnection)(fromServer=CN=NTDS Settings," + serverName + "))",
+ new string[] { "objectClass", "cn" },
+ SearchScope.Subtree);
+
+ SearchResultCollection results = null;
+ DirectoryContext newContext = Utils.GetNewDirectoryContext(Name, DirectoryContextType.DirectoryServer, context);
+
+ try
+ {
+ results = adSearcher.FindAll();
+ _outbound = new ReplicationConnectionCollection();
+
+ foreach (SearchResult result in results)
+ {
+ ReplicationConnection con = new ReplicationConnection(newContext, result.GetDirectoryEntry(), (string)result.Properties["cn"][0]);
+ _outbound.Add(con);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(newContext, e);
+ }
+ finally
+ {
+ if (results != null)
+ results.Dispose();
+
+ de.Dispose();
+ }
+ }
+
+ return _outbound;
+ }
+
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServerCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServerCollection.cs
new file mode 100644
index 0000000000..259a64dc3d
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServerCollection.cs
@@ -0,0 +1,411 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+ using System.Diagnostics;
+
+ public class DirectoryServerCollection : CollectionBase
+ {
+ internal string siteDN = null;
+ internal string transportDN = null;
+ internal DirectoryContext context = null;
+ internal bool initialized = false;
+ internal Hashtable changeList = null;
+ private ArrayList _copyList = new ArrayList();
+ private DirectoryEntry _crossRefEntry = null;
+ private bool _isADAM = false;
+ private bool _isForNC = false;
+
+ internal DirectoryServerCollection(DirectoryContext context, string siteDN, string transportName)
+ {
+ Hashtable tempTable = new Hashtable();
+
+ changeList = Hashtable.Synchronized(tempTable);
+ this.context = context;
+ this.siteDN = siteDN;
+ this.transportDN = transportName;
+ }
+
+ internal DirectoryServerCollection(DirectoryContext context, DirectoryEntry crossRefEntry, bool isADAM, ReadOnlyDirectoryServerCollection servers)
+ {
+ this.context = context;
+ _crossRefEntry = crossRefEntry;
+ _isADAM = isADAM;
+
+ _isForNC = true;
+ foreach (DirectoryServer server in servers)
+ {
+ InnerList.Add(server);
+ }
+ }
+
+ public DirectoryServer this[int index]
+ {
+ get
+ {
+ return (DirectoryServer)InnerList[index];
+ }
+ set
+ {
+ DirectoryServer server = (DirectoryServer)value;
+
+ if (server == null)
+ throw new ArgumentNullException("value");
+
+ if (!Contains(server))
+ List[index] = server;
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, server), "value");
+ }
+ }
+
+ public int Add(DirectoryServer server)
+ {
+ if (server == null)
+ throw new ArgumentNullException("server");
+
+ // make sure that it is within the current site
+ if (_isForNC)
+ {
+ if ((!_isADAM))
+ {
+ if (!(server is DomainController))
+ throw new ArgumentException(Res.GetString(Res.ServerShouldBeDC), "server");
+
+ // verify that the version >= 5.2
+ // DC should be Win 2003 or higher
+ if (((DomainController)server).NumericOSVersion < 5.2)
+ {
+ throw new ArgumentException(Res.GetString(Res.ServerShouldBeW2K3), "server");
+ }
+ }
+
+ if (!Contains(server))
+ {
+ return List.Add(server);
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, server), "server");
+ }
+ }
+ else
+ {
+ string siteName = (server is DomainController) ? ((DomainController)server).SiteObjectName : ((AdamInstance)server).SiteObjectName;
+ Debug.Assert(siteName != null);
+ if (Utils.Compare(siteDN, siteName) != 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.NotWithinSite));
+ }
+
+ if (!Contains(server))
+ return List.Add(server);
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, server), "server");
+ }
+ }
+
+ public void AddRange(DirectoryServer[] servers)
+ {
+ if (servers == null)
+ throw new ArgumentNullException("servers");
+
+ foreach (DirectoryServer s in servers)
+ {
+ if (s == null)
+ {
+ throw new ArgumentException("servers");
+ }
+ }
+
+ for (int i = 0; ((i) < (servers.Length)); i = ((i) + (1)))
+ this.Add(servers[i]);
+ }
+
+ public bool Contains(DirectoryServer server)
+ {
+ if (server == null)
+ throw new ArgumentNullException("server");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ DirectoryServer tmp = (DirectoryServer)InnerList[i];
+
+ if (Utils.Compare(tmp.Name, server.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void CopyTo(DirectoryServer[] array, int index)
+ {
+ List.CopyTo(array, index);
+ }
+
+ public int IndexOf(DirectoryServer server)
+ {
+ if (server == null)
+ throw new ArgumentNullException("server");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ DirectoryServer tmp = (DirectoryServer)InnerList[i];
+
+ if (Utils.Compare(tmp.Name, server.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void Insert(int index, DirectoryServer server)
+ {
+ if (server == null)
+ throw new ArgumentNullException("server");
+
+ if (_isForNC)
+ {
+ if ((!_isADAM))
+ {
+ if (!(server is DomainController))
+ throw new ArgumentException(Res.GetString(Res.ServerShouldBeDC), "server");
+
+ // verify that the version >= 5.2
+ // DC should be Win 2003 or higher
+ if (((DomainController)server).NumericOSVersion < 5.2)
+ {
+ throw new ArgumentException(Res.GetString(Res.ServerShouldBeW2K3), "server");
+ }
+ }
+
+ if (!Contains(server))
+ {
+ List.Insert(index, server);
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, server), "server");
+ }
+ }
+ else
+ {
+ // make sure that it is within the current site
+ string siteName = (server is DomainController) ? ((DomainController)server).SiteObjectName : ((AdamInstance)server).SiteObjectName;
+ Debug.Assert(siteName != null);
+ if (Utils.Compare(siteDN, siteName) != 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.NotWithinSite), "server");
+ }
+
+ if (!Contains(server))
+ List.Insert(index, server);
+ else
+ throw new ArgumentException(Res.GetString(Res.AlreadyExistingInCollection, server));
+ }
+ }
+
+ public void Remove(DirectoryServer server)
+ {
+ if (server == null)
+ throw new ArgumentNullException("server");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ DirectoryServer tmp = (DirectoryServer)InnerList[i];
+
+ if (Utils.Compare(tmp.Name, server.Name) == 0)
+ {
+ List.Remove(tmp);
+ return;
+ }
+ }
+
+ // something that does not exist in the collection
+ throw new ArgumentException(Res.GetString(Res.NotFoundInCollection, server), "server");
+ }
+
+ protected override void OnClear()
+ {
+ if (initialized && !_isForNC)
+ {
+ _copyList.Clear();
+ foreach (object o in List)
+ {
+ _copyList.Add(o);
+ }
+ }
+ }
+
+ protected override void OnClearComplete()
+ {
+ // if the property exists, clear it out
+ if (_isForNC)
+ {
+ if (_crossRefEntry != null)
+ {
+ try
+ {
+ if (_crossRefEntry.Properties.Contains(PropertyManager.MsDSNCReplicaLocations))
+ {
+ _crossRefEntry.Properties[PropertyManager.MsDSNCReplicaLocations].Clear();
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+ else if (initialized)
+ {
+ for (int i = 0; i < _copyList.Count; i++)
+ {
+ OnRemoveComplete(i, _copyList[i]);
+ }
+ }
+ }
+
+ protected override void OnInsertComplete(int index, object value)
+ {
+ if (_isForNC)
+ {
+ if (_crossRefEntry != null)
+ {
+ try
+ {
+ DirectoryServer server = (DirectoryServer)value;
+ string ntdsaName = (server is DomainController) ? ((DomainController)server).NtdsaObjectName : ((AdamInstance)server).NtdsaObjectName;
+ _crossRefEntry.Properties[PropertyManager.MsDSNCReplicaLocations].Add(ntdsaName);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+ else if (initialized)
+ {
+ DirectoryServer server = (DirectoryServer)value;
+ string name = server.Name;
+ string serverName = (server is DomainController) ? ((DomainController)server).ServerObjectName : ((AdamInstance)server).ServerObjectName;
+
+ try
+ {
+ if (changeList.Contains(name))
+ {
+ ((DirectoryEntry)changeList[name]).Properties["bridgeheadTransportList"].Value = this.transportDN;
+ }
+ else
+ {
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, serverName);
+
+ de.Properties["bridgeheadTransportList"].Value = this.transportDN;
+ changeList.Add(name, de);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ protected override void OnRemoveComplete(int index, object value)
+ {
+ if (_isForNC)
+ {
+ try
+ {
+ if (_crossRefEntry != null)
+ {
+ string ntdsaName = (value is DomainController) ? ((DomainController)value).NtdsaObjectName : ((AdamInstance)value).NtdsaObjectName;
+ _crossRefEntry.Properties[PropertyManager.MsDSNCReplicaLocations].Remove(ntdsaName);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ else
+ {
+ DirectoryServer server = (DirectoryServer)value;
+ string name = server.Name;
+ string serverName = (server is DomainController) ? ((DomainController)server).ServerObjectName : ((AdamInstance)server).ServerObjectName;
+
+ try
+ {
+ if (changeList.Contains(name))
+ {
+ ((DirectoryEntry)changeList[name]).Properties["bridgeheadTransportList"].Clear();
+ }
+ else
+ {
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, serverName);
+
+ de.Properties["bridgeheadTransportList"].Clear();
+ changeList.Add(name, de);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ protected override void OnSetComplete(int index, object oldValue, object newValue)
+ {
+ OnRemoveComplete(index, oldValue);
+ OnInsertComplete(index, newValue);
+ }
+
+ protected override void OnValidate(Object value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ if (_isForNC)
+ {
+ if (_isADAM)
+ {
+ // for adam this should be an ADAMInstance
+ if (!(value is AdamInstance))
+ throw new ArgumentException(Res.GetString(Res.ServerShouldBeAI), "value");
+ }
+ else
+ {
+ // for AD this should be a DomainController
+ if (!(value is DomainController))
+ throw new ArgumentException(Res.GetString(Res.ServerShouldBeDC), "value");
+ }
+ }
+ else
+ {
+ if (!(value is DirectoryServer))
+ throw new ArgumentException("value");
+ }
+ }
+
+ internal string[] GetMultiValuedProperty()
+ {
+ ArrayList values = new ArrayList();
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ DirectoryServer ds = (DirectoryServer)InnerList[i];
+
+ string ntdsaName = (ds is DomainController) ? ((DomainController)ds).NtdsaObjectName : ((AdamInstance)ds).NtdsaObjectName;
+ values.Add(ntdsaName);
+ }
+ return (string[])values.ToArray(typeof(string));
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Domain.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Domain.cs
new file mode 100644
index 0000000000..6fca6f6669
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Domain.cs
@@ -0,0 +1,1538 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Text;
+ using System.Collections;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.DirectoryServices;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ public enum DomainMode : int
+ {
+ Unknown = -1,
+ Windows2000MixedDomain = 0, // win2000, win2003, NT
+ Windows2000NativeDomain = 1, // win2000, win2003
+ Windows2003InterimDomain = 2, // win2003, NT
+ Windows2003Domain = 3, // win2003
+ Windows2008Domain = 4, // win2008
+ Windows2008R2Domain = 5, // win2008 R2
+ Windows8Domain = 6, //Windows Server 2012
+ Windows2012R2Domain = 7, //Windows Server 2012 R2
+ }
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class Domain : ActiveDirectoryPartition
+ {
+ /// Private Variables
+ private string _crossRefDN = null;
+ private string _trustParent = null;
+
+ // internal variables corresponding to public properties
+ private DomainControllerCollection _cachedDomainControllers = null;
+ private DomainCollection _cachedChildren = null;
+ private DomainMode _currentDomainMode = (DomainMode)(-1);
+ private int _domainModeLevel = -1;
+ private DomainController _cachedPdcRoleOwner = null;
+ private DomainController _cachedRidRoleOwner = null;
+ private DomainController _cachedInfrastructureRoleOwner = null;
+ private Domain _cachedParent = null;
+ private Forest _cachedForest = null;
+ // this is needed because null value for parent is valid
+ private bool _isParentInitialized = false;
+
+ #region constructors
+ // internal constructors
+ internal Domain(DirectoryContext context, string domainName, DirectoryEntryManager directoryEntryMgr)
+ : base(context, domainName)
+ {
+ this.directoryEntryMgr = directoryEntryMgr;
+ }
+ internal Domain(DirectoryContext context, string domainName)
+ : this(context, domainName, new DirectoryEntryManager(context))
+ {
+ }
+ #endregion constructors
+
+ #region public methods
+
+ public static Domain GetDomain(DirectoryContext context)
+ {
+ // check that the argument is not null
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // contexttype should be Domain or DirectoryServer
+ if ((context.ContextType != DirectoryContextType.Domain) &&
+ (context.ContextType != DirectoryContextType.DirectoryServer))
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeServerORDomain), "context");
+ }
+
+ if ((context.Name == null) && (!context.isDomain()))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ContextNotAssociatedWithDomain), typeof(Domain), null);
+ }
+
+ if (context.Name != null)
+ {
+ // the target should be a valid domain name or a server
+ if (!((context.isDomain()) || (context.isServer())))
+ {
+ if (context.ContextType == DirectoryContextType.Domain)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DomainNotFound), typeof(Domain), context.Name);
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFound, context.Name), typeof(Domain), null);
+ }
+ }
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // bind to the rootDSE of the domain specified in the context
+ // and get the dns name
+ DirectoryEntryManager directoryEntryMgr = new DirectoryEntryManager(context);
+ DirectoryEntry rootDSE = null;
+ string defaultDomainNC = null;
+ try
+ {
+ rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ if ((context.isServer()) && (!Utils.CheckCapability(rootDSE, Capability.ActiveDirectory)))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFound, context.Name), typeof(Domain), null);
+ }
+ defaultDomainNC = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DefaultNamingContext);
+ }
+ catch (COMException e)
+ {
+ int errorCode = e.ErrorCode;
+
+ if (errorCode == unchecked((int)0x8007203a))
+ {
+ if (context.ContextType == DirectoryContextType.Domain)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DomainNotFound), typeof(Domain), context.Name);
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFound, context.Name), typeof(Domain), null);
+ }
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ // return domain object
+ return new Domain(context, Utils.GetDnsNameFromDN(defaultDomainNC), directoryEntryMgr);
+ }
+
+ public static Domain GetComputerDomain()
+ {
+ string computerDomainName = DirectoryContext.GetDnsDomainName(null);
+ if (computerDomainName == null)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ComputerNotJoinedToDomain), typeof(Domain), null);
+ }
+
+ return Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, computerDomainName));
+ }
+
+ public void RaiseDomainFunctionalityLevel(int domainMode)
+ {
+ int existingDomainModeLevel;
+ CheckIfDisposed();
+
+ // check if domainMode is within the valid range
+ if (domainMode < 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "domainMode");
+ }
+
+ // get the current domain mode
+ existingDomainModeLevel = DomainModeLevel;
+
+ if (existingDomainModeLevel >= domainMode)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "domainMode");
+ }
+
+ DomainMode existingDomainMode = DomainMode;
+
+ // set the forest mode on AD
+ DirectoryEntry domainEntry = null;
+
+ // CurrentDomain Valid domainMode Action
+ -----------------
+ // Windows2000Mixed 0 ntMixedDomain = 0 msDS-Behavior-Version = 0
+ // Windows2000Mixed 1 msDS-Behavior-Version = 1
+ // Windows2000Mixed 2 ntMixedDomain = 0, msDS-Behavior-Version = 2
+ //
+ // Windows2003Interim 2 ntMixedDomain = 0, msDS-Behavior-Version = 2
+ //
+ // Rest 2 or above msDS-Behavior-Version = domainMode
+ try
+ {
+ domainEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.DefaultNamingContext));
+
+ // set the new functional level
+ domainEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = domainMode;
+
+ switch (existingDomainMode)
+ {
+ case DomainMode.Windows2000MixedDomain:
+ {
+ if (domainMode == 2 || domainMode == 0)
+ {
+ domainEntry.Properties[PropertyManager.NTMixedDomain].Value = 0;
+ }
+ else if (domainMode > 2) // new level should be less than or equal to Windows2003
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "domainMode");
+ }
+ break;
+ }
+
+ case DomainMode.Windows2003InterimDomain:
+ {
+ if (domainMode == 2) // only Windows2003 allowed
+ {
+ domainEntry.Properties[PropertyManager.NTMixedDomain].Value = 0;
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "domainMode");
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ // NOTE:
+ // If the domain controller we are talking to is W2K
+ // (more specifically the schema is a W2K schema) then the
+ // msDS-Behavior-Version attribute will not be present.
+ // If that is the case, the domain functionality cannot be raised
+ // to Windows2003InterimDomain or Windows2003Domain (which is when we would set this attribute)
+ // since there are only W2K domain controllers
+ // So, we catch that exception and throw a more meaningful one.
+ domainEntry.CommitChanges();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8007200A))
+ {
+ // attribute does not exist which means this is not a W2K3 DC
+ // cannot raise domain functionality
+ throw new ArgumentException(Res.GetString(Res.NoW2K3DCs), "domainMode");
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ finally
+ {
+ if (domainEntry != null)
+ {
+ domainEntry.Dispose();
+ }
+ }
+
+ // at this point the raise domain function has succeeded
+ // invalidate the domain mode so that we get it from the server the next time
+ _currentDomainMode = (DomainMode)(-1);
+ _domainModeLevel = -1;
+ }
+
+ public void RaiseDomainFunctionality(DomainMode domainMode)
+ {
+ DomainMode existingDomainMode;
+ CheckIfDisposed();
+
+ // check if domain mode is within the valid range
+ if (domainMode < DomainMode.Windows2000MixedDomain || domainMode > DomainMode.Windows2012R2Domain)
+ {
+ throw new InvalidEnumArgumentException("domainMode", (int)domainMode, typeof(DomainMode));
+ }
+
+ // get the current domain mode
+ existingDomainMode = GetDomainMode();
+
+ // set the forest mode on AD
+ DirectoryEntry domainEntry = null;
+
+ // CurrentDomain Valid RequestedDomain Action
+ -----------------
+ // Windows2000Mixed Windows2000Native ntMixedDomain = 0
+ // Windows2000Mixed Windows2003Interim msDS-Behavior-Version = 1
+ // Windows2000Mixed Windows2003 ntMixedDomain = 0, msDS-Behavior-Version = 2
+ //
+ // Windows2003Interim Windows2003 ntMixedDomain = 0, msDS-Behavior-Version = 2
+ //
+ // Windows2000Native Windows2003 or above
+ // Windows2003 Windows2008 or above
+ // Windows2008 Windows2008R2 or above
+ // Windows2008R2 Windows2012 or above
+ // Windows2012 Windows2012R2 or above
+ // Windows2012R2 ERROR
+
+ try
+ {
+ domainEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.DefaultNamingContext));
+
+ switch (existingDomainMode)
+ {
+ case DomainMode.Windows2000MixedDomain:
+ {
+ if (domainMode == DomainMode.Windows2000NativeDomain)
+ {
+ domainEntry.Properties[PropertyManager.NTMixedDomain].Value = 0;
+ }
+ else if (domainMode == DomainMode.Windows2003InterimDomain)
+ {
+ domainEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = 1;
+ }
+ else if (domainMode == DomainMode.Windows2003Domain)
+ {
+ domainEntry.Properties[PropertyManager.NTMixedDomain].Value = 0;
+ domainEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = 2;
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "domainMode");
+ }
+
+ break;
+ }
+
+ case DomainMode.Windows2003InterimDomain:
+ {
+ if (domainMode == DomainMode.Windows2003Domain)
+ {
+ domainEntry.Properties[PropertyManager.NTMixedDomain].Value = 0;
+ domainEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = 2;
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "domainMode");
+ }
+
+ break;
+ }
+
+ case DomainMode.Windows2000NativeDomain:
+ case DomainMode.Windows2003Domain:
+ case DomainMode.Windows2008Domain:
+ case DomainMode.Windows2008R2Domain:
+ case DomainMode.Windows8Domain:
+ case DomainMode.Windows2012R2Domain:
+ {
+ if (existingDomainMode >= domainMode)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "domainMode");
+ }
+
+ if (domainMode == DomainMode.Windows2003Domain)
+ {
+ domainEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = 2;
+ }
+ else if (domainMode == DomainMode.Windows2008Domain)
+ {
+ domainEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = 3;
+ }
+ else if (domainMode == DomainMode.Windows2008R2Domain)
+ {
+ domainEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = 4;
+ }
+ else if (domainMode == DomainMode.Windows8Domain)
+ {
+ domainEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = 5;
+ }
+ else if (domainMode == DomainMode.Windows2012R2Domain)
+ {
+ domainEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = 6;
+ }
+ else
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "domainMode");
+ }
+ }
+ break;
+ default:
+ {
+ // should not happen
+ throw new ActiveDirectoryOperationException();
+ }
+ }
+
+ // NOTE:
+ // If the domain controller we are talking to is W2K
+ // (more specifically the schema is a W2K schema) then the
+ // msDS-Behavior-Version attribute will not be present.
+ // If that is the case, the domain functionality cannot be raised
+ // to Windows2003InterimDomain or Windows2003Domain (which is when we would set this attribute)
+ // since there are only W2K domain controllers
+ // So, we catch that exception and throw a more meaningful one.
+ domainEntry.CommitChanges();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8007200A))
+ {
+ // attribute does not exist which means this is not a W2K3 DC
+ // cannot raise domain functionality
+ throw new ArgumentException(Res.GetString(Res.NoW2K3DCs), "domainMode");
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ finally
+ {
+ if (domainEntry != null)
+ {
+ domainEntry.Dispose();
+ }
+ }
+
+ // at this point the raise domain function has succeeded
+ // invalidate the domain mode so that we get it from the server the next time
+ _currentDomainMode = (DomainMode)(-1);
+ _domainModeLevel = -1;
+ }
+
+ public DomainController FindDomainController()
+ {
+ CheckIfDisposed();
+
+ return DomainController.FindOneInternal(context, Name, null, 0);
+ }
+
+ public DomainController FindDomainController(string siteName)
+ {
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return DomainController.FindOneInternal(context, Name, siteName, 0);
+ }
+
+ public DomainController FindDomainController(LocatorOptions flag)
+ {
+ CheckIfDisposed();
+
+ return DomainController.FindOneInternal(context, Name, null, flag);
+ }
+
+ public DomainController FindDomainController(string siteName, LocatorOptions flag)
+ {
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return DomainController.FindOneInternal(context, Name, siteName, flag);
+ }
+
+ public DomainControllerCollection FindAllDomainControllers()
+ {
+ CheckIfDisposed();
+
+ return DomainController.FindAllInternal(context, Name, true /*isDnsDomainName */, null);
+ }
+
+ public DomainControllerCollection FindAllDomainControllers(string siteName)
+ {
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return DomainController.FindAllInternal(context, Name, true /*isDnsDomainName */, siteName);
+ }
+
+ public DomainControllerCollection FindAllDiscoverableDomainControllers()
+ {
+ long flag = (long)PrivateLocatorFlags.DSWriteableRequired;
+
+ CheckIfDisposed();
+ return new DomainControllerCollection(Locator.EnumerateDomainControllers(context, Name, null, (long)flag));
+ }
+
+ public DomainControllerCollection FindAllDiscoverableDomainControllers(string siteName)
+ {
+ long flag = (long)PrivateLocatorFlags.DSWriteableRequired;
+
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ if (siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ return new DomainControllerCollection(Locator.EnumerateDomainControllers(context, Name, siteName, (long)flag));
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override DirectoryEntry GetDirectoryEntry()
+ {
+ CheckIfDisposed();
+ return DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.DefaultNamingContext));
+ }
+
+ public TrustRelationshipInformationCollection GetAllTrustRelationships()
+ {
+ CheckIfDisposed();
+
+ ArrayList trusts = GetTrustsHelper(null);
+ TrustRelationshipInformationCollection collection = new TrustRelationshipInformationCollection(context, Name, trusts);
+ return collection;
+ }
+
+ public TrustRelationshipInformation GetTrustRelationship(string targetDomainName)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ ArrayList trusts = GetTrustsHelper(targetDomainName);
+ TrustRelationshipInformationCollection collection = new TrustRelationshipInformationCollection(context, Name, trusts);
+ if (collection.Count == 0)
+ {
+ // trust relationship does not exist
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DomainTrustDoesNotExist, Name, targetDomainName), typeof(TrustRelationshipInformation), null);
+ }
+ else
+ {
+ Debug.Assert(collection.Count == 1);
+ return collection[0];
+ }
+ }
+
+ public bool GetSelectiveAuthenticationStatus(string targetDomainName)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ return TrustHelper.GetTrustedDomainInfoStatus(context, Name, targetDomainName, TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_CROSS_ORGANIZATION, false);
+ }
+
+ public void SetSelectiveAuthenticationStatus(string targetDomainName, bool enable)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ TrustHelper.SetTrustedDomainInfoStatus(context, Name, targetDomainName, TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_CROSS_ORGANIZATION, enable, false);
+ }
+
+ public bool GetSidFilteringStatus(string targetDomainName)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ return TrustHelper.GetTrustedDomainInfoStatus(context, Name, targetDomainName, TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_QUARANTINED_DOMAIN, false);
+ }
+
+ public void SetSidFilteringStatus(string targetDomainName, bool enable)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ TrustHelper.SetTrustedDomainInfoStatus(context, Name, targetDomainName, TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_QUARANTINED_DOMAIN, enable, false);
+ }
+
+ public void DeleteLocalSideOfTrustRelationship(string targetDomainName)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ // delete local side of trust only
+ TrustHelper.DeleteTrust(context, Name, targetDomainName, false);
+ }
+
+ public void DeleteTrustRelationship(Domain targetDomain)
+ {
+ CheckIfDisposed();
+
+ if (targetDomain == null)
+ throw new ArgumentNullException("targetDomain");
+
+ // first delete the trust on the remote side
+ TrustHelper.DeleteTrust(targetDomain.GetDirectoryContext(), targetDomain.Name, Name, false);
+
+ // then delete the local side trust
+ TrustHelper.DeleteTrust(context, Name, targetDomain.Name, false);
+ }
+
+ public void VerifyOutboundTrustRelationship(string targetDomainName)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ TrustHelper.VerifyTrust(context, Name, targetDomainName, false/*not forest*/, TrustDirection.Outbound, false/*just TC verification*/, null /* no need to go to specific server*/);
+ }
+
+ public void VerifyTrustRelationship(Domain targetDomain, TrustDirection direction)
+ {
+ CheckIfDisposed();
+
+ if (targetDomain == null)
+ throw new ArgumentNullException("targetDomain");
+
+ if (direction < TrustDirection.Inbound || direction > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("direction", (int)direction, typeof(TrustDirection));
+
+ // verify outbound trust first
+ if ((direction & TrustDirection.Outbound) != 0)
+ {
+ try
+ {
+ TrustHelper.VerifyTrust(context, Name, targetDomain.Name, false/*not forest*/, TrustDirection.Outbound, false/*just TC verification*/, null /* no need to go to specific server*/);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetDomain.Name, direction), typeof(TrustRelationshipInformation), null);
+ }
+ }
+
+ // verify inbound trust
+ if ((direction & TrustDirection.Inbound) != 0)
+ {
+ try
+ {
+ TrustHelper.VerifyTrust(targetDomain.GetDirectoryContext(), targetDomain.Name, Name, false/*not forest*/, TrustDirection.Outbound, false/*just TC verification*/, null /* no need to go to specific server*/);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetDomain.Name, direction), typeof(TrustRelationshipInformation), null);
+ }
+ }
+ }
+
+ public void CreateLocalSideOfTrustRelationship(string targetDomainName, TrustDirection direction, string trustPassword)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ if (direction < TrustDirection.Inbound || direction > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("direction", (int)direction, typeof(TrustDirection));
+
+ if (trustPassword == null)
+ throw new ArgumentNullException("trustPassword");
+
+ if (trustPassword.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "trustPassword");
+
+ // verify first that the target domain name is valid
+ Locator.GetDomainControllerInfo(null, targetDomainName, null, (long)PrivateLocatorFlags.DirectoryServicesRequired);
+
+ DirectoryContext targetContext = Utils.GetNewDirectoryContext(targetDomainName, DirectoryContextType.Domain, context);
+
+ TrustHelper.CreateTrust(context, Name, targetContext, targetDomainName, false, direction, trustPassword);
+ }
+
+ public void CreateTrustRelationship(Domain targetDomain, TrustDirection direction)
+ {
+ CheckIfDisposed();
+
+ if (targetDomain == null)
+ throw new ArgumentNullException("targetDomain");
+
+ if (direction < TrustDirection.Inbound || direction > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("direction", (int)direction, typeof(TrustDirection));
+
+ string password = TrustHelper.CreateTrustPassword();
+
+ // first create trust on local side
+ TrustHelper.CreateTrust(context, Name, targetDomain.GetDirectoryContext(), targetDomain.Name, false, direction, password);
+
+ // then create trust on remote side
+ int reverseDirection = 0;
+ if ((direction & TrustDirection.Inbound) != 0)
+ reverseDirection |= (int)TrustDirection.Outbound;
+ if ((direction & TrustDirection.Outbound) != 0)
+ reverseDirection |= (int)TrustDirection.Inbound;
+
+ TrustHelper.CreateTrust(targetDomain.GetDirectoryContext(), targetDomain.Name, context, Name, false, (TrustDirection)reverseDirection, password);
+ }
+
+ public void UpdateLocalSideOfTrustRelationship(string targetDomainName, string newTrustPassword)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ if (newTrustPassword == null)
+ throw new ArgumentNullException("newTrustPassword");
+
+ if (newTrustPassword.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "newTrustPassword");
+
+ TrustHelper.UpdateTrust(context, Name, targetDomainName, newTrustPassword, false);
+ }
+
+ public void UpdateLocalSideOfTrustRelationship(string targetDomainName, TrustDirection newTrustDirection, string newTrustPassword)
+ {
+ CheckIfDisposed();
+
+ if (targetDomainName == null)
+ throw new ArgumentNullException("targetDomainName");
+
+ if (targetDomainName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetDomainName");
+
+ if (newTrustDirection < TrustDirection.Inbound || newTrustDirection > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("newTrustDirection", (int)newTrustDirection, typeof(TrustDirection));
+
+ if (newTrustPassword == null)
+ throw new ArgumentNullException("newTrustPassword");
+
+ if (newTrustPassword.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "newTrustPassword");
+
+ TrustHelper.UpdateTrustDirection(context, Name, targetDomainName, newTrustPassword, false /*not a forest*/, newTrustDirection);
+ }
+
+ public void UpdateTrustRelationship(Domain targetDomain, TrustDirection newTrustDirection)
+ {
+ CheckIfDisposed();
+
+ if (targetDomain == null)
+ throw new ArgumentNullException("targetDomain");
+
+ if (newTrustDirection < TrustDirection.Inbound || newTrustDirection > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("newTrustDirection", (int)newTrustDirection, typeof(TrustDirection));
+
+ // no we generate trust password
+ string password = TrustHelper.CreateTrustPassword();
+
+ TrustHelper.UpdateTrustDirection(context, Name, targetDomain.Name, password, false /* not a forest */, newTrustDirection);
+
+ // then create trust on remote side
+ TrustDirection reverseDirection = 0;
+ if ((newTrustDirection & TrustDirection.Inbound) != 0)
+ reverseDirection |= TrustDirection.Outbound;
+ if ((newTrustDirection & TrustDirection.Outbound) != 0)
+ reverseDirection |= TrustDirection.Inbound;
+
+ TrustHelper.UpdateTrustDirection(targetDomain.GetDirectoryContext(), targetDomain.Name, Name, password, false /* not a forest */, reverseDirection);
+ }
+
+ public void RepairTrustRelationship(Domain targetDomain)
+ {
+ TrustDirection direction = TrustDirection.Bidirectional;
+
+ CheckIfDisposed();
+
+ if (targetDomain == null)
+ throw new ArgumentNullException("targetDomain");
+
+ // first try to reset the secure channel
+ try
+ {
+ direction = GetTrustRelationship(targetDomain.Name).TrustDirection;
+
+ // verify outbound trust first
+ if ((direction & TrustDirection.Outbound) != 0)
+ {
+ TrustHelper.VerifyTrust(context, Name, targetDomain.Name, false /*not forest*/, TrustDirection.Outbound, true /*reset secure channel*/, null /* no need to go to specific server*/);
+ }
+
+ // verify inbound trust
+ if ((direction & TrustDirection.Inbound) != 0)
+ {
+ TrustHelper.VerifyTrust(targetDomain.GetDirectoryContext(), targetDomain.Name, Name, false /*not forest*/, TrustDirection.Outbound, true/*reset secure channel*/, null /* no need to go to specific server*/);
+ }
+ }
+ catch (ActiveDirectoryOperationException)
+ {
+ // secure channel setup fails
+ RepairTrustHelper(targetDomain, direction);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ // trust password does not match
+ RepairTrustHelper(targetDomain, direction);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetDomain.Name, direction), typeof(TrustRelationshipInformation), null);
+ }
+ }
+
+ public static Domain GetCurrentDomain()
+ {
+ return Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain));
+ }
+
+ #endregion public methods
+
+ #region public properties
+
+ public Forest Forest
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedForest == null)
+ {
+ // get the name of rootDomainNamingContext
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ string rootDomainNC = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.RootDomainNamingContext);
+ string forestName = Utils.GetDnsNameFromDN(rootDomainNC);
+ DirectoryContext forestContext = Utils.GetNewDirectoryContext(forestName, DirectoryContextType.Forest, context);
+ _cachedForest = new Forest(forestContext, forestName);
+ }
+ return _cachedForest;
+ }
+ }
+
+ public DomainControllerCollection DomainControllers
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedDomainControllers == null)
+ {
+ _cachedDomainControllers = FindAllDomainControllers();
+ }
+ return _cachedDomainControllers;
+ }
+ }
+
+ public DomainCollection Children
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedChildren == null)
+ {
+ _cachedChildren = new DomainCollection(GetChildDomains());
+ }
+ return _cachedChildren;
+ }
+ }
+
+ public DomainMode DomainMode
+ {
+ get
+ {
+ CheckIfDisposed();
+ if ((int)_currentDomainMode == -1)
+ {
+ _currentDomainMode = GetDomainMode();
+ }
+ return _currentDomainMode;
+ }
+ }
+
+ public int DomainModeLevel
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_domainModeLevel == -1)
+ {
+ _domainModeLevel = GetDomainModeLevel();
+ }
+ return _domainModeLevel;
+ }
+ }
+
+ public Domain Parent
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (!_isParentInitialized)
+ {
+ _cachedParent = GetParent();
+ _isParentInitialized = true;
+ }
+ return _cachedParent;
+ }
+ }
+
+ public DomainController PdcRoleOwner
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedPdcRoleOwner == null)
+ {
+ _cachedPdcRoleOwner = GetRoleOwner(ActiveDirectoryRole.PdcRole);
+ }
+ return _cachedPdcRoleOwner;
+ }
+ }
+
+ public DomainController RidRoleOwner
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedRidRoleOwner == null)
+ {
+ _cachedRidRoleOwner = GetRoleOwner(ActiveDirectoryRole.RidRole);
+ }
+ return _cachedRidRoleOwner;
+ }
+ }
+
+ public DomainController InfrastructureRoleOwner
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedInfrastructureRoleOwner == null)
+ {
+ _cachedInfrastructureRoleOwner = GetRoleOwner(ActiveDirectoryRole.InfrastructureRole);
+ }
+ return _cachedInfrastructureRoleOwner;
+ }
+ }
+
+ #endregion public properties
+
+ #region private methods
+
+ internal DirectoryContext GetDirectoryContext()
+ {
+ return context;
+ }
+
+ private int GetDomainModeLevel()
+ {
+ DirectoryEntry domainEntry = null;
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ int domainFunctionality = 0;
+
+ try
+ {
+ if (rootDSE.Properties.Contains(PropertyManager.DomainFunctionality))
+ {
+ domainFunctionality = Int32.Parse((string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DomainFunctionality), NumberFormatInfo.InvariantInfo);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ if (domainEntry != null)
+ {
+ domainEntry.Dispose();
+ }
+ }
+ return domainFunctionality;
+ }
+
+ private DomainMode GetDomainMode()
+ {
+ // logic to check the domain mode
+ // if domainFunctionality is 0,
+ // then check ntMixedDomain to differentiate between
+ // Windows2000Native and Windows2000Mixed
+ // if domainFunctionality is 1 ==> Windows2003Interim
+ // if domainFunctionality is 2 ==> Windows2003
+ // if domainFunctionality is 3 ==> Windows2008
+ // if domainFunctionality is 4 ==> Windows2008R2
+ // if domainFunctionality is 5 ==> Windows2012
+ // if domainFunctionality is 6 ==> Windows2012R2
+ DomainMode domainMode;
+ DirectoryEntry domainEntry = null;
+ int domainFunctionality = DomainModeLevel;
+
+ try
+ {
+ // If the "domainFunctionality" attribute is not set on the rootdse, then
+ // this is a W2K domain (with W2K schema) so just check for mixed or native
+ switch (domainFunctionality)
+ {
+ case 0:
+ {
+ domainEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.DefaultNamingContext));
+ int ntMixedDomain = (int)PropertyManager.GetPropertyValue(context, domainEntry, PropertyManager.NTMixedDomain);
+
+ if (ntMixedDomain == 0)
+ {
+ domainMode = DomainMode.Windows2000NativeDomain;
+ }
+ else
+ {
+ domainMode = DomainMode.Windows2000MixedDomain;
+ }
+ break;
+ }
+
+ case 1:
+ domainMode = DomainMode.Windows2003InterimDomain;
+ break;
+
+ case 2:
+ domainMode = DomainMode.Windows2003Domain;
+ break;
+
+ case 3:
+ domainMode = DomainMode.Windows2008Domain;
+ break;
+ case 4:
+ domainMode = DomainMode.Windows2008R2Domain;
+ break;
+ case 5:
+ domainMode = DomainMode.Windows8Domain;
+ break;
+ case 6:
+ domainMode = DomainMode.Windows2012R2Domain;
+ break;
+ default:
+ // unrecognized domain mode
+ domainMode = DomainMode.Unknown;
+ break;
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (domainEntry != null)
+ {
+ domainEntry.Dispose();
+ }
+ }
+ return domainMode;
+ }
+
+ /// <returns>Returns a DomainController object for the DC that holds the the specified FSMO role</returns>
+ private DomainController GetRoleOwner(ActiveDirectoryRole role)
+ {
+ DirectoryEntry entry = null;
+
+ string dcName = null;
+ try
+ {
+ switch (role)
+ {
+ case ActiveDirectoryRole.PdcRole:
+ {
+ entry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.DefaultNamingContext));
+ break;
+ }
+ case ActiveDirectoryRole.RidRole:
+ {
+ entry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.RidManager));
+ break;
+ }
+ case ActiveDirectoryRole.InfrastructureRole:
+ {
+ entry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.Infrastructure));
+ break;
+ }
+ default:
+ // should not happen since we are calling this only internally
+ Debug.Assert(false, "Domain.GetRoleOwner: Invalid role type.");
+ break;
+ }
+
+ dcName = Utils.GetDnsHostNameFromNTDSA(context, (string)PropertyManager.GetPropertyValue(context, entry, PropertyManager.FsmoRoleOwner));
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (entry != null)
+ {
+ entry.Dispose();
+ }
+ }
+
+ // create a new context object for the domain controller passing on the
+ // credentials from the domain context
+ DirectoryContext dcContext = Utils.GetNewDirectoryContext(dcName, DirectoryContextType.DirectoryServer, context);
+ return new DomainController(dcContext, dcName);
+ }
+
+ private void LoadCrossRefAttributes()
+ {
+ DirectoryEntry partitionsEntry = null;
+ try
+ {
+ partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+
+ // now within the partitions container search for the
+ // crossRef object that has it's "dnsRoot" attribute equal to the
+ // dns name of the current domain
+
+ // build the filter
+ StringBuilder str = new StringBuilder(15);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=crossRef)(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsNC);
+ str.Append(")(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsDomain);
+ str.Append(")(");
+ str.Append(PropertyManager.DnsRoot);
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(partitionName));
+ str.Append("))");
+
+ string filter = str.ToString();
+ string[] propertiesToLoad = new string[2];
+
+ propertiesToLoad[0] = PropertyManager.DistinguishedName;
+ propertiesToLoad[1] = PropertyManager.TrustParent;
+
+ ADSearcher searcher = new ADSearcher(partitionsEntry, filter, propertiesToLoad, SearchScope.OneLevel, false /*not paged search*/, false /*no cached results*/);
+ SearchResult res = searcher.FindOne();
+
+ _crossRefDN = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DistinguishedName);
+
+ // "trustParent" attribute may not be set
+ if (res.Properties[PropertyManager.TrustParent].Count > 0)
+ {
+ _trustParent = (string)res.Properties[PropertyManager.TrustParent][0];
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (partitionsEntry != null)
+ {
+ partitionsEntry.Dispose();
+ }
+ }
+ }
+
+ private Domain GetParent()
+ {
+ if (_crossRefDN == null)
+ {
+ LoadCrossRefAttributes();
+ }
+ if (_trustParent != null)
+ {
+ DirectoryEntry parentCrossRef = DirectoryEntryManager.GetDirectoryEntry(context, _trustParent);
+ string parentDomainName = null;
+ DirectoryContext domainContext = null;
+ try
+ {
+ // create a new directory context for the parent domain
+ parentDomainName = (string)PropertyManager.GetPropertyValue(context, parentCrossRef, PropertyManager.DnsRoot);
+ domainContext = Utils.GetNewDirectoryContext(parentDomainName, DirectoryContextType.Domain, context);
+ }
+ finally
+ {
+ parentCrossRef.Dispose();
+ }
+ return new Domain(domainContext, parentDomainName);
+ }
+ // does not have a parent so just return null
+ return null;
+ }
+
+ private ArrayList GetChildDomains()
+ {
+ ArrayList childDomains = new ArrayList();
+
+ if (_crossRefDN == null)
+ {
+ LoadCrossRefAttributes();
+ }
+
+ DirectoryEntry partitionsEntry = null;
+ SearchResultCollection resCol = null;
+ try
+ {
+ partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(context, directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+ // search for all the "crossRef" objects that have the
+ // ADS_SYSTEMFLAG_CR_NTDS_NC and SYSTEMFLAG_CR_NTDS_DOMAIN flags set
+ // (one-level search is good enough)
+
+ // setup the directory searcher object
+
+ // build the filter
+ StringBuilder str = new StringBuilder(15);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=crossRef)(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsNC);
+ str.Append(")(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsDomain);
+ str.Append(")(");
+ str.Append(PropertyManager.TrustParent);
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(_crossRefDN));
+ str.Append("))");
+
+ string filter = str.ToString();
+ string[] propertiesToLoad = new string[1];
+ propertiesToLoad[0] = PropertyManager.DnsRoot;
+
+ ADSearcher searcher = new ADSearcher(partitionsEntry, filter, propertiesToLoad, SearchScope.OneLevel);
+ resCol = searcher.FindAll();
+
+ foreach (SearchResult res in resCol)
+ {
+ string childDomainName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DnsRoot);
+ DirectoryContext childContext = Utils.GetNewDirectoryContext(childDomainName, DirectoryContextType.Domain, context);
+ childDomains.Add(new Domain(childContext, childDomainName));
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (resCol != null)
+ {
+ resCol.Dispose();
+ }
+ if (partitionsEntry != null)
+ {
+ partitionsEntry.Dispose();
+ }
+ }
+ return childDomains;
+ }
+
+ private ArrayList GetTrustsHelper(string targetDomainName)
+ {
+ string serverName = null;
+ IntPtr domains = (IntPtr)0;
+ int count = 0;
+ ArrayList unmanagedTrustList = new ArrayList();
+ ArrayList tmpTrustList = new ArrayList();
+ TrustRelationshipInformationCollection collection = new TrustRelationshipInformationCollection();
+ int localDomainIndex = 0;
+ string localDomainParent = null;
+ int error = 0;
+ bool impersonated = false;
+
+ // first decide which server to go to
+ if (context.isServer())
+ {
+ serverName = context.Name;
+ }
+ else
+ {
+ serverName = DomainController.FindOne(context).Name;
+ }
+
+ // impersonate appropriately
+ impersonated = Utils.Impersonate(context);
+
+ // call the DS API to get trust domain information
+ try
+ {
+ try
+ {
+ error = UnsafeNativeMethods.DsEnumerateDomainTrustsW(serverName, (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_IN_FOREST | (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_OUTBOUND | (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_INBOUND, out domains, out count);
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+ }
+ }
+ catch { throw; }
+
+ // check the result
+ if (error != 0)
+ throw ExceptionHelper.GetExceptionFromErrorCode(error, serverName);
+
+ try
+ {
+ // now enumerate through the collection
+ if (domains != (IntPtr)0 && count != 0)
+ {
+ IntPtr addr = (IntPtr)0;
+ int j = 0;
+ for (int i = 0; i < count; i++)
+ {
+ // get the unmanaged trust object
+ addr = IntPtr.Add(domains, +i * Marshal.SizeOf(typeof(DS_DOMAIN_TRUSTS)));
+ DS_DOMAIN_TRUSTS unmanagedTrust = new DS_DOMAIN_TRUSTS();
+ Marshal.PtrToStructure(addr, unmanagedTrust);
+
+ unmanagedTrustList.Add(unmanagedTrust);
+ }
+
+ for (int i = 0; i < unmanagedTrustList.Count; i++)
+ {
+ DS_DOMAIN_TRUSTS unmanagedTrust = (DS_DOMAIN_TRUSTS)unmanagedTrustList[i];
+
+ // make sure this is the trust object that we want
+ if ((unmanagedTrust.Flags & (int)(DS_DOMAINTRUST_FLAG.DS_DOMAIN_PRIMARY | DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_OUTBOUND | DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_INBOUND)) == 0)
+ {
+ // Not interested in indirectly trusted domains.
+ continue;
+ }
+
+ // we don't want to have the NT4 trust to be returned
+ if (unmanagedTrust.TrustType == TrustHelper.TRUST_TYPE_DOWNLEVEL)
+ continue;
+
+ TrustObject obj = new TrustObject();
+ obj.TrustType = TrustType.Unknown;
+ if (unmanagedTrust.DnsDomainName != (IntPtr)0)
+ obj.DnsDomainName = Marshal.PtrToStringUni(unmanagedTrust.DnsDomainName);
+ if (unmanagedTrust.NetbiosDomainName != (IntPtr)0)
+ obj.NetbiosDomainName = Marshal.PtrToStringUni(unmanagedTrust.NetbiosDomainName);
+ obj.Flags = unmanagedTrust.Flags;
+ obj.TrustAttributes = unmanagedTrust.TrustAttributes;
+ obj.OriginalIndex = i;
+ obj.ParentIndex = unmanagedTrust.ParentIndex;
+
+ // check whether it is the case that we are only interested in the trust with target as specified
+ if (targetDomainName != null)
+ {
+ bool sameTarget = false;
+
+ // check whether it is the same target
+ if (obj.DnsDomainName != null && Utils.Compare(targetDomainName, obj.DnsDomainName) == 0)
+ sameTarget = true;
+ else if (obj.NetbiosDomainName != null && Utils.Compare(targetDomainName, obj.NetbiosDomainName) == 0)
+ sameTarget = true;
+
+ // we only want to need local domain and specified target domain trusts
+ if (!sameTarget && (obj.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_PRIMARY) == 0)
+ continue;
+ }
+
+ // local domain case
+ if ((obj.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_PRIMARY) != 0)
+ {
+ localDomainIndex = j;
+
+ // verify whether this is already the root
+ if ((obj.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_TREE_ROOT) == 0)
+ {
+ // get the parent domain name
+ DS_DOMAIN_TRUSTS parentTrust = (DS_DOMAIN_TRUSTS)unmanagedTrustList[obj.ParentIndex];
+ if (parentTrust.DnsDomainName != (IntPtr)0)
+ localDomainParent = Marshal.PtrToStringUni(parentTrust.DnsDomainName);
+ }
+
+ // this is the trust type SELF
+ obj.TrustType = (TrustType)7;
+ }
+ // this is the case of MIT kerberos trust
+ else if (unmanagedTrust.TrustType == 3)
+ {
+ obj.TrustType = TrustType.Kerberos;
+ }
+
+ j++;
+ tmpTrustList.Add(obj);
+ }
+
+ // now determine the trust type
+ for (int i = 0; i < tmpTrustList.Count; i++)
+ {
+ TrustObject tmpObject = (TrustObject)tmpTrustList[i];
+ // local domain case, trust type has been determined
+ if (i == localDomainIndex)
+ continue;
+
+ if (tmpObject.TrustType == TrustType.Kerberos)
+ continue;
+
+ // parent domain
+ if (localDomainParent != null && Utils.Compare(localDomainParent, tmpObject.DnsDomainName) == 0)
+ {
+ tmpObject.TrustType = TrustType.ParentChild;
+ continue;
+ }
+
+ if ((tmpObject.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_IN_FOREST) != 0)
+ {
+ // child domain
+ if (tmpObject.ParentIndex == ((TrustObject)tmpTrustList[localDomainIndex]).OriginalIndex)
+ {
+ tmpObject.TrustType = TrustType.ParentChild;
+ }
+ // tree root
+ else if ((tmpObject.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_TREE_ROOT) != 0 &&
+ (((TrustObject)tmpTrustList[localDomainIndex]).Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_TREE_ROOT) != 0)
+ {
+ string tmpForestName = null;
+ string rootDomainNC = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.RootDomainNamingContext);
+ tmpForestName = Utils.GetDnsNameFromDN(rootDomainNC);
+
+ // only if either the local domain or tmpObject is the tree root, will this trust relationship be a Root, otherwise it is cross link
+ DirectoryContext tmpContext = Utils.GetNewDirectoryContext(context.Name, DirectoryContextType.Forest, context);
+ if (tmpContext.isRootDomain() || Utils.Compare(tmpObject.DnsDomainName, tmpForestName) == 0)
+ {
+ tmpObject.TrustType = TrustType.TreeRoot;
+ }
+ else
+ {
+ tmpObject.TrustType = TrustType.CrossLink;
+ }
+ }
+ else
+ {
+ tmpObject.TrustType = TrustType.CrossLink;
+ }
+
+ continue;
+ }
+
+ // external trust or forest trust
+ if ((tmpObject.TrustAttributes & (int)TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_FOREST_TRANSITIVE) != 0)
+ {
+ // should not happen as we specify DS_DOMAIN_IN_FOREST when enumerating the trust, so forest trust will not be returned
+ tmpObject.TrustType = TrustType.Forest;
+ }
+ else
+ {
+ tmpObject.TrustType = TrustType.External;
+ }
+ }
+ }
+
+ return tmpTrustList;
+ }
+ finally
+ {
+ if (domains != (IntPtr)0)
+ UnsafeNativeMethods.NetApiBufferFree(domains);
+ }
+ }
+
+ private void RepairTrustHelper(Domain targetDomain, TrustDirection direction)
+ {
+ // now we try changing trust password on both sides
+ string password = TrustHelper.CreateTrustPassword();
+
+ // first reset trust password on remote side
+ string targetServerName = TrustHelper.UpdateTrust(targetDomain.GetDirectoryContext(), targetDomain.Name, Name, password, false);
+
+ // then reset trust password on local side
+ string sourceServerName = TrustHelper.UpdateTrust(context, Name, targetDomain.Name, password, false);
+
+ // last we reset the secure channel again to make sure info is replicated and trust is indeed ready now
+
+ // verify outbound trust first
+ if ((direction & TrustDirection.Outbound) != 0)
+ {
+ try
+ {
+ TrustHelper.VerifyTrust(context, Name, targetDomain.Name, false /*not forest*/, TrustDirection.Outbound, true /*reset secure channel*/, targetServerName /* need to specify which target server */);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetDomain.Name, direction), typeof(TrustRelationshipInformation), null);
+ }
+ }
+
+ // verify inbound trust
+ if ((direction & TrustDirection.Inbound) != 0)
+ {
+ try
+ {
+ TrustHelper.VerifyTrust(targetDomain.GetDirectoryContext(), targetDomain.Name, Name, false /*not forest*/, TrustDirection.Outbound, true/*reset secure channel*/, sourceServerName /* need to specify which target server */);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetDomain.Name, direction), typeof(TrustRelationshipInformation), null);
+ }
+ }
+ }
+
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainCollection.cs
new file mode 100644
index 0000000000..977d660009
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainCollection.cs
@@ -0,0 +1,81 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+ using System.DirectoryServices;
+
+ public class DomainCollection : ReadOnlyCollectionBase
+ {
+ internal DomainCollection() { }
+
+ internal DomainCollection(ArrayList values)
+ {
+ if (values != null)
+ {
+ for (int i = 0; i < values.Count; i++)
+ {
+ Add((Domain)values[i]);
+ }
+ }
+ }
+
+ public Domain this[int index]
+ {
+ get
+ {
+ return (Domain)InnerList[index];
+ }
+ }
+
+ public bool Contains(Domain domain)
+ {
+ if (domain == null)
+ throw new ArgumentNullException("domain");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ Domain tmp = (Domain)InnerList[i];
+ if (Utils.Compare(tmp.Name, domain.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(Domain domain)
+ {
+ if (domain == null)
+ throw new ArgumentNullException("domain");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ Domain tmp = (Domain)InnerList[i];
+ if (Utils.Compare(tmp.Name, domain.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(Domain[] domains, int index)
+ {
+ InnerList.CopyTo(domains, index);
+ }
+
+ internal int Add(Domain domain)
+ {
+ return InnerList.Add(domain);
+ }
+ internal void Clear()
+ {
+ InnerList.Clear();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainController.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainController.cs
new file mode 100644
index 0000000000..ed966f2b68
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainController.cs
@@ -0,0 +1,1449 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Net;
+ using System.ComponentModel;
+ using System.Collections;
+ using System.Globalization;
+ using System.Security.Principal;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ [Flags]
+ public enum SyncFromAllServersOptions
+ {
+ None = 0,
+ AbortIfServerUnavailable = 1,
+ SyncAdjacentServerOnly = 2,
+ CheckServerAlivenessOnly = 0x8,
+ SkipInitialCheck = 0x10,
+ PushChangeOutward = 0x20,
+ CrossSite = 0x40
+ }
+ public enum SyncFromAllServersEvent
+ {
+ Error = 0,
+ SyncStarted = 1,
+ SyncCompleted = 2,
+ Finished = 3
+ }
+ public enum SyncFromAllServersErrorCategory
+ {
+ ErrorContactingServer = 0,
+ ErrorReplicating = 1,
+ ServerUnreachable = 2
+ }
+ public delegate bool SyncUpdateCallback(SyncFromAllServersEvent eventType, string targetServer, string sourceServer, SyncFromAllServersOperationException exception);
+ internal delegate bool SyncReplicaFromAllServersCallback(IntPtr data, IntPtr update);
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class DomainController : DirectoryServer
+ {
+ private IntPtr _dsHandle = IntPtr.Zero;
+ private IntPtr _authIdentity = IntPtr.Zero;
+ private string[] _becomeRoleOwnerAttrs = null;
+ private bool _disposed = false;
+
+ // internal variables for the public properties
+ private string _cachedComputerObjectName = null;
+ private string _cachedOSVersion = null;
+ private double _cachedNumericOSVersion = 0;
+ private Forest _currentForest = null;
+ private Domain _cachedDomain = null;
+ private ActiveDirectoryRoleCollection _cachedRoles = null;
+ private bool _dcInfoInitialized = false;
+
+ internal SyncUpdateCallback userDelegate = null;
+ internal SyncReplicaFromAllServersCallback syncAllFunctionPointer = null;
+
+ // this is twice the maximum allowed RIDPool size which is 15k
+ internal const int UpdateRidPoolSeizureValue = 30000;
+
+ #region constructors
+
+ // Internal constructors
+ protected DomainController()
+ {
+ }
+
+ internal DomainController(DirectoryContext context, string domainControllerName)
+ : this(context, domainControllerName, new DirectoryEntryManager(context))
+ {
+ }
+
+ internal DomainController(DirectoryContext context, string domainControllerName, DirectoryEntryManager directoryEntryMgr)
+ {
+ this.context = context;
+ this.replicaName = domainControllerName;
+ this.directoryEntryMgr = directoryEntryMgr;
+
+ // initialize the transfer role owner attributes
+ _becomeRoleOwnerAttrs = new String[5];
+ _becomeRoleOwnerAttrs[0] = PropertyManager.BecomeSchemaMaster;
+ _becomeRoleOwnerAttrs[1] = PropertyManager.BecomeDomainMaster;
+ _becomeRoleOwnerAttrs[2] = PropertyManager.BecomePdc;
+ _becomeRoleOwnerAttrs[3] = PropertyManager.BecomeRidMaster;
+ _becomeRoleOwnerAttrs[4] = PropertyManager.BecomeInfrastructureMaster;
+
+ // initialize the callback function
+ syncAllFunctionPointer = new SyncReplicaFromAllServersCallback(SyncAllCallbackRoutine);
+ }
+ #endregion constructors
+
+ #region IDisposable
+
+ ~DomainController()
+ {
+ // finalizer is called => Dispose has not been called yet.
+ Dispose(false);
+ }
+
+ // private Dispose method
+ protected override void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ try
+ {
+ // if there are any managed or unmanaged
+ // resources to be freed, those should be done here
+ // if disposing = true, only unmanaged resources should
+ // be freed, else both managed and unmanaged.
+ FreeDSHandle();
+ _disposed = true;
+ }
+ finally
+ {
+ base.Dispose();
+ }
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+
+ public static DomainController GetDomainController(DirectoryContext context)
+ {
+ string dcDnsName = null;
+ DirectoryEntryManager directoryEntryMgr = null;
+
+ // check that the context argument is not null
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // target should be DC
+ if (context.ContextType != DirectoryContextType.DirectoryServer)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeDC), "context");
+ }
+
+ // target should be a server
+ if (!(context.isServer()))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFound, context.Name), typeof(DomainController), context.Name);
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ try
+ {
+ // Get dns name of the dc
+ // by binding to root dse and getting the "dnsHostName" attribute
+ directoryEntryMgr = new DirectoryEntryManager(context);
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ if (!Utils.CheckCapability(rootDSE, Capability.ActiveDirectory))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFound, context.Name), typeof(DomainController), context.Name);
+ }
+ dcDnsName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName);
+ }
+ catch (COMException e)
+ {
+ int errorCode = e.ErrorCode;
+
+ if (errorCode == unchecked((int)0x8007203a))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFound, context.Name), typeof(DomainController), context.Name);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ return new DomainController(context, dcDnsName, directoryEntryMgr);
+ }
+
+ public static DomainController FindOne(DirectoryContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Domain)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeDomain), "context");
+ }
+
+ return FindOneWithCredentialValidation(context, null, 0);
+ }
+
+ public static DomainController FindOne(DirectoryContext context, string siteName)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Domain)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeDomain), "context");
+ }
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return FindOneWithCredentialValidation(context, siteName, 0);
+ }
+
+ public static DomainController FindOne(DirectoryContext context, LocatorOptions flag)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Domain)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeDomain), "context");
+ }
+
+ return FindOneWithCredentialValidation(context, null, flag);
+ }
+
+ public static DomainController FindOne(DirectoryContext context, string siteName, LocatorOptions flag)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Domain)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeDomain), "context");
+ }
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return FindOneWithCredentialValidation(context, siteName, flag);
+ }
+
+ public static DomainControllerCollection FindAll(DirectoryContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Domain)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeDomain), "context");
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ return FindAllInternal(context, context.Name, false /* isDnsDomainName */, null);
+ }
+
+ public static DomainControllerCollection FindAll(DirectoryContext context, string siteName)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Domain)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeDomain), "context");
+ }
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ return FindAllInternal(context, context.Name, false /* isDnsDomainName */, siteName);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public virtual GlobalCatalog EnableGlobalCatalog()
+ {
+ CheckIfDisposed();
+
+ try
+ {
+ // bind to the server object
+ DirectoryEntry serverNtdsaEntry = directoryEntryMgr.GetCachedDirectoryEntry(NtdsaObjectName);
+ // set the NTDSDSA_OPT_IS_GC flag on the "options" property
+ int options = 0;
+ if (serverNtdsaEntry.Properties[PropertyManager.Options].Value != null)
+ {
+ options = (int)serverNtdsaEntry.Properties[PropertyManager.Options].Value;
+ }
+ serverNtdsaEntry.Properties[PropertyManager.Options].Value = options | 1;
+ serverNtdsaEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ // return a GlobalCatalog object
+ return new GlobalCatalog(context, Name);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public virtual bool IsGlobalCatalog()
+ {
+ CheckIfDisposed();
+
+ try
+ {
+ DirectoryEntry serverNtdsaEntry = directoryEntryMgr.GetCachedDirectoryEntry(NtdsaObjectName);
+ serverNtdsaEntry.RefreshCache();
+ // check if the NTDSDSA_OPT_IS_GC flag is set in the
+ // "options" attribute (lowest bit)
+ int options = 0;
+ if (serverNtdsaEntry.Properties[PropertyManager.Options].Value != null)
+ {
+ options = (int)serverNtdsaEntry.Properties[PropertyManager.Options].Value;
+ }
+ if ((options & (1)) == 1)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ public void TransferRoleOwnership(ActiveDirectoryRole role)
+ {
+ CheckIfDisposed();
+
+ if (role < ActiveDirectoryRole.SchemaRole || role > ActiveDirectoryRole.InfrastructureRole)
+ {
+ throw new InvalidEnumArgumentException("role", (int)role, typeof(ActiveDirectoryRole));
+ }
+
+ try
+ {
+ // set the appropriate attribute on the rootDSE
+ DirectoryEntry rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ rootDSE.Properties[_becomeRoleOwnerAttrs[(int)role]].Value = 1;
+ rootDSE.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e); ;
+ }
+
+ // invalidate the role collection so that it gets loaded again next time
+ _cachedRoles = null;
+ }
+
+ public void SeizeRoleOwnership(ActiveDirectoryRole role)
+ {
+ // set the "fsmoRoleOwner" attribute on the appropriate role object
+ // to the NTDSAObjectName of this DC
+ string roleObjectDN = null;
+
+ CheckIfDisposed();
+
+ switch (role)
+ {
+ case ActiveDirectoryRole.SchemaRole:
+ {
+ roleObjectDN = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.SchemaNamingContext);
+ break;
+ }
+ case ActiveDirectoryRole.NamingRole:
+ {
+ roleObjectDN = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer);
+ break;
+ }
+ case ActiveDirectoryRole.PdcRole:
+ {
+ roleObjectDN = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.DefaultNamingContext);
+ break;
+ }
+ case ActiveDirectoryRole.RidRole:
+ {
+ roleObjectDN = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.RidManager);
+ break;
+ }
+ case ActiveDirectoryRole.InfrastructureRole:
+ {
+ roleObjectDN = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.Infrastructure);
+ break;
+ }
+ default:
+ throw new InvalidEnumArgumentException("role", (int)role, typeof(ActiveDirectoryRole));
+ }
+
+ DirectoryEntry roleObjectEntry = null;
+ try
+ {
+ roleObjectEntry = DirectoryEntryManager.GetDirectoryEntry(context, roleObjectDN);
+
+ // For RID FSMO role
+ // Increment the RIDAvailablePool by 30k.
+ if (role == ActiveDirectoryRole.RidRole)
+ {
+ System.DirectoryServices.Interop.UnsafeNativeMethods.IADsLargeInteger ridPool = (System.DirectoryServices.Interop.UnsafeNativeMethods.IADsLargeInteger)roleObjectEntry.Properties[PropertyManager.RIDAvailablePool].Value;
+
+ // check the overflow of the low part
+ if (ridPool.LowPart + UpdateRidPoolSeizureValue < ridPool.LowPart)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.UpdateAvailableRIDPoolOverflowFailure));
+ }
+ ridPool.LowPart += UpdateRidPoolSeizureValue;
+ roleObjectEntry.Properties[PropertyManager.RIDAvailablePool].Value = ridPool;
+ }
+ roleObjectEntry.Properties[PropertyManager.FsmoRoleOwner].Value = NtdsaObjectName;
+ roleObjectEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (roleObjectEntry != null)
+ {
+ roleObjectEntry.Dispose();
+ }
+ }
+
+ // invalidate the role collection so that it gets loaded again next time
+ _cachedRoles = null;
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public virtual DirectorySearcher GetDirectorySearcher()
+ {
+ CheckIfDisposed();
+
+ return InternalGetDirectorySearcher();
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override void CheckReplicationConsistency()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the handle
+ GetDSHandle();
+
+ // call private helper function
+ CheckConsistencyHelper(_dsHandle, DirectoryContext.ADHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationCursorCollection GetReplicationCursors(string partition)
+ {
+ IntPtr info = (IntPtr)0;
+ int context = 0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ // get the handle
+ GetDSHandle();
+ info = GetReplicationInfoHelper(_dsHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_CURSORS_3_FOR_NC, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_CURSORS_FOR_NC, partition, ref advanced, context, DirectoryContext.ADHandle);
+ return ConstructReplicationCursors(_dsHandle, advanced, info, partition, this, DirectoryContext.ADHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationOperationInformation GetReplicationOperationInformation()
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the handle
+ GetDSHandle();
+ info = GetReplicationInfoHelper(_dsHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_PENDING_OPS, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_PENDING_OPS, null, ref advanced, 0, DirectoryContext.ADHandle);
+ return ConstructPendingOperations(info, this, DirectoryContext.ADHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationNeighborCollection GetReplicationNeighbors(string partition)
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ // get the handle
+ GetDSHandle();
+ info = GetReplicationInfoHelper(_dsHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_NEIGHBORS, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_NEIGHBORS, partition, ref advanced, 0, DirectoryContext.ADHandle);
+ return ConstructNeighbors(info, this, DirectoryContext.ADHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationNeighborCollection GetAllReplicationNeighbors()
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the handle
+ GetDSHandle();
+ info = GetReplicationInfoHelper(_dsHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_NEIGHBORS, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_NEIGHBORS, null, ref advanced, 0, DirectoryContext.ADHandle);
+ return ConstructNeighbors(info, this, DirectoryContext.ADHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ReplicationFailureCollection GetReplicationConnectionFailures()
+ {
+ return GetReplicationFailures(DS_REPL_INFO_TYPE.DS_REPL_INFO_KCC_DSA_CONNECT_FAILURES);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override ActiveDirectoryReplicationMetadata GetReplicationMetadata(string objectPath)
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (objectPath == null)
+ throw new ArgumentNullException("objectPath");
+
+ if (objectPath.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "objectPath");
+
+ // get the handle
+ GetDSHandle();
+ info = GetReplicationInfoHelper(_dsHandle, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_METADATA_2_FOR_OBJ, (int)DS_REPL_INFO_TYPE.DS_REPL_INFO_METADATA_FOR_OBJ, objectPath, ref advanced, 0, DirectoryContext.ADHandle);
+ return ConstructMetaData(advanced, info, this, DirectoryContext.ADHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override void SyncReplicaFromServer(string partition, string sourceServer)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ if (sourceServer == null)
+ throw new ArgumentNullException("sourceServer");
+
+ if (sourceServer.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "sourceServer");
+
+ // get the dsHandle
+ GetDSHandle();
+ SyncReplicaHelper(_dsHandle, false, partition, sourceServer, 0, DirectoryContext.ADHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override void TriggerSyncReplicaFromNeighbors(string partition)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ // get the dsHandle
+ GetDSHandle();
+ SyncReplicaHelper(_dsHandle, false, partition, null, DS_REPSYNC_ASYNCHRONOUS_OPERATION | DS_REPSYNC_ALL_SOURCES, DirectoryContext.ADHandle);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override void SyncReplicaFromAllServers(string partition, SyncFromAllServersOptions options)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (partition == null)
+ throw new ArgumentNullException("partition");
+
+ if (partition.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "partition");
+
+ // get the dsHandle
+ GetDSHandle();
+ SyncReplicaAllHelper(_dsHandle, syncAllFunctionPointer, partition, options, SyncFromAllServersCallback, DirectoryContext.ADHandle);
+ }
+ #endregion public methods
+
+ #region public properties
+
+ public Forest Forest
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_currentForest == null)
+ {
+ DirectoryContext forestContext = Utils.GetNewDirectoryContext(Name, DirectoryContextType.DirectoryServer, context);
+ _currentForest = Forest.GetForest(forestContext);
+ }
+ return _currentForest;
+ }
+ }
+
+ public DateTime CurrentTime
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string serverUTCTime = null;
+
+ try
+ {
+ serverUTCTime = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.CurrentTime);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+ return ParseDateTime(serverUTCTime);
+ }
+ }
+
+ public Int64 HighestCommittedUsn
+ {
+ get
+ {
+ CheckIfDisposed();
+
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string serverHighestCommittedUsn = null;
+
+ try
+ {
+ serverHighestCommittedUsn = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.HighestCommittedUSN);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+ return Int64.Parse(serverHighestCommittedUsn, NumberFormatInfo.InvariantInfo);
+ }
+ }
+
+ public string OSVersion
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedOSVersion == null)
+ {
+ // get the operating system version attribute
+ DirectoryEntry computerEntry = directoryEntryMgr.GetCachedDirectoryEntry(ComputerObjectName);
+ // is in the form Windows Server 2003
+ _cachedOSVersion = (string)PropertyManager.GetPropertyValue(context, computerEntry, PropertyManager.OperatingSystem);
+ }
+ return _cachedOSVersion;
+ }
+ }
+
+ internal double NumericOSVersion
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedNumericOSVersion == 0)
+ {
+ // get the operating system version attribute
+ DirectoryEntry computerEntry = directoryEntryMgr.GetCachedDirectoryEntry(ComputerObjectName);
+
+ // is in the form Windows Server 2003
+ string osVersion = (string)PropertyManager.GetPropertyValue(context, computerEntry, PropertyManager.OperatingSystemVersion);
+
+ // this could be in the form 5.2 (3790), so we need to take out the (3790)
+ int index = osVersion.IndexOf('(');
+ if (index != -1)
+ {
+ osVersion = osVersion.Substring(0, index);
+ }
+ _cachedNumericOSVersion = (double)Double.Parse(osVersion, NumberFormatInfo.InvariantInfo);
+ }
+
+ return _cachedNumericOSVersion;
+ }
+ }
+
+ public ActiveDirectoryRoleCollection Roles
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedRoles == null)
+ {
+ _cachedRoles = new ActiveDirectoryRoleCollection(GetRoles());
+ }
+ return _cachedRoles;
+ }
+ }
+
+ public Domain Domain
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedDomain == null)
+ {
+ string domainName = null;
+ try
+ {
+ string defaultNCName = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.DefaultNamingContext);
+ domainName = Utils.GetDnsNameFromDN(defaultNCName);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ // For domain controllers this is always the
+ // domain naming context
+ // create a new domain context for the domain
+ DirectoryContext domainContext = Utils.GetNewDirectoryContext(Name, DirectoryContextType.DirectoryServer, context);
+ _cachedDomain = new Domain(domainContext, domainName);
+ }
+ return _cachedDomain;
+ }
+ }
+
+ public override string IPAddress
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true),
+ DnsPermission(SecurityAction.Assert, Unrestricted = true)
+ ]
+ get
+ {
+ CheckIfDisposed();
+ IPHostEntry hostEntry = Dns.GetHostEntry(Name);
+ if (hostEntry.AddressList.GetLength(0) > 0)
+ {
+ return (hostEntry.AddressList[0]).ToString();
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+ public override String SiteName
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get
+ {
+ CheckIfDisposed();
+ if (!_dcInfoInitialized || siteInfoModified)
+ {
+ GetDomainControllerInfo();
+ }
+ if (cachedSiteName == null)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.SiteNameNotFound, Name));
+ }
+
+ return cachedSiteName;
+ }
+ }
+
+ internal String SiteObjectName
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (!_dcInfoInitialized || siteInfoModified)
+ {
+ GetDomainControllerInfo();
+ }
+ if (cachedSiteObjectName == null)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.SiteObjectNameNotFound, Name));
+ }
+ return cachedSiteObjectName;
+ }
+ }
+
+ internal String ComputerObjectName
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (!_dcInfoInitialized)
+ {
+ GetDomainControllerInfo();
+ }
+ if (_cachedComputerObjectName == null)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ComputerObjectNameNotFound, Name));
+ }
+ return _cachedComputerObjectName;
+ }
+ }
+
+ internal String ServerObjectName
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (!_dcInfoInitialized || siteInfoModified)
+ {
+ GetDomainControllerInfo();
+ }
+ if (cachedServerObjectName == null)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.ServerObjectNameNotFound, Name));
+ }
+ return cachedServerObjectName;
+ }
+ }
+
+ internal String NtdsaObjectName
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (!_dcInfoInitialized || siteInfoModified)
+ {
+ GetDomainControllerInfo();
+ }
+ if (cachedNtdsaObjectName == null)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.NtdsaObjectNameNotFound, Name));
+ }
+ return cachedNtdsaObjectName;
+ }
+ }
+
+ internal Guid NtdsaObjectGuid
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (!_dcInfoInitialized || siteInfoModified)
+ {
+ GetDomainControllerInfo();
+ }
+ if (cachedNtdsaObjectGuid.Equals(Guid.Empty))
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.NtdsaObjectGuidNotFound, Name));
+ }
+ return cachedNtdsaObjectGuid;
+ }
+ }
+
+ public override SyncUpdateCallback SyncFromAllServersCallback
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return userDelegate;
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ userDelegate = value;
+ }
+ }
+
+ public override ReplicationConnectionCollection InboundConnections
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get
+ {
+ return GetInboundConnectionsHelper();
+ }
+ }
+
+ public override ReplicationConnectionCollection OutboundConnections
+ {
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ get
+ {
+ return GetOutboundConnectionsHelper();
+ }
+ }
+
+ internal IntPtr Handle
+ {
+ get
+ {
+ GetDSHandle();
+ return _dsHandle;
+ }
+ }
+
+ #endregion public properties
+
+ #region private methods
+
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal static void ValidateCredential(DomainController dc, DirectoryContext context)
+ {
+ DirectoryEntry de;
+
+ if (DirectoryContext.ServerBindSupported)
+ {
+ de = new DirectoryEntry("LDAP://" + dc.Name + "/RootDSE", context.UserName, context.Password, Utils.DefaultAuthType | AuthenticationTypes.ServerBind);
+ }
+ else
+ {
+ de = new DirectoryEntry("LDAP://" + dc.Name + "/RootDSE", context.UserName, context.Password, Utils.DefaultAuthType);
+ }
+
+ de.Bind(true);
+ }
+
+ internal static DomainController FindOneWithCredentialValidation(DirectoryContext context, string siteName, LocatorOptions flag)
+ {
+ DomainController dc;
+ bool retry = false;
+ bool credsValidated = false;
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // authenticate against this DC to validate the credentials
+ dc = FindOneInternal(context, context.Name, siteName, flag);
+ try
+ {
+ ValidateCredential(dc, context);
+ credsValidated = true;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8007203a))
+ {
+ // server is down , so try again with force rediscovery if the flags did not already contain force rediscovery
+ if ((flag & LocatorOptions.ForceRediscovery) == 0)
+ {
+ retry = true;
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFoundInDomain, context.Name), typeof(DomainController), null);
+ }
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ finally
+ {
+ if (!credsValidated)
+ {
+ dc.Dispose();
+ }
+ }
+
+ if (retry)
+ {
+ credsValidated = false;
+ dc = FindOneInternal(context, context.Name, siteName, flag | LocatorOptions.ForceRediscovery);
+ try
+ {
+ ValidateCredential(dc, context);
+ credsValidated = true;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8007203a))
+ {
+ // server is down
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFoundInDomain, context.Name), typeof(DomainController), null);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ finally
+ {
+ if (!credsValidated)
+ {
+ dc.Dispose();
+ }
+ }
+ }
+
+ return dc;
+ }
+
+ internal static DomainController FindOneInternal(DirectoryContext context, string domainName, string siteName, LocatorOptions flag)
+ {
+ DomainControllerInfo domainControllerInfo;
+ int errorCode = 0;
+
+ if (siteName != null && siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ // check that the flags passed have only the valid bits set
+ if (((long)flag & (~((long)LocatorOptions.AvoidSelf | (long)LocatorOptions.ForceRediscovery | (long)LocatorOptions.KdcRequired | (long)LocatorOptions.TimeServerRequired | (long)LocatorOptions.WriteableRequired))) != 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidFlags), "flag");
+ }
+
+ if (domainName == null)
+ {
+ domainName = DirectoryContext.GetLoggedOnDomain();
+ }
+
+ // call DsGetDcName
+ errorCode = Locator.DsGetDcNameWrapper(null, domainName, siteName, (long)flag | (long)PrivateLocatorFlags.DirectoryServicesRequired, out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFoundInDomain, domainName), typeof(DomainController), null);
+ }
+ // this can only occur when flag is being explicitly passed (since the flags that we pass internally are valid)
+ if (errorCode == NativeMethods.ERROR_INVALID_FLAGS)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidFlags), "flag");
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+
+ // create a DomainController object
+ Debug.Assert(domainControllerInfo.DomainControllerName.Length > 2);
+ string domainControllerName = domainControllerInfo.DomainControllerName.Substring(2);
+
+ // create a new context object for the domain controller
+ DirectoryContext dcContext = Utils.GetNewDirectoryContext(domainControllerName, DirectoryContextType.DirectoryServer, context);
+
+ return new DomainController(dcContext, domainControllerName);
+ }
+
+ internal static DomainControllerCollection FindAllInternal(DirectoryContext context, string domainName, bool isDnsDomainName, string siteName)
+ {
+ ArrayList dcList = new ArrayList();
+
+ if (siteName != null && siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ if (domainName == null || !isDnsDomainName)
+ {
+ // get the dns name of the domain
+ DomainControllerInfo domainControllerInfo;
+ int errorCode = Locator.DsGetDcNameWrapper(null, (domainName != null) ? domainName : DirectoryContext.GetLoggedOnDomain(), null, (long)PrivateLocatorFlags.DirectoryServicesRequired, out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ // return an empty collection
+ return new DomainControllerCollection(dcList);
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+
+ Debug.Assert(domainControllerInfo.DomainName != null);
+ domainName = domainControllerInfo.DomainName;
+ }
+
+ foreach (string dcName in Utils.GetReplicaList(context, Utils.GetDNFromDnsName(domainName), siteName, true /* isDefaultNC */, false /* isADAM */, false /* mustBeGC */))
+ {
+ DirectoryContext dcContext = Utils.GetNewDirectoryContext(dcName, DirectoryContextType.DirectoryServer, context);
+ dcList.Add(new DomainController(dcContext, dcName));
+ }
+
+ return new DomainControllerCollection(dcList);
+ }
+
+ private void GetDomainControllerInfo()
+ {
+ int result = 0;
+ int dcCount = 0;
+ IntPtr dcInfoPtr = IntPtr.Zero;
+ int dcInfoLevel = 0;
+ bool initialized = false;
+
+ // get the handle
+ GetDSHandle();
+
+ // call DsGetDomainControllerInfo
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsGetDomainControllerInfoW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsGetDomainControllerInfo dsGetDomainControllerInfo = (NativeMethods.DsGetDomainControllerInfo)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsGetDomainControllerInfo));
+
+ // try DsDomainControllerInfoLevel3 first which supports Read only DC (RODC)
+ dcInfoLevel = NativeMethods.DsDomainControllerInfoLevel3;
+ result = dsGetDomainControllerInfo(_dsHandle, Domain.Name, dcInfoLevel, out dcCount, out dcInfoPtr);
+
+ if (result != 0)
+ {
+ // fallback to DsDomainControllerInfoLevel2
+ dcInfoLevel = NativeMethods.DsDomainControllerInfoLevel2;
+ result = dsGetDomainControllerInfo(_dsHandle, Domain.Name, dcInfoLevel, out dcCount, out dcInfoPtr);
+ }
+
+ if (result == 0)
+ {
+ try
+ {
+ IntPtr currentDc = dcInfoPtr;
+ for (int i = 0; i < dcCount; i++)
+ {
+ if (dcInfoLevel == NativeMethods.DsDomainControllerInfoLevel3)
+ {
+ DsDomainControllerInfo3 domainControllerInfo3 = new DsDomainControllerInfo3();
+ Marshal.PtrToStructure(currentDc, domainControllerInfo3);
+ // check if this is the same as "this" DC
+ if (domainControllerInfo3 != null)
+ {
+ if (Utils.Compare(domainControllerInfo3.dnsHostName, replicaName) == 0)
+ {
+ initialized = true;
+
+ // update all the fields
+ cachedSiteName = domainControllerInfo3.siteName;
+ cachedSiteObjectName = domainControllerInfo3.siteObjectName;
+ _cachedComputerObjectName = domainControllerInfo3.computerObjectName;
+ cachedServerObjectName = domainControllerInfo3.serverObjectName;
+ cachedNtdsaObjectName = domainControllerInfo3.ntdsaObjectName;
+ cachedNtdsaObjectGuid = domainControllerInfo3.ntdsDsaObjectGuid;
+ }
+ }
+ currentDc = IntPtr.Add(currentDc, Marshal.SizeOf(domainControllerInfo3));
+ }
+ else
+ { //NativeMethods.DsDomainControllerInfoLevel2
+ DsDomainControllerInfo2 domainControllerInfo2 = new DsDomainControllerInfo2();
+ Marshal.PtrToStructure(currentDc, domainControllerInfo2);
+ // check if this is the same as "this" DC
+ if (domainControllerInfo2 != null)
+ {
+ if (Utils.Compare(domainControllerInfo2.dnsHostName, replicaName) == 0)
+ {
+ initialized = true;
+
+ // update all the fields
+ cachedSiteName = domainControllerInfo2.siteName;
+ cachedSiteObjectName = domainControllerInfo2.siteObjectName;
+ _cachedComputerObjectName = domainControllerInfo2.computerObjectName;
+ cachedServerObjectName = domainControllerInfo2.serverObjectName;
+ cachedNtdsaObjectName = domainControllerInfo2.ntdsaObjectName;
+ cachedNtdsaObjectGuid = domainControllerInfo2.ntdsDsaObjectGuid;
+ }
+ }
+ currentDc = IntPtr.Add(currentDc, Marshal.SizeOf(domainControllerInfo2));
+ }
+ }
+ }
+ finally
+ {
+ // free the domain controller info structure
+ if (dcInfoPtr != IntPtr.Zero)
+ {
+ // call DsFreeDomainControllerInfo
+ functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsFreeDomainControllerInfoW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsFreeDomainControllerInfo dsFreeDomainControllerInfo = (NativeMethods.DsFreeDomainControllerInfo)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsFreeDomainControllerInfo));
+ dsFreeDomainControllerInfo(dcInfoLevel, dcCount, dcInfoPtr);
+ }
+ }
+
+ // if we couldn't get this DC's info, throw an exception
+ if (!initialized)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.DCInfoNotFound));
+ }
+
+ _dcInfoInitialized = true;
+ siteInfoModified = false;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(result, Name);
+ }
+ }
+
+ internal void GetDSHandle()
+ {
+ if (_disposed)
+ {
+ // cannot bind to the domain controller as the object has been
+ // disposed (finalizer has been supressed)
+ throw new ObjectDisposedException(GetType().Name);
+ }
+
+ // this part of the code needs to be synchronized
+ lock (this)
+ {
+ if (_dsHandle == IntPtr.Zero)
+ {
+ // get the credentials object
+ if (_authIdentity == IntPtr.Zero)
+ {
+ _authIdentity = Utils.GetAuthIdentity(context, DirectoryContext.ADHandle);
+ }
+
+ // DsBind
+ _dsHandle = Utils.GetDSHandle(replicaName, null, _authIdentity, DirectoryContext.ADHandle);
+ }
+ }
+ }
+
+ internal void FreeDSHandle()
+ {
+ lock (this)
+ {
+ // DsUnbind
+ Utils.FreeDSHandle(_dsHandle, DirectoryContext.ADHandle);
+ // free the credentials object
+ Utils.FreeAuthIdentity(_authIdentity, DirectoryContext.ADHandle);
+ }
+ }
+
+ internal ReplicationFailureCollection GetReplicationFailures(DS_REPL_INFO_TYPE type)
+ {
+ IntPtr info = (IntPtr)0;
+ bool advanced = true;
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the handle
+ GetDSHandle();
+ info = GetReplicationInfoHelper(_dsHandle, (int)type, (int)type, null, ref advanced, 0, DirectoryContext.ADHandle);
+ return ConstructFailures(info, this, DirectoryContext.ADHandle);
+ }
+
+ private ArrayList GetRoles()
+ {
+ ArrayList roleList = new ArrayList();
+ int result = 0;
+ IntPtr rolesPtr = IntPtr.Zero;
+
+ GetDSHandle();
+ // Get the roles
+ // call DsListRoles
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsListRolesW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsListRoles dsListRoles = (NativeMethods.DsListRoles)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsListRoles));
+
+ result = dsListRoles(_dsHandle, out rolesPtr);
+ if (result == 0)
+ {
+ try
+ {
+ DsNameResult dsNameResult = new DsNameResult();
+ Marshal.PtrToStructure(rolesPtr, dsNameResult);
+ IntPtr currentItem = dsNameResult.items;
+ for (int i = 0; i < dsNameResult.itemCount; i++)
+ {
+ DsNameResultItem dsNameResultItem = new DsNameResultItem();
+ Marshal.PtrToStructure(currentItem, dsNameResultItem);
+
+ // check if the role owner is this dc
+ if (dsNameResultItem.status == NativeMethods.DsNameNoError)
+ {
+ if (dsNameResultItem.name.Equals(NtdsaObjectName))
+ {
+ // add this role to the array
+ // the index of the item in the result signifies
+ // which role owner it is
+ roleList.Add((ActiveDirectoryRole)i);
+ }
+ }
+ currentItem = IntPtr.Add(currentItem, Marshal.SizeOf(dsNameResultItem));
+ }
+ }
+ finally
+ {
+ // free the DsNameResult structure
+ if (rolesPtr != IntPtr.Zero)
+ {
+ // call DsFreeNameResult
+ functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsFreeNameResultW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsFreeNameResultW dsFreeNameResult = (UnsafeNativeMethods.DsFreeNameResultW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsFreeNameResultW));
+ dsFreeNameResult(rolesPtr);
+ }
+ }
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(result, Name);
+ }
+ return roleList;
+ }
+
+ private DateTime ParseDateTime(string dateTime)
+ {
+ int year = (int)Int32.Parse(dateTime.Substring(0, 4), NumberFormatInfo.InvariantInfo);
+ int month = (int)Int32.Parse(dateTime.Substring(4, 2), NumberFormatInfo.InvariantInfo);
+ int day = (int)Int32.Parse(dateTime.Substring(6, 2), NumberFormatInfo.InvariantInfo);
+ int hour = (int)Int32.Parse(dateTime.Substring(8, 2), NumberFormatInfo.InvariantInfo);
+ int min = (int)Int32.Parse(dateTime.Substring(10, 2), NumberFormatInfo.InvariantInfo);
+ int sec = (int)Int32.Parse(dateTime.Substring(12, 2), NumberFormatInfo.InvariantInfo);
+
+ // this is the UniversalTime
+ return new DateTime(year, month, day, hour, min, sec, 0);
+ }
+
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ private DirectorySearcher InternalGetDirectorySearcher()
+ {
+ DirectoryEntry de = new DirectoryEntry("LDAP://" + Name);
+
+ if (DirectoryContext.ServerBindSupported)
+ {
+ de.AuthenticationType = Utils.DefaultAuthType | AuthenticationTypes.ServerBind;
+ }
+ else
+ {
+ de.AuthenticationType = Utils.DefaultAuthType;
+ }
+
+ de.Username = context.UserName;
+ de.Password = context.Password;
+
+ return new DirectorySearcher(de);
+ }
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainControllerCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainControllerCollection.cs
new file mode 100644
index 0000000000..72815f98eb
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DomainControllerCollection.cs
@@ -0,0 +1,68 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+
+ public class DomainControllerCollection : ReadOnlyCollectionBase
+ {
+ internal DomainControllerCollection() { }
+
+ internal DomainControllerCollection(ArrayList values)
+ {
+ if (values != null)
+ {
+ InnerList.AddRange(values);
+ }
+ }
+
+ public DomainController this[int index]
+ {
+ get
+ {
+ return (DomainController)InnerList[index];
+ }
+ }
+
+ public bool Contains(DomainController domainController)
+ {
+ if (domainController == null)
+ throw new ArgumentNullException("domainController");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ DomainController tmp = (DomainController)InnerList[i];
+ if (Utils.Compare(tmp.Name, domainController.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(DomainController domainController)
+ {
+ if (domainController == null)
+ throw new ArgumentNullException("domainController");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ DomainController tmp = (DomainController)InnerList[i];
+ if (Utils.Compare(tmp.Name, domainController.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(DomainController[] domainControllers, int index)
+ {
+ InnerList.CopyTo(domainControllers, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Exception.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Exception.cs
new file mode 100644
index 0000000000..66ec8bdfb3
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Exception.cs
@@ -0,0 +1,558 @@
+// 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.
+
+// </copyright>
+
+namespace System.DirectoryServices.ActiveDirectory
+{
+ using System;
+ using System.Net;
+ using System.Runtime.InteropServices;
+ using System.Security.Authentication;
+ using System.Text;
+ using System.Collections;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+
+ public class SyncFromAllServersErrorInformation
+ {
+ private SyncFromAllServersErrorCategory _category;
+ private int _errorCode;
+ private string _errorMessage = null;
+ private string _sourceServer = null;
+ private string _targetServer = null;
+
+ internal SyncFromAllServersErrorInformation(SyncFromAllServersErrorCategory category, int errorCode, string errorMessage, string sourceServer, string targetServer)
+ {
+ _category = category;
+ _errorCode = errorCode;
+ _errorMessage = errorMessage;
+ _sourceServer = sourceServer;
+ _targetServer = targetServer;
+ }
+
+ public SyncFromAllServersErrorCategory ErrorCategory
+ {
+ get
+ {
+ return _category;
+ }
+ }
+
+ public int ErrorCode
+ {
+ get
+ {
+ return _errorCode;
+ }
+ }
+
+ public string ErrorMessage
+ {
+ get
+ {
+ return _errorMessage;
+ }
+ }
+
+ public string TargetServer
+ {
+ get
+ {
+ return _targetServer;
+ }
+ }
+
+ public string SourceServer
+ {
+ get
+ {
+ return _sourceServer;
+ }
+ }
+ }
+
+ [Serializable]
+ public class ActiveDirectoryObjectNotFoundException : Exception, ISerializable
+ {
+ private Type _objectType;
+ private string _name = null;
+
+ public ActiveDirectoryObjectNotFoundException(string message, Type type, string name) : base(message)
+ {
+ _objectType = type;
+ _name = name;
+ }
+
+ public ActiveDirectoryObjectNotFoundException(string message, Exception inner) : base(message, inner) { }
+
+ public ActiveDirectoryObjectNotFoundException(string message) : base(message) { }
+
+ public ActiveDirectoryObjectNotFoundException() : base() { }
+
+ protected ActiveDirectoryObjectNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+
+ public Type Type
+ {
+ get
+ {
+ return _objectType;
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ return _name;
+ }
+ }
+
+ [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ }
+ }
+
+ [Serializable]
+ public class ActiveDirectoryOperationException : Exception, ISerializable
+ {
+ private int _errorCode = 0;
+
+ public ActiveDirectoryOperationException(string message, Exception inner, int errorCode) : base(message, inner)
+ {
+ _errorCode = errorCode;
+ }
+
+ public ActiveDirectoryOperationException(string message, int errorCode) : base(message)
+ {
+ _errorCode = errorCode;
+ }
+
+ public ActiveDirectoryOperationException(string message, Exception inner) : base(message, inner) { }
+
+ public ActiveDirectoryOperationException(string message) : base(message) { }
+
+ public ActiveDirectoryOperationException() : base(Res.GetString(Res.DSUnknownFailure)) { }
+
+ protected ActiveDirectoryOperationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+
+ public int ErrorCode
+ {
+ get
+ {
+ return _errorCode;
+ }
+ }
+
+ [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ }
+ }
+
+ [Serializable]
+ public class ActiveDirectoryServerDownException : Exception, ISerializable
+ {
+ private int _errorCode = 0;
+ private string _name = null;
+
+ public ActiveDirectoryServerDownException(string message, Exception inner, int errorCode, string name) : base(message, inner)
+ {
+ _errorCode = errorCode;
+ _name = name;
+ }
+
+ public ActiveDirectoryServerDownException(string message, int errorCode, string name) : base(message)
+ {
+ _errorCode = errorCode;
+ _name = name;
+ }
+
+ public ActiveDirectoryServerDownException(string message, Exception inner) : base(message, inner) { }
+
+ public ActiveDirectoryServerDownException(string message) : base(message) { }
+
+ public ActiveDirectoryServerDownException() : base() { }
+
+ protected ActiveDirectoryServerDownException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+
+ public int ErrorCode
+ {
+ get
+ {
+ return _errorCode;
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ return _name;
+ }
+ }
+
+ public override String Message
+ {
+ get
+ {
+ String s = base.Message;
+ if (!((_name == null) ||
+ (_name.Length == 0)))
+ return s + Environment.NewLine + Res.GetString(Res.Name, _name) + Environment.NewLine;
+ else
+ return s;
+ }
+ }
+
+ [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ }
+ }
+
+ [Serializable]
+ public class ActiveDirectoryObjectExistsException : Exception
+ {
+ public ActiveDirectoryObjectExistsException(string message, Exception inner) : base(message, inner) { }
+
+ public ActiveDirectoryObjectExistsException(string message) : base(message) { }
+
+ public ActiveDirectoryObjectExistsException() : base() { }
+
+ protected ActiveDirectoryObjectExistsException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+ }
+
+ [Serializable]
+ public class SyncFromAllServersOperationException : ActiveDirectoryOperationException, ISerializable
+ {
+ private SyncFromAllServersErrorInformation[] _errors = null;
+
+ public SyncFromAllServersOperationException(string message, Exception inner, SyncFromAllServersErrorInformation[] errors) : base(message, inner)
+ {
+ _errors = errors;
+ }
+
+ public SyncFromAllServersOperationException(string message, Exception inner) : base(message, inner) { }
+
+ public SyncFromAllServersOperationException(string message) : base(message) { }
+
+ public SyncFromAllServersOperationException() : base(Res.GetString(Res.DSSyncAllFailure)) { }
+
+ protected SyncFromAllServersOperationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+
+ public SyncFromAllServersErrorInformation[] ErrorInformation
+ {
+ get
+ {
+ if (_errors == null)
+ return new SyncFromAllServersErrorInformation[0];
+
+ SyncFromAllServersErrorInformation[] tempError = new SyncFromAllServersErrorInformation[_errors.Length];
+ for (int i = 0; i < _errors.Length; i++)
+ tempError[i] = new SyncFromAllServersErrorInformation(_errors[i].ErrorCategory, _errors[i].ErrorCode, _errors[i].ErrorMessage, _errors[i].SourceServer, _errors[i].TargetServer);
+
+ return tempError;
+ }
+ }
+
+ [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ }
+ }
+
+ [Serializable]
+ public class ForestTrustCollisionException : ActiveDirectoryOperationException, ISerializable
+ {
+ private ForestTrustRelationshipCollisionCollection _collisions = new ForestTrustRelationshipCollisionCollection();
+
+ public ForestTrustCollisionException(string message, Exception inner, ForestTrustRelationshipCollisionCollection collisions) : base(message, inner)
+ {
+ _collisions = collisions;
+ }
+
+ public ForestTrustCollisionException(string message, Exception inner) : base(message, inner) { }
+
+ public ForestTrustCollisionException(string message) : base(message) { }
+
+ public ForestTrustCollisionException() : base(Res.GetString(Res.ForestTrustCollision)) { }
+
+ protected ForestTrustCollisionException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+
+ public ForestTrustRelationshipCollisionCollection Collisions
+ {
+ get
+ {
+ return _collisions;
+ }
+ }
+
+ [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ }
+ }
+
+ internal class ExceptionHelper
+ {
+ private static int s_ERROR_NOT_ENOUGH_MEMORY = 8; // map to outofmemory exception
+ private static int s_ERROR_OUTOFMEMORY = 14; // map to outofmemory exception
+ private static int s_ERROR_DS_DRA_OUT_OF_MEM = 8446; // map to outofmemory exception
+ private static int s_ERROR_NO_SUCH_DOMAIN = 1355; // map to ActiveDirectoryServerDownException
+ private static int s_ERROR_ACCESS_DENIED = 5; // map to UnauthorizedAccessException
+ private static int s_ERROR_NO_LOGON_SERVERS = 1311; // map to ActiveDirectoryServerDownException
+ private static int s_ERROR_DS_DRA_ACCESS_DENIED = 8453; // map to UnauthorizedAccessException
+ private static int s_RPC_S_OUT_OF_RESOURCES = 1721; // map to outofmemory exception
+ internal static int RPC_S_SERVER_UNAVAILABLE = 1722; // map to ActiveDirectoryServerDownException
+ internal static int RPC_S_CALL_FAILED = 1726; // map to ActiveDirectoryServerDownException
+ private static int s_ERROR_CANCELLED = 1223;
+ internal static int ERROR_DS_DRA_BAD_DN = 8439;
+ internal static int ERROR_DS_NAME_UNPARSEABLE = 8350;
+ internal static int ERROR_DS_UNKNOWN_ERROR = 8431;
+
+ //
+ // This method maps some common COM Hresults to
+ // existing clr exceptions
+ //
+
+ internal static Exception GetExceptionFromCOMException(COMException e)
+ {
+ return GetExceptionFromCOMException(null, e);
+ }
+
+ internal static Exception GetExceptionFromCOMException(DirectoryContext context, COMException e)
+ {
+ Exception exception;
+ int errorCode = e.ErrorCode;
+ string errorMessage = e.Message;
+
+ //
+ // Check if we can throw a more specific exception
+ //
+ if (errorCode == unchecked((int)0x80070005))
+ {
+ //
+ // Access Denied
+ //
+ exception = new UnauthorizedAccessException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x8007052e))
+ {
+ //
+ // Logon Failure
+ //
+ exception = new AuthenticationException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x8007202f))
+ {
+ //
+ // Constraint Violation
+ //
+ exception = new InvalidOperationException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x80072035))
+ {
+ //
+ // Unwilling to perform
+ //
+ exception = new InvalidOperationException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x80071392))
+ {
+ //
+ // Object already exists
+ //
+ exception = new ActiveDirectoryObjectExistsException(errorMessage, e);
+ }
+ else if (errorCode == unchecked((int)0x80070008))
+ {
+ //
+ // No Memory
+ //
+ exception = new OutOfMemoryException();
+ }
+ else if ((errorCode == unchecked((int)0x8007203a)) || (errorCode == unchecked((int)0x8007200e)) || (errorCode == unchecked((int)0x8007200f)))
+ {
+ //
+ // ServerDown/Unavailable/Busy
+ //
+
+ if (context != null)
+ {
+ exception = new ActiveDirectoryServerDownException(errorMessage, e, errorCode, context.GetServerName());
+ }
+ else
+ {
+ exception = new ActiveDirectoryServerDownException(errorMessage, e, errorCode, null);
+ }
+ }
+ else
+ {
+ //
+ // Wrap the exception in a generic OperationException
+ //
+ exception = new ActiveDirectoryOperationException(errorMessage, e, errorCode);
+ }
+
+ return exception;
+ }
+
+ internal static Exception GetExceptionFromErrorCode(int errorCode)
+ {
+ return GetExceptionFromErrorCode(errorCode, null);
+ }
+
+ internal static Exception GetExceptionFromErrorCode(int errorCode, string targetName)
+
+ {
+ string errorMsg = GetErrorMessage(errorCode, false);
+
+ if ((errorCode == s_ERROR_ACCESS_DENIED) || (errorCode == s_ERROR_DS_DRA_ACCESS_DENIED))
+
+ return new UnauthorizedAccessException(errorMsg);
+
+ else if ((errorCode == s_ERROR_NOT_ENOUGH_MEMORY) || (errorCode == s_ERROR_OUTOFMEMORY) || (errorCode == s_ERROR_DS_DRA_OUT_OF_MEM) || (errorCode == s_RPC_S_OUT_OF_RESOURCES))
+
+ return new OutOfMemoryException();
+
+ else if ((errorCode == s_ERROR_NO_LOGON_SERVERS) || (errorCode == s_ERROR_NO_SUCH_DOMAIN) || (errorCode == RPC_S_SERVER_UNAVAILABLE) || (errorCode == RPC_S_CALL_FAILED))
+
+ return new ActiveDirectoryServerDownException(errorMsg, errorCode, targetName);
+
+ else
+
+ return new ActiveDirectoryOperationException(errorMsg, errorCode);
+ }
+
+ internal static string GetErrorMessage(int errorCode, bool hresult)
+ {
+ uint temp = (uint)errorCode;
+ if (!hresult)
+ {
+ temp = ((((temp) & 0x0000FFFF) | (7 << 16) | 0x80000000));
+ }
+ string errorMsg = "";
+ StringBuilder sb = new StringBuilder(256);
+ int result = UnsafeNativeMethods.FormatMessageW(UnsafeNativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS |
+ UnsafeNativeMethods.FORMAT_MESSAGE_FROM_SYSTEM |
+ UnsafeNativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ 0, (int)temp, 0, sb, sb.Capacity + 1, 0);
+ if (result != 0)
+ {
+ errorMsg = sb.ToString(0, result);
+ }
+ else
+ {
+ errorMsg = Res.GetString(Res.DSUnknown, Convert.ToString(temp, 16));
+ }
+
+ return errorMsg;
+ }
+
+ internal static SyncFromAllServersOperationException CreateSyncAllException(IntPtr errorInfo, bool singleError)
+ {
+ if (errorInfo == (IntPtr)0)
+ return new SyncFromAllServersOperationException();
+
+ if (singleError)
+ {
+ // single error
+ DS_REPSYNCALL_ERRINFO error = new DS_REPSYNCALL_ERRINFO();
+ Marshal.PtrToStructure(errorInfo, error);
+ string message = GetErrorMessage(error.dwWin32Err, false);
+ string source = Marshal.PtrToStringUni(error.pszSrcId);
+ string target = Marshal.PtrToStringUni(error.pszSvrId);
+
+ if (error.dwWin32Err == s_ERROR_CANCELLED)
+ {
+ // this is a special case. the failure is because user specifies SyncAllOptions.CheckServerAlivenessOnly, ignore it here
+ return null;
+ }
+ else
+ {
+ SyncFromAllServersErrorInformation managedError = new SyncFromAllServersErrorInformation(error.error, error.dwWin32Err, message, source, target);
+ return new SyncFromAllServersOperationException(Res.GetString(Res.DSSyncAllFailure), null, new SyncFromAllServersErrorInformation[] { managedError });
+ }
+ }
+ else
+ {
+ // it is a NULL terminated array of DS_REPSYNCALL_ERRINFO
+ IntPtr tempPtr = Marshal.ReadIntPtr(errorInfo);
+ ArrayList errorList = new ArrayList();
+ int i = 0;
+ while (tempPtr != (IntPtr)0)
+ {
+ DS_REPSYNCALL_ERRINFO error = new DS_REPSYNCALL_ERRINFO();
+ Marshal.PtrToStructure(tempPtr, error);
+ // this is a special case. the failure is because user specifies SyncAllOptions.CheckServerAlivenessOnly, ignore it here
+ if (error.dwWin32Err != s_ERROR_CANCELLED)
+ {
+ string message = GetErrorMessage(error.dwWin32Err, false);
+ string source = Marshal.PtrToStringUni(error.pszSrcId);
+ string target = Marshal.PtrToStringUni(error.pszSvrId);
+ SyncFromAllServersErrorInformation managedError = new SyncFromAllServersErrorInformation(error.error, error.dwWin32Err, message, source, target);
+
+ errorList.Add(managedError);
+ }
+
+ i++;
+ tempPtr = Marshal.ReadIntPtr(errorInfo, i * Marshal.SizeOf(typeof(IntPtr)));
+ }
+ // no error information, so we should not throw exception.
+ if (errorList.Count == 0)
+ return null;
+
+ SyncFromAllServersErrorInformation[] info = new SyncFromAllServersErrorInformation[errorList.Count];
+ for (int j = 0; j < errorList.Count; j++)
+ {
+ SyncFromAllServersErrorInformation tmp = (SyncFromAllServersErrorInformation)errorList[j];
+ info[j] = new SyncFromAllServersErrorInformation(tmp.ErrorCategory, tmp.ErrorCode, tmp.ErrorMessage, tmp.SourceServer, tmp.TargetServer);
+ }
+
+ return new SyncFromAllServersOperationException(Res.GetString(Res.DSSyncAllFailure), null, info);
+ }
+ }
+
+ internal static Exception CreateForestTrustCollisionException(IntPtr collisionInfo)
+ {
+ ForestTrustRelationshipCollisionCollection collection = new ForestTrustRelationshipCollisionCollection();
+ LSA_FOREST_TRUST_COLLISION_INFORMATION collision = new LSA_FOREST_TRUST_COLLISION_INFORMATION();
+ Marshal.PtrToStructure(collisionInfo, collision);
+
+ int count = collision.RecordCount;
+ IntPtr addr = (IntPtr)0;
+ for (int i = 0; i < count; i++)
+ {
+ addr = Marshal.ReadIntPtr(collision.Entries, i * Marshal.SizeOf(typeof(IntPtr)));
+ LSA_FOREST_TRUST_COLLISION_RECORD record = new LSA_FOREST_TRUST_COLLISION_RECORD();
+ Marshal.PtrToStructure(addr, record);
+
+ ForestTrustCollisionType type = record.Type;
+ string recordName = Marshal.PtrToStringUni(record.Name.Buffer, record.Name.Length / 2);
+ TopLevelNameCollisionOptions TLNFlag = TopLevelNameCollisionOptions.None;
+ DomainCollisionOptions domainFlag = DomainCollisionOptions.None;
+ if (type == ForestTrustCollisionType.TopLevelName)
+ {
+ TLNFlag = (TopLevelNameCollisionOptions)record.Flags;
+ }
+ else if (type == ForestTrustCollisionType.Domain)
+ {
+ domainFlag = (DomainCollisionOptions)record.Flags;
+ }
+ ForestTrustRelationshipCollision tmp = new ForestTrustRelationshipCollision(type, TLNFlag, domainFlag, recordName);
+ collection.Add(tmp);
+ }
+
+ ForestTrustCollisionException exception = new ForestTrustCollisionException(Res.GetString(Res.ForestTrustCollision), null, collection);
+ return exception;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Forest.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Forest.cs
new file mode 100644
index 0000000000..d34627b3e9
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Forest.cs
@@ -0,0 +1,1259 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Text;
+ using System.Threading;
+ using System.Collections;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.DirectoryServices;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ public enum ForestMode : int
+ {
+ Unknown = -1,
+ Windows2000Forest = 0,
+ Windows2003InterimForest = 1,
+ Windows2003Forest = 2,
+ Windows2008Forest = 3,
+ Windows2008R2Forest = 4,
+ Windows8Forest = 5,
+ Windows2012R2Forest = 6,
+ }
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class Forest : IDisposable
+ {
+ // Private Variables
+ private DirectoryContext _context = null;
+ private DirectoryEntryManager _directoryEntryMgr = null;
+ private IntPtr _dsHandle = IntPtr.Zero;
+ private IntPtr _authIdentity = IntPtr.Zero;
+ private bool _disposed = false;
+
+ // Internal variables corresponding to public properties
+ private string _forestDnsName = null;
+ private ReadOnlySiteCollection _cachedSites = null;
+ private DomainCollection _cachedDomains = null;
+ private GlobalCatalogCollection _cachedGlobalCatalogs = null;
+ private ApplicationPartitionCollection _cachedApplicationPartitions = null;
+ private int _forestModeLevel = -1;
+ private Domain _cachedRootDomain = null;
+ private ActiveDirectorySchema _cachedSchema = null;
+ private DomainController _cachedSchemaRoleOwner = null;
+ private DomainController _cachedNamingRoleOwner = null;
+
+ #region constructors
+ internal Forest(DirectoryContext context, string forestDnsName, DirectoryEntryManager directoryEntryMgr)
+ {
+ _context = context;
+ _directoryEntryMgr = directoryEntryMgr;
+ _forestDnsName = forestDnsName;
+ }
+
+ internal Forest(DirectoryContext context, string name)
+ : this(context, name, new DirectoryEntryManager(context))
+ {
+ }
+ #endregion constructors
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ // private Dispose method
+ protected void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ // check if this is an explicit Dispose
+ // only then clean up the directory entries
+ if (disposing)
+ {
+ // dispose all directory entries
+ foreach (DirectoryEntry entry in _directoryEntryMgr.GetCachedDirectoryEntries())
+ {
+ entry.Dispose();
+ }
+ }
+ _disposed = true;
+ }
+ }
+ #endregion IDisposable
+
+ #region public methods
+
+ public static Forest GetForest(DirectoryContext context)
+ {
+ DirectoryEntryManager directoryEntryMgr = null;
+ DirectoryEntry rootDSE = null;
+ string rootDomainNC = null;
+
+ // check that the argument is not null
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // contexttype should be Forest or DirectoryServer
+ if ((context.ContextType != DirectoryContextType.Forest) &&
+ (context.ContextType != DirectoryContextType.DirectoryServer))
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeServerORForest), "context");
+ }
+
+ if ((context.Name == null) && (!context.isRootDomain()))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ContextNotAssociatedWithDomain), typeof(Forest), null);
+ }
+
+ if (context.Name != null)
+ {
+ // the target should be a valid forest name or a server
+ if (!((context.isRootDomain()) || (context.isServer())))
+ {
+ if (context.ContextType == DirectoryContextType.Forest)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestNotFound), typeof(Forest), context.Name);
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFound, context.Name), typeof(Forest), null);
+ }
+ }
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ directoryEntryMgr = new DirectoryEntryManager(context);
+ // at this point we know that the target is either a
+ // valid forest name or a server (may be a bogus server name -- to check bind to rootdse)
+ // bind to the rootDSE of the forest specified in the context
+ try
+ {
+ rootDSE = directoryEntryMgr.GetCachedDirectoryEntry(WellKnownDN.RootDSE);
+ if ((context.isServer()) && (!Utils.CheckCapability(rootDSE, Capability.ActiveDirectory)))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFound, context.Name), typeof(Forest), null);
+ }
+ rootDomainNC = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.RootDomainNamingContext);
+ }
+ catch (COMException e)
+ {
+ int errorCode = e.ErrorCode;
+
+ if (errorCode == unchecked((int)0x8007203a))
+ {
+ if (context.ContextType == DirectoryContextType.Forest)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestNotFound), typeof(Forest), context.Name);
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DCNotFound, context.Name), typeof(Forest), null);
+ }
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ // return forest object
+
+ return new Forest(context, Utils.GetDnsNameFromDN(rootDomainNC), directoryEntryMgr);
+ }
+
+ public void RaiseForestFunctionalityLevel(int forestMode)
+ {
+ CheckIfDisposed();
+
+ // check new functional level is valid or not
+ if (forestMode < 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "forestMode");
+ }
+
+ // new functional level should be higher than the old one
+ if (forestMode <= ForestModeLevel)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "forestMode");
+ }
+
+ // set the forest mode on AD
+ DirectoryEntry partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(_context, _directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+ // NOTE:
+ // If the domain is a W2K domain (W2K schema) then the msDS-Behavior-Version attribute will not be present.
+ // If that is the case, the forest functionality cannot be raised.
+ try
+ {
+ partitionsEntry.Properties[PropertyManager.MsDSBehaviorVersion].Value = forestMode;
+ partitionsEntry.CommitChanges();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8007200A))
+ {
+ throw new ArgumentException(Res.GetString(Res.NoW2K3DCsInForest), "forestMode");
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ finally
+ {
+ partitionsEntry.Dispose();
+ }
+
+ // at this point the raise forest function has succeeded
+ // invalidate the cached entry so that we will go to the server next time
+ _forestModeLevel = -1;
+ }
+
+ public void RaiseForestFunctionality(ForestMode forestMode)
+ {
+ CheckIfDisposed();
+
+ // check if forest mode is a valid enum value
+ if (forestMode < ForestMode.Windows2000Forest)
+ {
+ throw new InvalidEnumArgumentException("forestMode", (int)forestMode, typeof(ForestMode));
+ }
+
+ if (forestMode <= ForestMode)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidMode), "forestMode");
+ }
+
+ RaiseForestFunctionalityLevel((int)forestMode);
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ public GlobalCatalog FindGlobalCatalog()
+ {
+ CheckIfDisposed();
+
+ return GlobalCatalog.FindOneInternal(_context, Name, null, 0);
+ }
+
+ public GlobalCatalog FindGlobalCatalog(string siteName)
+ {
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return GlobalCatalog.FindOneInternal(_context, Name, siteName, 0);
+ }
+
+ public GlobalCatalog FindGlobalCatalog(LocatorOptions flag)
+ {
+ CheckIfDisposed();
+
+ return GlobalCatalog.FindOneInternal(_context, Name, null, flag);
+ }
+
+ public GlobalCatalog FindGlobalCatalog(string siteName, LocatorOptions flag)
+ {
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return GlobalCatalog.FindOneInternal(_context, Name, siteName, flag);
+ }
+
+ public GlobalCatalogCollection FindAllGlobalCatalogs()
+ {
+ CheckIfDisposed();
+
+ return GlobalCatalog.FindAllInternal(_context, null);
+ }
+
+ public GlobalCatalogCollection FindAllGlobalCatalogs(string siteName)
+ {
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return GlobalCatalog.FindAllInternal(_context, siteName);
+ }
+
+ public GlobalCatalogCollection FindAllDiscoverableGlobalCatalogs()
+ {
+ long flag = (long)PrivateLocatorFlags.GCRequired;
+
+ CheckIfDisposed();
+ return new GlobalCatalogCollection(Locator.EnumerateDomainControllers(_context, Name, null, flag));
+ }
+
+ public GlobalCatalogCollection FindAllDiscoverableGlobalCatalogs(string siteName)
+ {
+ long flag = (long)PrivateLocatorFlags.GCRequired;
+
+ CheckIfDisposed();
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ if (siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ return new GlobalCatalogCollection(Locator.EnumerateDomainControllers(_context, Name, siteName, flag));
+ }
+
+ public TrustRelationshipInformationCollection GetAllTrustRelationships()
+ {
+ CheckIfDisposed();
+
+ return GetTrustsHelper(null);
+ }
+
+ public ForestTrustRelationshipInformation GetTrustRelationship(string targetForestName)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ TrustRelationshipInformationCollection collection = GetTrustsHelper(targetForestName);
+ if (collection.Count != 0)
+ {
+ Debug.Assert(collection.Count == 1);
+ return (ForestTrustRelationshipInformation)collection[0];
+ }
+ else
+ {
+ // trust relationship does not exist
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestTrustDoesNotExist, Name, targetForestName), typeof(TrustRelationshipInformation), null);
+ }
+ }
+
+ public bool GetSelectiveAuthenticationStatus(string targetForestName)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ return TrustHelper.GetTrustedDomainInfoStatus(_context, Name, targetForestName, TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_CROSS_ORGANIZATION, true);
+ }
+
+ public void SetSelectiveAuthenticationStatus(string targetForestName, bool enable)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ TrustHelper.SetTrustedDomainInfoStatus(_context, Name, targetForestName, TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_CROSS_ORGANIZATION, enable, true);
+ }
+
+ public bool GetSidFilteringStatus(string targetForestName)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ return TrustHelper.GetTrustedDomainInfoStatus(_context, Name, targetForestName, TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL, true);
+ }
+
+ public void SetSidFilteringStatus(string targetForestName, bool enable)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ TrustHelper.SetTrustedDomainInfoStatus(_context, Name, targetForestName, TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL, enable, true);
+ }
+
+ public void DeleteLocalSideOfTrustRelationship(string targetForestName)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ // delete local side of trust only
+ TrustHelper.DeleteTrust(_context, Name, targetForestName, true);
+ }
+
+ public void DeleteTrustRelationship(Forest targetForest)
+ {
+ CheckIfDisposed();
+
+ if (targetForest == null)
+ throw new ArgumentNullException("targetForest");
+
+ // first delete the trust on the remote side
+ TrustHelper.DeleteTrust(targetForest.GetDirectoryContext(), targetForest.Name, Name, true);
+
+ // then delete the local side trust
+ TrustHelper.DeleteTrust(_context, Name, targetForest.Name, true);
+ }
+
+ public void VerifyOutboundTrustRelationship(string targetForestName)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ TrustHelper.VerifyTrust(_context, Name, targetForestName, true/*forest*/, TrustDirection.Outbound, false /*just TC verification*/, null /* no need to go to specific server*/);
+ }
+
+ public void VerifyTrustRelationship(Forest targetForest, TrustDirection direction)
+ {
+ CheckIfDisposed();
+
+ if (targetForest == null)
+ throw new ArgumentNullException("targetForest");
+
+ if (direction < TrustDirection.Inbound || direction > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("direction", (int)direction, typeof(TrustDirection));
+
+ // verify outbound trust first
+ if ((direction & TrustDirection.Outbound) != 0)
+ {
+ try
+ {
+ TrustHelper.VerifyTrust(_context, Name, targetForest.Name, true/*forest*/, TrustDirection.Outbound, false/*just TC verification*/, null /* no need to go to specific server*/);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetForest.Name, direction), typeof(ForestTrustRelationshipInformation), null);
+ }
+ }
+
+ // verify inbound trust
+ if ((direction & TrustDirection.Inbound) != 0)
+ {
+ try
+ {
+ TrustHelper.VerifyTrust(targetForest.GetDirectoryContext(), targetForest.Name, Name, true/*forest*/, TrustDirection.Outbound, false/*just TC verification*/, null /* no need to go to specific server*/);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetForest.Name, direction), typeof(ForestTrustRelationshipInformation), null);
+ }
+ }
+ }
+
+ public void CreateLocalSideOfTrustRelationship(string targetForestName, TrustDirection direction, string trustPassword)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ if (direction < TrustDirection.Inbound || direction > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("direction", (int)direction, typeof(TrustDirection));
+
+ if (trustPassword == null)
+ throw new ArgumentNullException("trustPassword");
+
+ if (trustPassword.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "trustPassword");
+
+ // verify first that the target forest name is valid
+ Locator.GetDomainControllerInfo(null, targetForestName, null, (long)(PrivateLocatorFlags.DirectoryServicesRequired | PrivateLocatorFlags.GCRequired));
+
+ DirectoryContext targetContext = Utils.GetNewDirectoryContext(targetForestName, DirectoryContextType.Forest, _context);
+
+ TrustHelper.CreateTrust(_context, Name, targetContext, targetForestName, true, direction, trustPassword);
+ }
+
+ public void CreateTrustRelationship(Forest targetForest, TrustDirection direction)
+ {
+ CheckIfDisposed();
+
+ if (targetForest == null)
+ throw new ArgumentNullException("targetForest");
+
+ if (direction < TrustDirection.Inbound || direction > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("direction", (int)direction, typeof(TrustDirection));
+
+ string password = TrustHelper.CreateTrustPassword();
+
+ // first create trust on local side
+ TrustHelper.CreateTrust(_context, Name, targetForest.GetDirectoryContext(), targetForest.Name, true, direction, password);
+
+ // then create trust on remote side
+ int reverseDirection = 0;
+ if ((direction & TrustDirection.Inbound) != 0)
+ reverseDirection |= (int)TrustDirection.Outbound;
+ if ((direction & TrustDirection.Outbound) != 0)
+ reverseDirection |= (int)TrustDirection.Inbound;
+
+ TrustHelper.CreateTrust(targetForest.GetDirectoryContext(), targetForest.Name, _context, Name, true, (TrustDirection)reverseDirection, password);
+ }
+
+ public void UpdateLocalSideOfTrustRelationship(string targetForestName, string newTrustPassword)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ if (newTrustPassword == null)
+ throw new ArgumentNullException("newTrustPassword");
+
+ if (newTrustPassword.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "newTrustPassword");
+
+ TrustHelper.UpdateTrust(_context, Name, targetForestName, newTrustPassword, true);
+ }
+
+ public void UpdateLocalSideOfTrustRelationship(string targetForestName, TrustDirection newTrustDirection, string newTrustPassword)
+ {
+ CheckIfDisposed();
+
+ if (targetForestName == null)
+ throw new ArgumentNullException("targetForestName");
+
+ if (targetForestName.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "targetForestName");
+
+ if (newTrustDirection < TrustDirection.Inbound || newTrustDirection > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("newTrustDirection", (int)newTrustDirection, typeof(TrustDirection));
+
+ if (newTrustPassword == null)
+ throw new ArgumentNullException("newTrustPassword");
+
+ if (newTrustPassword.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "newTrustPassword");
+
+ TrustHelper.UpdateTrustDirection(_context, Name, targetForestName, newTrustPassword, true /*is forest*/, newTrustDirection);
+ }
+
+ public void UpdateTrustRelationship(Forest targetForest, TrustDirection newTrustDirection)
+ {
+ CheckIfDisposed();
+
+ if (targetForest == null)
+ throw new ArgumentNullException("targetForest");
+
+ if (newTrustDirection < TrustDirection.Inbound || newTrustDirection > TrustDirection.Bidirectional)
+ throw new InvalidEnumArgumentException("newTrustDirection", (int)newTrustDirection, typeof(TrustDirection));
+
+ // no we generate trust password
+ string password = TrustHelper.CreateTrustPassword();
+
+ TrustHelper.UpdateTrustDirection(_context, Name, targetForest.Name, password, true /*is forest*/, newTrustDirection);
+
+ // then create trust on remote side
+ TrustDirection reverseDirection = 0;
+ if ((newTrustDirection & TrustDirection.Inbound) != 0)
+ reverseDirection |= TrustDirection.Outbound;
+ if ((newTrustDirection & TrustDirection.Outbound) != 0)
+ reverseDirection |= TrustDirection.Inbound;
+
+ TrustHelper.UpdateTrustDirection(targetForest.GetDirectoryContext(), targetForest.Name, Name, password, true /*is forest*/, reverseDirection);
+ }
+
+ public void RepairTrustRelationship(Forest targetForest)
+ {
+ TrustDirection direction = TrustDirection.Bidirectional;
+ CheckIfDisposed();
+
+ if (targetForest == null)
+ throw new ArgumentNullException("targetForest");
+
+ // first try to reset the secure channel
+ try
+ {
+ direction = GetTrustRelationship(targetForest.Name).TrustDirection;
+
+ // verify outbound trust first
+ if ((direction & TrustDirection.Outbound) != 0)
+ {
+ TrustHelper.VerifyTrust(_context, Name, targetForest.Name, true /*is forest*/, TrustDirection.Outbound, true/*reset secure channel*/, null /* no need to go to specific server*/);
+ }
+
+ // verify inbound trust
+ if ((direction & TrustDirection.Inbound) != 0)
+ {
+ TrustHelper.VerifyTrust(targetForest.GetDirectoryContext(), targetForest.Name, Name, true/*is forest*/, TrustDirection.Outbound, true/*reset secure channel*/, null /* no need to go to specific server*/);
+ }
+ }
+ catch (ActiveDirectoryOperationException)
+ {
+ RepairTrustHelper(targetForest, direction);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ RepairTrustHelper(targetForest, direction);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetForest.Name, direction), typeof(ForestTrustRelationshipInformation), null);
+ }
+ }
+
+ public static Forest GetCurrentForest()
+ {
+ return Forest.GetForest(new DirectoryContext(DirectoryContextType.Forest));
+ }
+
+ #endregion public methods
+
+ #region public properties
+
+ public string Name
+ {
+ get
+ {
+ CheckIfDisposed();
+ return _forestDnsName;
+ }
+ }
+
+ public ReadOnlySiteCollection Sites
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedSites == null)
+ {
+ _cachedSites = new ReadOnlySiteCollection(GetSites());
+ }
+ return _cachedSites;
+ }
+ }
+
+ public DomainCollection Domains
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedDomains == null)
+ {
+ _cachedDomains = new DomainCollection(GetDomains());
+ }
+ return _cachedDomains;
+ }
+ }
+
+ public GlobalCatalogCollection GlobalCatalogs
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedGlobalCatalogs == null)
+ {
+ _cachedGlobalCatalogs = FindAllGlobalCatalogs();
+ }
+ return _cachedGlobalCatalogs;
+ }
+ }
+
+ public ApplicationPartitionCollection ApplicationPartitions
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedApplicationPartitions == null)
+ {
+ _cachedApplicationPartitions = new ApplicationPartitionCollection(GetApplicationPartitions());
+ }
+ return _cachedApplicationPartitions;
+ }
+ }
+
+ public int ForestModeLevel
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_forestModeLevel == -1)
+ {
+ _forestModeLevel = GetForestModeLevel();
+ }
+ return _forestModeLevel;
+ }
+ }
+
+ public ForestMode ForestMode
+ {
+ get
+ {
+ CheckIfDisposed();
+ // if forest mode is known cast to proper enum
+ if (ForestModeLevel <= (int)ForestMode.Windows2012R2Forest)
+ {
+ return (ForestMode)ForestModeLevel;
+ }
+ // else return unknown
+ return ForestMode.Unknown;
+ }
+ }
+
+ public Domain RootDomain
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedRootDomain == null)
+ {
+ // Domain context is created by passing the name of the forest
+ // (since the root domain and the forest have the same name)
+ DirectoryContext domainContext = Utils.GetNewDirectoryContext(Name, DirectoryContextType.Domain, _context);
+ _cachedRootDomain = new Domain(domainContext, Name);
+ }
+ return _cachedRootDomain;
+ }
+ }
+
+ public ActiveDirectorySchema Schema
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedSchema == null)
+ {
+ try
+ {
+ _cachedSchema = new ActiveDirectorySchema(_context, _directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.SchemaNamingContext));
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ }
+ return _cachedSchema;
+ }
+ }
+
+ public DomainController SchemaRoleOwner
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedSchemaRoleOwner == null)
+ {
+ _cachedSchemaRoleOwner = GetRoleOwner(ActiveDirectoryRole.SchemaRole);
+ }
+ return _cachedSchemaRoleOwner;
+ }
+ }
+
+ public DomainController NamingRoleOwner
+ {
+ get
+ {
+ CheckIfDisposed();
+ if (_cachedNamingRoleOwner == null)
+ {
+ _cachedNamingRoleOwner = GetRoleOwner(ActiveDirectoryRole.NamingRole);
+ }
+ return _cachedNamingRoleOwner;
+ }
+ }
+
+ #endregion public properties
+
+ #region private methods
+
+ internal DirectoryContext GetDirectoryContext()
+ {
+ return _context;
+ }
+
+ private int GetForestModeLevel()
+ {
+ int forestModeValue = -1;
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.RootDSE);
+ try
+ {
+ if (!rootDSE.Properties.Contains(PropertyManager.ForestFunctionality))
+ {
+ // Since this value is not set, it is a Win2000 forest (with W2K schema)
+ forestModeValue = 0;
+ }
+ else
+ {
+ forestModeValue = Int32.Parse((string)rootDSE.Properties[PropertyManager.ForestFunctionality].Value, NumberFormatInfo.InvariantInfo);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ finally
+ {
+ rootDSE.Dispose();
+ }
+ return forestModeValue;
+ }
+
+ //
+ // Returns a DomainController object for the DC that holds the the specified FSMO role
+ //
+ private DomainController GetRoleOwner(ActiveDirectoryRole role)
+ {
+ DirectoryEntry entry = null;
+ string dcName = null;
+
+ try
+ {
+ switch (role)
+ {
+ case ActiveDirectoryRole.SchemaRole:
+ {
+ entry = DirectoryEntryManager.GetDirectoryEntry(_context, _directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.SchemaNamingContext));
+ break;
+ }
+
+ case ActiveDirectoryRole.NamingRole:
+ {
+ entry = DirectoryEntryManager.GetDirectoryEntry(_context, _directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+ break;
+ }
+
+ default:
+ // should not happen since we are calling this only internally
+ Debug.Assert(false, "Forest.GetRoleOwner: Invalid role type.");
+ break;
+ }
+
+ dcName = Utils.GetDnsHostNameFromNTDSA(_context, (string)PropertyManager.GetPropertyValue(_context, entry, PropertyManager.FsmoRoleOwner));
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ finally
+ {
+ if (entry != null)
+ {
+ entry.Dispose();
+ }
+ }
+
+ // create a new context object for the domain controller passing on the
+ // credentials from the forest context
+ DirectoryContext dcContext = Utils.GetNewDirectoryContext(dcName, DirectoryContextType.DirectoryServer, _context);
+ return new DomainController(dcContext, dcName);
+ }
+
+ private ArrayList GetSites()
+ {
+ ArrayList sites = new ArrayList();
+ int result = 0;
+ IntPtr dsHandle = IntPtr.Zero;
+ IntPtr authIdentity = IntPtr.Zero;
+ IntPtr sitesPtr = IntPtr.Zero;
+
+ try
+ {
+ // get the directory handle
+ GetDSHandle(out dsHandle, out authIdentity);
+
+ // Get the sites within the forest
+ // call DsListSites
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsListSitesW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsListSites dsListSites = (NativeMethods.DsListSites)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsListSites));
+
+ result = dsListSites(dsHandle, out sitesPtr);
+ if (result == 0)
+ {
+ try
+ {
+ DsNameResult dsNameResult = new DsNameResult();
+ Marshal.PtrToStructure(sitesPtr, dsNameResult);
+ IntPtr currentItem = dsNameResult.items;
+
+ for (int i = 0; i < dsNameResult.itemCount; i++)
+ {
+ DsNameResultItem dsNameResultItem = new DsNameResultItem();
+
+ Marshal.PtrToStructure(currentItem, dsNameResultItem);
+ if (dsNameResultItem.status == NativeMethods.DsNameNoError)
+ {
+ string siteName = Utils.GetDNComponents(dsNameResultItem.name)[0].Value;
+ // an existing site
+ sites.Add(new ActiveDirectorySite(_context, siteName, true));
+ }
+
+ currentItem = IntPtr.Add(currentItem, Marshal.SizeOf(dsNameResultItem));
+ }
+ }
+ finally
+ {
+ // free the DsNameResult structure
+ if (sitesPtr != IntPtr.Zero)
+ {
+ // call DsFreeNameResultW
+ functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsFreeNameResultW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsFreeNameResultW dsFreeNameResultW = (UnsafeNativeMethods.DsFreeNameResultW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsFreeNameResultW));
+ dsFreeNameResultW(sitesPtr);
+ }
+ }
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(result, _context.GetServerName());
+ }
+ }
+ finally
+ {
+ // DsUnbind
+ if (dsHandle != (IntPtr)0)
+ {
+ Utils.FreeDSHandle(dsHandle, DirectoryContext.ADHandle);
+ }
+
+ // free the credentials object
+ if (authIdentity != (IntPtr)0)
+ {
+ Utils.FreeAuthIdentity(authIdentity, DirectoryContext.ADHandle);
+ }
+ }
+
+ return sites;
+ }
+
+ private ArrayList GetApplicationPartitions()
+ {
+ ArrayList appNCs = new ArrayList();
+
+ DirectoryEntry partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(_context, _directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+
+ // search for all the "crossRef" objects that have the
+ // ADS_SYSTEMFLAG_CR_NTDS_NC set and the SYSTEMFLAG_CR_NTDS_DOMAIN flag not set
+ // (one-level search is good enough)
+
+ // setup the directory searcher object
+
+ // build the filter
+ StringBuilder str = new StringBuilder(15);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=crossRef)(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsNC);
+ str.Append(")(!(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.803:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsDomain);
+ str.Append(")))");
+
+ string filter = str.ToString();
+ string[] propertiesToLoad = new string[2];
+ propertiesToLoad[0] = PropertyManager.DnsRoot;
+ propertiesToLoad[1] = PropertyManager.NCName;
+
+ ADSearcher searcher = new ADSearcher(partitionsEntry, filter, propertiesToLoad, SearchScope.OneLevel);
+ SearchResultCollection resCol = null;
+ try
+ {
+ resCol = searcher.FindAll();
+
+ string schemaNamingContext = _directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.SchemaNamingContext);
+ string configurationNamingContext = _directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.ConfigurationNamingContext);
+
+ foreach (SearchResult res in resCol)
+ {
+ // add the name of the appNC only if it is not
+ // the Schema or Configuration partition
+ string nCName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.NCName);
+ if ((!(nCName.Equals(schemaNamingContext)))
+ && (!(nCName.Equals(configurationNamingContext))))
+ {
+ // create a new context to be passed on to the appNC object
+ // (pass the dns name of the appliction partition as the target)
+ string dnsName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DnsRoot);
+ DirectoryContext appNCContext = Utils.GetNewDirectoryContext(dnsName, DirectoryContextType.ApplicationPartition, _context);
+ appNCs.Add(new ApplicationPartition(appNCContext, nCName, (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DnsRoot), ApplicationPartitionType.ADApplicationPartition, new DirectoryEntryManager(appNCContext)));
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ finally
+ {
+ if (resCol != null)
+ {
+ resCol.Dispose();
+ }
+ partitionsEntry.Dispose();
+ }
+ return appNCs;
+ }
+
+ private ArrayList GetDomains()
+ {
+ ArrayList domains = new ArrayList();
+ DirectoryEntry partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(_context, _directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.PartitionsContainer));
+
+ // search for all the "crossRef" objects that have the
+ // ADS_SYSTEMFLAG_CR_NTDS_NC and SYSTEMFLAG_CR_NTDS_DOMAIN flags set
+ // (one-level search is good enough)
+
+ // setup the directory searcher object
+
+ // build the filter
+ StringBuilder str = new StringBuilder(15);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=crossRef)(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsNC);
+ str.Append(")(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsDomain);
+ str.Append("))");
+
+ string filter = str.ToString();
+ string[] propertiesToLoad = new string[1];
+ propertiesToLoad[0] = PropertyManager.DnsRoot;
+
+ ADSearcher searcher = new ADSearcher(partitionsEntry, filter, propertiesToLoad, SearchScope.OneLevel);
+ SearchResultCollection resCol = null;
+ try
+ {
+ resCol = searcher.FindAll();
+
+ foreach (SearchResult res in resCol)
+ {
+ string domainName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DnsRoot);
+ DirectoryContext domainContext = Utils.GetNewDirectoryContext(domainName, DirectoryContextType.Domain, _context);
+ domains.Add(new Domain(domainContext, domainName));
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
+ }
+ finally
+ {
+ if (resCol != null)
+ {
+ resCol.Dispose();
+ }
+ partitionsEntry.Dispose();
+ }
+ return domains;
+ }
+
+ private void GetDSHandle(out IntPtr dsHandle, out IntPtr authIdentity)
+ {
+ authIdentity = Utils.GetAuthIdentity(_context, DirectoryContext.ADHandle);
+
+ // DsBind
+ if (_context.ContextType == DirectoryContextType.DirectoryServer)
+ {
+ dsHandle = Utils.GetDSHandle(_context.GetServerName(), null, authIdentity, DirectoryContext.ADHandle);
+ }
+ else
+ {
+ dsHandle = Utils.GetDSHandle(null, _context.GetServerName(), authIdentity, DirectoryContext.ADHandle);
+ }
+ }
+
+ private void CheckIfDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+
+ private TrustRelationshipInformationCollection GetTrustsHelper(string targetForestName)
+ {
+ string serverName = null;
+ IntPtr domains = (IntPtr)0;
+ int count = 0;
+ TrustRelationshipInformationCollection collection = new TrustRelationshipInformationCollection();
+ bool impersonated = false;
+ int error = 0;
+
+ // first decide which server to go to
+ serverName = Utils.GetPolicyServerName(_context, true, false, Name);
+
+ // impersonate appropriately
+ impersonated = Utils.Impersonate(_context);
+
+ // call the DS API to get trust domain information
+ try
+ {
+ try
+ {
+ error = UnsafeNativeMethods.DsEnumerateDomainTrustsW(serverName, (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_PRIMARY | (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_OUTBOUND | (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_INBOUND, out domains, out count);
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+ }
+ }
+ catch { throw; }
+
+ // check the result
+ if (error != 0)
+ throw ExceptionHelper.GetExceptionFromErrorCode(error, serverName);
+
+ try
+ {
+ // now enumerate through the collection
+ if (domains != (IntPtr)0 && count != 0)
+ {
+ IntPtr addr = (IntPtr)0;
+ for (int i = 0; i < count; i++)
+ {
+ addr = IntPtr.Add(domains, i * Marshal.SizeOf(typeof(DS_DOMAIN_TRUSTS)));
+ DS_DOMAIN_TRUSTS unmanagedTrust = new DS_DOMAIN_TRUSTS();
+ Marshal.PtrToStructure(addr, unmanagedTrust);
+
+ // whether this is the case that a paticular forest trust info is needed
+ if (targetForestName != null)
+ {
+ bool sameTarget = false;
+ string tmpDNSName = null;
+ string tmpNetBIOSName = null;
+
+ if (unmanagedTrust.DnsDomainName != (IntPtr)0)
+ tmpDNSName = Marshal.PtrToStringUni(unmanagedTrust.DnsDomainName);
+ if (unmanagedTrust.NetbiosDomainName != (IntPtr)0)
+ tmpNetBIOSName = Marshal.PtrToStringUni(unmanagedTrust.NetbiosDomainName);
+
+ // check whether it is the same target
+ if (tmpDNSName != null && Utils.Compare(targetForestName, tmpDNSName) == 0)
+ sameTarget = true;
+ else if (tmpNetBIOSName != null && Utils.Compare(targetForestName, tmpNetBIOSName) == 0)
+ sameTarget = true;
+
+ if (!sameTarget)
+ continue;
+ }
+
+ // if it is up level trust and forest attribute is set
+ if (unmanagedTrust.TrustType == TrustHelper.TRUST_TYPE_UPLEVEL && ((unmanagedTrust.TrustAttributes & (int)TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_FOREST_TRANSITIVE) != 0))
+ {
+ // we don't want to include self
+ if ((unmanagedTrust.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_PRIMARY) != 0)
+ continue;
+
+ TrustRelationshipInformation trust = new ForestTrustRelationshipInformation(_context, Name, unmanagedTrust, TrustType.Forest);
+ collection.Add(trust);
+ }
+ }
+ }
+ return collection;
+ }
+ finally
+ {
+ if (domains != (IntPtr)0)
+ UnsafeNativeMethods.NetApiBufferFree(domains);
+ }
+ }
+
+ private void RepairTrustHelper(Forest targetForest, TrustDirection direction)
+ {
+ // no we try changing trust password on both sides
+ string password = TrustHelper.CreateTrustPassword();
+
+ // first reset trust password on remote side
+ string targetServerName = TrustHelper.UpdateTrust(targetForest.GetDirectoryContext(), targetForest.Name, Name, password, true /*is forest*/);
+
+ // then reset trust password on local side
+ string sourceServerName = TrustHelper.UpdateTrust(_context, Name, targetForest.Name, password, true /*is forest*/);
+
+ // last we reset the secure channel again to make sure info is replicated and trust is indeed ready now
+
+ // verify outbound trust first
+ if ((direction & TrustDirection.Outbound) != 0)
+ {
+ try
+ {
+ TrustHelper.VerifyTrust(_context, Name, targetForest.Name, true /*is forest*/, TrustDirection.Outbound, true/*reset secure channel*/, targetServerName /* need to specify which target server */);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetForest.Name, direction), typeof(ForestTrustRelationshipInformation), null);
+ }
+ }
+
+ // verify inbound trust
+ if ((direction & TrustDirection.Inbound) != 0)
+ {
+ try
+ {
+ TrustHelper.VerifyTrust(targetForest.GetDirectoryContext(), targetForest.Name, Name, true/*is forest*/, TrustDirection.Outbound, true/*reset secure channel*/, sourceServerName /* need to specify which target server */);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, Name, targetForest.Name, direction), typeof(ForestTrustRelationshipInformation), null);
+ }
+ }
+ }
+
+ #endregion private methods
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustCollision.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustCollision.cs
new file mode 100644
index 0000000000..aca9bb97f1
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustCollision.cs
@@ -0,0 +1,99 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Collections.Specialized;
+ using System.Diagnostics;
+
+ public class ForestTrustRelationshipCollision
+ {
+ private ForestTrustCollisionType _type;
+ private TopLevelNameCollisionOptions _tlnFlag;
+ private DomainCollisionOptions _domainFlag;
+ private string _record = null;
+
+ internal ForestTrustRelationshipCollision(ForestTrustCollisionType collisionType, TopLevelNameCollisionOptions TLNFlag, DomainCollisionOptions domainFlag, string record)
+ {
+ _type = collisionType;
+ _tlnFlag = TLNFlag;
+ _domainFlag = domainFlag;
+ _record = record;
+ }
+
+ public ForestTrustCollisionType CollisionType
+ {
+ get
+ {
+ return _type;
+ }
+ }
+
+ public TopLevelNameCollisionOptions TopLevelNameCollisionOption
+ {
+ get
+ {
+ return _tlnFlag;
+ }
+ }
+
+ public DomainCollisionOptions DomainCollisionOption
+ {
+ get
+ {
+ return _domainFlag;
+ }
+ }
+
+ public string CollisionRecord
+ {
+ get
+ {
+ return _record;
+ }
+ }
+ }
+
+ public class ForestTrustRelationshipCollisionCollection : ReadOnlyCollectionBase
+ {
+ internal ForestTrustRelationshipCollisionCollection() { }
+
+ public ForestTrustRelationshipCollision this[int index]
+ {
+ get
+ {
+ return (ForestTrustRelationshipCollision)InnerList[index];
+ }
+ }
+
+ public bool Contains(ForestTrustRelationshipCollision collision)
+ {
+ if (collision == null)
+ throw new ArgumentNullException("collision");
+
+ return InnerList.Contains(collision);
+ }
+
+ public int IndexOf(ForestTrustRelationshipCollision collision)
+ {
+ if (collision == null)
+ throw new ArgumentNullException("collision");
+
+ return InnerList.IndexOf(collision);
+ }
+
+ public void CopyTo(ForestTrustRelationshipCollision[] array, int index)
+ {
+ InnerList.CopyTo(array, index);
+ }
+
+ internal int Add(ForestTrustRelationshipCollision collision)
+ {
+ return InnerList.Add(collision);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustDomainInfoCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustDomainInfoCollection.cs
new file mode 100644
index 0000000000..c4176cc756
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustDomainInfoCollection.cs
@@ -0,0 +1,50 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+
+ public class ForestTrustDomainInfoCollection : ReadOnlyCollectionBase
+ {
+ internal ForestTrustDomainInfoCollection() { }
+
+ public ForestTrustDomainInformation this[int index]
+ {
+ get
+ {
+ return (ForestTrustDomainInformation)InnerList[index];
+ }
+ }
+
+ public bool Contains(ForestTrustDomainInformation information)
+ {
+ if (information == null)
+ throw new ArgumentNullException("information");
+
+ return InnerList.Contains(information);
+ }
+
+ public int IndexOf(ForestTrustDomainInformation information)
+ {
+ if (information == null)
+ throw new ArgumentNullException("information");
+
+ return InnerList.IndexOf(information);
+ }
+
+ public void CopyTo(ForestTrustDomainInformation[] array, int index)
+ {
+ InnerList.CopyTo(array, index);
+ }
+
+ internal int Add(ForestTrustDomainInformation info)
+ {
+ return InnerList.Add(info);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustDomainInformation.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustDomainInformation.cs
new file mode 100644
index 0000000000..2dc86aade0
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustDomainInformation.cs
@@ -0,0 +1,97 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+ using System.ComponentModel;
+
+ public enum ForestTrustDomainStatus
+ {
+ Enabled = 0,
+ SidAdminDisabled = 1,
+ SidConflictDisabled = 2,
+ NetBiosNameAdminDisabled = 4,
+ NetBiosNameConflictDisabled = 8
+ }
+
+ public class ForestTrustDomainInformation
+ {
+ private string _dnsName = null;
+ private string _nbName = null;
+ private string _sid = null;
+ private ForestTrustDomainStatus _status;
+ internal LARGE_INTEGER time;
+
+ internal ForestTrustDomainInformation(int flag, LSA_FOREST_TRUST_DOMAIN_INFO domainInfo, LARGE_INTEGER time)
+ {
+ _status = (ForestTrustDomainStatus)flag;
+ _dnsName = Marshal.PtrToStringUni(domainInfo.DNSNameBuffer, domainInfo.DNSNameLength / 2);
+ _nbName = Marshal.PtrToStringUni(domainInfo.NetBIOSNameBuffer, domainInfo.NetBIOSNameLength / 2);
+ IntPtr ptr = (IntPtr)0;
+ int result = UnsafeNativeMethods.ConvertSidToStringSidW(domainInfo.sid, ref ptr);
+ if (result == 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+
+ try
+ {
+ _sid = Marshal.PtrToStringUni(ptr);
+ }
+ finally
+ {
+ UnsafeNativeMethods.LocalFree(ptr);
+ }
+
+ this.time = time;
+ }
+
+ public string DnsName
+ {
+ get
+ {
+ return _dnsName;
+ }
+ }
+
+ public string NetBiosName
+ {
+ get
+ {
+ return _nbName;
+ }
+ }
+
+ public string DomainSid
+ {
+ get
+ {
+ return _sid;
+ }
+ }
+
+ public ForestTrustDomainStatus Status
+ {
+ get
+ {
+ return _status;
+ }
+ set
+ {
+ if (value != ForestTrustDomainStatus.Enabled &&
+ value != ForestTrustDomainStatus.SidAdminDisabled &&
+ value != ForestTrustDomainStatus.SidConflictDisabled &&
+ value != ForestTrustDomainStatus.NetBiosNameAdminDisabled &&
+ value != ForestTrustDomainStatus.NetBiosNameConflictDisabled)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(ForestTrustDomainStatus));
+
+ _status = value;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustRelationshipInformation.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustRelationshipInformation.cs
new file mode 100644
index 0000000000..db6f19f675
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ForestTrustRelationshipInformation.cs
@@ -0,0 +1,476 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Collections.Specialized;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ForestTrustRelationshipInformation : TrustRelationshipInformation
+ {
+ private TopLevelNameCollection _topLevelNames = new TopLevelNameCollection();
+ private StringCollection _excludedNames = new StringCollection();
+ private ForestTrustDomainInfoCollection _domainInfo = new ForestTrustDomainInfoCollection();
+ private ArrayList _binaryData = new ArrayList();
+ private Hashtable _excludedNameTime = new Hashtable();
+ private ArrayList _binaryDataTime = new ArrayList();
+ internal bool retrieved = false;
+
+ internal ForestTrustRelationshipInformation(DirectoryContext context, string source, DS_DOMAIN_TRUSTS unmanagedTrust, TrustType type)
+ {
+ string tmpDNSName = null;
+ string tmpNetBIOSName = null;
+
+ // security context
+ this.context = context;
+ // source
+ this.source = source;
+ // target
+ if (unmanagedTrust.DnsDomainName != (IntPtr)0)
+ tmpDNSName = Marshal.PtrToStringUni(unmanagedTrust.DnsDomainName);
+ if (unmanagedTrust.NetbiosDomainName != (IntPtr)0)
+ tmpNetBIOSName = Marshal.PtrToStringUni(unmanagedTrust.NetbiosDomainName);
+
+ this.target = (tmpDNSName == null ? tmpNetBIOSName : tmpDNSName);
+ // direction
+ if ((unmanagedTrust.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_OUTBOUND) != 0 &&
+ (unmanagedTrust.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_INBOUND) != 0)
+ direction = TrustDirection.Bidirectional;
+ else if ((unmanagedTrust.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_OUTBOUND) != 0)
+ direction = TrustDirection.Outbound;
+ else if ((unmanagedTrust.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_INBOUND) != 0)
+ direction = TrustDirection.Inbound;
+ // type
+ this.type = type;
+ }
+
+ public TopLevelNameCollection TopLevelNames
+ {
+ get
+ {
+ if (!retrieved)
+ GetForestTrustInfoHelper();
+ return _topLevelNames;
+ }
+ }
+
+ public StringCollection ExcludedTopLevelNames
+ {
+ get
+ {
+ if (!retrieved)
+ GetForestTrustInfoHelper();
+ return _excludedNames;
+ }
+ }
+
+ public ForestTrustDomainInfoCollection TrustedDomainInformation
+ {
+ get
+ {
+ if (!retrieved)
+ GetForestTrustInfoHelper();
+ return _domainInfo;
+ }
+ }
+
+ public void Save()
+ {
+ int count = 0;
+ IntPtr records = (IntPtr)0;
+ int currentCount = 0;
+ IntPtr tmpPtr = (IntPtr)0;
+ IntPtr forestInfo = (IntPtr)0;
+ PolicySafeHandle handle = null;
+ LSA_UNICODE_STRING trustedDomainName;
+ IntPtr collisionInfo = (IntPtr)0;
+ ArrayList ptrList = new ArrayList();
+ ArrayList sidList = new ArrayList();
+ bool impersonated = false;
+ IntPtr target = (IntPtr)0;
+ string serverName = null;
+ IntPtr fileTime = (IntPtr)0;
+
+ // first get the count of all the records
+ int toplevelNamesCount = TopLevelNames.Count;
+ int excludedNamesCount = ExcludedTopLevelNames.Count;
+ int trustedDomainCount = TrustedDomainInformation.Count;
+ int binaryDataCount = 0;
+
+ checked
+ {
+ count += toplevelNamesCount;
+ count += excludedNamesCount;
+ count += trustedDomainCount;
+ if (_binaryData.Count != 0)
+ {
+ binaryDataCount = _binaryData.Count;
+ // for the ForestTrustRecordTypeLast record
+ count++;
+ count += binaryDataCount;
+ }
+
+ // allocate the memory for all the records
+ records = Marshal.AllocHGlobal(count * Marshal.SizeOf(typeof(IntPtr)));
+ }
+
+ try
+ {
+ try
+ {
+ IntPtr ptr = (IntPtr)0;
+ fileTime = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(FileTime)));
+ UnsafeNativeMethods.GetSystemTimeAsFileTime(fileTime);
+
+ // set the time
+ FileTime currentTime = new FileTime();
+ Marshal.PtrToStructure(fileTime, currentTime);
+
+ for (int i = 0; i < toplevelNamesCount; i++)
+ {
+ // now begin to construct top leve name record
+ LSA_FOREST_TRUST_RECORD record = new LSA_FOREST_TRUST_RECORD();
+ record.Flags = (int)_topLevelNames[i].Status;
+ record.ForestTrustType = LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelName;
+ TopLevelName TLN = _topLevelNames[i];
+ record.Time = TLN.time;
+ record.TopLevelName = new LSA_UNICODE_STRING();
+ ptr = Marshal.StringToHGlobalUni(TLN.Name);
+ ptrList.Add(ptr);
+ UnsafeNativeMethods.RtlInitUnicodeString(record.TopLevelName, ptr);
+
+ tmpPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_RECORD)));
+ ptrList.Add(tmpPtr);
+ Marshal.StructureToPtr(record, tmpPtr, false);
+
+ Marshal.WriteIntPtr(records, Marshal.SizeOf(typeof(IntPtr)) * currentCount, tmpPtr);
+
+ currentCount++;
+ }
+
+ for (int i = 0; i < excludedNamesCount; i++)
+ {
+ // now begin to construct excluded top leve name record
+ LSA_FOREST_TRUST_RECORD record = new LSA_FOREST_TRUST_RECORD();
+ record.Flags = 0;
+ record.ForestTrustType = LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelNameEx;
+ if (_excludedNameTime.Contains(_excludedNames[i]))
+ {
+ record.Time = (LARGE_INTEGER)_excludedNameTime[i];
+ }
+ else
+ {
+ record.Time = new LARGE_INTEGER();
+ record.Time.lowPart = currentTime.lower;
+ record.Time.highPart = currentTime.higher;
+ }
+ record.TopLevelName = new LSA_UNICODE_STRING();
+ ptr = Marshal.StringToHGlobalUni(_excludedNames[i]);
+ ptrList.Add(ptr);
+ UnsafeNativeMethods.RtlInitUnicodeString(record.TopLevelName, ptr);
+ tmpPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_RECORD)));
+ ptrList.Add(tmpPtr);
+ Marshal.StructureToPtr(record, tmpPtr, false);
+
+ Marshal.WriteIntPtr(records, Marshal.SizeOf(typeof(IntPtr)) * currentCount, tmpPtr);
+
+ currentCount++;
+ }
+
+ for (int i = 0; i < trustedDomainCount; i++)
+ {
+ // now begin to construct domain info record
+ LSA_FOREST_TRUST_RECORD record = new LSA_FOREST_TRUST_RECORD();
+ record.Flags = (int)_domainInfo[i].Status;
+ record.ForestTrustType = LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustDomainInfo;
+ ForestTrustDomainInformation tmp = _domainInfo[i];
+ record.Time = tmp.time;
+ IntPtr pSid = (IntPtr)0;
+ IntPtr stringSid = (IntPtr)0;
+ stringSid = Marshal.StringToHGlobalUni(tmp.DomainSid);
+ ptrList.Add(stringSid);
+ int result = UnsafeNativeMethods.ConvertStringSidToSidW(stringSid, ref pSid);
+ if (result == 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ record.DomainInfo = new LSA_FOREST_TRUST_DOMAIN_INFO();
+ record.DomainInfo.sid = pSid;
+ sidList.Add(pSid);
+ record.DomainInfo.DNSNameBuffer = Marshal.StringToHGlobalUni(tmp.DnsName);
+ ptrList.Add(record.DomainInfo.DNSNameBuffer);
+ record.DomainInfo.DNSNameLength = (short)(tmp.DnsName == null ? 0 : tmp.DnsName.Length * 2); // sizeof(WCHAR)
+ record.DomainInfo.DNSNameMaximumLength = (short)(tmp.DnsName == null ? 0 : tmp.DnsName.Length * 2);
+ record.DomainInfo.NetBIOSNameBuffer = Marshal.StringToHGlobalUni(tmp.NetBiosName);
+ ptrList.Add(record.DomainInfo.NetBIOSNameBuffer);
+ record.DomainInfo.NetBIOSNameLength = (short)(tmp.NetBiosName == null ? 0 : tmp.NetBiosName.Length * 2);
+ record.DomainInfo.NetBIOSNameMaximumLength = (short)(tmp.NetBiosName == null ? 0 : tmp.NetBiosName.Length * 2);
+ tmpPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_RECORD)));
+ ptrList.Add(tmpPtr);
+ Marshal.StructureToPtr(record, tmpPtr, false);
+
+ Marshal.WriteIntPtr(records, Marshal.SizeOf(typeof(IntPtr)) * currentCount, tmpPtr);
+
+ currentCount++;
+ }
+
+ if (binaryDataCount > 0)
+ {
+ // now begin to construct ForestTrustRecordTypeLast
+ LSA_FOREST_TRUST_RECORD lastRecord = new LSA_FOREST_TRUST_RECORD();
+ lastRecord.Flags = 0;
+ lastRecord.ForestTrustType = LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustRecordTypeLast;
+ tmpPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_RECORD)));
+ ptrList.Add(tmpPtr);
+ Marshal.StructureToPtr(lastRecord, tmpPtr, false);
+ Marshal.WriteIntPtr(records, Marshal.SizeOf(typeof(IntPtr)) * currentCount, tmpPtr);
+ currentCount++;
+
+ for (int i = 0; i < binaryDataCount; i++)
+ {
+ // now begin to construct excluded top leve name record
+ LSA_FOREST_TRUST_RECORD record = new LSA_FOREST_TRUST_RECORD();
+ record.Flags = 0;
+ record.Time = (LARGE_INTEGER)_binaryDataTime[i];
+ record.Data.Length = ((byte[])_binaryData[i]).Length;
+ if (record.Data.Length == 0)
+ {
+ record.Data.Buffer = (IntPtr)0;
+ }
+ else
+ {
+ record.Data.Buffer = Marshal.AllocHGlobal(record.Data.Length);
+ ptrList.Add(record.Data.Buffer);
+ Marshal.Copy((byte[])_binaryData[i], 0, record.Data.Buffer, record.Data.Length);
+ }
+ tmpPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_RECORD)));
+ ptrList.Add(tmpPtr);
+ Marshal.StructureToPtr(record, tmpPtr, false);
+
+ Marshal.WriteIntPtr(records, Marshal.SizeOf(typeof(IntPtr)) * currentCount, tmpPtr);
+
+ currentCount++;
+ }
+ }
+
+ // finally construct the LSA_FOREST_TRUST_INFORMATION
+ LSA_FOREST_TRUST_INFORMATION trustInformation = new LSA_FOREST_TRUST_INFORMATION();
+ trustInformation.RecordCount = count;
+ trustInformation.Entries = records;
+ forestInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_FOREST_TRUST_INFORMATION)));
+ Marshal.StructureToPtr(trustInformation, forestInfo, false);
+
+ // get policy server name
+ serverName = Utils.GetPolicyServerName(context, true, true, SourceName);
+
+ // do impersonation first
+ impersonated = Utils.Impersonate(context);
+
+ // get the policy handle
+ handle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+
+ // get the target name
+ trustedDomainName = new LSA_UNICODE_STRING();
+ target = Marshal.StringToHGlobalUni(TargetName);
+ UnsafeNativeMethods.RtlInitUnicodeString(trustedDomainName, target);
+
+ // call the unmanaged function
+ int error = UnsafeNativeMethods.LsaSetForestTrustInformation(handle, trustedDomainName, forestInfo, 1, out collisionInfo);
+ if (error != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(UnsafeNativeMethods.LsaNtStatusToWinError(error), serverName);
+ }
+
+ // there is collision, throw proper exception so user can deal with it
+ if (collisionInfo != (IntPtr)0)
+ {
+ throw ExceptionHelper.CreateForestTrustCollisionException(collisionInfo);
+ }
+
+ // commit the changes
+ error = UnsafeNativeMethods.LsaSetForestTrustInformation(handle, trustedDomainName, forestInfo, 0, out collisionInfo);
+ if (error != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(error, serverName);
+ }
+
+ // now next time property is invoked, we need to go to the server
+ retrieved = false;
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+
+ // release the memory
+ for (int i = 0; i < ptrList.Count; i++)
+ {
+ Marshal.FreeHGlobal((IntPtr)ptrList[i]);
+ }
+
+ for (int i = 0; i < sidList.Count; i++)
+ {
+ UnsafeNativeMethods.LocalFree((IntPtr)sidList[i]);
+ }
+
+ if (records != (IntPtr)0)
+ {
+ Marshal.FreeHGlobal(records);
+ }
+
+ if (forestInfo != (IntPtr)0)
+ {
+ Marshal.FreeHGlobal(forestInfo);
+ }
+
+ if (collisionInfo != (IntPtr)0)
+ UnsafeNativeMethods.LsaFreeMemory(collisionInfo);
+
+ if (target != (IntPtr)0)
+ Marshal.FreeHGlobal(target);
+
+ if (fileTime != (IntPtr)0)
+ Marshal.FreeHGlobal(fileTime);
+ }
+ }
+ catch { throw; }
+ }
+
+ private void GetForestTrustInfoHelper()
+ {
+ IntPtr forestTrustInfo = (IntPtr)0;
+ PolicySafeHandle handle = null;
+ LSA_UNICODE_STRING tmpName = null;
+ bool impersonated = false;
+ IntPtr targetPtr = (IntPtr)0;
+ string serverName = null;
+
+ TopLevelNameCollection tmpTLNs = new TopLevelNameCollection();
+ StringCollection tmpExcludedTLNs = new StringCollection();
+ ForestTrustDomainInfoCollection tmpDomainInformation = new ForestTrustDomainInfoCollection();
+
+ // internal members
+ ArrayList tmpBinaryData = new ArrayList();
+ Hashtable tmpExcludedNameTime = new Hashtable();
+ ArrayList tmpBinaryDataTime = new ArrayList();
+
+ try
+ {
+ try
+ {
+ // get the target name
+ tmpName = new LSA_UNICODE_STRING();
+ targetPtr = Marshal.StringToHGlobalUni(TargetName);
+ UnsafeNativeMethods.RtlInitUnicodeString(tmpName, targetPtr);
+
+ serverName = Utils.GetPolicyServerName(context, true, false, source);
+
+ // do impersonation
+ impersonated = Utils.Impersonate(context);
+
+ // get the policy handle
+ handle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+
+ int result = UnsafeNativeMethods.LsaQueryForestTrustInformation(handle, tmpName, ref forestTrustInfo);
+ // check the result
+ if (result != 0)
+ {
+ int win32Error = UnsafeNativeMethods.LsaNtStatusToWinError(result);
+ if (win32Error != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error, serverName);
+ }
+ }
+
+ try
+ {
+ if (forestTrustInfo != (IntPtr)0)
+ {
+ LSA_FOREST_TRUST_INFORMATION trustInfo = new LSA_FOREST_TRUST_INFORMATION();
+ Marshal.PtrToStructure(forestTrustInfo, trustInfo);
+
+ int count = trustInfo.RecordCount;
+ IntPtr addr = (IntPtr)0;
+ for (int i = 0; i < count; i++)
+ {
+ addr = Marshal.ReadIntPtr(trustInfo.Entries, i * Marshal.SizeOf(typeof(IntPtr)));
+ LSA_FOREST_TRUST_RECORD record = new LSA_FOREST_TRUST_RECORD();
+ Marshal.PtrToStructure(addr, record);
+
+ if (record.ForestTrustType == LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelName)
+ {
+ IntPtr myPtr = IntPtr.Add(addr, 16);
+ Marshal.PtrToStructure(myPtr, record.TopLevelName);
+ TopLevelName TLN = new TopLevelName(record.Flags, record.TopLevelName, record.Time);
+ tmpTLNs.Add(TLN);
+ }
+ else if (record.ForestTrustType == LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelNameEx)
+ {
+ // get the excluded TLN and put it in our collection
+ IntPtr myPtr = IntPtr.Add(addr, 16);
+ Marshal.PtrToStructure(myPtr, record.TopLevelName);
+ string excludedName = Marshal.PtrToStringUni(record.TopLevelName.Buffer, record.TopLevelName.Length / 2);
+ tmpExcludedTLNs.Add(excludedName);
+ tmpExcludedNameTime.Add(excludedName, record.Time);
+ }
+ else if (record.ForestTrustType == LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustDomainInfo)
+ {
+ ForestTrustDomainInformation dom = new ForestTrustDomainInformation(record.Flags, record.DomainInfo, record.Time);
+ tmpDomainInformation.Add(dom);
+ }
+ else if (record.ForestTrustType == LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustRecordTypeLast)
+ {
+ // enumeration is done, but we might still have some unrecognized entries after that
+ continue;
+ }
+ else
+ {
+ int length = record.Data.Length;
+ byte[] byteArray = new byte[length];
+ if ((record.Data.Buffer != (IntPtr)0) && (length != 0))
+ {
+ Marshal.Copy(record.Data.Buffer, byteArray, 0, length);
+ }
+ tmpBinaryData.Add(byteArray);
+ tmpBinaryDataTime.Add(record.Time);
+ }
+ }
+ }
+ }
+ finally
+ {
+ UnsafeNativeMethods.LsaFreeMemory(forestTrustInfo);
+ }
+
+ _topLevelNames = tmpTLNs;
+ _excludedNames = tmpExcludedTLNs;
+ _domainInfo = tmpDomainInformation;
+
+ _binaryData = tmpBinaryData;
+ _excludedNameTime = tmpExcludedNameTime;
+ _binaryDataTime = tmpBinaryDataTime;
+
+ // mark it as retrieved
+ retrieved = true;
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+
+ if (targetPtr != (IntPtr)0)
+ {
+ Marshal.FreeHGlobal(targetPtr);
+ }
+ }
+ }
+ catch { throw; }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/GlobalCatalog.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/GlobalCatalog.cs
new file mode 100644
index 0000000000..c3de387ff5
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/GlobalCatalog.cs
@@ -0,0 +1,491 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.ComponentModel;
+ using System.Security.Principal;
+ using System.Runtime.InteropServices;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class GlobalCatalog : DomainController
+ {
+ // private variables
+ private ActiveDirectorySchema _schema = null;
+ private bool _disabled = false;
+
+ #region constructors
+ internal GlobalCatalog(DirectoryContext context, string globalCatalogName)
+ : base(context, globalCatalogName)
+ { }
+
+ internal GlobalCatalog(DirectoryContext context, string globalCatalogName, DirectoryEntryManager directoryEntryMgr)
+ : base(context, globalCatalogName, directoryEntryMgr)
+ { }
+ #endregion constructors
+
+ #region public methods
+
+ public static GlobalCatalog GetGlobalCatalog(DirectoryContext context)
+ {
+ string gcDnsName = null;
+ bool isGlobalCatalog = false;
+ DirectoryEntryManager directoryEntryMgr = null;
+
+ // check that the context argument is not null
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // target should be GC
+ if (context.ContextType != DirectoryContextType.DirectoryServer)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeGC), "context");
+ }
+
+ // target should be a server
+ if (!(context.isServer()))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.GCNotFound, context.Name), typeof(GlobalCatalog), context.Name);
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ try
+ {
+ // Get dns name of the dc
+ // by binding to root dse and getting the "dnsHostName" attribute
+ // (also check that the "isGlobalCatalogReady" attribute is true)
+ directoryEntryMgr = new DirectoryEntryManager(context);
+ DirectoryEntry rootDSE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ if (!Utils.CheckCapability(rootDSE, Capability.ActiveDirectory))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.GCNotFound, context.Name), typeof(GlobalCatalog), context.Name);
+ }
+
+ gcDnsName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName);
+ isGlobalCatalog = (bool)Boolean.Parse((string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.IsGlobalCatalogReady));
+ if (!isGlobalCatalog)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.GCNotFound, context.Name), typeof(GlobalCatalog), context.Name);
+ }
+ }
+ catch (COMException e)
+ {
+ int errorCode = e.ErrorCode;
+
+ if (errorCode == unchecked((int)0x8007203a))
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.GCNotFound, context.Name), typeof(GlobalCatalog), context.Name);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ return new GlobalCatalog(context, gcDnsName, directoryEntryMgr);
+ }
+
+ public static new GlobalCatalog FindOne(DirectoryContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Forest)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeForest), "context");
+ }
+
+ return FindOneWithCredentialValidation(context, null, 0);
+ }
+
+ public static new GlobalCatalog FindOne(DirectoryContext context, string siteName)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Forest)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeForest), "context");
+ }
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return FindOneWithCredentialValidation(context, siteName, 0);
+ }
+
+ public static new GlobalCatalog FindOne(DirectoryContext context, LocatorOptions flag)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Forest)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeForest), "context");
+ }
+
+ return FindOneWithCredentialValidation(context, null, flag);
+ }
+
+ public static new GlobalCatalog FindOne(DirectoryContext context, string siteName, LocatorOptions flag)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Forest)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeForest), "context");
+ }
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ return FindOneWithCredentialValidation(context, siteName, flag);
+ }
+
+ public static new GlobalCatalogCollection FindAll(DirectoryContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Forest)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeForest), "context");
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ return FindAllInternal(context, null);
+ }
+
+ public static new GlobalCatalogCollection FindAll(DirectoryContext context, string siteName)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ if (context.ContextType != DirectoryContextType.Forest)
+ {
+ throw new ArgumentException(Res.GetString(Res.TargetShouldBeForest), "context");
+ }
+
+ if (siteName == null)
+ {
+ throw new ArgumentNullException("siteName");
+ }
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ return FindAllInternal(context, siteName);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override GlobalCatalog EnableGlobalCatalog()
+ {
+ CheckIfDisposed();
+ throw new InvalidOperationException(Res.GetString(Res.CannotPerformOnGCObject));
+ }
+
+ public DomainController DisableGlobalCatalog()
+ {
+ CheckIfDisposed();
+ CheckIfDisabled();
+
+ // bind to the server object
+ DirectoryEntry serverNtdsaEntry = directoryEntryMgr.GetCachedDirectoryEntry(NtdsaObjectName);
+
+ // reset the NTDSDSA_OPT_IS_GC flag on the "options" property
+ int options = 0;
+
+ try
+ {
+ if (serverNtdsaEntry.Properties[PropertyManager.Options].Value != null)
+ {
+ options = (int)serverNtdsaEntry.Properties[PropertyManager.Options].Value;
+ }
+
+ serverNtdsaEntry.Properties[PropertyManager.Options].Value = options & (~1);
+ serverNtdsaEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ // mark as disbaled
+ _disabled = true;
+
+ // return a domain controller object
+ return new DomainController(context, Name);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override bool IsGlobalCatalog()
+ {
+ CheckIfDisposed();
+ CheckIfDisabled();
+
+ // since this is a global catalog object, this should always return true
+ return true;
+ }
+
+ public ReadOnlyActiveDirectorySchemaPropertyCollection FindAllProperties()
+ {
+ CheckIfDisposed();
+ CheckIfDisabled();
+
+ // create an ActiveDirectorySchema object
+ if (_schema == null)
+ {
+ string schemaNC = null;
+ try
+ {
+ schemaNC = directoryEntryMgr.ExpandWellKnownDN(WellKnownDN.SchemaNamingContext);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ DirectoryContext schemaContext = Utils.GetNewDirectoryContext(Name, DirectoryContextType.DirectoryServer, context);
+ _schema = new ActiveDirectorySchema(context, schemaNC);
+ }
+
+ // return the global catalog replicated properties
+ return _schema.FindAllProperties(PropertyTypes.InGlobalCatalog);
+ }
+
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DirectoryServicesPermission(SecurityAction.InheritanceDemand, Unrestricted = true)
+ ]
+ public override DirectorySearcher GetDirectorySearcher()
+ {
+ CheckIfDisposed();
+ CheckIfDisabled();
+
+ return InternalGetDirectorySearcher();
+ }
+
+ #endregion public methods
+
+ #region private methods
+
+ private void CheckIfDisabled()
+ {
+ if (_disabled)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.GCDisabled));
+ }
+ }
+
+ internal static new GlobalCatalog FindOneWithCredentialValidation(DirectoryContext context, string siteName, LocatorOptions flag)
+ {
+ GlobalCatalog gc;
+ bool retry = false;
+ bool credsValidated = false;
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // authenticate against this GC to validate the credentials
+ gc = FindOneInternal(context, context.Name, siteName, flag);
+ try
+ {
+ ValidateCredential(gc, context);
+ credsValidated = true;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8007203a))
+ {
+ // server is down , so try again with force rediscovery if the flags did not already contain force rediscovery
+ if ((flag & LocatorOptions.ForceRediscovery) == 0)
+ {
+ retry = true;
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.GCNotFoundInForest, context.Name), typeof(GlobalCatalog), null);
+ }
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ finally
+ {
+ if (!credsValidated)
+ {
+ gc.Dispose();
+ }
+ }
+
+ if (retry)
+ {
+ credsValidated = false;
+ gc = FindOneInternal(context, context.Name, siteName, flag | LocatorOptions.ForceRediscovery);
+ try
+ {
+ ValidateCredential(gc, context);
+ credsValidated = true;
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8007203a))
+ {
+ // server is down
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.GCNotFoundInForest, context.Name), typeof(GlobalCatalog), null);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ finally
+ {
+ if (!credsValidated)
+ {
+ gc.Dispose();
+ }
+ }
+ }
+
+ return gc;
+ }
+
+ internal static new GlobalCatalog FindOneInternal(DirectoryContext context, string forestName, string siteName, LocatorOptions flag)
+ {
+ DomainControllerInfo domainControllerInfo;
+ int errorCode = 0;
+
+ if (siteName != null && siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ // check that the flags passed have only the valid bits set
+ if (((long)flag & (~((long)LocatorOptions.AvoidSelf | (long)LocatorOptions.ForceRediscovery | (long)LocatorOptions.KdcRequired | (long)LocatorOptions.TimeServerRequired | (long)LocatorOptions.WriteableRequired))) != 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidFlags), "flag");
+ }
+
+ if (forestName == null)
+ {
+ // get the dns name of the logged on forest
+ DomainControllerInfo tempDomainControllerInfo;
+ int error = Locator.DsGetDcNameWrapper(null, DirectoryContext.GetLoggedOnDomain(), null, (long)PrivateLocatorFlags.DirectoryServicesRequired, out tempDomainControllerInfo);
+
+ if (error == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ // throw not found exception
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ContextNotAssociatedWithDomain), typeof(GlobalCatalog), null);
+ }
+ else if (error != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+
+ Debug.Assert(tempDomainControllerInfo.DnsForestName != null);
+ forestName = tempDomainControllerInfo.DnsForestName;
+ }
+
+ // call DsGetDcName
+ errorCode = Locator.DsGetDcNameWrapper(null, forestName, siteName, (long)flag | (long)(PrivateLocatorFlags.GCRequired | PrivateLocatorFlags.DirectoryServicesRequired), out domainControllerInfo);
+
+ if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.GCNotFoundInForest, forestName), typeof(GlobalCatalog), null);
+ }
+ // this can only occur when flag is being explicitly passed (since the flags that we pass internally are valid)
+ if (errorCode == NativeMethods.ERROR_INVALID_FLAGS)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidFlags), "flag");
+ }
+ else if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+
+ // create a GlobalCatalog object
+ // the name is returned in the form "\\servername", so skip the "\\"
+ Debug.Assert(domainControllerInfo.DomainControllerName.Length > 2);
+ string globalCatalogName = domainControllerInfo.DomainControllerName.Substring(2);
+
+ // create a new context object for the global catalog
+ DirectoryContext gcContext = Utils.GetNewDirectoryContext(globalCatalogName, DirectoryContextType.DirectoryServer, context);
+
+ return new GlobalCatalog(gcContext, globalCatalogName);
+ }
+
+ internal static GlobalCatalogCollection FindAllInternal(DirectoryContext context, string siteName)
+ {
+ ArrayList gcList = new ArrayList();
+
+ if (siteName != null && siteName.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "siteName");
+ }
+
+ foreach (string gcName in Utils.GetReplicaList(context, null /* not specific to any partition */, siteName, false /* isDefaultNC */, false /* isADAM */, true /* mustBeGC */))
+ {
+ DirectoryContext gcContext = Utils.GetNewDirectoryContext(gcName, DirectoryContextType.DirectoryServer, context);
+ gcList.Add(new GlobalCatalog(gcContext, gcName));
+ }
+
+ return new GlobalCatalogCollection(gcList);
+ }
+
+ [DirectoryServicesPermission(SecurityAction.Assert, Unrestricted = true)]
+ private DirectorySearcher InternalGetDirectorySearcher()
+ {
+ DirectoryEntry de = new DirectoryEntry("GC://" + Name);
+
+ if (DirectoryContext.ServerBindSupported)
+ {
+ de.AuthenticationType = Utils.DefaultAuthType | AuthenticationTypes.ServerBind;
+ }
+ else
+ {
+ de.AuthenticationType = Utils.DefaultAuthType;
+ }
+
+ de.Username = context.UserName;
+ de.Password = context.Password;
+
+ return new DirectorySearcher(de);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/GlobalCatalogCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/GlobalCatalogCollection.cs
new file mode 100644
index 0000000000..cc7f232e5c
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/GlobalCatalogCollection.cs
@@ -0,0 +1,68 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Globalization;
+ using System.Collections;
+
+ public class GlobalCatalogCollection : ReadOnlyCollectionBase
+ {
+ internal GlobalCatalogCollection() { }
+
+ internal GlobalCatalogCollection(ArrayList values)
+ {
+ if (values != null)
+ {
+ InnerList.AddRange(values);
+ }
+ }
+
+ public GlobalCatalog this[int index]
+ {
+ get
+ {
+ return (GlobalCatalog)InnerList[index];
+ }
+ }
+
+ public bool Contains(GlobalCatalog globalCatalog)
+ {
+ if (globalCatalog == null)
+ throw new ArgumentNullException("globalCatalog");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ GlobalCatalog tmp = (GlobalCatalog)InnerList[i];
+ if (Utils.Compare(tmp.Name, globalCatalog.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(GlobalCatalog globalCatalog)
+ {
+ if (globalCatalog == null)
+ throw new ArgumentNullException("globalCatalog");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ GlobalCatalog tmp = (GlobalCatalog)InnerList[i];
+ if (Utils.Compare(tmp.Name, globalCatalog.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(GlobalCatalog[] globalCatalogs, int index)
+ {
+ InnerList.CopyTo(globalCatalogs, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Locator.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Locator.cs
new file mode 100644
index 0000000000..07656446a2
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Locator.cs
@@ -0,0 +1,307 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Net;
+ using System.Text;
+ using System.Collections;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+
+ internal sealed class Locator
+ {
+ // To disable public/protected constructors for this class
+ private Locator() { }
+
+ internal static DomainControllerInfo GetDomainControllerInfo(string computerName, string domainName, string siteName, long flags)
+ {
+ int errorCode = 0;
+ DomainControllerInfo domainControllerInfo;
+
+ errorCode = DsGetDcNameWrapper(computerName, domainName, siteName, flags, out domainControllerInfo);
+
+ if (errorCode != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode, domainName);
+ }
+
+ return domainControllerInfo;
+ }
+
+ internal static int DsGetDcNameWrapper(string computerName, string domainName, string siteName, long flags, out DomainControllerInfo domainControllerInfo)
+ {
+ IntPtr pDomainControllerInfo = IntPtr.Zero;
+ int result = 0;
+
+ // empty siteName/computerName should be treated as null
+ if ((computerName != null) && (computerName.Length == 0))
+ {
+ computerName = null;
+ }
+ if ((siteName != null) && (siteName.Length == 0))
+ {
+ siteName = null;
+ }
+
+ result = NativeMethods.DsGetDcName(computerName, domainName, IntPtr.Zero, siteName, (int)(flags | (long)PrivateLocatorFlags.ReturnDNSName), out pDomainControllerInfo);
+ if (result == 0)
+ {
+ try
+ {
+ // success case
+ domainControllerInfo = new DomainControllerInfo();
+ Marshal.PtrToStructure(pDomainControllerInfo, domainControllerInfo);
+ }
+ finally
+ {
+ // free the buffer
+ // what to do with error code??
+ if (pDomainControllerInfo != IntPtr.Zero)
+ {
+ result = NativeMethods.NetApiBufferFree(pDomainControllerInfo);
+ }
+ }
+ }
+ else
+ {
+ domainControllerInfo = new DomainControllerInfo();
+ }
+
+ return result;
+ }
+
+ internal static ArrayList EnumerateDomainControllers(DirectoryContext context, string domainName, string siteName, long dcFlags)
+ {
+ Hashtable allDCs = null;
+ ArrayList dcs = new ArrayList();
+
+ //
+ // this api obtains the list of DCs/GCs based on dns records. The DCs/GCs that have registered
+ // non site specific records for the domain/forest are returned. Additonally DCs/GCs that have registered site specific records
+ // (site is either specified or defaulted to the site of the local machine) are also returned in this list.
+ //
+
+ if (siteName == null)
+ {
+ //
+ // if the site name is not specified then we get the site specific records for the local machine's site (in the context of the domain/forest/application partition that is specified)
+ // (sitename could still be null if the machine is not in any site for the specified domain/forest, in that case we don't look for any site specific records)
+ //
+ DomainControllerInfo domainControllerInfo;
+
+ int errorCode = DsGetDcNameWrapper(null, domainName, null, dcFlags & (long)(PrivateLocatorFlags.GCRequired | PrivateLocatorFlags.DSWriteableRequired | PrivateLocatorFlags.OnlyLDAPNeeded), out domainControllerInfo);
+ if (errorCode == 0)
+ {
+ siteName = domainControllerInfo.ClientSiteName;
+ }
+ else if (errorCode == NativeMethods.ERROR_NO_SUCH_DOMAIN)
+ {
+ // return an empty collection
+ return dcs;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(errorCode);
+ }
+ }
+
+ if (DirectoryContext.DnsgetdcSupported)
+ {
+ // this will get both the non site specific and the site specific records
+ allDCs = DnsGetDcWrapper(domainName, siteName, dcFlags);
+ }
+ else
+ {
+ // first get all the non site specific
+ allDCs = DnsQueryWrapper(domainName, null, dcFlags);
+ // now get all the site specific records
+ if (siteName != null)
+ {
+ foreach (string dc in DnsQueryWrapper(domainName, siteName, dcFlags).Keys)
+ {
+ if (!allDCs.Contains(dc))
+ {
+ allDCs.Add(dc, null);
+ }
+ }
+ }
+ }
+
+ foreach (string dcName in allDCs.Keys)
+ {
+ DirectoryContext dcContext = Utils.GetNewDirectoryContext(dcName, DirectoryContextType.DirectoryServer, context);
+
+ if ((dcFlags & (long)PrivateLocatorFlags.GCRequired) != 0)
+ {
+ // add a GlobalCatalog object
+ dcs.Add(new GlobalCatalog(dcContext, dcName));
+ }
+ else
+ {
+ // add a domain controller object
+ dcs.Add(new DomainController(dcContext, dcName));
+ }
+ }
+
+ return dcs;
+ }
+
+ private static Hashtable DnsGetDcWrapper(string domainName, string siteName, long dcFlags)
+ {
+ Hashtable domainControllers = new Hashtable();
+
+ int optionFlags = 0;
+ IntPtr retGetDcContext = IntPtr.Zero;
+ IntPtr dcDnsHostNamePtr = IntPtr.Zero;
+ int sockAddressCount = 0;
+ IntPtr sockAddressCountPtr = new IntPtr(sockAddressCount);
+ IntPtr sockAddressList = IntPtr.Zero;
+ string dcDnsHostName = null;
+ int result = 0;
+
+ result = NativeMethods.DsGetDcOpen(domainName, (int)optionFlags, siteName, IntPtr.Zero, null, (int)dcFlags, out retGetDcContext);
+ if (result == 0)
+ {
+ try
+ {
+ result = NativeMethods.DsGetDcNext(retGetDcContext, ref sockAddressCountPtr, out sockAddressList, out dcDnsHostNamePtr);
+
+ if (result != 0 && result != NativeMethods.ERROR_FILE_MARK_DETECTED && result != NativeMethods.DNS_ERROR_RCODE_NAME_ERROR && result != NativeMethods.ERROR_NO_MORE_ITEMS)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+
+ while (result != NativeMethods.ERROR_NO_MORE_ITEMS)
+ {
+ if (result != NativeMethods.ERROR_FILE_MARK_DETECTED && result != NativeMethods.DNS_ERROR_RCODE_NAME_ERROR)
+ {
+ try
+ {
+ dcDnsHostName = Marshal.PtrToStringUni(dcDnsHostNamePtr);
+ string key = dcDnsHostName.ToLower(CultureInfo.InvariantCulture);
+
+ if (!domainControllers.Contains(key))
+ {
+ domainControllers.Add(key, null);
+ }
+ }
+ finally
+ {
+ // what to do with the error?
+ if (dcDnsHostNamePtr != IntPtr.Zero)
+ {
+ result = NativeMethods.NetApiBufferFree(dcDnsHostNamePtr);
+ }
+ }
+ }
+
+ result = NativeMethods.DsGetDcNext(retGetDcContext, ref sockAddressCountPtr, out sockAddressList, out dcDnsHostNamePtr);
+ if (result != 0 && result != NativeMethods.ERROR_FILE_MARK_DETECTED && result != NativeMethods.DNS_ERROR_RCODE_NAME_ERROR && result != NativeMethods.ERROR_NO_MORE_ITEMS)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+ }
+ }
+ finally
+ {
+ NativeMethods.DsGetDcClose(retGetDcContext);
+ }
+ }
+ else if (result != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+
+ return domainControllers;
+ }
+
+ private static Hashtable DnsQueryWrapper(string domainName, string siteName, long dcFlags)
+ {
+ Hashtable domainControllers = new Hashtable();
+ string recordName = "_ldap._tcp.";
+ int result = 0;
+ int options = 0;
+ IntPtr dnsResults = IntPtr.Zero;
+
+ // construct the record name
+ if ((siteName != null) && (!(siteName.Length == 0)))
+ {
+ // only looking for domain controllers / global catalogs within a
+ // particular site
+ recordName = recordName + siteName + "._sites.";
+ }
+
+ // check if gc or dc
+ if (((long)dcFlags & (long)(PrivateLocatorFlags.GCRequired)) != 0)
+ {
+ // global catalog
+ recordName += "gc._msdcs.";
+ }
+ else if (((long)dcFlags & (long)(PrivateLocatorFlags.DSWriteableRequired)) != 0)
+ {
+ // domain controller
+ recordName += "dc._msdcs.";
+ }
+
+ // now add the domainName
+ recordName = recordName + domainName;
+
+ // set the BYPASS CACHE option is specified
+ if (((long)dcFlags & (long)LocatorOptions.ForceRediscovery) != 0)
+ {
+ options |= NativeMethods.DnsQueryBypassCache;
+ }
+
+ // Call DnsQuery
+ result = NativeMethods.DnsQuery(recordName, NativeMethods.DnsSrvData, options, IntPtr.Zero, out dnsResults, IntPtr.Zero);
+ if (result == 0)
+ {
+ try
+ {
+ IntPtr currentDnsRecord = dnsResults;
+
+ while (currentDnsRecord != IntPtr.Zero)
+ {
+ // partial marshalling of dns record data
+ PartialDnsRecord partialDnsRecord = new PartialDnsRecord();
+ Marshal.PtrToStructure(currentDnsRecord, partialDnsRecord);
+
+ //check if the record is of type DNS_SRV_DATA
+ if (partialDnsRecord.type == NativeMethods.DnsSrvData)
+ {
+ // remarshal to get the srv record data
+ DnsRecord dnsRecord = new DnsRecord();
+ Marshal.PtrToStructure(currentDnsRecord, dnsRecord);
+ string targetName = dnsRecord.data.targetName;
+ string key = targetName.ToLower(CultureInfo.InvariantCulture);
+
+ if (!domainControllers.Contains(key))
+ {
+ domainControllers.Add(key, null);
+ }
+ }
+ // move to next record
+ currentDnsRecord = partialDnsRecord.next;
+ }
+ }
+ finally
+ {
+ // release the dns results buffer
+ if (dnsResults != IntPtr.Zero)
+ {
+ NativeMethods.DnsRecordListFree(dnsResults, true);
+ }
+ }
+ }
+ else if (result != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+
+ return domainControllers;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/LocatorFlag.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/LocatorFlag.cs
new file mode 100644
index 0000000000..19075d037f
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/LocatorFlag.cs
@@ -0,0 +1,63 @@
+// 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.ActiveDirectory
+{
+ using System;
+
+ /*
+ #define DS_FORCE_REDISCOVERY 0x00000001
+ #define DS_DIRECTORY_SERVICE_REQUIRED 0x00000010
+ #define DS_DIRECTORY_SERVICE_PREFERRED 0x00000020
+ #define DS_GC_SERVER_REQUIRED 0x00000040
+ #define DS_PDC_REQUIRED 0x00000080
+ #define DS_BACKGROUND_ONLY 0x00000100
+ #define DS_IP_REQUIRED 0x00000200
+ #define DS_KDC_REQUIRED 0x00000400
+ #define DS_TIMESERV_REQUIRED 0x00000800
+ #define DS_WRITABLE_REQUIRED 0x00001000
+ #define DS_GOOD_TIMESERV_PREFERRED 0x00002000
+ #define DS_AVOID_SELF 0x00004000
+ #define DS_ONLY_LDAP_NEEDED 0x00008000
+ #define DS_IS_FLAT_NAME 0x00010000
+ #define DS_IS_DNS_NAME 0x00020000
+ #define DS_RETURN_DNS_NAME 0x40000000
+ #define DS_RETURN_FLAT_NAME 0x80000000
+ */
+
+ [Flags]
+ public enum LocatorOptions : long
+ {
+ ForceRediscovery = 0x00000001,
+ KdcRequired = 0x00000400,
+ TimeServerRequired = 0x00000800,
+ WriteableRequired = 0x00001000,
+ AvoidSelf = 0x00004000
+ }
+
+ [Flags]
+ internal enum PrivateLocatorFlags : long
+ {
+ DirectoryServicesRequired = 0x00000010,
+ DirectoryServicesPreferred = 0x00000020,
+ GCRequired = 0x00000040,
+ PdcRequired = 0x00000080,
+ BackgroundOnly = 0x00000100,
+ IPRequired = 0x00000200,
+ DSWriteableRequired = 0x00001000,
+ GoodTimeServerPreferred = 0x00002000,
+ OnlyLDAPNeeded = 0X0008000,
+ IsFlatName = 0x00010000,
+ IsDNSName = 0x00020000,
+ ReturnDNSName = 0x40000000,
+ ReturnFlatName = 0x80000000
+ }
+
+ [Flags]
+ internal enum DcEnumFlag : int
+ {
+ OnlyDoSiteName = 0x01,
+ NotifyAfterSiteRecords = 0x02
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/NativeMethods.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/NativeMethods.cs
new file mode 100644
index 0000000000..ef9b825b7b
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/NativeMethods.cs
@@ -0,0 +1,994 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Security;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.DirectoryServices.Interop;
+ using System.Runtime.InteropServices;
+
+ /*typedef struct _DOMAIN_CONTROLLER_INFO {
+ LPTSTR DomainControllerName;
+ LPTSTR DomainControllerAddress;
+ ULONG DomainControllerAddressType;
+ GUID DomainGuid;
+ LPTSTR DomainName;
+ LPTSTR DnsForestName;
+ ULONG Flags;
+ LPTSTR DcSiteName;
+ LPTSTR ClientSiteName;
+ } DOMAIN_CONTROLLER_INFO, *PDOMAIN_CONTROLLER_INFO; */
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class DomainControllerInfo
+ {
+ public string DomainControllerName;
+ public string DomainControllerAddress;
+ public int DomainControllerAddressType;
+ public Guid DomainGuid;
+ public string DomainName;
+ public string DnsForestName;
+ public int Flags;
+ public string DcSiteName;
+ public string ClientSiteName;
+ }
+
+ /*typedef struct {
+ LPTSTR NetbiosName;
+ LPTSTR DnsHostName;
+ LPTSTR SiteName;
+ LPTSTR SiteObjectName;
+ LPTSTR ComputerObjectName;
+ LPTSTR ServerObjectName;
+ LPTSTR NtdsaObjectName;
+ BOOL fIsPdc;
+ BOOL fDsEnabled;
+ BOOL fIsGc;
+ GUID SiteObjectGuid;
+ GUID ComputerObjectGuid;
+ GUID ServerObjectGuid;
+ GUID NtdsDsaObjectGuid;
+ } DS_DOMAIN_CONTROLLER_INFO_2, *PDS_DOMAIN_CONTROLLER_INFO_2;*/
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class DsDomainControllerInfo2
+ {
+ public string netBiosName;
+ public string dnsHostName;
+ public string siteName;
+ public string siteObjectName;
+ public string computerObjectName;
+ public string serverObjectName;
+ public string ntdsaObjectName;
+ public bool isPdc;
+ public bool dsEnabled;
+ public bool isGC;
+ public Guid siteObjectGuid;
+ public Guid computerObjectGuid;
+ public Guid serverObjectGuid;
+ public Guid ntdsDsaObjectGuid;
+ }
+
+ /*typedef struct {
+ LPTSTR NetbiosName;
+ LPTSTR DnsHostName;
+ LPTSTR SiteName;
+ LPTSTR SiteObjectName;
+ LPTSTR ComputerObjectName;
+ LPTSTR ServerObjectName;
+ LPTSTR NtdsaObjectName;
+ BOOL fIsPdc;
+ BOOL fDsEnabled;
+ BOOL fIsGc;
+ BOOL fIsRodc;
+ GUID SiteObjectGuid;
+ GUID ComputerObjectGuid;
+ GUID ServerObjectGuid;
+ GUID NtdsDsaObjectGuid;
+ } DS_DOMAIN_CONTROLLER_INFO_3, *PDS_DOMAIN_CONTROLLER_INFO_3;*/
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class DsDomainControllerInfo3
+ {
+ public string netBiosName;
+ public string dnsHostName;
+ public string siteName;
+ public string siteObjectName;
+ public string computerObjectName;
+ public string serverObjectName;
+ public string ntdsaObjectName;
+ public bool isPdc;
+ public bool dsEnabled;
+ public bool isGC;
+ public bool isRodc;
+ public Guid siteObjectGuid;
+ public Guid computerObjectGuid;
+ public Guid serverObjectGuid;
+ public Guid ntdsDsaObjectGuid;
+ }
+
+ /*typedef struct {
+ DWORD cItems;
+ PDS_NAME_RESULT_ITEM rItems;
+ } DS_NAME_RESULT, *PDS_NAME_RESULT;*/
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DsNameResult
+ {
+ public int itemCount;
+ public IntPtr items;
+ }
+
+ /*typedef struct {
+ DWORD status;
+ LPTSTR pDomain;
+ LPTSTR pName;
+ } DS_NAME_RESULT_ITEM, *PDS_NAME_RESULT_ITEM;*/
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class DsNameResultItem
+ {
+ public int status;
+ public string domain;
+ public string name;
+ }
+
+ /*typedef struct _DnsRecord {
+ struct _DnsRecord * pNext;
+ LPTSTR pName;
+ WORD wType;
+ WORD wDataLength; // Not referenced for DNS record
+ //types defined above.
+ union {
+ DWORD DW; // flags as DWORD
+ DNS_RECORD_FLAGS S; // flags as structure
+ } Flags;
+
+ DWORD dwTtl;
+ DWORD dwReserved;
+
+ // Record Data
+ union {
+ DNS_A_DATA A;
+ DNS_SOA_DATA SOA, Soa;
+ DNS_PTR_DATA PTR, Ptr,
+ NS, Ns,
+ CNAME, Cname,
+ MB, Mb,
+ MD, Md,
+ MF, Mf,
+ MG, Mg,
+ MR, Mr;
+ DNS_MINFO_DATA MINFO, Minfo,
+ RP, Rp;
+ DNS_MX_DATA MX, Mx,
+ AFSDB, Afsdb,
+ RT, Rt;
+ DNS_TXT_DATA HINFO, Hinfo,
+ ISDN, Isdn,
+ TXT, Txt,
+ X25;
+ DNS_NULL_DATA Null;
+ DNS_WKS_DATA WKS, Wks;
+ DNS_AAAA_DATA AAAA;
+ DNS_KEY_DATA KEY, Key;
+ DNS_SIG_DATA SIG, Sig;
+ DNS_ATMA_DATA ATMA, Atma;
+ DNS_NXT_DATA NXT, Nxt;
+ DNS_SRV_DATA SRV, Srv;
+ DNS_TKEY_DATA TKEY, Tkey;
+ DNS_TSIG_DATA TSIG, Tsig;
+ DNS_WINS_DATA WINS, Wins;
+ DNS_WINSR_DATA WINSR, WinsR, NBSTAT, Nbstat;
+ } Data;
+ }DNS_RECORD, *PDNS_RECORD;*/
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class DnsRecord
+ {
+ public IntPtr next;
+ public string name;
+ public short type;
+ public short dataLength;
+ public int flags;
+ public int ttl;
+ public int reserved;
+ public DnsSrvData data;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class PartialDnsRecord
+ {
+ public IntPtr next;
+ public string name;
+ public short type;
+ public short dataLength;
+ public int flags;
+ public int ttl;
+ public int reserved;
+ public IntPtr data;
+ }
+
+ /*typedef struct {
+ LPTSTR pNameTarget;
+ WORD wPriority;
+ WORD wWeight;
+ WORD wPort;
+ WORD Pad; // keep ptrs DWORD aligned
+ }DNS_SRV_DATA, *PDNS_SRV_DATA;*/
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class DnsSrvData
+ {
+ public string targetName;
+ public short priority;
+ public short weight;
+ public short port;
+ public short pad;
+ }
+
+ /*typedef struct _OSVERSIONINFOEX {
+ DWORD dwOSVersionInfoSize;
+ DWORD dwMajorVersion;
+ DWORD dwMinorVersion;
+ DWORD dwBuildNumber;
+ DWORD dwPlatformId;
+ TCHAR szCSDVersion[ 128 ];
+ WORD wServicePackMajor;
+ WORD wServicePackMinor;
+ WORD wSuiteMask;
+ BYTE wProductType;
+ BYTE wReserved;
+ } OSVERSIONINFOEX, *POSVERSIONINFOEX, *LPOSVERSIONINFOEX;*/
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class OSVersionInfoEx
+ {
+ public OSVersionInfoEx()
+ {
+ osVersionInfoSize = (int)Marshal.SizeOf(this);
+ }
+
+ // The OSVersionInfoSize field must be set to Marshal.SizeOf(this)
+ public int osVersionInfoSize = 0;
+ public int majorVersion = 0;
+ public int minorVersion = 0;
+ public int buildNumber = 0;
+ public int platformId = 0;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ public string csdVersion = null;
+ public short servicePackMajor = 0;
+ public short servicePackMinor = 0;
+ public short suiteMask = 0;
+ public byte productType = 0;
+ public byte reserved = 0;
+ }
+
+ /*typedef struct _LUID {
+ DWORD LowPart;
+ LONG HighPart;
+ } LUID, *PLUID;*/
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LUID
+ {
+ public int LowPart;
+ public int HighPart;
+ }
+
+ /*typedef struct _NEGOTIATE_CALLER_NAME_REQUEST {
+ ULONG MessageType ;
+ LUID LogonId ;
+ } NEGOTIATE_CALLER_NAME_REQUEST, *PNEGOTIATE_CALLER_NAME_REQUEST ;*/
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class NegotiateCallerNameRequest
+ {
+ public int messageType;
+ public LUID logonId;
+ }
+
+ /*typedef struct _NEGOTIATE_CALLER_NAME_RESPONSE {
+ ULONG MessageType ;
+ PWSTR CallerName ;
+ } NEGOTIATE_CALLER_NAME_RESPONSE, * PNEGOTIATE_CALLER_NAME_RESPONSE ;*/
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class NegotiateCallerNameResponse
+ {
+ public int messageType;
+ public string callerName;
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal sealed class NativeMethods
+ {
+ // disable public constructor
+ private NativeMethods() { }
+
+ internal const int VER_PLATFORM_WIN32_NT = 2;
+ internal const int ERROR_INVALID_DOMAIN_NAME_FORMAT = 1212;
+ internal const int ERROR_NO_SUCH_DOMAIN = 1355;
+ internal const int ERROR_NOT_ENOUGH_MEMORY = 8;
+ internal const int ERROR_INVALID_FLAGS = 1004;
+ internal const int DS_NAME_NO_ERROR = 0;
+ internal const int ERROR_NO_MORE_ITEMS = 259;
+ internal const int ERROR_FILE_MARK_DETECTED = 1101;
+ internal const int DNS_ERROR_RCODE_NAME_ERROR = 9003;
+ internal const int ERROR_NO_SUCH_LOGON_SESSION = 1312;
+
+ internal const int DS_NAME_FLAG_SYNTACTICAL_ONLY = 1;
+ internal const int DS_FQDN_1779_NAME = 1;
+ internal const int DS_CANONICAL_NAME = 7;
+ internal const int DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 6;
+
+ internal const int STATUS_QUOTA_EXCEEDED = unchecked((int)0xC0000044);
+
+ /*DWORD DsGetDcName(
+ LPCTSTR ComputerName,
+ LPCTSTR DomainName,
+ GUID* DomainGuid,
+ LPCTSTR SiteName,
+ ULONG Flags,
+ PDOMAIN_CONTROLLER_INFO* DomainControllerInfo
+ );*/
+ [DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsGetDcNameW", CharSet = CharSet.Unicode)]
+ internal static extern int DsGetDcName(
+ [In] string computerName,
+ [In] string domainName,
+ [In] IntPtr domainGuid,
+ [In] string siteName,
+ [In] int flags,
+ [Out] out IntPtr domainControllerInfo);
+
+ /* DWORD WINAPI DsGetDcOpen(
+ LPCTSTR DnsName,
+ ULONG OptionFlags,
+ LPCTSTR SiteName,
+ GUID* DomainGuid,
+ LPCTSTR DnsForestName,
+ ULONG DcFlags,
+ PHANDLE RetGetDcContext
+ );*/
+ [DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsGetDcOpenW", CharSet = CharSet.Unicode)]
+ internal static extern int DsGetDcOpen(
+ [In] string dnsName,
+ [In] int optionFlags,
+ [In] string siteName,
+ [In] IntPtr domainGuid,
+ [In] string dnsForestName,
+ [In] int dcFlags,
+ [Out] out IntPtr retGetDcContext);
+
+ /*DWORD WINAPI DsGetDcNext(
+ HANDLE GetDcContextHandle,
+ PULONG SockAddressCount,
+ LPSOCKET_ADDRESS* SockAddresses,
+ LPTSTR* DnsHostName
+ );*/
+ [DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsGetDcNextW", CharSet = CharSet.Unicode)]
+ internal static extern int DsGetDcNext(
+ [In] IntPtr getDcContextHandle,
+ [In, Out] ref IntPtr sockAddressCount,
+ [Out] out IntPtr sockAdresses,
+ [Out] out IntPtr dnsHostName);
+
+ /*void WINAPI DsGetDcClose(
+ HANDLE GetDcContextHandle
+ );*/
+ [DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsGetDcCloseW", CharSet = CharSet.Unicode)]
+ internal static extern void DsGetDcClose(
+ [In] IntPtr getDcContextHandle);
+
+ /*NET_API_STATUS NetApiBufferFree(
+ LPVOID Buffer
+ );*/
+ [DllImport("Netapi32.dll")]
+ internal static extern int NetApiBufferFree(
+ [In] IntPtr buffer);
+
+ /*DWORD DsMakePasswordCredentials(
+ LPTSTR User,
+ LPTSTR Domain,
+ LPTSTR Password,
+ RPC_AUTH_IDENTITY_HANDLE* pAuthIdentity
+ );*/
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal delegate int DsMakePasswordCredentials(
+ [MarshalAs(UnmanagedType.LPWStr)] string user,
+ [MarshalAs(UnmanagedType.LPWStr)] string domain,
+ [MarshalAs(UnmanagedType.LPWStr)] string password,
+ [Out] out IntPtr authIdentity);
+
+ /*VOID DsFreePasswordCredentials(
+ RPC_AUTH_IDENTITY_HANDLE AuthIdentity
+ );*/
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal delegate void DsFreePasswordCredentials(
+ [In] IntPtr authIdentity);
+
+ /*DWORD DsBindWithCred(
+ TCHAR* DomainController,
+ TCHAR* DnsDomainName,
+ RPC_AUTH_IDENTITY_HANDLE AuthIdentity,
+ HANDLE* phDS
+ );*/
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal delegate int DsBindWithCred(
+ [MarshalAs(UnmanagedType.LPWStr)] string domainController,
+ [MarshalAs(UnmanagedType.LPWStr)] string dnsDomainName,
+ [In] IntPtr authIdentity,
+ [Out] out IntPtr handle);
+
+ /*DWORD DsUnBind(
+ HANDLE* phDS
+ );*/
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal delegate int DsUnBind(
+ [In] ref IntPtr handle);
+
+ /*DWORD DsGetDomainControllerInfo(
+ HANDLE hDs,
+ LPTSTR DomainName,
+ DWORD InfoLevel,
+ DWORD* pcOut,
+ VOID** ppInfo
+ );*/
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal delegate int DsGetDomainControllerInfo(
+ [In] IntPtr handle,
+ [MarshalAs(UnmanagedType.LPWStr)] string domainName,
+ [In] int infoLevel,
+ [Out] out int dcCount,
+ [Out] out IntPtr dcInfo);
+
+ internal const int DsDomainControllerInfoLevel2 = 2;
+ internal const int DsDomainControllerInfoLevel3 = 3;
+
+ /*VOID DsFreeDomainControllerInfo(
+ DWORD InfoLevel,
+ DWORD cInfo,
+ VOID* pInfo
+ );*/
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal delegate void DsFreeDomainControllerInfo(
+ [In] int infoLevel,
+ [In] int dcInfoListCount,
+ [In] IntPtr dcInfoList);
+
+ internal const int DsNameNoError = 0;
+
+ /*DWORD DsListSites(
+ HANDLE hDs,
+ PDS_NAME_RESULT* ppSites
+ );*/
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal delegate int DsListSites(
+ [In] IntPtr dsHandle,
+ [Out] out IntPtr sites);
+
+ /*DWORD DsListRoles(
+ HANDLE hDs,
+ PDS_NAME_RESULTW* ppRoles
+ );*/
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal delegate int DsListRoles(
+ [In] IntPtr dsHandle,
+ [Out] out IntPtr roles);
+
+ /*DWORD GetLastError(VOID)*/
+ [DllImport("Kernel32.dll")]
+ internal static extern int GetLastError();
+
+ internal const int DnsSrvData = 33;
+ internal const int DnsQueryBypassCache = 8;
+
+ /*DNS_STATUS WINAPI DnsQuery (
+ LPSTR lpstrName,
+ WORD wType,
+ DWORD fOptions,
+ PIP4_ARRAY aipServers,
+ PDNS_RECORD *ppQueryResultsSet,
+ PVOID *pReserved
+ );*/
+ [DllImport("Dnsapi.dll", EntryPoint = "DnsQuery_W", CharSet = CharSet.Unicode)]
+ internal static extern int DnsQuery(
+ [In] string recordName,
+ [In] short recordType,
+ [In] int options,
+ [In] IntPtr servers,
+ [Out] out IntPtr dnsResultList,
+ [Out] IntPtr reserved);
+
+ /*VOID WINAPI DnsRecordListFree(
+ PDNS_RECORD pRecordList,
+ DNS_FREE_TYPE FreeType
+ );*/
+ [DllImport("Dnsapi.dll", CharSet = CharSet.Unicode)]
+ internal static extern void DnsRecordListFree(
+ [In] IntPtr dnsResultList,
+ [In] bool dnsFreeType);
+
+ /*BOOL GetVersionEx(
+ LPOSVERSIONINFO lpVersionInfo
+ );*/
+ [DllImport("Kernel32.dll", EntryPoint = "GetVersionExW", CharSet = CharSet.Unicode, SetLastError = true)]
+ internal static extern bool GetVersionEx(
+ [In, Out] OSVersionInfoEx ver);
+
+ /*DWORD DsCrackNames(
+ HANDLE hDS,
+ DS_NAME_FLAGS flags,
+ DS_NAME_FORMAT formatOffered,
+ DS_NAME_FORMAT formatDesired,
+ DWORD cNames,
+ LPTSTR* rpNames,
+ PDS_NAME_RESULT* ppResult
+ );*/
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal delegate int DsCrackNames(
+ [In] IntPtr hDS,
+ [In] int flags,
+ [In] int formatOffered,
+ [In] int formatDesired,
+ [In] int nameCount,
+ [In] IntPtr names,
+ [Out] out IntPtr results);
+
+ /*NTSTATUS LsaConnectUntrusted(
+ PHANDLE LsaHandle
+ );*/
+ [DllImport("Secur32.dll")]
+ internal static extern int LsaConnectUntrusted(
+ [Out] out LsaLogonProcessSafeHandle lsaHandle);
+
+ internal const int NegGetCallerName = 1;
+
+ /*NTSTATUS LsaCallAuthenticationPackage(
+ HANDLE LsaHandle,
+ ULONG AuthenticationPackage,
+ PVOID ProtocolSubmitBuffer,
+ ULONG SubmitBufferLength,
+ PVOID* ProtocolReturnBuffer,
+ PULONG ReturnBufferLength,
+ PNTSTATUS ProtocolStatus
+ );*/
+ [DllImport("Secur32.dll")]
+ internal static extern int LsaCallAuthenticationPackage(
+ [In] LsaLogonProcessSafeHandle lsaHandle,
+ [In] int authenticationPackage,
+ [In] NegotiateCallerNameRequest protocolSubmitBuffer,
+ [In] int submitBufferLength,
+ [Out] out IntPtr protocolReturnBuffer,
+ [Out] out int returnBufferLength,
+ [Out] out int protocolStatus);
+
+ /*NTSTATUS LsaFreeReturnBuffer(
+ PVOID Buffer
+ );*/
+ [DllImport("Secur32.dll")]
+ internal static extern uint LsaFreeReturnBuffer(
+ [In] IntPtr buffer);
+
+ /*NTSTATUS LsaDeregisterLogonProcess(
+ HANDLE LsaHandle
+ );*/
+ [DllImport("Secur32.dll")]
+ internal static extern int LsaDeregisterLogonProcess(
+ [In] IntPtr lsaHandle);
+
+ /*int CompareString(LCID Locale,
+ DWORD dwCmpFlags,
+ DWORD lpString1,
+ DWORD cchCount1,
+ DWORD lpString2,
+ DWORD cchCount2
+ );*/
+ [DllImport("Kernel32.dll", EntryPoint = "CompareStringW", CharSet = CharSet.Unicode, SetLastError = true)]
+ internal static extern int CompareString(
+ [In] uint locale,
+ [In] uint dwCmpFlags,
+ [In] IntPtr lpString1,
+ [In] int cchCount1,
+ [In] IntPtr lpString2,
+ [In] int cchCount2);
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaNtStatusToWinError", CharSet = CharSet.Unicode)]
+ internal static extern int LsaNtStatusToWinError(int ntStatus);
+ }
+
+ [
+ SuppressUnmanagedCodeSecurityAttribute()
+ ]
+ internal sealed class NativeComInterfaces
+ {
+ /*typedef enum {
+ ADS_SETTYPE_FULL=1,
+ ADS_SETTYPE_PROVIDER=2,
+ ADS_SETTYPE_SERVER=3,
+ ADS_SETTYPE_DN=4
+ } ADS_SETTYPE_ENUM;
+
+ typedef enum {
+ ADS_FORMAT_WINDOWS=1,
+ ADS_FORMAT_WINDOWS_NO_SERVER=2,
+ ADS_FORMAT_WINDOWS_DN=3,
+ ADS_FORMAT_WINDOWS_PARENT=4,
+ ADS_FORMAT_X500=5,
+ ADS_FORMAT_X500_NO_SERVER=6,
+ ADS_FORMAT_X500_DN=7,
+ ADS_FORMAT_X500_PARENT=8,
+ ADS_FORMAT_SERVER=9,
+ ADS_FORMAT_PROVIDER=10,
+ ADS_FORMAT_LEAF=11
+ } ADS_FORMAT_ENUM;
+
+ typedef enum {
+ ADS_ESCAPEDMODE_DEFAULT=1,
+ ADS_ESCAPEDMODE_ON=2,
+ ADS_ESCAPEDMODE_OFF=3,
+ ADS_ESCAPEDMODE_OFF_EX=4
+ } ADS_ESCAPE_MODE_ENUM;*/
+
+ internal const int ADS_SETTYPE_DN = 4;
+ internal const int ADS_FORMAT_X500_DN = 7;
+ internal const int ADS_ESCAPEDMODE_ON = 2;
+ internal const int ADS_ESCAPEDMODE_OFF_EX = 4;
+ internal const int ADS_FORMAT_LEAF = 11;
+
+ //
+ // Pathname as a co-class that implements the IAdsPathname interface
+ //
+ [ComImport, Guid("080d0d78-f421-11d0-a36e-00c04fb950dc")]
+ internal class Pathname
+ {
+ }
+
+ [ComImport, Guid("D592AED4-F420-11D0-A36E-00C04FB950DC"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ internal interface IAdsPathname
+ {
+ // HRESULT Set([in] BSTR bstrADsPath, [in] long lnSetType);
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ int Set([In, MarshalAs(UnmanagedType.BStr)] string bstrADsPath, [In, MarshalAs(UnmanagedType.U4)] int lnSetType);
+
+ // HRESULT SetDisplayType([in] long lnDisplayType);
+ int SetDisplayType([In, MarshalAs(UnmanagedType.U4)] int lnDisplayType);
+
+ // HRESULT Retrieve([in] long lnFormatType, [out, retval] BSTR* pbstrADsPath);
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ string Retrieve([In, MarshalAs(UnmanagedType.U4)] int lnFormatType);
+
+ // HRESULT GetNumElements([out, retval] long* plnNumPathElements);
+ [return: MarshalAs(UnmanagedType.U4)]
+ int GetNumElements();
+
+ // HRESULT GetElement([in] long lnElementIndex, [out, retval] BSTR* pbstrElement);
+ [return: MarshalAs(UnmanagedType.BStr)]
+ string GetElement([In, MarshalAs(UnmanagedType.U4)] int lnElementIndex);
+
+ // HRESULT AddLeafElement([in] BSTR bstrLeafElement);
+ void AddLeafElement([In, MarshalAs(UnmanagedType.BStr)] string bstrLeafElement);
+
+ // HRESULT RemoveLeafElement();
+ void RemoveLeafElement();
+
+ // HRESULT CopyPath([out, retval] IDispatch** ppAdsPath);
+ [return: MarshalAs(UnmanagedType.Interface)]
+ object CopyPath();
+
+ // HRESULT GetEscapedElement([in] long lnReserved, [in] BSTR bstrInStr, [out, retval] BSTR* pbstrOutStr );
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ string GetEscapedElement([In, MarshalAs(UnmanagedType.U4)] int lnReserved, [In, MarshalAs(UnmanagedType.BStr)] string bstrInStr);
+
+ int EscapedMode
+ {
+ get;
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ set;
+ }
+ }
+
+ [ComImport, Guid("C8F93DD3-4AE0-11CF-9E73-00AA004A5691"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ internal interface IAdsProperty
+ {
+ //
+ // Need to also include the IAds interface definition here
+ //
+
+ string Name
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Class
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string GUID
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string ADsPath
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Parent
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Schema
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ void GetInfo();
+
+ void SetInfo();
+
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object Get([In, MarshalAs(UnmanagedType.BStr)] string bstrName);
+
+ void Put([In, MarshalAs(UnmanagedType.BStr)] string bstrName,
+ [In, MarshalAs(UnmanagedType.Struct)] Object vProp);
+
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object GetEx([In, MarshalAs(UnmanagedType.BStr)] String bstrName);
+
+ void PutEx([In, MarshalAs(UnmanagedType.U4)] int lnControlCode,
+ [In, MarshalAs(UnmanagedType.BStr)] string bstrName,
+ [In, MarshalAs(UnmanagedType.Struct)] Object vProp);
+
+ void GetInfoEx([In, MarshalAs(UnmanagedType.Struct)] Object vProperties,
+ [In, MarshalAs(UnmanagedType.U4)] int lnReserved);
+
+ //
+ // IAdsProperty definition starts here
+ //
+
+ string OID
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ string Syntax
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ int MaxRange
+ {
+ [return: MarshalAs(UnmanagedType.U4)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.U4)]
+ set;
+ }
+
+ int MinRange
+ {
+ [return: MarshalAs(UnmanagedType.U4)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.U4)]
+ set;
+ }
+
+ bool MultiValued
+ {
+ [return: MarshalAs(UnmanagedType.VariantBool)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.VariantBool)]
+ set;
+ }
+ object Qualifiers();
+ }
+
+ [ComImport, Guid("C8F93DD0-4AE0-11CF-9E73-00AA004A5691"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ internal interface IAdsClass
+ {
+ //
+ // Need to also include the IAds interface definition here
+ //
+
+ string Name
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Class
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string GUID
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string ADsPath
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Parent
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string Schema
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ void GetInfo();
+
+ void SetInfo();
+
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object Get([In, MarshalAs(UnmanagedType.BStr)] string bstrName);
+
+ void Put([In, MarshalAs(UnmanagedType.BStr)] string bstrName,
+ [In, MarshalAs(UnmanagedType.Struct)] Object vProp);
+
+ [return: MarshalAs(UnmanagedType.Struct)]
+ Object GetEx([In, MarshalAs(UnmanagedType.BStr)] String bstrName);
+
+ void PutEx([In, MarshalAs(UnmanagedType.U4)] int lnControlCode,
+ [In, MarshalAs(UnmanagedType.BStr)] string bstrName,
+ [In, MarshalAs(UnmanagedType.Struct)] Object vProp);
+
+ void GetInfoEx([In, MarshalAs(UnmanagedType.Struct)] Object vProperties,
+ [In, MarshalAs(UnmanagedType.U4)] int lnReserved);
+
+ //
+ // IAdsClass definition starts here
+ //
+
+ string PrimaryInterface
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ }
+
+ string CLSID
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ string OID
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ bool Abstract
+ {
+ [return: MarshalAs(UnmanagedType.VariantBool)]
+ get;
+ [param: MarshalAs(UnmanagedType.VariantBool)]
+ set;
+ }
+
+ bool Auxiliary
+ {
+ [return: MarshalAs(UnmanagedType.VariantBool)]
+ get;
+ [param: MarshalAs(UnmanagedType.VariantBool)]
+ set;
+ }
+
+ object MandatoryProperties
+ {
+ [return: MarshalAs(UnmanagedType.Struct)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.Struct)]
+ set;
+ }
+
+ object OptionalProperties
+ {
+ [return: MarshalAs(UnmanagedType.Struct)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.Struct)]
+ set;
+ }
+
+ object NamingProperties
+ {
+ [return: MarshalAs(UnmanagedType.Struct)]
+ get;
+ [param: MarshalAs(UnmanagedType.Struct)]
+ set;
+ }
+
+ object DerivedFrom
+ {
+ [return: MarshalAs(UnmanagedType.Struct)]
+ get;
+ [param: MarshalAs(UnmanagedType.Struct)]
+ set;
+ }
+
+ object AuxDerivedFrom
+ {
+ [return: MarshalAs(UnmanagedType.Struct)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.Struct)]
+ set;
+ }
+
+ object PossibleSuperiors
+ {
+ [return: MarshalAs(UnmanagedType.Struct)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ get;
+ [param: MarshalAs(UnmanagedType.Struct)]
+ set;
+ }
+
+ object Containment
+ {
+ [return: MarshalAs(UnmanagedType.Struct)]
+ get;
+ [param: MarshalAs(UnmanagedType.Struct)]
+ set;
+ }
+
+ bool Container
+ {
+ [return: MarshalAs(UnmanagedType.VariantBool)]
+ get;
+ [param: MarshalAs(UnmanagedType.VariantBool)]
+ set;
+ }
+
+ string HelpFileName
+ {
+ [return: MarshalAs(UnmanagedType.BStr)]
+ get;
+ [param: MarshalAs(UnmanagedType.BStr)]
+ set;
+ }
+
+ int HelpFileContext
+ {
+ [return: MarshalAs(UnmanagedType.U4)]
+ get;
+ [param: MarshalAs(UnmanagedType.U4)]
+ set;
+ }
+
+ [return: MarshalAs(UnmanagedType.Interface)]
+ object Qualifiers();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/PropertyManager.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/PropertyManager.cs
new file mode 100644
index 0000000000..87cf95787f
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/PropertyManager.cs
@@ -0,0 +1,185 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+
+ internal class PropertyManager
+ {
+ public static string DefaultNamingContext = "defaultNamingContext";
+ public static string SchemaNamingContext = "schemaNamingContext";
+ public static string ConfigurationNamingContext = "configurationNamingContext";
+ public static string RootDomainNamingContext = "rootDomainNamingContext";
+ public static string MsDSBehaviorVersion = "msDS-Behavior-Version";
+ public static string FsmoRoleOwner = "fsmoRoleOwner";
+ public static string ForestFunctionality = "forestFunctionality";
+ public static string NTMixedDomain = "ntMixedDomain";
+ public static string DomainFunctionality = "domainFunctionality";
+ public static string ObjectCategory = "objectCategory";
+ public static string SystemFlags = "systemFlags";
+ public static string DnsRoot = "dnsRoot";
+ public static string DistinguishedName = "distinguishedName";
+ public static string TrustParent = "trustParent";
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ public static string FlatName = "flatName";
+ public static string Name = "name";
+ public static string Flags = "flags";
+ public static string TrustType = "trustType";
+ public static string TrustAttributes = "trustAttributes";
+#pragma warning restore 0414
+ public static string BecomeSchemaMaster = "becomeSchemaMaster";
+ public static string BecomeDomainMaster = "becomeDomainMaster";
+ public static string BecomePdc = "becomePdc";
+ public static string BecomeRidMaster = "becomeRidMaster";
+ public static string BecomeInfrastructureMaster = "becomeInfrastructureMaster";
+ public static string DnsHostName = "dnsHostName";
+ public static string Options = "options";
+ public static string CurrentTime = "currentTime";
+ public static string HighestCommittedUSN = "highestCommittedUSN";
+ public static string OperatingSystem = "operatingSystem";
+ public static string HasMasterNCs = "hasMasterNCs";
+ public static string MsDSHasMasterNCs = "msDS-HasMasterNCs";
+ public static string MsDSHasFullReplicaNCs = "msDS-hasFullReplicaNCs";
+ public static string NCName = "nCName";
+ public static string Cn = "cn";
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ public static string NETBIOSName = "nETBIOSName";
+#pragma warning restore 0414
+ public static string DomainDNS = "domainDNS";
+ public static string InstanceType = "instanceType";
+ public static string MsDSSDReferenceDomain = "msDS-SDReferenceDomain";
+ public static string MsDSPortLDAP = "msDS-PortLDAP";
+ public static string MsDSPortSSL = "msDS-PortSSL";
+ public static string MsDSNCReplicaLocations = "msDS-NC-Replica-Locations";
+ public static string MsDSNCROReplicaLocations = "msDS-NC-RO-Replica-Locations";
+ public static string SupportedCapabilities = "supportedCapabilities";
+ public static string ServerName = "serverName";
+ public static string Enabled = "Enabled";
+ public static string ObjectGuid = "objectGuid";
+ public static string Keywords = "keywords";
+ public static string ServiceBindingInformation = "serviceBindingInformation";
+ public static string MsDSReplAuthenticationMode = "msDS-ReplAuthenticationMode";
+ public static string HasPartialReplicaNCs = "hasPartialReplicaNCs";
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ public static string Container = "container";
+#pragma warning restore 0414
+ public static string LdapDisplayName = "ldapDisplayName";
+ public static string AttributeID = "attributeID";
+ public static string AttributeSyntax = "attributeSyntax";
+ public static string Description = "description";
+ public static string SearchFlags = "searchFlags";
+ public static string OMSyntax = "oMSyntax";
+ public static string OMObjectClass = "oMObjectClass";
+ public static string IsSingleValued = "isSingleValued";
+ public static string IsDefunct = "isDefunct";
+ public static string RangeUpper = "rangeUpper";
+ public static string RangeLower = "rangeLower";
+ public static string IsMemberOfPartialAttributeSet = "isMemberOfPartialAttributeSet";
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ public static string ObjectVersion = "objectVersion";
+#pragma warning restore 0414
+ public static string LinkID = "linkID";
+ public static string ObjectClassCategory = "objectClassCategory";
+ public static string SchemaUpdateNow = "schemaUpdateNow";
+ public static string SubClassOf = "subClassOf";
+ public static string SchemaIDGuid = "schemaIDGUID";
+ public static string PossibleSuperiors = "possSuperiors";
+ public static string PossibleInferiors = "possibleInferiors";
+ public static string MustContain = "mustContain";
+ public static string MayContain = "mayContain";
+ public static string SystemMustContain = "systemMustContain";
+ public static string SystemMayContain = "systemMayContain";
+ public static string GovernsID = "governsID";
+ public static string IsGlobalCatalogReady = "isGlobalCatalogReady";
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ public static string NTSecurityDescriptor = "ntSecurityDescriptor";
+#pragma warning restore 0414
+ public static string DsServiceName = "dsServiceName";
+ public static string ReplicateSingleObject = "replicateSingleObject";
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ public static string MsDSMasteredBy = "msDS-masteredBy";
+#pragma warning restore 0414
+ public static string DefaultSecurityDescriptor = "defaultSecurityDescriptor";
+ public static string NamingContexts = "namingContexts";
+ public static string MsDSDefaultNamingContext = "msDS-DefaultNamingContext";
+ public static string OperatingSystemVersion = "operatingSystemVersion";
+ public static string AuxiliaryClass = "auxiliaryClass";
+ public static string SystemAuxiliaryClass = "systemAuxiliaryClass";
+ public static string SystemPossibleSuperiors = "systemPossSuperiors";
+ public static string InterSiteTopologyGenerator = "interSiteTopologyGenerator";
+ public static string FromServer = "fromServer";
+ public static string RIDAvailablePool = "rIDAvailablePool";
+
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ public static string SiteList = "siteList";
+#pragma warning restore 0414
+ public static string MsDSHasInstantiatedNCs = "msDS-HasInstantiatedNCs";
+
+ public static object GetPropertyValue(DirectoryEntry directoryEntry, string propertyName)
+ {
+ return GetPropertyValue(null, directoryEntry, propertyName);
+ }
+
+ public static object GetPropertyValue(DirectoryContext context, DirectoryEntry directoryEntry, string propertyName)
+ {
+ Debug.Assert(directoryEntry != null, "PropertyManager::GetPropertyValue - directoryEntry is null");
+
+ Debug.Assert(propertyName != null, "PropertyManager::GetPropertyValue - propertyName is null");
+
+ try
+ {
+ if (directoryEntry.Properties[propertyName].Count == 0)
+ {
+ if (directoryEntry.Properties[PropertyManager.DistinguishedName].Count != 0)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.PropertyNotFoundOnObject, propertyName, directoryEntry.Properties[PropertyManager.DistinguishedName].Value));
+ }
+ else
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.PropertyNotFound, propertyName));
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ return directoryEntry.Properties[propertyName].Value;
+ }
+
+ public static object GetSearchResultPropertyValue(SearchResult res, string propertyName)
+ {
+ Debug.Assert(res != null, "PropertyManager::GetSearchResultPropertyValue - res is null");
+
+ Debug.Assert(propertyName != null, "PropertyManager::GetSearchResultPropertyValue - propertyName is null");
+
+ ResultPropertyValueCollection propertyValues = null;
+ try
+ {
+ propertyValues = res.Properties[propertyName];
+ if ((propertyValues == null) || (propertyValues.Count < 1))
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.PropertyNotFound, propertyName));
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(e);
+ }
+
+ return propertyValues[0];
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyActiveDirectorySchemaClassCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyActiveDirectorySchemaClassCollection.cs
new file mode 100644
index 0000000000..d68acc590a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyActiveDirectorySchemaClassCollection.cs
@@ -0,0 +1,68 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Globalization;
+ using System.Collections;
+
+ public class ReadOnlyActiveDirectorySchemaClassCollection : ReadOnlyCollectionBase
+ {
+ internal ReadOnlyActiveDirectorySchemaClassCollection() { }
+
+ internal ReadOnlyActiveDirectorySchemaClassCollection(ICollection values)
+ {
+ if (values != null)
+ {
+ InnerList.AddRange(values);
+ }
+ }
+
+ public ActiveDirectorySchemaClass this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySchemaClass)InnerList[index];
+ }
+ }
+
+ public bool Contains(ActiveDirectorySchemaClass schemaClass)
+ {
+ if (schemaClass == null)
+ throw new ArgumentNullException("schemaClass");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaClass tmp = (ActiveDirectorySchemaClass)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaClass.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(ActiveDirectorySchemaClass schemaClass)
+ {
+ if (schemaClass == null)
+ throw new ArgumentNullException("schemaClass");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaClass tmp = (ActiveDirectorySchemaClass)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaClass.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(ActiveDirectorySchemaClass[] classes, int index)
+ {
+ InnerList.CopyTo(classes, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyActiveDirectorySchemaPropertyCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyActiveDirectorySchemaPropertyCollection.cs
new file mode 100644
index 0000000000..2f0692af06
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyActiveDirectorySchemaPropertyCollection.cs
@@ -0,0 +1,67 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Globalization;
+ using System.Collections;
+
+ public class ReadOnlyActiveDirectorySchemaPropertyCollection : ReadOnlyCollectionBase
+ {
+ internal ReadOnlyActiveDirectorySchemaPropertyCollection() { }
+
+ internal ReadOnlyActiveDirectorySchemaPropertyCollection(ArrayList values)
+ {
+ if (values != null)
+ {
+ InnerList.AddRange(values);
+ }
+ }
+
+ public ActiveDirectorySchemaProperty this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySchemaProperty)InnerList[index];
+ }
+ }
+
+ public bool Contains(ActiveDirectorySchemaProperty schemaProperty)
+ {
+ if (schemaProperty == null)
+ throw new ArgumentNullException("schemaProperty");
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaProperty tmp = (ActiveDirectorySchemaProperty)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaProperty.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(ActiveDirectorySchemaProperty schemaProperty)
+ {
+ if (schemaProperty == null)
+ throw new ArgumentNullException("schemaProperty");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySchemaProperty tmp = (ActiveDirectorySchemaProperty)InnerList[i];
+ if (Utils.Compare(tmp.Name, schemaProperty.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(ActiveDirectorySchemaProperty[] properties, int index)
+ {
+ InnerList.CopyTo(properties, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyDirectoryServerCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyDirectoryServerCollection.cs
new file mode 100644
index 0000000000..113baf7eb4
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyDirectoryServerCollection.cs
@@ -0,0 +1,86 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Globalization;
+ using System.Collections;
+
+ public class ReadOnlyDirectoryServerCollection : ReadOnlyCollectionBase
+ {
+ internal ReadOnlyDirectoryServerCollection() { }
+
+ internal ReadOnlyDirectoryServerCollection(ArrayList values)
+ {
+ if (values != null)
+ {
+ for (int i = 0; i < values.Count; i++)
+ {
+ Add((DirectoryServer)values[i]);
+ }
+ }
+ }
+
+ public DirectoryServer this[int index]
+ {
+ get
+ {
+ return (DirectoryServer)InnerList[index];
+ }
+ }
+
+ public bool Contains(DirectoryServer directoryServer)
+ {
+ if (directoryServer == null)
+ throw new ArgumentNullException("directoryServer");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ DirectoryServer tmp = (DirectoryServer)InnerList[i];
+ if (Utils.Compare(tmp.Name, directoryServer.Name) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(DirectoryServer directoryServer)
+ {
+ if (directoryServer == null)
+ throw new ArgumentNullException("directoryServer");
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ DirectoryServer tmp = (DirectoryServer)InnerList[i];
+ if (Utils.Compare(tmp.Name, directoryServer.Name) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(DirectoryServer[] directoryServers, int index)
+ {
+ InnerList.CopyTo(directoryServers, index);
+ }
+
+ internal int Add(DirectoryServer server)
+ {
+ return InnerList.Add(server);
+ }
+
+ internal void AddRange(ICollection servers)
+ {
+ InnerList.AddRange(servers);
+ }
+
+ internal void Clear()
+ {
+ InnerList.Clear();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteCollection.cs
new file mode 100644
index 0000000000..e80b1b0fe1
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteCollection.cs
@@ -0,0 +1,91 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Diagnostics;
+ using System.Globalization;
+
+ public class ReadOnlySiteCollection : ReadOnlyCollectionBase
+ {
+ internal ReadOnlySiteCollection() { }
+
+ internal ReadOnlySiteCollection(ArrayList sites)
+ {
+ for (int i = 0; i < sites.Count; i++)
+ {
+ Add((ActiveDirectorySite)sites[i]);
+ }
+ }
+
+ public ActiveDirectorySite this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySite)InnerList[index];
+ }
+ }
+
+ public bool Contains(ActiveDirectorySite site)
+ {
+ if (site == null)
+ throw new ArgumentNullException("site");
+
+ string dn = (string)PropertyManager.GetPropertyValue(site.context, site.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySite tmp = (ActiveDirectorySite)InnerList[i];
+
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(ActiveDirectorySite site)
+ {
+ if (site == null)
+ throw new ArgumentNullException("site");
+
+ string dn = (string)PropertyManager.GetPropertyValue(site.context, site.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySite tmp = (ActiveDirectorySite)InnerList[i];
+
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(ActiveDirectorySite[] sites, int index)
+ {
+ InnerList.CopyTo(sites, index);
+ }
+
+ internal int Add(ActiveDirectorySite site)
+ {
+ return InnerList.Add(site);
+ }
+
+ internal void Clear()
+ {
+ InnerList.Clear();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteLinkBridgeCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteLinkBridgeCollection.cs
new file mode 100644
index 0000000000..aec6cd78bc
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteLinkBridgeCollection.cs
@@ -0,0 +1,80 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Globalization;
+
+ public class ReadOnlySiteLinkBridgeCollection : ReadOnlyCollectionBase
+ {
+ internal ReadOnlySiteLinkBridgeCollection() { }
+
+ public ActiveDirectorySiteLinkBridge this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySiteLinkBridge)InnerList[index];
+ }
+ }
+
+ public bool Contains(ActiveDirectorySiteLinkBridge bridge)
+ {
+ if (bridge == null)
+ throw new ArgumentNullException("bridge");
+
+ string dn = (string)PropertyManager.GetPropertyValue(bridge.context, bridge.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySiteLinkBridge tmp = (ActiveDirectorySiteLinkBridge)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(ActiveDirectorySiteLinkBridge bridge)
+ {
+ if (bridge == null)
+ throw new ArgumentNullException("bridge");
+
+ string dn = (string)PropertyManager.GetPropertyValue(bridge.context, bridge.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySiteLinkBridge tmp = (ActiveDirectorySiteLinkBridge)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(ActiveDirectorySiteLinkBridge[] bridges, int index)
+ {
+ InnerList.CopyTo(bridges, index);
+ }
+
+ internal int Add(ActiveDirectorySiteLinkBridge bridge)
+ {
+ return InnerList.Add(bridge);
+ }
+
+ internal void Clear()
+ {
+ InnerList.Clear();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteLinkCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteLinkCollection.cs
new file mode 100644
index 0000000000..01a48a1bc8
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteLinkCollection.cs
@@ -0,0 +1,81 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.DirectoryServices;
+ using System.Globalization;
+
+ public class ReadOnlySiteLinkCollection : ReadOnlyCollectionBase
+ {
+ internal ReadOnlySiteLinkCollection() { }
+
+ public ActiveDirectorySiteLink this[int index]
+ {
+ get
+ {
+ return (ActiveDirectorySiteLink)InnerList[index];
+ }
+ }
+
+ public bool Contains(ActiveDirectorySiteLink link)
+ {
+ if (link == null)
+ throw new ArgumentNullException("link");
+
+ string dn = (string)PropertyManager.GetPropertyValue(link.context, link.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySiteLink tmp = (ActiveDirectorySiteLink)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(ActiveDirectorySiteLink link)
+ {
+ if (link == null)
+ throw new ArgumentNullException("link");
+
+ string dn = (string)PropertyManager.GetPropertyValue(link.context, link.cachedEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ActiveDirectorySiteLink tmp = (ActiveDirectorySiteLink)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(ActiveDirectorySiteLink[] links, int index)
+ {
+ InnerList.CopyTo(links, index);
+ }
+
+ internal int Add(ActiveDirectorySiteLink link)
+ {
+ return InnerList.Add(link);
+ }
+
+ internal void Clear()
+ {
+ InnerList.Clear();
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyStringCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyStringCollection.cs
new file mode 100644
index 0000000000..ec603b94f1
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlyStringCollection.cs
@@ -0,0 +1,84 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+ using System.DirectoryServices;
+
+ public class ReadOnlyStringCollection : ReadOnlyCollectionBase
+ {
+ internal ReadOnlyStringCollection() { }
+
+ internal ReadOnlyStringCollection(ArrayList values)
+ {
+ if (values == null)
+ {
+ values = new ArrayList();
+ }
+
+ this.InnerList.AddRange(values);
+ }
+ public string this[int index]
+ {
+ get
+ {
+ object returnValue = InnerList[index];
+
+ if (returnValue is Exception)
+ throw (Exception)returnValue;
+ else
+ return (string)returnValue;
+ }
+ }
+
+ public bool Contains(string value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ string tmp = (string)InnerList[i];
+ if (Utils.Compare(tmp, value) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(string value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ string tmp = (string)InnerList[i];
+ if (Utils.Compare(tmp, value) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(string[] values, int index)
+ {
+ InnerList.CopyTo(values, index);
+ }
+
+ internal void Add(String value)
+ {
+ InnerList.Add(value);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnection.cs
new file mode 100644
index 0000000000..ae6b1ed6f7
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnection.cs
@@ -0,0 +1,1001 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.DirectoryServices;
+ using System.Diagnostics;
+ using System.ComponentModel;
+ using System.Globalization;
+ using System.Security.Permissions;
+
+ public enum NotificationStatus
+ {
+ NoNotification = 0,
+ IntraSiteOnly = 1,
+ NotificationAlways = 2
+ }
+
+ public enum ReplicationSpan
+ {
+ IntraSite = 0,
+ InterSite = 1
+ }
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class ReplicationConnection : IDisposable
+ {
+ internal DirectoryContext context = null;
+ internal DirectoryEntry cachedDirectoryEntry = null;
+ internal bool existingConnection = false;
+ private bool _disposed = false;
+ private bool _checkADAM = false;
+ private bool _isADAMServer = false;
+ private int _options = 0;
+
+ private string _connectionName = null;
+ private string _sourceServerName = null;
+ private string _destinationServerName = null;
+ private ActiveDirectoryTransportType _transport = ActiveDirectoryTransportType.Rpc;
+
+ private const string ADAMGuid = "1.2.840.113556.1.4.1851";
+
+ public static ReplicationConnection FindByName(DirectoryContext context, string name)
+ {
+ ValidateArgument(context, name);
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ // bind to the rootdse to get the servername property
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ try
+ {
+ string serverDN = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ServerName);
+ string connectionContainer = "CN=NTDS Settings," + serverDN;
+ de = DirectoryEntryManager.GetDirectoryEntry(context, connectionContainer);
+ // doing the search to find the connection object based on its name
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=nTDSConnection)(objectCategory=NTDSConnection)(name=" + Utils.GetEscapedFilterValue(name) + "))",
+ new string[] { "distinguishedName" },
+ SearchScope.OneLevel,
+ false, /* no paged search */
+ false /* don't cache results */);
+ SearchResult srchResult = null;
+ try
+ {
+ srchResult = adSearcher.FindOne();
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // object is not found since we cannot even find the container in which to search
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ReplicationConnection), name);
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+
+ if (srchResult == null)
+ {
+ // no such connection object
+ Exception e = new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound), typeof(ReplicationConnection), name);
+ throw e;
+ }
+ else
+ {
+ DirectoryEntry connectionEntry = srchResult.GetDirectoryEntry();
+ return new ReplicationConnection(context, connectionEntry, name);
+ }
+ }
+ finally
+ {
+ de.Dispose();
+ }
+ }
+
+ internal ReplicationConnection(DirectoryContext context, DirectoryEntry connectionEntry, string name)
+ {
+ this.context = context;
+ cachedDirectoryEntry = connectionEntry;
+ _connectionName = name;
+ // this is an exising connection object
+ existingConnection = true;
+ }
+
+ public ReplicationConnection(DirectoryContext context, string name, DirectoryServer sourceServer) : this(context, name, sourceServer, null, ActiveDirectoryTransportType.Rpc)
+ {
+ }
+
+ public ReplicationConnection(DirectoryContext context, string name, DirectoryServer sourceServer, ActiveDirectorySchedule schedule) : this(context, name, sourceServer, schedule, ActiveDirectoryTransportType.Rpc)
+ {
+ }
+
+ public ReplicationConnection(DirectoryContext context, string name, DirectoryServer sourceServer, ActiveDirectoryTransportType transport) : this(context, name, sourceServer, null, transport)
+ {
+ }
+
+ public ReplicationConnection(DirectoryContext context, string name, DirectoryServer sourceServer, ActiveDirectorySchedule schedule, ActiveDirectoryTransportType transport)
+ {
+ ValidateArgument(context, name);
+
+ if (sourceServer == null)
+ throw new ArgumentNullException("sourceServer");
+
+ if (transport < ActiveDirectoryTransportType.Rpc || transport > ActiveDirectoryTransportType.Smtp)
+ throw new InvalidEnumArgumentException("value", (int)transport, typeof(ActiveDirectoryTransportType));
+
+ // work with copy of the context
+ context = new DirectoryContext(context);
+
+ ValidateTargetAndSourceServer(context, sourceServer);
+
+ this.context = context;
+ _connectionName = name;
+ _transport = transport;
+
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ try
+ {
+ string serverDN = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ServerName);
+ string connectionContainer = "CN=NTDS Settings," + serverDN;
+ de = DirectoryEntryManager.GetDirectoryEntry(context, connectionContainer);
+
+ // create the connection entry
+ string rdn = "cn=" + _connectionName;
+ rdn = Utils.GetEscapedPath(rdn);
+ cachedDirectoryEntry = de.Children.Add(rdn, "nTDSConnection");
+
+ // set all the properties
+
+ // sourceserver property
+ DirectoryContext sourceServerContext = sourceServer.Context;
+ de = DirectoryEntryManager.GetDirectoryEntry(sourceServerContext, WellKnownDN.RootDSE);
+ string serverName = (string)PropertyManager.GetPropertyValue(sourceServerContext, de, PropertyManager.ServerName);
+ serverName = "CN=NTDS Settings," + serverName;
+
+ cachedDirectoryEntry.Properties["fromServer"].Add(serverName);
+
+ // schedule property
+ if (schedule != null)
+ cachedDirectoryEntry.Properties["schedule"].Value = schedule.GetUnmanagedSchedule();
+
+ // transporttype property
+ string transportPath = Utils.GetDNFromTransportType(TransportType, context);
+ // verify that the transport is supported
+ de = DirectoryEntryManager.GetDirectoryEntry(context, transportPath);
+ try
+ {
+ de.Bind(true);
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ {
+ // if it is ADAM and transport type is SMTP, throw NotSupportedException.
+ DirectoryEntry tmpDE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ if (Utils.CheckCapability(tmpDE, Capability.ActiveDirectoryApplicationMode) && transport == ActiveDirectoryTransportType.Smtp)
+ {
+ throw new NotSupportedException(Res.GetString(Res.NotSupportTransportSMTP));
+ }
+ }
+
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ cachedDirectoryEntry.Properties["transportType"].Add(transportPath);
+
+ // enabledConnection property
+ cachedDirectoryEntry.Properties["enabledConnection"].Value = false;
+
+ // options
+ cachedDirectoryEntry.Properties["options"].Value = 0;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ de.Close();
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ if (disposing && cachedDirectoryEntry != null)
+ cachedDirectoryEntry.Dispose();
+
+ _disposed = true;
+ }
+ }
+
+ ~ReplicationConnection()
+ {
+ Dispose(false); // finalizer is called => Dispose has not been called yet.
+ }
+
+ public string Name
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _connectionName;
+ }
+ }
+
+ public string SourceServer
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the source server
+ if (_sourceServerName == null)
+ {
+ string sourceServerDN = (string)PropertyManager.GetPropertyValue(context, cachedDirectoryEntry, PropertyManager.FromServer);
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, sourceServerDN);
+ if (IsADAM)
+ {
+ int portnumber = (int)PropertyManager.GetPropertyValue(context, de, PropertyManager.MsDSPortLDAP);
+ string tmpServerName = (string)PropertyManager.GetPropertyValue(context, de.Parent, PropertyManager.DnsHostName);
+ if (portnumber != 389)
+ {
+ _sourceServerName = tmpServerName + ":" + portnumber;
+ }
+ }
+ else
+ {
+ _sourceServerName = (string)PropertyManager.GetPropertyValue(context, de.Parent, PropertyManager.DnsHostName);
+ }
+ }
+ return _sourceServerName;
+ }
+ }
+
+ public string DestinationServer
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (_destinationServerName == null)
+ {
+ DirectoryEntry NTDSObject = null;
+ DirectoryEntry serverObject = null;
+ try
+ {
+ NTDSObject = cachedDirectoryEntry.Parent;
+ serverObject = NTDSObject.Parent;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ string hostName = (string)PropertyManager.GetPropertyValue(context, serverObject, PropertyManager.DnsHostName);
+ if (IsADAM)
+ {
+ int portnumber = (int)PropertyManager.GetPropertyValue(context, NTDSObject, PropertyManager.MsDSPortLDAP);
+ if (portnumber != 389)
+ {
+ _destinationServerName = hostName + ":" + portnumber;
+ }
+ else
+ _destinationServerName = hostName;
+ }
+ else
+ _destinationServerName = hostName;
+ }
+ return _destinationServerName;
+ }
+ }
+
+ public bool Enabled
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // fetch the property value
+ try
+ {
+ if (cachedDirectoryEntry.Properties.Contains("enabledConnection"))
+ return (bool)cachedDirectoryEntry.Properties["enabledConnection"][0];
+ else
+ return false;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ cachedDirectoryEntry.Properties["enabledConnection"].Value = value;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public ActiveDirectoryTransportType TransportType
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // for exisint connection, we need to check its property, for newly created and not committed one, we just return
+ // the member variable value directly
+ if (existingConnection)
+ {
+ PropertyValueCollection propValue = null;
+ try
+ {
+ propValue = cachedDirectoryEntry.Properties["transportType"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (propValue.Count == 0)
+ {
+ // if the property does not exist, then default is to RPC over IP
+ return ActiveDirectoryTransportType.Rpc;
+ }
+ else
+ {
+ return Utils.GetTransportTypeFromDN((string)propValue[0]);
+ }
+ }
+ else
+ return _transport;
+ }
+ }
+
+ public bool GeneratedByKcc
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ PropertyValueCollection propValue = null;
+
+ try
+ {
+ propValue = cachedDirectoryEntry.Properties["options"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (propValue.Count == 0)
+ {
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ // NTDSCONN_OPT_IS_GENERATED ( 1 << 0 ) object generated by DS, not admin
+ if ((_options & 0x1) == 0)
+ return false;
+ else
+ return true;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ PropertyValueCollection propValue = cachedDirectoryEntry.Properties["options"];
+ if (propValue.Count == 0)
+ {
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ // NTDSCONN_OPT_IS_GENERATED ( 1 << 0 ) object generated by DS, not admin
+ if (value)
+ {
+ _options |= 0x1;
+ }
+ else
+ {
+ _options &= (~(0x1));
+ }
+
+ // put the value into cache
+ cachedDirectoryEntry.Properties["options"].Value = _options;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public bool ReciprocalReplicationEnabled
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ PropertyValueCollection propValue = null;
+ try
+ {
+ propValue = cachedDirectoryEntry.Properties["options"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (propValue.Count == 0)
+ {
+ // if the property does not exist, then default is to RPC over IP
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ // NTDSCONN_OPT_TWOWAY_SYNC ( 1 << 1 ) force sync in opposite direction at end of sync
+ if ((_options & 0x2) == 0)
+ return false;
+ else
+ return true;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ PropertyValueCollection propValue = cachedDirectoryEntry.Properties["options"];
+ if (propValue.Count == 0)
+ {
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ // NTDSCONN_OPT_TWOWAY_SYNC ( 1 << 1 ) force sync in opposite direction at end of sync
+ if (value == true)
+ {
+ _options |= 0x2;
+ }
+ else
+ {
+ _options &= (~(0x2));
+ }
+
+ // put the value into cache
+ cachedDirectoryEntry.Properties["options"].Value = _options;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public NotificationStatus ChangeNotificationStatus
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ PropertyValueCollection propValue = null;
+ try
+ {
+ propValue = cachedDirectoryEntry.Properties["options"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (propValue.Count == 0)
+ {
+ // if the property does not exist, then default is to RPC over IP
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ int overrideNotify = _options & 0x4;
+ int userNotify = _options & 0x8;
+ if (overrideNotify == 0x4 && userNotify == 0)
+ return NotificationStatus.NoNotification;
+ else if (overrideNotify == 0x4 && userNotify == 0x8)
+ return NotificationStatus.NotificationAlways;
+ else
+ return NotificationStatus.IntraSiteOnly;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (value < NotificationStatus.NoNotification || value > NotificationStatus.NotificationAlways)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(NotificationStatus));
+
+ try
+ {
+ PropertyValueCollection propValue = cachedDirectoryEntry.Properties["options"];
+ if (propValue.Count == 0)
+ {
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ if (value == NotificationStatus.IntraSiteOnly)
+ {
+ _options &= (~(0x4));
+ _options &= (~(0x8));
+ }
+ else if (value == NotificationStatus.NoNotification)
+ {
+ _options |= (0x4);
+ _options &= (~(0x8));
+ }
+ else
+ {
+ _options |= (0x4);
+ _options |= (0x8);
+ }
+
+ // put the value into cache
+ cachedDirectoryEntry.Properties["options"].Value = _options;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public bool DataCompressionEnabled
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ PropertyValueCollection propValue = null;
+ try
+ {
+ propValue = cachedDirectoryEntry.Properties["options"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (propValue.Count == 0)
+ {
+ // if the property does not exist, then default is to RPC over IP
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ //NTDSCONN_OPT_DISABLE_INTERSITE_COMPRESSION (1 << 4)
+ // 0 - Compression of replication data enabled
+ // 1 - Compression of replication data disabled
+ if ((_options & 0x10) == 0)
+ return true;
+ else
+ return false;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ PropertyValueCollection propValue = cachedDirectoryEntry.Properties["options"];
+ if (propValue.Count == 0)
+ {
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ //NTDSCONN_OPT_DISABLE_INTERSITE_COMPRESSION (1 << 4)
+ // 0 - Compression of replication data enabled
+ // 1 - Compression of replication data disabled
+ if (value == false)
+ {
+ _options |= 0x10;
+ }
+ else
+ {
+ _options &= (~(0x10));
+ }
+
+ // put the value into cache
+ cachedDirectoryEntry.Properties["options"].Value = _options;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public bool ReplicationScheduleOwnedByUser
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ PropertyValueCollection propValue = null;
+ try
+ {
+ propValue = cachedDirectoryEntry.Properties["options"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (propValue.Count == 0)
+ {
+ // if the property does not exist, then default is to RPC over IP
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ // NTDSCONN_OPT_USER_OWNED_SCHEDULE (1 << 5)
+ if ((_options & 0x20) == 0)
+ return false;
+ else
+ return true;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ PropertyValueCollection propValue = cachedDirectoryEntry.Properties["options"];
+ if (propValue.Count == 0)
+ {
+ _options = 0;
+ }
+ else
+ {
+ _options = (int)propValue[0];
+ }
+
+ // NTDSCONN_OPT_USER_OWNED_SCHEDULE (1 << 5)
+ if (value == true)
+ {
+ _options |= 0x20;
+ }
+ else
+ {
+ _options &= (~(0x20));
+ }
+
+ // put the value into cache
+ cachedDirectoryEntry.Properties["options"].Value = _options;
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public ReplicationSpan ReplicationSpan
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // find out whether the site and the destination is in the same site
+ string destinationPath = (string)PropertyManager.GetPropertyValue(context, cachedDirectoryEntry, PropertyManager.FromServer);
+ string destinationSite = Utils.GetDNComponents(destinationPath)[3].Value;
+
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string serverDN = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.ServerName);
+ string serverSite = Utils.GetDNComponents(serverDN)[2].Value;
+
+ if (Utils.Compare(destinationSite, serverSite) == 0)
+ {
+ return ReplicationSpan.IntraSite;
+ }
+ else
+ {
+ return ReplicationSpan.InterSite;
+ }
+ }
+ }
+
+ public ActiveDirectorySchedule ReplicationSchedule
+ {
+ get
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ ActiveDirectorySchedule schedule = null;
+ bool scheduleExists = false;
+ try
+ {
+ scheduleExists = cachedDirectoryEntry.Properties.Contains("schedule");
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (scheduleExists)
+ {
+ byte[] tmpSchedule = (byte[])cachedDirectoryEntry.Properties["schedule"][0];
+ Debug.Assert(tmpSchedule != null && tmpSchedule.Length == 188);
+ schedule = new ActiveDirectorySchedule();
+ schedule.SetUnmanagedSchedule(tmpSchedule);
+ }
+
+ return schedule;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ if (value == null)
+ {
+ if (cachedDirectoryEntry.Properties.Contains("schedule"))
+ cachedDirectoryEntry.Properties["schedule"].Clear();
+ }
+ else
+ {
+ cachedDirectoryEntry.Properties["schedule"].Value = value.GetUnmanagedSchedule();
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ private bool IsADAM
+ {
+ get
+ {
+ if (!_checkADAM)
+ {
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ PropertyValueCollection values = null;
+ try
+ {
+ values = de.Properties["supportedCapabilities"];
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (values.Contains(ADAMGuid))
+ _isADAMServer = true;
+ }
+
+ return _isADAMServer;
+ }
+ }
+
+ public void Delete()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!existingConnection)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotDelete));
+ }
+ else
+ {
+ try
+ {
+ cachedDirectoryEntry.Parent.Children.Remove(cachedDirectoryEntry);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+
+ public void Save()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ try
+ {
+ cachedDirectoryEntry.CommitChanges();
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ if (!existingConnection)
+ {
+ existingConnection = true;
+ }
+ }
+
+ public override string ToString()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return Name;
+ }
+
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (!existingConnection)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotGetObject));
+ }
+ else
+ {
+ return DirectoryEntryManager.GetDirectoryEntryInternal(context, cachedDirectoryEntry.Path);
+ }
+ }
+
+ private static void ValidateArgument(DirectoryContext context, string name)
+ {
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ // the target of the scope must be server
+ if (context.Name == null || !context.isServer())
+ throw new ArgumentException(Res.GetString(Res.DirectoryContextNeedHost));
+
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (name.Length == 0)
+ throw new ArgumentException(Res.GetString(Res.EmptyStringParameter), "name");
+ }
+
+ private void ValidateTargetAndSourceServer(DirectoryContext context, DirectoryServer sourceServer)
+ {
+ bool targetIsDC = false;
+ DirectoryEntry targetDE = null;
+ DirectoryEntry sourceDE = null;
+
+ // first find out target is a dc or ADAM instance
+ targetDE = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ try
+ {
+ if (Utils.CheckCapability(targetDE, Capability.ActiveDirectory))
+ {
+ targetIsDC = true;
+ }
+ else if (!Utils.CheckCapability(targetDE, Capability.ActiveDirectoryApplicationMode))
+ {
+ // if it is also not an ADAM instance, it is invalid then
+ throw new ArgumentException(Res.GetString(Res.DirectoryContextNeedHost), "context");
+ }
+
+ if (targetIsDC && !(sourceServer is DomainController))
+ {
+ // target and sourceServer are not of the same type
+ throw new ArgumentException(Res.GetString(Res.ConnectionSourcServerShouldBeDC), "sourceServer");
+ }
+ else if (!targetIsDC && (sourceServer is DomainController))
+ {
+ // target and sourceServer are not of the same type
+ throw new ArgumentException(Res.GetString(Res.ConnectionSourcServerShouldBeADAM), "sourceServer");
+ }
+
+ sourceDE = DirectoryEntryManager.GetDirectoryEntry(sourceServer.Context, WellKnownDN.RootDSE);
+
+ // now if they are both dc, we need to check whether they come from the same forest
+ if (targetIsDC)
+ {
+ string targetRoot = (string)PropertyManager.GetPropertyValue(context, targetDE, PropertyManager.RootDomainNamingContext);
+ string sourceRoot = (string)PropertyManager.GetPropertyValue(sourceServer.Context, sourceDE, PropertyManager.RootDomainNamingContext);
+ if (Utils.Compare(targetRoot, sourceRoot) != 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.ConnectionSourcServerSameForest), "sourceServer");
+ }
+ }
+ else
+ {
+ string targetRoot = (string)PropertyManager.GetPropertyValue(context, targetDE, PropertyManager.ConfigurationNamingContext);
+ string sourceRoot = (string)PropertyManager.GetPropertyValue(sourceServer.Context, sourceDE, PropertyManager.ConfigurationNamingContext);
+ if (Utils.Compare(targetRoot, sourceRoot) != 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.ConnectionSourcServerSameConfigSet), "sourceServer");
+ }
+ }
+ }
+ catch (COMException e)
+ {
+ ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (targetDE != null)
+ targetDE.Close();
+
+ if (sourceDE != null)
+ sourceDE.Close();
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnectionCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnectionCollection.cs
new file mode 100644
index 0000000000..3d02726cd8
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnectionCollection.cs
@@ -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.
+
+namespace System.DirectoryServices.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+
+ public class ReplicationConnectionCollection : ReadOnlyCollectionBase
+ {
+ internal ReplicationConnectionCollection() { }
+
+ public ReplicationConnection this[int index]
+ {
+ get
+ {
+ return (ReplicationConnection)InnerList[index];
+ }
+ }
+
+ public bool Contains(ReplicationConnection connection)
+ {
+ if (connection == null)
+ throw new ArgumentNullException("connection");
+
+ if (!connection.existingConnection)
+ throw new InvalidOperationException(Res.GetString(Res.ConnectionNotCommitted, connection.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(connection.context, connection.cachedDirectoryEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ReplicationConnection tmp = (ReplicationConnection)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedDirectoryEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(ReplicationConnection connection)
+ {
+ if (connection == null)
+ throw new ArgumentNullException("connection");
+
+ if (!connection.existingConnection)
+ throw new InvalidOperationException(Res.GetString(Res.ConnectionNotCommitted, connection.Name));
+
+ string dn = (string)PropertyManager.GetPropertyValue(connection.context, connection.cachedDirectoryEntry, PropertyManager.DistinguishedName);
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ ReplicationConnection tmp = (ReplicationConnection)InnerList[i];
+ string tmpDn = (string)PropertyManager.GetPropertyValue(tmp.context, tmp.cachedDirectoryEntry, PropertyManager.DistinguishedName);
+
+ if (Utils.Compare(tmpDn, dn) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void CopyTo(ReplicationConnection[] connections, int index)
+ {
+ InnerList.CopyTo(connections, index);
+ }
+
+ internal int Add(ReplicationConnection value)
+ {
+ return InnerList.Add(value);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationCursor.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationCursor.cs
new file mode 100644
index 0000000000..daed244b7c
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationCursor.cs
@@ -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.
+
+namespace System.DirectoryServices.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ public class ReplicationCursor
+ {
+ private string _partition;
+ private Guid _invocationID;
+ private long _USN;
+ private string _serverDN = null;
+ private DateTime _syncTime;
+ private bool _advanced = false;
+ private string _sourceServer = null;
+
+ private DirectoryServer _server = null;
+
+ private ReplicationCursor() { }
+
+ internal ReplicationCursor(DirectoryServer server, string partition, Guid guid, long filter, long time, IntPtr dn)
+ {
+ _partition = partition;
+ _invocationID = guid;
+ _USN = filter;
+
+ // convert filetime to DateTime
+ _syncTime = DateTime.FromFileTime(time);
+
+ // get the dn
+ _serverDN = Marshal.PtrToStringUni(dn);
+
+ _advanced = true;
+
+ _server = server;
+ }
+
+ internal ReplicationCursor(DirectoryServer server, string partition, Guid guid, long filter)
+ {
+ _partition = partition;
+ _invocationID = guid;
+ _USN = filter;
+
+ _server = server;
+ }
+
+ public string PartitionName
+ {
+ get
+ {
+ return _partition;
+ }
+ }
+
+ public Guid SourceInvocationId
+ {
+ get
+ {
+ return _invocationID;
+ }
+ }
+
+ public long UpToDatenessUsn
+ {
+ get
+ {
+ return _USN;
+ }
+ }
+
+ public string SourceServer
+ {
+ get
+ {
+ // get the source server name if we are on win2k, or above win2k and serverDN is not NULL (means KCC translation is successful)
+ if (!_advanced || (_advanced && _serverDN != null))
+ {
+ _sourceServer = Utils.GetServerNameFromInvocationID(_serverDN, SourceInvocationId, _server);
+ }
+
+ return _sourceServer;
+ }
+ }
+
+ public DateTime LastSuccessfulSyncTime
+ {
+ get
+ {
+ if (_advanced)
+ return _syncTime;
+ else
+ {
+ // win2k client machine does not support this
+ if ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor == 0))
+ throw new PlatformNotSupportedException(Res.GetString(Res.DSNotSupportOnClient));
+ else
+ throw new PlatformNotSupportedException(Res.GetString(Res.DSNotSupportOnDC));
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationCursorCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationCursorCollection.cs
new file mode 100644
index 0000000000..dde8543f3a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationCursorCollection.cs
@@ -0,0 +1,95 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+
+ public class ReplicationCursorCollection : ReadOnlyCollectionBase
+ {
+ private DirectoryServer _server = null;
+ internal ReplicationCursorCollection(DirectoryServer server)
+ {
+ _server = server;
+ }
+
+ public ReplicationCursor this[int index]
+ {
+ get
+ {
+ return (ReplicationCursor)InnerList[index];
+ }
+ }
+
+ public bool Contains(ReplicationCursor cursor)
+ {
+ if (cursor == null)
+ throw new ArgumentNullException("cursor");
+
+ return InnerList.Contains(cursor);
+ }
+
+ public int IndexOf(ReplicationCursor cursor)
+ {
+ if (cursor == null)
+ throw new ArgumentNullException("cursor");
+
+ return InnerList.IndexOf(cursor);
+ }
+
+ public void CopyTo(ReplicationCursor[] values, int index)
+ {
+ InnerList.CopyTo(values, index);
+ }
+
+ private int Add(ReplicationCursor cursor)
+ {
+ return InnerList.Add(cursor);
+ }
+
+ internal void AddHelper(string partition, object cursors, bool advanced, IntPtr info)
+ {
+ // get the count
+ int count = 0;
+ if (advanced)
+ count = ((DS_REPL_CURSORS_3)cursors).cNumCursors;
+ else
+ count = ((DS_REPL_CURSORS)cursors).cNumCursors;
+
+ IntPtr addr = (IntPtr)0;
+
+ for (int i = 0; i < count; i++)
+ {
+ if (advanced)
+ {
+ addr = IntPtr.Add(info, Marshal.SizeOf(typeof(int)) * 2 + i * Marshal.SizeOf(typeof(DS_REPL_CURSOR_3)));
+ DS_REPL_CURSOR_3 cursor = new DS_REPL_CURSOR_3();
+ Marshal.PtrToStructure(addr, cursor);
+
+ ReplicationCursor managedCursor = new ReplicationCursor(_server,
+ partition,
+ cursor.uuidSourceDsaInvocationID,
+ cursor.usnAttributeFilter,
+ cursor.ftimeLastSyncSuccess,
+ cursor.pszSourceDsaDN);
+ Add(managedCursor);
+ }
+ else
+ {
+ addr = IntPtr.Add(info, Marshal.SizeOf(typeof(int)) * 2 + i * Marshal.SizeOf(typeof(DS_REPL_CURSOR)));
+ DS_REPL_CURSOR cursor = new DS_REPL_CURSOR();
+ Marshal.PtrToStructure(addr, cursor);
+
+ ReplicationCursor managedCursor = new ReplicationCursor(_server,
+ partition,
+ cursor.uuidSourceDsaInvocationID,
+ cursor.usnAttributeFilter);
+ Add(managedCursor);
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationFailure.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationFailure.cs
new file mode 100644
index 0000000000..b6a97bbd69
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationFailure.cs
@@ -0,0 +1,102 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+
+ public class ReplicationFailure
+ {
+ private string _sourceDsaDN;
+ private Guid _uuidDsaObjGuid;
+ private DateTime _timeFirstFailure;
+ private int _numFailures;
+ internal int lastResult;
+
+ private DirectoryServer _server = null;
+ private string _sourceServer = null;
+ private Hashtable _nameTable = null;
+
+ internal ReplicationFailure(IntPtr addr, DirectoryServer server, Hashtable table)
+ {
+ DS_REPL_KCC_DSA_FAILURE failure = new DS_REPL_KCC_DSA_FAILURE();
+ Marshal.PtrToStructure(addr, failure);
+
+ _sourceDsaDN = Marshal.PtrToStringUni(failure.pszDsaDN);
+ _uuidDsaObjGuid = failure.uuidDsaObjGuid;
+ _timeFirstFailure = DateTime.FromFileTime(failure.ftimeFirstFailure);
+ _numFailures = failure.cNumFailures;
+ lastResult = failure.dwLastResult;
+
+ _server = server;
+ _nameTable = table;
+ }
+
+ public string SourceServer
+ {
+ get
+ {
+ if (_sourceServer == null)
+ {
+ // check whether we have got it before
+ if (_nameTable.Contains(SourceServerGuid))
+ {
+ _sourceServer = (string)_nameTable[SourceServerGuid];
+ }
+ else if (_sourceDsaDN != null)
+ {
+ _sourceServer = Utils.GetServerNameFromInvocationID(_sourceDsaDN, SourceServerGuid, _server);
+ // add it to the hashtable
+ _nameTable.Add(SourceServerGuid, _sourceServer);
+ }
+ }
+
+ return _sourceServer;
+ }
+ }
+
+ private Guid SourceServerGuid
+ {
+ get
+ {
+ return _uuidDsaObjGuid;
+ }
+ }
+
+ public DateTime FirstFailureTime
+ {
+ get
+ {
+ return _timeFirstFailure;
+ }
+ }
+
+ public int ConsecutiveFailureCount
+ {
+ get
+ {
+ return _numFailures;
+ }
+ }
+
+ public int LastErrorCode
+ {
+ get
+ {
+ return lastResult;
+ }
+ }
+
+ public string LastErrorMessage
+ {
+ get
+ {
+ return ExceptionHelper.GetErrorMessage(lastResult, false);
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationFailureCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationFailureCollection.cs
new file mode 100644
index 0000000000..c0530978af
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationFailureCollection.cs
@@ -0,0 +1,81 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+
+ public class ReplicationFailureCollection : ReadOnlyCollectionBase
+ {
+ private DirectoryServer _server = null;
+ private Hashtable _nameTable = null;
+
+ internal ReplicationFailureCollection(DirectoryServer server)
+ {
+ _server = server;
+ Hashtable tempNameTable = new Hashtable();
+ _nameTable = Hashtable.Synchronized(tempNameTable);
+ }
+
+ public ReplicationFailure this[int index]
+ {
+ get
+ {
+ return (ReplicationFailure)InnerList[index];
+ }
+ }
+
+ public bool Contains(ReplicationFailure failure)
+ {
+ if (failure == null)
+ throw new ArgumentNullException("failure");
+
+ return InnerList.Contains(failure);
+ }
+
+ public int IndexOf(ReplicationFailure failure)
+ {
+ if (failure == null)
+ throw new ArgumentNullException("failure");
+
+ return InnerList.IndexOf(failure);
+ }
+
+ public void CopyTo(ReplicationFailure[] failures, int index)
+ {
+ InnerList.CopyTo(failures, index);
+ }
+
+ private int Add(ReplicationFailure failure)
+ {
+ return InnerList.Add(failure);
+ }
+
+ internal void AddHelper(DS_REPL_KCC_DSA_FAILURES failures, IntPtr info)
+ {
+ // get the count
+ int count = failures.cNumEntries;
+
+ IntPtr addr = (IntPtr)0;
+
+ for (int i = 0; i < count; i++)
+ {
+ addr = IntPtr.Add(info, Marshal.SizeOf(typeof(int)) * 2 + i * Marshal.SizeOf(typeof(DS_REPL_KCC_DSA_FAILURE)));
+
+ ReplicationFailure managedFailure = new ReplicationFailure(addr, _server, _nameTable);
+
+ // in certain scenario, KCC returns some failure records that we need to process it first before returning
+ if (managedFailure.LastErrorCode == 0)
+ {
+ // we change the error code to some generic one
+ managedFailure.lastResult = ExceptionHelper.ERROR_DS_UNKNOWN_ERROR;
+ }
+
+ Add(managedFailure);
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationNeighbor.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationNeighbor.cs
new file mode 100644
index 0000000000..5fa56b8ed7
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationNeighbor.cs
@@ -0,0 +1,200 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+
+ public enum ActiveDirectoryTransportType
+ {
+ Rpc = 0,
+ Smtp = 1
+ }
+
+ public class ReplicationNeighbor
+ {
+ [Flags]
+ public enum ReplicationNeighborOptions : long
+ {
+ Writeable = 0x10,
+ SyncOnStartup = 0x20,
+ ScheduledSync = 0x40,
+ UseInterSiteTransport = 0x80,
+ TwoWaySync = 0x200,
+ ReturnObjectParent = 0x800,
+ FullSyncInProgress = 0x10000,
+ FullSyncNextPacket = 0x20000,
+ NeverSynced = 0x200000,
+ Preempted = 0x01000000,
+ IgnoreChangeNotifications = 0x04000000,
+ DisableScheduledSync = 0x08000000,
+ CompressChanges = 0x10000000,
+ NoChangeNotifications = 0x20000000,
+ PartialAttributeSet = 0x40000000
+ }
+
+ private string _namingContext;
+ private string _sourceServerDN;
+ private ActiveDirectoryTransportType _transportType;
+ private ReplicationNeighborOptions _replicaFlags;
+ private Guid _uuidSourceDsaInvocationID;
+ private long _usnLastObjChangeSynced;
+ private long _usnAttributeFilter;
+ private DateTime _timeLastSyncSuccess;
+ private DateTime _timeLastSyncAttempt;
+ private int _lastSyncResult;
+ private int _consecutiveSyncFailures;
+
+ private DirectoryServer _server = null;
+ private string _sourceServer = null;
+ private Hashtable _nameTable = null;
+
+ internal ReplicationNeighbor(IntPtr addr, DirectoryServer server, Hashtable table)
+ {
+ DS_REPL_NEIGHBOR neighbor = new DS_REPL_NEIGHBOR();
+ Marshal.PtrToStructure(addr, neighbor);
+
+ _namingContext = Marshal.PtrToStringUni(neighbor.pszNamingContext);
+ _sourceServerDN = Marshal.PtrToStringUni(neighbor.pszSourceDsaDN);
+
+ string transportDN = Marshal.PtrToStringUni(neighbor.pszAsyncIntersiteTransportDN);
+ if (transportDN != null)
+ {
+ string rdn = Utils.GetRdnFromDN(transportDN);
+ string transport = (Utils.GetDNComponents(rdn))[0].Value;
+
+ if (String.Compare(transport, "SMTP", StringComparison.OrdinalIgnoreCase) == 0)
+ _transportType = ActiveDirectoryTransportType.Smtp;
+ else
+ _transportType = ActiveDirectoryTransportType.Rpc;
+ }
+
+ _replicaFlags = (ReplicationNeighborOptions)neighbor.dwReplicaFlags;
+ _uuidSourceDsaInvocationID = neighbor.uuidSourceDsaInvocationID;
+ _usnLastObjChangeSynced = neighbor.usnLastObjChangeSynced;
+ _usnAttributeFilter = neighbor.usnAttributeFilter;
+ _timeLastSyncSuccess = DateTime.FromFileTime(neighbor.ftimeLastSyncSuccess);
+ _timeLastSyncAttempt = DateTime.FromFileTime(neighbor.ftimeLastSyncAttempt);
+ _lastSyncResult = neighbor.dwLastSyncResult;
+ _consecutiveSyncFailures = neighbor.cNumConsecutiveSyncFailures;
+
+ _server = server;
+ _nameTable = table;
+ }
+
+ public string PartitionName
+ {
+ get
+ {
+ return _namingContext;
+ }
+ }
+
+ public string SourceServer
+ {
+ get
+ {
+ if (_sourceServer == null)
+ {
+ // check whether we have got it before
+ if (_nameTable.Contains(SourceInvocationId))
+ {
+ _sourceServer = (string)_nameTable[SourceInvocationId];
+ }
+ else if (_sourceServerDN != null)
+ {
+ _sourceServer = Utils.GetServerNameFromInvocationID(_sourceServerDN, SourceInvocationId, _server);
+ // add it to the hashtable
+ _nameTable.Add(SourceInvocationId, _sourceServer);
+ }
+ }
+
+ return _sourceServer;
+ }
+ }
+
+ public ActiveDirectoryTransportType TransportType
+ {
+ get
+ {
+ return _transportType;
+ }
+ }
+
+ public ReplicationNeighborOptions ReplicationNeighborOption
+ {
+ get
+ {
+ return _replicaFlags;
+ }
+ }
+
+ public Guid SourceInvocationId
+ {
+ get
+ {
+ return _uuidSourceDsaInvocationID;
+ }
+ }
+
+ public long UsnLastObjectChangeSynced
+ {
+ get
+ {
+ return _usnLastObjChangeSynced;
+ }
+ }
+
+ public long UsnAttributeFilter
+ {
+ get
+ {
+ return _usnAttributeFilter;
+ }
+ }
+
+ public DateTime LastSuccessfulSync
+ {
+ get
+ {
+ return _timeLastSyncSuccess;
+ }
+ }
+
+ public DateTime LastAttemptedSync
+ {
+ get
+ {
+ return _timeLastSyncAttempt;
+ }
+ }
+
+ public int LastSyncResult
+ {
+ get
+ {
+ return _lastSyncResult;
+ }
+ }
+
+ public string LastSyncMessage
+ {
+ get
+ {
+ return ExceptionHelper.GetErrorMessage(_lastSyncResult, false);
+ }
+ }
+
+ public int ConsecutiveFailureCount
+ {
+ get
+ {
+ return _consecutiveSyncFailures;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationNeighborCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationNeighborCollection.cs
new file mode 100644
index 0000000000..0d89a09445
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationNeighborCollection.cs
@@ -0,0 +1,75 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+
+ public class ReplicationNeighborCollection : ReadOnlyCollectionBase
+ {
+ private DirectoryServer _server = null;
+ private Hashtable _nameTable = null;
+
+ internal ReplicationNeighborCollection(DirectoryServer server)
+ {
+ _server = server;
+ Hashtable tempNameTable = new Hashtable();
+ _nameTable = Hashtable.Synchronized(tempNameTable);
+ }
+
+ public ReplicationNeighbor this[int index]
+ {
+ get
+ {
+ return (ReplicationNeighbor)InnerList[index];
+ }
+ }
+
+ public bool Contains(ReplicationNeighbor neighbor)
+ {
+ if (neighbor == null)
+ throw new ArgumentNullException("neighbor");
+
+ return InnerList.Contains(neighbor);
+ }
+
+ public int IndexOf(ReplicationNeighbor neighbor)
+ {
+ if (neighbor == null)
+ throw new ArgumentNullException("neighbor");
+
+ return InnerList.IndexOf(neighbor);
+ }
+
+ public void CopyTo(ReplicationNeighbor[] neighbors, int index)
+ {
+ InnerList.CopyTo(neighbors, index);
+ }
+
+ private int Add(ReplicationNeighbor neighbor)
+ {
+ return InnerList.Add(neighbor);
+ }
+
+ internal void AddHelper(DS_REPL_NEIGHBORS neighbors, IntPtr info)
+ {
+ // get the count
+ int count = neighbors.cNumNeighbors;
+
+ IntPtr addr = (IntPtr)0;
+
+ for (int i = 0; i < count; i++)
+ {
+ addr = IntPtr.Add(info, Marshal.SizeOf(typeof(int)) * 2 + i * Marshal.SizeOf(typeof(DS_REPL_NEIGHBOR)));
+
+ ReplicationNeighbor managedNeighbor = new ReplicationNeighbor(addr, _server, _nameTable);
+
+ Add(managedNeighbor);
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperation.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperation.cs
new file mode 100644
index 0000000000..d1db7b707c
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperation.cs
@@ -0,0 +1,127 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+
+ public class ReplicationOperation
+ {
+ private DateTime _timeEnqueued;
+ private int _serialNumber;
+ private int _priority;
+ private ReplicationOperationType _operationType;
+ private string _namingContext;
+ private string _dsaDN;
+ private Guid _uuidDsaObjGuid;
+
+ private DirectoryServer _server = null;
+ private string _sourceServer = null;
+ private Hashtable _nameTable = null;
+
+ internal ReplicationOperation(IntPtr addr, DirectoryServer server, Hashtable table)
+ {
+ DS_REPL_OP operation = new DS_REPL_OP();
+ Marshal.PtrToStructure(addr, operation);
+
+ // get the enqueued time
+ _timeEnqueued = DateTime.FromFileTime(operation.ftimeEnqueued);
+
+ // get the operation identifier
+ _serialNumber = operation.ulSerialNumber;
+
+ // get the priority
+ _priority = operation.ulPriority;
+
+ // get the operation type
+ _operationType = operation.OpType;
+
+ // get the partition name
+ _namingContext = Marshal.PtrToStringUni(operation.pszNamingContext);
+
+ // get the dsaDN
+ _dsaDN = Marshal.PtrToStringUni(operation.pszDsaDN);
+
+ // get the dsaobject guid
+ _uuidDsaObjGuid = operation.uuidDsaObjGuid;
+
+ _server = server;
+ _nameTable = table;
+ }
+
+ public DateTime TimeEnqueued
+ {
+ get
+ {
+ return _timeEnqueued;
+ }
+ }
+
+ public int OperationNumber
+ {
+ get
+ {
+ return _serialNumber;
+ }
+ }
+
+ public int Priority
+ {
+ get
+ {
+ return _priority;
+ }
+ }
+
+ public ReplicationOperationType OperationType
+ {
+ get
+ {
+ return _operationType;
+ }
+ }
+
+ public string PartitionName
+ {
+ get
+ {
+ return _namingContext;
+ }
+ }
+
+ public string SourceServer
+ {
+ get
+ {
+ if (_sourceServer == null)
+ {
+ // check whether we have got it before
+ if (_nameTable.Contains(SourceServerGuid))
+ {
+ _sourceServer = (string)_nameTable[SourceServerGuid];
+ }
+ else if (_dsaDN != null)
+ {
+ _sourceServer = Utils.GetServerNameFromInvocationID(_dsaDN, SourceServerGuid, _server);
+ // add it to the hashtable
+ _nameTable.Add(SourceServerGuid, _sourceServer);
+ }
+ }
+
+ return _sourceServer;
+ }
+ }
+
+ private Guid SourceServerGuid
+ {
+ get
+ {
+ return _uuidDsaObjGuid;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperationCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperationCollection.cs
new file mode 100644
index 0000000000..ab4bf1f30a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperationCollection.cs
@@ -0,0 +1,82 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+
+ public class ReplicationOperationCollection : ReadOnlyCollectionBase
+ {
+ private DirectoryServer _server = null;
+ private Hashtable _nameTable = null;
+
+ internal ReplicationOperationCollection(DirectoryServer server)
+ {
+ _server = server;
+ Hashtable tempNameTable = new Hashtable();
+ _nameTable = Hashtable.Synchronized(tempNameTable);
+ }
+
+ public ReplicationOperation this[int index]
+ {
+ get
+ {
+ return (ReplicationOperation)InnerList[index];
+ }
+ }
+
+ public bool Contains(ReplicationOperation operation)
+ {
+ if (operation == null)
+ throw new ArgumentNullException("operation");
+
+ return InnerList.Contains(operation);
+ }
+
+ public int IndexOf(ReplicationOperation operation)
+ {
+ if (operation == null)
+ throw new ArgumentNullException("operation");
+
+ return InnerList.IndexOf(operation);
+ }
+
+ public void CopyTo(ReplicationOperation[] operations, int index)
+ {
+ InnerList.CopyTo(operations, index);
+ }
+
+ private int Add(ReplicationOperation operation)
+ {
+ return InnerList.Add(operation);
+ }
+
+ internal void AddHelper(DS_REPL_PENDING_OPS operations, IntPtr info)
+ {
+ // get the count
+ int count = operations.cNumPendingOps;
+
+ IntPtr addr = (IntPtr)0;
+
+ for (int i = 0; i < count; i++)
+ {
+ addr = IntPtr.Add(info, Marshal.SizeOf(typeof(DS_REPL_PENDING_OPS)) + i * Marshal.SizeOf(typeof(DS_REPL_OP)));
+ ReplicationOperation managedOperation = new ReplicationOperation(addr, _server, _nameTable);
+
+ Add(managedOperation);
+ }
+ }
+
+ internal ReplicationOperation GetFirstOperation()
+ {
+ ReplicationOperation op = (ReplicationOperation)InnerList[0];
+ InnerList.RemoveAt(0);
+
+ return op;
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperationInformation.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperationInformation.cs
new file mode 100644
index 0000000000..d439165f5a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationOperationInformation.cs
@@ -0,0 +1,46 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+
+ public class ReplicationOperationInformation
+ {
+ internal DateTime startTime;
+ internal ReplicationOperation currentOp = null;
+ internal ReplicationOperationCollection collection = null;
+
+ public ReplicationOperationInformation()
+ {
+ }
+
+ public DateTime OperationStartTime
+ {
+ get
+ {
+ return startTime;
+ }
+ }
+
+ public ReplicationOperation CurrentOperation
+ {
+ get
+ {
+ return currentOp;
+ }
+ }
+
+ public ReplicationOperationCollection PendingOperations
+ {
+ get
+ {
+ return collection;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/RoleOwner.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/RoleOwner.cs
new file mode 100644
index 0000000000..ef9427cf43
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/RoleOwner.cs
@@ -0,0 +1,23 @@
+// 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.ActiveDirectory
+{
+ using System;
+
+ public enum ActiveDirectoryRole : int
+ {
+ SchemaRole = 0,
+ NamingRole = 1,
+ PdcRole = 2,
+ RidRole = 3,
+ InfrastructureRole = 4
+ }
+
+ public enum AdamRole : int
+ {
+ SchemaRole = 0,
+ NamingRole = 1
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/RoleOwnerCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/RoleOwnerCollection.cs
new file mode 100644
index 0000000000..4adaf964d8
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/RoleOwnerCollection.cs
@@ -0,0 +1,140 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Collections;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.Runtime.InteropServices;
+
+ public class ActiveDirectoryRoleCollection : ReadOnlyCollectionBase
+ {
+ internal ActiveDirectoryRoleCollection() { }
+
+ internal ActiveDirectoryRoleCollection(ArrayList values)
+ {
+ if (values != null)
+ {
+ InnerList.AddRange(values);
+ }
+ }
+
+ public ActiveDirectoryRole this[int index]
+ {
+ get
+ {
+ return (ActiveDirectoryRole)InnerList[index];
+ }
+ }
+
+ public bool Contains(ActiveDirectoryRole role)
+ {
+ if (role < ActiveDirectoryRole.SchemaRole || role > ActiveDirectoryRole.InfrastructureRole)
+ {
+ throw new InvalidEnumArgumentException("role", (int)role, typeof(ActiveDirectoryRole));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ int tmp = (int)InnerList[i];
+ if (tmp == (int)role)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(ActiveDirectoryRole role)
+ {
+ if (role < ActiveDirectoryRole.SchemaRole || role > ActiveDirectoryRole.InfrastructureRole)
+ {
+ throw new InvalidEnumArgumentException("role", (int)role, typeof(ActiveDirectoryRole));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ int tmp = (int)InnerList[i];
+
+ if (tmp == (int)role)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ public void CopyTo(ActiveDirectoryRole[] roles, int index)
+ {
+ InnerList.CopyTo(roles, index);
+ }
+ }
+
+ public class AdamRoleCollection : ReadOnlyCollectionBase
+ {
+ internal AdamRoleCollection() { }
+
+ internal AdamRoleCollection(ArrayList values)
+ {
+ if (values != null)
+ {
+ InnerList.AddRange(values);
+ }
+ }
+
+ public AdamRole this[int index]
+ {
+ get
+ {
+ return (AdamRole)InnerList[index];
+ }
+ }
+
+ public bool Contains(AdamRole role)
+ {
+ if (role < AdamRole.SchemaRole || role > AdamRole.NamingRole)
+ {
+ throw new InvalidEnumArgumentException("role", (int)role, typeof(AdamRole));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ int tmp = (int)InnerList[i];
+ if (tmp == (int)role)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int IndexOf(AdamRole role)
+ {
+ if (role < AdamRole.SchemaRole || role > AdamRole.NamingRole)
+ {
+ throw new InvalidEnumArgumentException("role", (int)role, typeof(AdamRole));
+ }
+
+ for (int i = 0; i < InnerList.Count; i++)
+ {
+ int tmp = (int)InnerList[i];
+
+ if (tmp == (int)role)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ public void CopyTo(AdamRole[] roles, int index)
+ {
+ InnerList.CopyTo(roles, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SafeHandle.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SafeHandle.cs
new file mode 100644
index 0000000000..c342df108c
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SafeHandle.cs
@@ -0,0 +1,61 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using Microsoft.Win32.SafeHandles;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Security;
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal sealed class PolicySafeHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ internal PolicySafeHandle(IntPtr value) : base(true)
+ {
+ SetHandle(value);
+ }
+
+ override protected bool ReleaseHandle()
+ {
+ // STATUS_SUCCESS is 0
+ return UnsafeNativeMethods.LsaClose(handle) == 0;
+ }
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal sealed class LsaLogonProcessSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ private LsaLogonProcessSafeHandle() : base(true) { }
+
+ internal LsaLogonProcessSafeHandle(IntPtr value) : base(true)
+ {
+ SetHandle(value);
+ }
+
+ override protected bool ReleaseHandle()
+ {
+ // STATUS_SUCCESS is 0
+ return NativeMethods.LsaDeregisterLogonProcess(handle) == 0;
+ }
+ }
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal sealed class LoadLibrarySafeHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ private LoadLibrarySafeHandle() : base(true) { }
+
+ internal LoadLibrarySafeHandle(IntPtr value) : base(true)
+ {
+ SetHandle(value);
+ }
+
+ override protected bool ReleaseHandle()
+ {
+ return UnsafeNativeMethods.FreeLibrary(handle) != 0;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SecurityLevel.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SecurityLevel.cs
new file mode 100644
index 0000000000..8f272e2670
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SecurityLevel.cs
@@ -0,0 +1,15 @@
+// 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.ActiveDirectory
+{
+ using System;
+
+ public enum ReplicationSecurityLevel : int
+ {
+ MutualAuthentication = 2,
+ Negotiate = 1,
+ NegotiatePassThrough = 0
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SystemFlag.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SystemFlag.cs
new file mode 100644
index 0000000000..dbe8286e5a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/SystemFlag.cs
@@ -0,0 +1,14 @@
+// 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.ActiveDirectory
+{
+ using System;
+
+ internal enum SystemFlag : int
+ {
+ SystemFlagNtdsNC = 1,
+ SystemFlagNtdsDomain = 2
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TopLevelName.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TopLevelName.cs
new file mode 100644
index 0000000000..9fc52bb89c
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TopLevelName.cs
@@ -0,0 +1,60 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+ using System.ComponentModel;
+
+ public enum TopLevelNameStatus
+ {
+ Enabled = 0,
+ NewlyCreated = 1,
+ AdminDisabled = 2,
+ ConflictDisabled = 4
+ }
+
+ public class TopLevelName
+ {
+ private string _name = null;
+ private TopLevelNameStatus _status;
+ internal LARGE_INTEGER time;
+
+ internal TopLevelName(int flag, LSA_UNICODE_STRING val, LARGE_INTEGER time)
+ {
+ _status = (TopLevelNameStatus)flag;
+ _name = Marshal.PtrToStringUni(val.Buffer, val.Length / 2);
+ this.time = time;
+ }
+
+ public string Name
+ {
+ get
+ {
+ return _name;
+ }
+ }
+
+ public TopLevelNameStatus Status
+ {
+ get
+ {
+ return _status;
+ }
+ set
+ {
+ if (value != TopLevelNameStatus.Enabled &&
+ value != TopLevelNameStatus.NewlyCreated &&
+ value != TopLevelNameStatus.AdminDisabled &&
+ value != TopLevelNameStatus.ConflictDisabled)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(TopLevelNameStatus));
+
+ _status = value;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TopLevelNameCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TopLevelNameCollection.cs
new file mode 100644
index 0000000000..789b603741
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TopLevelNameCollection.cs
@@ -0,0 +1,53 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+
+ public class TopLevelNameCollection : ReadOnlyCollectionBase
+ {
+ internal TopLevelNameCollection() { }
+
+ public TopLevelName this[int index]
+ {
+ get
+ {
+ return (TopLevelName)InnerList[index];
+ }
+ }
+
+ public bool Contains(TopLevelName name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ return InnerList.Contains(name);
+ }
+
+ public int IndexOf(TopLevelName name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ return InnerList.IndexOf(name);
+ }
+
+ public void CopyTo(TopLevelName[] names, int index)
+ {
+ InnerList.CopyTo(names, index);
+ }
+
+ internal int Add(TopLevelName name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ return InnerList.Add(name);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustHelper.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustHelper.cs
new file mode 100644
index 0000000000..0570ee7232
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustHelper.cs
@@ -0,0 +1,1053 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Text;
+ using System.Security.Cryptography;
+
+ internal enum TRUSTED_INFORMATION_CLASS
+ {
+ TrustedDomainNameInformation = 1,
+ TrustedControllersInformation,
+ TrustedPosixOffsetInformation,
+ TrustedPasswordInformation,
+ TrustedDomainInformationBasic,
+ TrustedDomainInformationEx,
+ TrustedDomainAuthInformation,
+ TrustedDomainFullInformation,
+ TrustedDomainAuthInformationInternal,
+ TrustedDomainFullInformationInternal,
+ TrustedDomainInformationEx2Internal,
+ TrustedDomainFullInformation2Internal
+ }
+
+ [Flags]
+ internal enum TRUST_ATTRIBUTE
+ {
+ TRUST_ATTRIBUTE_NON_TRANSITIVE = 0x00000001,
+ TRUST_ATTRIBUTE_UPLEVEL_ONLY = 0x00000002,
+ TRUST_ATTRIBUTE_QUARANTINED_DOMAIN = 0x00000004,
+ TRUST_ATTRIBUTE_FOREST_TRANSITIVE = 0x00000008,
+ TRUST_ATTRIBUTE_CROSS_ORGANIZATION = 0x00000010,
+ TRUST_ATTRIBUTE_WITHIN_FOREST = 0x00000020,
+ TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL = 0x00000040
+ }
+
+ internal class TrustHelper
+ {
+ private static int s_STATUS_OBJECT_NAME_NOT_FOUND = 2;
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ internal static int ERROR_NOT_FOUND = 1168;
+#pragma warning restore 0414
+ internal static int NETLOGON_QUERY_LEVEL = 2;
+ internal static int NETLOGON_CONTROL_REDISCOVER = 5;
+ private static int s_NETLOGON_CONTROL_TC_VERIFY = 10;
+ private static int s_NETLOGON_VERIFY_STATUS_RETURNED = 0x80;
+ private static int s_PASSWORD_LENGTH = 15;
+ private static int s_TRUST_AUTH_TYPE_CLEAR = 2;
+ private static int s_policyDnsDomainInformation = 12;
+ private static int s_TRUSTED_SET_POSIX = 0x00000010;
+ private static int s_TRUSTED_SET_AUTH = 0x00000020;
+ internal static int TRUST_TYPE_DOWNLEVEL = 0x00000001;
+ internal static int TRUST_TYPE_UPLEVEL = 0x00000002;
+ internal static int TRUST_TYPE_MIT = 0x00000003;
+ private static int s_ERROR_ALREADY_EXISTS = 183;
+ private static int s_ERROR_INVALID_LEVEL = 124;
+ private static char[] s_punctuations = "!@#$%^&*()_-+=[{]};:>|./?".ToCharArray();
+
+ private TrustHelper() { }
+
+ internal static bool GetTrustedDomainInfoStatus(DirectoryContext context, string sourceName, string targetName, TRUST_ATTRIBUTE attribute, bool isForest)
+ {
+ PolicySafeHandle handle = null;
+ IntPtr buffer = (IntPtr)0;
+ LSA_UNICODE_STRING trustedDomainName = null;
+ bool impersonated = false;
+ IntPtr target = (IntPtr)0;
+ string serverName = null;
+
+ // get policy server name
+ serverName = Utils.GetPolicyServerName(context, isForest, false, sourceName);
+
+ impersonated = Utils.Impersonate(context);
+
+ try
+ {
+ try
+ {
+ // get the policy handle first
+ handle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+
+ // get the target name
+ trustedDomainName = new LSA_UNICODE_STRING();
+ target = Marshal.StringToHGlobalUni(targetName);
+ UnsafeNativeMethods.RtlInitUnicodeString(trustedDomainName, target);
+
+ int result = UnsafeNativeMethods.LsaQueryTrustedDomainInfoByName(handle, trustedDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainInformationEx, ref buffer);
+ if (result != 0)
+ {
+ int win32Error = UnsafeNativeMethods.LsaNtStatusToWinError(result);
+ // 2 ERROR_FILE_NOT_FOUND <--> 0xc0000034 STATUS_OBJECT_NAME_NOT_FOUND
+ if (win32Error == s_STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ if (isForest)
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestTrustDoesNotExist, sourceName, targetName), typeof(ForestTrustRelationshipInformation), null);
+ else
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DomainTrustDoesNotExist, sourceName, targetName), typeof(TrustRelationshipInformation), null);
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error, serverName);
+ }
+
+ Debug.Assert(buffer != (IntPtr)0);
+
+ TRUSTED_DOMAIN_INFORMATION_EX domainInfo = new TRUSTED_DOMAIN_INFORMATION_EX();
+ Marshal.PtrToStructure(buffer, domainInfo);
+
+ // validate this is the trust that the user refers to
+ ValidateTrustAttribute(domainInfo, isForest, sourceName, targetName);
+
+ // get the attribute of the trust
+
+ // selective authentication info
+ if (attribute == TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_CROSS_ORGANIZATION)
+ {
+ if ((domainInfo.TrustAttributes & TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_CROSS_ORGANIZATION) == 0)
+ return false;
+ else
+ return true;
+ }
+ // sid filtering behavior for forest trust
+ else if (attribute == TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL)
+ {
+ if ((domainInfo.TrustAttributes & TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL) == 0)
+ return true;
+ else
+ return false;
+ }
+ // sid filtering behavior for domain trust
+ else if (attribute == TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_QUARANTINED_DOMAIN)
+ {
+ if ((domainInfo.TrustAttributes & TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) == 0)
+ return false;
+ else
+ return true;
+ }
+ else
+ {
+ // should not happen
+ throw new ArgumentException("attribute");
+ }
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+
+ if (target != (IntPtr)0)
+ Marshal.FreeHGlobal(target);
+
+ if (buffer != (IntPtr)0)
+ UnsafeNativeMethods.LsaFreeMemory(buffer);
+ }
+ }
+ catch { throw; }
+ }
+
+ internal static void SetTrustedDomainInfoStatus(DirectoryContext context, string sourceName, string targetName, TRUST_ATTRIBUTE attribute, bool status, bool isForest)
+ {
+ PolicySafeHandle handle = null;
+ IntPtr buffer = (IntPtr)0;
+ IntPtr newInfo = (IntPtr)0;
+ LSA_UNICODE_STRING trustedDomainName = null;
+ bool impersonated = false;
+ IntPtr target = (IntPtr)0;
+ string serverName = null;
+
+ serverName = Utils.GetPolicyServerName(context, isForest, false, sourceName);
+
+ impersonated = Utils.Impersonate(context);
+
+ try
+ {
+ try
+ {
+ // get the policy handle first
+ handle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+
+ // get the target name
+ trustedDomainName = new LSA_UNICODE_STRING();
+ target = Marshal.StringToHGlobalUni(targetName);
+ UnsafeNativeMethods.RtlInitUnicodeString(trustedDomainName, target);
+
+ // get the trusted domain information
+ int result = UnsafeNativeMethods.LsaQueryTrustedDomainInfoByName(handle, trustedDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainInformationEx, ref buffer);
+ if (result != 0)
+ {
+ int win32Error = UnsafeNativeMethods.LsaNtStatusToWinError(result);
+ // 2 ERROR_FILE_NOT_FOUND <--> 0xc0000034 STATUS_OBJECT_NAME_NOT_FOUND
+ if (win32Error == s_STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ if (isForest)
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestTrustDoesNotExist, sourceName, targetName), typeof(ForestTrustRelationshipInformation), null);
+ else
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DomainTrustDoesNotExist, sourceName, targetName), typeof(TrustRelationshipInformation), null);
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error, serverName);
+ }
+ Debug.Assert(buffer != (IntPtr)0);
+
+ // get the managed structre representation
+ TRUSTED_DOMAIN_INFORMATION_EX domainInfo = new TRUSTED_DOMAIN_INFORMATION_EX();
+ Marshal.PtrToStructure(buffer, domainInfo);
+
+ // validate this is the trust that the user refers to
+ ValidateTrustAttribute(domainInfo, isForest, sourceName, targetName);
+
+ // change the attribute value properly
+
+ // selective authentication
+ if (attribute == TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_CROSS_ORGANIZATION)
+ {
+ if (status)
+ {
+ // turns on selective authentication
+ domainInfo.TrustAttributes |= TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_CROSS_ORGANIZATION;
+ }
+ else
+ {
+ // turns off selective authentication
+ domainInfo.TrustAttributes &= ~(TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_CROSS_ORGANIZATION);
+ }
+ }
+ // user wants to change sid filtering behavior for forest trust
+ else if (attribute == TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL)
+ {
+ if (status)
+ {
+ // user wants sid filtering behavior
+ domainInfo.TrustAttributes &= ~(TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL);
+ }
+ else
+ {
+ // users wants to turn off sid filtering behavior
+ domainInfo.TrustAttributes |= TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL;
+ }
+ }
+ // user wants to change sid filtering behavior for external trust
+ else if (attribute == TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_QUARANTINED_DOMAIN)
+ {
+ if (status)
+ {
+ // user wants sid filtering behavior
+ domainInfo.TrustAttributes |= TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_QUARANTINED_DOMAIN;
+ }
+ else
+ {
+ // user wants to turn off sid filtering behavior
+ domainInfo.TrustAttributes &= ~(TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_QUARANTINED_DOMAIN);
+ }
+ }
+ else
+ {
+ throw new ArgumentException("attribute");
+ }
+
+ // reconstruct the unmanaged structure to set it back
+ newInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TRUSTED_DOMAIN_INFORMATION_EX)));
+ Marshal.StructureToPtr(domainInfo, newInfo, false);
+
+ result = UnsafeNativeMethods.LsaSetTrustedDomainInfoByName(handle, trustedDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainInformationEx, newInfo);
+ if (result != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(UnsafeNativeMethods.LsaNtStatusToWinError(result), serverName);
+ }
+
+ return;
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+
+ if (target != (IntPtr)0)
+ Marshal.FreeHGlobal(target);
+
+ if (buffer != (IntPtr)0)
+ UnsafeNativeMethods.LsaFreeMemory(buffer);
+
+ if (newInfo != (IntPtr)0)
+ Marshal.FreeHGlobal(newInfo);
+ }
+ }
+ catch { throw; }
+ }
+
+ internal static void DeleteTrust(DirectoryContext sourceContext, string sourceName, string targetName, bool isForest)
+ {
+ PolicySafeHandle policyHandle = null;
+ LSA_UNICODE_STRING trustedDomainName = null;
+ int win32Error = 0;
+ bool impersonated = false;
+ IntPtr target = (IntPtr)0;
+ string serverName = null;
+ IntPtr buffer = (IntPtr)0;
+
+ serverName = Utils.GetPolicyServerName(sourceContext, isForest, false, sourceName);
+
+ impersonated = Utils.Impersonate(sourceContext);
+
+ try
+ {
+ try
+ {
+ // get the policy handle
+ policyHandle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+
+ // get the target name
+ trustedDomainName = new LSA_UNICODE_STRING();
+ target = Marshal.StringToHGlobalUni(targetName);
+ UnsafeNativeMethods.RtlInitUnicodeString(trustedDomainName, target);
+
+ // get trust information
+ int result = UnsafeNativeMethods.LsaQueryTrustedDomainInfoByName(policyHandle, trustedDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainInformationEx, ref buffer);
+ if (result != 0)
+ {
+ win32Error = UnsafeNativeMethods.LsaNtStatusToWinError(result);
+ // 2 ERROR_FILE_NOT_FOUND <--> 0xc0000034 STATUS_OBJECT_NAME_NOT_FOUND
+ if (win32Error == s_STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ if (isForest)
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestTrustDoesNotExist, sourceName, targetName), typeof(ForestTrustRelationshipInformation), null);
+ else
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DomainTrustDoesNotExist, sourceName, targetName), typeof(TrustRelationshipInformation), null);
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error, serverName);
+ }
+
+ Debug.Assert(buffer != (IntPtr)0);
+
+ try
+ {
+ TRUSTED_DOMAIN_INFORMATION_EX domainInfo = new TRUSTED_DOMAIN_INFORMATION_EX();
+ Marshal.PtrToStructure(buffer, domainInfo);
+
+ // validate this is the trust that the user refers to
+ ValidateTrustAttribute(domainInfo, isForest, sourceName, targetName);
+
+ // delete the trust
+ result = UnsafeNativeMethods.LsaDeleteTrustedDomain(policyHandle, domainInfo.Sid);
+ if (result != 0)
+ {
+ win32Error = UnsafeNativeMethods.LsaNtStatusToWinError(result);
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error, serverName);
+ }
+ }
+ finally
+ {
+ if (buffer != (IntPtr)0)
+ UnsafeNativeMethods.LsaFreeMemory(buffer);
+ }
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+
+ if (target != (IntPtr)0)
+ Marshal.FreeHGlobal(target);
+ }
+ }
+ catch { throw; }
+ }
+
+ internal static void VerifyTrust(DirectoryContext context, string sourceName, string targetName, bool isForest, TrustDirection direction, bool forceSecureChannelReset, string preferredTargetServer)
+ {
+ PolicySafeHandle policyHandle = null;
+ LSA_UNICODE_STRING trustedDomainName = null;
+ int win32Error = 0;
+ IntPtr data = (IntPtr)0;
+ IntPtr ptr = (IntPtr)0;
+ IntPtr buffer1 = (IntPtr)0;
+ IntPtr buffer2 = (IntPtr)0;
+ bool impersonated = true;
+ IntPtr target = (IntPtr)0;
+ string policyServerName = null;
+
+ policyServerName = Utils.GetPolicyServerName(context, isForest, false, sourceName);
+
+ impersonated = Utils.Impersonate(context);
+
+ try
+ {
+ try
+ {
+ // get the policy handle
+ policyHandle = new PolicySafeHandle(Utils.GetPolicyHandle(policyServerName));
+
+ // get the target name
+ trustedDomainName = new LSA_UNICODE_STRING();
+ target = Marshal.StringToHGlobalUni(targetName);
+ UnsafeNativeMethods.RtlInitUnicodeString(trustedDomainName, target);
+
+ // validate the trust existence
+ ValidateTrust(policyHandle, trustedDomainName, sourceName, targetName, isForest, (int)direction, policyServerName); // need to verify direction
+
+ if (preferredTargetServer == null)
+ data = Marshal.StringToHGlobalUni(targetName);
+ else
+ // this is the case that we need to specifically go to a particular server. This is the way to tell netlogon to do that.
+ data = Marshal.StringToHGlobalUni(targetName + "\\" + preferredTargetServer);
+ ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
+ Marshal.WriteIntPtr(ptr, data);
+
+ if (!forceSecureChannelReset)
+ {
+ win32Error = UnsafeNativeMethods.I_NetLogonControl2(policyServerName, s_NETLOGON_CONTROL_TC_VERIFY, NETLOGON_QUERY_LEVEL, ptr, out buffer1);
+
+ if (win32Error == 0)
+ {
+ NETLOGON_INFO_2 info = new NETLOGON_INFO_2();
+ Marshal.PtrToStructure(buffer1, info);
+
+ if ((info.netlog2_flags & s_NETLOGON_VERIFY_STATUS_RETURNED) != 0)
+ {
+ int result = info.netlog2_pdc_connection_status;
+ if (result == 0)
+ {
+ // verification succeeded
+ return;
+ }
+ else
+ {
+ // don't really know which server is down, the source or the target
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+ }
+ else
+ {
+ int result = info.netlog2_tc_connection_status;
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+ }
+ else
+ {
+ if (win32Error == s_ERROR_INVALID_LEVEL)
+ {
+ // it is pre-win2k SP3 dc that does not support NETLOGON_CONTROL_TC_VERIFY
+ throw new NotSupportedException(Res.GetString(Res.TrustVerificationNotSupport));
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error);
+ }
+ }
+ }
+ else
+ {
+ // then try secure channel reset
+ win32Error = UnsafeNativeMethods.I_NetLogonControl2(policyServerName, NETLOGON_CONTROL_REDISCOVER, NETLOGON_QUERY_LEVEL, ptr, out buffer2);
+ if (win32Error != 0)
+ // don't really know which server is down, the source or the target
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error);
+ }
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+
+ if (target != (IntPtr)0)
+ Marshal.FreeHGlobal(target);
+
+ if (ptr != (IntPtr)0)
+ Marshal.FreeHGlobal(ptr);
+
+ if (data != (IntPtr)0)
+ Marshal.FreeHGlobal(data);
+
+ if (buffer1 != (IntPtr)0)
+ UnsafeNativeMethods.NetApiBufferFree(buffer1);
+
+ if (buffer2 != (IntPtr)0)
+ UnsafeNativeMethods.NetApiBufferFree(buffer2);
+ }
+ }
+ catch { throw; }
+ }
+
+ internal static void CreateTrust(DirectoryContext sourceContext, string sourceName, DirectoryContext targetContext, string targetName, bool isForest, TrustDirection direction, string password)
+ {
+ LSA_AUTH_INFORMATION AuthData = null;
+ TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfoEx = null;
+ TRUSTED_DOMAIN_INFORMATION_EX tdi = null;
+ IntPtr fileTime = (IntPtr)0;
+ IntPtr unmanagedPassword = (IntPtr)0;
+ IntPtr info = (IntPtr)0;
+ IntPtr domainHandle = (IntPtr)0;
+ PolicySafeHandle policyHandle = null;
+ IntPtr unmanagedAuthData = (IntPtr)0;
+ bool impersonated = false;
+ string serverName = null;
+
+ // get the domain info first
+ info = GetTrustedDomainInfo(targetContext, targetName, isForest);
+
+ try
+ {
+ try
+ {
+ POLICY_DNS_DOMAIN_INFO domainInfo = new POLICY_DNS_DOMAIN_INFO();
+ Marshal.PtrToStructure(info, domainInfo);
+
+ AuthData = new LSA_AUTH_INFORMATION();
+ fileTime = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(FileTime)));
+ UnsafeNativeMethods.GetSystemTimeAsFileTime(fileTime);
+
+ // set the time
+ FileTime tmp = new FileTime();
+ Marshal.PtrToStructure(fileTime, tmp);
+ AuthData.LastUpdateTime = new LARGE_INTEGER();
+ AuthData.LastUpdateTime.lowPart = tmp.lower;
+ AuthData.LastUpdateTime.highPart = tmp.higher;
+
+ AuthData.AuthType = s_TRUST_AUTH_TYPE_CLEAR;
+ unmanagedPassword = Marshal.StringToHGlobalUni(password);
+ AuthData.AuthInfo = unmanagedPassword;
+ AuthData.AuthInfoLength = password.Length * 2; // sizeof(WCHAR)
+
+ unmanagedAuthData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_AUTH_INFORMATION)));
+ Marshal.StructureToPtr(AuthData, unmanagedAuthData, false);
+
+ AuthInfoEx = new TRUSTED_DOMAIN_AUTH_INFORMATION();
+ if ((direction & TrustDirection.Inbound) != 0)
+ {
+ AuthInfoEx.IncomingAuthInfos = 1;
+ AuthInfoEx.IncomingAuthenticationInformation = unmanagedAuthData;
+ AuthInfoEx.IncomingPreviousAuthenticationInformation = (IntPtr)0;
+ }
+
+ if ((direction & TrustDirection.Outbound) != 0)
+ {
+ AuthInfoEx.OutgoingAuthInfos = 1;
+ AuthInfoEx.OutgoingAuthenticationInformation = unmanagedAuthData;
+ AuthInfoEx.OutgoingPreviousAuthenticationInformation = (IntPtr)0;
+ }
+
+ tdi = new TRUSTED_DOMAIN_INFORMATION_EX();
+ tdi.FlatName = domainInfo.Name;
+ tdi.Name = domainInfo.DnsDomainName;
+ tdi.Sid = domainInfo.Sid;
+ tdi.TrustType = TRUST_TYPE_UPLEVEL;
+ tdi.TrustDirection = (int)direction;
+ if (isForest)
+ {
+ tdi.TrustAttributes = TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_FOREST_TRANSITIVE;
+ }
+ else
+ {
+ tdi.TrustAttributes = TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_QUARANTINED_DOMAIN;
+ }
+
+ // get server name
+ serverName = Utils.GetPolicyServerName(sourceContext, isForest, false, sourceName);
+
+ // do impersonation and get policy handle
+ impersonated = Utils.Impersonate(sourceContext);
+ policyHandle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+
+ int result = UnsafeNativeMethods.LsaCreateTrustedDomainEx(policyHandle, tdi, AuthInfoEx, s_TRUSTED_SET_POSIX | s_TRUSTED_SET_AUTH, out domainHandle);
+ if (result != 0)
+ {
+ result = UnsafeNativeMethods.LsaNtStatusToWinError(result);
+ if (result == s_ERROR_ALREADY_EXISTS)
+ {
+ if (isForest)
+ throw new ActiveDirectoryObjectExistsException(Res.GetString(Res.AlreadyExistingForestTrust, sourceName, targetName));
+ else
+ throw new ActiveDirectoryObjectExistsException(Res.GetString(Res.AlreadyExistingDomainTrust, sourceName, targetName));
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromErrorCode(result, serverName);
+ }
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+
+ if (fileTime != (IntPtr)0)
+ Marshal.FreeHGlobal(fileTime);
+
+ if (domainHandle != (IntPtr)0)
+ UnsafeNativeMethods.LsaClose(domainHandle);
+
+ if (info != (IntPtr)0)
+ UnsafeNativeMethods.LsaFreeMemory(info);
+
+ if (unmanagedPassword != (IntPtr)0)
+ Marshal.FreeHGlobal(unmanagedPassword);
+
+ if (unmanagedAuthData != (IntPtr)0)
+ Marshal.FreeHGlobal(unmanagedAuthData);
+ }
+ }
+ catch { throw; }
+ }
+
+ internal static string UpdateTrust(DirectoryContext context, string sourceName, string targetName, string password, bool isForest)
+ {
+ PolicySafeHandle handle = null;
+ IntPtr buffer = (IntPtr)0;
+ LSA_UNICODE_STRING trustedDomainName = null;
+ IntPtr newBuffer = (IntPtr)0;
+ bool impersonated = false;
+ LSA_AUTH_INFORMATION AuthData = null;
+ IntPtr fileTime = (IntPtr)0;
+ IntPtr unmanagedPassword = (IntPtr)0;
+ IntPtr unmanagedAuthData = (IntPtr)0;
+ TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfoEx = null;
+ TrustDirection direction;
+ IntPtr target = (IntPtr)0;
+ string serverName = null;
+
+ serverName = Utils.GetPolicyServerName(context, isForest, false, sourceName);
+
+ impersonated = Utils.Impersonate(context);
+
+ try
+ {
+ try
+ {
+ // get the policy handle first
+ handle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+
+ // get the target name
+ trustedDomainName = new LSA_UNICODE_STRING();
+ target = Marshal.StringToHGlobalUni(targetName);
+ UnsafeNativeMethods.RtlInitUnicodeString(trustedDomainName, target);
+
+ // get the trusted domain information
+ int result = UnsafeNativeMethods.LsaQueryTrustedDomainInfoByName(handle, trustedDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainFullInformation, ref buffer);
+ if (result != 0)
+ {
+ int win32Error = UnsafeNativeMethods.LsaNtStatusToWinError(result);
+ // 2 ERROR_FILE_NOT_FOUND <--> 0xc0000034 STATUS_OBJECT_NAME_NOT_FOUND
+ if (win32Error == s_STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ if (isForest)
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestTrustDoesNotExist, sourceName, targetName), typeof(ForestTrustRelationshipInformation), null);
+ else
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DomainTrustDoesNotExist, sourceName, targetName), typeof(TrustRelationshipInformation), null);
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error, serverName);
+ }
+
+ // get the managed structre representation
+ TRUSTED_DOMAIN_FULL_INFORMATION domainInfo = new TRUSTED_DOMAIN_FULL_INFORMATION();
+ Marshal.PtrToStructure(buffer, domainInfo);
+
+ // validate the trust attribute first
+ ValidateTrustAttribute(domainInfo.Information, isForest, sourceName, targetName);
+
+ // get trust direction
+ direction = (TrustDirection)domainInfo.Information.TrustDirection;
+
+ // change the attribute value properly
+ AuthData = new LSA_AUTH_INFORMATION();
+ fileTime = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(FileTime)));
+ UnsafeNativeMethods.GetSystemTimeAsFileTime(fileTime);
+
+ // set the time
+ FileTime tmp = new FileTime();
+ Marshal.PtrToStructure(fileTime, tmp);
+ AuthData.LastUpdateTime = new LARGE_INTEGER();
+ AuthData.LastUpdateTime.lowPart = tmp.lower;
+ AuthData.LastUpdateTime.highPart = tmp.higher;
+
+ AuthData.AuthType = s_TRUST_AUTH_TYPE_CLEAR;
+ unmanagedPassword = Marshal.StringToHGlobalUni(password);
+ AuthData.AuthInfo = unmanagedPassword;
+ AuthData.AuthInfoLength = password.Length * 2;
+
+ unmanagedAuthData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_AUTH_INFORMATION)));
+ Marshal.StructureToPtr(AuthData, unmanagedAuthData, false);
+
+ AuthInfoEx = new TRUSTED_DOMAIN_AUTH_INFORMATION();
+ if ((direction & TrustDirection.Inbound) != 0)
+ {
+ AuthInfoEx.IncomingAuthInfos = 1;
+ AuthInfoEx.IncomingAuthenticationInformation = unmanagedAuthData;
+ AuthInfoEx.IncomingPreviousAuthenticationInformation = (IntPtr)0;
+ }
+
+ if ((direction & TrustDirection.Outbound) != 0)
+ {
+ AuthInfoEx.OutgoingAuthInfos = 1;
+ AuthInfoEx.OutgoingAuthenticationInformation = unmanagedAuthData;
+ AuthInfoEx.OutgoingPreviousAuthenticationInformation = (IntPtr)0;
+ }
+
+ // reconstruct the unmanaged structure to set it back
+ domainInfo.AuthInformation = AuthInfoEx;
+ newBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TRUSTED_DOMAIN_FULL_INFORMATION)));
+ Marshal.StructureToPtr(domainInfo, newBuffer, false);
+
+ result = UnsafeNativeMethods.LsaSetTrustedDomainInfoByName(handle, trustedDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainFullInformation, newBuffer);
+ if (result != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(UnsafeNativeMethods.LsaNtStatusToWinError(result), serverName);
+ }
+
+ return serverName;
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+
+ if (target != (IntPtr)0)
+ Marshal.FreeHGlobal(target);
+
+ if (buffer != (IntPtr)0)
+ UnsafeNativeMethods.LsaFreeMemory(buffer);
+
+ if (newBuffer != (IntPtr)0)
+ Marshal.FreeHGlobal(newBuffer);
+
+ if (fileTime != (IntPtr)0)
+ Marshal.FreeHGlobal(fileTime);
+
+ if (unmanagedPassword != (IntPtr)0)
+ Marshal.FreeHGlobal(unmanagedPassword);
+
+ if (unmanagedAuthData != (IntPtr)0)
+ Marshal.FreeHGlobal(unmanagedAuthData);
+ }
+ }
+ catch { throw; }
+ }
+
+ internal static void UpdateTrustDirection(DirectoryContext context, string sourceName, string targetName, string password, bool isForest, TrustDirection newTrustDirection)
+ {
+ PolicySafeHandle handle = null;
+ IntPtr buffer = (IntPtr)0;
+ LSA_UNICODE_STRING trustedDomainName = null;
+ IntPtr newBuffer = (IntPtr)0;
+ bool impersonated = false;
+ LSA_AUTH_INFORMATION AuthData = null;
+ IntPtr fileTime = (IntPtr)0;
+ IntPtr unmanagedPassword = (IntPtr)0;
+ IntPtr unmanagedAuthData = (IntPtr)0;
+ TRUSTED_DOMAIN_AUTH_INFORMATION AuthInfoEx = null;
+ IntPtr target = (IntPtr)0;
+ string serverName = null;
+
+ serverName = Utils.GetPolicyServerName(context, isForest, false, sourceName);
+
+ impersonated = Utils.Impersonate(context);
+
+ try
+ {
+ try
+ {
+ // get the policy handle first
+ handle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+
+ // get the target name
+ trustedDomainName = new LSA_UNICODE_STRING();
+ target = Marshal.StringToHGlobalUni(targetName);
+ UnsafeNativeMethods.RtlInitUnicodeString(trustedDomainName, target);
+
+ // get the trusted domain information
+ int result = UnsafeNativeMethods.LsaQueryTrustedDomainInfoByName(handle, trustedDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainFullInformation, ref buffer);
+ if (result != 0)
+ {
+ int win32Error = UnsafeNativeMethods.LsaNtStatusToWinError(result);
+ // 2 ERROR_FILE_NOT_FOUND <--> 0xc0000034 STATUS_OBJECT_NAME_NOT_FOUND
+ if (win32Error == s_STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ if (isForest)
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestTrustDoesNotExist, sourceName, targetName), typeof(ForestTrustRelationshipInformation), null);
+ else
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DomainTrustDoesNotExist, sourceName, targetName), typeof(TrustRelationshipInformation), null);
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error, serverName);
+ }
+
+ // get the managed structre representation
+ TRUSTED_DOMAIN_FULL_INFORMATION domainInfo = new TRUSTED_DOMAIN_FULL_INFORMATION();
+ Marshal.PtrToStructure(buffer, domainInfo);
+
+ // validate the trust attribute first
+ ValidateTrustAttribute(domainInfo.Information, isForest, sourceName, targetName);
+
+ // change the attribute value properly
+ AuthData = new LSA_AUTH_INFORMATION();
+ fileTime = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(FileTime)));
+ UnsafeNativeMethods.GetSystemTimeAsFileTime(fileTime);
+
+ // set the time
+ FileTime tmp = new FileTime();
+ Marshal.PtrToStructure(fileTime, tmp);
+ AuthData.LastUpdateTime = new LARGE_INTEGER();
+ AuthData.LastUpdateTime.lowPart = tmp.lower;
+ AuthData.LastUpdateTime.highPart = tmp.higher;
+
+ AuthData.AuthType = s_TRUST_AUTH_TYPE_CLEAR;
+ unmanagedPassword = Marshal.StringToHGlobalUni(password);
+ AuthData.AuthInfo = unmanagedPassword;
+ AuthData.AuthInfoLength = password.Length * 2;
+
+ unmanagedAuthData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_AUTH_INFORMATION)));
+ Marshal.StructureToPtr(AuthData, unmanagedAuthData, false);
+
+ AuthInfoEx = new TRUSTED_DOMAIN_AUTH_INFORMATION();
+ if ((newTrustDirection & TrustDirection.Inbound) != 0)
+ {
+ AuthInfoEx.IncomingAuthInfos = 1;
+ AuthInfoEx.IncomingAuthenticationInformation = unmanagedAuthData;
+ AuthInfoEx.IncomingPreviousAuthenticationInformation = (IntPtr)0;
+ }
+ else
+ {
+ AuthInfoEx.IncomingAuthInfos = 0;
+ AuthInfoEx.IncomingAuthenticationInformation = (IntPtr)0;
+ AuthInfoEx.IncomingPreviousAuthenticationInformation = (IntPtr)0;
+ }
+
+ if ((newTrustDirection & TrustDirection.Outbound) != 0)
+ {
+ AuthInfoEx.OutgoingAuthInfos = 1;
+ AuthInfoEx.OutgoingAuthenticationInformation = unmanagedAuthData;
+ AuthInfoEx.OutgoingPreviousAuthenticationInformation = (IntPtr)0;
+ }
+ else
+ {
+ AuthInfoEx.OutgoingAuthInfos = 0;
+ AuthInfoEx.OutgoingAuthenticationInformation = (IntPtr)0;
+ AuthInfoEx.OutgoingPreviousAuthenticationInformation = (IntPtr)0;
+ }
+
+ // reconstruct the unmanaged structure to set it back
+ domainInfo.AuthInformation = AuthInfoEx;
+ // reset the trust direction
+ domainInfo.Information.TrustDirection = (int)newTrustDirection;
+
+ newBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TRUSTED_DOMAIN_FULL_INFORMATION)));
+ Marshal.StructureToPtr(domainInfo, newBuffer, false);
+
+ result = UnsafeNativeMethods.LsaSetTrustedDomainInfoByName(handle, trustedDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainFullInformation, newBuffer);
+ if (result != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(UnsafeNativeMethods.LsaNtStatusToWinError(result), serverName);
+ }
+
+ return;
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+
+ if (target != (IntPtr)0)
+ Marshal.FreeHGlobal(target);
+
+ if (buffer != (IntPtr)0)
+ UnsafeNativeMethods.LsaFreeMemory(buffer);
+
+ if (newBuffer != (IntPtr)0)
+ Marshal.FreeHGlobal(newBuffer);
+
+ if (fileTime != (IntPtr)0)
+ Marshal.FreeHGlobal(fileTime);
+
+ if (unmanagedPassword != (IntPtr)0)
+ Marshal.FreeHGlobal(unmanagedPassword);
+
+ if (unmanagedAuthData != (IntPtr)0)
+ Marshal.FreeHGlobal(unmanagedAuthData);
+ }
+ }
+ catch { throw; }
+ }
+
+ private static void ValidateTrust(PolicySafeHandle handle, LSA_UNICODE_STRING trustedDomainName, string sourceName, string targetName, bool isForest, int direction, string serverName)
+ {
+ IntPtr buffer = (IntPtr)0;
+
+ // get trust information
+ int result = UnsafeNativeMethods.LsaQueryTrustedDomainInfoByName(handle, trustedDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainInformationEx, ref buffer);
+ if (result != 0)
+ {
+ int win32Error = UnsafeNativeMethods.LsaNtStatusToWinError(result);
+ // 2 ERROR_FILE_NOT_FOUND <--> 0xc0000034 STATUS_OBJECT_NAME_NOT_FOUND
+ if (win32Error == s_STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ if (isForest)
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestTrustDoesNotExist, sourceName, targetName), typeof(ForestTrustRelationshipInformation), null);
+ else
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DomainTrustDoesNotExist, sourceName, targetName), typeof(TrustRelationshipInformation), null);
+ }
+ else
+ throw ExceptionHelper.GetExceptionFromErrorCode(win32Error, serverName);
+ }
+
+ Debug.Assert(buffer != (IntPtr)0);
+
+ try
+ {
+ TRUSTED_DOMAIN_INFORMATION_EX domainInfo = new TRUSTED_DOMAIN_INFORMATION_EX();
+ Marshal.PtrToStructure(buffer, domainInfo);
+
+ // validate this is the trust that the user refers to
+ ValidateTrustAttribute(domainInfo, isForest, sourceName, targetName);
+
+ // validate trust direction if applicable
+ if (direction != 0)
+ {
+ if ((direction & domainInfo.TrustDirection) == 0)
+ {
+ if (isForest)
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, sourceName, targetName, (TrustDirection)direction), typeof(ForestTrustRelationshipInformation), null);
+ else
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongTrustDirection, sourceName, targetName, (TrustDirection)direction), typeof(TrustRelationshipInformation), null);
+ }
+ }
+ }
+ finally
+ {
+ if (buffer != (IntPtr)0)
+ UnsafeNativeMethods.LsaFreeMemory(buffer);
+ }
+ }
+
+ private static void ValidateTrustAttribute(TRUSTED_DOMAIN_INFORMATION_EX domainInfo, bool isForest, string sourceName, string targetName)
+ {
+ if (isForest)
+ {
+ // it should be a forest trust, make sure that TRUST_ATTRIBUTE_FOREST_TRANSITIVE bit is set
+ if ((domainInfo.TrustAttributes & TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_FOREST_TRANSITIVE) == 0)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.ForestTrustDoesNotExist, sourceName, targetName), typeof(ForestTrustRelationshipInformation), null);
+ }
+ }
+ else
+ {
+ // it should not be a forest trust, make sure that TRUST_ATTRIBUTE_FOREST_TRANSITIVE bit is not set
+ if ((domainInfo.TrustAttributes & TRUST_ATTRIBUTE.TRUST_ATTRIBUTE_FOREST_TRANSITIVE) != 0)
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.WrongForestTrust, sourceName, targetName), typeof(TrustRelationshipInformation), null);
+ }
+
+ // we don't deal with NT4 trust also
+ if (domainInfo.TrustType == TRUST_TYPE_DOWNLEVEL)
+ throw new InvalidOperationException(Res.GetString(Res.NT4NotSupported));
+
+ // we don't perform any operation on kerberos trust also
+ if (domainInfo.TrustType == TRUST_TYPE_MIT)
+ throw new InvalidOperationException(Res.GetString(Res.KerberosNotSupported));
+ }
+ }
+
+ internal static string CreateTrustPassword()
+ {
+ string password;
+ byte[] buf;
+ char[] cBuf;
+
+ buf = new byte[s_PASSWORD_LENGTH];
+ cBuf = new char[s_PASSWORD_LENGTH];
+
+ (new RNGCryptoServiceProvider()).GetBytes(buf);
+ for (int iter = 0; iter < s_PASSWORD_LENGTH; iter++)
+ {
+ int i = (int)(buf[iter] % 87);
+ if (i < 10)
+ cBuf[iter] = (char)('0' + i);
+ else if (i < 36)
+ cBuf[iter] = (char)('A' + i - 10);
+ else if (i < 62)
+ cBuf[iter] = (char)('a' + i - 36);
+ else
+ cBuf[iter] = s_punctuations[i - 62];
+ }
+
+ password = new string(cBuf);
+
+ return password;
+ }
+
+ private static IntPtr GetTrustedDomainInfo(DirectoryContext targetContext, string targetName, bool isForest)
+ {
+ PolicySafeHandle policyHandle = null;
+ IntPtr buffer = (IntPtr)0;
+ bool impersonated = false;
+ string serverName = null;
+
+ try
+ {
+ try
+ {
+ serverName = Utils.GetPolicyServerName(targetContext, isForest, false, targetName);
+ impersonated = Utils.Impersonate(targetContext);
+ try
+ {
+ policyHandle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+ }
+ catch (ActiveDirectoryOperationException)
+ {
+ if (impersonated)
+ {
+ Utils.Revert();
+ impersonated = false;
+ }
+ // try anonymous
+ Utils.ImpersonateAnonymous();
+ impersonated = true;
+ policyHandle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+ }
+ catch (UnauthorizedAccessException)
+ {
+ if (impersonated)
+ {
+ Utils.Revert();
+ impersonated = false;
+ }
+ // try anonymous
+ Utils.ImpersonateAnonymous();
+ impersonated = true;
+ policyHandle = new PolicySafeHandle(Utils.GetPolicyHandle(serverName));
+ }
+
+ int result = UnsafeNativeMethods.LsaQueryInformationPolicy(policyHandle, s_policyDnsDomainInformation, out buffer);
+ if (result != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(UnsafeNativeMethods.LsaNtStatusToWinError(result), serverName);
+ }
+
+ return buffer;
+ }
+ finally
+ {
+ if (impersonated)
+ Utils.Revert();
+ }
+ }
+ catch { throw; }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustRelationshipInformation.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustRelationshipInformation.cs
new file mode 100644
index 0000000000..5ed2de9138
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustRelationshipInformation.cs
@@ -0,0 +1,93 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+ using System.Net;
+
+ public enum TrustType
+ {
+ TreeRoot = 0,
+ ParentChild = 1,
+ CrossLink = 2,
+ External = 3,
+ Forest = 4,
+ Kerberos = 5,
+ Unknown = 6
+ }
+
+ public enum TrustDirection
+ {
+ Inbound = 1,
+ Outbound = 2,
+ Bidirectional = Outbound | Inbound
+ }
+
+ public class TrustRelationshipInformation
+ {
+ internal string source = null;
+ internal string target = null;
+ internal TrustType type;
+ internal TrustDirection direction;
+ internal DirectoryContext context = null;
+
+ internal TrustRelationshipInformation() { }
+
+ internal TrustRelationshipInformation(DirectoryContext context, string source, TrustObject obj)
+ {
+ // security context
+ this.context = context;
+ // source
+ this.source = source;
+ // target
+ this.target = (obj.DnsDomainName == null ? obj.NetbiosDomainName : obj.DnsDomainName);
+ // direction
+ if ((obj.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_OUTBOUND) != 0 &&
+ (obj.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_INBOUND) != 0)
+ direction = TrustDirection.Bidirectional;
+ else if ((obj.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_OUTBOUND) != 0)
+ direction = TrustDirection.Outbound;
+ else if ((obj.Flags & (int)DS_DOMAINTRUST_FLAG.DS_DOMAIN_DIRECT_INBOUND) != 0)
+ direction = TrustDirection.Inbound;
+ // type
+ this.type = obj.TrustType;
+ }
+
+ public string SourceName
+ {
+ get
+ {
+ return this.source;
+ }
+ }
+
+ public string TargetName
+ {
+ get
+ {
+ return target;
+ }
+ }
+
+ public TrustType TrustType
+ {
+ get
+ {
+ return type;
+ }
+ }
+
+ public TrustDirection TrustDirection
+ {
+ get
+ {
+ return direction;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustRelationshipInformationCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustRelationshipInformationCollection.cs
new file mode 100644
index 0000000000..83f03a2e12
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/TrustRelationshipInformationCollection.cs
@@ -0,0 +1,66 @@
+// 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.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Globalization;
+
+ public class TrustRelationshipInformationCollection : ReadOnlyCollectionBase
+ {
+ internal TrustRelationshipInformationCollection() { }
+
+ internal TrustRelationshipInformationCollection(DirectoryContext context, string source, ArrayList trusts)
+ {
+ for (int i = 0; i < trusts.Count; i++)
+ {
+ TrustObject obj = (TrustObject)trusts[i];
+ // we don't need self and forest trust
+ if ((obj.TrustType == TrustType.Forest) || ((int)obj.TrustType == 7))
+ {
+ continue;
+ }
+
+ TrustRelationshipInformation info = new TrustRelationshipInformation(context, source, obj);
+ Add(info);
+ }
+ }
+
+ public TrustRelationshipInformation this[int index]
+ {
+ get
+ {
+ return (TrustRelationshipInformation)InnerList[index];
+ }
+ }
+
+ public bool Contains(TrustRelationshipInformation information)
+ {
+ if (information == null)
+ throw new ArgumentNullException("information");
+
+ return InnerList.Contains(information);
+ }
+
+ public int IndexOf(TrustRelationshipInformation information)
+ {
+ if (information == null)
+ throw new ArgumentNullException("information");
+
+ return InnerList.IndexOf(information);
+ }
+
+ public void CopyTo(TrustRelationshipInformation[] array, int index)
+ {
+ InnerList.CopyTo(array, index);
+ }
+
+ internal int Add(TrustRelationshipInformation info)
+ {
+ return InnerList.Add(info);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/UnsafeNativeMethods.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/UnsafeNativeMethods.cs
new file mode 100644
index 0000000000..2115fac685
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/UnsafeNativeMethods.cs
@@ -0,0 +1,872 @@
+// 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.
+
+//
+//NOTE:
+//Structures containing collection of another structures are defined without
+//embedded structure which will ensure proper marshalling in case collection
+//count is zero and there is no embedded structure. Marshalling code read the
+//embedded structure appropriately for non-zero collection count.
+//
+//E.g.
+//Unmanaged structure DS_REPL_CURSORS_3 is defind as
+//typedef struct {
+// DWORD cNumCursors;
+// DWORD dwEnumerationContext;
+// DS_REPL_CURSOR_3 rgCursor[1];
+//} DS_REPL_CURSORS_3;
+//
+//Here it has been defined as (without embedded structure DS_REPL_CURSOR_3)
+//
+//internal sealed class DS_REPL_CURSORS_3
+//{
+// public int cNumCursors;
+// public int dwEnumerationContext;
+//}
+
+namespace System.DirectoryServices.ActiveDirectory
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Security;
+ using System.Text;
+
+ internal enum DS_REPL_INFO_TYPE
+ {
+ DS_REPL_INFO_NEIGHBORS = 0,
+ DS_REPL_INFO_CURSORS_FOR_NC = 1,
+ DS_REPL_INFO_METADATA_FOR_OBJ = 2,
+ DS_REPL_INFO_KCC_DSA_CONNECT_FAILURES = 3,
+ DS_REPL_INFO_KCC_DSA_LINK_FAILURES = 4,
+ DS_REPL_INFO_PENDING_OPS = 5,
+ DS_REPL_INFO_METADATA_FOR_ATTR_VALUE = 6,
+ DS_REPL_INFO_CURSORS_2_FOR_NC = 7,
+ DS_REPL_INFO_CURSORS_3_FOR_NC = 8,
+ DS_REPL_INFO_METADATA_2_FOR_OBJ = 9,
+ DS_REPL_INFO_METADATA_2_FOR_ATTR_VALUE = 10
+ }
+
+ public enum ReplicationOperationType
+ {
+ Sync = 0,
+ Add = 1,
+ Delete = 2,
+ Modify = 3,
+ UpdateReference = 4
+ }
+
+ internal enum DS_NAME_ERROR
+ {
+ DS_NAME_NO_ERROR = 0,
+ DS_NAME_ERROR_RESOLVING = 1,
+ DS_NAME_ERROR_NOT_FOUND = 2,
+ DS_NAME_ERROR_NOT_UNIQUE = 3,
+ DS_NAME_ERROR_NO_MAPPING = 4,
+ DS_NAME_ERROR_DOMAIN_ONLY = 5,
+ DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 6,
+ DS_NAME_ERROR_TRUST_REFERRAL = 7
+ }
+
+ [Flags]
+ internal enum DS_DOMAINTRUST_FLAG
+ {
+ DS_DOMAIN_IN_FOREST = 0x0001,
+ DS_DOMAIN_DIRECT_OUTBOUND = 0x0002,
+ DS_DOMAIN_TREE_ROOT = 0x0004,
+ DS_DOMAIN_PRIMARY = 0x0008,
+ DS_DOMAIN_NATIVE_MODE = 0x0010,
+ DS_DOMAIN_DIRECT_INBOUND = 0x0020
+ }
+
+ internal enum LSA_FOREST_TRUST_RECORD_TYPE
+ {
+ ForestTrustTopLevelName,
+ ForestTrustTopLevelNameEx,
+ ForestTrustDomainInfo,
+ ForestTrustRecordTypeLast
+ }
+
+ public enum ForestTrustCollisionType
+ {
+ TopLevelName,
+ Domain,
+ Other
+ }
+
+ [Flags]
+ public enum TopLevelNameCollisionOptions
+ {
+ None = 0,
+ NewlyCreated = 1,
+ DisabledByAdmin = 2,
+ DisabledByConflict = 4
+ }
+
+ [Flags]
+ public enum DomainCollisionOptions
+ {
+ None = 0,
+ SidDisabledByAdmin = 1,
+ SidDisabledByConflict = 2,
+ NetBiosNameDisabledByAdmin = 4,
+ NetBiosNameDisabledByConflict = 8
+ }
+
+ /*
+ typedef enum
+ {
+ DsRole_RoleStandaloneWorkstation,
+ DsRole_RoleMemberWorkstation,
+ DsRole_RoleStandaloneServer,
+ DsRole_RoleMemberServer,
+ DsRole_RoleBackupDomainController,
+ DsRole_RolePrimaryDomainController,
+ DsRole_WorkstationWithSharedAccountDomain,
+ DsRole_ServerWithSharedAccountDomain,
+ DsRole_MemberWorkstationWithSharedAccountDomain,
+ DsRole_MemberServerWithSharedAccountDomain
+ }DSROLE_MACHINE_ROLE;
+ */
+
+ internal enum DSROLE_MACHINE_ROLE
+ {
+ DsRole_RoleStandaloneWorkstation,
+ DsRole_RoleMemberWorkstation,
+ DsRole_RoleStandaloneServer,
+ DsRole_RoleMemberServer,
+ DsRole_RoleBackupDomainController,
+ DsRole_RolePrimaryDomainController,
+ DsRole_WorkstationWithSharedAccountDomain,
+ DsRole_ServerWithSharedAccountDomain,
+ DsRole_MemberWorkstationWithSharedAccountDomain,
+ DsRole_MemberServerWithSharedAccountDomain
+ }
+
+ /*
+ typedef enum
+ {
+ DsRolePrimaryDomainInfoBasic,
+ DsRoleUpgradeStatus,
+ DsRoleOperationState,
+ DsRolePrimaryDomainInfoBasicEx
+ }DSROLE_PRIMARY_DOMAIN_INFO_LEVEL;
+ */
+
+ internal enum DSROLE_PRIMARY_DOMAIN_INFO_LEVEL
+ {
+ DsRolePrimaryDomainInfoBasic = 1,
+ DsRoleUpgradeStatus = 2,
+ DsRoleOperationState = 3,
+ DsRolePrimaryDomainInfoBasicEx = 4
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class FileTime
+ {
+ public int lower;
+ public int higher;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class SystemTime
+ {
+ public ushort wYear;
+ public ushort wMonth;
+ public ushort wDayOfWeek;
+ public ushort wDay;
+ public ushort wHour;
+ public ushort wMinute;
+ public ushort wSecond;
+ public ushort wMilliseconds;
+ }
+
+ //Without embedded structure DS_REPL_CURSOR_3.
+ //See NOTE at the top of this file for more details
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_CURSORS_3
+ {
+ public int cNumCursors;
+ public int dwEnumerationContext;
+ }
+
+ //Without embedded structure DS_REPL_CURSOR.
+ //See NOTE at the top of this file for more details
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_CURSORS
+ {
+ public int cNumCursors;
+ public int reserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_CURSOR_3
+ {
+ public Guid uuidSourceDsaInvocationID;
+ public long usnAttributeFilter;
+ public long ftimeLastSyncSuccess;
+ public IntPtr pszSourceDsaDN;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_CURSOR
+ {
+ public Guid uuidSourceDsaInvocationID;
+ public long usnAttributeFilter;
+ }
+
+ //Without embedded structure DS_REPL_OP.
+ //See NOTE at the top of this file for more details
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_PENDING_OPS
+ {
+ public long ftimeCurrentOpStarted;
+ public int cNumPendingOps;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ internal sealed class DS_REPL_OP
+ {
+ public long ftimeEnqueued;
+ public int ulSerialNumber;
+ public int ulPriority;
+ public ReplicationOperationType OpType;
+ public int ulOptions;
+ public IntPtr pszNamingContext;
+ public IntPtr pszDsaDN;
+ public IntPtr pszDsaAddress;
+ public Guid uuidNamingContextObjGuid;
+ public Guid uuidDsaObjGuid;
+ }
+
+ //Without embedded structure DS_REPL_NEIGHBOR.
+ //See NOTE at the top of this file for more details
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_NEIGHBORS
+ {
+ public int cNumNeighbors;
+ public int dwReserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_NEIGHBOR
+ {
+ public IntPtr pszNamingContext;
+ public IntPtr pszSourceDsaDN;
+ public IntPtr pszSourceDsaAddress;
+ public IntPtr pszAsyncIntersiteTransportDN;
+ public int dwReplicaFlags;
+ public int dwReserved;
+ public Guid uuidNamingContextObjGuid;
+ public Guid uuidSourceDsaObjGuid;
+ public Guid uuidSourceDsaInvocationID;
+ public Guid uuidAsyncIntersiteTransportObjGuid;
+ public long usnLastObjChangeSynced;
+ public long usnAttributeFilter;
+ public long ftimeLastSyncSuccess;
+ public long ftimeLastSyncAttempt;
+ public int dwLastSyncResult;
+ public int cNumConsecutiveSyncFailures;
+ }
+
+ //Without embedded structure DS_REPL_KCC_DSA_FAILURE.
+ //See NOTE at the top of this file for more details
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_KCC_DSA_FAILURES
+ {
+ public int cNumEntries;
+ public int dwReserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ internal sealed class DS_REPL_KCC_DSA_FAILURE
+ {
+ public IntPtr pszDsaDN;
+ public Guid uuidDsaObjGuid;
+ public long ftimeFirstFailure;
+ public int cNumFailures;
+ public int dwLastResult;
+ }
+
+ //Without embedded structure DS_REPL_ATTR_META_DATA_2.
+ //See NOTE at the top of this file for more details
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_OBJ_META_DATA_2
+ {
+ public int cNumEntries;
+ public int dwReserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_ATTR_META_DATA_2
+ {
+ public IntPtr pszAttributeName;
+ public int dwVersion;
+ // using two int to replace long to prevent managed code packing it
+ public int ftimeLastOriginatingChange1;
+ public int ftimeLastOriginatingChange2;
+ public Guid uuidLastOriginatingDsaInvocationID;
+ public long usnOriginatingChange;
+ public long usnLocalChange;
+ public IntPtr pszLastOriginatingDsaDN;
+ }
+
+ //Without embedded structure DS_REPL_ATTR_META_DATA.
+ //See NOTE at the top of this file for more details
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_OBJ_META_DATA
+ {
+ public int cNumEntries;
+ public int dwReserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPL_ATTR_META_DATA
+ {
+ public IntPtr pszAttributeName;
+ public int dwVersion;
+ // using two int to replace long to prevent managed code packing it
+ public int ftimeLastOriginatingChange1;
+ public int ftimeLastOriginatingChange2;
+ public Guid uuidLastOriginatingDsaInvocationID;
+ public long usnOriginatingChange;
+ public long usnLocalChange;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPSYNCALL_UPDATE
+ {
+ public SyncFromAllServersEvent eventType;
+ public IntPtr pErrInfo;
+ public IntPtr pSync;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPSYNCALL_ERRINFO
+ {
+ public IntPtr pszSvrId;
+ public SyncFromAllServersErrorCategory error;
+ public int dwWin32Err;
+ public IntPtr pszSrcId;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_REPSYNCALL_SYNC
+ {
+ public IntPtr pszSrcId;
+ public IntPtr pszDstId;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_NAME_RESULT_ITEM
+ {
+ public DS_NAME_ERROR status;
+ public IntPtr pDomain;
+ public IntPtr pName;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_NAME_RESULT
+ {
+ public int cItems;
+ public IntPtr rItems;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class DS_DOMAIN_TRUSTS
+ {
+ public IntPtr NetbiosDomainName;
+ public IntPtr DnsDomainName;
+ public int Flags;
+ public int ParentIndex;
+ public int TrustType;
+ public int TrustAttributes;
+ public IntPtr DomainSid;
+ public Guid DomainGuid;
+ }
+
+ internal sealed class TrustObject
+ {
+ public string NetbiosDomainName;
+ public string DnsDomainName;
+ public int Flags;
+ public int ParentIndex;
+ public TrustType TrustType;
+ public int TrustAttributes;
+ public int OriginalIndex;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LSA_FOREST_TRUST_INFORMATION
+ {
+ public int RecordCount;
+ public IntPtr Entries;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal sealed class LSA_FOREST_TRUST_RECORD
+ {
+ [FieldOffset(0)]
+ public int Flags;
+ [FieldOffset(4)]
+ public LSA_FOREST_TRUST_RECORD_TYPE ForestTrustType;
+ [FieldOffset(8)]
+ public LARGE_INTEGER Time;
+ [FieldOffset(16)]
+ public LSA_UNICODE_STRING TopLevelName;
+ [FieldOffset(16)]
+ public LSA_FOREST_TRUST_BINARY_DATA Data;
+ [FieldOffset(16)]
+ public LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LARGE_INTEGER
+ {
+ public int lowPart;
+ public int highPart;
+
+ public LARGE_INTEGER()
+ {
+ lowPart = 0;
+ highPart = 0;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LSA_UNICODE_STRING
+ {
+ public short Length;
+ public short MaximumLength;
+ public IntPtr Buffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LSA_FOREST_TRUST_DOMAIN_INFO
+ {
+ public IntPtr sid;
+ public short DNSNameLength;
+ public short DNSNameMaximumLength;
+ public IntPtr DNSNameBuffer;
+ public short NetBIOSNameLength;
+ public short NetBIOSNameMaximumLength;
+ public IntPtr NetBIOSNameBuffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LSA_FOREST_TRUST_BINARY_DATA
+ {
+ public int Length;
+ public IntPtr Buffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LSA_OBJECT_ATTRIBUTES
+ {
+ internal int Length;
+ private IntPtr _rootDirectory;
+ private IntPtr _objectName;
+ internal int Attributes;
+ private IntPtr _securityDescriptor;
+ private IntPtr _securityQualityOfService;
+
+ public LSA_OBJECT_ATTRIBUTES()
+ {
+ Length = 0;
+ _rootDirectory = (IntPtr)0;
+ _objectName = (IntPtr)0;
+ Attributes = 0;
+ _securityDescriptor = (IntPtr)0;
+ _securityQualityOfService = (IntPtr)0;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class TRUSTED_DOMAIN_INFORMATION_EX
+ {
+ public LSA_UNICODE_STRING Name;
+ public LSA_UNICODE_STRING FlatName;
+ public IntPtr Sid;
+ public int TrustDirection;
+ public int TrustType;
+ public TRUST_ATTRIBUTE TrustAttributes;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LSA_FOREST_TRUST_COLLISION_INFORMATION
+ {
+ public int RecordCount;
+ public IntPtr Entries;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LSA_FOREST_TRUST_COLLISION_RECORD
+ {
+ public int Index;
+ public ForestTrustCollisionType Type;
+ public int Flags;
+ public LSA_UNICODE_STRING Name;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class NETLOGON_INFO_2
+ {
+ public int netlog2_flags;
+
+ //
+ // If NETLOGON_VERIFY_STATUS_RETURNED bit is set in
+ // netlog2_flags, the following field will return
+ // the status of trust verification. Otherwise,
+ // the field will return the status of the secure
+ // channel to the primary domain of the machine
+ // (useful for BDCs only).
+ //
+ public int netlog2_pdc_connection_status;
+ public IntPtr netlog2_trusted_dc_name;
+ public int netlog2_tc_connection_status;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class TRUSTED_DOMAIN_AUTH_INFORMATION
+ {
+ public int IncomingAuthInfos;
+ public IntPtr IncomingAuthenticationInformation;
+ public IntPtr IncomingPreviousAuthenticationInformation;
+ public int OutgoingAuthInfos;
+ public IntPtr OutgoingAuthenticationInformation;
+ public IntPtr OutgoingPreviousAuthenticationInformation;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class LSA_AUTH_INFORMATION
+ {
+ public LARGE_INTEGER LastUpdateTime;
+ public int AuthType;
+ public int AuthInfoLength;
+ public IntPtr AuthInfo;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class POLICY_DNS_DOMAIN_INFO
+ {
+ public LSA_UNICODE_STRING Name;
+ public LSA_UNICODE_STRING DnsDomainName;
+ public LSA_UNICODE_STRING DnsForestName;
+ public Guid DomainGuid;
+ public IntPtr Sid;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class TRUSTED_POSIX_OFFSET_INFO
+ {
+ internal int Offset;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal sealed class TRUSTED_DOMAIN_FULL_INFORMATION
+ {
+ public TRUSTED_DOMAIN_INFORMATION_EX Information;
+ internal TRUSTED_POSIX_OFFSET_INFO PosixOffset;
+ public TRUSTED_DOMAIN_AUTH_INFORMATION AuthInformation;
+ }
+
+ /*
+ typedef struct _DSROLE_PRIMARY_DOMAIN_INFO_BASIC {
+ DSROLE_MACHINE_ROLE MachineRole;
+ ULONG Flags;
+ LPWSTR DomainNameFlat;
+ LPWSTR DomainNameDns;
+ LPWSTR DomainForestName;
+ GUID DomainGuid;
+ } DSROLE_PRIMARY_DOMAIN_INFO_BASIC, *PDSROLE_PRIMARY_DOMAIN_INFO_BASIC;
+ */
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class DSROLE_PRIMARY_DOMAIN_INFO_BASIC
+ {
+ public DSROLE_MACHINE_ROLE MachineRole;
+ public uint Flags;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string DomainNameFlat;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string DomainNameDns;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string DomainForestName;
+ public Guid DomainGuid = new Guid();
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class SID_AND_ATTR
+ {
+ public IntPtr pSid = IntPtr.Zero;
+ public int attrs = 0;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class TOKEN_USER
+ {
+ public SID_AND_ATTR sidAndAttributes = new SID_AND_ATTR();
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class SID_IDENTIFIER_AUTHORITY
+ {
+ public byte b1 = 0;
+ public byte b2 = 0;
+ public byte b3 = 0;
+ public byte b4 = 0;
+ public byte b5 = 0;
+ public byte b6 = 0;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal sealed class POLICY_ACCOUNT_DOMAIN_INFO
+ {
+ public LSA_UNICODE_STRING domainName = new LSA_UNICODE_STRING();
+ public IntPtr domainSid = IntPtr.Zero;
+ }
+
+ [
+ SuppressUnmanagedCodeSecurityAttribute()
+ ]
+ internal class UnsafeNativeMethods
+ {
+ public const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100,
+ FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200,
+ FORMAT_MESSAGE_FROM_STRING = 0x00000400,
+ FORMAT_MESSAGE_FROM_HMODULE = 0x00000800,
+ FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000,
+ FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000,
+ FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF;
+
+ [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ public static extern int FormatMessageW(int dwFlags, int lpSource, int dwMessageId,
+ int dwLanguageId, StringBuilder lpBuffer, int nSize, int arguments);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ public delegate int DsReplicaConsistencyCheck([In]IntPtr handle, int taskID, int flags);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ public delegate int DsReplicaGetInfo2W(IntPtr handle, int type, [MarshalAs(UnmanagedType.LPWStr)] string objectPath, IntPtr sourceGUID, string attributeName, string value, int flag, int context, ref IntPtr info);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ public delegate int DsReplicaGetInfoW(IntPtr handle, int type, [MarshalAs(UnmanagedType.LPWStr)] string objectPath, IntPtr sourceGUID, ref IntPtr info);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ public delegate int DsReplicaFreeInfo(int type, IntPtr value);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ public delegate int DsReplicaSyncW(IntPtr handle, [MarshalAs(UnmanagedType.LPWStr)] string partition, IntPtr uuid, int option);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ public delegate int DsReplicaSyncAllW(IntPtr handle, [MarshalAs(UnmanagedType.LPWStr)] string partition, int flags, SyncReplicaFromAllServersCallback callback, IntPtr data, ref IntPtr error);
+
+ [DllImport("kernel32.dll", EntryPoint = "LocalFree")]
+ public static extern int LocalFree(IntPtr mem);
+
+ [DllImport("activeds.dll", EntryPoint = "ADsEncodeBinaryData", CharSet = CharSet.Unicode)]
+ public static extern int ADsEncodeBinaryData(byte[] data, int length, ref IntPtr result);
+
+ [DllImport("activeds.dll", EntryPoint = "FreeADsMem")]
+ public static extern bool FreeADsMem(IntPtr pVoid);
+
+ [DllImport("netapi32.dll", EntryPoint = "DsGetSiteNameW", CharSet = CharSet.Unicode)]
+ public static extern int DsGetSiteName(string dcName, ref IntPtr ptr);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ public delegate int DsListDomainsInSiteW(IntPtr handle, [MarshalAs(UnmanagedType.LPWStr)] string site, ref IntPtr info);
+
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ public delegate void DsFreeNameResultW(IntPtr result);
+
+ [DllImport("Netapi32.dll", EntryPoint = "DsEnumerateDomainTrustsW", CharSet = CharSet.Unicode)]
+ public static extern int DsEnumerateDomainTrustsW(string serverName, int flags, out IntPtr domains, out int count);
+
+ [DllImport("Netapi32.dll", EntryPoint = "NetApiBufferFree")]
+ public static extern int NetApiBufferFree(IntPtr buffer);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LogonUserW", CharSet = CharSet.Unicode, SetLastError = true)]
+ public static extern int LogonUserW(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
+
+ [DllImport("Advapi32.dll", EntryPoint = "ImpersonateLoggedOnUser", SetLastError = true)]
+ public static extern int ImpersonateLoggedOnUser(IntPtr hToken);
+
+ [DllImport("Advapi32.dll", EntryPoint = "RevertToSelf", SetLastError = true)]
+ public static extern int RevertToSelf();
+
+ [DllImport("Advapi32.dll", EntryPoint = "ConvertSidToStringSidW", CharSet = CharSet.Unicode, SetLastError = true)]
+ public static extern int ConvertSidToStringSidW(IntPtr pSid, ref IntPtr stringSid);
+
+ [DllImport("Advapi32.dll", EntryPoint = "ConvertStringSidToSidW", CharSet = CharSet.Unicode, SetLastError = true)]
+ public static extern int ConvertStringSidToSidW(IntPtr stringSid, ref IntPtr pSid);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaSetForestTrustInformation")]
+ public static extern int LsaSetForestTrustInformation(PolicySafeHandle handle, LSA_UNICODE_STRING target, IntPtr forestTrustInfo, int checkOnly, out IntPtr collisionInfo);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaOpenPolicy")]
+ public static extern int LsaOpenPolicy(LSA_UNICODE_STRING target, LSA_OBJECT_ATTRIBUTES objectAttributes, int access, out IntPtr handle);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaClose")]
+ public static extern int LsaClose(IntPtr handle);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaQueryForestTrustInformation")]
+ public static extern int LsaQueryForestTrustInformation(PolicySafeHandle handle, LSA_UNICODE_STRING target, ref IntPtr ForestTrustInfo);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaQueryTrustedDomainInfoByName")]
+ public static extern int LsaQueryTrustedDomainInfoByName(PolicySafeHandle handle, LSA_UNICODE_STRING trustedDomain, TRUSTED_INFORMATION_CLASS infoClass, ref IntPtr buffer);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaNtStatusToWinError")]
+ public static extern int LsaNtStatusToWinError(int status);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaFreeMemory")]
+ public static extern int LsaFreeMemory(IntPtr ptr);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaSetTrustedDomainInfoByName")]
+ public static extern int LsaSetTrustedDomainInfoByName(PolicySafeHandle handle, LSA_UNICODE_STRING trustedDomain, TRUSTED_INFORMATION_CLASS infoClass, IntPtr buffer);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaOpenTrustedDomainByName")]
+ public static extern int LsaOpenTrustedDomainByName(PolicySafeHandle policyHandle, LSA_UNICODE_STRING trustedDomain, int access, ref IntPtr trustedDomainHandle);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaDeleteTrustedDomain")]
+ public static extern int LsaDeleteTrustedDomain(PolicySafeHandle handle, IntPtr pSid);
+
+ [DllImport("netapi32.dll", EntryPoint = "I_NetLogonControl2", CharSet = CharSet.Unicode)]
+ public static extern int I_NetLogonControl2(string serverName, int FunctionCode, int QueryLevel, IntPtr data, out IntPtr buffer);
+
+ [DllImport("Kernel32.dll", EntryPoint = "GetSystemTimeAsFileTime")]
+ public static extern void GetSystemTimeAsFileTime(IntPtr fileTime);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaQueryInformationPolicy")]
+ public static extern int LsaQueryInformationPolicy(PolicySafeHandle handle, int infoClass, out IntPtr buffer);
+
+ [DllImport("Advapi32.dll", EntryPoint = "LsaCreateTrustedDomainEx")]
+ public static extern int LsaCreateTrustedDomainEx(PolicySafeHandle handle, TRUSTED_DOMAIN_INFORMATION_EX domainEx, TRUSTED_DOMAIN_AUTH_INFORMATION authInfo, int classInfo, out IntPtr domainHandle);
+
+ [DllImport("Kernel32.dll", EntryPoint = "OpenThread", SetLastError = true)]
+ public static extern IntPtr OpenThread(uint desiredAccess, bool inheirted, int threadID);
+
+ [DllImport("Kernel32.dll", EntryPoint = "GetCurrentThreadId")]
+ public static extern int GetCurrentThreadId();
+
+ [DllImport("Advapi32.dll", EntryPoint = "ImpersonateAnonymousToken", SetLastError = true)]
+ public static extern int ImpersonateAnonymousToken(IntPtr token);
+
+ [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")]
+ public static extern int CloseHandle(IntPtr handle);
+
+ [DllImport("ntdll.dll", EntryPoint = "RtlInitUnicodeString")]
+ public static extern int RtlInitUnicodeString(LSA_UNICODE_STRING result, IntPtr s);
+
+ [DllImport("Kernel32.dll", EntryPoint = "LoadLibraryW", CharSet = CharSet.Unicode, SetLastError = true)]
+ public static extern IntPtr LoadLibrary(string name);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
+ public extern static uint FreeLibrary(IntPtr libName);
+
+ [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", SetLastError = true, BestFitMapping = false)]
+ public extern static IntPtr GetProcAddress(LoadLibrarySafeHandle hModule, string entryPoint);
+
+ /*
+ DWORD DsRoleGetPrimaryDomainInformation(
+ LPCWSTR lpServer,
+ DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
+ PBYTE* Buffer
+ ); */
+
+ [DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsRoleGetPrimaryDomainInformation", CharSet = CharSet.Unicode)]
+ public static extern int DsRoleGetPrimaryDomainInformation(
+ [MarshalAs(UnmanagedType.LPTStr)] string lpServer,
+ [In] DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
+ out IntPtr Buffer);
+
+ [DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsRoleGetPrimaryDomainInformation", CharSet = CharSet.Unicode)]
+ public static extern int DsRoleGetPrimaryDomainInformation(
+ [In] IntPtr lpServer,
+ [In] DSROLE_PRIMARY_DOMAIN_INFO_LEVEL InfoLevel,
+ out IntPtr Buffer);
+
+ [DllImport("advapi32.dll")]
+ public static extern int GetLengthSid(IntPtr sid);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ public static extern bool IsValidSid(IntPtr sid);
+
+ [DllImport("advapi32.dll")]
+ public static extern IntPtr GetSidIdentifierAuthority(IntPtr sid);
+
+ [DllImport("advapi32.dll")]
+ public static extern IntPtr GetSidSubAuthority(IntPtr sid, int index);
+
+ [DllImport("advapi32.dll")]
+ public static extern IntPtr GetSidSubAuthorityCount(IntPtr sid);
+
+ [DllImport("advapi32.dll")]
+ public static extern bool EqualDomainSid(IntPtr pSid1, IntPtr pSid2, ref bool equal);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ public static extern bool CopySid(int destinationLength, IntPtr pSidDestination, IntPtr pSidSource);
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "OpenThreadToken", CharSet = CharSet.Unicode)]
+ static extern public bool OpenThreadToken(
+ IntPtr threadHandle,
+ int desiredAccess,
+ bool openAsSelf,
+ ref IntPtr tokenHandle
+ );
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "OpenProcessToken", CharSet = CharSet.Unicode)]
+ static extern public bool OpenProcessToken(
+ IntPtr processHandle,
+ int desiredAccess,
+ ref IntPtr tokenHandle
+ );
+
+ [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCurrentThread", CharSet = CharSet.Unicode)]
+ static extern public IntPtr GetCurrentThread();
+
+ [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GetCurrentProcess", CharSet = CharSet.Unicode)]
+ static extern public IntPtr GetCurrentProcess();
+
+ [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "GetTokenInformation", CharSet = CharSet.Unicode)]
+ static extern public bool GetTokenInformation(
+ IntPtr tokenHandle,
+ int tokenInformationClass,
+ IntPtr buffer,
+ int bufferSize,
+ ref int returnLength
+ );
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaOpenPolicy", CharSet = CharSet.Unicode)]
+ static extern public int LsaOpenPolicy(
+ IntPtr lsaUnicodeString,
+ IntPtr lsaObjectAttributes,
+ int desiredAccess,
+ ref IntPtr policyHandle);
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaQueryInformationPolicy", CharSet = CharSet.Unicode)]
+ static extern public int LsaQueryInformationPolicy(
+ IntPtr policyHandle,
+ int policyInformationClass,
+ ref IntPtr buffer
+ );
+
+ [DllImport("advapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "LsaLookupSids", CharSet = CharSet.Unicode)]
+ public static extern int LsaLookupSids(
+ IntPtr policyHandle,
+ int count,
+ IntPtr[] sids,
+ out IntPtr referencedDomains,
+ out IntPtr names
+ );
+
+ /*
+ void DsRoleFreeMemory(
+ PVOID Buffer
+ );
+ */
+ [DllImport("Netapi32.dll")]
+ public static extern int DsRoleFreeMemory(
+ [In] IntPtr buffer);
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs
new file mode 100644
index 0000000000..0ac85d732a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs
@@ -0,0 +1,2453 @@
+// 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.Text;
+using System.Net;
+using System.Collections;
+using System.Security.Principal;
+using System.Security.Permissions;
+using System.DirectoryServices;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using System.Globalization;
+
+#pragma warning disable 618
+[assembly: FileIOPermission(SecurityAction.RequestMinimum, AllFiles = FileIOPermissionAccess.PathDiscovery),
+SecurityPermission(SecurityAction.RequestMinimum, UnmanagedCode = true),
+SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true),
+EnvironmentPermission(SecurityAction.RequestMinimum, Unrestricted = true),
+DnsPermission(SecurityAction.RequestMinimum, Unrestricted = true)
+]
+
+#pragma warning restore 618
+
+namespace System.DirectoryServices.ActiveDirectory
+{
+ internal struct Component
+ {
+ public string Name;
+ public string Value;
+ }
+
+ internal enum Capability : int
+ {
+ ActiveDirectory = 0,
+ ActiveDirectoryApplicationMode = 1,
+ ActiveDirectoryOrADAM = 2
+ }
+
+ internal enum SidType
+ {
+ RealObject = 0, // Account SID (S-1-5-21-....)
+ RealObjectFakeDomain = 1, // BUILTIN SID (S-1-5-32-....)
+ FakeObject = 2 // everything else: S-1-1-0 (\Everyone), S-1-2-0 (\LOCAL),
+ // S-1-5-X for X != 21 and X != 32 (NT AUTHORITY), etc.
+ }
+
+ internal struct SupportedCapability
+ {
+ public static string ADOid = "1.2.840.113556.1.4.800";
+ public static string ADAMOid = "1.2.840.113556.1.4.1851";
+ }
+
+ internal sealed class Utils
+ {
+ private static int s_LOGON32_LOGON_NEW_CREDENTIALS = 9;
+ private static int s_LOGON32_PROVIDER_WINNT50 = 3;
+ private static int s_POLICY_VIEW_LOCAL_INFORMATION = 0x00000001;
+ private static uint s_STANDARD_RIGHTS_REQUIRED = 0x000F0000;
+ private static uint s_SYNCHRONIZE = 0x00100000;
+ private static uint s_THREAD_ALL_ACCESS = s_STANDARD_RIGHTS_REQUIRED | s_SYNCHRONIZE | 0x3FF;
+ internal static AuthenticationTypes DefaultAuthType = AuthenticationTypes.Secure | AuthenticationTypes.Signing | AuthenticationTypes.Sealing;
+
+ /*
+
+ #define LANG_ENGLISH 0x09
+ #define SUBLANG_ENGLISH_US 0x01 // English (USA)
+ #define SORT_DEFAULT 0x0 // sorting default
+
+ #define NORM_IGNORECASE 0x00000001 // ignore case
+ #define NORM_IGNORENONSPACE 0x00000002 // ignore nonspacing chars
+ #define NORM_IGNORESYMBOLS 0x00000004 // ignore symbols
+ #define NORM_IGNOREKANATYPE 0x00010000 // ignore kanatype
+ #define NORM_IGNOREWIDTH 0x00020000 // ignore width
+
+ #define SORT_STRINGSORT 0x00001000 // use string sort method
+
+ #define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p))
+
+ #define MAKELCID(lgid, srtid) ((DWORD)((((DWORD)((WORD )(srtid))) << 16) | \
+ ((DWORD)((WORD )(lgid)))))
+
+ #define DS_DEFAULT_LOCALE \
+ (MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), \
+ SORT_DEFAULT))
+
+ #define DS_DEFAULT_LOCALE_COMPARE_FLAGS (NORM_IGNORECASE | \
+ NORM_IGNOREKANATYPE | \
+ NORM_IGNORENONSPACE | \
+ NORM_IGNOREWIDTH | \
+ SORT_STRINGSORT )
+
+ */
+ private static uint s_LANG_ENGLISH = 0x09;
+ private static uint s_SUBLANG_ENGLISH_US = 0x01;
+ private static uint s_SORT_DEFAULT = 0x0;
+ private static uint s_LANGID = ((uint)((((ushort)(s_SUBLANG_ENGLISH_US)) << 10) | (ushort)(s_LANG_ENGLISH)));
+ private static uint s_LCID = ((uint)((((uint)((ushort)(s_SORT_DEFAULT))) << 16) | ((uint)((ushort)(s_LANGID)))));
+
+ internal static uint NORM_IGNORECASE = 0x00000001;
+ internal static uint NORM_IGNORENONSPACE = 0x00000002;
+ internal static uint NORM_IGNOREKANATYPE = 0x00010000;
+ internal static uint NORM_IGNOREWIDTH = 0x00020000;
+ internal static uint SORT_STRINGSORT = 0x00001000;
+ internal static uint DEFAULT_CMP_FLAGS = NORM_IGNORECASE |
+ NORM_IGNOREKANATYPE |
+ NORM_IGNORENONSPACE |
+ NORM_IGNOREWIDTH |
+ SORT_STRINGSORT;
+
+ // To disable public/protected constructors for this class
+ private Utils() { }
+
+ internal static string GetDnsNameFromDN(string distinguishedName)
+ {
+ int result = 0;
+ string dnsName = null;
+ IntPtr results = IntPtr.Zero;
+
+ Debug.Assert(distinguishedName != null);
+
+ // call DsCrackNamesW
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsCrackNamesW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsCrackNames dsCrackNames = (NativeMethods.DsCrackNames)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsCrackNames));
+
+ IntPtr name = Marshal.StringToHGlobalUni(distinguishedName);
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
+ Marshal.WriteIntPtr(ptr, name);
+ result = dsCrackNames(IntPtr.Zero, NativeMethods.DS_NAME_FLAG_SYNTACTICAL_ONLY,
+ NativeMethods.DS_FQDN_1779_NAME, NativeMethods.DS_CANONICAL_NAME, 1, ptr, out results);
+ if (result == 0)
+ {
+ try
+ {
+ DsNameResult dsNameResult = new DsNameResult();
+ Marshal.PtrToStructure(results, dsNameResult);
+ if ((dsNameResult.itemCount >= 1) && (dsNameResult.items != IntPtr.Zero))
+ {
+ DsNameResultItem dsNameResultItem = new DsNameResultItem();
+ Marshal.PtrToStructure(dsNameResult.items, dsNameResultItem);
+
+ if (dsNameResultItem.status == NativeMethods.DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING ||
+ dsNameResultItem.name == null)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat), "distinguishedName");
+ }
+ else if (dsNameResultItem.status != 0)
+ {
+ // it is only syntatic mapping, we don't go on the wire
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+
+ if ((dsNameResultItem.name.Length - 1) == dsNameResultItem.name.IndexOf('/'))
+ {
+ dnsName = dsNameResultItem.name.Substring(0, dsNameResultItem.name.Length - 1);
+ }
+ else
+ {
+ dnsName = dsNameResultItem.name;
+ }
+ }
+ }
+ finally
+ {
+ if (ptr != (IntPtr)0)
+ Marshal.FreeHGlobal(ptr);
+
+ if (name != (IntPtr)0)
+ Marshal.FreeHGlobal(name);
+
+ // free the results
+ if (results != IntPtr.Zero)
+ {
+ // call DsFreeNameResultW
+ functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsFreeNameResultW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsFreeNameResultW dsFreeNameResultW = (UnsafeNativeMethods.DsFreeNameResultW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsFreeNameResultW));
+ dsFreeNameResultW(results);
+ }
+ }
+ }
+ else if (result == NativeMethods.DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat), "distinguishedName");
+ }
+ else
+ {
+ // it is only syntatic mapping, we don't go on the wire
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+
+ return dnsName;
+ }
+
+ internal static string GetDNFromDnsName(string dnsName)
+ {
+ int result = 0;
+ string dn = null;
+ IntPtr results = IntPtr.Zero;
+
+ Debug.Assert(dnsName != null);
+
+ // call DsCrackNamesW
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsCrackNamesW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsCrackNames dsCrackNames = (NativeMethods.DsCrackNames)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsCrackNames));
+ IntPtr name = Marshal.StringToHGlobalUni(dnsName + "/");
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
+ Marshal.WriteIntPtr(ptr, name);
+ result = dsCrackNames(IntPtr.Zero, NativeMethods.DS_NAME_FLAG_SYNTACTICAL_ONLY,
+ NativeMethods.DS_CANONICAL_NAME, NativeMethods.DS_FQDN_1779_NAME, 1, ptr, out results);
+ if (result == 0)
+ {
+ try
+ {
+ DsNameResult dsNameResult = new DsNameResult();
+ Marshal.PtrToStructure(results, dsNameResult);
+
+ if ((dsNameResult.itemCount >= 1) && (dsNameResult.items != IntPtr.Zero))
+ {
+ DsNameResultItem dsNameResultItem = new DsNameResultItem();
+ Marshal.PtrToStructure(dsNameResult.items, dsNameResultItem);
+ dn = dsNameResultItem.name;
+ }
+ }
+ finally
+ {
+ if (ptr != (IntPtr)0)
+ Marshal.FreeHGlobal(ptr);
+
+ if (name != (IntPtr)0)
+ Marshal.FreeHGlobal(name);
+ // free the results
+ if (results != IntPtr.Zero)
+ {
+ // call DsFreeNameResultW
+ functionPtr = UnsafeNativeMethods.GetProcAddress(DirectoryContext.ADHandle, "DsFreeNameResultW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ UnsafeNativeMethods.DsFreeNameResultW dsFreeNameResultW = (UnsafeNativeMethods.DsFreeNameResultW)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(UnsafeNativeMethods.DsFreeNameResultW));
+ dsFreeNameResultW(results);
+ }
+ }
+ }
+ else if (result == NativeMethods.DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat));
+ }
+ else
+ {
+ // it is only syntatic mapping, we don't go on the wire
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+
+ return dn;
+ }
+
+ //
+ // DN is of the form cn=NTDS Settings, cn={dc name}, cn=Servers, cn={site name}, cn=Sites,
+ // cn=Configuration, {defaultNamingContext}
+ // Bind to the NTDS-DSA (parent) object for and get the dnsHostName
+ // from there
+ //
+ internal static string GetDnsHostNameFromNTDSA(DirectoryContext context, string dn)
+ {
+ string dcName = null;
+ int index = dn.IndexOf(',');
+ if (index == -1)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat), "dn");
+ }
+
+ // get parent name simply by removing the first component
+ string bindingDN = dn.Substring(index + 1);
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, bindingDN);
+ try
+ {
+ // the "dnsHostName" attribute contains the dns name of the computer
+ dcName = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.DnsHostName);
+ }
+ finally
+ {
+ de.Dispose();
+ }
+ return dcName;
+ }
+
+ internal static string GetAdamDnsHostNameFromNTDSA(DirectoryContext context, string dn)
+ {
+ string dnsHostName = null;
+ int ldapPort = -1;
+ string ntdsaDn = dn;
+ string serverDn = GetPartialDN(dn, 1);
+ string serversDn = GetPartialDN(dn, 2);
+ string ntdsdsa = "CN=NTDS-DSA";
+
+ DirectoryEntry serversEntry = DirectoryEntryManager.GetDirectoryEntry(context, serversDn);
+
+ string filter = "(|(&(" + PropertyManager.ObjectCategory + "=server)(" + PropertyManager.DistinguishedName + "=" + GetEscapedFilterValue(serverDn) + "))" +
+ "(&(" + PropertyManager.ObjectCategory + "=nTDSDSA)(" + PropertyManager.DistinguishedName + "=" + GetEscapedFilterValue(ntdsaDn) + ")))";
+ string[] propertiesToLoad = new string[3];
+ propertiesToLoad[0] = PropertyManager.DnsHostName;
+ propertiesToLoad[1] = PropertyManager.MsDSPortLDAP;
+ propertiesToLoad[2] = PropertyManager.ObjectCategory;
+
+ ADSearcher searcher = new ADSearcher(serversEntry, filter, propertiesToLoad, SearchScope.Subtree, true /* paged search */, true /* cache results */);
+ SearchResultCollection resCol = searcher.FindAll();
+
+ try
+ {
+ if (resCol.Count != 2)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.NoHostNameOrPortNumber, dn));
+ }
+
+ foreach (SearchResult res in resCol)
+ {
+ string objectCategoryValue = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.ObjectCategory);
+ if ((objectCategoryValue.Length >= ntdsdsa.Length) && (Utils.Compare(objectCategoryValue, 0, ntdsdsa.Length, ntdsdsa, 0, ntdsdsa.Length) == 0))
+ {
+ // ntdsa object
+ ldapPort = (int)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.MsDSPortLDAP);
+ }
+ else
+ {
+ // server object
+ dnsHostName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DnsHostName);
+ }
+ }
+ }
+ finally
+ {
+ resCol.Dispose();
+ serversEntry.Dispose();
+ }
+
+ if ((ldapPort == -1) || (dnsHostName == null))
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.NoHostNameOrPortNumber, dn));
+ }
+
+ return dnsHostName + ":" + ldapPort;
+ }
+
+ internal static string GetAdamHostNameAndPortsFromNTDSA(DirectoryContext context, string dn)
+ {
+ string dnsHostName = null;
+ int ldapPort = -1;
+ int sslPort = -1;
+ string ntdsaDn = dn;
+ string serverDn = GetPartialDN(dn, 1);
+ string serversDn = GetPartialDN(dn, 2);
+ string ntdsdsa = "CN=NTDS-DSA";
+
+ DirectoryEntry serversEntry = DirectoryEntryManager.GetDirectoryEntry(context, serversDn);
+
+ string filter = "(|(&(" + PropertyManager.ObjectCategory + "=server)(" + PropertyManager.DistinguishedName + "=" + GetEscapedFilterValue(serverDn) + "))" +
+ "(&(" + PropertyManager.ObjectCategory + "=nTDSDSA)(" + PropertyManager.DistinguishedName + "=" + GetEscapedFilterValue(ntdsaDn) + ")))";
+ string[] propertiesToLoad = new string[4];
+ propertiesToLoad[0] = PropertyManager.DnsHostName;
+ propertiesToLoad[1] = PropertyManager.MsDSPortLDAP;
+ propertiesToLoad[2] = PropertyManager.MsDSPortSSL;
+ propertiesToLoad[3] = PropertyManager.ObjectCategory;
+
+ ADSearcher searcher = new ADSearcher(serversEntry, filter, propertiesToLoad, SearchScope.Subtree, true /* paged search */, true /* cache results */);
+ SearchResultCollection resCol = searcher.FindAll();
+
+ try
+ {
+ if (resCol.Count != 2)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.NoHostNameOrPortNumber, dn));
+ }
+
+ foreach (SearchResult res in resCol)
+ {
+ string objectCategoryValue = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.ObjectCategory);
+ if ((objectCategoryValue.Length >= ntdsdsa.Length) && (Utils.Compare(objectCategoryValue, 0, ntdsdsa.Length, ntdsdsa, 0, ntdsdsa.Length) == 0))
+ {
+ // ntdsa object
+ ldapPort = (int)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.MsDSPortLDAP);
+ sslPort = (int)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.MsDSPortSSL);
+ }
+ else
+ {
+ // server object
+ dnsHostName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DnsHostName);
+ }
+ }
+ }
+ finally
+ {
+ resCol.Dispose();
+ serversEntry.Dispose();
+ }
+
+ if ((ldapPort == -1) || (sslPort == -1) || (dnsHostName == null))
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.NoHostNameOrPortNumber, dn));
+ }
+
+ return dnsHostName + ":" + ldapPort + ":" + sslPort;
+ }
+
+ //
+ // If distinguished name is in the form cn=a,cn=b,.... this will return cn=a
+ //
+ internal static string GetRdnFromDN(string distinguishedName)
+ {
+ Component[] dnComponents = GetDNComponents(distinguishedName);
+ // dnComponents will have atleast one component
+ string rdn = dnComponents[0].Name + "=" + dnComponents[0].Value;
+ return rdn;
+ }
+
+ //
+ // if distinguished name is in the form of cn=a,cn=b,cn=c and startingIndex is 1, this will return cn=b,cn=c
+ //
+ internal static string GetPartialDN(string distinguishedName, int startingIndex)
+ {
+ string resultDN = "";
+ Component[] dnComponents = GetDNComponents(distinguishedName);
+ bool firstTime = true;
+ for (int i = startingIndex; i < dnComponents.GetLength(0); i++)
+ {
+ if (firstTime)
+ {
+ resultDN = dnComponents[i].Name + "=" + dnComponents[i].Value;
+ firstTime = false;
+ }
+ else
+ {
+ resultDN += "," + dnComponents[i].Name + "=" + dnComponents[i].Value;
+ }
+ }
+
+ return resultDN;
+ }
+
+ //
+ // Splits up a DN into it's components
+ // e.g. cn=a,cn=b,dc=c,dc=d would be returned as
+ // a component array
+ // components[0].name = cn
+ // components[0].value = a
+ // components[1].name = cn
+ // components[1].value = b ... and so on
+ //
+ internal static Component[] GetDNComponents(string distinguishedName)
+ {
+ Debug.Assert(distinguishedName != null, "Utils.GetDNComponents: distinguishedName is null");
+
+ // First split by ','
+ string[] components = Split(distinguishedName, ',');
+ Component[] dnComponents = new Component[components.GetLength(0)];
+
+ for (int i = 0; i < components.GetLength(0); i++)
+ {
+ // split each component by '='
+ string[] subComponents = Split(components[i], '=');
+ if (subComponents.GetLength(0) != 2)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat), "distinguishedName");
+ }
+
+ dnComponents[i].Name = subComponents[0].Trim();
+ if (dnComponents[i].Name.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat), "distinguishedName");
+ }
+
+ dnComponents[i].Value = subComponents[1].Trim();
+ if (dnComponents[i].Value.Length == 0)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat), "distinguishedName");
+ }
+ }
+ return dnComponents;
+ }
+
+ //
+ // A valid DN is one which can be split based on ',' into components and each
+ // components contains two tokens separated by '='
+ //
+ internal static bool IsValidDNFormat(string distinguishedName)
+ {
+ Debug.Assert(distinguishedName != null, "Utils.GetDNComponents: distinguishedName is null");
+
+ // First split by ','
+ string[] components = Split(distinguishedName, ',');
+ Component[] dnComponents = new Component[components.GetLength(0)];
+
+ for (int i = 0; i < components.GetLength(0); i++)
+ {
+ // split each component by '='
+ string[] subComponents = Split(components[i], '=');
+ if (subComponents.GetLength(0) != 2)
+ {
+ return false;
+ }
+
+ dnComponents[i].Name = subComponents[0].Trim();
+ if (dnComponents[i].Name.Length == 0)
+ {
+ return false;
+ }
+
+ dnComponents[i].Value = subComponents[1].Trim();
+ if (dnComponents[i].Value.Length == 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ //
+ // this method breaks up the string into tokens based on the delimiter
+ // (escaped characters are those preceded by '\' or contained in quotes and
+ // such characters are not considered for a match with the delimiter)
+ //
+ public static string[] Split(string distinguishedName, char delim)
+ {
+ bool inQuotedString = false;
+ char curr;
+ char quote = '\"';
+ char escape = '\\';
+ int nextTokenStart = 0;
+ ArrayList resultList = new ArrayList();
+ string[] results;
+
+ // get the actual tokens
+ for (int i = 0; i < distinguishedName.Length; i++)
+ {
+ curr = distinguishedName[i];
+
+ if (curr == quote)
+ {
+ inQuotedString = !inQuotedString;
+ }
+ else if (curr == escape)
+ {
+ // skip the next character (if one exists)
+ if (i < (distinguishedName.Length - 1))
+ {
+ i++;
+ }
+ }
+ else if ((!inQuotedString) && (curr == delim))
+ {
+ // we found an unqoted character that matches the delimiter
+ // split it at the delimiter (add the tokrn that ends at this delimiter)
+ resultList.Add(distinguishedName.Substring(nextTokenStart, i - nextTokenStart));
+ nextTokenStart = i + 1;
+ }
+
+ if (i == (distinguishedName.Length - 1))
+ {
+ // we've reached the end
+
+ // if we are still in quoted string, the format is invalid
+ if (inQuotedString)
+ {
+ throw new ArgumentException(Res.GetString(Res.InvalidDNFormat), "distinguishedName");
+ }
+
+ // we need to end the last token
+ resultList.Add(distinguishedName.Substring(nextTokenStart, i - nextTokenStart + 1));
+ }
+ }
+
+ results = new string[resultList.Count];
+ for (int i = 0; i < resultList.Count; i++)
+ {
+ results[i] = (string)resultList[i];
+ }
+
+ return results;
+ }
+
+ internal static DirectoryContext GetNewDirectoryContext(string name, DirectoryContextType contextType, DirectoryContext context)
+ {
+ return new DirectoryContext(contextType, name, context);
+ }
+
+ internal static void GetDomainAndUsername(DirectoryContext context, out string username, out string domain)
+ {
+ if ((context.UserName != null) && (context.UserName.Length > 0))
+ {
+ string tmpUsername = context.UserName;
+ int index = -1;
+ if ((index = tmpUsername.IndexOf('\\')) != -1)
+ {
+ domain = tmpUsername.Substring(0, index);
+ username = tmpUsername.Substring(index + 1, tmpUsername.Length - index - 1);
+ }
+ else
+ {
+ username = tmpUsername;
+ domain = null;
+ }
+ }
+ else
+ {
+ username = context.UserName;
+ domain = null;
+ }
+ }
+
+ internal static IntPtr GetAuthIdentity(DirectoryContext context, LoadLibrarySafeHandle libHandle)
+ {
+ IntPtr authIdentity;
+ int result = 0;
+
+ string username;
+ string domain;
+
+ // split the username from the context into username and domain (if possible)
+ GetDomainAndUsername(context, out username, out domain);
+
+ // create the credentials
+ // call DsMakePasswordCredentialsW
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsMakePasswordCredentialsW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsMakePasswordCredentials dsMakePasswordCredentials = (NativeMethods.DsMakePasswordCredentials)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsMakePasswordCredentials));
+
+ result = dsMakePasswordCredentials(username,
+ domain,
+ context.Password,
+ out authIdentity);
+
+ if (result != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+ return authIdentity;
+ }
+
+ internal static void FreeAuthIdentity(IntPtr authIdentity, LoadLibrarySafeHandle libHandle)
+ {
+ // free the credentials object
+ if (authIdentity != IntPtr.Zero)
+ {
+ // call DsMakePasswordCredentialsW
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsFreePasswordCredentials");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsFreePasswordCredentials dsFreePasswordCredentials = (NativeMethods.DsFreePasswordCredentials)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsFreePasswordCredentials));
+ dsFreePasswordCredentials(authIdentity);
+ }
+ }
+
+ internal static IntPtr GetDSHandle(string domainControllerName, string domainName, IntPtr authIdentity, LoadLibrarySafeHandle libHandle)
+ {
+ int result = 0;
+ IntPtr handle;
+
+ // call DsBindWithCred
+ Debug.Assert((domainControllerName != null && domainName == null) || (domainName != null && domainControllerName == null));
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsBindWithCredW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsBindWithCred bindWithCred = (NativeMethods.DsBindWithCred)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsBindWithCred));
+
+ result = bindWithCred(domainControllerName, domainName, authIdentity, out handle);
+ if (result != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(result, (domainControllerName != null) ? domainControllerName : domainName);
+ }
+ return handle;
+ }
+
+ internal static void FreeDSHandle(IntPtr dsHandle, LoadLibrarySafeHandle libHandle)
+ {
+ // DsUnbind
+ if (dsHandle != IntPtr.Zero)
+ {
+ // call DsUnbind
+ IntPtr functionPtr = UnsafeNativeMethods.GetProcAddress(libHandle, "DsUnBindW");
+ if (functionPtr == (IntPtr)0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ NativeMethods.DsUnBind dsUnBind = (NativeMethods.DsUnBind)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(NativeMethods.DsUnBind));
+ int result = dsUnBind(ref dsHandle);
+ }
+ }
+
+ internal static bool CheckCapability(DirectoryEntry rootDSE, Capability capability)
+ {
+ bool result = false;
+ if (rootDSE != null)
+ {
+ if (capability == Capability.ActiveDirectory)
+ {
+ foreach (string supportedCapability in rootDSE.Properties[PropertyManager.SupportedCapabilities])
+ {
+ if (String.Compare(supportedCapability, SupportedCapability.ADOid, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ else if (capability == Capability.ActiveDirectoryApplicationMode)
+ {
+ foreach (string supportedCapability in rootDSE.Properties[PropertyManager.SupportedCapabilities])
+ {
+ if (String.Compare(supportedCapability, SupportedCapability.ADAMOid, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ else if (capability == Capability.ActiveDirectoryOrADAM)
+ {
+ foreach (string supportedCapability in rootDSE.Properties[PropertyManager.SupportedCapabilities])
+ {
+ if (String.Compare(supportedCapability, SupportedCapability.ADAMOid, StringComparison.OrdinalIgnoreCase) == 0 ||
+ String.Compare(supportedCapability, SupportedCapability.ADOid, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ internal static DirectoryEntry GetCrossRefEntry(DirectoryContext context, DirectoryEntry partitionsEntry, string partitionName)
+ {
+ // search for the crossRef that matches this one and
+
+ // build the filter
+ StringBuilder str = new StringBuilder(15);
+ str.Append("(&(");
+ str.Append(PropertyManager.ObjectCategory);
+ str.Append("=crossRef)(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.804:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsNC);
+ str.Append(")(!(");
+ str.Append(PropertyManager.SystemFlags);
+ str.Append(":1.2.840.113556.1.4.803:=");
+ str.Append((int)SystemFlag.SystemFlagNtdsDomain);
+ str.Append("))(");
+ str.Append(PropertyManager.NCName);
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(partitionName));
+ str.Append("))");
+
+ string filter = str.ToString();
+ string[] propertiesToLoad = new string[1];
+
+ propertiesToLoad[0] = PropertyManager.DistinguishedName;
+
+ ADSearcher searcher = new ADSearcher(partitionsEntry, filter, propertiesToLoad, SearchScope.OneLevel, false /*not paged search*/, false /*no cached results*/);
+
+ SearchResult res = null;
+
+ try
+ {
+ res = searcher.FindOne();
+
+ if (res == null)
+ {
+ // should not happen
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.AppNCNotFound), typeof(ActiveDirectoryPartition), partitionName);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ string crossRefDN = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DistinguishedName);
+ return res.GetDirectoryEntry();
+ }
+
+ internal static ActiveDirectoryTransportType GetTransportTypeFromDN(string DN)
+ {
+ Debug.Assert(DN != null);
+
+ string rdn = GetRdnFromDN(DN);
+ Component[] component = GetDNComponents(rdn);
+
+ Debug.Assert(component.Length == 1);
+
+ string transportName = component[0].Value;
+
+ if (String.Compare(transportName, "IP", StringComparison.OrdinalIgnoreCase) == 0)
+ return ActiveDirectoryTransportType.Rpc;
+ else if (String.Compare(transportName, "SMTP", StringComparison.OrdinalIgnoreCase) == 0)
+ return ActiveDirectoryTransportType.Smtp;
+ else
+ {
+ string message = Res.GetString(Res.UnknownTransport, transportName);
+ throw new ActiveDirectoryOperationException(message);
+ }
+ }
+
+ internal static string GetDNFromTransportType(ActiveDirectoryTransportType transport, DirectoryContext context)
+ {
+ string sitesDN = DirectoryEntryManager.ExpandWellKnownDN(context, WellKnownDN.SitesContainer);
+ string transportContainerDN = "CN=Inter-Site Transports," + sitesDN;
+
+ if (transport == ActiveDirectoryTransportType.Rpc)
+ {
+ return "CN=IP," + transportContainerDN;
+ }
+ else
+ {
+ return "CN=SMTP," + transportContainerDN;
+ }
+ }
+
+ internal static string GetServerNameFromInvocationID(string serverObjectDN, Guid invocationID, DirectoryServer server)
+ {
+ string originatingServerName = null;
+
+ if (serverObjectDN == null)
+ {
+ // this is the win2k case, we need to get the DSA address first
+ string siteName = (server is DomainController) ? ((DomainController)server).SiteObjectName : ((AdamInstance)server).SiteObjectName;
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(server.Context, siteName);
+
+ // get the string representation of the invocationID
+ byte[] byteGuid = invocationID.ToByteArray();
+ IntPtr ptr = (IntPtr)0;
+ string stringGuid = null;
+
+ // encode the byte arry into binary string representation
+ int hr = UnsafeNativeMethods.ADsEncodeBinaryData(byteGuid, byteGuid.Length, ref ptr);
+
+ if (hr == 0)
+ {
+ try
+ {
+ stringGuid = Marshal.PtrToStringUni(ptr);
+ }
+ finally
+ {
+ if (ptr != (IntPtr)0)
+ UnsafeNativeMethods.FreeADsMem(ptr);
+ }
+ }
+ else
+ {
+ // throw exception as the call failed
+ throw ExceptionHelper.GetExceptionFromCOMException(new COMException(ExceptionHelper.GetErrorMessage(hr, true), hr));
+ }
+
+ ADSearcher adSearcher = new ADSearcher(de,
+ "(&(objectClass=nTDSDSA)(invocationID=" + stringGuid + "))",
+ new string[] { "distinguishedName" },
+ SearchScope.Subtree,
+ false, /* don't need paged search */
+ false /* don't need to cache result */);
+ SearchResult srchResult = null;
+
+ try
+ {
+ srchResult = adSearcher.FindOne();
+ if (srchResult != null)
+ {
+ DirectoryEntry srvEntry = srchResult.GetDirectoryEntry().Parent;
+ originatingServerName = (string)PropertyManager.GetPropertyValue(server.Context, srvEntry, PropertyManager.DnsHostName);
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(server.Context, e);
+ }
+ }
+ else
+ {
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(server.Context, serverObjectDN);
+
+ try
+ {
+ originatingServerName = (string)PropertyManager.GetPropertyValue(de.Parent, PropertyManager.DnsHostName);
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030))
+ return null;
+ else
+ throw ExceptionHelper.GetExceptionFromCOMException(server.Context, e);
+ }
+ if (server is AdamInstance)
+ {
+ // we might need to add the port number
+ int portnumber = (int)PropertyManager.GetPropertyValue(server.Context, de, PropertyManager.MsDSPortLDAP);
+
+ if (portnumber != 389)
+ originatingServerName = originatingServerName + ":" + portnumber;
+ }
+ }
+
+ return originatingServerName;
+ }
+
+ internal static int GetRandomIndex(int count)
+ {
+ Random random = new Random();
+ int randomNumber = random.Next();
+ return (randomNumber % count);
+ }
+
+ internal static bool Impersonate(DirectoryContext context)
+ {
+ IntPtr hToken = (IntPtr)0;
+
+ // default credential is specified, no need to do impersonation
+ if ((context.UserName == null) && (context.Password == null))
+ return false;
+
+ string userName;
+ string domainName;
+
+ Utils.GetDomainAndUsername(context, out userName, out domainName);
+
+ int result = UnsafeNativeMethods.LogonUserW(userName, domainName, context.Password, s_LOGON32_LOGON_NEW_CREDENTIALS, s_LOGON32_PROVIDER_WINNT50, ref hToken);
+ // check the result
+ if (result == 0)
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+
+ try
+ {
+ result = UnsafeNativeMethods.ImpersonateLoggedOnUser(hToken);
+ if (result == 0)
+ {
+ result = Marshal.GetLastWin32Error();
+ throw ExceptionHelper.GetExceptionFromErrorCode(result);
+ }
+ }
+ finally
+ {
+ if (hToken != (IntPtr)0)
+ UnsafeNativeMethods.CloseHandle(hToken);
+ }
+
+ return true;
+ }
+
+ internal static void ImpersonateAnonymous()
+ {
+ IntPtr hThread = (IntPtr)0;
+ hThread = UnsafeNativeMethods.OpenThread(s_THREAD_ALL_ACCESS, false, UnsafeNativeMethods.GetCurrentThreadId());
+ if (hThread == (IntPtr)0)
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+
+ try
+ {
+ int result = UnsafeNativeMethods.ImpersonateAnonymousToken(hThread);
+ if (result == 0)
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ finally
+ {
+ if (hThread != (IntPtr)0)
+ UnsafeNativeMethods.CloseHandle(hThread);
+ }
+ }
+
+ internal static void Revert()
+ {
+ int error = UnsafeNativeMethods.RevertToSelf();
+ // function failed
+ if (error == 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ }
+
+ internal static string GetPolicyServerName(DirectoryContext context, bool isForest, bool needPdc, string source)
+ {
+ string serverName = null;
+ PrivateLocatorFlags flag = PrivateLocatorFlags.DirectoryServicesRequired;
+
+ // passes in either domain or forest name, just find the dc
+ if (context.isDomain())
+ {
+ if (needPdc)
+ {
+ flag |= PrivateLocatorFlags.PdcRequired;
+ }
+ serverName = Locator.GetDomainControllerInfo(null, source, null, (long)flag).DomainControllerName.Substring(2);
+ }
+ else
+ {
+ // user could pass in non-root domain server name in the context, so need to find a dc in root domain
+ if (isForest)
+ {
+ if (needPdc)
+ {
+ flag |= PrivateLocatorFlags.PdcRequired;
+ serverName = Locator.GetDomainControllerInfo(null, source, null, (long)flag).DomainControllerName.Substring(2);
+ }
+ else
+ {
+ if (context.ContextType == DirectoryContextType.DirectoryServer)
+ {
+ // need first to decide whether this is a server in the root domain or not
+ DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.RootDSE);
+ string namingContext = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.DefaultNamingContext);
+ string rootNamingContext = (string)PropertyManager.GetPropertyValue(context, de, PropertyManager.RootDomainNamingContext);
+ if (Compare(namingContext, rootNamingContext) == 0)
+ {
+ serverName = context.Name;
+ }
+ else
+ {
+ // it is not a server in the root domain, so we need to do dc location
+ serverName = Locator.GetDomainControllerInfo(null, source, null, (long)flag).DomainControllerName.Substring(2);
+ }
+ }
+ else
+ {
+ serverName = Locator.GetDomainControllerInfo(null, source, null, (long)flag).DomainControllerName.Substring(2);
+ }
+ }
+ }
+ else
+ {
+ serverName = context.Name;
+ }
+ }
+
+ return serverName;
+ }
+
+ internal static IntPtr GetPolicyHandle(string serverName)
+ {
+ IntPtr handle = (IntPtr)0;
+ LSA_UNICODE_STRING systemName;
+ LSA_OBJECT_ATTRIBUTES objectAttribute = new LSA_OBJECT_ATTRIBUTES();
+ IntPtr target = (IntPtr)0;
+
+ int mask = s_POLICY_VIEW_LOCAL_INFORMATION;
+
+ systemName = new LSA_UNICODE_STRING();
+ target = Marshal.StringToHGlobalUni(serverName);
+ UnsafeNativeMethods.RtlInitUnicodeString(systemName, target);
+
+ try
+ {
+ int result = UnsafeNativeMethods.LsaOpenPolicy(systemName, objectAttribute, mask, out handle);
+ if (result != 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(UnsafeNativeMethods.LsaNtStatusToWinError(result), serverName);
+ }
+
+ return handle;
+ }
+ finally
+ {
+ if (target != (IntPtr)0)
+ Marshal.FreeHGlobal(target);
+ }
+ }
+
+ //
+ // This function returns a hashtable, where key = propertyname (lowercase) and value = ArrayList of values for that property
+ // (It always searches for one object matching the searching criteria and returns the values for the specified properties using
+ // range retrieval)
+ //
+ internal static Hashtable GetValuesWithRangeRetrieval(DirectoryEntry searchRootEntry, string filter, ArrayList propertiesToLoad, SearchScope searchScope)
+ {
+ return GetValuesWithRangeRetrieval(searchRootEntry, filter, propertiesToLoad, new ArrayList(), searchScope);
+ }
+
+ //
+ // This function returns a hashtable, where key = propertyname (lowercase) and value = ArrayList of values for that property
+ // (It always searches for one object matching the searching criteria and returns the values for the specified properties using
+ // range retrieval)
+ //
+ internal static Hashtable GetValuesWithRangeRetrieval(DirectoryEntry searchRootEntry, string filter, ArrayList propertiesWithRangeRetrieval, ArrayList propertiesWithoutRangeRetrieval, SearchScope searchScope)
+ {
+ ADSearcher searcher = new ADSearcher(searchRootEntry, filter, new string[] { }, searchScope, false /* paged search */, false /* cache results */);
+ SearchResult res = null;
+ int rangeStart = 0;
+ Hashtable results = new Hashtable();
+ Hashtable propertyNamesWithRangeInfo = new Hashtable();
+ ArrayList propertyNamesWithoutRangeInfo = new ArrayList();
+ ArrayList propertiesStillToLoad = new ArrayList();
+
+ //
+ // The logic is as follows:
+ // For each property in the propertiesWithRangeRetrieval we add the range as 0-*, e.g. member would be "member;range=0-*"
+ // When the results are returned if the property name is not present or is still "member;range=0-*", then we got the last batch and so we
+ // will not retrieve this property in the next round. However, if the property comes back as "member;range=0-1499" this means
+ // we still have more values to retrieve, so we will retrieve "member;range=5000-*" next time and so on...
+ //
+ // Properties in the propertiesWithoutRangeRetrieval arraylist, we only include the properties in the first search without any range info
+ //
+
+ foreach (string propertyName in propertiesWithoutRangeRetrieval)
+ {
+ // need to convert to lower case since S.DS returns property names in all lower case
+ string lowerCasePropertyName = propertyName.ToLower(CultureInfo.InvariantCulture);
+ propertyNamesWithoutRangeInfo.Add(lowerCasePropertyName);
+ results.Add(lowerCasePropertyName, new ArrayList());
+ // add to the seachers's propertiesToLoad
+ searcher.PropertiesToLoad.Add(propertyName);
+ }
+
+ // keep a list of properties for which we have not yet retrieved all the
+ // results
+ foreach (string propertyName in propertiesWithRangeRetrieval)
+ {
+ // need to convert to lower case since S.DS returns property names in all lower case
+ string lowerCasePropertyName = propertyName.ToLower(CultureInfo.InvariantCulture);
+ propertiesStillToLoad.Add(lowerCasePropertyName);
+ results.Add(lowerCasePropertyName, new ArrayList());
+ }
+
+ do
+ {
+ foreach (string propertyName in propertiesStillToLoad)
+ {
+ string propertyToLoad = propertyName + ";range=" + rangeStart + "-*";
+ searcher.PropertiesToLoad.Add(propertyToLoad);
+ // need to convert to lower case since S.DS returns property names in all lower case
+ propertyNamesWithRangeInfo.Add(propertyName.ToLower(CultureInfo.InvariantCulture), propertyToLoad);
+ }
+
+ //clear for the nezxt round
+ propertiesStillToLoad.Clear();
+
+ res = searcher.FindOne();
+ if (res != null)
+ {
+ foreach (string propertyNameWithRangeInfo in res.Properties.PropertyNames)
+ {
+ int index = propertyNameWithRangeInfo.IndexOf(';');
+
+ string propertyName = null;
+ if (index != -1)
+ {
+ propertyName = propertyNameWithRangeInfo.Substring(0, index);
+ }
+ else
+ {
+ propertyName = propertyNameWithRangeInfo;
+ }
+
+ if (!propertyNamesWithRangeInfo.Contains(propertyName) && !propertyNamesWithoutRangeInfo.Contains(propertyName))
+ {
+ // we're not interested in this property (could be adspath), so just skip
+ continue;
+ }
+
+ ArrayList values = (ArrayList)results[propertyName];
+ values.AddRange(res.Properties[propertyNameWithRangeInfo]);
+
+ if (propertyNamesWithRangeInfo.Contains(propertyName))
+ {
+ //
+ // if this is a property retrieved along with range retrieval, check if we need to include
+ // it in the next round.
+ //
+
+ string propertyToLoad = (string)propertyNamesWithRangeInfo[propertyName];
+
+ if ((propertyNameWithRangeInfo.Length >= propertyToLoad.Length) && (Utils.Compare(propertyToLoad, 0, propertyToLoad.Length, propertyNameWithRangeInfo, 0, propertyToLoad.Length) != 0))
+ {
+ propertiesStillToLoad.Add(propertyName);
+ rangeStart += res.Properties[propertyNameWithRangeInfo].Count;
+ }
+ }
+ }
+ }
+ else
+ {
+ throw new ActiveDirectoryObjectNotFoundException(Res.GetString(Res.DSNotFound));
+ }
+
+ // clear for the next round
+ searcher.PropertiesToLoad.Clear();
+ propertyNamesWithRangeInfo.Clear();
+ } while (propertiesStillToLoad.Count > 0);
+
+ return results;
+ }
+
+ internal static ArrayList GetReplicaList(DirectoryContext context, string partitionName, string siteName, bool isDefaultNC, bool isADAM, bool isGC)
+ {
+ ArrayList ntdsaNames = new ArrayList();
+ ArrayList dnsNames = new ArrayList();
+
+ //
+ // The algorithm is as follows:
+ // 1. Search for the crossRef entry of this partition and retrieve the msDS-NC-Replica-Locations and
+ // msDS_NC-RO-Replica-Locations for a list of the replicas (using range retrieval). This is needed
+ // in the case of application partition only.
+ // 2. Search for the ntdsa objects of these replicas which have the partition in the Has-MasterNCs attribute (if partition name is specified
+ // else search for all ntdsa objects)
+ // 3. For each replica in the resulting set, check if the msDS-Has-InstantiatedNCs attribute is of the form B:8:00000005:<DN of partition>
+ // where the second nibble from the least significant side is 0, B:8:00000015 would signify that the partition is still being replicated in
+ // and B:8:00000025 would indicate the partition is being replicated out (replica deletion) (again, this is only if partitionName is specified).
+ // This step is needed only for application partitions. This will be ignored for read-only NCs as it will ONLY be populated locally to each RODC.
+ //
+
+ Hashtable serverNames = new Hashtable();
+ Hashtable serverPorts = new Hashtable();
+ StringBuilder ntdsaFilter = new StringBuilder(10);
+ StringBuilder serverFilter = new StringBuilder(10);
+ StringBuilder roNtdsaFilter = new StringBuilder(10);
+ StringBuilder roServerFilter = new StringBuilder(10);
+
+ bool useReplicaInfo = false;
+ string configurationNamingContext = null;
+
+ try
+ {
+ configurationNamingContext = DirectoryEntryManager.ExpandWellKnownDN(context, WellKnownDN.ConfigurationNamingContext);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+
+ //
+ // If partition name is not null and is not Configuration/Schema/defaultNC , we need to get the list of the
+ // msDS-NC-Replica-Locations and msDS-NC-RO-Replica-Locations (for Configuration/Schema, these attributes are
+ // not populated, so we just return a list of all the servers)
+ //
+ if (partitionName != null && !isDefaultNC)
+ {
+ DistinguishedName dn = new DistinguishedName(partitionName);
+ DistinguishedName configDn = new DistinguishedName(configurationNamingContext);
+ DistinguishedName schemaDn = new DistinguishedName("CN=Schema," + configurationNamingContext);
+
+ if ((!(configDn.Equals(dn))) && (!(schemaDn.Equals(dn))))
+ {
+ useReplicaInfo = true;
+ }
+ }
+
+ if (useReplicaInfo)
+ {
+ DirectoryEntry partitionsEntry = null;
+ DirectoryEntry fsmoPartitionsEntry = null;
+
+ try
+ {
+ //
+ // get the partitions entry on the naming master
+ //
+ partitionsEntry = DirectoryEntryManager.GetDirectoryEntry(context, "CN=Partitions," + configurationNamingContext);
+ string fsmoRoleOwnerName = null;
+ if (isADAM)
+ {
+ fsmoRoleOwnerName = Utils.GetAdamDnsHostNameFromNTDSA(context, (string)PropertyManager.GetPropertyValue(context, partitionsEntry, PropertyManager.FsmoRoleOwner));
+ }
+ else
+ {
+ fsmoRoleOwnerName = Utils.GetDnsHostNameFromNTDSA(context, (string)PropertyManager.GetPropertyValue(context, partitionsEntry, PropertyManager.FsmoRoleOwner));
+ }
+
+ DirectoryContext fsmoContext = Utils.GetNewDirectoryContext(fsmoRoleOwnerName, DirectoryContextType.DirectoryServer, context);
+ fsmoPartitionsEntry = DirectoryEntryManager.GetDirectoryEntry(fsmoContext, "CN=Partitions," + configurationNamingContext);
+
+ // get the properties using range retrieval
+ // (since msDS-NC-Replica-Locations and msDS-NC-RO-Replica-Locations are multi-valued)
+ string filter = "(&(" + PropertyManager.ObjectCategory + "=crossRef)(" + PropertyManager.NCName + "=" + Utils.GetEscapedFilterValue(partitionName) + "))";
+ ArrayList propertyNames = new ArrayList();
+ propertyNames.Add(PropertyManager.MsDSNCReplicaLocations);
+ propertyNames.Add(PropertyManager.MsDSNCROReplicaLocations);
+
+ Hashtable values = null;
+ try
+ {
+ values = Utils.GetValuesWithRangeRetrieval(fsmoPartitionsEntry, filter, propertyNames, SearchScope.OneLevel);
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(fsmoContext, e);
+ }
+ catch (ActiveDirectoryObjectNotFoundException)
+ {
+ // this means that this partition does not exist, so we return an empty collection
+ return dnsNames;
+ }
+
+ // extract the property values
+ ArrayList replicaLocations = (ArrayList)values[PropertyManager.MsDSNCReplicaLocations.ToLower(CultureInfo.InvariantCulture)];
+ ArrayList roReplicaLocations = (ArrayList)values[PropertyManager.MsDSNCROReplicaLocations.ToLower(CultureInfo.InvariantCulture)];
+ Debug.Assert(replicaLocations != null);
+
+ if (replicaLocations.Count == 0)
+ {
+ // At this point we find that there are no replica locations, so we return an empty collection.
+ return dnsNames;
+ }
+
+ foreach (string replicaLocation in replicaLocations)
+ {
+ ntdsaFilter.Append("(");
+ ntdsaFilter.Append(PropertyManager.DistinguishedName);
+ ntdsaFilter.Append("=");
+ ntdsaFilter.Append(Utils.GetEscapedFilterValue(replicaLocation));
+ ntdsaFilter.Append(")");
+
+ serverFilter.Append("(");
+ serverFilter.Append(PropertyManager.DistinguishedName);
+ serverFilter.Append("=");
+ serverFilter.Append(Utils.GetEscapedFilterValue(Utils.GetPartialDN(replicaLocation, 1)));
+ serverFilter.Append(")");
+ }
+
+ foreach (string roReplicaLocation in roReplicaLocations)
+ {
+ roNtdsaFilter.Append("(");
+ roNtdsaFilter.Append(PropertyManager.DistinguishedName);
+ roNtdsaFilter.Append("=");
+ roNtdsaFilter.Append(Utils.GetEscapedFilterValue(roReplicaLocation));
+ roNtdsaFilter.Append(")");
+
+ roServerFilter.Append("(");
+ roServerFilter.Append(PropertyManager.DistinguishedName);
+ roServerFilter.Append("=");
+ roServerFilter.Append(Utils.GetEscapedFilterValue(Utils.GetPartialDN(roReplicaLocation, 1)));
+ roServerFilter.Append(")");
+ }
+ }
+ catch (COMException e)
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ finally
+ {
+ if (partitionsEntry != null)
+ {
+ partitionsEntry.Dispose();
+ }
+ if (fsmoPartitionsEntry != null)
+ {
+ fsmoPartitionsEntry.Dispose();
+ }
+ }
+ }
+
+ string searchRootDN = null;
+ DirectoryEntry searchRootEntry = null;
+ try
+ {
+ // check whether we can narrow down our search within a specific site
+ if (siteName != null)
+ {
+ searchRootDN = "CN=Servers,CN=" + siteName + ",CN=Sites," + configurationNamingContext;
+ }
+ else
+ {
+ searchRootDN = "CN=Sites," + configurationNamingContext;
+ }
+ searchRootEntry = DirectoryEntryManager.GetDirectoryEntry(context, searchRootDN);
+
+ // set up searcher object
+ string filter2 = null;
+ if (ntdsaFilter.ToString().Length == 0)
+ {
+ // either this is the case when we want all the servers (partitionName = null or partitionName is Configuration/Schema)
+ // or this is the case when partitionName is the defaultNamingContext
+ // for the latter we want to restrict the search to only that naming context
+
+ if (isDefaultNC)
+ {
+ Debug.Assert(partitionName != null);
+ Debug.Assert(!isGC);
+
+ filter2 = "(|(&(" + PropertyManager.ObjectCategory + "=nTDSDSA)(" + PropertyManager.HasMasterNCs +
+ "=" + Utils.GetEscapedFilterValue(partitionName) + "))(&(" + PropertyManager.ObjectCategory + "=nTDSDSARO)(" +
+ PropertyManager.MsDSHasFullReplicaNCs + "=" + Utils.GetEscapedFilterValue(partitionName) + "))(" +
+ PropertyManager.ObjectCategory + "=server))";
+ }
+ else
+ {
+ if (isGC)
+ {
+ filter2 = "(|(&(" + PropertyManager.ObjectCategory + "=nTDSDSA)(" +
+ PropertyManager.Options + ":1.2.840.113556.1.4.804:=1))(&(" +
+ PropertyManager.ObjectCategory + "=nTDSDSARO)(" +
+ PropertyManager.Options + ":1.2.840.113556.1.4.804:=1))(" +
+ PropertyManager.ObjectCategory + "=server))";
+ }
+ else
+ {
+ filter2 = "(|" + "(" + PropertyManager.ObjectCategory + "=nTDSDSA)(" +
+ PropertyManager.ObjectCategory + "=nTDSDSARO)(" +
+ PropertyManager.ObjectCategory + "=server))";
+ }
+ }
+ }
+ else
+ {
+ Debug.Assert(partitionName != null);
+ // resctrict the search to the servers that were listed in the crossRef
+ if (isGC)
+ {
+ if (roNtdsaFilter.Length > 0)
+ {
+ //for read-only NCs, msDS-hasFullReplicaNCs is equivalent of msDS-hasMasterNCs. But since msDS-hasFullReplicaNCs will be
+ //populated ONLY on each RODC, it can't be used. Since roNtdsaFilter is populated using input partitionName, we should
+ //be fine.
+ filter2 = "(|(&(" + PropertyManager.ObjectCategory + "=nTDSDSA)(" + PropertyManager.Options +
+ ":1.2.840.113556.1.4.804:=1)(" + PropertyManager.MsDSHasMasterNCs + "=" + Utils.GetEscapedFilterValue(partitionName) +
+ ")(|" + ntdsaFilter.ToString() + "))" + "(&(" + PropertyManager.ObjectCategory + "=nTDSDSARO)(" + PropertyManager.Options +
+ ":1.2.840.113556.1.4.804:=1)(|" + roNtdsaFilter.ToString() + "))" +
+ "(&(" + PropertyManager.ObjectCategory + "=server)(|" + serverFilter.ToString() + "))" +
+ "(&(" + PropertyManager.ObjectCategory + "=server)(|" + roServerFilter.ToString() + ")))";
+ }
+ else
+ {
+ filter2 = "(|(&(" + PropertyManager.ObjectCategory + "=nTDSDSA)(" + PropertyManager.Options +
+ ":1.2.840.113556.1.4.804:=1)(" + PropertyManager.MsDSHasMasterNCs + "=" + Utils.GetEscapedFilterValue(partitionName) +
+ ")(|" + ntdsaFilter.ToString() + "))" + "(&(" + PropertyManager.ObjectCategory + "=server)(|" + serverFilter.ToString() + ")))";
+ }
+ }
+ else
+ {
+ if (roNtdsaFilter.Length > 0)
+ {
+ //for read-only NCs, msDS-hasFullReplicaNCs is equivalent of msDS-hasMasterNCs. But since msDS-hasFullReplicaNCs will be
+ //populated ONLY on each RODC, it can't be used. Since roNtdsaFilter is populated using input partitionName, we should
+ //be fine.
+ filter2 = "(|(&(" + PropertyManager.ObjectCategory + "=nTDSDSA)(" + PropertyManager.MsDSHasMasterNCs + "=" + Utils.GetEscapedFilterValue(partitionName) + ")(|" + ntdsaFilter.ToString() + "))"
+ + "(&(" + PropertyManager.ObjectCategory + "=nTDSDSARO)(|" + roNtdsaFilter.ToString() + "))"
+ + "(&(" + PropertyManager.ObjectCategory + "=server)(|" + serverFilter.ToString() + "))"
+ + "(&(" + PropertyManager.ObjectCategory + "=server)(|" + roServerFilter.ToString() + ")))";
+ }
+ else
+ {
+ filter2 = "(|(&(" + PropertyManager.ObjectCategory + "=nTDSDSA)(" + PropertyManager.MsDSHasMasterNCs + "=" + Utils.GetEscapedFilterValue(partitionName) + ")(|" + ntdsaFilter.ToString() + "))"
+ + "(&(" + PropertyManager.ObjectCategory + "=server)(|" + serverFilter.ToString() + ")))";
+ }
+ }
+ }
+
+ string[] propertiesToLoad2 = new string[5];
+
+ ADSearcher searcher2 = new ADSearcher(searchRootEntry, filter2, new string[] { }, SearchScope.Subtree);
+ SearchResultCollection resCol = null;
+ bool needToContinueRangeRetrieval = false;
+ ArrayList ntdsaNamesForRangeRetrieval = new ArrayList();
+ int rangeStart = 0;
+
+ string propertyWithRangeInfo = PropertyManager.MsDSHasInstantiatedNCs + ";range=0-*";
+ searcher2.PropertiesToLoad.Add(PropertyManager.DistinguishedName);
+ searcher2.PropertiesToLoad.Add(PropertyManager.DnsHostName);
+ searcher2.PropertiesToLoad.Add(propertyWithRangeInfo);
+ searcher2.PropertiesToLoad.Add(PropertyManager.ObjectCategory);
+ if (isADAM)
+ {
+ searcher2.PropertiesToLoad.Add(PropertyManager.MsDSPortLDAP);
+ }
+
+ try
+ {
+ string objectCategoryValue = "CN=NTDS-DSA";
+ string roObjectCategoryValue = "CN=NTDS-DSA-RO";
+
+ resCol = searcher2.FindAll();
+
+ try
+ {
+ foreach (SearchResult res in resCol)
+ {
+ string objectCategory = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.ObjectCategory);
+ if ((objectCategory.Length >= objectCategoryValue.Length) && (Utils.Compare(objectCategory, 0, objectCategoryValue.Length, objectCategoryValue, 0, objectCategoryValue.Length) == 0))
+ {
+ //
+ // ntdsa objects (return only those servers which have the partition fully instantiated)
+ //
+ string ntdsaName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DistinguishedName);
+ if (useReplicaInfo)
+ {
+ if ((objectCategory.Length >= roObjectCategoryValue.Length) && (Utils.Compare(objectCategory, 0, roObjectCategoryValue.Length, roObjectCategoryValue, 0, roObjectCategoryValue.Length) == 0))
+ {
+ //for read-only NCs, msDS-HasInstantiatedNCs will be populated ONLY on each RODC and it will NOT be
+ //replicated to other DCs. So it can't be used, provided we connect to each RODC and verify it which is not
+ //really required as msDS-NC-RO-Replica-Locations should provide the correct information.
+ ntdsaNames.Add(ntdsaName);
+ if (isADAM)
+ {
+ serverPorts.Add(ntdsaName, (int)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.MsDSPortLDAP));
+ }
+ continue;
+ }
+
+ // Here we need to check if we retrieved all the msDS-HasInstantiatedNCs values
+ // if not we need to continue with the range retrieval (in parallel for the various ntdsa objects)
+
+ string propertyName = null;
+ if (!res.Properties.Contains(propertyWithRangeInfo))
+ {
+ // find the property name with the range info
+ foreach (string property in res.Properties.PropertyNames)
+ {
+ if ((property.Length >= PropertyManager.MsDSHasInstantiatedNCs.Length) && (Utils.Compare(property, 0, PropertyManager.MsDSHasInstantiatedNCs.Length, PropertyManager.MsDSHasInstantiatedNCs, 0, PropertyManager.MsDSHasInstantiatedNCs.Length) == 0))
+ {
+ propertyName = property;
+ break;
+ }
+ }
+ }
+ else
+ {
+ propertyName = propertyWithRangeInfo;
+ }
+
+ if (propertyName == null)
+ {
+ // property does not exist, possiblyno values, so continue
+ continue;
+ }
+
+ bool foundPartitionEntry = false;
+ int valueCount = 0;
+
+ foreach (string dnString in res.Properties[propertyName])
+ {
+ Debug.Assert(dnString.Length > 10, "ConfigurationSet::GetReplicaList - dnWithBinary is not in the expected format.");
+
+ if (((dnString.Length - 13) >= partitionName.Length) && (Utils.Compare(dnString, 13, partitionName.Length, partitionName, 0, partitionName.Length) == 0))
+ {
+ // found the entry that corresponds to this partition so even if we didn't get all the values of the
+ // multivalues attribute we can stop here.
+ foundPartitionEntry = true;
+
+ if (String.Compare(dnString, 10, "0", 0, 1, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ // this server has the partition fully instantiated
+ ntdsaNames.Add(ntdsaName);
+ if (isADAM)
+ {
+ serverPorts.Add(ntdsaName, (int)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.MsDSPortLDAP));
+ }
+ break;
+ }
+ }
+
+ valueCount++;
+ }
+
+ if ((!foundPartitionEntry) && ((propertyName.Length >= propertyWithRangeInfo.Length) && (Utils.Compare(propertyName, 0, propertyWithRangeInfo.Length, propertyWithRangeInfo, 0, propertyWithRangeInfo.Length) != 0)))
+ {
+ needToContinueRangeRetrieval = true;
+ ntdsaNamesForRangeRetrieval.Add(ntdsaName);
+ rangeStart = valueCount;
+ }
+ }
+ else
+ {
+ // schema or configuration partition, so we add all the servers
+ ntdsaNames.Add(ntdsaName);
+ if (isADAM)
+ {
+ serverPorts.Add(ntdsaName, (int)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.MsDSPortLDAP));
+ }
+ }
+ }
+ else
+ {
+ // server objects, just keep infor regarding the dns name (to be used later), if not available we will throw an error later
+ // when we try to retrieve this info for a valid DC/GC
+ if (res.Properties.Contains(PropertyManager.DnsHostName))
+ {
+ serverNames.Add("CN=NTDS Settings," + (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DistinguishedName),
+ (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DnsHostName));
+ }
+ }
+ }
+ }
+ finally
+ {
+ if (resCol != null)
+ {
+ resCol.Dispose();
+ }
+ }
+
+ if (needToContinueRangeRetrieval)
+ {
+ // Now continue with range retrieval if necessary for msDS-HasInstantiatedNCs
+ do
+ {
+ // Here we only need the NTDS settings objects of the ntdsaNames that need range retrieval
+
+ // this should be greater than 0, since needToContinueRangeRetrieval is true
+ Debug.Assert(ntdsaNamesForRangeRetrieval.Count > 0);
+
+ StringBuilder str = new StringBuilder(20);
+ if (ntdsaNamesForRangeRetrieval.Count > 1)
+ {
+ str.Append("(|");
+ }
+
+ foreach (string name in ntdsaNamesForRangeRetrieval)
+ {
+ str.Append("(");
+ str.Append(PropertyManager.NCName);
+ str.Append("=");
+ str.Append(Utils.GetEscapedFilterValue(name));
+ str.Append(")");
+ }
+
+ if (ntdsaNamesForRangeRetrieval.Count > 1)
+ {
+ str.Append(")");
+ }
+
+ // Clear it for the next round of range retrieval
+ ntdsaNamesForRangeRetrieval.Clear();
+ needToContinueRangeRetrieval = false;
+
+ searcher2.Filter = "(&" + "(" + PropertyManager.ObjectCategory + "=nTDSDSA)" + str.ToString() + ")";
+
+ string propertyWithRangeInfo2 = PropertyManager.MsDSHasInstantiatedNCs + ";range=" + rangeStart + "-*";
+ searcher2.PropertiesToLoad.Clear();
+ searcher2.PropertiesToLoad.Add(propertyWithRangeInfo2);
+ searcher2.PropertiesToLoad.Add(PropertyManager.DistinguishedName);
+
+ SearchResultCollection resCol2 = searcher2.FindAll();
+
+ try
+ {
+ foreach (SearchResult res in resCol2)
+ {
+ string ntdsaName = (string)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.DistinguishedName);
+ // Here we need to check if we retrieved all the msDS-HasInstantiatedNCs values
+ // if not we need to continue with the range retrieval (in parallel for the various ntdsa objects)
+ string propertyName = null;
+ if (!res.Properties.Contains(propertyWithRangeInfo2))
+ {
+ // find the property name with the range info
+ foreach (string property in res.Properties.PropertyNames)
+ {
+ if (String.Compare(property, 0, PropertyManager.MsDSHasInstantiatedNCs, 0, PropertyManager.MsDSHasInstantiatedNCs.Length, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ propertyName = property;
+ break;
+ }
+ }
+ }
+ else
+ {
+ propertyName = propertyWithRangeInfo2;
+ }
+
+ if (propertyName == null)
+ {
+ // property does not exist, possiblyno values, so continue
+ continue;
+ }
+
+ bool foundPartitionEntry = false;
+ int valueCount = 0;
+
+ foreach (string dnString in res.Properties[propertyName])
+ {
+ Debug.Assert(dnString.Length > 10, "ConfigurationSet::GetReplicaList - dnWithBinary is not in the expected format.");
+
+ if (((dnString.Length - 13) >= partitionName.Length) && (Utils.Compare(dnString, 13, partitionName.Length, partitionName, 0, partitionName.Length) == 0))
+ {
+ foundPartitionEntry = true;
+
+ if (String.Compare(dnString, 10, "0", 0, 1, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ ntdsaNames.Add(ntdsaName);
+ if (isADAM)
+ {
+ serverPorts.Add(ntdsaName, (int)PropertyManager.GetSearchResultPropertyValue(res, PropertyManager.MsDSPortLDAP));
+ }
+ break;
+ }
+ }
+
+ valueCount++;
+ }
+
+ if ((!foundPartitionEntry) && ((propertyName.Length >= propertyWithRangeInfo2.Length) && (Utils.Compare(propertyName, 0, propertyWithRangeInfo2.Length, propertyWithRangeInfo2, 0, propertyWithRangeInfo2.Length) != 0)))
+ {
+ needToContinueRangeRetrieval = true;
+ ntdsaNamesForRangeRetrieval.Add(ntdsaName);
+ rangeStart += valueCount;
+ }
+ }
+ }
+ finally
+ {
+ resCol2.Dispose();
+ }
+ } while (needToContinueRangeRetrieval);
+ }
+ }
+ catch (COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030) && siteName != null)
+ {
+ // this means that the site object does not exist, so we return an empty collection
+ return dnsNames;
+ }
+ else
+ {
+ throw ExceptionHelper.GetExceptionFromCOMException(context, e);
+ }
+ }
+ }
+ finally
+ {
+ if (searchRootEntry != null)
+ {
+ searchRootEntry.Dispose();
+ }
+ }
+
+ // convert the ntdsa object names to server:port
+ foreach (string ntdsaName in ntdsaNames)
+ {
+ string hostName = (string)serverNames[ntdsaName];
+
+ if (hostName == null)
+ {
+ Debug.Fail(string.Format(CultureInfo.InvariantCulture, "ConfigurationSet::GetReplicaList - no dnsHostName information for replica {0}", ntdsaName));
+ if (isADAM)
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.NoHostNameOrPortNumber, ntdsaName));
+ }
+ else
+ {
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.NoHostName, ntdsaName));
+ }
+ }
+
+ if (isADAM)
+ {
+ if (serverPorts[ntdsaName] == null)
+ {
+ Debug.Fail(string.Format(CultureInfo.InvariantCulture, "ConfigurationSet::GetReplicaList - no port number information for replica {0}", ntdsaName));
+ throw new ActiveDirectoryOperationException(Res.GetString(Res.NoHostNameOrPortNumber, ntdsaName));
+ }
+ }
+
+ if (isADAM)
+ {
+ dnsNames.Add(hostName + ":" + (int)serverPorts[ntdsaName]);
+ }
+ else
+ {
+ dnsNames.Add(hostName);
+ }
+ }
+
+ return dnsNames;
+ }
+
+ //
+ // Generates an escaped name that may be used in an LDAP query. The characters
+ // ( ) * \ must be escaped when used in an LDAP query per RFC 2254.
+ //
+ internal static string GetEscapedFilterValue(string filterValue)
+ {
+ int index = -1;
+ char[] specialCharacters = new char[] { '(', ')', '*', '\\' };
+
+ index = filterValue.IndexOfAny(specialCharacters);
+ if (index != -1)
+ {
+ //
+ // if it contains any of the special characters then we
+ // need to escape those
+ //
+
+ StringBuilder str = new StringBuilder(2 * filterValue.Length);
+
+ str.Append(filterValue.Substring(0, index));
+
+ for (int i = index; i < filterValue.Length; i++)
+ {
+ switch (filterValue[i])
+ {
+ case ('('):
+ {
+ str.Append("\\28");
+ break;
+ }
+
+ case (')'):
+ {
+ str.Append("\\29");
+ break;
+ }
+
+ case ('*'):
+ {
+ str.Append("\\2A");
+ break;
+ }
+
+ case ('\\'):
+ {
+ str.Append("\\5C");
+ break;
+ }
+
+ default:
+ {
+ str.Append(filterValue[i]);
+ break;
+ }
+ }
+ }
+
+ return str.ToString();
+ }
+ else
+ {
+ //
+ // just return the original string
+ //
+
+ return filterValue;
+ }
+ }
+
+ internal static string GetEscapedPath(string originalPath)
+ {
+ NativeComInterfaces.IAdsPathname pathCracker = (NativeComInterfaces.IAdsPathname)new NativeComInterfaces.Pathname();
+ return pathCracker.GetEscapedElement(0, originalPath);
+ }
+
+ internal static int Compare(string s1, string s2, uint compareFlags)
+ {
+ // This code block was specifically written for handling string comparison
+ // involving null strings. The unmanged API "NativeMethods.CompareString"
+ // does not handle null strings elegantly.
+ //
+ // This method handles comparison of the specified strings
+ // if and only if either one of the two strings or both are null.
+ if (s1 == null || s2 == null)
+ {
+ return string.Compare(s1, s2);
+ }
+
+ int result = 0;
+ IntPtr lpString1 = IntPtr.Zero;
+ IntPtr lpString2 = IntPtr.Zero;
+ int cchCount1 = 0;
+ int cchCount2 = 0;
+
+ try
+ {
+ lpString1 = Marshal.StringToHGlobalUni(s1);
+ cchCount1 = s1.Length;
+ lpString2 = Marshal.StringToHGlobalUni(s2);
+ cchCount2 = s2.Length;
+
+ result = NativeMethods.CompareString(s_LCID, compareFlags, lpString1, cchCount1, lpString2, cchCount2);
+ if (result == 0)
+ {
+ throw ExceptionHelper.GetExceptionFromErrorCode(Marshal.GetLastWin32Error());
+ }
+ }
+ finally
+ {
+ if (lpString1 != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(lpString1);
+ }
+ if (lpString2 != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(lpString2);
+ }
+ }
+
+ return (result - 2); // to give the semantics of <0, ==0, >0
+ }
+
+ internal static int Compare(string s1, string s2)
+ {
+ return Compare(s1, s2, DEFAULT_CMP_FLAGS);
+ }
+
+ internal static int Compare(string s1, int offset1, int length1, string s2, int offset2, int length2)
+ {
+ if (s1 == null)
+ {
+ throw new ArgumentNullException("s1");
+ }
+ if (s2 == null)
+ {
+ throw new ArgumentNullException("s2");
+ }
+ return Compare(s1.Substring(offset1, length1), s2.Substring(offset2, length2));
+ }
+
+ internal static int Compare(string s1, int offset1, int length1, string s2, int offset2, int length2, uint compareFlags)
+ {
+ if (s1 == null)
+ {
+ throw new ArgumentNullException("s1");
+ }
+ if (s2 == null)
+ {
+ throw new ArgumentNullException("s2");
+ }
+ return Compare(s1.Substring(offset1, length1), s2.Substring(offset2, length2), compareFlags);
+ }
+
+ // Split given server name string to server name and port number.
+ // e.g. serverName input serverName return portNumber
+ // DC1 DC1 null
+ // IPv4:Port IPv4 Port
+ // [IPv6]:Port IPv6 Port
+ internal static string SplitServerNameAndPortNumber(string serverName, out string portNumber)
+ {
+ portNumber = null;
+
+ int lastColon = serverName.LastIndexOf(':');
+ if (lastColon == -1)
+ {
+ //no port number e.g. DC1, IPv4
+ return serverName;
+ }
+
+ //extract IPv6 port number if any
+ bool isBrace = serverName.StartsWith("[");
+ if (isBrace == true)
+ {
+ if (serverName.EndsWith("]"))
+ {
+ //[IPv6]
+ serverName = serverName.Substring(1, serverName.Length - 2);//2 for []
+ return serverName;
+ }
+ int closingBrace = serverName.LastIndexOf("]:");
+ if ((closingBrace == -1) || (closingBrace + 1 != lastColon))
+ {
+ //error, return input string
+ return serverName;
+ }
+ //[IPv6]:Port
+ portNumber = serverName.Substring(lastColon + 1);
+ serverName = serverName.Substring(1, closingBrace - 1);
+ return serverName;
+ }
+
+ //check if IPv6 address
+ try
+ {
+ IPAddress address = IPAddress.Parse(serverName);
+ if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
+ {
+ //IPv6
+ return serverName;
+ }
+ }
+ catch (FormatException)
+ {
+ //not the address
+ }
+
+ //extract port number e.g. DC1:Port, IPv4:Port
+ portNumber = serverName.Substring(lastColon + 1);
+ serverName = serverName.Substring(0, lastColon);
+ return serverName;
+ }
+
+ private static string s_NTAuthorityString = null;
+
+ internal static string GetNtAuthorityString()
+ {
+ if (s_NTAuthorityString == null)
+ {
+ SecurityIdentifier sidLocalSystem = new SecurityIdentifier("S-1-5-18");
+ NTAccount ntLocalSystem = (NTAccount)sidLocalSystem.Translate(typeof(NTAccount));
+ int index = ntLocalSystem.Value.IndexOf('\\');
+ Debug.Assert(index != -1);
+ s_NTAuthorityString = ntLocalSystem.Value.Substring(0, index);
+ }
+ return s_NTAuthorityString;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.EqualDomainSid(System.IntPtr,System.IntPtr,System.Boolean&):System.Boolean" />
+ // <SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static bool IsSamUser()
+ {
+ //
+ // Basic algorithm
+ //
+ // Get SID of current user (via OpenThreadToken/GetTokenInformation/CloseHandle for TokenUser)
+ //
+ // Is the user SID of the form S-1-5-21-... (does GetSidIdentityAuthority(u) == 5 and GetSidSubauthority(u, 0) == 21)?
+ // If NO ---> is local user
+ // If YES --->
+ // Get machine domain SID (via LsaOpenPolicy/LsaQueryInformationPolicy for PolicyAccountDomainInformation/LsaClose)
+ // Does EqualDomainSid indicate the current user SID and the machine domain SID have the same domain?
+ // If YES -->
+ // IS the local machine a DC
+ // If NO --> is local user
+ // If YES --> is _not_ local user
+ // If NO --> is _not_ local user
+ //
+
+ IntPtr pCopyOfUserSid = IntPtr.Zero;
+ IntPtr pMachineDomainSid = IntPtr.Zero;
+
+ try
+ {
+ // Get the user's SID
+ pCopyOfUserSid = GetCurrentUserSid();
+
+ // Is it of S-1-5-21 form: Is the issuing authority NT_AUTHORITY and the RID NT_NOT_UNIQUE?
+ SidType sidType = ClassifySID(pCopyOfUserSid);
+
+ if (sidType == SidType.RealObject)
+ {
+ // It's a domain SID. Now, is the domain portion for the local machine, or something else?
+
+ // Get the machine domain SID
+ pMachineDomainSid = GetMachineDomainSid();
+
+ // Does the user SID have the same domain as the machine SID?
+ bool sameDomain = false;
+ bool success = UnsafeNativeMethods.EqualDomainSid(pCopyOfUserSid, pMachineDomainSid, ref sameDomain);
+
+ // Since both pCopyOfUserSid and pMachineDomainSid should always be account SIDs
+ Debug.Assert(success == true);
+
+ // If user SID is the same domain as the machine domain, and the machine is not a DC then the user is a local (machine) user
+ return sameDomain ? !IsMachineDC(null) : false;
+ }
+ else
+ {
+ // It's not a domain SID, must be local (e.g., NT AUTHORITY\foo, or BUILTIN\foo)
+ return true;
+ }
+ }
+ finally
+ {
+ if (pCopyOfUserSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pCopyOfUserSid);
+
+ if (pMachineDomainSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pMachineDomainSid);
+ }
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetCurrentThread():System.IntPtr" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.OpenThreadToken(System.IntPtr,System.Int32,System.Boolean,System.IntPtr&amp;):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetCurrentProcess():System.IntPtr" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.OpenProcessToken(System.IntPtr,System.Int32,System.IntPtr&amp;):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetTokenInformation(System.IntPtr,System.Int32,System.IntPtr,System.Int32,System.Int32&amp;):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.IsValidSid(System.IntPtr):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetLengthSid(System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.CopySid(System.Int32,System.IntPtr,System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.CloseHandle(System.IntPtr):System.Boolean" />
+ //<SatisfiesLinkDemand Name="Marshal.GetLastWin32Error():System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.AllocHGlobal(System.Int32):System.IntPtr" />
+ //<SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ //<SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ internal static IntPtr GetCurrentUserSid()
+ {
+ IntPtr pTokenHandle = IntPtr.Zero;
+ IntPtr pBuffer = IntPtr.Zero;
+
+ try
+ {
+ //
+ // Get the current user's SID
+ //
+ int error = 0;
+
+ // Get the current thread's token
+ if (!UnsafeNativeMethods.OpenThreadToken(
+ UnsafeNativeMethods.GetCurrentThread(),
+ 0x8, // TOKEN_QUERY
+ true,
+ ref pTokenHandle
+ ))
+ {
+ if ((error = Marshal.GetLastWin32Error()) == 1008) // ERROR_NO_TOKEN
+ {
+ Debug.Assert(pTokenHandle == IntPtr.Zero);
+
+ // Current thread doesn't have a token, try the process
+ if (!UnsafeNativeMethods.OpenProcessToken(
+ UnsafeNativeMethods.GetCurrentProcess(),
+ 0x8, // TOKEN_QUERY
+ ref pTokenHandle
+ ))
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ Res.GetString(Res.UnableToOpenToken),
+ lastError));
+ }
+ }
+ else
+ {
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture,
+ Res.GetString(Res.UnableToOpenToken),
+ error));
+ }
+ }
+
+ Debug.Assert(pTokenHandle != IntPtr.Zero);
+
+ int neededBufferSize = 0;
+
+ // Retrieve the user info from the current thread's token
+ // First, determine how big a buffer we need.
+ bool success = UnsafeNativeMethods.GetTokenInformation(
+ pTokenHandle,
+ 1, // TokenUser
+ IntPtr.Zero,
+ 0,
+ ref neededBufferSize);
+
+ int getTokenInfoError = 0;
+ if ((getTokenInfoError = Marshal.GetLastWin32Error()) != 122) // ERROR_INSUFFICIENT_BUFFER
+ {
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, Res.GetString(Res.UnableToRetrieveTokenInfo), getTokenInfoError));
+ }
+
+ // Allocate the necessary buffer.
+ Debug.Assert(neededBufferSize > 0);
+ pBuffer = Marshal.AllocHGlobal(neededBufferSize);
+
+ // Load the user info into the buffer
+ success = UnsafeNativeMethods.GetTokenInformation(
+ pTokenHandle,
+ 1, // TokenUser
+ pBuffer,
+ neededBufferSize,
+ ref neededBufferSize);
+
+ if (!success)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, Res.GetString(Res.UnableToRetrieveTokenInfo), lastError));
+ }
+
+ // Retrieve the user's SID from the user info
+ TOKEN_USER tokenUser = (TOKEN_USER)Marshal.PtrToStructure(pBuffer, typeof(TOKEN_USER));
+ IntPtr pUserSid = tokenUser.sidAndAttributes.pSid; // this is a reference into the NATIVE memory (into pBuffer)
+
+ Debug.Assert(UnsafeNativeMethods.IsValidSid(pUserSid));
+
+ // Now we make a copy of the SID to return
+ int userSidLength = UnsafeNativeMethods.GetLengthSid(pUserSid);
+ IntPtr pCopyOfUserSid = Marshal.AllocHGlobal(userSidLength);
+ success = UnsafeNativeMethods.CopySid(userSidLength, pCopyOfUserSid, pUserSid);
+ if (!success)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, Res.GetString(Res.UnableToRetrieveTokenInfo), lastError));
+ }
+
+ return pCopyOfUserSid;
+ }
+ finally
+ {
+ if (pTokenHandle != IntPtr.Zero)
+ UnsafeNativeMethods.CloseHandle(pTokenHandle);
+
+ if (pBuffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(pBuffer);
+ }
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LsaOpenPolicy(System.IntPtr,System.IntPtr,System.Int32,System.IntPtr&amp;):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="SafeNativeMethods.LsaNtStatusToWinError(System.Int32):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LsaQueryInformationPolicy(System.IntPtr,System.Int32,System.IntPtr&amp;):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.IsValidSid(System.IntPtr):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetLengthSid(System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.CopySid(System.Int32,System.IntPtr,System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LsaClose(System.IntPtr):System.Int32" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.LsaFreeMemory(System.IntPtr):System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.SizeOf(System.Type):System.Int32" />
+ //<SatisfiesLinkDemand Name="Marshal.AllocHGlobal(System.Int32):System.IntPtr" />
+ //<SatisfiesLinkDemand Name="Marshal.StructureToPtr(System.Object,System.IntPtr,System.Boolean):System.Void" />
+ //<SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ //<SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ internal static IntPtr GetMachineDomainSid()
+ {
+ IntPtr pPolicyHandle = IntPtr.Zero;
+ IntPtr pBuffer = IntPtr.Zero;
+ IntPtr pOA = IntPtr.Zero;
+
+ try
+ {
+ LSA_OBJECT_ATTRIBUTES oa = new LSA_OBJECT_ATTRIBUTES();
+
+ pOA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES)));
+ Marshal.StructureToPtr(oa, pOA, false);
+ int err = UnsafeNativeMethods.LsaOpenPolicy(
+ IntPtr.Zero,
+ pOA,
+ 1, // POLICY_VIEW_LOCAL_INFORMATION
+ ref pPolicyHandle);
+
+ if (err != 0)
+ {
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
+ Res.GetString(Res.UnableToRetrievePolicy),
+ NativeMethods.LsaNtStatusToWinError(err)));
+ }
+
+ Debug.Assert(pPolicyHandle != IntPtr.Zero);
+ err = UnsafeNativeMethods.LsaQueryInformationPolicy(
+ pPolicyHandle,
+ 5, // PolicyAccountDomainInformation
+ ref pBuffer);
+
+ if (err != 0)
+ {
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
+ Res.GetString(Res.UnableToRetrievePolicy),
+ NativeMethods.LsaNtStatusToWinError(err)));
+ }
+
+ Debug.Assert(pBuffer != IntPtr.Zero);
+ POLICY_ACCOUNT_DOMAIN_INFO info = (POLICY_ACCOUNT_DOMAIN_INFO)
+ Marshal.PtrToStructure(pBuffer, typeof(POLICY_ACCOUNT_DOMAIN_INFO));
+
+ Debug.Assert(UnsafeNativeMethods.IsValidSid(info.domainSid));
+
+ // Now we make a copy of the SID to return
+ int sidLength = UnsafeNativeMethods.GetLengthSid(info.domainSid);
+ IntPtr pCopyOfSid = Marshal.AllocHGlobal(sidLength);
+ bool success = UnsafeNativeMethods.CopySid(sidLength, pCopyOfSid, info.domainSid);
+ if (!success)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentCulture, Res.GetString(Res.UnableToRetrievePolicy), lastError));
+ }
+
+ return pCopyOfSid;
+ }
+ finally
+ {
+ if (pPolicyHandle != IntPtr.Zero)
+ UnsafeNativeMethods.LsaClose(pPolicyHandle);
+
+ if (pBuffer != IntPtr.Zero)
+ UnsafeNativeMethods.LsaFreeMemory(pBuffer);
+
+ if (pOA != IntPtr.Zero)
+ Marshal.FreeHGlobal(pOA);
+ }
+ }
+
+ // <SecurityKernel TreatAsSafe="Directly applied from MetaData" Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.DsRoleGetPrimaryDomainInformation(System.IntPtr,System.DirectoryServices.AccountManagement.UnsafeNativeMethods+DSROLE_PRIMARY_DOMAIN_INFO_LEVEL,System.IntPtr&):System.Int32" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.DsRoleGetPrimaryDomainInformation(System.String,System.DirectoryServices.AccountManagement.UnsafeNativeMethods+DSROLE_PRIMARY_DOMAIN_INFO_LEVEL,System.IntPtr&):System.Int32" />
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.DsRoleFreeMemory(System.IntPtr):System.Int32" />
+ // <SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ internal static bool IsMachineDC(String computerName)
+ {
+ IntPtr dsRoleInfoPtr = IntPtr.Zero;
+ int err = -1;
+
+ try
+ {
+ if (null == computerName)
+ err = UnsafeNativeMethods.DsRoleGetPrimaryDomainInformation(IntPtr.Zero, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL.DsRolePrimaryDomainInfoBasic, out dsRoleInfoPtr);
+ else
+ err = UnsafeNativeMethods.DsRoleGetPrimaryDomainInformation(computerName, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL.DsRolePrimaryDomainInfoBasic, out dsRoleInfoPtr);
+
+ if (err != 0)
+ {
+ throw new InvalidOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Res.GetString(Res.UnableToRetrieveDomainInfo),
+ err));
+ }
+
+ DSROLE_PRIMARY_DOMAIN_INFO_BASIC dsRolePrimaryDomainInfo =
+ (DSROLE_PRIMARY_DOMAIN_INFO_BASIC)Marshal.PtrToStructure(dsRoleInfoPtr, typeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
+
+ return (dsRolePrimaryDomainInfo.MachineRole == DSROLE_MACHINE_ROLE.DsRole_RoleBackupDomainController ||
+ dsRolePrimaryDomainInfo.MachineRole == DSROLE_MACHINE_ROLE.DsRole_RolePrimaryDomainController);
+ }
+ finally
+ {
+ if (dsRoleInfoPtr != IntPtr.Zero)
+ UnsafeNativeMethods.DsRoleFreeMemory(dsRoleInfoPtr);
+ }
+ }
+
+ //<SecurityKernel Critical="True" Ring="0">
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.IsValidSid(System.IntPtr):System.Boolean" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetSidIdentifierAuthority(System.IntPtr):System.IntPtr" />
+ //<CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetSidSubAuthority(System.IntPtr,System.Int32):System.IntPtr" />
+ //<SatisfiesLinkDemand Name="Marshal.PtrToStructure(System.IntPtr,System.Type):System.Object" />
+ //<SatisfiesLinkDemand Name="Marshal.ReadInt32(System.IntPtr):System.Int32" />
+ //</SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+
+ internal static SidType ClassifySID(IntPtr pSid)
+ {
+ Debug.Assert(UnsafeNativeMethods.IsValidSid(pSid));
+
+ // Get the issuing authority and the first RID
+ IntPtr pIdentAuth = UnsafeNativeMethods.GetSidIdentifierAuthority(pSid);
+
+ SID_IDENTIFIER_AUTHORITY identAuth =
+ (SID_IDENTIFIER_AUTHORITY)Marshal.PtrToStructure(pIdentAuth, typeof(SID_IDENTIFIER_AUTHORITY));
+
+ IntPtr pRid = UnsafeNativeMethods.GetSidSubAuthority(pSid, 0);
+ int rid = Marshal.ReadInt32(pRid);
+
+ // These bit signify that the sid was issued by ADAM. If so then it can't be a fake sid.
+ if ((identAuth.b3 & 0xF0) == 0x10)
+ return SidType.RealObject;
+
+ // Is it S-1-5-...?
+ if (!(identAuth.b1 == 0) &&
+ (identAuth.b2 == 0) &&
+ (identAuth.b3 == 0) &&
+ (identAuth.b4 == 0) &&
+ (identAuth.b5 == 0) &&
+ (identAuth.b6 == 5))
+ {
+ // No, so it can't be a account or builtin SID.
+ // Probably something like \Everyone or \LOCAL.
+ return SidType.FakeObject;
+ }
+
+ switch (rid)
+ {
+ case 21:
+ // Account SID
+ return SidType.RealObject;
+
+ case 32:
+ // BUILTIN SID
+ return SidType.RealObjectFakeDomain;
+
+ default:
+ return SidType.FakeObject;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+
+ internal static int GetLastRidFromSid(IntPtr pSid)
+ {
+ IntPtr pRidCount = UnsafeNativeMethods.GetSidSubAuthorityCount(pSid);
+ int ridCount = Marshal.ReadByte(pRidCount);
+ IntPtr pLastRid = UnsafeNativeMethods.GetSidSubAuthority(pSid, ridCount - 1);
+ int lastRid = Marshal.ReadInt32(pLastRid);
+
+ return lastRid;
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ // <ReferencesCritical Name="Method: ConvertByteArrayToIntPtr(Byte[]):IntPtr" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static int GetLastRidFromSid(byte[] sid)
+ {
+ IntPtr pSid = IntPtr.Zero;
+
+ try
+ {
+ pSid = Utils.ConvertByteArrayToIntPtr(sid);
+ int rid = GetLastRidFromSid(pSid);
+
+ return rid;
+ }
+ finally
+ {
+ if (pSid != IntPtr.Zero)
+ Marshal.FreeHGlobal(pSid);
+ }
+ }
+
+ // The caller must call Marshal.FreeHGlobal on the returned
+ // value to free it.
+ // <SecurityKernel Critical="True" Ring="0">
+ // <SatisfiesLinkDemand Name="Marshal.AllocHGlobal(System.Int32):System.IntPtr" />
+ // <SatisfiesLinkDemand Name="Marshal.Copy(System.Byte[],System.Int32,System.IntPtr,System.Int32):System.Void" />
+ // <SatisfiesLinkDemand Name="Marshal.FreeHGlobal(System.IntPtr):System.Void" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal static IntPtr ConvertByteArrayToIntPtr(byte[] bytes)
+ {
+ IntPtr pBytes = IntPtr.Zero;
+
+ pBytes = Marshal.AllocHGlobal(bytes.Length);
+
+ try
+ {
+ Marshal.Copy(bytes, 0, pBytes, bytes.Length);
+ }
+ catch (Exception)
+ {
+ Marshal.FreeHGlobal(pBytes);
+ throw;
+ }
+
+ Debug.Assert(pBytes != IntPtr.Zero);
+ return pBytes;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/WellKnownDN.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/WellKnownDN.cs
new file mode 100644
index 0000000000..4fb5e5e74c
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/WellKnownDN.cs
@@ -0,0 +1,23 @@
+// 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.ActiveDirectory
+{
+ using System;
+
+ internal enum WellKnownDN : int
+ {
+ RootDSE = 0,
+ DefaultNamingContext = 1,
+ SchemaNamingContext = 2,
+ ConfigurationNamingContext = 3,
+ PartitionsContainer = 4,
+ SitesContainer = 5,
+ SystemContainer = 6,
+ RidManager = 7,
+ Infrastructure = 8,
+ RootDomainNamingContext = 9,
+ Schema = 10
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectorySecurity.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectorySecurity.cs
new file mode 100644
index 0000000000..fe29c2ee4d
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectorySecurity.cs
@@ -0,0 +1,1441 @@
+// 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
+{
+ using System;
+ using System.Security;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.ComponentModel;
+ using System.Security.Principal;
+ using System.Security.AccessControl;
+ using System.Runtime.InteropServices;
+ using System.DirectoryServices.Interop;
+
+ [Flags]
+ public enum ActiveDirectoryRights
+ {
+ Delete = 0x10000,
+ ReadControl = 0x20000,
+ WriteDacl = 0x40000,
+ WriteOwner = 0x80000,
+ Synchronize = 0x100000,
+ AccessSystemSecurity = 0x1000000,
+ GenericRead = ReadControl | ListChildren | ReadProperty | ListObject,
+ GenericWrite = ReadControl | Self | WriteProperty,
+ GenericExecute = ReadControl | ListChildren,
+ GenericAll = Delete | ReadControl | WriteDacl | WriteOwner | CreateChild | DeleteChild | ListChildren | Self | ReadProperty | WriteProperty | DeleteTree | ListObject | ExtendedRight,
+ CreateChild = 0x1,
+ DeleteChild = 0x2,
+ ListChildren = 0x4,
+ Self = 0x8,
+ ReadProperty = 0x10,
+ WriteProperty = 0x20,
+ DeleteTree = 0x40,
+ ListObject = 0x80,
+ ExtendedRight = 0x100
+ }
+
+ public enum ActiveDirectorySecurityInheritance
+ {
+ None = 0,
+ All = 1,
+ Descendents = 2,
+ SelfAndChildren = 3,
+ Children = 4
+ }
+
+ public enum PropertyAccess
+ {
+ Read = 0,
+ Write = 1
+ }
+
+ public class ActiveDirectorySecurity : DirectoryObjectSecurity
+ {
+ private SecurityMasks _securityMaskUsedInRetrieval = SecurityMasks.Owner | SecurityMasks.Group | SecurityMasks.Dacl | SecurityMasks.Sacl;
+
+ #region Constructors
+
+ public ActiveDirectorySecurity()
+ : base()
+ {
+ }
+
+ internal ActiveDirectorySecurity(byte[] sdBinaryForm, SecurityMasks securityMask)
+ : base(new CommonSecurityDescriptor(true, true, sdBinaryForm, 0))
+ {
+ _securityMaskUsedInRetrieval = securityMask;
+ }
+
+ #endregion
+
+ #region Public methods
+
+ //
+ // DiscretionaryAcl related methods
+ //
+
+ public void AddAccessRule(ActiveDirectoryAccessRule rule)
+ {
+ if (!DaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifyDacl));
+ }
+
+ base.AddAccessRule(rule);
+ }
+
+ public void SetAccessRule(ActiveDirectoryAccessRule rule)
+ {
+ if (!DaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifyDacl));
+ }
+
+ base.SetAccessRule(rule);
+ }
+
+ public void ResetAccessRule(ActiveDirectoryAccessRule rule)
+ {
+ if (!DaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifyDacl));
+ }
+
+ base.ResetAccessRule(rule);
+ }
+
+ public void RemoveAccess(IdentityReference identity, AccessControlType type)
+ {
+ if (!DaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifyDacl));
+ }
+
+ //
+ // Create a new rule
+ //
+ ActiveDirectoryAccessRule rule = new ActiveDirectoryAccessRule(
+ identity,
+ ActiveDirectoryRights.GenericRead, // will be ignored
+ type,
+ ActiveDirectorySecurityInheritance.None);
+
+ base.RemoveAccessRuleAll(rule);
+ }
+
+ public bool RemoveAccessRule(ActiveDirectoryAccessRule rule)
+ {
+ if (!DaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifyDacl));
+ }
+
+ return base.RemoveAccessRule(rule);
+ }
+
+ public void RemoveAccessRuleSpecific(ActiveDirectoryAccessRule rule)
+ {
+ if (!DaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifyDacl));
+ }
+
+ base.RemoveAccessRuleSpecific(rule);
+ }
+
+ public override bool ModifyAccessRule(AccessControlModification modification, AccessRule rule, out bool modified)
+ {
+ if (!DaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifyDacl));
+ }
+
+ return base.ModifyAccessRule(modification, rule, out modified);
+ }
+
+ public override void PurgeAccessRules(IdentityReference identity)
+ {
+ if (!DaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifyDacl));
+ }
+
+ base.PurgeAccessRules(identity);
+ }
+
+ //
+ // SystemAcl related methods
+ //
+ public void AddAuditRule(ActiveDirectoryAuditRule rule)
+ {
+ if (!SaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifySacl));
+ }
+
+ base.AddAuditRule(rule);
+ }
+
+ public void SetAuditRule(ActiveDirectoryAuditRule rule)
+ {
+ if (!SaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifySacl));
+ }
+
+ base.SetAuditRule(rule);
+ }
+
+ public void RemoveAudit(IdentityReference identity)
+ {
+ if (!SaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifySacl));
+ }
+
+ //
+ // Create a new rule
+ //
+ ActiveDirectoryAuditRule rule = new ActiveDirectoryAuditRule(
+ identity,
+ ActiveDirectoryRights.GenericRead, // will be ignored
+ AuditFlags.Success | AuditFlags.Failure,
+ ActiveDirectorySecurityInheritance.None);
+
+ base.RemoveAuditRuleAll(rule);
+ }
+
+ public bool RemoveAuditRule(ActiveDirectoryAuditRule rule)
+ {
+ if (!SaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifySacl));
+ }
+
+ return base.RemoveAuditRule(rule);
+ }
+
+ public void RemoveAuditRuleSpecific(ActiveDirectoryAuditRule rule)
+ {
+ if (!SaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifySacl));
+ }
+
+ base.RemoveAuditRuleSpecific(rule);
+ }
+
+ public override bool ModifyAuditRule(AccessControlModification modification, AuditRule rule, out bool modified)
+ {
+ if (!SaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifySacl));
+ }
+
+ return base.ModifyAuditRule(modification, rule, out modified);
+ }
+
+ public override void PurgeAuditRules(IdentityReference identity)
+ {
+ if (!SaclRetrieved())
+ {
+ throw new InvalidOperationException(Res.GetString(Res.CannotModifySacl));
+ }
+
+ base.PurgeAuditRules(identity);
+ }
+
+ #endregion
+
+ #region Factories
+
+ public sealed override AccessRule AccessRuleFactory(
+ IdentityReference identityReference,
+ int accessMask,
+ bool isInherited,
+ InheritanceFlags inheritanceFlags,
+ PropagationFlags propagationFlags,
+ AccessControlType type)
+ {
+ return new ActiveDirectoryAccessRule(
+ identityReference,
+ accessMask,
+ type,
+ Guid.Empty,
+ isInherited,
+ inheritanceFlags,
+ propagationFlags,
+ Guid.Empty);
+ }
+
+ public sealed override AccessRule AccessRuleFactory(
+ IdentityReference identityReference,
+ int accessMask,
+ bool isInherited,
+ InheritanceFlags inheritanceFlags,
+ PropagationFlags propagationFlags,
+ AccessControlType type,
+ Guid objectGuid,
+ Guid inheritedObjectGuid)
+ {
+ return new ActiveDirectoryAccessRule(
+ identityReference,
+ accessMask,
+ type,
+ objectGuid,
+ isInherited,
+ inheritanceFlags,
+ propagationFlags,
+ inheritedObjectGuid);
+ }
+
+ public sealed override AuditRule AuditRuleFactory(
+ IdentityReference identityReference,
+ int accessMask,
+ bool isInherited,
+ InheritanceFlags inheritanceFlags,
+ PropagationFlags propagationFlags,
+ AuditFlags flags)
+ {
+ return new ActiveDirectoryAuditRule(
+ identityReference,
+ accessMask,
+ flags,
+ Guid.Empty,
+ isInherited,
+ inheritanceFlags,
+ propagationFlags,
+ Guid.Empty);
+ }
+
+ public sealed override AuditRule AuditRuleFactory(
+ IdentityReference identityReference,
+ int accessMask,
+ bool isInherited,
+ InheritanceFlags inheritanceFlags,
+ PropagationFlags propagationFlags,
+ AuditFlags flags,
+ Guid objectGuid,
+ Guid inheritedObjectGuid)
+ {
+ return new ActiveDirectoryAuditRule(
+ identityReference,
+ accessMask,
+ flags,
+ objectGuid,
+ isInherited,
+ inheritanceFlags,
+ propagationFlags,
+ inheritedObjectGuid);
+ }
+
+ internal bool IsModified()
+ {
+ ReadLock();
+
+ try
+ {
+ return (OwnerModified || GroupModified || AccessRulesModified || AuditRulesModified);
+ }
+ finally
+ {
+ ReadUnlock();
+ }
+ }
+
+ private bool DaclRetrieved()
+ {
+ return ((_securityMaskUsedInRetrieval & SecurityMasks.Dacl) != 0);
+ }
+
+ private bool SaclRetrieved()
+ {
+ return ((_securityMaskUsedInRetrieval & SecurityMasks.Sacl) != 0);
+ }
+
+ #endregion
+
+ #region some overrides
+ public override Type AccessRightType
+ {
+ get { return typeof(System.DirectoryServices.ActiveDirectoryRights); }
+ }
+
+ public override Type AccessRuleType
+ {
+ get { return typeof(System.DirectoryServices.ActiveDirectoryAccessRule); }
+ }
+
+ public override Type AuditRuleType
+ {
+ get { return typeof(System.DirectoryServices.ActiveDirectoryAuditRule); }
+ }
+ #endregion
+
+ }
+
+ internal sealed class ActiveDirectoryRightsTranslator
+ {
+ #region Access mask to rights translation
+
+ internal static int AccessMaskFromRights(ActiveDirectoryRights adRights)
+ {
+ return (int)adRights;
+ }
+ internal static ActiveDirectoryRights RightsFromAccessMask(int accessMask)
+ {
+ return (ActiveDirectoryRights)accessMask;
+ }
+
+ #endregion
+ }
+
+ internal sealed class PropertyAccessTranslator
+ {
+ #region PropertyAccess to access mask translation
+
+ internal static int AccessMaskFromPropertyAccess(PropertyAccess access)
+ {
+ int accessMask = 0;
+
+ if (access < PropertyAccess.Read || access > PropertyAccess.Write)
+ {
+ throw new InvalidEnumArgumentException("access", (int)access, typeof(PropertyAccess));
+ }
+
+ switch (access)
+ {
+ case PropertyAccess.Read:
+ {
+ accessMask = ActiveDirectoryRightsTranslator.AccessMaskFromRights(ActiveDirectoryRights.ReadProperty);
+ break;
+ }
+
+ case PropertyAccess.Write:
+ {
+ accessMask = ActiveDirectoryRightsTranslator.AccessMaskFromRights(ActiveDirectoryRights.WriteProperty);
+ break;
+ }
+
+ default:
+
+ //
+ // This should not happen. Indicates a problem with the
+ // internal logic.
+ //
+ Debug.Fail("Invalid PropertyAccess value");
+ throw new ArgumentException("access");
+ }
+ return accessMask;
+ }
+
+ #endregion
+ }
+
+ internal sealed class ActiveDirectoryInheritanceTranslator
+ {
+ #region ActiveDirectorySecurityInheritance to Inheritance/Propagation flags translation
+
+ //
+ // InheritanceType InheritanceFlags PropagationFlags
+ // ------------------------------------------------------------------------------
+ // None None None
+ // All ContainerInherit None
+ // Descendents ContainerInherit InheritOnly
+ // SelfAndChildren ContainerInherit NoPropogateInherit
+ // Children ContainerInherit InheritOnly | NoPropagateInherit
+ //
+ internal static InheritanceFlags[] ITToIF = new InheritanceFlags[] {
+ InheritanceFlags.None,
+ InheritanceFlags.ContainerInherit,
+ InheritanceFlags.ContainerInherit,
+ InheritanceFlags.ContainerInherit,
+ InheritanceFlags.ContainerInherit
+ };
+
+ internal static PropagationFlags[] ITToPF = new PropagationFlags[] {
+ PropagationFlags.None,
+ PropagationFlags.None,
+ PropagationFlags.InheritOnly,
+ PropagationFlags.NoPropagateInherit,
+ PropagationFlags.InheritOnly | PropagationFlags.NoPropagateInherit
+ };
+
+ internal static InheritanceFlags GetInheritanceFlags(ActiveDirectorySecurityInheritance inheritanceType)
+ {
+ if (inheritanceType < ActiveDirectorySecurityInheritance.None || inheritanceType > ActiveDirectorySecurityInheritance.Children)
+ {
+ throw new InvalidEnumArgumentException("inheritanceType", (int)inheritanceType, typeof(ActiveDirectorySecurityInheritance));
+ }
+
+ return ITToIF[(int)inheritanceType];
+ }
+
+ internal static PropagationFlags GetPropagationFlags(ActiveDirectorySecurityInheritance inheritanceType)
+ {
+ if (inheritanceType < ActiveDirectorySecurityInheritance.None || inheritanceType > ActiveDirectorySecurityInheritance.Children)
+ {
+ throw new InvalidEnumArgumentException("inheritanceType", (int)inheritanceType, typeof(ActiveDirectorySecurityInheritance));
+ }
+
+ return ITToPF[(int)inheritanceType];
+ }
+
+ internal static ActiveDirectorySecurityInheritance GetEffectiveInheritanceFlags(InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
+ {
+ ActiveDirectorySecurityInheritance inheritanceType = ActiveDirectorySecurityInheritance.None;
+
+ if ((inheritanceFlags & InheritanceFlags.ContainerInherit) != 0)
+ {
+ switch (propagationFlags)
+ {
+ case PropagationFlags.None:
+ {
+ inheritanceType = ActiveDirectorySecurityInheritance.All;
+ break;
+ }
+
+ case PropagationFlags.InheritOnly:
+ {
+ inheritanceType = ActiveDirectorySecurityInheritance.Descendents;
+ break;
+ }
+
+ case PropagationFlags.NoPropagateInherit:
+ {
+ inheritanceType = ActiveDirectorySecurityInheritance.SelfAndChildren;
+ break;
+ }
+
+ case PropagationFlags.InheritOnly | PropagationFlags.NoPropagateInherit:
+ {
+ inheritanceType = ActiveDirectorySecurityInheritance.Children;
+ break;
+ }
+
+ default:
+
+ //
+ // This should not happen. Indicates a problem with the
+ // internal logic.
+ //
+ Debug.Fail("Invalid PropagationFlags value");
+ throw new ArgumentException("propagationFlags");
+ }
+ }
+
+ return inheritanceType;
+ }
+
+ #endregion
+ }
+
+ public class ActiveDirectoryAccessRule : ObjectAccessRule
+ {
+ #region Constructors
+
+ public ActiveDirectoryAccessRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AccessControlType type)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ type,
+ Guid.Empty,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty
+ )
+ {
+ }
+
+ public ActiveDirectoryAccessRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AccessControlType type,
+ Guid objectType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ type,
+ objectType,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public ActiveDirectoryAccessRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ type,
+ Guid.Empty,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public ActiveDirectoryAccessRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AccessControlType type,
+ Guid objectType,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ type,
+ objectType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public ActiveDirectoryAccessRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ type,
+ Guid.Empty,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ public ActiveDirectoryAccessRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AccessControlType type,
+ Guid objectType,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ type,
+ objectType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ internal ActiveDirectoryAccessRule(
+ IdentityReference identity,
+ int accessMask,
+ AccessControlType type,
+ Guid objectType,
+ bool isInherited,
+ InheritanceFlags inheritanceFlags,
+ PropagationFlags propagationFlags,
+ Guid inheritedObjectType
+ )
+ : base(identity,
+ accessMask,
+ isInherited,
+ inheritanceFlags,
+ propagationFlags,
+ objectType,
+ inheritedObjectType,
+ type)
+ {
+ }
+
+ #endregion constructors
+
+ #region Public properties
+
+ public ActiveDirectoryRights ActiveDirectoryRights
+ {
+ get
+ {
+ return ActiveDirectoryRightsTranslator.RightsFromAccessMask(base.AccessMask);
+ }
+ }
+
+ public ActiveDirectorySecurityInheritance InheritanceType
+ {
+ get
+ {
+ return ActiveDirectoryInheritanceTranslator.GetEffectiveInheritanceFlags(base.InheritanceFlags, base.PropagationFlags);
+ }
+ }
+
+ #endregion
+ }
+
+ public sealed class ListChildrenAccessRule : ActiveDirectoryAccessRule
+ {
+ #region Constructors
+
+ public ListChildrenAccessRule(
+ IdentityReference identity,
+ AccessControlType type)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.ListChildren,
+ type,
+ Guid.Empty,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty
+ )
+ {
+ }
+
+ public ListChildrenAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.ListChildren,
+ type,
+ Guid.Empty,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public ListChildrenAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.ListChildren,
+ type,
+ Guid.Empty,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ #endregion constructors
+ }
+
+ public sealed class CreateChildAccessRule : ActiveDirectoryAccessRule
+ {
+ #region Constructors
+
+ public CreateChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.CreateChild,
+ type,
+ Guid.Empty, // all child objects
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public CreateChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ Guid childType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.CreateChild,
+ type,
+ childType,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public CreateChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.CreateChild,
+ type,
+ Guid.Empty, // all child objects
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public CreateChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ Guid childType,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.CreateChild,
+ type,
+ childType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public CreateChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.CreateChild,
+ type,
+ Guid.Empty, // all child objects
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ public CreateChildAccessRule(
+ IdentityReference identity, AccessControlType type,
+ Guid childType,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.CreateChild,
+ type,
+ childType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ #endregion constructors
+ }
+
+ public sealed class DeleteChildAccessRule : ActiveDirectoryAccessRule
+ {
+ #region Constructors
+
+ public DeleteChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.DeleteChild,
+ type,
+ Guid.Empty, // all child objects
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public DeleteChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ Guid childType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.DeleteChild,
+ type,
+ childType,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public DeleteChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.DeleteChild,
+ type,
+ Guid.Empty, // all child objects
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public DeleteChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ Guid childType,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.DeleteChild,
+ type,
+ childType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public DeleteChildAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.DeleteChild,
+ type,
+ Guid.Empty, // all child objects
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ public DeleteChildAccessRule(
+ IdentityReference identity, AccessControlType type,
+ Guid childType,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.DeleteChild,
+ type,
+ childType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+ #endregion constructors
+ }
+
+ public sealed class PropertyAccessRule : ActiveDirectoryAccessRule
+ {
+ #region Constructors
+
+ public PropertyAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ PropertyAccess access)
+ : base(
+ identity,
+ (int)PropertyAccessTranslator.AccessMaskFromPropertyAccess(access),
+ type,
+ Guid.Empty, // all properties
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public PropertyAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ PropertyAccess access,
+ Guid propertyType)
+ : base(
+ identity,
+ (int)PropertyAccessTranslator.AccessMaskFromPropertyAccess(access),
+ type,
+ propertyType,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public PropertyAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ PropertyAccess access,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)PropertyAccessTranslator.AccessMaskFromPropertyAccess(access),
+ type,
+ Guid.Empty, // all properties
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public PropertyAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ PropertyAccess access,
+ Guid propertyType,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)PropertyAccessTranslator.AccessMaskFromPropertyAccess(access),
+ type,
+ propertyType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public PropertyAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ PropertyAccess access,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)PropertyAccessTranslator.AccessMaskFromPropertyAccess(access),
+ type,
+ Guid.Empty, // all properties
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ public PropertyAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ PropertyAccess access,
+ Guid propertyType,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)PropertyAccessTranslator.AccessMaskFromPropertyAccess(access),
+ type,
+ propertyType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ #endregion constructors
+ }
+
+ public sealed class PropertySetAccessRule : ActiveDirectoryAccessRule
+ {
+ #region Constructors
+
+ public PropertySetAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ PropertyAccess access,
+ Guid propertySetType)
+ : base(
+ identity,
+ (int)PropertyAccessTranslator.AccessMaskFromPropertyAccess(access),
+ type,
+ propertySetType,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public PropertySetAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ PropertyAccess access,
+ Guid propertySetType,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)PropertyAccessTranslator.AccessMaskFromPropertyAccess(access),
+ type,
+ propertySetType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public PropertySetAccessRule(IdentityReference identity,
+ AccessControlType type,
+ PropertyAccess access,
+ Guid propertySetType,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)PropertyAccessTranslator.AccessMaskFromPropertyAccess(access),
+ type,
+ propertySetType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ #endregion constructors
+ }
+
+ public sealed class ExtendedRightAccessRule : ActiveDirectoryAccessRule
+ {
+ #region Constructors
+
+ public ExtendedRightAccessRule(
+ IdentityReference identity,
+ AccessControlType type)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.ExtendedRight,
+ type,
+ Guid.Empty, // all extended rights
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public ExtendedRightAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ Guid extendedRightType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.ExtendedRight,
+ type,
+ extendedRightType,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public ExtendedRightAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.ExtendedRight,
+ type,
+ Guid.Empty, // all extended rights
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public ExtendedRightAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ Guid extendedRightType,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.ExtendedRight,
+ type,
+ extendedRightType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public ExtendedRightAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.ExtendedRight,
+ type,
+ Guid.Empty, // all extended rights
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ public ExtendedRightAccessRule(IdentityReference identity,
+ AccessControlType type,
+ Guid extendedRightType,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.ExtendedRight,
+ type,
+ extendedRightType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ #endregion constructors
+ }
+
+ public sealed class DeleteTreeAccessRule : ActiveDirectoryAccessRule
+ {
+ #region Constructors
+
+ public DeleteTreeAccessRule(
+ IdentityReference identity,
+ AccessControlType type)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.DeleteTree,
+ type,
+ Guid.Empty,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public DeleteTreeAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.DeleteTree,
+ type,
+ Guid.Empty,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public DeleteTreeAccessRule(
+ IdentityReference identity,
+ AccessControlType type,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : base(
+ identity,
+ (int)ActiveDirectoryRights.DeleteTree,
+ type,
+ Guid.Empty,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ #endregion constructors
+ }
+
+ public class ActiveDirectoryAuditRule : ObjectAuditRule
+ {
+ #region Constructors
+
+ public ActiveDirectoryAuditRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AuditFlags auditFlags)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ auditFlags,
+ Guid.Empty,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty
+ )
+ {
+ }
+
+ public ActiveDirectoryAuditRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AuditFlags auditFlags,
+ Guid objectType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ auditFlags,
+ objectType,
+ false,
+ InheritanceFlags.None,
+ PropagationFlags.None,
+ Guid.Empty)
+ {
+ }
+
+ public ActiveDirectoryAuditRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AuditFlags auditFlags,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ auditFlags,
+ Guid.Empty,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public ActiveDirectoryAuditRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AuditFlags auditFlags,
+ Guid objectType,
+ ActiveDirectorySecurityInheritance inheritanceType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ auditFlags,
+ objectType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ Guid.Empty)
+ {
+ }
+
+ public ActiveDirectoryAuditRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AuditFlags auditFlags,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ auditFlags,
+ Guid.Empty,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ public ActiveDirectoryAuditRule(
+ IdentityReference identity,
+ ActiveDirectoryRights adRights,
+ AuditFlags auditFlags,
+ Guid objectType,
+ ActiveDirectorySecurityInheritance inheritanceType,
+ Guid inheritedObjectType)
+ : this(
+ identity,
+ ActiveDirectoryRightsTranslator.AccessMaskFromRights(adRights),
+ auditFlags,
+ objectType,
+ false,
+ ActiveDirectoryInheritanceTranslator.GetInheritanceFlags(inheritanceType),
+ ActiveDirectoryInheritanceTranslator.GetPropagationFlags(inheritanceType),
+ inheritedObjectType)
+ {
+ }
+
+ internal ActiveDirectoryAuditRule(
+ IdentityReference identity,
+ int accessMask,
+ AuditFlags auditFlags,
+ Guid objectGuid,
+ bool isInherited,
+ InheritanceFlags inheritanceFlags,
+ PropagationFlags propagationFlags,
+ Guid inheritedObjectType
+ )
+ : base(identity,
+ accessMask,
+ isInherited,
+ inheritanceFlags,
+ propagationFlags,
+ objectGuid,
+ inheritedObjectType,
+ auditFlags)
+ {
+ }
+
+ #endregion constructors
+
+ #region Public properties
+
+ public ActiveDirectoryRights ActiveDirectoryRights
+ {
+ get
+ {
+ return ActiveDirectoryRightsTranslator.RightsFromAccessMask(base.AccessMask);
+ }
+ }
+
+ public ActiveDirectorySecurityInheritance InheritanceType
+ {
+ get
+ {
+ return ActiveDirectoryInheritanceTranslator.GetEffectiveInheritanceFlags(base.InheritanceFlags, base.PropagationFlags);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/AdsVLV.cs b/src/System.DirectoryServices/src/System/DirectoryServices/AdsVLV.cs
new file mode 100644
index 0000000000..f1c9eee281
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/AdsVLV.cs
@@ -0,0 +1,21 @@
+// 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
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class AdsVLV
+ {
+ public int beforeCount;
+ public int afterCount;
+ public int offset;
+ public int contentCount;
+ public IntPtr target;
+ public int contextIDlength;
+ public IntPtr contextID;
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/AuthenticationTypes.cs b/src/System.DirectoryServices/src/System/DirectoryServices/AuthenticationTypes.cs
new file mode 100644
index 0000000000..728fdeba97
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/AuthenticationTypes.cs
@@ -0,0 +1,93 @@
+// 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
+{
+ using System;
+ using System.DirectoryServices.Interop;
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Specifies what kind of acknowledgment to get after sending a message.
+ /// </para>
+ /// </devdoc>
+ [Flags]
+ public enum AuthenticationTypes
+ {
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.None"]/*' />
+ None = 0,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.Secure"]/*' />
+ /// <devdoc>
+ /// Requests secure authentication. When this flag is set, the WinNT provider uses NT LAN Manager (NTLM)
+ /// to authenticate the client. Active Directory will use Kerberos, and possibly NTLM, to authenticate the client.
+ /// </devdoc>
+ Secure = NativeMethods.AuthenticationModes.SecureAuthentication,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.Encription"]/*' />
+ /// <devdoc>
+ /// Forces ADSI to use encryption for data exchange over the network.
+ /// </devdoc>
+ Encryption = NativeMethods.AuthenticationModes.UseEncryption,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.SecureSocketsLayer"]/*' />
+ /// <devdoc>
+ /// Encrypts the channel with SSL. Data will be encrypted using SSL. Active Directory requires that the
+ /// Certificate Server be installed to support SSL encryption.
+ /// </devdoc>
+ SecureSocketsLayer = NativeMethods.AuthenticationModes.UseSSL,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.ReadonlyServer"]/*' />
+ /// <devdoc>
+ /// For a WinNT provider, ADSI tries to connect to a primary domain controller or a backup domain
+ /// controller. For Active Directory, this flag indicates that a writeable server is not required for a
+ /// serverless binding.
+ /// </devdoc>
+ ReadonlyServer = NativeMethods.AuthenticationModes.ReadonlyServer,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.Anonymous"]/*' />
+ /// <devdoc>
+ /// Request no authentication. The providers may attempt to bind client, as an anonymous user, to the targeted
+ /// object. The WinNT provider does not support this flag. Active Directory establishes a connection between
+ /// the client and the targeted object, but will not perform any authentication. Setting this flag amounts to
+ /// requesting an anonymous binding, which means "Everyone" as the security context.
+ /// </devdoc>
+ Anonymous = NativeMethods.AuthenticationModes.NoAuthentication,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.FastBind"]/*' />
+ /// <devdoc>
+ /// When this flag is set, ADSI will not attempt to query the objectClass property and thus will only expose
+ /// the base interfaces supported by all ADSI objects instead of the full object support.
+ /// </devdoc>
+ FastBind = NativeMethods.AuthenticationModes.FastBind,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.Signing"]/*' />
+ /// <devdoc>
+ /// Verifies data integrity to ensure the data received is the same as the data sent. The Secure flag
+ /// must be set also in order to use the signing.
+ /// </devdoc>
+ Signing = NativeMethods.AuthenticationModes.UseSigning,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.Sealing"]/*' />
+ /// <devdoc>
+ /// Encrypts data using Kerberos. The Secure flag must be set also in order to use the sealing.
+ /// </devdoc>
+ Sealing = NativeMethods.AuthenticationModes.UseSealing,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.Delegation"]/*' />
+ /// <devdoc>
+ /// Enables ADSI to delegate the user's security context, which is necessary for moving objects across domains.
+ /// </devdoc>
+ Delegation = NativeMethods.AuthenticationModes.UseDelegation,
+
+ /// <include file='doc\AuthenticationTypes.uex' path='docs/doc[@for="AuthenticationTypes.ServerBind"]/*' />
+ /// <devdoc>
+ /// Specify this flag when using the LDAP provider if your ADsPath includes a server name. Do not use
+ /// this flag for paths that include a domain name or for serverless paths.
+ /// </devdoc>
+ ServerBind = NativeMethods.AuthenticationModes.UseServerBinding
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/BinaryCompatibility.cs b/src/System.DirectoryServices/src/System/DirectoryServices/BinaryCompatibility.cs
new file mode 100644
index 0000000000..74df9bbb71
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/BinaryCompatibility.cs
@@ -0,0 +1,45 @@
+// 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.Security;
+using System.Reflection;
+using System.Security.Permissions;
+using System.Runtime.Versioning;
+
+namespace System.DirectoryServices
+{
+ // This class uses reflection on System.Runtime.Versioning.BinaryCompatibility type.
+ internal static class BinaryCompatibility
+ {
+ internal static bool TargetsAtLeast_Desktop_V4_5_3 { get { return s_targetsAtLeast_Desktop_V4_5_3; } }
+
+ private static bool s_targetsAtLeast_Desktop_V4_5_3 = RunningOnCheck("TargetsAtLeast_Desktop_V4_5_3");
+
+ [SecuritySafeCritical]
+ [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)]
+ private static bool RunningOnCheck(string propertyName)
+ {
+ Type binaryCompatabilityType;
+
+ try
+ {
+ binaryCompatabilityType = typeof(Object).GetTypeInfo().Assembly.GetType("System.Runtime.Versioning.BinaryCompatibility", false);
+ }
+ catch (TypeLoadException)
+ {
+ return false;
+ }
+
+ if (binaryCompatabilityType == null)
+ return false;
+
+ PropertyInfo runningOnProperty = binaryCompatabilityType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+ if (runningOnProperty == null)
+ return false;
+
+ return (bool)runningOnProperty.GetValue(null);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DerefAlias.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DerefAlias.cs
new file mode 100644
index 0000000000..3bbb5e41ce
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DerefAlias.cs
@@ -0,0 +1,27 @@
+// 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
+{
+ /// <include file='doc\DerefAlias.uex' path='docs/doc[@for="DerefAlias"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Specifies the behavior in which aliases are dereferenced.
+ /// </para>
+ /// </devdoc>
+ public enum DereferenceAlias
+ {
+ /// <include file='doc\DerefAlias.uex' path='docs/doc[@for="DerefAlias.Never"]/*' />
+ Never = 0,
+
+ /// <include file='doc\DerefAlias.uex' path='docs/doc[@for="DerefAlias.Searching"]/*' />
+ InSearching = 1,
+
+ /// <include file='doc\DerefAlias.uex' path='docs/doc[@for="DerefAlias.Finding"]/*' />
+ FindingBaseObject = 2,
+
+ /// <include file='doc\DerefAlias.uex' path='docs/doc[@for="DerefAlias.Always"]/*' />
+ Always = 3
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/Design/DirectoryEntryConverter.cs b/src/System.DirectoryServices/src/System/DirectoryServices/Design/DirectoryEntryConverter.cs
new file mode 100644
index 0000000000..e292e726fe
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/Design/DirectoryEntryConverter.cs
@@ -0,0 +1,122 @@
+// 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.Design
+{
+ using System.ComponentModel;
+ using System.ComponentModel.Design;
+ using System;
+ using System.Reflection;
+ using System.Collections;
+ using System.Collections.Specialized;
+ using System.Globalization;
+
+ /// <include file='doc\DirectoryEntryConverter.uex' path='docs/doc[@for="DirectoryEntryConverter"]/*' />
+ /// <internalonly/>
+ internal class DirectoryEntryConverter : TypeConverter
+ {
+ private static StandardValuesCollection s_values;
+ private static Hashtable s_componentsCreated = new Hashtable(StringComparer.OrdinalIgnoreCase);
+
+ /// <include file='doc\DirectoryEntryConverter.uex' path='docs/doc[@for="DirectoryEntryConverter.CanConvertFrom"]/*' />
+ /// <internalonly/>
+ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+ {
+ if (sourceType == typeof(string))
+ {
+ return true;
+ }
+ return base.CanConvertFrom(context, sourceType);
+ }
+
+ /// <include file='doc\DirectoryEntryConverter.uex' path='docs/doc[@for="DirectoryEntryConverter.ConvertFrom"]/*' />
+ /// <internalonly/>
+ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
+ {
+ if (value != null && value is string)
+ {
+ string text = ((string)value).Trim();
+
+ if (text.Length == 0)
+ return null;
+
+ if (text.CompareTo(Res.GetString(Res.DSNotSet)) != 0)
+ {
+ DirectoryEntry newEntry = GetFromCache(text);
+ if (newEntry == null)
+ {
+ newEntry = new DirectoryEntry(text);
+ s_componentsCreated[text] = newEntry;
+ if (context != null)
+ context.Container.Add(newEntry);
+
+ return newEntry;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /// <include file='doc\DirectoryEntryConverter.uex' path='docs/doc[@for="DirectoryEntryConverter.ConvertTo"]/*' />
+ /// <internalonly/>
+ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
+ {
+ if (destinationType != null && destinationType == typeof(string))
+ {
+ if (value != null)
+ return ((DirectoryEntry)value).Path;
+ else
+ return Res.GetString(Res.DSNotSet);
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ /// <include file='doc\MessageFormatterConverter.uex' path='docs/doc[@for="DirectoryEntryConverter.GetStandardValues"]/*' />
+ /// <internalonly/>
+ public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
+ {
+ if (s_values == null)
+ {
+ s_values = new StandardValuesCollection(new object[] { null });
+ }
+ return s_values;
+ }
+
+ internal static DirectoryEntry GetFromCache(string path)
+ {
+ if (s_componentsCreated.ContainsKey(path))
+ {
+ DirectoryEntry existingComponent = (DirectoryEntry)s_componentsCreated[path];
+ if (existingComponent.Site == null)
+ s_componentsCreated.Remove(path);
+ else
+ {
+ if (existingComponent.Path == path)
+ return existingComponent;
+ else
+ s_componentsCreated.Remove(path);
+ }
+ }
+
+ return null;
+ }
+
+ /// <include file='doc\MessageFormatterConverter.uex' path='docs/doc[@for="DirectoryEntryConverter.GetStandardValuesExclusive"]/*' />
+ /// <internalonly/>
+ public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
+ {
+ return false;
+ }
+
+ /// <include file='doc\MessageFormatterConverter.uex' path='docs/doc[@for="DirectoryEntryConverter.GetStandardValuesSupported"]/*' />
+ /// <internalonly/>
+ public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
+ {
+ return true;
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryDescriptionAttribute.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryDescriptionAttribute.cs
new file mode 100644
index 0000000000..809fe252a1
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryDescriptionAttribute.cs
@@ -0,0 +1,47 @@
+// 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
+{
+ using System;
+ using System.ComponentModel;
+
+ /// <include file='doc\DirectoryDescriptionAttribute.uex' path='docs/doc[@for="DSDescriptionAttribute"]/*' />
+ /// <internalonly/>
+ /// <devdoc>
+ /// <para>DescriptionAttribute marks a property, event, or extender with a
+ /// description. Visual designers can display this description when referencing
+ /// the member.</para>
+ /// </devdoc>
+ [AttributeUsage(AttributeTargets.All)]
+ public class DSDescriptionAttribute : DescriptionAttribute
+ {
+ private bool _replaced = false;
+
+ /// <include file='doc\DirectoryDescriptionAttribute.uex' path='docs/doc[@for="DSDescriptionAttribute.DSDescriptionAttribute"]/*' />
+ /// <devdoc>
+ /// Constructs a new sys description.
+ /// </devdoc>
+ public DSDescriptionAttribute(string description) : base(description)
+ {
+ }
+
+ /// <include file='doc\DirectoryDescriptionAttribute.uex' path='docs/doc[@for="DSDescriptionAttribute.Description"]/*' />
+ /// <devdoc>
+ /// Retrieves the description text.
+ /// </devdoc>
+ public override string Description
+ {
+ get
+ {
+ if (!_replaced)
+ {
+ _replaced = true;
+ DescriptionValue = Res.GetString(base.Description);
+ }
+ return base.Description;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntries.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntries.cs
new file mode 100644
index 0000000000..93da1e0aae
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntries.cs
@@ -0,0 +1,204 @@
+// 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
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.DirectoryServices.Interop;
+ using System.Security.Permissions;
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries"]/*' />
+ /// <devdoc>
+ /// <para>Contains the children (child entries) of an entry in the Active Directory.</para>
+ /// </devdoc>
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class DirectoryEntries : IEnumerable
+ {
+ // the parent of the children in this collection
+ private DirectoryEntry _container;
+
+ internal DirectoryEntries(DirectoryEntry parent)
+ {
+ _container = parent;
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.SchemaFilter"]/*' />
+ /// <devdoc>
+ /// <para>Gets the schemas that specify which children are shown.</para>
+ /// </devdoc>
+ public SchemaNameCollection SchemaFilter
+ {
+ get
+ {
+ CheckIsContainer();
+ SchemaNameCollection.FilterDelegateWrapper filter = new SchemaNameCollection.FilterDelegateWrapper(_container.ContainerObject);
+ return new SchemaNameCollection(filter.Getter, filter.Setter);
+ }
+ }
+
+ private void CheckIsContainer()
+ {
+ if (!_container.IsContainer)
+ throw new InvalidOperationException(Res.GetString(Res.DSNotAContainer, _container.Path));
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.Add"]/*' />
+ /// <devdoc>
+ /// <para>Creates a request to create a new entry in the container.</para>
+ /// </devdoc>
+ public DirectoryEntry Add(string name, string schemaClassName)
+ {
+ CheckIsContainer();
+ object newChild = _container.ContainerObject.Create(schemaClassName, name);
+ DirectoryEntry entry = new DirectoryEntry(newChild, _container.UsePropertyCache, _container.GetUsername(), _container.GetPassword(), _container.AuthenticationType);
+ entry.JustCreated = true; // suspend writing changes until CommitChanges() is called
+ return entry;
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.Find"]/*' />
+ /// <devdoc>
+ /// <para>Returns the child with the given name.</para>
+ /// </devdoc>
+ public DirectoryEntry Find(string name)
+ {
+ // For IIS: and WinNT: providers schemaClassName == "" does general search.
+ return Find(name, null);
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.Find1"]/*' />
+ /// <devdoc>
+ /// <para>Returns the child with the given name and of the given type.</para>
+ /// </devdoc>
+ public DirectoryEntry Find(string name, string schemaClassName)
+ {
+ CheckIsContainer();
+ // Note: schemaClassName == null does not work for IIS: provider.
+ object o = null;
+ try
+ {
+ o = _container.ContainerObject.GetObject(schemaClassName, name);
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ return new DirectoryEntry(o, _container.UsePropertyCache, _container.GetUsername(), _container.GetPassword(), _container.AuthenticationType);
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.Remove"]/*' />
+ /// <devdoc>
+ /// <para>Deletes a child <see cref='System.DirectoryServices.DirectoryEntry'/> from this collection.</para>
+ /// </devdoc>
+ public void Remove(DirectoryEntry entry)
+ {
+ CheckIsContainer();
+ try
+ {
+ _container.ContainerObject.Delete(entry.SchemaClassName, entry.Name);
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.GetEnumerator"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public IEnumerator GetEnumerator()
+ {
+ return new ChildEnumerator(_container);
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.ChildEnumerator"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Supports a simple ForEach-style iteration over a collection and defines
+ /// enumerators, size, and synchronization methods.
+ /// </para>
+ /// </devdoc>
+ private class ChildEnumerator : IEnumerator
+ {
+ private DirectoryEntry _container;
+ private SafeNativeMethods.EnumVariant _enumVariant;
+ private DirectoryEntry _currentEntry;
+
+ internal ChildEnumerator(DirectoryEntry container)
+ {
+ _container = container;
+ if (container.IsContainer)
+ {
+ _enumVariant = new SafeNativeMethods.EnumVariant((SafeNativeMethods.IEnumVariant)container.ContainerObject._NewEnum);
+ }
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.ChildEnumerator.Current"]/*' />
+ /// <devdoc>
+ /// <para>Gets the current element in the collection.</para>
+ /// </devdoc>
+ public DirectoryEntry Current
+ {
+ get
+ {
+ if (_enumVariant == null)
+ throw new InvalidOperationException(Res.GetString(Res.DSNoCurrentChild));
+
+ if (_currentEntry == null)
+ _currentEntry = new DirectoryEntry(_enumVariant.GetValue(), _container.UsePropertyCache, _container.GetUsername(), _container.GetPassword(), _container.AuthenticationType);
+
+ return _currentEntry;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.ChildEnumerator.MoveNext"]/*' />
+ /// <devdoc>
+ /// <para>Advances
+ /// the enumerator to the next element of the collection
+ /// and returns a Boolean value indicating whether a valid element is available.</para>
+ /// </devdoc>
+ public bool MoveNext()
+ {
+ if (_enumVariant == null)
+ return false;
+
+ _currentEntry = null;
+ return _enumVariant.GetNext();
+ }
+
+ /// <include file='doc\DirectoryEntries.uex' path='docs/doc[@for="DirectoryEntries.ChildEnumerator.Reset"]/*' />
+ /// <devdoc>
+ /// <para>Resets the enumerator back to its initial position before the first element in the collection.</para>
+ /// </devdoc>
+ public void Reset()
+ {
+ if (_enumVariant != null)
+ {
+ try
+ {
+ _enumVariant.Reset();
+ }
+ catch (NotImplementedException)
+ {
+ //Some providers might not implement Reset, workaround the problem.
+ _enumVariant = new SafeNativeMethods.EnumVariant((SafeNativeMethods.IEnumVariant)_container.ContainerObject._NewEnum);
+ }
+ _currentEntry = null;
+ }
+ }
+
+ object IEnumerator.Current
+ {
+ get
+ {
+ return Current;
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs
new file mode 100644
index 0000000000..2ac44a0ab0
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs
@@ -0,0 +1,1409 @@
+// 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
+{
+ using System;
+ using System.Text;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.DirectoryServices.Interop;
+ using System.ComponentModel;
+ using System.Threading;
+ using System.Reflection;
+ using System.Security.Permissions;
+ using System.DirectoryServices.Design;
+ using System.Globalization;
+ using System.Net;
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry"]/*' />
+ /// <devdoc>
+ /// <para> Encapsulates a node or an object in the Active Directory hierarchy.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ TypeConverterAttribute(typeof(DirectoryEntryConverter)),
+ EnvironmentPermission(SecurityAction.Assert, Unrestricted = true),
+ SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode),
+ DSDescriptionAttribute(Res.DirectoryEntryDesc)
+ ]
+ public class DirectoryEntry : Component
+ {
+ private string _path = "";
+ private UnsafeNativeMethods.IAds _adsObject;
+ private bool _useCache = true;
+ private bool _cacheFilled;
+ // disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ internal bool propertiesAlreadyEnumerated = false;
+#pragma warning restore 0414
+ private bool _justCreated = false; // 'true' if newly created entry was not yet stored by CommitChanges().
+ private bool _disposed = false;
+ private AuthenticationTypes _authenticationType = AuthenticationTypes.Secure;
+ private NetworkCredential _credentials;
+ private DirectoryEntryConfiguration _options;
+
+ private PropertyCollection _propertyCollection = null;
+ internal bool allowMultipleChange = false;
+ private bool _userNameIsNull = false;
+ private bool _passwordIsNull = false;
+ private bool _objectSecurityInitialized = false;
+ private bool _objectSecurityModified = false;
+ private ActiveDirectorySecurity _objectSecurity = null;
+ private static string s_securityDescriptorProperty = "ntSecurityDescriptor";
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.DirectoryEntry"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Initializes a new instance of the <see cref='System.DirectoryServices.DirectoryEntry'/>class.
+ /// </para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectoryEntry()
+ {
+ _options = new DirectoryEntryConfiguration(this);
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.DirectoryEntry1"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Initializes a new instance of the <see cref='System.DirectoryServices.DirectoryEntry'/> class that will bind
+ /// to the directory entry at <paramref name="path"/>.
+ /// </para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectoryEntry(string path) : this()
+ {
+ Path = path;
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.DirectoryEntry2"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Initializes a new instance of the <see cref='System.DirectoryServices.DirectoryEntry'/> class.
+ /// </para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectoryEntry(string path, string username, string password) : this(path, username, password, AuthenticationTypes.Secure)
+ {
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.DirectoryEntry3"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Initializes a new instance of the <see cref='System.DirectoryServices.DirectoryEntry'/> class.
+ /// </para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectoryEntry(string path, string username, string password, AuthenticationTypes authenticationType) : this(path)
+ {
+ _credentials = new NetworkCredential(username, password);
+ if (username == null)
+ _userNameIsNull = true;
+
+ if (password == null)
+ _passwordIsNull = true;
+
+ _authenticationType = authenticationType;
+ }
+
+ internal DirectoryEntry(string path, bool useCache, string username, string password, AuthenticationTypes authenticationType)
+ {
+ _path = path;
+ _useCache = useCache;
+ _credentials = new NetworkCredential(username, password);
+ if (username == null)
+ _userNameIsNull = true;
+
+ if (password == null)
+ _passwordIsNull = true;
+
+ _authenticationType = authenticationType;
+
+ _options = new DirectoryEntryConfiguration(this);
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.DirectoryEntry4"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Initializes a new instance of the <see cref='System.DirectoryServices.DirectoryEntry'/> class that will bind
+ /// to the native Active Directory object which is passed in.
+ /// </para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectoryEntry(object adsObject)
+ : this(adsObject, true, null, null, AuthenticationTypes.Secure, true)
+ {
+ }
+
+ internal DirectoryEntry(object adsObject, bool useCache, string username, string password, AuthenticationTypes authenticationType)
+ : this(adsObject, useCache, username, password, authenticationType, false)
+ {
+ }
+
+ internal DirectoryEntry(object adsObject, bool useCache, string username, string password, AuthenticationTypes authenticationType, bool AdsObjIsExternal)
+ {
+ _adsObject = adsObject as UnsafeNativeMethods.IAds;
+ if (_adsObject == null)
+ throw new ArgumentException(Res.GetString(Res.DSDoesNotImplementIADs));
+
+ // GetInfo is not needed here. ADSI executes an implicit GetInfo when GetEx
+ // is called on the PropertyValueCollection. 0x800704BC error might be returned
+ // on some WinNT entries, when iterating through 'Users' group members.
+ // if (forceBind)
+ // this.adsObject.GetInfo();
+ _path = _adsObject.ADsPath;
+ _useCache = useCache;
+
+ _authenticationType = authenticationType;
+ _credentials = new NetworkCredential(username, password);
+ if (username == null)
+ _userNameIsNull = true;
+
+ if (password == null)
+ _passwordIsNull = true;
+
+ if (!useCache)
+ CommitChanges();
+
+ _options = new DirectoryEntryConfiguration(this);
+
+ // We are starting from an already bound connection so make sure the options are set properly.
+ // If this is an externallly managed com object then we don't want to change it's current behavior
+ if (!AdsObjIsExternal)
+ {
+ InitADsObjectOptions();
+ }
+ }
+
+ internal UnsafeNativeMethods.IAds AdsObject
+ {
+ get
+ {
+ Bind();
+ return _adsObject;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.AuthenticationType"]/*' />
+ [
+ DefaultValue(AuthenticationTypes.Secure),
+ DSDescriptionAttribute(Res.DSAuthenticationType)
+ ]
+ public AuthenticationTypes AuthenticationType
+ {
+ get
+ {
+ return _authenticationType;
+ }
+ set
+ {
+ if (_authenticationType == value)
+ return;
+
+ _authenticationType = value;
+ Unbind();
+ }
+ }
+
+ private bool Bound
+ {
+ get
+ {
+ return _adsObject != null;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Children"]/*' />
+ /// <devdoc>
+ /// <para>Gets a <see cref='System.DirectoryServices.DirectoryEntries'/>
+ /// containing the child entries of this node in the Active
+ /// Directory hierarchy.</para>
+ /// </devdoc>
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSChildren)
+ ]
+ public DirectoryEntries Children
+ {
+ get
+ {
+ return new DirectoryEntries(this);
+ }
+ }
+
+ internal UnsafeNativeMethods.IAdsContainer ContainerObject
+ {
+ get
+ {
+ Bind();
+ return (UnsafeNativeMethods.IAdsContainer)_adsObject;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Guid"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Gets the globally unique identifier of the <see cref='System.DirectoryServices.DirectoryEntry'/>.
+ /// </para>
+ /// </devdoc>
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSGuid)
+ ]
+ public Guid Guid
+ {
+ get
+ {
+ string guid = NativeGuid;
+ if (guid.Length == 32)
+ {
+ // oddly, the value comes back as a string with no dashes from LDAP
+ byte[] intGuid = new byte[16];
+ for (int j = 0; j < 16; j++)
+ {
+ intGuid[j] = Convert.ToByte(new String(new char[] { guid[j * 2], guid[j * 2 + 1] }), 16);
+ }
+ return new Guid(intGuid);
+ // return new Guid(guid.Substring(0, 8) + "-" + guid.Substring(8, 4) + "-" + guid.Substring(12, 4) + "-" + guid.Substring(16, 4) + "-" + guid.Substring(20));
+ }
+ else
+ return new Guid(guid);
+ }
+ }
+
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSObjectSecurity)
+ ]
+ public ActiveDirectorySecurity ObjectSecurity
+ {
+ get
+ {
+ if (!_objectSecurityInitialized)
+ {
+ _objectSecurity = GetObjectSecurityFromCache();
+ _objectSecurityInitialized = true;
+ }
+
+ return _objectSecurity;
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ _objectSecurity = value;
+ _objectSecurityInitialized = true;
+ _objectSecurityModified = true;
+
+ CommitIfNotCaching();
+ }
+ }
+
+ internal bool IsContainer
+ {
+ get
+ {
+ Bind();
+ return _adsObject is UnsafeNativeMethods.IAdsContainer;
+ }
+ }
+
+ internal bool JustCreated
+ {
+ get
+ {
+ return _justCreated;
+ }
+ set
+ {
+ _justCreated = value;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Name"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Gets the relative name of the object as named with the
+ /// underlying directory service.
+ /// </para>
+ /// </devdoc>
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSName)
+ ]
+ public string Name
+ {
+ get
+ {
+ Bind();
+ string tmpName = _adsObject.Name;
+ GC.KeepAlive(this);
+ return tmpName;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.NativeGuid"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSNativeGuid)
+ ]
+ public string NativeGuid
+ {
+ get
+ {
+ FillCache("GUID");
+ string tmpGuid = _adsObject.GUID;
+ GC.KeepAlive(this);
+ return tmpGuid;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.NativeObject"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Gets the native Active Directory Services Interface (ADSI) object.
+ /// </para>
+ /// </devdoc>
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSNativeObject)
+ ]
+ public object NativeObject
+ {
+ get
+ {
+ Bind();
+ return _adsObject;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Parent"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Gets this
+ /// entry's parent entry in the Active Directory hierarchy.
+ /// </para>
+ /// </devdoc>
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSParent)
+ ]
+ public DirectoryEntry Parent
+ {
+ get
+ {
+ Bind();
+ return new DirectoryEntry(_adsObject.Parent, UsePropertyCache, GetUsername(), GetPassword(), AuthenticationType);
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Password"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the password to use when authenticating the client.</para>
+ /// </devdoc>
+ [
+ DSDescriptionAttribute(Res.DSPassword),
+ DefaultValue(null),
+ Browsable(false)
+ ]
+ public string Password
+ {
+ set
+ {
+ if (value == GetPassword())
+ return;
+
+ if (_credentials == null)
+ {
+ _credentials = new NetworkCredential();
+ // have not set it yet
+ _userNameIsNull = true;
+ }
+
+ if (value == null)
+ _passwordIsNull = true;
+ else
+ _passwordIsNull = false;
+
+ _credentials.Password = value;
+
+ Unbind();
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Path"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the path for this <see cref='System.DirectoryServices.DirectoryEntry'/>.</para>
+ /// </devdoc>
+ [
+ DefaultValue(""),
+ DSDescriptionAttribute(Res.DSPath),
+ TypeConverter("System.Diagnostics.Design.StringValueConverter, " + AssemblyRef.SystemDesign),
+ SettingsBindable(true)
+ ]
+ public string Path
+ {
+ get
+ {
+ return _path;
+ }
+ set
+ {
+ if (value == null)
+ value = "";
+
+ if (System.DirectoryServices.ActiveDirectory.Utils.Compare(_path, value) == 0)
+ return;
+
+ _path = value;
+ Unbind();
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Properties"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Gets a <see cref='System.DirectoryServices.PropertyCollection'/>
+ /// of properties set on this object.
+ /// </para>
+ /// </devdoc>
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSProperties)
+ ]
+ public PropertyCollection Properties
+ {
+ get
+ {
+ if (_propertyCollection == null)
+ {
+ _propertyCollection = new PropertyCollection(this);
+ }
+
+ return _propertyCollection;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.SchemaClassName"]/*' />
+ /// <devdoc>
+ /// <para>Gets the name of the schema used for this <see cref='System.DirectoryServices.DirectoryEntry'/>.</para>
+ /// </devdoc>
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSSchemaClassName)
+ ]
+ public string SchemaClassName
+ {
+ get
+ {
+ Bind();
+ string tmpClass = _adsObject.Class;
+ GC.KeepAlive(this);
+ return tmpClass;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.SchemaEntry"]/*' />
+ /// <devdoc>
+ /// <para>Gets the <see cref='System.DirectoryServices.DirectoryEntry'/> that holds schema information for this
+ /// entry. An entry's <see cref='System.DirectoryServices.DirectoryEntry.SchemaClassName'/>
+ /// determines what properties are valid for it.</para>
+ /// </devdoc>
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSSchemaEntry)
+ ]
+ public DirectoryEntry SchemaEntry
+ {
+ get
+ {
+ Bind();
+ return new DirectoryEntry(_adsObject.Schema, UsePropertyCache, GetUsername(), GetPassword(), AuthenticationType);
+ }
+ }
+
+ // By default changes to properties are done locally to
+ // a cache and reading property values is cached after
+ // the first read. Setting this to false will cause the
+ // cache to be committed after each operation.
+ //
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.UsePropertyCache"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Gets a value indicating whether the cache should be committed after each
+ /// operation.
+ /// </para>
+ /// </devdoc>
+ [
+ DefaultValue(true),
+ DSDescriptionAttribute(Res.DSUsePropertyCache)
+ ]
+ public bool UsePropertyCache
+ {
+ get
+ {
+ return _useCache;
+ }
+ set
+ {
+ if (value == _useCache)
+ return;
+
+ // auto-commit when they set this to false.
+ if (!value)
+ CommitChanges();
+
+ _cacheFilled = false; // cache mode has been changed
+ _useCache = value;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Username"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the username to use when authenticating the client.</para>
+ /// </devdoc>
+ [
+ DSDescriptionAttribute(Res.DSUsername),
+ TypeConverter("System.Diagnostics.Design.StringValueConverter, " + AssemblyRef.SystemDesign),
+ DefaultValue(null),
+ Browsable(false)
+ ]
+ public string Username
+ {
+ get
+ {
+ if (_credentials == null || _userNameIsNull)
+ return null;
+
+ return _credentials.UserName;
+ }
+ set
+ {
+ if (value == GetUsername())
+ return;
+
+ if (_credentials == null)
+ {
+ _credentials = new NetworkCredential();
+ _passwordIsNull = true;
+ }
+
+ if (value == null)
+ _userNameIsNull = true;
+ else
+ _userNameIsNull = false;
+
+ _credentials.UserName = value;
+
+ Unbind();
+ }
+ }
+
+ [
+ Browsable(false),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
+ DSDescriptionAttribute(Res.DSOptions)
+ ]
+ public DirectoryEntryConfiguration Options
+ {
+ get
+ {
+ // only LDAP provider supports IADsObjectOptions, so make the check here
+ if (!(AdsObject is UnsafeNativeMethods.IAdsObjectOptions))
+ return null;
+
+ return _options;
+ }
+ }
+
+ internal void InitADsObjectOptions()
+ {
+ if (_adsObject is UnsafeNativeMethods.IAdsObjectOptions2)
+ {
+ //--------------------------------------------
+ // Check if ACCUMULATE_MODIFICATION is available
+ //--------------------------------------------
+ object o = null;
+ int unmanagedResult = 0;
+ // check whether the new option is available
+
+ // 8 is ADS_OPTION_ACCUMULATIVE_MODIFICATION
+ unmanagedResult = ((UnsafeNativeMethods.IAdsObjectOptions2)_adsObject).GetOption(8, out o);
+ if (unmanagedResult != 0)
+ {
+ // rootdse does not support this option and invalid parameter due to without accumulative change fix in ADSI
+ if ((unmanagedResult == unchecked((int)0x80004001)) || (unmanagedResult == unchecked((int)0x80005008)))
+ {
+ return;
+ }
+ else
+ {
+ throw COMExceptionHelper.CreateFormattedComException(unmanagedResult);
+ }
+ }
+
+ // the new option is available, set it so we get the new PutEx behavior that will allow multiple changes
+ Variant value = new Variant();
+ value.varType = 11; //VT_BOOL
+ value.boolvalue = -1;
+ ((UnsafeNativeMethods.IAdsObjectOptions2)_adsObject).SetOption(8, value);
+
+ allowMultipleChange = true;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Bind"]/*' />
+ /// <devdoc>
+ /// Binds to the ADs object (if not already bound).
+ /// </devdoc>
+ private void Bind()
+ {
+ Bind(true);
+ }
+
+ internal void Bind(bool throwIfFail)
+ {
+ //Cannot rebind after the object has been disposed, since finalization has been suppressed.
+
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ if (_adsObject == null)
+ {
+ string pathToUse = Path;
+ if (pathToUse == null || pathToUse.Length == 0)
+ {
+ // get the default naming context. This should be the default root for the search.
+ DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE", true, null, null, AuthenticationTypes.Secure);
+
+ //SECREVIEW: Looking at the root of the DS will demand browse permissions
+ // on "*" or "LDAP://RootDSE".
+ string defaultNamingContext = (string)rootDSE.Properties["defaultNamingContext"][0];
+ rootDSE.Dispose();
+
+ pathToUse = "LDAP://" + defaultNamingContext;
+ }
+
+ // Ensure we've got a thread model set, else CoInitialize() won't have been called.
+ if (Thread.CurrentThread.GetApartmentState() == ApartmentState.Unknown)
+ Thread.CurrentThread.SetApartmentState(ApartmentState.MTA);
+
+ Guid g = new Guid("00000000-0000-0000-c000-000000000046"); // IID_IUnknown
+ object value = null;
+ int hr = UnsafeNativeMethods.ADsOpenObject(pathToUse, GetUsername(), GetPassword(), (int)_authenticationType, ref g, out value);
+
+ if (hr != 0)
+ {
+ if (throwIfFail)
+ throw COMExceptionHelper.CreateFormattedComException(hr);
+ }
+ else
+ {
+ _adsObject = (UnsafeNativeMethods.IAds)value;
+ }
+
+ InitADsObjectOptions();
+ }
+ }
+
+ // Create new entry with the same data, but different IADs object, and grant it Browse Permission.
+ internal DirectoryEntry CloneBrowsable()
+ {
+ DirectoryEntry newEntry = new DirectoryEntry(this.Path, this.UsePropertyCache, this.GetUsername(), this.GetPassword(), this.AuthenticationType);
+ return newEntry;
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Close"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Closes the <see cref='System.DirectoryServices.DirectoryEntry'/>
+ /// and releases any system resources associated with this component.
+ /// </para>
+ /// </devdoc>
+ public void Close()
+ {
+ Unbind();
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.CommitChanges"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Saves any
+ /// changes to the entry in the directory store.
+ /// </para>
+ /// </devdoc>
+ public void CommitChanges()
+ {
+ if (_justCreated)
+ {
+ // Note: Permissions Demand is not necessary here, because entry has already been created with appr. permissions.
+ // Write changes regardless of Caching mode to finish construction of a new entry.
+ try
+ {
+ //
+ // Write the security descriptor to the cache
+ //
+ SetObjectSecurityInCache();
+
+ _adsObject.SetInfo();
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ _justCreated = false;
+ _objectSecurityInitialized = false;
+ _objectSecurityModified = false;
+
+ // we need to refresh that properties table.
+ _propertyCollection = null;
+ return;
+ }
+ if (!_useCache)
+ {
+ // unless we have modified the existing security descriptor (in-place) through ObjectSecurity property
+ // there is nothing to do
+ if ((_objectSecurity == null) || (!_objectSecurity.IsModified()))
+ {
+ return;
+ }
+ }
+
+ if (!Bound)
+ return;
+
+ try
+ {
+ //
+ // Write the security descriptor to the cache
+ //
+ SetObjectSecurityInCache();
+ _adsObject.SetInfo();
+ _objectSecurityInitialized = false;
+ _objectSecurityModified = false;
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ // we need to refresh that properties table.
+ _propertyCollection = null;
+ }
+
+ internal void CommitIfNotCaching()
+ {
+ if (_justCreated)
+ return; // Do not write changes, beacuse the entry is just under construction until CommitChanges() is called.
+
+ if (_useCache)
+ return;
+
+ if (!Bound)
+ return;
+
+ // do full demand before we commit changes back to the server
+ new DirectoryServicesPermission(PermissionState.Unrestricted).Demand();
+
+ try
+ {
+ //
+ // Write the security descriptor to the cache
+ //
+ SetObjectSecurityInCache();
+
+ _adsObject.SetInfo();
+ _objectSecurityInitialized = false;
+ _objectSecurityModified = false;
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ // we need to refresh that properties table.
+ _propertyCollection = null;
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.CopyTo"]/*' />
+ /// <devdoc>
+ /// <para>Creates a copy of this entry as a child of the given parent.</para>
+ /// </devdoc>
+ public DirectoryEntry CopyTo(DirectoryEntry newParent)
+ {
+ return CopyTo(newParent, null);
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.CopyTo1"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Creates a copy of this entry as a child of the given parent and
+ /// gives it a new name.
+ /// </para>
+ /// </devdoc>
+ public DirectoryEntry CopyTo(DirectoryEntry newParent, string newName)
+ {
+ if (!newParent.IsContainer)
+ throw new InvalidOperationException(Res.GetString(Res.DSNotAContainer, newParent.Path));
+
+ object copy = null;
+ try
+ {
+ copy = newParent.ContainerObject.CopyHere(Path, newName);
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ return new DirectoryEntry(copy, newParent.UsePropertyCache, GetUsername(), GetPassword(), AuthenticationType);
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.DeleteTree"]/*' />
+ /// <devdoc>
+ /// <para>Deletes this entry and its entire subtree from the
+ /// Active Directory hierarchy.</para>
+ /// </devdoc>
+ public void DeleteTree()
+ {
+ if (!(AdsObject is UnsafeNativeMethods.IAdsDeleteOps))
+ throw new InvalidOperationException(Res.GetString(Res.DSCannotDelete));
+
+ UnsafeNativeMethods.IAdsDeleteOps entry = (UnsafeNativeMethods.IAdsDeleteOps)AdsObject;
+ try
+ {
+ entry.DeleteObject(0);
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+
+ GC.KeepAlive(this);
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Dispose"]/*' />
+ /// <devdoc>
+ /// </devdoc>
+ protected override void Dispose(bool disposing)
+ {
+ // no managed object to free
+
+ // free own state (unmanaged objects)
+ if (!_disposed)
+ {
+ Unbind();
+ _disposed = true;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Exists"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Searches the directory store at the given
+ /// path to see whether an entry exists.
+ /// </para>
+ /// </devdoc>
+ public static bool Exists(string path)
+ {
+ DirectoryEntry entry = new DirectoryEntry(path);
+ try
+ {
+ entry.Bind(true); // throws exceptions (possibly can break applications)
+ return entry.Bound;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x80072030) ||
+ e.ErrorCode == unchecked((int)0x80070003) || // ERROR_DS_NO_SUCH_OBJECT and path not found (not found in strict sense)
+ e.ErrorCode == unchecked((int)0x800708AC)) // Group name could not be found
+ return false;
+ throw;
+ }
+ finally
+ {
+ entry.Dispose();
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.FillCache"]/*' />
+ /// <devdoc>
+ /// If UsePropertyCache is true, calls GetInfo the first time it's necessary.
+ /// If it's false, calls GetInfoEx on the given property name.
+ /// </devdoc>
+ internal void FillCache(string propertyName)
+ {
+ if (UsePropertyCache)
+ {
+ if (_cacheFilled)
+ return;
+
+ RefreshCache();
+ _cacheFilled = true;
+ }
+ else
+ {
+ Bind();
+ try
+ {
+ if (propertyName.Length > 0)
+ _adsObject.GetInfoEx(new object[] { propertyName }, 0);
+ else
+ _adsObject.GetInfo();
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Invoke"]/*' />
+ /// <devdoc>
+ /// <para>Calls
+ /// a method on the native Active Directory.</para>
+ /// </devdoc>
+ public object Invoke(string methodName, params object[] args)
+ {
+ object target = this.NativeObject;
+ Type type = target.GetType();
+ object result = null;
+ try
+ {
+ result = type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, target, args, CultureInfo.InvariantCulture);
+ GC.KeepAlive(this);
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ catch (TargetInvocationException e)
+ {
+ if (e.InnerException != null)
+ {
+ if (e.InnerException is COMException)
+ {
+ COMException inner = (COMException)e.InnerException;
+ throw new TargetInvocationException(e.Message, COMExceptionHelper.CreateFormattedComException(inner));
+ }
+ }
+
+ throw e;
+ }
+
+ if (result is UnsafeNativeMethods.IAds)
+
+ return new DirectoryEntry(result, UsePropertyCache, GetUsername(), GetPassword(), AuthenticationType);
+ else
+ return result;
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.InvokeGet"]/*' />
+ /// <devdoc>
+ /// <para>Reads
+ /// a property on the native Active Directory object.</para>
+ /// </devdoc>
+ public object InvokeGet(string propertyName)
+ {
+ object target = this.NativeObject;
+ Type type = target.GetType();
+ object result = null;
+ try
+ {
+ result = type.InvokeMember(propertyName, BindingFlags.GetProperty, null, target, null, CultureInfo.InvariantCulture);
+ GC.KeepAlive(this);
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ catch (TargetInvocationException e)
+ {
+ if (e.InnerException != null)
+ {
+ if (e.InnerException is COMException)
+ {
+ COMException inner = (COMException)e.InnerException;
+ throw new TargetInvocationException(e.Message, COMExceptionHelper.CreateFormattedComException(inner));
+ }
+ }
+
+ throw e;
+ }
+
+ return result;
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.InvokeSet"]/*' />
+ /// <devdoc>
+ /// <para>Sets
+ /// a property on the native Active Directory object.</para>
+ /// </devdoc>
+ public void InvokeSet(string propertyName, params object[] args)
+ {
+ object target = this.NativeObject;
+ Type type = target.GetType();
+ try
+ {
+ type.InvokeMember(propertyName, BindingFlags.SetProperty, null, target, args, CultureInfo.InvariantCulture);
+ GC.KeepAlive(this);
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+ catch (TargetInvocationException e)
+ {
+ if (e.InnerException != null)
+ {
+ if (e.InnerException is COMException)
+ {
+ COMException inner = (COMException)e.InnerException;
+ throw new TargetInvocationException(e.Message, COMExceptionHelper.CreateFormattedComException(inner));
+ }
+ }
+
+ throw e;
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.MoveTo"]/*' />
+ /// <devdoc>
+ /// <para>Moves this entry to the given parent.</para>
+ /// </devdoc>
+ public void MoveTo(DirectoryEntry newParent)
+ {
+ MoveTo(newParent, null);
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.MoveTo1"]/*' />
+ /// <devdoc>
+ /// <para>Moves this entry to the given parent, and gives it a new name.</para>
+ /// </devdoc>
+ public void MoveTo(DirectoryEntry newParent, string newName)
+ {
+ object newEntry = null;
+ if (!(newParent.AdsObject is UnsafeNativeMethods.IAdsContainer))
+ throw new InvalidOperationException(Res.GetString(Res.DSNotAContainer, newParent.Path));
+ try
+ {
+ if (AdsObject.ADsPath.StartsWith("WinNT:", StringComparison.Ordinal))
+ {
+ // get the ADsPath instead of using Path as ADsPath for the case that "WinNT://computername" is passed in while we need "WinNT://domain/computer"
+ string childPath = AdsObject.ADsPath;
+ string parentPath = newParent.AdsObject.ADsPath;
+
+ // we know ADsPath does not end with object type qualifier like ",computer" so it is fine to compare with whole newparent's adspath
+ // for the case that child has different components from newparent in the aspects other than case, we don't do any processing, just let ADSI decide in case future adsi change
+ if (System.DirectoryServices.ActiveDirectory.Utils.Compare(childPath, 0, parentPath.Length, parentPath, 0, parentPath.Length) == 0)
+ {
+ uint compareFlags = System.DirectoryServices.ActiveDirectory.Utils.NORM_IGNORENONSPACE |
+ System.DirectoryServices.ActiveDirectory.Utils.NORM_IGNOREKANATYPE |
+ System.DirectoryServices.ActiveDirectory.Utils.NORM_IGNOREWIDTH |
+ System.DirectoryServices.ActiveDirectory.Utils.SORT_STRINGSORT;
+ // work around the ADSI case sensitive
+ if (System.DirectoryServices.ActiveDirectory.Utils.Compare(childPath, 0, parentPath.Length, parentPath, 0, parentPath.Length, compareFlags) != 0)
+ {
+ childPath = parentPath + childPath.Substring(parentPath.Length);
+ }
+ }
+
+ newEntry = newParent.ContainerObject.MoveHere(childPath, newName);
+ }
+ else
+ {
+ newEntry = newParent.ContainerObject.MoveHere(Path, newName);
+ }
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+
+ if (Bound)
+ System.Runtime.InteropServices.Marshal.ReleaseComObject(_adsObject); // release old handle
+
+ _adsObject = (UnsafeNativeMethods.IAds)newEntry;
+ _path = _adsObject.ADsPath;
+
+ // Reset the options on the ADSI object since there were lost when the new object was created.
+ InitADsObjectOptions();
+
+ if (!_useCache)
+ CommitChanges();
+ else
+ RefreshCache(); // in ADSI cache is lost after moving
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.RefreshCache"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Loads the property values for this directory entry into
+ /// the property cache.
+ /// </para>
+ /// </devdoc>
+ public void RefreshCache()
+ {
+ Bind();
+ try
+ {
+ _adsObject.GetInfo();
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+
+ _cacheFilled = true;
+ // we need to refresh that properties table.
+ _propertyCollection = null;
+
+ // need to refresh the objectSecurity property
+ _objectSecurityInitialized = false;
+ _objectSecurityModified = false;
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.RefreshCache1"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Loads the values of the specified properties into the
+ /// property cache.
+ /// </para>
+ /// </devdoc>
+ public void RefreshCache(string[] propertyNames)
+ {
+ Bind();
+
+ //Consider there shouldn't be any marshaling issues
+ //by just doing: AdsObject.GetInfoEx(object[]propertyNames, 0);
+ Object[] names = new Object[propertyNames.Length];
+ for (int i = 0; i < propertyNames.Length; i++)
+ names[i] = propertyNames[i];
+ try
+ {
+ AdsObject.GetInfoEx(names, 0);
+ }
+ catch (COMException e)
+ {
+ throw COMExceptionHelper.CreateFormattedComException(e);
+ }
+
+ // this is a half-lie, but oh well. Without it, this method is pointless.
+ _cacheFilled = true;
+ // we need to partially refresh that properties table.
+ if (_propertyCollection != null && propertyNames != null)
+ {
+ for (int i = 0; i < propertyNames.Length; i++)
+ {
+ if (propertyNames[i] != null)
+ {
+ string name = propertyNames[i].ToLower(CultureInfo.InvariantCulture);
+ _propertyCollection.valueTable.Remove(name);
+
+ // also need to consider the range retrieval case
+ string[] results = name.Split(new char[] { ';' });
+ if (results.Length != 1)
+ {
+ string rangeName = "";
+ for (int count = 0; count < results.Length; count++)
+ {
+ if (!results[count].StartsWith("range=", StringComparison.Ordinal))
+ {
+ rangeName += results[count];
+ rangeName += ";";
+ }
+ }
+
+ // remove the last ';' character
+ rangeName = rangeName.Remove(rangeName.Length - 1, 1);
+
+ _propertyCollection.valueTable.Remove(rangeName);
+ }
+
+ // if this is "ntSecurityDescriptor" we should refresh the objectSecurity property
+ if (String.Compare(propertyNames[i], s_securityDescriptorProperty, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ _objectSecurityInitialized = false;
+ _objectSecurityModified = false;
+ }
+ }
+ }
+ }
+ }
+
+ /// <include file='doc\DirectoryEntry.uex' path='docs/doc[@for="DirectoryEntry.Rename"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Changes the name of this entry.
+ /// </para>
+ /// </devdoc>
+ public void Rename(string newName)
+ {
+ MoveTo(Parent, newName);
+ }
+
+ private void Unbind()
+ {
+ if (_adsObject != null)
+ System.Runtime.InteropServices.Marshal.ReleaseComObject(_adsObject);
+ _adsObject = null;
+ // we need to release that properties table.
+ _propertyCollection = null;
+
+ // need to refresh the objectSecurity property
+ _objectSecurityInitialized = false;
+ _objectSecurityModified = false;
+ }
+
+ internal string GetUsername()
+ {
+ if (_credentials == null || _userNameIsNull)
+ return null;
+
+ return _credentials.UserName;
+ }
+
+ internal string GetPassword()
+ {
+ if (_credentials == null || _passwordIsNull)
+ return null;
+
+ return _credentials.Password;
+ }
+
+ private ActiveDirectorySecurity GetObjectSecurityFromCache()
+ {
+ try
+ {
+ //
+ // This property is the managed version of the "ntSecurityDescriptor"
+ // attribute. In order to build an ActiveDirectorySecurity object from it
+ // we need to get the binary form of the security descriptor.
+ // If we use IADs::Get to get the IADsSecurityDescriptor interface and then
+ // convert to raw form, there would be a performance overhead (because of
+ // sid lookups and reverse lookups during conversion).
+ // So to get the security descriptor in binary form, we use
+ // IADsPropertyList::GetPropertyItem
+ //
+
+ //
+ // GetPropertyItem does not implicitly fill the property cache
+ // so we need to fill it explicitly (for an existing entry)
+ //
+ if (!JustCreated)
+ {
+ SecurityMasks securityMasksUsedInRetrieval;
+
+ //
+ // To ensure that we honor the security masks while retrieving
+ // the security descriptor, we will retrieve the "ntSecurityDescriptor" each time
+ // while initializing the ObjectSecurity property
+ //
+ securityMasksUsedInRetrieval = this.Options.SecurityMasks;
+ RefreshCache(new string[] { s_securityDescriptorProperty });
+
+ //
+ // Get the IAdsPropertyList interface
+ // (Check that the IAdsPropertyList interface is supported)
+ //
+ if (!(NativeObject is UnsafeNativeMethods.IAdsPropertyList))
+ throw new NotSupportedException(Res.GetString(Res.DSPropertyListUnsupported));
+
+ UnsafeNativeMethods.IAdsPropertyList list = (UnsafeNativeMethods.IAdsPropertyList)NativeObject;
+
+ UnsafeNativeMethods.IAdsPropertyEntry propertyEntry = (UnsafeNativeMethods.IAdsPropertyEntry)list.GetPropertyItem(s_securityDescriptorProperty, (int)AdsType.ADSTYPE_OCTET_STRING);
+ GC.KeepAlive(this);
+
+ //
+ // Create a new ActiveDirectorySecurity object from the binary form
+ // of the security descriptor
+ //
+ object[] values = (object[])propertyEntry.Values;
+
+ //
+ // This should never happen. It indicates that there is a problem in ADSI's property cache logic.
+ //
+ if (values.Length < 1)
+ {
+ Debug.Fail("ntSecurityDescriptor property exists in cache but has no values.");
+ throw new InvalidOperationException(Res.GetString(Res.DSSDNoValues));
+ }
+
+ //
+ // Do not support more than one security descriptor
+ //
+ if (values.Length > 1)
+ {
+ throw new NotSupportedException(Res.GetString(Res.DSMultipleSDNotSupported));
+ }
+
+ UnsafeNativeMethods.IAdsPropertyValue propertyValue = (UnsafeNativeMethods.IAdsPropertyValue)values[0];
+ return new ActiveDirectorySecurity((byte[])propertyValue.OctetString, securityMasksUsedInRetrieval);
+ }
+ else
+ {
+ //
+ // Newly created directory entry
+ //
+
+ return null;
+ }
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ if (e.ErrorCode == unchecked((int)0x8000500D)) // property not found exception
+ return null;
+ else
+ throw;
+ }
+ }
+
+ private void SetObjectSecurityInCache()
+ {
+ if ((_objectSecurity != null) && (_objectSecurityModified || _objectSecurity.IsModified()))
+ {
+ UnsafeNativeMethods.IAdsPropertyValue sDValue = (UnsafeNativeMethods.IAdsPropertyValue)new UnsafeNativeMethods.PropertyValue();
+
+ sDValue.ADsType = (int)AdsType.ADSTYPE_OCTET_STRING;
+ sDValue.OctetString = _objectSecurity.GetSecurityDescriptorBinaryForm();
+
+ UnsafeNativeMethods.IAdsPropertyEntry newSDEntry = (UnsafeNativeMethods.IAdsPropertyEntry)new UnsafeNativeMethods.PropertyEntry();
+
+ newSDEntry.Name = s_securityDescriptorProperty;
+ newSDEntry.ADsType = (int)AdsType.ADSTYPE_OCTET_STRING;
+ newSDEntry.ControlCode = (int)AdsPropertyOperation.Update;
+ newSDEntry.Values = new object[] { sDValue };
+
+ ((UnsafeNativeMethods.IAdsPropertyList)NativeObject).PutPropertyItem(newSDEntry);
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntryConfiguration.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntryConfiguration.cs
new file mode 100644
index 0000000000..7d3ecf6328
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntryConfiguration.cs
@@ -0,0 +1,128 @@
+// 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
+{
+ using System;
+ using System.DirectoryServices.Interop;
+ using System.ComponentModel;
+ using System.Security.Permissions;
+
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class DirectoryEntryConfiguration
+ {
+ private DirectoryEntry _entry;
+ private const int ISC_RET_MUTUAL_AUTH = 0x00000002;
+
+ internal DirectoryEntryConfiguration(DirectoryEntry entry)
+ {
+ _entry = entry;
+ }
+
+ public ReferralChasingOption Referral
+ {
+ get
+ {
+ return (ReferralChasingOption)((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).GetOption((int)AdsOptions.ADS_OPTION_REFERRALS);
+ }
+ set
+ {
+ if (value != ReferralChasingOption.None &&
+ value != ReferralChasingOption.Subordinate &&
+ value != ReferralChasingOption.External &&
+ value != ReferralChasingOption.All)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(ReferralChasingOption));
+
+ ((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).SetOption((int)AdsOptions.ADS_OPTION_REFERRALS, value);
+ }
+ }
+
+ public SecurityMasks SecurityMasks
+ {
+ get
+ {
+ return (SecurityMasks)((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).GetOption((int)AdsOptions.ADS_OPTION_SECURITY_MASK);
+ }
+ set
+ {
+ if (value > (SecurityMasks.None | SecurityMasks.Owner | SecurityMasks.Group | SecurityMasks.Dacl | SecurityMasks.Sacl))
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(SecurityMasks));
+
+ ((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).SetOption((int)AdsOptions.ADS_OPTION_SECURITY_MASK, value);
+ }
+ }
+
+ public int PageSize
+ {
+ get
+ {
+ return (int)((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).GetOption((int)AdsOptions.ADS_OPTION_PAGE_SIZE);
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadPageSize));
+
+ ((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).SetOption((int)AdsOptions.ADS_OPTION_PAGE_SIZE, value);
+ }
+ }
+
+ public int PasswordPort
+ {
+ get
+ {
+ return (int)((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).GetOption((int)AdsOptions.ADS_OPTION_PASSWORD_PORTNUMBER);
+ }
+ set
+ {
+ ((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).SetOption((int)AdsOptions.ADS_OPTION_PASSWORD_PORTNUMBER, value);
+ }
+ }
+
+ public PasswordEncodingMethod PasswordEncoding
+ {
+ get
+ {
+ return (PasswordEncodingMethod)((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).GetOption((int)AdsOptions.ADS_OPTION_PASSWORD_METHOD);
+ }
+ set
+ {
+ if (value < PasswordEncodingMethod.PasswordEncodingSsl || value > PasswordEncodingMethod.PasswordEncodingClear)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(PasswordEncodingMethod));
+
+ ((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).SetOption((int)AdsOptions.ADS_OPTION_PASSWORD_METHOD, value);
+ }
+ }
+
+ public string GetCurrentServerName()
+ {
+ // underneath it uses the same handle and binds to the same object, so no permission is required as it has been done in Bind call
+ return (string)((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).GetOption((int)AdsOptions.ADS_OPTION_SERVERNAME);
+ }
+
+ public bool IsMutuallyAuthenticated()
+ {
+ try
+ {
+ int val = (int)((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).GetOption((int)AdsOptions.ADS_OPTION_MUTUAL_AUTH_STATUS);
+ if ((val & ISC_RET_MUTUAL_AUTH) != 0)
+ return true;
+ else
+ return false;
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ // if SSL is used, ADSI will return E_ADS_BAD_PARAMETER, we should catch it here
+ if (e.ErrorCode == unchecked((int)0x80005008))
+ return false;
+ throw;
+ }
+ }
+
+ public void SetUserNameQueryQuota(string accountName)
+ {
+ ((UnsafeNativeMethods.IAdsObjectOptions)_entry.AdsObject).SetOption((int)AdsOptions.ADS_OPTION_QUOTA, accountName);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs
new file mode 100644
index 0000000000..57a46fe88d
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectorySearcher.cs
@@ -0,0 +1,1240 @@
+// 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 INTPTR_INTPTRCAST = System.IntPtr;
+using INTPTR_INTCAST = System.Int32;
+
+namespace System.DirectoryServices
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Collections.Specialized;
+ using System.Diagnostics;
+ using System.DirectoryServices.Interop;
+ using System.DirectoryServices.Design;
+ using System.ComponentModel;
+ using System.Security.Permissions;
+ using System.Globalization;
+ using Microsoft.Win32;
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher"]/*' />
+ /// <devdoc>
+ /// <para> Performs queries against the Active Directory hierarchy.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true),
+ DSDescriptionAttribute(Res.DirectorySearcherDesc)
+ ]
+ public class DirectorySearcher : Component
+ {
+ private DirectoryEntry _searchRoot;
+ private string _filter = defaultFilter;
+ private StringCollection _propertiesToLoad;
+ private bool _disposed = false;
+
+ private static readonly TimeSpan s_minusOneSecond = new TimeSpan(0, 0, -1);
+
+ // search preference variables
+ private SearchScope _scope = System.DirectoryServices.SearchScope.Subtree;
+ private bool _scopeSpecified = false;
+ private int _sizeLimit = 0;
+ private TimeSpan _serverTimeLimit = s_minusOneSecond;
+ private bool _propertyNamesOnly = false;
+ private TimeSpan _clientTimeout = s_minusOneSecond;
+ private int _pageSize = 0;
+ private TimeSpan _serverPageTimeLimit = s_minusOneSecond;
+ private ReferralChasingOption _referralChasing = ReferralChasingOption.External;
+ private SortOption _sort = new SortOption();
+ private bool _cacheResults = true;
+ private bool _cacheResultsSpecified = false;
+ private bool _rootEntryAllocated = false; // true: if a temporary entry inside Searcher has been created
+ private string _assertDefaultNamingContext = null;
+ private bool _asynchronous = false;
+ private bool _tombstone = false;
+ private string _attributeScopeQuery = "";
+ private bool _attributeScopeQuerySpecified = false;
+ private DereferenceAlias _derefAlias = DereferenceAlias.Never;
+ private SecurityMasks _securityMask = SecurityMasks.None;
+ private ExtendedDN _extendedDN = ExtendedDN.None;
+ private DirectorySynchronization _sync = null;
+ internal bool directorySynchronizationSpecified = false;
+ private DirectoryVirtualListView _vlv = null;
+ internal bool directoryVirtualListViewSpecified = false;
+ internal SearchResultCollection searchResult = null;
+
+ private const string defaultFilter = "(objectClass=*)";
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DirectorySearcher"]/*' />
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.DirectoryServices.DirectorySearcher'/> class with <see cref='System.DirectoryServices.DirectorySearcher.SearchRoot'/>,
+ /// <see cref='System.DirectoryServices.DirectorySearcher.Filter'/>, <see cref='System.DirectoryServices.DirectorySearcher.PropertiesToLoad'/>, and <see cref='System.DirectoryServices.DirectorySearcher.SearchScope'/> set to their default values.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectorySearcher() : this(null, defaultFilter, null, System.DirectoryServices.SearchScope.Subtree)
+ {
+ _scopeSpecified = false;
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DirectorySearcher1"]/*' />
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.DirectoryServices.DirectorySearcher'/> class with
+ /// <see cref='System.DirectoryServices.DirectorySearcher.Filter'/>, <see cref='System.DirectoryServices.DirectorySearcher.PropertiesToLoad'/>, and <see cref='System.DirectoryServices.DirectorySearcher.SearchScope'/> set to their default
+ /// values, and <see cref='System.DirectoryServices.DirectorySearcher.SearchRoot'/> set to the given value.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectorySearcher(DirectoryEntry searchRoot) : this(searchRoot, defaultFilter, null, System.DirectoryServices.SearchScope.Subtree)
+ {
+ _scopeSpecified = false;
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DirectorySearcher2"]/*' />
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.DirectoryServices.DirectorySearcher'/> class with
+ /// <see cref='System.DirectoryServices.DirectorySearcher.PropertiesToLoad'/> and <see cref='System.DirectoryServices.DirectorySearcher.SearchScope'/> set to their default
+ /// values, and <see cref='System.DirectoryServices.DirectorySearcher.SearchRoot'/> and <see cref='System.DirectoryServices.DirectorySearcher.Filter'/> set to the respective given values.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectorySearcher(DirectoryEntry searchRoot, string filter) : this(searchRoot, filter, null, System.DirectoryServices.SearchScope.Subtree)
+ {
+ _scopeSpecified = false;
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DirectorySearcher3"]/*' />
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.DirectoryServices.DirectorySearcher'/> class with
+ /// <see cref='System.DirectoryServices.DirectorySearcher.SearchScope'/> set to its default
+ /// value, and <see cref='System.DirectoryServices.DirectorySearcher.SearchRoot'/>, <see cref='System.DirectoryServices.DirectorySearcher.Filter'/>, and <see cref='System.DirectoryServices.DirectorySearcher.PropertiesToLoad'/> set to the respective given values.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectorySearcher(DirectoryEntry searchRoot, string filter, string[] propertiesToLoad) : this(searchRoot, filter, propertiesToLoad, System.DirectoryServices.SearchScope.Subtree)
+ {
+ _scopeSpecified = false;
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DirectorySearcher4"]/*' />
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.DirectoryServices.DirectorySearcher'/> class with <see cref='System.DirectoryServices.DirectorySearcher.SearchRoot'/>,
+ /// <see cref='System.DirectoryServices.DirectorySearcher.PropertiesToLoad'/>, and <see cref='System.DirectoryServices.DirectorySearcher.SearchScope'/> set to their default
+ /// values, and <see cref='System.DirectoryServices.DirectorySearcher.Filter'/> set to the given value.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectorySearcher(string filter) : this(null, filter, null, System.DirectoryServices.SearchScope.Subtree)
+ {
+ _scopeSpecified = false;
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DirectorySearcher5"]/*' />
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.DirectoryServices.DirectorySearcher'/> class with <see cref='System.DirectoryServices.DirectorySearcher.SearchRoot'/>
+ /// and <see cref='System.DirectoryServices.DirectorySearcher.SearchScope'/> set to their default
+ /// values, and <see cref='System.DirectoryServices.DirectorySearcher.Filter'/> and <see cref='System.DirectoryServices.DirectorySearcher.PropertiesToLoad'/> set to the respective given values.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectorySearcher(string filter, string[] propertiesToLoad) : this(null, filter, propertiesToLoad, System.DirectoryServices.SearchScope.Subtree)
+ {
+ _scopeSpecified = false;
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DirectorySearcher6"]/*' />
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.DirectoryServices.DirectorySearcher'/> class with <see cref='System.DirectoryServices.DirectorySearcher.SearchRoot'/> set to its default
+ /// value, and <see cref='System.DirectoryServices.DirectorySearcher.Filter'/>, <see cref='System.DirectoryServices.DirectorySearcher.PropertiesToLoad'/>, and <see cref='System.DirectoryServices.DirectorySearcher.SearchScope'/> set to the respective given values.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectorySearcher(string filter, string[] propertiesToLoad, SearchScope scope) : this(null, filter, propertiesToLoad, scope)
+ {
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DirectorySearcher7"]/*' />
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.DirectoryServices.DirectorySearcher'/> class with the <see cref='System.DirectoryServices.DirectorySearcher.SearchRoot'/>, <see cref='System.DirectoryServices.DirectorySearcher.Filter'/>, <see cref='System.DirectoryServices.DirectorySearcher.PropertiesToLoad'/>, and <see cref='System.DirectoryServices.DirectorySearcher.SearchScope'/> properties set to the given
+ /// values.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.Demand, Unrestricted = true)
+ ]
+ public DirectorySearcher(DirectoryEntry searchRoot, string filter, string[] propertiesToLoad, SearchScope scope)
+ {
+ _searchRoot = searchRoot;
+ _filter = filter;
+ if (propertiesToLoad != null)
+ PropertiesToLoad.AddRange(propertiesToLoad);
+ this.SearchScope = scope;
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.Dispose"]/*' />
+ /// <devdoc>
+ /// </devdoc>
+ protected override void Dispose(bool disposing)
+ {
+ // safe to call while finalizing or disposing
+ //
+ if (!_disposed && disposing)
+ {
+ if (_rootEntryAllocated)
+ _searchRoot.Dispose();
+ _rootEntryAllocated = false;
+ _disposed = true;
+ }
+ base.Dispose(disposing);
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.CacheResults"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Gets or sets a value indicating whether the result should be cached on the
+ /// client machine.
+ /// </para>
+ /// </devdoc>
+ [
+ DefaultValue(true),
+ DSDescriptionAttribute(Res.DSCacheResults)
+ ]
+ public bool CacheResults
+ {
+ get
+ {
+ return _cacheResults;
+ }
+ set
+ {
+ // user explicitly set CacheResults to true and also want VLV
+ if (directoryVirtualListViewSpecified == true && value == true)
+ throw new ArgumentException(Res.GetString(Res.DSBadCacheResultsVLV));
+
+ _cacheResults = value;
+
+ _cacheResultsSpecified = true;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.ClientTimeout"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the maximum amount of time that the client waits for
+ /// the server to return results. If the server does not respond within this time,
+ /// the search is aborted, and no results are returned.</para>
+ /// </devdoc>
+ [
+ DSDescriptionAttribute(Res.DSClientTimeout)
+ ]
+ public TimeSpan ClientTimeout
+ {
+ get
+ {
+ return _clientTimeout;
+ }
+ set
+ {
+ // prevent integer overflow
+ if (value.TotalSeconds > Int32.MaxValue)
+ {
+ throw new ArgumentException(Res.GetString(Res.TimespanExceedMax), "value");
+ }
+
+ _clientTimeout = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.PropertyNamesOnly"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value indicating whether the search should retrieve only the names of requested
+ /// properties or the names and values of requested properties.</para>
+ /// </devdoc>
+ [
+ DefaultValue(false),
+ DSDescriptionAttribute(Res.DSPropertyNamesOnly)
+ ]
+ public bool PropertyNamesOnly
+ {
+ get
+ {
+ return _propertyNamesOnly;
+ }
+ set
+ {
+ _propertyNamesOnly = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.Filter"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the Lightweight Directory Access Protocol (LDAP) filter string
+ /// format.</para>
+ /// <![CDATA[ (objectClass=*) (!(objectClass=user)) (&(objectClass=user)(sn=Jones)) ]]>
+ /// </devdoc>
+ [
+ DefaultValue(defaultFilter),
+ DSDescriptionAttribute(Res.DSFilter),
+ TypeConverter("System.Diagnostics.Design.StringValueConverter, " + AssemblyRef.SystemDesign),
+ SettingsBindable(true)
+ ]
+ public string Filter
+ {
+ get
+ {
+ return _filter;
+ }
+ set
+ {
+ if (value == null || value.Length == 0)
+ value = defaultFilter;
+ _filter = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.PageSize"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the page size in a paged search.</para>
+ /// </devdoc>
+ [
+ DefaultValue(0),
+ DSDescriptionAttribute(Res.DSPageSize)
+ ]
+ public int PageSize
+ {
+ get
+ {
+ return _pageSize;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadPageSize));
+
+ // specify non-zero pagesize explicitly and also want dirsync
+ if (directorySynchronizationSpecified == true && value != 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadPageSizeDirsync));
+
+ _pageSize = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.PropertiesToLoad"]/*' />
+ /// <devdoc>
+ /// <para>Gets the set of properties retrieved during the search. By default, the <see cref='System.DirectoryServices.DirectoryEntry.Path'/>
+ /// and <see cref='System.DirectoryServices.DirectoryEntry.Name'/> properties are retrieved.</para>
+ /// </devdoc>
+ [
+ DSDescriptionAttribute(Res.DSPropertiesToLoad),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
+ Editor("System.Windows.Forms.Design.StringCollectionEditor, " + AssemblyRef.SystemDesign, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing)
+ ]
+ public StringCollection PropertiesToLoad
+ {
+ get
+ {
+ if (_propertiesToLoad == null)
+ {
+ _propertiesToLoad = new StringCollection();
+ }
+ return _propertiesToLoad;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.ReferralChasing"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets how referrals are chased.</para>
+ /// </devdoc>
+ [
+ DefaultValue(ReferralChasingOption.External),
+ DSDescriptionAttribute(Res.DSReferralChasing)
+ ]
+ public ReferralChasingOption ReferralChasing
+ {
+ get
+ {
+ return _referralChasing;
+ }
+ set
+ {
+ if (value != ReferralChasingOption.None &&
+ value != ReferralChasingOption.Subordinate &&
+ value != ReferralChasingOption.External &&
+ value != ReferralChasingOption.All)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(ReferralChasingOption));
+
+ _referralChasing = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.SearchScope"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the scope of the search that should be observed by the server.</para>
+ /// </devdoc>
+ [
+ DefaultValue(SearchScope.Subtree),
+ DSDescriptionAttribute(Res.DSSearchScope),
+ SettingsBindable(true)
+ ]
+ public SearchScope SearchScope
+ {
+ get
+ {
+ return _scope;
+ }
+ set
+ {
+ if (value < SearchScope.Base || value > SearchScope.Subtree)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(SearchScope));
+
+ // user explicitly set SearchScope to something other than Base and also want to do ASQ, it is not supported
+ if (_attributeScopeQuerySpecified == true && value != SearchScope.Base)
+ {
+ throw new ArgumentException(Res.GetString(Res.DSBadASQSearchScope));
+ }
+
+ _scope = value;
+
+ _scopeSpecified = true;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.ServerPageTimeLimit"]/*' />
+ /// <devdoc>
+ /// <para> Gets or sets the time limit that the server should
+ /// observe to search a page of results (as opposed to
+ /// the time limit for the entire search).</para>
+ /// </devdoc>
+ [
+ DSDescriptionAttribute(Res.DSServerPageTimeLimit)
+ ]
+ public TimeSpan ServerPageTimeLimit
+ {
+ get
+ {
+ return _serverPageTimeLimit;
+ }
+ set
+ {
+ // prevent integer overflow
+ if (value.TotalSeconds > Int32.MaxValue)
+ {
+ throw new ArgumentException(Res.GetString(Res.TimespanExceedMax), "value");
+ }
+
+ _serverPageTimeLimit = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.ServerTimeLimit"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the maximum amount of time the server spends searching. If the
+ /// time limit is reached, only entries found up to that point will be returned.</para>
+ /// </devdoc>
+ [
+ DSDescriptionAttribute(Res.DSServerTimeLimit)
+ ]
+ public TimeSpan ServerTimeLimit
+ {
+ get
+ {
+ return _serverTimeLimit;
+ }
+ set
+ {
+ // prevent integer overflow
+ if (value.TotalSeconds > Int32.MaxValue)
+ {
+ throw new ArgumentException(Res.GetString(Res.TimespanExceedMax), "value");
+ }
+
+ _serverTimeLimit = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.SizeLimit"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the maximum number of objects that the
+ /// server should return in a search.</para>
+ /// </devdoc>
+ [
+ DefaultValue(0),
+ DSDescriptionAttribute(Res.DSSizeLimit)
+ ]
+ public int SizeLimit
+ {
+ get
+ {
+ return _sizeLimit;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadSizeLimit));
+ _sizeLimit = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.SearchRoot"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the node in the Active Directory hierarchy
+ /// at which the search will start.</para>
+ /// </devdoc>
+ [
+ DSDescriptionAttribute(Res.DSSearchRoot),
+ DefaultValueAttribute(null)
+ ]
+ public DirectoryEntry SearchRoot
+ {
+ get
+ {
+ if (_searchRoot == null && !DesignMode)
+ {
+ // get the default naming context. This should be the default root for the search.
+ DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE", true, null, null, AuthenticationTypes.Secure);
+
+ //SECREVIEW: Searching the root of the DS will demand browse permissions
+ // on "*" or "LDAP://RootDSE".
+ string defaultNamingContext = (string)rootDSE.Properties["defaultNamingContext"][0];
+ rootDSE.Dispose();
+
+ _searchRoot = new DirectoryEntry("LDAP://" + defaultNamingContext, true, null, null, AuthenticationTypes.Secure);
+ _rootEntryAllocated = true;
+ _assertDefaultNamingContext = "LDAP://" + defaultNamingContext;
+ }
+ return _searchRoot;
+ }
+ set
+ {
+ if (_rootEntryAllocated)
+ _searchRoot.Dispose();
+ _rootEntryAllocated = false;
+
+ _assertDefaultNamingContext = null;
+ _searchRoot = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.Sort"]/*' />
+ /// <devdoc>
+ /// <para>Gets the property on which the results should be
+ /// sorted.</para>
+ /// </devdoc>
+ [
+ DSDescriptionAttribute(Res.DSSort),
+ TypeConverterAttribute(typeof(ExpandableObjectConverter)),
+ DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
+ ]
+ public SortOption Sort
+ {
+ get
+ {
+ return _sort;
+ }
+
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _sort = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.Asynchronous"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value indicating whether searches should be carried out in an asynchronous
+ /// way.</para>
+ /// </devdoc>
+ [
+ DefaultValue(false),
+ DSDescriptionAttribute(Res.DSAsynchronous)
+ ]
+ public bool Asynchronous
+ {
+ get
+ {
+ return _asynchronous;
+ }
+ set
+ {
+ _asynchronous = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.Tombstone"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value indicateing whether the search should also return deleted objects that match the search
+ /// filter.</para>
+ /// </devdoc>
+ [
+ DefaultValue(false),
+ DSDescriptionAttribute(Res.DSTombstone)
+ ]
+ public bool Tombstone
+ {
+ get
+ {
+ return _tombstone;
+ }
+ set
+ {
+ _tombstone = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.AttributeScopeQuery"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets an attribute name to indicate that an attribute-scoped query search should be
+ /// performed.</para>
+ /// </devdoc>
+ [
+ DefaultValue(""),
+ DSDescriptionAttribute(Res.DSAttributeQuery),
+ TypeConverter("System.Diagnostics.Design.StringValueConverter, " + AssemblyRef.SystemDesign)
+ ]
+ public string AttributeScopeQuery
+ {
+ get
+ {
+ return _attributeScopeQuery;
+ }
+ set
+ {
+ if (value == null)
+ value = "";
+
+ // user explicitly set AttributeScopeQuery and value is not null or empty string
+ if (value.Length != 0)
+ {
+ if (_scopeSpecified == true && SearchScope != SearchScope.Base)
+ {
+ throw new ArgumentException(Res.GetString(Res.DSBadASQSearchScope));
+ }
+
+ // if user did not explicitly set search scope
+ _scope = SearchScope.Base;
+
+ _attributeScopeQuerySpecified = true;
+ }
+ else
+ // user explicitly sets the value to default one and doesn't want to do asq
+ {
+ _attributeScopeQuerySpecified = false;
+ }
+
+ _attributeScopeQuery = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DerefAlias"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate how the aliases of found objects are to be
+ /// resolved.</para>
+ /// </devdoc>
+ [
+ DefaultValue(DereferenceAlias.Never),
+ DSDescriptionAttribute(Res.DSDerefAlias)
+ ]
+ public DereferenceAlias DerefAlias
+ {
+ get
+ {
+ return _derefAlias;
+ }
+
+ set
+ {
+ if (value < DereferenceAlias.Never || value > DereferenceAlias.Always)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(DereferenceAlias));
+
+ _derefAlias = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.SecurityMasks"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate the search should return security access information for the specified
+ /// attributes.</para>
+ /// </devdoc>
+ [
+ DefaultValue(SecurityMasks.None),
+ DSDescriptionAttribute(Res.DSSecurityMasks)
+ ]
+ public SecurityMasks SecurityMasks
+ {
+ get
+ {
+ return _securityMask;
+ }
+ set
+ {
+ // make sure the behavior is consistent with native ADSI
+ if (value > (SecurityMasks.None | SecurityMasks.Owner | SecurityMasks.Group | SecurityMasks.Dacl | SecurityMasks.Sacl))
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(SecurityMasks));
+
+ _securityMask = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.ExtendedDn"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to return extended DNs according to the requested
+ /// format.</para>
+ /// </devdoc>
+ [
+ DefaultValue(ExtendedDN.None),
+ DSDescriptionAttribute(Res.DSExtendedDn)
+ ]
+ public ExtendedDN ExtendedDN
+ {
+ get
+ {
+ return _extendedDN;
+ }
+ set
+ {
+ if (value < ExtendedDN.None || value > ExtendedDN.Standard)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(ExtendedDN));
+
+ _extendedDN = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.DirectorySynchronization"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate a directory synchronization search, which returns all changes since a specified
+ /// state.</para>
+ /// </devdoc>
+ [
+ DefaultValue(null),
+ DSDescriptionAttribute(Res.DSDirectorySynchronization),
+ Browsable(false)
+ ]
+ public DirectorySynchronization DirectorySynchronization
+ {
+ get
+ {
+ // if user specifies dirsync search preference and search is executed
+ if (directorySynchronizationSpecified && searchResult != null)
+ {
+ _sync.ResetDirectorySynchronizationCookie(searchResult.DirsyncCookie);
+ }
+ return _sync;
+ }
+
+ set
+ {
+ // specify non-zero pagesize explicitly and also want dirsync
+ if (value != null)
+ {
+ if (PageSize != 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadPageSizeDirsync));
+
+ directorySynchronizationSpecified = true;
+ }
+ else
+ // user explicitly sets the value to default one and doesn't want to do dirsync
+ {
+ directorySynchronizationSpecified = false;
+ }
+
+ _sync = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.VirtualListView"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate the search should use the LDAP virtual list view (VLV)
+ /// control.</para>
+ /// </devdoc>
+ [
+ DefaultValue(null),
+ DSDescriptionAttribute(Res.DSVirtualListView),
+ Browsable(false)
+ ]
+ public DirectoryVirtualListView VirtualListView
+ {
+ get
+ {
+ // if user specifies dirsync search preference and search is executed
+ if (directoryVirtualListViewSpecified && searchResult != null)
+ {
+ DirectoryVirtualListView tempval = searchResult.VLVResponse;
+ _vlv.Offset = tempval.Offset;
+ _vlv.ApproximateTotal = tempval.ApproximateTotal;
+ _vlv.DirectoryVirtualListViewContext = tempval.DirectoryVirtualListViewContext;
+ if (_vlv.ApproximateTotal != 0)
+ _vlv.TargetPercentage = (int)((double)_vlv.Offset / _vlv.ApproximateTotal * 100);
+ else
+ _vlv.TargetPercentage = 0;
+ }
+ return _vlv;
+ }
+ set
+ {
+ // if user explicitly set CacheResults to true and also want to set VLV
+ if (value != null)
+ {
+ if (_cacheResultsSpecified == true && CacheResults == true)
+ throw new ArgumentException(Res.GetString(Res.DSBadCacheResultsVLV));
+
+ directoryVirtualListViewSpecified = true;
+ // if user does not explicit specify cache results to true and also do vlv, then cache results is default to false
+ _cacheResults = false;
+ }
+ else
+ // user explicitly sets the value to default one and doesn't want to do vlv
+ {
+ directoryVirtualListViewSpecified = false;
+ }
+
+ _vlv = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.FindOne"]/*' />
+ /// <devdoc>
+ /// <para>Executes the search and returns only the first entry that is found.</para>
+ /// </devdoc>
+ public SearchResult FindOne()
+ {
+ DirectorySynchronization tempsync = null;
+ DirectoryVirtualListView tempvlv = null;
+ SearchResult resultEntry = null;
+
+ SearchResultCollection results = FindAll(false);
+
+ try
+ {
+ foreach (SearchResult entry in results)
+ {
+ // need to get the dirsync cookie
+ if (directorySynchronizationSpecified)
+ tempsync = DirectorySynchronization;
+
+ // need to get the vlv response
+ if (directoryVirtualListViewSpecified)
+ tempvlv = VirtualListView;
+
+ resultEntry = entry;
+ break;
+ }
+ }
+ finally
+ {
+ searchResult = null;
+
+ // still need to properly release the resource
+ results.Dispose();
+ }
+
+ return resultEntry;
+ }
+
+ /// <include file='doc\DirectorySearcher.uex' path='docs/doc[@for="DirectorySearcher.FindAll"]/*' />
+ /// <devdoc>
+ /// <para> Executes the search and returns a collection of the entries that are found.</para>
+ /// </devdoc>
+ public SearchResultCollection FindAll()
+ {
+ return FindAll(true);
+ }
+
+ private SearchResultCollection FindAll(bool findMoreThanOne)
+ {
+ searchResult = null;
+
+ DirectoryEntry clonedRoot = null;
+ if (_assertDefaultNamingContext == null)
+ {
+ clonedRoot = SearchRoot.CloneBrowsable();
+ }
+ else
+ {
+ clonedRoot = SearchRoot.CloneBrowsable();
+ }
+
+ UnsafeNativeMethods.IAds adsObject = clonedRoot.AdsObject;
+ if (!(adsObject is UnsafeNativeMethods.IDirectorySearch))
+ throw new NotSupportedException(Res.GetString(Res.DSSearchUnsupported, SearchRoot.Path));
+
+ // this is a little bit hacky, but we need to perform a bind here, so we make sure the LDAP connection that we hold has more than
+ // one reference count, one by SearchResultCollection object, one by DirectorySearcher object. In this way, when user calls
+ // Dispose on SearchResultCollection, the connection is still there instead of reference count dropping to zero and being closed.
+ // It is especially important for virtuallistview case, in order to reuse the vlv response, the search must be performed on the same ldap connection
+
+ // only do it when vlv is used
+ if (directoryVirtualListViewSpecified)
+ {
+ SearchRoot.Bind(true);
+ }
+
+ UnsafeNativeMethods.IDirectorySearch adsSearch = (UnsafeNativeMethods.IDirectorySearch)adsObject;
+ SetSearchPreferences(adsSearch, findMoreThanOne);
+
+ string[] properties = null;
+ if (PropertiesToLoad.Count > 0)
+ {
+ if (!PropertiesToLoad.Contains("ADsPath"))
+ {
+ // if we don't get this property, we won't be able to return a list of DirectoryEntry objects!
+ PropertiesToLoad.Add("ADsPath");
+ }
+ properties = new string[PropertiesToLoad.Count];
+ PropertiesToLoad.CopyTo(properties, 0);
+ }
+
+ IntPtr resultsHandle;
+ if (properties != null)
+ adsSearch.ExecuteSearch(Filter, properties, properties.Length, out resultsHandle);
+ else
+ {
+ adsSearch.ExecuteSearch(Filter, null, -1, out resultsHandle);
+ properties = new string[0];
+ }
+
+ SearchResultCollection result = new SearchResultCollection(clonedRoot, resultsHandle, properties, this);
+ searchResult = result;
+ return result;
+ }
+
+ private unsafe void SetSearchPreferences(UnsafeNativeMethods.IDirectorySearch adsSearch, bool findMoreThanOne)
+ {
+ ArrayList prefList = new ArrayList();
+ AdsSearchPreferenceInfo info;
+
+ // search scope
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.SEARCH_SCOPE;
+ info.vValue = new AdsValueHelper((int)SearchScope).GetStruct();
+ prefList.Add(info);
+
+ // size limit
+ if (_sizeLimit != 0 || !findMoreThanOne)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.SIZE_LIMIT;
+ info.vValue = new AdsValueHelper(findMoreThanOne ? SizeLimit : 1).GetStruct();
+ prefList.Add(info);
+ }
+
+ // time limit
+ if (ServerTimeLimit >= new TimeSpan(0))
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.TIME_LIMIT;
+ info.vValue = new AdsValueHelper((int)ServerTimeLimit.TotalSeconds).GetStruct();
+ prefList.Add(info);
+ }
+
+ // propertyNamesOnly
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.ATTRIBTYPES_ONLY;
+ info.vValue = new AdsValueHelper(PropertyNamesOnly).GetStruct();
+ prefList.Add(info);
+
+ // Timeout
+ if (ClientTimeout >= new TimeSpan(0))
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.TIMEOUT;
+ info.vValue = new AdsValueHelper((int)ClientTimeout.TotalSeconds).GetStruct();
+ prefList.Add(info);
+ }
+
+ // page size
+ if (PageSize != 0)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.PAGESIZE;
+ info.vValue = new AdsValueHelper(PageSize).GetStruct();
+ prefList.Add(info);
+ }
+
+ // page time limit
+ if (ServerPageTimeLimit >= new TimeSpan(0))
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.PAGED_TIME_LIMIT;
+ info.vValue = new AdsValueHelper((int)ServerPageTimeLimit.TotalSeconds).GetStruct();
+ prefList.Add(info);
+ }
+
+ // chase referrals
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.CHASE_REFERRALS;
+ info.vValue = new AdsValueHelper((int)ReferralChasing).GetStruct();
+ prefList.Add(info);
+
+ // asynchronous
+ if (Asynchronous == true)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.ASYNCHRONOUS;
+ info.vValue = new AdsValueHelper(Asynchronous).GetStruct();
+ prefList.Add(info);
+ }
+
+ // tombstone
+ if (Tombstone == true)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.TOMBSTONE;
+ info.vValue = new AdsValueHelper(Tombstone).GetStruct();
+ prefList.Add(info);
+ }
+
+ // attributescopequery
+ if (_attributeScopeQuerySpecified)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.ATTRIBUTE_QUERY;
+ info.vValue = new AdsValueHelper(AttributeScopeQuery, AdsType.ADSTYPE_CASE_IGNORE_STRING).GetStruct();
+ prefList.Add(info);
+ }
+
+ // derefalias
+ if (DerefAlias != DereferenceAlias.Never)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.DEREF_ALIASES;
+ info.vValue = new AdsValueHelper((int)DerefAlias).GetStruct();
+ prefList.Add(info);
+ }
+
+ // securitymask
+ if (SecurityMasks != SecurityMasks.None)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.SECURITY_MASK;
+ info.vValue = new AdsValueHelper((int)SecurityMasks).GetStruct();
+ prefList.Add(info);
+ }
+
+ // extendeddn
+ if (ExtendedDN != ExtendedDN.None)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.EXTENDED_DN;
+ info.vValue = new AdsValueHelper((int)ExtendedDN).GetStruct();
+ prefList.Add(info);
+ }
+
+ // dirsync
+ if (directorySynchronizationSpecified)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.DIRSYNC;
+ info.vValue = new AdsValueHelper(DirectorySynchronization.GetDirectorySynchronizationCookie(), AdsType.ADSTYPE_PROV_SPECIFIC).GetStruct();
+ prefList.Add(info);
+
+ if (DirectorySynchronization.Option != DirectorySynchronizationOptions.None)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.DIRSYNC_FLAG;
+ info.vValue = new AdsValueHelper((int)DirectorySynchronization.Option).GetStruct();
+ prefList.Add(info);
+ }
+ }
+
+ IntPtr ptrToFree = (IntPtr)0;
+ IntPtr ptrVLVToFree = (IntPtr)0;
+ IntPtr ptrVLVContexToFree = (IntPtr)0;
+
+ try
+ {
+ // sort
+ if (Sort.PropertyName != null && Sort.PropertyName.Length > 0)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.SORT_ON;
+ AdsSortKey sortKey = new AdsSortKey();
+ sortKey.pszAttrType = Marshal.StringToCoTaskMemUni(Sort.PropertyName);
+ ptrToFree = sortKey.pszAttrType; // so we can free it later.
+ sortKey.pszReserved = (IntPtr)0;
+ sortKey.fReverseOrder = (Sort.Direction == SortDirection.Descending) ? -1 : 0;
+ byte[] sortKeyBytes = new byte[Marshal.SizeOf(sortKey)];
+ Marshal.Copy((INTPTR_INTPTRCAST)(&sortKey), sortKeyBytes, 0, sortKeyBytes.Length);
+ info.vValue = new AdsValueHelper(sortKeyBytes, AdsType.ADSTYPE_PROV_SPECIFIC).GetStruct();
+ prefList.Add(info);
+ }
+
+ // vlv
+ if (directoryVirtualListViewSpecified)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.VLV;
+ AdsVLV vlvValue = new AdsVLV();
+ vlvValue.beforeCount = _vlv.BeforeCount;
+ vlvValue.afterCount = _vlv.AfterCount;
+ vlvValue.offset = _vlv.Offset;
+ //we need to treat the empty string as null here
+ if (_vlv.Target.Length != 0)
+ vlvValue.target = Marshal.StringToCoTaskMemUni(_vlv.Target);
+ else
+ vlvValue.target = IntPtr.Zero;
+ ptrVLVToFree = vlvValue.target;
+ if (_vlv.DirectoryVirtualListViewContext == null)
+ {
+ vlvValue.contextIDlength = 0;
+ vlvValue.contextID = (IntPtr)0;
+ }
+ else
+ {
+ vlvValue.contextIDlength = _vlv.DirectoryVirtualListViewContext.context.Length;
+ vlvValue.contextID = Marshal.AllocCoTaskMem(vlvValue.contextIDlength);
+ ptrVLVContexToFree = vlvValue.contextID;
+ Marshal.Copy(_vlv.DirectoryVirtualListViewContext.context, 0, vlvValue.contextID, vlvValue.contextIDlength);
+ }
+ IntPtr vlvPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(AdsVLV)));
+ byte[] vlvBytes = new byte[Marshal.SizeOf(vlvValue)];
+ try
+ {
+ Marshal.StructureToPtr(vlvValue, vlvPtr, false);
+ Marshal.Copy(vlvPtr, vlvBytes, 0, vlvBytes.Length);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(vlvPtr);
+ }
+ info.vValue = new AdsValueHelper(vlvBytes, AdsType.ADSTYPE_PROV_SPECIFIC).GetStruct();
+ prefList.Add(info);
+ }
+
+ // cacheResults
+ if (_cacheResultsSpecified)
+ {
+ info = new AdsSearchPreferenceInfo();
+ info.dwSearchPref = (int)AdsSearchPreferences.CACHE_RESULTS;
+ info.vValue = new AdsValueHelper(CacheResults).GetStruct();
+ prefList.Add(info);
+ }
+
+ //
+ // now make the call
+ //
+ AdsSearchPreferenceInfo[] prefs = new AdsSearchPreferenceInfo[prefList.Count];
+ for (int i = 0; i < prefList.Count; i++)
+ {
+ prefs[i] = (AdsSearchPreferenceInfo)prefList[i];
+ }
+
+ DoSetSearchPrefs(adsSearch, prefs);
+ }
+ finally
+ {
+ if (ptrToFree != (IntPtr)0)
+ Marshal.FreeCoTaskMem(ptrToFree);
+
+ if (ptrVLVToFree != (IntPtr)0)
+ Marshal.FreeCoTaskMem(ptrVLVToFree);
+
+ if (ptrVLVContexToFree != (IntPtr)0)
+ Marshal.FreeCoTaskMem(ptrVLVContexToFree);
+ }
+ }
+
+ private static void DoSetSearchPrefs(UnsafeNativeMethods.IDirectorySearch adsSearch, AdsSearchPreferenceInfo[] prefs)
+ {
+ int structSize = Marshal.SizeOf(typeof(AdsSearchPreferenceInfo));
+ IntPtr ptr = Marshal.AllocHGlobal((IntPtr)(structSize * prefs.Length));
+ try
+ {
+ IntPtr tempPtr = ptr;
+ for (int i = 0; i < prefs.Length; i++)
+ {
+ Marshal.StructureToPtr(prefs[i], tempPtr, false);
+ tempPtr = IntPtr.Add(tempPtr, structSize);
+ }
+
+ adsSearch.SetSearchPreference(ptr, prefs.Length);
+
+ // Check for the result status for all preferences
+ tempPtr = ptr;
+ for (int i = 0; i < prefs.Length; i++)
+ {
+ int status = Marshal.ReadInt32(tempPtr, 32);
+ if (status != 0)
+ {
+ int prefIndex = prefs[i].dwSearchPref;
+ string property = "";
+ switch (prefIndex)
+ {
+ case (int)AdsSearchPreferences.SEARCH_SCOPE:
+ property = "SearchScope";
+ break;
+ case (int)AdsSearchPreferences.SIZE_LIMIT:
+ property = "SizeLimit";
+ break;
+ case (int)AdsSearchPreferences.TIME_LIMIT:
+ property = "ServerTimeLimit";
+ break;
+ case (int)AdsSearchPreferences.ATTRIBTYPES_ONLY:
+ property = "PropertyNamesOnly";
+ break;
+ case (int)AdsSearchPreferences.TIMEOUT:
+ property = "ClientTimeout";
+ break;
+ case (int)AdsSearchPreferences.PAGESIZE:
+ property = "PageSize";
+ break;
+ case (int)AdsSearchPreferences.PAGED_TIME_LIMIT:
+ property = "ServerPageTimeLimit";
+ break;
+ case (int)AdsSearchPreferences.CHASE_REFERRALS:
+ property = "ReferralChasing";
+ break;
+ case (int)AdsSearchPreferences.SORT_ON:
+ property = "Sort";
+ break;
+ case (int)AdsSearchPreferences.CACHE_RESULTS:
+ property = "CacheResults";
+ break;
+ case (int)AdsSearchPreferences.ASYNCHRONOUS:
+ property = "Asynchronous";
+ break;
+ case (int)AdsSearchPreferences.TOMBSTONE:
+ property = "Tombstone";
+ break;
+ case (int)AdsSearchPreferences.ATTRIBUTE_QUERY:
+ property = "AttributeScopeQuery";
+ break;
+ case (int)AdsSearchPreferences.DEREF_ALIASES:
+ property = "DerefAlias";
+ break;
+ case (int)AdsSearchPreferences.SECURITY_MASK:
+ property = "SecurityMasks";
+ break;
+ case (int)AdsSearchPreferences.EXTENDED_DN:
+ property = "ExtendedDn";
+ break;
+ case (int)AdsSearchPreferences.DIRSYNC:
+ property = "DirectorySynchronization";
+ break;
+ case (int)AdsSearchPreferences.DIRSYNC_FLAG:
+ property = "DirectorySynchronizationFlag";
+ break;
+ case (int)AdsSearchPreferences.VLV:
+ property = "VirtualListView";
+ break;
+ }
+ throw new InvalidOperationException(Res.GetString(Res.DSSearchPreferencesNotAccepted, property));
+ }
+
+ tempPtr = IntPtr.Add(tempPtr, structSize);
+ }
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesCOMException.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesCOMException.cs
new file mode 100644
index 0000000000..d37a6bcc5d
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesCOMException.cs
@@ -0,0 +1,90 @@
+// 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
+{
+ using System;
+ using System.Text;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.DirectoryServices.Interop;
+ using System.Security.Permissions;
+
+ [Serializable]
+ public class DirectoryServicesCOMException : COMException, ISerializable
+ {
+ private int _extendederror = 0;
+ private string _extendedmessage = "";
+
+ public DirectoryServicesCOMException() { }
+ public DirectoryServicesCOMException(string message) : base(message) { }
+ public DirectoryServicesCOMException(string message, Exception inner) : base(message, inner) { }
+ protected DirectoryServicesCOMException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+
+ internal DirectoryServicesCOMException(string extendedMessage, int extendedError, COMException e) : base(e.Message, e.ErrorCode)
+ {
+ _extendederror = extendedError;
+ _extendedmessage = extendedMessage;
+ }
+
+ public int ExtendedError
+ {
+ get
+ {
+ return _extendederror;
+ }
+ }
+
+ public string ExtendedErrorMessage
+ {
+ get
+ {
+ return _extendedmessage;
+ }
+ }
+
+ [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ }
+ }
+
+ internal class COMExceptionHelper
+ {
+ internal static Exception CreateFormattedComException(int hr)
+ {
+ string errorMsg = "";
+ StringBuilder sb = new StringBuilder(256);
+ int result = SafeNativeMethods.FormatMessageW(SafeNativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS |
+ SafeNativeMethods.FORMAT_MESSAGE_FROM_SYSTEM |
+ SafeNativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ 0, hr, 0, sb, sb.Capacity + 1, 0);
+ if (result != 0)
+ {
+ errorMsg = sb.ToString(0, result);
+ }
+ else
+ {
+ errorMsg = Res.GetString(Res.DSUnknown, Convert.ToString(hr, 16));
+ }
+
+ return CreateFormattedComException(new COMException(errorMsg, hr));
+ }
+
+ internal static Exception CreateFormattedComException(COMException e)
+ {
+ // get extended error information
+ StringBuilder errorBuffer = new StringBuilder(256);
+ StringBuilder nameBuffer = new StringBuilder();
+ int error = 0;
+ SafeNativeMethods.ADsGetLastError(out error, errorBuffer, 256, nameBuffer, 0);
+
+ if (error != 0)
+ return new DirectoryServicesCOMException(errorBuffer.ToString(), error, e);
+ else
+ return e;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermission.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermission.cs
new file mode 100644
index 0000000000..eaa2d7cad6
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermission.cs
@@ -0,0 +1,92 @@
+
+namespace System.DirectoryServices {
+ using System;
+ using System.Security.Permissions;
+
+ /// <include file='doc\DirectoryServicesPermission.uex' path='docs/doc[@for="DirectoryServicesPermission"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ [
+ Serializable()
+ ]
+ public sealed class DirectoryServicesPermission : ResourcePermissionBase {
+ private DirectoryServicesPermissionEntryCollection innerCollection;
+
+ /// <include file='doc\DirectoryServicesPermission.uex' path='docs/doc[@for="DirectoryServicesPermission.DirectoryServicesPermission"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryServicesPermission() {
+ SetNames();
+ }
+
+ /// <include file='doc\DirectoryServicesPermission.uex' path='docs/doc[@for="DirectoryServicesPermission.DirectoryServicesPermission1"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryServicesPermission(PermissionState state)
+ : base(state) {
+ SetNames();
+ }
+
+ /// <include file='doc\DirectoryServicesPermission.uex' path='docs/doc[@for="DirectoryServicesPermission.DirectoryServicesPermission2"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryServicesPermission(DirectoryServicesPermissionAccess permissionAccess, string path) {
+ SetNames();
+ this.AddPermissionAccess(new DirectoryServicesPermissionEntry(permissionAccess, path));
+ }
+
+ /// <include file='doc\DirectoryServicesPermission.uex' path='docs/doc[@for="DirectoryServicesPermission.DirectoryServicesPermission3"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryServicesPermission(DirectoryServicesPermissionEntry[] permissionAccessEntries) {
+ if (permissionAccessEntries == null)
+ throw new ArgumentNullException("permissionAccessEntries");
+
+ SetNames();
+ for (int index = 0; index < permissionAccessEntries.Length; ++index)
+ this.AddPermissionAccess(permissionAccessEntries[index]);
+ }
+
+ /// <include file='doc\DirectoryServicesPermission.uex' path='docs/doc[@for="DirectoryServicesPermission.PermissionEntries"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryServicesPermissionEntryCollection PermissionEntries {
+ get {
+ if (this.innerCollection == null)
+ this.innerCollection = new DirectoryServicesPermissionEntryCollection(this, base.GetPermissionEntries());
+
+ return this.innerCollection;
+ }
+ }
+
+ /// <include file='doc\DirectoryServicesPermission.uex' path='docs/doc[@for="DirectoryServicesPermission.AddPermissionAccess"]/*' />
+ ///<internalonly/>
+ internal void AddPermissionAccess(DirectoryServicesPermissionEntry entry) {
+ base.AddPermissionAccess(entry.GetBaseEntry());
+ }
+
+ /// <include file='doc\DirectoryServicesPermission.uex' path='docs/doc[@for="DirectoryServicesPermission.Clear"]/*' />
+ ///<internalonly/>
+ internal new void Clear() {
+ base.Clear();
+ }
+
+ /// <include file='doc\DirectoryServicesPermission.uex' path='docs/doc[@for="DirectoryServicesPermission.RemovePermissionAccess"]/*' />
+ ///<internalonly/>
+ internal void RemovePermissionAccess(DirectoryServicesPermissionEntry entry) {
+ base.RemovePermissionAccess(entry.GetBaseEntry());
+ }
+
+ private void SetNames() {
+ this.PermissionAccessType = typeof(DirectoryServicesPermissionAccess);
+ this.TagNames = new string[]{"Path"};
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionAccess.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionAccess.cs
new file mode 100644
index 0000000000..a8616718dc
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionAccess.cs
@@ -0,0 +1,28 @@
+
+namespace System.DirectoryServices {
+
+ /// <include file='doc\DirectoryServicesPermissionAccess.uex' path='docs/doc[@for="DirectoryServicesPermissionAccess"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ [Flags]
+ public enum DirectoryServicesPermissionAccess {
+ /// <include file='doc\DirectoryServicesPermissionAccess.uex' path='docs/doc[@for="DirectoryServicesPermissionAccess.None"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ None = 0,
+ /// <include file='doc\DirectoryServicesPermissionAccess.uex' path='docs/doc[@for="DirectoryServicesPermissionAccess.Browse"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ Browse = 1 << 1,
+ /// <include file='doc\DirectoryServicesPermissionAccess.uex' path='docs/doc[@for="DirectoryServicesPermissionAccess.Write"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ Write = 1 << 2 | Browse,
+ }
+}
+
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionAttribute.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionAttribute.cs
new file mode 100644
index 0000000000..9ed558fe9a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionAttribute.cs
@@ -0,0 +1,59 @@
+
+namespace System.DirectoryServices {
+ using System.Security;
+ using System.Security.Permissions;
+
+ /// <include file='doc\DirectoryServicesPermissionAttribute.uex' path='docs/doc[@for="DirectoryServicesPermissionAttribute"]/*' />
+ [
+ AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly | AttributeTargets.Event, AllowMultiple = true, Inherited = false ),
+ Serializable()
+ ]
+ public class DirectoryServicesPermissionAttribute : CodeAccessSecurityAttribute {
+ private string path;
+ private DirectoryServicesPermissionAccess permissionAccess;
+
+ /// <include file='doc\DirectoryServicesPermissionAttribute.uex' path='docs/doc[@for="DirectoryServicesPermissionAttribute.DirectoryServicesPermissionAttribute"]/*' />
+ public DirectoryServicesPermissionAttribute(SecurityAction action)
+ : base(action) {
+ this.path = "*";
+ this.permissionAccess = DirectoryServicesPermissionAccess.Browse;
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionAttribute.uex' path='docs/doc[@for="DirectoryServicesPermissionAttribute.Path"]/*' />
+ public string Path {
+ get {
+ return this.path;
+ }
+
+ set {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ this.path = value;
+ }
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionAttribute.uex' path='docs/doc[@for="DirectoryServicesPermissionAttribute.PermissionAccess"]/*' />
+ public DirectoryServicesPermissionAccess PermissionAccess {
+ get {
+ return this.permissionAccess;
+ }
+
+ set {
+ this.permissionAccess = value;
+ }
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionAttribute.uex' path='docs/doc[@for="DirectoryServicesPermissionAttribute.CreatePermission"]/*' />
+ public override IPermission CreatePermission() {
+ if (Unrestricted)
+ return new DirectoryServicesPermission(PermissionState.Unrestricted);
+
+ DirectoryServicesPermissionAccess tmpAccess = this.permissionAccess;
+ string tmpPath = this.Path;
+ return new DirectoryServicesPermission(tmpAccess, tmpPath);
+
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionEntry.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionEntry.cs
new file mode 100644
index 0000000000..b0f3c27e21
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionEntry.cs
@@ -0,0 +1,57 @@
+//----------------------------------------------------
+// <copyright file="DirectoryServicesPermissionEntry.cs" company="Microsoft">
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// </copyright>
+//------------------------------------------------------------------------------
+
+namespace System.DirectoryServices {
+ using System.Security.Permissions;
+
+ /// <include file='doc\DirectoryServicesPermissionEntry.uex' path='docs/doc[@for="DirectoryServicesPermissionEntry"]/*' />
+ [
+ Serializable()
+ ]
+ public class DirectoryServicesPermissionEntry {
+ private string path;
+ private DirectoryServicesPermissionAccess permissionAccess;
+
+ /// <include file='doc\DirectoryServicesPermissionEntry.uex' path='docs/doc[@for="DirectoryServicesPermissionEntry.DirectoryServicesPermissionEntry"]/*' />
+ public DirectoryServicesPermissionEntry(DirectoryServicesPermissionAccess permissionAccess, string path) {
+ if (path == null)
+ throw new ArgumentNullException("path");
+
+ this.permissionAccess = permissionAccess;
+ this.path = path;
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntry.uex' path='docs/doc[@for="DirectoryServicesPermissionEntry.DirectoryServicesPermissionEntry1"]/*' />
+ ///<internalonly/>
+ internal DirectoryServicesPermissionEntry(ResourcePermissionBaseEntry baseEntry) {
+ this.permissionAccess = (DirectoryServicesPermissionAccess)baseEntry.PermissionAccess;
+ this.path = baseEntry.PermissionAccessPath[0];
+ }
+
+
+ /// <include file='doc\DirectoryServicesPermissionEntry.uex' path='docs/doc[@for="DirectoryServicesPermissionEntry.Path"]/*' />
+ public string Path {
+ get {
+ return this.path;
+ }
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntry.uex' path='docs/doc[@for="DirectoryServicesPermissionEntry.PermissionAccess"]/*' />
+ public DirectoryServicesPermissionAccess PermissionAccess {
+ get {
+ return this.permissionAccess;
+ }
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntry.uex' path='docs/doc[@for="DirectoryServicesPermissionEntry.GetBaseEntry"]/*' />
+ ///<internalonly/>
+ internal ResourcePermissionBaseEntry GetBaseEntry() {
+ ResourcePermissionBaseEntry baseEntry = new ResourcePermissionBaseEntry((int)this.PermissionAccess, new string[] {this.Path});
+ return baseEntry;
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionEntryCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionEntryCollection.cs
new file mode 100644
index 0000000000..dca525b984
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryServicesPermissionEntryCollection.cs
@@ -0,0 +1,118 @@
+//----------------------------------------------------
+// <copyright file="DirectoryServicesPermissionEntryCollection.cs" company="Microsoft">
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// </copyright>
+//------------------------------------------------------------------------------
+
+namespace System.DirectoryServices {
+ using System.Security.Permissions;
+ using System.Collections;
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection"]/*' />
+ [
+ Serializable()
+ ]
+ public class DirectoryServicesPermissionEntryCollection : CollectionBase {
+ DirectoryServicesPermission owner;
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.DirectoryServicesPermissionEntryCollection"]/*' />
+ ///<internalonly/>
+ internal DirectoryServicesPermissionEntryCollection(DirectoryServicesPermission owner, ResourcePermissionBaseEntry[] entries) {
+ this.owner = owner;
+ for (int index = 0; index < entries.Length; ++index)
+ this.InnerList.Add(new DirectoryServicesPermissionEntry(entries[index]));
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.DirectoryServicesPermissionEntryCollection"]/*' />
+ internal DirectoryServicesPermissionEntryCollection() {
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.this"]/*' />
+ public DirectoryServicesPermissionEntry this[int index] {
+ get {
+ return (DirectoryServicesPermissionEntry)List[index];
+ }
+ set {
+ List[index] = value;
+ }
+
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.Add"]/*' />
+ public int Add(DirectoryServicesPermissionEntry value) {
+ return List.Add(value);
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.AddRange"]/*' />
+ public void AddRange(DirectoryServicesPermissionEntry[] value) {
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+ for (int i = 0; ((i) < (value.Length)); i = ((i) + (1))) {
+ this.Add(value[i]);
+ }
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.AddRange1"]/*' />
+ public void AddRange(DirectoryServicesPermissionEntryCollection value) {
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+ int currentCount = value.Count;
+ for (int i = 0; i < currentCount; i = ((i) + (1))) {
+ this.Add(value[i]);
+ }
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.Contains"]/*' />
+ public bool Contains(DirectoryServicesPermissionEntry value) {
+ return List.Contains(value);
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.CopyTo"]/*' />
+ public void CopyTo(DirectoryServicesPermissionEntry[] array, int index) {
+ List.CopyTo(array, index);
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.IndexOf"]/*' />
+ public int IndexOf(DirectoryServicesPermissionEntry value) {
+ return List.IndexOf(value);
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.Insert"]/*' />
+ public void Insert(int index, DirectoryServicesPermissionEntry value) {
+ List.Insert(index, value);
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.Remove"]/*' />
+ public void Remove(DirectoryServicesPermissionEntry value) {
+ List.Remove(value);
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.OnClear"]/*' />
+ ///<internalonly/>
+ protected override void OnClear() {
+ this.owner.Clear();
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.OnInsert"]/*' />
+ ///<internalonly/>
+ protected override void OnInsert(int index, object value) {
+ this.owner.AddPermissionAccess((DirectoryServicesPermissionEntry)value);
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.OnRemove"]/*' />
+ ///<internalonly/>
+ protected override void OnRemove(int index, object value) {
+ this.owner.RemovePermissionAccess((DirectoryServicesPermissionEntry)value);
+ }
+
+ /// <include file='doc\DirectoryServicesPermissionEntryCollection.uex' path='docs/doc[@for="DirectoryServicesPermissionEntryCollection.OnSet"]/*' />
+ ///<internalonly/>
+ protected override void OnSet(int index, object oldValue, object newValue) {
+ this.owner.RemovePermissionAccess((DirectoryServicesPermissionEntry)oldValue);
+ this.owner.AddPermissionAccess((DirectoryServicesPermissionEntry)newValue);
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectorySynchronization.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectorySynchronization.cs
new file mode 100644
index 0000000000..52fe5e7a93
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectorySynchronization.cs
@@ -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.
+
+namespace System.DirectoryServices
+{
+ using System.ComponentModel;
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization"]/*' />
+ /// <devdoc>
+ /// <para>Specifies how to do directory synchronization search.</para>
+ /// </devdoc>
+ public class DirectorySynchronization
+ {
+ private DirectorySynchronizationOptions _flag = DirectorySynchronizationOptions.None;
+ private byte[] _cookie = new byte[0];
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.DirectorySynchronization"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectorySynchronization()
+ {
+ }
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.DirectorySynchronization1"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectorySynchronization(DirectorySynchronizationOptions option)
+ {
+ Option = option;
+ }
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.DirectorySynchronization2"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectorySynchronization(DirectorySynchronization sync)
+ {
+ if (sync != null)
+ {
+ Option = sync.Option;
+ ResetDirectorySynchronizationCookie(sync.GetDirectorySynchronizationCookie());
+ }
+ }
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.DirectorySynchronization3"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectorySynchronization(byte[] cookie)
+ {
+ ResetDirectorySynchronizationCookie(cookie);
+ }
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.DirectorySynchronization4"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectorySynchronization(DirectorySynchronizationOptions option, byte[] cookie)
+ {
+ Option = option;
+ ResetDirectorySynchronizationCookie(cookie);
+ }
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.Flag"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the flag to do directory synchronization search.</para>
+ /// </devdoc>
+ [
+ DefaultValue(DirectorySynchronizationOptions.None),
+ DSDescriptionAttribute(Res.DSDirectorySynchronizationFlag)
+ ]
+ public DirectorySynchronizationOptions Option
+ {
+ get
+ {
+ return _flag;
+ }
+
+ set
+ {
+ long val = (long)(value & (~(DirectorySynchronizationOptions.None | DirectorySynchronizationOptions.ObjectSecurity |
+ DirectorySynchronizationOptions.ParentsFirst | DirectorySynchronizationOptions.PublicDataOnly |
+ DirectorySynchronizationOptions.IncrementalValues)));
+ if (val != 0)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(DirectorySynchronizationOptions));
+
+ _flag = value;
+ }
+ }
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.GetDirectorySynchronizationCookie"]/*' />
+ /// <devdoc>
+ /// <para>Gets the directory synchronization search cookie.</para>
+ /// </devdoc>
+ public byte[] GetDirectorySynchronizationCookie()
+ {
+ byte[] tempcookie = new byte[_cookie.Length];
+ for (int i = 0; i < _cookie.Length; i++)
+ {
+ tempcookie[i] = _cookie[i];
+ }
+
+ return tempcookie;
+ }
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.GetDirectorySynchronizationCookie1"]/*' />
+ /// <devdoc>
+ /// <para>Gets the directory synchronization search cookie.</para>
+ /// </devdoc>
+ public void ResetDirectorySynchronizationCookie()
+ {
+ _cookie = new byte[0];
+ }
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.ResetDirectorySynchronizationCookie"]/*' />
+ /// <devdoc>
+ /// <para>Resets the directory synchronization search cookie.</para>
+ /// </devdoc>
+ public void ResetDirectorySynchronizationCookie(byte[] cookie)
+ {
+ if (cookie == null)
+ _cookie = new byte[0];
+ else
+ {
+ _cookie = new byte[cookie.Length];
+ for (int i = 0; i < cookie.Length; i++)
+ {
+ _cookie[i] = cookie[i];
+ }
+ }
+ }
+
+ /// <include file='doc\DirectorySynchronization.uex' path='docs/doc[@for="DirectorySynchronization.Copy"]/*' />
+ /// <devdoc>
+ /// <para>Returns a copy of the current DirectorySynchronization instance.</para>
+ /// </devdoc>
+ public DirectorySynchronization Copy()
+ {
+ return new DirectorySynchronization(_flag, _cookie);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectorySynchronizationFlags.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectorySynchronizationFlags.cs
new file mode 100644
index 0000000000..c0f6c014ef
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectorySynchronizationFlags.cs
@@ -0,0 +1,16 @@
+// 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
+{
+ [Flags]
+ public enum DirectorySynchronizationOptions : long
+ {
+ None = 0,
+ ObjectSecurity = 0x1,
+ ParentsFirst = 0x0800,
+ PublicDataOnly = 0x2000,
+ IncrementalValues = 0x80000000
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryVirtualListView.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryVirtualListView.cs
new file mode 100644
index 0000000000..c5266f9a40
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryVirtualListView.cs
@@ -0,0 +1,250 @@
+// 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
+{
+ using System.ComponentModel;
+
+ /// <include file='doc\DirectoryVirtualListView.uex' path='docs/doc[@for="DirectoryVirtualListView"]/*' />
+ /// <devdoc>
+ /// <para>Specifies how to do directory virtual list view search.</para>
+ /// </devdoc>
+ public class DirectoryVirtualListView
+ {
+ private int _beforeCount = 0;
+ private int _afterCount = 0;
+ private int _offset = 0;
+ private string _target = "";
+ private int _approximateTotal = 0;
+ private int _targetPercentage = 0;
+ private DirectoryVirtualListViewContext _context = null;
+
+ /// <include file='doc\DirectoryVirtualListView.uex' path='docs/doc[@for="DirectoryVirtualListView.DirectoryVirtualListView"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryVirtualListView()
+ {
+ }
+
+ /// <include file='doc\DirectoryVirtualListView.uex' path='docs/doc[@for="DirectoryVirtualListView.DirectoryVirtualListView1"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryVirtualListView(int afterCount)
+ {
+ AfterCount = afterCount;
+ }
+
+ /// <include file='doc\DirectoryVirtualListView.uex' path='docs/doc[@for="DirectoryVirtualListView.DirectoryVirtualListView2"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryVirtualListView(int beforeCount, int afterCount, int offset)
+ {
+ BeforeCount = beforeCount;
+ AfterCount = afterCount;
+ Offset = offset;
+ }
+
+ /// <include file='doc\DirectoryVirtualListView.uex' path='docs/doc[@for="DirectoryVirtualListView.DirectoryVirtualListView3"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryVirtualListView(int beforeCount, int afterCount, string target)
+ {
+ BeforeCount = beforeCount;
+ AfterCount = afterCount;
+ Target = target;
+ }
+
+ /// <include file='doc\DirectoryVirtualListView.uex' path='docs/doc[@for="DirectoryVirtualListView.DirectoryVirtualListView4"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryVirtualListView(int beforeCount, int afterCount, int offset, DirectoryVirtualListViewContext context)
+ {
+ BeforeCount = beforeCount;
+ AfterCount = afterCount;
+ Offset = offset;
+ _context = context;
+ }
+
+ /// <include file='doc\DirectoryVirtualListView.uex' path='docs/doc[@for="DirectoryVirtualListView.DirectoryVirtualListView5"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryVirtualListView(int beforeCount, int afterCount, string target, DirectoryVirtualListViewContext context)
+ {
+ BeforeCount = beforeCount;
+ AfterCount = afterCount;
+ Target = target;
+ _context = context;
+ }
+
+ /// <include file='doc\DirectoryVirtualListView..uex' path='docs/doc[@for="DirectoryVirtualListView.BeforeCount"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate the number of entries before the target entry that the client is requesting from the server.</para>
+ /// </devdoc>
+ [
+ DefaultValue(0),
+ DSDescriptionAttribute(Res.DSBeforeCount)
+ ]
+ public int BeforeCount
+ {
+ get
+ {
+ return _beforeCount;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadBeforeCount));
+
+ _beforeCount = value;
+ }
+ }
+
+ /// <include file='doc\DirectoryVirtualListView..uex' path='docs/doc[@for="DirectoryVirtualListView.AfterCount"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate the number of entries after the target entry that the client is requesting from the server</para>
+ /// </devdoc>
+ [
+ DefaultValue(0),
+ DSDescriptionAttribute(Res.DSAfterCount)
+ ]
+ public int AfterCount
+ {
+ get
+ {
+ return _afterCount;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadAfterCount));
+
+ _afterCount = value;
+ }
+ }
+
+ /// <include file='doc\DirectoryVirtualListView..uex' path='docs/doc[@for="DirectoryVirtualListView.Offset"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate the estimated target entry's requested offset within the list.</para>
+ /// </devdoc>
+ [
+ DefaultValue(0),
+ DSDescriptionAttribute(Res.DSOffset)
+ ]
+ public int Offset
+ {
+ get
+ {
+ return _offset;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadOffset));
+
+ _offset = value;
+ if (_approximateTotal != 0)
+ _targetPercentage = (int)((double)_offset / _approximateTotal * 100);
+ else
+ _targetPercentage = 0;
+ }
+ }
+
+ /// <include file='doc\DirectoryVirtualListView..uex' path='docs/doc[@for="DirectoryVirtualListView.AfterCount"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate the offset percentage</para>
+ /// </devdoc>
+ [
+ DefaultValue(0),
+ DSDescriptionAttribute(Res.DSTargetPercentage)
+ ]
+ public int TargetPercentage
+ {
+ get
+ {
+ return _targetPercentage;
+ }
+ set
+ {
+ if (value > 100 || value < 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadTargetPercentage));
+
+ _targetPercentage = value;
+ _offset = _approximateTotal * _targetPercentage / 100;
+ }
+ }
+
+ /// <include file='doc\DirectoryVirtualListView..uex' path='docs/doc[@for="DirectoryVirtualListView.AfterCount"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate the desired target entry requested by the client.</para>
+ /// </devdoc>
+ [
+ DefaultValue(""),
+ DSDescriptionAttribute(Res.DSTarget),
+ TypeConverter("System.Diagnostics.Design.StringValueConverter, " + AssemblyRef.SystemDesign)
+ ]
+ public string Target
+ {
+ get
+ {
+ return _target;
+ }
+ set
+ {
+ if (value == null)
+ value = "";
+
+ _target = value;
+ }
+ }
+
+ /// <include file='doc\DirectoryVirtualListView..uex' path='docs/doc[@for="DirectoryVirtualListView.AfterCount"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate the estimated total count.</para>
+ /// </devdoc>
+ [
+ DefaultValue(0),
+ DSDescriptionAttribute(Res.DSApproximateTotal)
+ ]
+ public int ApproximateTotal
+ {
+ get
+ {
+ return _approximateTotal;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException(Res.GetString(Res.DSBadApproximateTotal));
+
+ _approximateTotal = value;
+ }
+ }
+
+ /// <include file='doc\DirectoryVirtualListView..uex' path='docs/doc[@for="DirectoryVirtualListView.AfterCount"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets a value to indicate the virtual list view search response.</para>
+ /// </devdoc>
+ [
+ DefaultValue(null),
+ DSDescriptionAttribute(Res.DSDirectoryVirtualListViewContext)
+ ]
+ public DirectoryVirtualListViewContext DirectoryVirtualListViewContext
+ {
+ get
+ {
+ return _context;
+ }
+ set
+ {
+ _context = value;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryVirtualListViewContext.cs b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryVirtualListViewContext.cs
new file mode 100644
index 0000000000..ac4d47ae87
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/DirectoryVirtualListViewContext.cs
@@ -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.
+
+namespace System.DirectoryServices
+{
+ /// <include file='doc\DirectoryVirtualListViewContext.uex' path='docs/doc[@for="DirectoryVirtualListViewContext"]/*' />
+ /// <devdoc>
+ /// <para>Specifies how to construct directory virtual list view response.</para>
+ /// </devdoc>
+ public class DirectoryVirtualListViewContext
+ {
+ internal byte[] context;
+
+ /// <include file='doc\DirectoryVirtualListViewContext.uex' path='docs/doc[@for="DirectoryVirtualListViewContext.DirectoryVirtualListViewContext"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public DirectoryVirtualListViewContext() : this(new byte[0])
+ {
+ }
+
+ internal DirectoryVirtualListViewContext(byte[] context)
+ {
+ if (context == null)
+ {
+ this.context = new byte[0];
+ }
+ else
+ {
+ this.context = new byte[context.Length];
+ for (int i = 0; i < context.Length; i++)
+ {
+ this.context[i] = context[i];
+ }
+ }
+ }
+
+ /// <include file='doc\DirectoryVirtualListViewContext .uex' path='docs/doc[@for="DirectoryVirtualListViewContext .Copy"]/*' />
+ /// <devdoc>
+ /// <para>Returns a copy of the current DirectoryVirtualListViewContext instance.</para>
+ /// </devdoc>
+ public DirectoryVirtualListViewContext Copy()
+ {
+ DirectoryVirtualListViewContext context = new DirectoryVirtualListViewContext(this.context);
+ return context;
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ExtendedDn.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ExtendedDn.cs
new file mode 100644
index 0000000000..525bae3788
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ExtendedDn.cs
@@ -0,0 +1,24 @@
+// 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
+{
+ /// <include file='doc\ExtendedDN.uex' path='docs/doc[@for="ExtendedDn"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Specifies the possible representations of the distinguished name.
+ /// </para>
+ /// </devdoc>
+ public enum ExtendedDN
+ {
+ /// <include file='doc\ExtendedDn.uex' path='docs/doc[@for="ExtendedDn.None"]/*' />
+ None = -1,
+
+ /// <include file='doc\ExtendedDn.uex' path='docs/doc[@for="ExtendedDn.HexString"]/*' />
+ HexString = 0,
+
+ /// <include file='doc\ExtendedDn.uex' path='docs/doc[@for="ExtendedDn.Standard"]/*' />
+ Standard = 1
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ExternDll.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ExternDll.cs
new file mode 100644
index 0000000000..6877ccedf6
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ExternDll.cs
@@ -0,0 +1,83 @@
+// 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
+{
+ internal static class ExternDll
+ {
+#if FEATURE_PAL && !SILVERLIGHT
+
+#if !PLATFORM_UNIX
+ internal const String DLLPREFIX = "";
+ internal const String DLLSUFFIX = ".dll";
+#else // !PLATFORM_UNIX
+#if __APPLE__
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".dylib";
+#elif _AIX
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".a";
+#elif __hppa__ || IA64
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".sl";
+#else
+ internal const String DLLPREFIX = "lib";
+ internal const String DLLSUFFIX = ".so";
+#endif
+#endif // !PLATFORM_UNIX
+
+ public const string Kernel32 = DLLPREFIX + "rotor_pal" + DLLSUFFIX;
+ public const string User32 = DLLPREFIX + "rotor_pal" + DLLSUFFIX;
+ public const string Mscoree = DLLPREFIX + "sscoree" + DLLSUFFIX;
+
+#elif FEATURE_PAL && SILVERLIGHT
+
+ public const string Kernel32 = "coreclr";
+ public const string User32 = "coreclr";
+
+#else
+ public const string Activeds = "activeds.dll";
+ public const string Advapi32 = "advapi32.dll";
+ public const string Comctl32 = "comctl32.dll";
+ public const string Comdlg32 = "comdlg32.dll";
+ public const string Gdi32 = "gdi32.dll";
+ public const string Gdiplus = "gdiplus.dll";
+ public const string Hhctrl = "hhctrl.ocx";
+ public const string Imm32 = "imm32.dll";
+ public const string Kernel32 = "kernel32.dll";
+ public const string Loadperf = "Loadperf.dll";
+ public const string Mscoree = "mscoree.dll";
+ public const string Clr = "clr.dll";
+ public const string Msi = "msi.dll";
+ public const string Mqrt = "mqrt.dll";
+ public const string Ntdll = "ntdll.dll";
+ public const string Ole32 = "ole32.dll";
+ public const string Oleacc = "oleacc.dll";
+ public const string Oleaut32 = "oleaut32.dll";
+ public const string Olepro32 = "olepro32.dll";
+ public const string PerfCounter = "perfcounter.dll";
+ public const string Powrprof = "Powrprof.dll";
+ public const string Psapi = "psapi.dll";
+ public const string Shell32 = "shell32.dll";
+ public const string User32 = "user32.dll";
+ public const string Uxtheme = "uxtheme.dll";
+ public const string WinMM = "winmm.dll";
+ public const string Winspool = "winspool.drv";
+ public const string Wtsapi32 = "wtsapi32.dll";
+ public const string Version = "version.dll";
+ public const string Vsassert = "vsassert.dll";
+ public const string Fxassert = "Fxassert.dll";
+ public const string Shlwapi = "shlwapi.dll";
+ public const string Crypt32 = "crypt32.dll";
+
+ // system.data specific
+ internal const string Odbc32 = "odbc32.dll";
+ internal const string SNI = "System.Data.dll";
+
+ // system.data.oracleclient specific
+ internal const string OciDll = "oci.dll";
+ internal const string OraMtsDll = "oramts.dll";
+#endif //!FEATURE_PAL
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/PasswordEncodingMethod.cs b/src/System.DirectoryServices/src/System/DirectoryServices/PasswordEncodingMethod.cs
new file mode 100644
index 0000000000..0d5c5ea909
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/PasswordEncodingMethod.cs
@@ -0,0 +1,12 @@
+// 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
+{
+ public enum PasswordEncodingMethod
+ {
+ PasswordEncodingSsl,
+ PasswordEncodingClear
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/PrivilegedConfigurationManager.cs b/src/System.DirectoryServices/src/System/DirectoryServices/PrivilegedConfigurationManager.cs
new file mode 100644
index 0000000000..072b090499
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/PrivilegedConfigurationManager.cs
@@ -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.
+
+namespace System.Configuration
+{
+ using System.Collections.Specialized;
+ using System.Security;
+ using System.Security.Permissions;
+
+ [ConfigurationPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal static class PrivilegedConfigurationManager
+ {
+ internal static ConnectionStringSettingsCollection ConnectionStrings
+ {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ get
+ {
+ return ConfigurationManager.ConnectionStrings;
+ }
+ }
+
+ internal static object GetSection(string sectionName)
+ {
+ return ConfigurationManager.GetSection(sectionName);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs
new file mode 100644
index 0000000000..b317b57867
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs
@@ -0,0 +1,575 @@
+// 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
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.DirectoryServices.Interop;
+ using System.Security.Permissions;
+ using System.Globalization;
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection"]/*' />
+ /// <devdoc>
+ /// <para>Contains the properties on a <see cref='System.DirectoryServices.DirectoryEntry'/>.</para>
+ /// </devdoc>
+ [
+ DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)
+ ]
+ public class PropertyCollection : IDictionary
+ {
+ private DirectoryEntry _entry;
+ internal Hashtable valueTable = null;
+
+ internal PropertyCollection(DirectoryEntry entry)
+ {
+ _entry = entry;
+ Hashtable tempTable = new Hashtable();
+ valueTable = Hashtable.Synchronized(tempTable);
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.this"]/*' />
+ /// <devdoc>
+ /// <para>Gets the property with the given name.</para>
+ /// </devdoc>
+ public PropertyValueCollection this[string propertyName]
+ {
+ get
+ {
+ if (propertyName == null)
+ throw new ArgumentNullException("propertyName");
+
+ string name = propertyName.ToLower(CultureInfo.InvariantCulture);
+ if (valueTable.Contains(name))
+ return (PropertyValueCollection)valueTable[name];
+ else
+ {
+ PropertyValueCollection value = new PropertyValueCollection(_entry, propertyName);
+ valueTable.Add(name, value);
+ return value;
+ }
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.Count"]/*' />
+ /// <devdoc>
+ /// <para>Gets the number of properties available on this entry.</para>
+ /// </devdoc>
+ public int Count
+ {
+ get
+ {
+ if (!(_entry.AdsObject is UnsafeNativeMethods.IAdsPropertyList))
+ throw new NotSupportedException(Res.GetString(Res.DSCannotCount));
+
+ _entry.FillCache("");
+
+ UnsafeNativeMethods.IAdsPropertyList propList = (UnsafeNativeMethods.IAdsPropertyList)_entry.AdsObject;
+
+ return propList.PropertyCount;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.PropertyNames"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public ICollection PropertyNames
+ {
+ get
+ {
+ return new KeysCollection(this);
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.Values"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public ICollection Values
+ {
+ get
+ {
+ return new ValuesCollection(this);
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.Contains"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public bool Contains(string propertyName)
+ {
+ //entry.FillCache(propertyName);
+ object var;
+ int unmanagedResult = _entry.AdsObject.GetEx(propertyName, out var);
+ if (unmanagedResult != 0)
+ {
+ // property not found (IIS provider returns 0x80005006, other provides return 0x8000500D).
+ if ((unmanagedResult == unchecked((int)0x8000500D)) || (unmanagedResult == unchecked((int)0x80005006)))
+ {
+ return false;
+ }
+ else
+ {
+ throw COMExceptionHelper.CreateFormattedComException(unmanagedResult);
+ }
+ }
+
+ return true;
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.CopyTo"]/*' />
+ /// <devdoc>
+ /// <para>Copies the elements of this instance into an <see cref='System.Array'/>, starting at a particular index into the array.</para>
+ /// </devdoc>
+ public void CopyTo(PropertyValueCollection[] array, int index)
+ {
+ ((ICollection)this).CopyTo((Array)array, index);
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.GetEnumerator"]/*' />
+ /// <devdoc>
+ /// <para>Returns an enumerator, which can be used to iterate through the collection.</para>
+ /// </devdoc>
+ public IDictionaryEnumerator GetEnumerator()
+ {
+ if (!(_entry.AdsObject is UnsafeNativeMethods.IAdsPropertyList))
+ throw new NotSupportedException(Res.GetString(Res.DSCannotEmunerate));
+
+ // Once an object has been used for an enumerator once, it can't be used again, because it only
+ // maintains a single cursor. Re-bind to the ADSI object to get a new instance.
+ // That's why we must clone entry here. It will be automatically disposed inside Enumerator.
+ DirectoryEntry entryToUse = _entry.CloneBrowsable();
+ entryToUse.FillCache("");
+
+ UnsafeNativeMethods.IAdsPropertyList propList = (UnsafeNativeMethods.IAdsPropertyList)entryToUse.AdsObject;
+
+ entryToUse.propertiesAlreadyEnumerated = true;
+ return new PropertyEnumerator(_entry, entryToUse);
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.IDictionary.this"]/*' />
+ ///<internalonly/>
+ object IDictionary.this[object key]
+ {
+ get
+ {
+ return this[(string)key];
+ }
+
+ set
+ {
+ throw new NotSupportedException(Res.GetString(Res.DSPropertySetSupported));
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.IDictionary.IsFixedSize"]/*' />
+ ///<internalonly/>
+ bool IDictionary.IsFixedSize
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.IDictionary.IsReadOnly"]/*' />
+ ///<internalonly/>
+ bool IDictionary.IsReadOnly
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.IDictionary.Keys"]/*' />
+ ///<internalonly/>
+ ICollection IDictionary.Keys
+ {
+ get
+ {
+ return new KeysCollection(this);
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.IDictionary.Add"]/*' />
+ ///<internalonly/>
+ void IDictionary.Add(object key, object value)
+ {
+ throw new NotSupportedException(Res.GetString(Res.DSAddNotSupported));
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.IDictionary.Clear"]/*' />
+ ///<internalonly/>
+ void IDictionary.Clear()
+ {
+ throw new NotSupportedException(Res.GetString(Res.DSClearNotSupported));
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.IDictionary.Contains"]/*' />
+ ///<internalonly/>
+ bool IDictionary.Contains(object value)
+ {
+ return this.Contains((string)value);
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.IDictionary.Remove"]/*' />
+ ///<internalonly/>
+ void IDictionary.Remove(object key)
+ {
+ throw new NotSupportedException(Res.GetString(Res.DSRemoveNotSupported));
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.IEnumerable.GetEnumerator"]/*' />
+ ///<internalonly/>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return (IEnumerator)GetEnumerator();
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ICollection.IsSynchronized"]/*' />
+ ///<internalonly/>
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ICollection.SyncRoot"]/*' />
+ ///<internalonly/>
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ return this;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ICollection.CopyTo"]/*' />
+ ///<internalonly/>
+ void ICollection.CopyTo(Array array, Int32 index)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+
+ if (array.Rank != 1)
+ throw new ArgumentException(Res.GetString(Res.OnlyAllowSingleDimension), "array");
+
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(Res.GetString(Res.LessThanZero), "index");
+
+ if (((index + Count) > array.Length) || ((index + Count) < index))
+ throw new ArgumentException(Res.GetString(Res.DestinationArrayNotLargeEnough));
+
+ foreach (PropertyValueCollection value in this)
+ {
+ array.SetValue(value, index);
+ index++;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.PropertyEnumerator"]/*' />
+ ///<internalonly/>
+ private class PropertyEnumerator : IDictionaryEnumerator, IDisposable
+ {
+ private DirectoryEntry _entry; // clone (to be disposed)
+ private DirectoryEntry _parentEntry; // original entry to pass to PropertyValueCollection
+ private string _currentPropName = null;
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.PropertyEnumerator.PropertyEnumerator"]/*' />
+ ///<internalonly/>
+ public PropertyEnumerator(DirectoryEntry parent, DirectoryEntry clone)
+ {
+ _entry = clone;
+ _parentEntry = parent;
+ }
+
+ ~PropertyEnumerator()
+ {
+ Dispose(true); // finalizer is called => Dispose has not been called yet.
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyEnumerator.Dispose"]/*' />
+ /// <devdoc>
+ /// </devdoc>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyEnumerator.Dispose1"]/*' />
+ /// <devdoc>
+ /// </devdoc>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _entry.Dispose();
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.PropertyEnumerator.Current"]/*' />
+ ///<internalonly/>
+ public object Current
+ {
+ get
+ {
+ return Entry.Value;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.PropertyEnumerator.Entry"]/*' />
+ ///<internalonly/>
+ public DictionaryEntry Entry
+ {
+ get
+ {
+ if (_currentPropName == null)
+ throw new InvalidOperationException(Res.GetString(Res.DSNoCurrentProperty));
+
+ return new DictionaryEntry(_currentPropName, new PropertyValueCollection(_parentEntry, _currentPropName));
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.PropertyEnumerator.Key"]/*' />
+ ///<internalonly/>
+ public object Key
+ {
+ get
+ {
+ return Entry.Key;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.PropertyEnumerator.Value"]/*' />
+ ///<internalonly/>
+ public object Value
+ {
+ get
+ {
+ return Entry.Value;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.PropertyEnumerator.MoveNext"]/*' />
+ ///<internalonly/>
+ public bool MoveNext()
+ {
+ object prop;
+ int hr = 0;
+ try
+ {
+ hr = ((UnsafeNativeMethods.IAdsPropertyList)_entry.AdsObject).Next(out prop);
+ }
+ catch (COMException e)
+ {
+ hr = e.ErrorCode;
+ prop = null;
+ }
+ if (hr == 0)
+ {
+ if (prop != null)
+ _currentPropName = ((UnsafeNativeMethods.IAdsPropertyEntry)prop).Name;
+ else
+ _currentPropName = null;
+
+ return true;
+ }
+ else
+ {
+ _currentPropName = null;
+ return false;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.PropertyEnumerator.Reset"]/*' />
+ ///<internalonly/>
+ public void Reset()
+ {
+ ((UnsafeNativeMethods.IAdsPropertyList)_entry.AdsObject).Reset();
+ _currentPropName = null;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesCollection"]/*' />
+ ///<internalonly/>
+ private class ValuesCollection : ICollection
+ {
+ protected PropertyCollection props;
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesCollection.ValuesCollection"]/*' />
+ ///<internalonly/>
+ public ValuesCollection(PropertyCollection props)
+ {
+ this.props = props;
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesCollection.Count"]/*' />
+ ///<internalonly/>
+ public int Count
+ {
+ get
+ {
+ return props.Count;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesCollection.IsReadOnly"]/*' />
+ ///<internalonly/>
+ public bool IsReadOnly
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesCollection.IsSynchronized"]/*' />
+ ///<internalonly/>
+ public bool IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesCollection.SyncRoot"]/*' />
+ ///<internalonly/>
+ public object SyncRoot
+ {
+ get
+ {
+ return ((ICollection)props).SyncRoot;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesCollection.CopyTo"]/*' />
+ ///<internalonly/>
+ public void CopyTo(Array array, int index)
+ {
+ foreach (object value in this)
+ array.SetValue(value, index++);
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesCollection.GetEnumerator"]/*' />
+ ///<internalonly/>
+ public virtual IEnumerator GetEnumerator()
+ {
+ return new ValuesEnumerator(props);
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.KeysCollection"]/*' />
+ ///<internalonly/>
+ private class KeysCollection : ValuesCollection
+ {
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.KeysCollection.KeysCollection"]/*' />
+ ///<internalonly/>
+ public KeysCollection(PropertyCollection props)
+ : base(props)
+ {
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.KeysCollection.GetEnumerator"]/*' />
+ ///<internalonly/>
+ public override IEnumerator GetEnumerator()
+ {
+ props._entry.FillCache("");
+ return new KeysEnumerator(props);
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesEnumerator"]/*' />
+ ///<internalonly/>
+ private class ValuesEnumerator : IEnumerator
+ {
+ private int _currentIndex = -1;
+ protected PropertyCollection propCollection;
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesEnumerator.ValuesEnumerator"]/*' />
+ ///<internalonly/>
+ public ValuesEnumerator(PropertyCollection propCollection)
+ {
+ this.propCollection = propCollection;
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesEnumerator.CurrentIndex"]/*' />
+ ///<internalonly/>
+ protected int CurrentIndex
+ {
+ get
+ {
+ if (_currentIndex == -1)
+ throw new InvalidOperationException(Res.GetString(Res.DSNoCurrentValue));
+ return _currentIndex;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesEnumerator.Current"]/*' />
+ ///<internalonly/>
+ public virtual object Current
+ {
+ get
+ {
+ UnsafeNativeMethods.IAdsPropertyList propList = (UnsafeNativeMethods.IAdsPropertyList)propCollection._entry.AdsObject;
+ return propCollection[((UnsafeNativeMethods.IAdsPropertyEntry)propList.Item(CurrentIndex)).Name];
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesEnumerator.MoveNext"]/*' />
+ ///<internalonly/>
+ public bool MoveNext()
+ {
+ _currentIndex++;
+ if (_currentIndex >= propCollection.Count)
+ {
+ _currentIndex = -1;
+ return false;
+ }
+ else
+ return true;
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.ValuesEnumerator.Reset"]/*' />
+ ///<internalonly/>
+ public void Reset()
+ {
+ _currentIndex = -1;
+ }
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.KeysEnumerator"]/*' />
+ ///<internalonly/>
+ private class KeysEnumerator : ValuesEnumerator
+ {
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.KeysEnumerator.KeysEnumerator"]/*' />
+ ///<internalonly/>
+ public KeysEnumerator(PropertyCollection collection)
+ : base(collection)
+ {
+ }
+
+ /// <include file='doc\PropertyCollection.uex' path='docs/doc[@for="PropertyCollection.KeysEnumerator.Current"]/*' />
+ ///<internalonly/>
+ public override object Current
+ {
+ get
+ {
+ UnsafeNativeMethods.IAdsPropertyList propList = (UnsafeNativeMethods.IAdsPropertyList)propCollection._entry.AdsObject;
+
+ return ((UnsafeNativeMethods.IAdsPropertyEntry)propList.Item(CurrentIndex)).Name;
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/PropertyValueCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/PropertyValueCollection.cs
new file mode 100644
index 0000000000..a3376b331f
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/PropertyValueCollection.cs
@@ -0,0 +1,410 @@
+// 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
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.DirectoryServices.Interop;
+ using System.Security.Permissions;
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection"]/*' />
+ /// <devdoc>
+ /// <para>Holds a collection of values for a multi-valued property.</para>
+ /// </devdoc>
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class PropertyValueCollection : CollectionBase
+ {
+ internal enum UpdateType
+ {
+ Add = 0,
+ Delete = 1,
+ Update = 2,
+ None = 3
+ }
+
+ private DirectoryEntry _entry;
+ private string _propertyName;
+ private UpdateType _updateType = UpdateType.None;
+ private ArrayList _changeList = null;
+ private bool _allowMultipleChange = false;
+ private bool _needNewBehavior = false;
+
+ internal PropertyValueCollection(DirectoryEntry entry, string propertyName)
+ {
+ _entry = entry;
+ _propertyName = propertyName;
+ PopulateList();
+ ArrayList tempList = new ArrayList();
+ _changeList = ArrayList.Synchronized(tempList);
+ _allowMultipleChange = entry.allowMultipleChange;
+ string tempPath = entry.Path;
+ if (tempPath == null || tempPath.Length == 0)
+ {
+ // user does not specify path, so we bind to default naming context using LDAP provider.
+ _needNewBehavior = true;
+ }
+ else
+ {
+ if (tempPath.StartsWith("LDAP:", StringComparison.Ordinal))
+ _needNewBehavior = true;
+ }
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.this"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public object this[int index]
+ {
+ get
+ {
+ return List[index];
+ }
+ set
+ {
+ if (_needNewBehavior && !_allowMultipleChange)
+ throw new NotSupportedException();
+ else
+ {
+ List[index] = value;
+ }
+ }
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.PropertyName"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public string PropertyName
+ {
+ get
+ {
+ return _propertyName;
+ }
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.Value"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public object Value
+ {
+ get
+ {
+ if (this.Count == 0)
+ return null;
+ else if (this.Count == 1)
+ return List[0];
+ else
+ {
+ object[] objectArray = new object[this.Count];
+ List.CopyTo(objectArray, 0);
+ return objectArray;
+ }
+ }
+
+ set
+ {
+ try
+ {
+ this.Clear();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ if (e.ErrorCode != unchecked((int)0x80004005) || (value == null))
+ // WinNT provider throws E_FAIL when null value is specified though actually ADS_PROPERTY_CLEAR option is used, need to catch exception
+ // here. But at the same time we don't want to catch the exception if user explicitly sets the value to null.
+ throw;
+ }
+
+ if (value == null)
+ return;
+
+ // we could not do Clear and Add, we have to bypass the existing collection cache
+ _changeList.Clear();
+
+ if (value is Array)
+ {
+ // byte[] is a special case, we will follow what ADSI is doing, it must be an octet string. So treat it as a single valued attribute
+ if (value is byte[])
+ _changeList.Add(value);
+ else if (value is object[])
+ _changeList.AddRange((object[])value);
+ else
+ {
+ //Need to box value type array elements.
+ object[] objArray = new object[((Array)value).Length];
+ ((Array)value).CopyTo(objArray, 0);
+ _changeList.AddRange((object[])objArray);
+ }
+ }
+ else
+ _changeList.Add(value);
+
+ object[] allValues = new object[_changeList.Count];
+ _changeList.CopyTo(allValues, 0);
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Update, _propertyName, allValues);
+
+ _entry.CommitIfNotCaching();
+
+ // populate the new context
+ PopulateList();
+ }
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.Add"]/*' />
+ /// <devdoc>
+ /// <para>Appends the value to the set of values for this property.</para>
+ /// </devdoc>
+ public int Add(object value)
+ {
+ return List.Add(value);
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.AddRange"]/*' />
+ /// <devdoc>
+ /// <para>Appends the values to the set of values for this property.</para>
+ /// </devdoc>
+ public void AddRange(object[] value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+ for (int i = 0; ((i) < (value.Length)); i = ((i) + (1)))
+ {
+ this.Add(value[i]);
+ }
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.AddRange1"]/*' />
+ /// <devdoc>
+ /// <para>Appends the values to the set of values for this property.</para>
+ /// </devdoc>
+ public void AddRange(PropertyValueCollection value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+ int currentCount = value.Count;
+ for (int i = 0; i < currentCount; i = ((i) + (1)))
+ {
+ this.Add(value[i]);
+ }
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.Contains"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public bool Contains(object value)
+ {
+ return List.Contains(value);
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.CopyTo"]/*' />
+ /// <devdoc>
+ /// <para>Copies the elements of this instance into an <see cref='System.Array'/>,
+ /// starting at a particular index
+ /// into the given <paramref name="array"/>.</para>
+ /// </devdoc>
+ public void CopyTo(object[] array, int index)
+ {
+ List.CopyTo(array, index);
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.IndexOf"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public int IndexOf(object value)
+ {
+ return List.IndexOf(value);
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.Insert"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public void Insert(int index, object value)
+ {
+ List.Insert(index, value);
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.PopulateList"]/*' />
+ ///<internalonly/>
+ private void PopulateList()
+ {
+ //No need to fill the cache here, when GetEx is calles, an implicit
+ //call to GetInfo will be called against an uninitialized property
+ //cache. Which is exactly what FillCache does.
+ //entry.FillCache(propertyName);
+ object var;
+ int unmanagedResult = _entry.AdsObject.GetEx(_propertyName, out var);
+ if (unmanagedResult != 0)
+ {
+ // property not found (IIS provider returns 0x80005006, other provides return 0x8000500D).
+ if ((unmanagedResult == unchecked((int)0x8000500D)) || (unmanagedResult == unchecked((int)0x80005006)))
+ {
+ return;
+ }
+ else
+ {
+ throw COMExceptionHelper.CreateFormattedComException(unmanagedResult);
+ }
+ }
+ if (var is ICollection)
+ InnerList.AddRange((ICollection)var);
+ else
+ InnerList.Add(var);
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.Remove"]/*' />
+ /// <devdoc>
+ /// <para>Removes the value from the collection.</para>
+ /// </devdoc>
+ public void Remove(object value)
+ {
+ if (_needNewBehavior)
+ {
+ try
+ {
+ List.Remove(value);
+ }
+ catch (ArgumentException)
+ {
+ // exception is thrown because value does not exist in the current cache, but it actually might do exist just because it is a very
+ // large multivalued attribute, the value has not been downloaded yet.
+ OnRemoveComplete(0, value);
+ }
+ }
+ else
+ List.Remove(value);
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.OnClear"]/*' />
+ ///<internalonly/>
+ protected override void OnClearComplete()
+ {
+ if (_needNewBehavior && !_allowMultipleChange && _updateType != UpdateType.None && _updateType != UpdateType.Update)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.DSPropertyValueSupportOneOperation));
+ }
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Clear, _propertyName, null);
+ _updateType = UpdateType.Update;
+ try
+ {
+ _entry.CommitIfNotCaching();
+ }
+ catch (System.Runtime.InteropServices.COMException e)
+ {
+ // On ADSI 2.5 if property has not been assigned any value before,
+ // then IAds::SetInfo() in CommitIfNotCaching returns bad HREsult 0x8007200A, which we ignore.
+ if (e.ErrorCode != unchecked((int)0x8007200A)) // ERROR_DS_NO_ATTRIBUTE_OR_VALUE
+ throw;
+ }
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.OnInsert"]/*' />
+ ///<internalonly/>
+ protected override void OnInsertComplete(int index, object value)
+ {
+ if (_needNewBehavior)
+ {
+ if (!_allowMultipleChange)
+ {
+ if (_updateType != UpdateType.None && _updateType != UpdateType.Add)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.DSPropertyValueSupportOneOperation));
+ }
+
+ _changeList.Add(value);
+
+ object[] allValues = new object[_changeList.Count];
+ _changeList.CopyTo(allValues, 0);
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Append, _propertyName, allValues);
+
+ _updateType = UpdateType.Add;
+ }
+ else
+ {
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Append, _propertyName, new object[] { value });
+ }
+ }
+ else
+ {
+ object[] allValues = new object[InnerList.Count];
+ InnerList.CopyTo(allValues, 0);
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Update, _propertyName, allValues);
+ }
+ _entry.CommitIfNotCaching();
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.OnRemove"]/*' />
+ ///<internalonly/>
+ protected override void OnRemoveComplete(int index, object value)
+ {
+ if (_needNewBehavior)
+ {
+ if (!_allowMultipleChange)
+ {
+ if (_updateType != UpdateType.None && _updateType != UpdateType.Delete)
+ {
+ throw new InvalidOperationException(Res.GetString(Res.DSPropertyValueSupportOneOperation));
+ }
+
+ _changeList.Add(value);
+ object[] allValues = new object[_changeList.Count];
+ _changeList.CopyTo(allValues, 0);
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Delete, _propertyName, allValues);
+
+ _updateType = UpdateType.Delete;
+ }
+ else
+ {
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Delete, _propertyName, new object[] { value });
+ }
+ }
+ else
+ {
+ object[] allValues = new object[InnerList.Count];
+ InnerList.CopyTo(allValues, 0);
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Update, _propertyName, allValues);
+ }
+
+ _entry.CommitIfNotCaching();
+ }
+
+ /// <include file='doc\PropertyValueCollection.uex' path='docs/doc[@for="PropertyValueCollection.OnSet"]/*' />
+ ///<internalonly/>
+ protected override void OnSetComplete(int index, object oldValue, object newValue)
+ {
+ // no need to consider the not allowing accumulative change case as it does not support Set
+ if (Count <= 1)
+ {
+ _entry.AdsObject.Put(_propertyName, newValue);
+ }
+ else
+ {
+ if (_needNewBehavior)
+ {
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Delete, _propertyName, new object[] { oldValue });
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Append, _propertyName, new object[] { newValue });
+ }
+ else
+ {
+ object[] allValues = new object[InnerList.Count];
+ InnerList.CopyTo(allValues, 0);
+ _entry.AdsObject.PutEx((int)AdsPropertyOperation.Update, _propertyName, allValues);
+ }
+ }
+
+ _entry.CommitIfNotCaching();
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ReferalChasingOption.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ReferalChasingOption.cs
new file mode 100644
index 0000000000..b9db5bf981
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ReferalChasingOption.cs
@@ -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.
+
+namespace System.DirectoryServices
+{
+ /// <include file='doc\ReferalChasingOption.uex' path='docs/doc[@for="ReferralChasingOption"]/*' />
+ /// <devdoc>
+ /// <para>Specifies if and how referral chasing is pursued.</para>
+ /// </devdoc>
+ public enum ReferralChasingOption
+ {
+ /// <include file='doc\ReferalChasingOption.uex' path='docs/doc[@for="ReferralChasingOption.None"]/*' />
+ /// <devdoc>
+ /// <para> Never chase the referred-to server. Setthing this option
+ /// prevents a client from contacting other servers in a referral process.</para>
+ /// </devdoc>
+ None = 0,
+ /// <include file='doc\ReferalChasingOption.uex' path='docs/doc[@for="ReferralChasingOption.Subordinate"]/*' />
+ /// <devdoc>
+ /// <para>Chase only subordinate referrals which are a subordinate naming context in a
+ /// directory tree. The ADSI LDAP provider always turns off this flag for paged
+ /// searches.</para>
+ /// </devdoc>
+ Subordinate = 0x20,
+ /// <include file='doc\ReferalChasingOption.uex' path='docs/doc[@for="ReferralChasingOption.External"]/*' />
+ /// <devdoc>
+ /// <para>Chase external referrals.</para>
+ /// </devdoc>
+ External = 0x40,
+ /// <include file='doc\ReferalChasingOption.uex' path='docs/doc[@for="ReferralChasingOption.All"]/*' />
+ /// <devdoc>
+ /// <para>Chase referrals of either the subordinate or external type.</para>
+ /// </devdoc>
+ All = Subordinate | External
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ResultPropertyCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ResultPropertyCollection.cs
new file mode 100644
index 0000000000..2edf1a4cd9
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ResultPropertyCollection.cs
@@ -0,0 +1,89 @@
+// 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
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+ using System.Globalization;
+
+ /// <include file='doc\ResultPropertyCollection.uex' path='docs/doc[@for="ResultPropertyCollection"]/*' />
+ /// <devdoc>
+ /// <para>Contains the properties on a <see cref='System.DirectoryServices.SearchResult'/>.</para>
+ /// </devdoc>
+ public class ResultPropertyCollection : DictionaryBase
+ {
+ internal ResultPropertyCollection()
+ {
+ }
+
+ /// <include file='doc\ResultPropertyCollection.uex' path='docs/doc[@for="ResultPropertyCollection.this"]/*' />
+ /// <devdoc>
+ /// <para>Gets the property with the given name.</para>
+ /// </devdoc>
+ public ResultPropertyValueCollection this[string name]
+ {
+ get
+ {
+ object objectName = name.ToLower(CultureInfo.InvariantCulture);
+ if (Contains((string)objectName))
+ {
+ return (ResultPropertyValueCollection)InnerHashtable[objectName];
+ }
+ else
+ {
+ return new ResultPropertyValueCollection(new object[0]);
+ }
+ }
+ }
+
+ /// <include file='doc\ResultPropertyCollection.uex' path='docs/doc[@for="ResultPropertyCollection.PropertyNames"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public ICollection PropertyNames
+ {
+ get { return Dictionary.Keys; }
+ }
+
+ /// <include file='doc\ResultPropertyCollection.uex' path='docs/doc[@for="ResultPropertyCollection.Values"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public ICollection Values
+ {
+ get
+ {
+ return Dictionary.Values;
+ }
+ }
+
+ internal void Add(string name, ResultPropertyValueCollection value)
+ {
+ Dictionary.Add(name.ToLower(CultureInfo.InvariantCulture), value);
+ }
+
+ /// <include file='doc\ResultPropertyCollection.uex' path='docs/doc[@for="ResultPropertyCollection.Contains"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public bool Contains(string propertyName)
+ {
+ object objectName = propertyName.ToLower(CultureInfo.InvariantCulture);
+ return Dictionary.Contains(objectName);
+ }
+
+ /// <include file='doc\ResultPropertyCollection.uex' path='docs/doc[@for="ResultPropertyCollection.CopyTo"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public void CopyTo(ResultPropertyValueCollection[] array, int index)
+ {
+ Dictionary.Values.CopyTo((Array)array, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/ResultPropertyValueCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/ResultPropertyValueCollection.cs
new file mode 100644
index 0000000000..4a729b848a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/ResultPropertyValueCollection.cs
@@ -0,0 +1,69 @@
+// 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
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+
+ /// <include file='doc\ResultPropertyValueCollection.uex' path='docs/doc[@for="ResultPropertyValueCollection"]/*' />
+ /// <devdoc>
+ /// <para>Specifies a collection of values for a multi-valued property.</para>
+ /// </devdoc>
+ public class ResultPropertyValueCollection : ReadOnlyCollectionBase
+ {
+ internal ResultPropertyValueCollection(object[] values)
+ {
+ if (values == null)
+ values = new object[0];
+
+ InnerList.AddRange(values);
+ }
+
+ /// <include file='doc\ResultPropertyValueCollection.uex' path='docs/doc[@for="ResultPropertyValueCollection.this"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public object this[int index]
+ {
+ get
+ {
+ object returnValue = InnerList[index];
+ if (returnValue is Exception)
+ throw (Exception)returnValue;
+ else
+ return returnValue;
+ }
+ }
+
+ /// <include file='doc\ResultPropertyValueCollection.uex' path='docs/doc[@for="ResultPropertyValueCollection.Contains"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public bool Contains(object value)
+ {
+ return InnerList.Contains(value);
+ }
+
+ /// <include file='doc\ResultPropertyValueCollection.uex' path='docs/doc[@for="ResultPropertyValueCollection.IndexOf"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public int IndexOf(object value)
+ {
+ return InnerList.IndexOf(value);
+ }
+
+ /// <include file='doc\ResultPropertyValueCollection.uex' path='docs/doc[@for="ResultPropertyValueCollection.CopyTo"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public void CopyTo(object[] values, int index)
+ {
+ InnerList.CopyTo(values, index);
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/SchemaNameCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/SchemaNameCollection.cs
new file mode 100644
index 0000000000..6cc8708e3a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/SchemaNameCollection.cs
@@ -0,0 +1,369 @@
+// 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
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.DirectoryServices.Interop;
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection"]/*' />
+ /// <devdoc>
+ /// <para>Contains a list of schema names used for the <see cref='System.DirectoryServices.DirectoryEntries.SchemaFilter'/> property of a <see cref='System.DirectoryServices.DirectoryEntries'/>.</para>
+ /// </devdoc>
+ public class SchemaNameCollection : IList
+ {
+ private VariantPropGetter _propGetter;
+ private VariantPropSetter _propSetter;
+
+ internal SchemaNameCollection(VariantPropGetter propGetter, VariantPropSetter propSetter)
+ {
+ _propGetter = propGetter;
+ _propSetter = propSetter;
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.this"]/*' />
+ /// <devdoc>
+ /// <para>Gets or sets the object
+ /// at the given index.</para>
+ /// </devdoc>
+ public string this[int index]
+ {
+ get
+ {
+ object[] values = GetValue();
+ return (string)values[index];
+ }
+ set
+ {
+ object[] values = GetValue();
+ values[index] = value;
+ _propSetter(values);
+ }
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.Count"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Gets the number of objects available on this entry.
+ /// </para>
+ /// </devdoc>
+ public int Count
+ {
+ get
+ {
+ object[] values = GetValue();
+ return values.Length;
+ }
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.Add"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Appends the value to the
+ /// collection.
+ /// </para>
+ /// </devdoc>
+ public int Add(string value)
+ {
+ object[] oldValues = GetValue();
+ object[] newValues = new object[oldValues.Length + 1];
+ for (int i = 0; i < oldValues.Length; i++)
+ newValues[i] = oldValues[i];
+ newValues[newValues.Length - 1] = value;
+ _propSetter(newValues);
+ return newValues.Length - 1;
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.AddRange"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Appends the values to the collection.
+ /// </para>
+ /// </devdoc>
+ public void AddRange(string[] value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+ object[] oldValues = GetValue();
+ object[] newValues = new object[oldValues.Length + value.Length];
+ for (int i = 0; i < oldValues.Length; i++)
+ newValues[i] = oldValues[i];
+ for (int i = oldValues.Length; i < newValues.Length; i++)
+ newValues[i] = value[i - oldValues.Length];
+ _propSetter(newValues);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.AddRange1"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public void AddRange(SchemaNameCollection value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+ object[] oldValues = GetValue();
+ object[] newValues = new object[oldValues.Length + value.Count];
+ for (int i = 0; i < oldValues.Length; i++)
+ newValues[i] = oldValues[i];
+ for (int i = oldValues.Length; i < newValues.Length; i++)
+ newValues[i] = value[i - oldValues.Length];
+ _propSetter(newValues);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.Clear"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Removes all items from the collection.
+ /// </para>
+ /// </devdoc>
+ public void Clear()
+ {
+ object[] newValues = new object[0];
+ _propSetter(newValues);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.Contains"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Determines if the collection contains a specific value.
+ /// </para>
+ /// </devdoc>
+ public bool Contains(string value)
+ {
+ return IndexOf(value) != -1;
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.CopyTo"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public void CopyTo(String[] stringArray, int index)
+ {
+ object[] values = GetValue();
+ values.CopyTo(stringArray, index);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.GetEnumerator"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public IEnumerator GetEnumerator()
+ {
+ object[] values = GetValue();
+ return values.GetEnumerator();
+ }
+
+ private object[] GetValue()
+ {
+ object value = _propGetter();
+ if (value == null)
+ return new object[0];
+ else
+ return (object[])value;
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.IndexOf"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Determines the index of a specific item in the collection.
+ /// </para>
+ /// </devdoc>
+ public int IndexOf(string value)
+ {
+ object[] values = GetValue();
+ for (int i = 0; i < values.Length; i++)
+ {
+ if (value == (string)values[i])
+ return i;
+ }
+ return -1;
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.Insert"]/*' />
+ /// <devdoc>
+ /// <para>Inserts an item at the specified position in the collection.</para>
+ /// </devdoc>
+ public void Insert(int index, string value)
+ {
+ ArrayList tmpList = new ArrayList((ICollection)GetValue());
+ tmpList.Insert(index, value);
+ _propSetter(tmpList.ToArray());
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.Remove"]/*' />
+ /// <devdoc>
+ /// <para>Removes an item from the collection.</para>
+ /// </devdoc>
+ public void Remove(string value)
+ {
+ // this does take two scans of the array, but value isn't guaranteed to be there.
+ int index = IndexOf(value);
+ RemoveAt(index);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.RemoveAt"]/*' />
+ /// <devdoc>
+ /// <para>Removes the
+ /// item at the specified index from the collection.</para>
+ /// </devdoc>
+ public void RemoveAt(int index)
+ {
+ object[] oldValues = GetValue();
+ if (index >= oldValues.Length || index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ object[] newValues = new object[oldValues.Length - 1];
+ for (int i = 0; i < index; i++)
+ newValues[i] = oldValues[i];
+ for (int i = index + 1; i < oldValues.Length; i++)
+ newValues[i - 1] = oldValues[i];
+ _propSetter(newValues);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.IList.IsReadOnly"]/*' />
+ /// <internalonly/>
+ bool IList.IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.IList.IsFixedSize"]/*' />
+ /// <internalonly/>
+ bool IList.IsFixedSize
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.ICollection.CopyTo"]/*' />
+ /// <internalonly/>
+ void ICollection.CopyTo(Array array, int index)
+ {
+ object[] values = GetValue();
+ values.CopyTo(array, index);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.ICollection.IsSynchronized"]/*' />
+ /// <internalonly/>
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.ICollection.SyncRoot"]/*' />
+ /// <internalonly/>
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ return this;
+ }
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.IList.this"]/*' />
+ /// <internalonly/>
+ object IList.this[int index]
+ {
+ get
+ {
+ return this[index];
+ }
+ set
+ {
+ this[index] = (string)value;
+ }
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.IList.Add"]/*' />
+ /// <internalonly/>
+ int IList.Add(object value)
+ {
+ return Add((string)value);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.IList.Contains"]/*' />
+ /// <internalonly/>
+ bool IList.Contains(object value)
+ {
+ return Contains((string)value);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.IList.IndexOf"]/*' />
+ /// <internalonly/>
+ int IList.IndexOf(object value)
+ {
+ return IndexOf((string)value);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.IList.Insert"]/*' />
+ /// <internalonly/>
+ void IList.Insert(int index, object value)
+ {
+ Insert(index, (string)value);
+ }
+
+ /// <include file='doc\SchemaNameCollection.uex' path='docs/doc[@for="SchemaNameCollection.IList.Remove"]/*' />
+ /// <internalonly/>
+ void IList.Remove(object value)
+ {
+ Remove((string)value);
+ }
+
+ internal delegate object VariantPropGetter();
+ internal delegate void VariantPropSetter(object value);
+
+ // this class and HintsDelegateWrapper exist only because you can't create
+ // a delegate to a property's accessors. You have to supply methods. So these
+ // classes wrap an object and supply properties as methods.
+ internal class FilterDelegateWrapper
+ {
+ private UnsafeNativeMethods.IAdsContainer _obj;
+ internal FilterDelegateWrapper(UnsafeNativeMethods.IAdsContainer wrapped)
+ {
+ _obj = wrapped;
+ }
+ public VariantPropGetter Getter
+ {
+ get
+ {
+ return new VariantPropGetter(GetFilter);
+ }
+ }
+
+ public VariantPropSetter Setter
+ {
+ get
+ {
+ return new VariantPropSetter(SetFilter);
+ }
+ }
+
+ private object GetFilter()
+ {
+ return _obj.Filter;
+ }
+
+ private void SetFilter(object value)
+ {
+ _obj.Filter = value;
+ }
+ }
+ }
+}
+
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/SearchResult.cs b/src/System.DirectoryServices/src/System/DirectoryServices/SearchResult.cs
new file mode 100644
index 0000000000..f60aad78ac
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/SearchResult.cs
@@ -0,0 +1,77 @@
+// 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
+{
+ using System;
+ using System.Net;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+
+ /// <include file='doc\SearchResult.uex' path='docs/doc[@for="SearchResult"]/*' />
+ /// <devdoc>
+ /// <para>Encapsulates a node in the Active Directory hierarchy
+ /// that is returned during a search through <see cref='System.DirectoryServices.DirectorySearcher'/>.</para>
+ /// </devdoc>
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class SearchResult
+ {
+ private NetworkCredential _parentCredentials;
+ private AuthenticationTypes _parentAuthenticationType;
+ private ResultPropertyCollection _properties = new ResultPropertyCollection();
+
+ internal SearchResult(NetworkCredential parentCredentials, AuthenticationTypes parentAuthenticationType)
+ {
+ _parentCredentials = parentCredentials;
+ _parentAuthenticationType = parentAuthenticationType;
+ }
+
+ /// <include file='doc\SearchResult.uex' path='docs/doc[@for="SearchResult.GetDirectoryEntry"]/*' />
+ /// <devdoc>
+ /// <para>Retrieves the <see cref='System.DirectoryServices.DirectoryEntry'/> that corresponds to the <see cref='System.DirectoryServices.SearchResult'/>, from the Active Directory
+ /// hierarchy.</para>
+ /// </devdoc>
+ [
+ EnvironmentPermission(SecurityAction.Assert, Unrestricted = true),
+ SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
+ ]
+ public DirectoryEntry GetDirectoryEntry()
+ {
+ if (_parentCredentials != null)
+ return new DirectoryEntry(Path, true, _parentCredentials.UserName, _parentCredentials.Password, _parentAuthenticationType);
+ else
+ {
+ DirectoryEntry newEntry = new DirectoryEntry(Path, true, null, null, _parentAuthenticationType);
+ return newEntry;
+ }
+ }
+
+ /// <include file='doc\SearchResult.uex' path='docs/doc[@for="SearchResult.Path"]/*' />
+ /// <devdoc>
+ /// <para> Gets the path for this <see cref='System.DirectoryServices.SearchResult'/>.</para>
+ /// </devdoc>
+ public string Path
+ {
+ get
+ {
+ return (string)Properties["ADsPath"][0];
+ }
+ }
+
+ /// <include file='doc\SearchResult.uex' path='docs/doc[@for="SearchResult.Properties"]/*' />
+ /// <devdoc>
+ /// <para>Gets a <see cref='System.DirectoryServices.ResultPropertyCollection'/>
+ /// of properties set on this object.</para>
+ /// </devdoc>
+ public ResultPropertyCollection Properties
+ {
+ get
+ {
+ return _properties;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/SearchResultCollection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/SearchResultCollection.cs
new file mode 100644
index 0000000000..6f2b6df88a
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/SearchResultCollection.cs
@@ -0,0 +1,562 @@
+// 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 INTPTR_INTCAST = System.Int32;
+using INTPTR_INTPTRCAST = System.IntPtr;
+
+namespace System.DirectoryServices
+{
+ using System;
+ using System.Net;
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.DirectoryServices.Interop;
+ using System.Text;
+ using System.Configuration;
+ using System.Security.Permissions;
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection"]/*' />
+ /// <devdoc>
+ /// <para>Contains the instances of <see cref='System.DirectoryServices.SearchResult'/> returned during a
+ /// query to the Active Directory hierarchy through <see cref='System.DirectoryServices.DirectorySearcher'/>.</para>
+ /// </devdoc>
+ [DirectoryServicesPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+ public class SearchResultCollection : MarshalByRefObject, ICollection, IEnumerable, IDisposable
+ {
+ private IntPtr _handle;
+ private string[] _properties;
+ private UnsafeNativeMethods.IDirectorySearch _searchObject;
+ private string _filter;
+ private ArrayList _innerList;
+ private bool _disposed;
+ private DirectoryEntry _rootEntry; // clone of parent entry object
+ private const string ADS_DIRSYNC_COOKIE = "fc8cb04d-311d-406c-8cb9-1ae8b843b418";
+ private IntPtr _adsDirsynCookieName = Marshal.StringToCoTaskMemUni(ADS_DIRSYNC_COOKIE);
+ private const string ADS_VLV_RESPONSE = "fc8cb04d-311d-406c-8cb9-1ae8b843b419";
+ private IntPtr _adsVLVResponseName = Marshal.StringToCoTaskMemUni(ADS_VLV_RESPONSE);
+ internal DirectorySearcher srch = null;
+
+ ///<internalonly/>
+ internal SearchResultCollection(DirectoryEntry root, IntPtr searchHandle, string[] propertiesLoaded, DirectorySearcher srch)
+ {
+ _handle = searchHandle;
+ _properties = propertiesLoaded;
+ _filter = srch.Filter;
+ _rootEntry = root;
+ this.srch = srch;
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.this"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public SearchResult this[int index]
+ {
+ get
+ {
+ return (SearchResult)InnerList[index];
+ }
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.Count"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public int Count
+ {
+ get
+ {
+ return InnerList.Count;
+ }
+ }
+
+ ///<internalonly/>
+ internal string Filter
+ {
+ get
+ {
+ return _filter;
+ }
+ }
+
+ ///<internalonly/>
+ private ArrayList InnerList
+ {
+ get
+ {
+ if (_innerList == null)
+ {
+ _innerList = new ArrayList();
+ IEnumerator enumerator = new ResultsEnumerator(this,
+ _rootEntry.GetUsername(),
+ _rootEntry.GetPassword(),
+ _rootEntry.AuthenticationType);
+ while (enumerator.MoveNext())
+ _innerList.Add(enumerator.Current);
+ }
+
+ return _innerList;
+ }
+ }
+
+ ///<internalonly/>
+ internal UnsafeNativeMethods.IDirectorySearch SearchObject
+ {
+ get
+ {
+ if (_searchObject == null)
+ {
+ _searchObject = (UnsafeNativeMethods.IDirectorySearch)_rootEntry.AdsObject; // get it only once
+ }
+ return _searchObject;
+ }
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.Handle"]/*' />
+ /// <devdoc>
+ /// <para>Gets the handle returned by IDirectorySearch::ExecuteSearch, which was called
+ /// by the DirectorySearcher that created this object.</para>
+ /// </devdoc>
+ public IntPtr Handle
+ {
+ get
+ {
+ //The handle is no longer valid since the object has been disposed.
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ return _handle;
+ }
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.PropertiesLoaded"]/*' />
+ /// <devdoc>
+ /// <para>Gets a read-only collection of the properties
+ /// specified on <see cref='System.DirectoryServices.DirectorySearcher'/> before the
+ /// search was executed.</para>
+ /// </devdoc>
+ public string[] PropertiesLoaded
+ {
+ get
+ {
+ return _properties;
+ }
+ }
+
+ internal byte[] DirsyncCookie
+ {
+ get
+ {
+ return RetrieveDirectorySynchronizationCookie();
+ }
+ }
+
+ internal DirectoryVirtualListView VLVResponse
+ {
+ get
+ {
+ return RetrieveVLVResponse();
+ }
+ }
+
+ internal unsafe byte[] RetrieveDirectorySynchronizationCookie()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the dirsync cookie back
+ AdsSearchColumn column = new AdsSearchColumn();
+ AdsSearchColumn* pColumn = &column;
+ SearchObject.GetColumn(Handle, _adsDirsynCookieName, (INTPTR_INTPTRCAST)pColumn);
+ try
+ {
+ AdsValue* pValue = column.pADsValues;
+ byte[] value = (byte[])new AdsValueHelper(*pValue).GetValue();
+
+ return value;
+ }
+ finally
+ {
+ try
+ {
+ SearchObject.FreeColumn((INTPTR_INTPTRCAST)pColumn);
+ }
+ catch (COMException)
+ {
+ }
+ }
+ }
+
+ internal unsafe DirectoryVirtualListView RetrieveVLVResponse()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name);
+
+ // get the vlv response back
+ AdsSearchColumn column = new AdsSearchColumn();
+ AdsSearchColumn* pColumn = &column;
+ SearchObject.GetColumn(Handle, _adsVLVResponseName, (INTPTR_INTPTRCAST)pColumn);
+ try
+ {
+ AdsValue* pValue = column.pADsValues;
+ DirectoryVirtualListView value = (DirectoryVirtualListView)new AdsValueHelper(*pValue).GetVlvValue();
+ return value;
+ }
+ finally
+ {
+ try
+ {
+ SearchObject.FreeColumn((INTPTR_INTPTRCAST)pColumn);
+ }
+ catch (COMException)
+ {
+ }
+ }
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.Dispose"]/*' />
+ /// <devdoc>
+ /// </devdoc>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.Dispose1"]/*' />
+ /// <devdoc>
+ /// </devdoc>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ if (_handle != (IntPtr)0 && _searchObject != null && disposing)
+ {
+ // NOTE: We can't call methods on SearchObject in the finalizer because it
+ // runs on a different thread. The IDirectorySearch object is STA, so COM must create
+ // a proxy stub to marshal the call back to the original thread. Unfortunately, the
+ // IDirectorySearch interface cannot be registered, because it is not automation
+ // compatible. Therefore the QI for IDirectorySearch on this thread fails, and we get
+ // an InvalidCastException. The conclusion is that the user simply must call Dispose
+ // on this object.
+
+ _searchObject.CloseSearchHandle(_handle);
+
+ _handle = (IntPtr)0;
+ }
+
+ if (disposing)
+ _rootEntry.Dispose();
+
+ if (_adsDirsynCookieName != (IntPtr)0)
+ Marshal.FreeCoTaskMem(_adsDirsynCookieName);
+
+ if (_adsVLVResponseName != (IntPtr)0)
+ Marshal.FreeCoTaskMem(_adsVLVResponseName);
+
+ _disposed = true;
+ }
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for=".Finalize"]/*' />
+ ~SearchResultCollection()
+ {
+ Dispose(false); // finalizer is called => Dispose has not been called yet.
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.GetEnumerator"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public IEnumerator GetEnumerator()
+ {
+ // Two ResultsEnumerators can't exist at the same time over the
+ // same object. Need to get a new handle, which means re-querying.
+ return new ResultsEnumerator(this,
+ _rootEntry.GetUsername(),
+ _rootEntry.GetPassword(),
+ _rootEntry.AuthenticationType);
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.Contains"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public bool Contains(SearchResult result)
+ {
+ return InnerList.Contains(result);
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.CopyTo"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public void CopyTo(SearchResult[] results, int index)
+ {
+ InnerList.CopyTo(results, index);
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.IndexOf"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public int IndexOf(SearchResult result)
+ {
+ return InnerList.IndexOf(result);
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.ICollection.IsSynchronized"]/*' />
+ ///<internalonly/>
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.ICollection.SyncRoot"]/*' />
+ ///<internalonly/>
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ return this;
+ }
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.ICollection.CopyTo"]/*' />
+ /// <internalonly/>
+ void ICollection.CopyTo(Array array, int index)
+ {
+ InnerList.CopyTo(array, index);
+ }
+
+ /// <devdoc>
+ /// <para> Supports a simple
+ /// ForEach-style iteration over a collection.</para>
+ /// </devdoc>
+ private class ResultsEnumerator : IEnumerator
+ {
+ private NetworkCredential _parentCredentials;
+ private AuthenticationTypes _parentAuthenticationType;
+ private SearchResultCollection _results;
+ private bool _initialized;
+ private SearchResult _currentResult;
+ private bool _eof;
+ private bool _waitForResult = false;
+
+ internal ResultsEnumerator(SearchResultCollection results, string parentUserName, string parentPassword, AuthenticationTypes parentAuthenticationType)
+ {
+ if (parentUserName != null && parentPassword != null)
+ _parentCredentials = new NetworkCredential(parentUserName, parentPassword);
+
+ _parentAuthenticationType = parentAuthenticationType;
+ _results = results;
+ _initialized = false;
+
+ // get the app configuration information
+ object o = PrivilegedConfigurationManager.GetSection("system.directoryservices");
+ if (o != null && o is bool)
+ {
+ _waitForResult = (bool)o;
+ }
+ }
+
+ /// <devdoc>
+ /// <para>Gets the current element in the collection.</para>
+ /// </devdoc>
+ public SearchResult Current
+ {
+ get
+ {
+ if (!_initialized || _eof)
+ throw new InvalidOperationException(Res.GetString(Res.DSNoCurrentEntry));
+
+ if (_currentResult == null)
+ _currentResult = GetCurrentResult();
+
+ return _currentResult;
+ }
+ }
+
+ private unsafe SearchResult GetCurrentResult()
+ {
+ SearchResult entry = new SearchResult(_parentCredentials, _parentAuthenticationType);
+ int hr = 0;
+ IntPtr pszColumnName = (IntPtr)0;
+ hr = _results.SearchObject.GetNextColumnName(_results.Handle, (INTPTR_INTPTRCAST)(&pszColumnName));
+ while (hr == 0)
+ {
+ try
+ {
+ AdsSearchColumn column = new AdsSearchColumn();
+ AdsSearchColumn* pColumn = &column;
+ _results.SearchObject.GetColumn(_results.Handle, pszColumnName, (INTPTR_INTPTRCAST)pColumn);
+ try
+ {
+ int numValues = column.dwNumValues;
+ AdsValue* pValue = column.pADsValues;
+ object[] values = new object[numValues];
+ for (int i = 0; i < numValues; i++)
+ {
+ values[i] = new AdsValueHelper(*pValue).GetValue();
+ pValue++;
+ }
+ entry.Properties.Add(Marshal.PtrToStringUni(pszColumnName), new ResultPropertyValueCollection(values));
+ }
+ finally
+ {
+ try
+ {
+ _results.SearchObject.FreeColumn((INTPTR_INTPTRCAST)pColumn);
+ }
+ catch (COMException)
+ {
+ }
+ }
+ }
+ finally
+ {
+ SafeNativeMethods.FreeADsMem(pszColumnName);
+ }
+ hr = _results.SearchObject.GetNextColumnName(_results.Handle, (INTPTR_INTPTRCAST)(&pszColumnName));
+ }
+
+ return entry;
+ }
+
+ /// <include file='doc\SearchResultCollection.uex' path='docs/doc[@for="SearchResultCollection.ResultsEnumerator.MoveNext"]/*' />
+ /// <devdoc>
+ /// <para>Advances
+ /// the enumerator to the next element of the collection
+ /// and returns a Boolean value indicating whether a valid element is available.</para>
+ /// </devdoc>
+ public bool MoveNext()
+ {
+ DirectorySynchronization tempsync = null;
+ DirectoryVirtualListView tempvlv = null;
+ int errorCode = 0;
+
+ if (_eof)
+ return false;
+
+ _currentResult = null;
+ if (!_initialized)
+ {
+ int hr = _results.SearchObject.GetFirstRow(_results.Handle);
+
+ if (hr != UnsafeNativeMethods.S_ADS_NOMORE_ROWS)
+ {
+ //throw a clearer exception if the filter was invalid
+ if (hr == UnsafeNativeMethods.INVALID_FILTER)
+ throw new ArgumentException(Res.GetString(Res.DSInvalidSearchFilter, _results.Filter));
+ if (hr != 0)
+ throw COMExceptionHelper.CreateFormattedComException(hr);
+
+ _eof = false;
+ _initialized = true;
+ return true;
+ }
+
+ _initialized = true;
+ }
+
+ while (true)
+ {
+ // clear the last error first
+ CleanLastError();
+ errorCode = 0;
+
+ int hr = _results.SearchObject.GetNextRow(_results.Handle);
+ // SIZE_LIMIT_EXCEEDED occurs when we supply too generic filter or small SizeLimit value.
+ if (hr == UnsafeNativeMethods.S_ADS_NOMORE_ROWS || hr == UnsafeNativeMethods.SIZE_LIMIT_EXCEEDED)
+ {
+ // need to make sure this is not the case that server actually still has record not returned yet
+ if (hr == UnsafeNativeMethods.S_ADS_NOMORE_ROWS)
+ {
+ hr = GetLastError(ref errorCode);
+ // get last error call failed, we need to bail out
+ if (hr != 0)
+ throw COMExceptionHelper.CreateFormattedComException(hr);
+ }
+
+ // not the case that server still has result, we are done here
+ if (errorCode != SafeNativeMethods.ERROR_MORE_DATA)
+ {
+ // get the dirsync cookie as we finished all the rows
+ if (_results.srch.directorySynchronizationSpecified)
+ tempsync = _results.srch.DirectorySynchronization;
+
+ // get the vlv response as we finished all the rows
+ if (_results.srch.directoryVirtualListViewSpecified)
+ tempvlv = _results.srch.VirtualListView;
+
+ _results.srch.searchResult = null;
+
+ _eof = true;
+ _initialized = false;
+ return false;
+ }
+ else
+ {
+ // if user chooses to wait to continue the search
+ if (_waitForResult)
+ {
+ continue;
+ }
+ else
+ {
+ uint temp = (uint)errorCode;
+ temp = ((((temp) & 0x0000FFFF) | (7 << 16) | 0x80000000));
+ throw COMExceptionHelper.CreateFormattedComException((int)temp);
+ }
+ }
+ }
+ //throw a clearer exception if the filter was invalid
+ if (hr == UnsafeNativeMethods.INVALID_FILTER)
+ throw new ArgumentException(Res.GetString(Res.DSInvalidSearchFilter, _results.Filter));
+ if (hr != 0)
+ throw COMExceptionHelper.CreateFormattedComException(hr);
+
+ _eof = false;
+ return true;
+ }
+ }
+
+ /// <devdoc>
+ /// <para>Resets the enumerator back to its initial position before the first element in the collection.</para>
+ /// </devdoc>
+ public void Reset()
+ {
+ _eof = false;
+ _initialized = false;
+ }
+
+ object IEnumerator.Current
+ {
+ get
+ {
+ return Current;
+ }
+ }
+
+ private void CleanLastError()
+ {
+ SafeNativeMethods.ADsSetLastError(SafeNativeMethods.ERROR_SUCCESS, null, null);
+ }
+
+ private int GetLastError(ref int errorCode)
+ {
+ StringBuilder errorBuffer = new StringBuilder();
+ StringBuilder nameBuffer = new StringBuilder();
+ errorCode = SafeNativeMethods.ERROR_SUCCESS;
+ int hr = SafeNativeMethods.ADsGetLastError(out errorCode, errorBuffer, 0, nameBuffer, 0);
+
+ return hr;
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/SearchScope.cs b/src/System.DirectoryServices/src/System/DirectoryServices/SearchScope.cs
new file mode 100644
index 0000000000..dae91782ba
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/SearchScope.cs
@@ -0,0 +1,30 @@
+// 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
+{
+ /// <include file='doc\SearchScope.uex' path='docs/doc[@for="SearchScope"]/*' />
+ /// <devdoc>
+ /// <para>Specifies the scope of a directory search.</para>
+ /// </devdoc>
+ public enum SearchScope
+ {
+ /// <include file='doc\SearchScope.uex' path='docs/doc[@for="SearchScope.Base"]/*' />
+ /// <devdoc>
+ /// <para>Limits the search to the base object. The result contains at most one object. </para>
+ /// </devdoc>
+ Base = 0,
+ /// <include file='doc\SearchScope.uex' path='docs/doc[@for="SearchScope.OneLevel"]/*' />
+ /// <devdoc>
+ /// <para>Searched one level of the immediate children, excluding the base object.</para>
+ /// </devdoc>
+ OneLevel = 1,
+ /// <include file='doc\SearchScope.uex' path='docs/doc[@for="SearchScope.Subtree"]/*' />
+ /// <devdoc>
+ /// <para>Searches the whole subtree, including all the children and the base object
+ /// itself.</para>
+ /// </devdoc>
+ Subtree = 2
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/SearchWaitHandler.cs b/src/System.DirectoryServices/src/System/DirectoryServices/SearchWaitHandler.cs
new file mode 100644
index 0000000000..bc984d4fe7
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/SearchWaitHandler.cs
@@ -0,0 +1,70 @@
+// 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 INTPTR_INTCAST = System.Int32;
+using INTPTR_INTPTRCAST = System.IntPtr;
+
+namespace System.DirectoryServices
+{
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Xml;
+ using System.Configuration;
+ using System.Reflection;
+ using System.Security.Permissions;
+ using System.Globalization;
+
+ internal class SearchWaitHandler : IConfigurationSectionHandler
+ {
+ public virtual object Create(object parent, object configContext, XmlNode section)
+ {
+ bool foundWaitStatus = false;
+ bool waitForSearchResult = false;
+
+ foreach (XmlNode child in section.ChildNodes)
+ {
+ switch (child.Name)
+ {
+ case "DirectorySearcher":
+ if (foundWaitStatus)
+ throw new ConfigurationErrorsException(Res.GetString(Res.ConfigSectionsUnique, "DirectorySearcher"));
+ HandlerBase.RemoveBooleanAttribute(child, "waitForPagedSearchData", ref waitForSearchResult);
+ foundWaitStatus = true;
+ break;
+
+ default:
+ break;
+ } // switch(child.Name)
+ }
+
+ object o = waitForSearchResult;
+ return o;
+ }
+ }
+
+ internal class HandlerBase
+ {
+ private HandlerBase()
+ {
+ }
+
+ static internal void RemoveBooleanAttribute(XmlNode node, string name, ref bool value)
+ {
+ value = false;
+ XmlNode attribute = node.Attributes.RemoveNamedItem(name);
+ if (null != attribute)
+ {
+ try
+ {
+ value = bool.Parse(attribute.Value);
+ }
+ catch (FormatException)
+ {
+ throw new ConfigurationErrorsException(Res.GetString(Res.Invalid_boolean_attribute, name));
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/SecurityMasks.cs b/src/System.DirectoryServices/src/System/DirectoryServices/SecurityMasks.cs
new file mode 100644
index 0000000000..a06ea8f503
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/SecurityMasks.cs
@@ -0,0 +1,31 @@
+// 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
+{
+ /// <include file='doc\SecurityMasks.uex' path='docs/doc[@for="SecurityMasks"]/*' />
+ /// <devdoc>
+ /// <para>
+ /// Specifies the available options for examining security information of an object.
+ /// </para>
+ /// </devdoc>
+ [Flags]
+ public enum SecurityMasks
+ {
+ /// <include file='doc\SecurityMasks.uex' path='docs/doc[@for="SecurityMasks.None"]/*' />
+ None = 0,
+
+ /// <include file='doc\SecurityMasks.uex' path='docs/doc[@for="SecurityMasks.Owner"]/*' />
+ Owner = 1,
+
+ /// <include file='doc\SecurityMasks.uex' path='docs/doc[@for="SecurityMasks.Group"]/*' />
+ Group = 2,
+
+ /// <include file='doc\SecurityMasks.uex' path='docs/doc[@for="SecurityMasks.DACL"]/*' />
+ Dacl = 4,
+
+ /// <include file='doc\SecurityMasks.uex' path='docs/doc[@for="SecurityMasks.SACL"]/*' />
+ Sacl = 8
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/SortDirection.cs b/src/System.DirectoryServices/src/System/DirectoryServices/SortDirection.cs
new file mode 100644
index 0000000000..bc3d4be2c2
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/SortDirection.cs
@@ -0,0 +1,23 @@
+// 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
+{
+ /// <include file='doc\SortDirection.uex' path='docs/doc[@for="SortDirection"]/*' />
+ /// <devdoc>
+ /// </devdoc>
+ public enum SortDirection
+ {
+ /// <include file='doc\SortDirection.uex' path='docs/doc[@for="SortDirection.Ascending"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ Ascending = 0,
+ /// <include file='doc\SortDirection.uex' path='docs/doc[@for="SortDirection.Descending"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ Descending = 1
+ }
+}
diff --git a/src/System.DirectoryServices/src/System/DirectoryServices/SortOption.cs b/src/System.DirectoryServices/src/System/DirectoryServices/SortOption.cs
new file mode 100644
index 0000000000..035fcc1b67
--- /dev/null
+++ b/src/System.DirectoryServices/src/System/DirectoryServices/SortOption.cs
@@ -0,0 +1,91 @@
+// 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
+{
+ using System.ComponentModel;
+
+ /// <include file='doc\SortOption.uex' path='docs/doc[@for="SortOption"]/*' />
+ /// <devdoc>
+ /// <para>Specifies how to sort a query.</para>
+ /// </devdoc>
+ [TypeConverter(typeof(ExpandableObjectConverter))]
+ public class SortOption
+ {
+ private string _propertyName;
+ private SortDirection _sortDirection;
+
+ /// <include file='doc\SortOption.uex' path='docs/doc[@for="SortOption.SortOption"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public SortOption()
+ {
+ }
+
+ /// <include file='doc\SortOption.uex' path='docs/doc[@for="SortOption.SortOption1"]/*' />
+ /// <devdoc>
+ /// <para>[To be supplied.]</para>
+ /// </devdoc>
+ public SortOption(string propertyName, SortDirection direction)
+ {
+ this.PropertyName = propertyName;
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5_3)
+ {
+ this.Direction = direction;
+ }
+ else
+ {
+ this.Direction = _sortDirection;
+ }
+ }
+
+ /// <include file='doc\SortOption.uex' path='docs/doc[@for="SortOption.PropertyName"]/*' />
+ /// <devdoc>
+ /// <para>Specifies a pointer to a stream that contains the type for the attribute.</para>
+ /// </devdoc>
+ [
+ DefaultValue(null),
+ DSDescriptionAttribute(Res.DSSortName)
+ ]
+ public string PropertyName
+ {
+ get
+ {
+ return _propertyName;
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _propertyName = value;
+ }
+ }
+
+ /// <include file='doc\SortOption.uex' path='docs/doc[@for="SortOption.Direction"]/*' />
+ /// <devdoc>
+ /// <para>Specifies one of the <see cref='System.DirectoryServices.SortDirection'/> values.</para>
+ /// </devdoc>
+ [
+ DefaultValue(SortDirection.Ascending),
+ DSDescriptionAttribute(Res.DSSortDirection)
+ ]
+ public SortDirection Direction
+ {
+ get
+ {
+ return _sortDirection;
+ }
+
+ set
+ {
+ if (value < SortDirection.Ascending || value > SortDirection.Descending)
+ throw new InvalidEnumArgumentException("value", (int)value, typeof(SortDirection));
+
+ _sortDirection = value;
+ }
+ }
+ }
+}
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.delegateEvent.delegate.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.delegateEvent.delegate.cs
index e967cca0be..9120da1158 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.delegateEvent.delegate.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.delegateEvent.delegate.cs
@@ -65,7 +65,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
public class Foo
{
// public delegate dynamic D001(dynamic v);
- static public dynamic M01(dynamic v)
+ public static dynamic M01(dynamic v)
{
return 0x01;
}
@@ -80,13 +80,13 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
return 0x03;
}
- static public dynamic M04(object v)
+ public static dynamic M04(object v)
{
return 0x04;
}
// public delegate object D002(dynamic d, object o);
- static public object M05(dynamic v1, object v2)
+ public static object M05(dynamic v1, object v2)
{
return 0x05;
}
@@ -96,7 +96,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
return 0x06;
}
- static public dynamic M07(dynamic v1, object v2)
+ public static dynamic M07(dynamic v1, object v2)
{
return 0x07;
}
@@ -107,7 +107,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
}
// dynamic D003(ref dynamic d1, object o, out dynamic d3);
- static public dynamic M09(ref dynamic v1, object v2, out dynamic v3)
+ public static dynamic M09(ref dynamic v1, object v2, out dynamic v3)
{
v3 = null;
return 0x09;
@@ -126,7 +126,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
}
// public delegate void D004(dynamic[] d1, params dynamic[] d2);
- static public void M0C(ref int n, dynamic[] v1, params dynamic[] v2)
+ public static void M0C(ref int n, dynamic[] v1, params dynamic[] v2)
{
n += 0x0C;
}
@@ -151,7 +151,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
Assert.Equal(0, MainMethod());
}
- static public int MainMethod()
+ public static int MainMethod()
{
Foo foo = new Foo();
dynamic d = new object();
@@ -229,7 +229,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
public class Foo
{
// DynNamespace01: public delegate dynamic D101(dynamic d, DynInterface01 i);
- static public dynamic M01(dynamic v1, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynInterface01 v2)
+ public static dynamic M01(dynamic v1, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynInterface01 v2)
{
return 0x01;
}
@@ -240,7 +240,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
}
// DynNamespace01: public delegate void D102(DynClass01 c, ref dynamic d1, ref object d2)
- static public void M03(ref ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynClass01 v1, dynamic v2, ref object v3)
+ public static void M03(ref ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynClass01 v1, dynamic v2, ref object v3)
{
v1.n = 3;
}
@@ -258,7 +258,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
v3 = null;
}
- static public void M06(ref object v1, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynClass01 v2, out dynamic[] v3, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynStruct01 v4)
+ public static void M06(ref object v1, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynClass01 v2, out dynamic[] v3, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynStruct01 v4)
{
v1 = 6;
v3 = null;
@@ -272,7 +272,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
// DynNamespace01:
// public delegate dynamic D202(DynStruct01 st, params object[] d2)
- static public dynamic M08(ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynStruct01 v1, params object[] v2)
+ public static dynamic M08(ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib01.dlgatedeclarelib01.DynNamespace01.DynStruct01 v1, params object[] v2)
{
return 0x08;
}
@@ -345,7 +345,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
{
// DynNamespace01.DynClass:
// public delegate string D001(object v1, dynamic v2, ref DynEnum v3)
- static public string M01(object v1, object v2, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib02.dlgatedeclarelib02.DynNamespace01.DynEnum v3)
+ public static string M01(object v1, object v2, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib02.dlgatedeclarelib02.DynNamespace01.DynEnum v3)
{
return v3.ToString();
}
@@ -360,7 +360,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
return v3.ToString();
}
- static public string M02(dynamic v1, dynamic v2, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib02.dlgatedeclarelib02.DynNamespace01.DynEnum v3)
+ public static string M02(dynamic v1, dynamic v2, ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlgate.dlgatedeclarelib02.dlgatedeclarelib02.DynNamespace01.DynEnum v3)
{
return v3.ToString();
}
@@ -392,7 +392,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
Assert.Equal(0, MainMethod());
}
- static public int MainMethod()
+ public static int MainMethod()
{
bool ret = true;
Foo foo = new Foo();
@@ -566,23 +566,23 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
// DynNamespace31.DynClassDrived:
// internal delegate long InternalDel(sbyte v1, dynamic v2, short v3, dynamic v4, int v5, dynamic v6, long v7, dynamic v8, dynamic v9)
- static public long M11(sbyte v1, dynamic v2, short v3, dynamic v4, int v5, dynamic v6, long v7, dynamic v8, dynamic v9)
+ public static long M11(sbyte v1, dynamic v2, short v3, dynamic v4, int v5, dynamic v6, long v7, dynamic v8, dynamic v9)
{
return v1 + (int)v2 + v3 + (int)v4 + v5 + (int)v6 + v7 + (int)v8 + (int)v9;
}
- static internal long M12(sbyte v1, dynamic v2, short v3, dynamic v4, int v5, dynamic v6, long v7, dynamic v8, object v9)
+ internal static long M12(sbyte v1, dynamic v2, short v3, dynamic v4, int v5, dynamic v6, long v7, dynamic v8, object v9)
{
return v1 + v3 + v5 + v7 + (int)v9;
}
- static public long M13(sbyte v1, dynamic v2, short v3, object v4, int v5, dynamic v6, long v7, dynamic v8, object v9)
+ public static long M13(sbyte v1, dynamic v2, short v3, object v4, int v5, dynamic v6, long v7, dynamic v8, object v9)
{
return (int)v2 + (int)v4 + (int)v6 + (int)v8;
}
// DynNamespace31.DynClassDrived:
- // static public delegate int StPublicDel(dynamic v1, decimal v2);
+ // public static delegate int StPublicDel(dynamic v1, decimal v2);
internal int M21(dynamic v1, decimal v2)
{
return 33;
@@ -615,7 +615,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
Assert.Equal(0, MainMethod());
}
- static public int MainMethod()
+ public static int MainMethod()
{
bool ret = true;
Foo foo = new Foo();
@@ -781,9 +781,9 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
{
public class Foo
{
- static public int val = -1;
- static public int? nval = -1;
- static public string str = string.Empty;
+ public static int val = -1;
+ public static int? nval = -1;
+ public static string str = string.Empty;
// public delegate void D001(dynamic d = null);
public void M01(dynamic d = null)
{
@@ -796,7 +796,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
}
// internal delegate void D002(dynamic v1, object v2 = null, dynamic v3 = null)
- static internal void M11(dynamic v1, object v2, dynamic v3 = null)
+ internal static void M11(dynamic v1, object v2, dynamic v3 = null)
{
str = v3;
}
@@ -808,19 +808,19 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
}
// internal delegate int D021(params dynamic[] d);
- static internal int M31(params dynamic[] d)
+ internal static int M31(params dynamic[] d)
{
return 31;
}
// public delegate void D022(DynStruct01 v1, dynamic v2 = 0.123f, int v3 = -1);
- static internal void M41(DynStruct01 v1, dynamic v2 = null, int v3 = 41)
+ internal static void M41(DynStruct01 v1, dynamic v2 = null, int v3 = 41)
{
val = v3;
}
// public delegate dynamic D031(DynClass01 v1, DynStruct01 v2 = new DynStruct01(), dynamic[] v3 = null);
- static public dynamic M51(DynClass01 v1, DynStruct01 v2 = new DynStruct01(), dynamic[] v3 = null)
+ public static dynamic M51(DynClass01 v1, DynStruct01 v2 = new DynStruct01(), dynamic[] v3 = null)
{
return 51;
}
@@ -843,7 +843,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
Assert.Equal(0, MainMethod());
}
- static public int MainMethod()
+ public static int MainMethod()
{
bool ret = true;
Foo foo = new Foo();
@@ -969,22 +969,22 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
public delegate void DelOut(object v1, out object v2);
public class Foo
{
- static public void M01(object v1, out object v2)
+ public static void M01(object v1, out object v2)
{
v2 = null;
}
- static public void M02(object v1, out dynamic v2)
+ public static void M02(object v1, out dynamic v2)
{
v2 = null;
}
- static public void M03(dynamic v1, out object v2)
+ public static void M03(dynamic v1, out object v2)
{
v2 = null;
}
- static internal void M04(dynamic v1, out dynamic v2)
+ internal static void M04(dynamic v1, out dynamic v2)
{
v2 = null;
}
@@ -998,7 +998,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
Assert.Equal(0, MainMethod());
}
- static public int MainMethod()
+ public static int MainMethod()
{
dynamic nd = null;
dynamic d = new object();
@@ -1056,7 +1056,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
{
}
- static public void SMinStruct(dynamic v1)
+ public static void SMinStruct(dynamic v1)
{
}
}
@@ -1067,7 +1067,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
{
}
- static public void SMinClass(dynamic v1)
+ public static void SMinClass(dynamic v1)
{
}
}
@@ -1080,7 +1080,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
Assert.Equal(0, MainMethod());
}
- static public int MainMethod()
+ public static int MainMethod()
{
bool ret = true;
Bar bar = new Bar();
@@ -1156,7 +1156,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.dlgateEvent.dlg
Assert.Equal(0, MainMethod());
}
- static public int MainMethod()
+ public static int MainMethod()
{
Foo foo = new Foo();
DOptObj dobj01 = new DOptObj(foo.M01);
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.indexer.regclass.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.indexer.regclass.cs
index c2cafb140b..a67ab71bfe 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.indexer.regclass.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.indexer.regclass.cs
@@ -1211,7 +1211,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.indexer.regclas
}
}
- static public class Extension
+ public static class Extension
{
public static Test ExReturnTest(this MyEnum me)
{
@@ -2435,7 +2435,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.indexer.regclas
}
}
- static public class Extension
+ public static class Extension
{
public static char Method(this char? c)
{
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.genclass.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.genclass.cs
index 097076b836..de5075e0da 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.genclass.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.genclass.cs
@@ -437,7 +437,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.method.regmetho
}
}
- static public class Extension
+ public static class Extension
{
public static Test ExReturnTest(this int t)
{
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs
index 97ef6787c1..55a9e075ed 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.method.regmethod.regclass.cs
@@ -1427,7 +1427,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.method.regmetho
}
}
- static public class Extension
+ public static class Extension
{
public static bool IsNull(this int? value)
{
@@ -1564,7 +1564,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.method.regmetho
namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.method.regmethod.regclass.regclass057.regclass057
{
using ManagedTests.DynamicCSharp.Conformance.dynamic.context.method.regmethod.regclass.regclassregmeth.regclassregmeth;
- // <Title> Tests regular class regular method used in unsafe static method body.</Title>
+ // <Title> Tests regular class regular method used in static unsafe method body.</Title>
// <Description>
// </Description>
// <RelatedBugs></RelatedBugs>
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.compound.basic.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.compound.basic.cs
index 2e6a7a5339..20999ed9d1 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.compound.basic.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.compound.basic.cs
@@ -163,7 +163,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.operate.compoun
public class Test
{
- static public dynamic count1 = 1;
+ public static dynamic count1 = 1;
[Fact]
public static void DynamicCSharpRunTest()
{
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.genclass.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.genclass.cs
index 49fe4c8a8b..1c9b550f53 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.genclass.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.genclass.cs
@@ -697,7 +697,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.operate.genclas
}
}
- static public class Extension
+ public static class Extension
{
public static int ExReturnTest(this int p)
{
@@ -1250,7 +1250,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.operate.genclas
}
}
- static public class Extension
+ public static class Extension
{
public static int Method(this string s)
{
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.regclass.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.regclass.cs
index 8f4795d853..40163531bc 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.regclass.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.operator.regclass.cs
@@ -861,7 +861,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.operate.regclas
}
}
- static public class Extension
+ public static class Extension
{
public static MyEnum ExReturnMyEnum(this MyClass mc)
{
@@ -2817,7 +2817,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.operate.regclas
}
}
- static public class Extension
+ public static class Extension
{
public static int Method(this MyEnum[] mea)
{
@@ -3068,7 +3068,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.operate.regclas
}
}
- static public class Extension
+ public static class Extension
{
public static float? ExReturnFloat(this MyStruct mc)
{
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.genclass.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.genclass.cs
index 3fe2193511..436d62fe0f 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.genclass.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.genclass.cs
@@ -536,7 +536,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.property.autopr
}
}
- static public class Extension
+ public static class Extension
{
public static Test ExReturnTest(this string s)
{
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.regclass.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.regclass.cs
index 848a9e5f7c..58405b7b40 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.regclass.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Context/Conformance.dynamic.context.property.autoproperty.regclass.cs
@@ -598,7 +598,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.context.property.autopr
}
}
- static public class Extension
+ public static class Extension
{
public static MyStruct TestSetMyStruct(this int i)
{
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.formalParameter.Methods.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.formalParameter.Methods.cs
index 57d18474fb..3aaac9f201 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.formalParameter.Methods.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.formalParameter.Methods.cs
@@ -16,7 +16,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.declarations.formalPara
// <Code>
public class MyClass
{
- static public dynamic Foo(this int x)
+ public static dynamic Foo(this int x)
{
return x;
}
@@ -64,7 +64,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.declarations.formalPara
// <Code>
public class MyClass
{
- static public dynamic Foo(this int x, dynamic d)
+ public static dynamic Foo(this int x, dynamic d)
{
return d;
}
@@ -113,7 +113,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.declarations.formalPara
// <Code>
public class MyClass
{
- static public string Foo(this object x, dynamic d)
+ public static string Foo(this object x, dynamic d)
{
return d.ToString();
}
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.returnType.methods.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.returnType.methods.cs
index 1e819f9b72..92986c992f 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.returnType.methods.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Declarations/Conformance.dynamic.declarations.returnType.methods.cs
@@ -311,7 +311,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.declarations.returnType
// <Code>
public class MyClass
{
- static public dynamic Foo(this int x)
+ public static dynamic Foo(this int x)
{
dynamic d = x;
return d;
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.basic.cs b/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.basic.cs
index f7d9efaa29..eaddcc3175 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.basic.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.basic.cs
@@ -5483,7 +5483,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.basic.unsfe
// <Code>
//class B
//{
- //[Test][Priority(Priority.Priority2)]public void DynamicCSharpRunTest(){Assert.AreEqual(0, MainMethod());} public unsafe static int MainMethod()
+ //[Test][Priority(Priority.Priority2)]public void DynamicCSharpRunTest(){Assert.AreEqual(0, MainMethod());} public static unsafe int MainMethod()
//{
////basic alloc
//dynamic y = 1;
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.conversions.cs b/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.conversions.cs
index 225b1e4149..de56a7187d 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.conversions.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.conversions.cs
@@ -4206,7 +4206,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.conversions
return 0;
}
- static public MyStack<object> SPropObj
+ public static MyStack<object> SPropObj
{
get
{
@@ -4242,7 +4242,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.conversions
return new MyStack<object>();
}
- static public MyStack<dynamic> M4DelDyn(int x = 1, int y = 1)
+ public static MyStack<dynamic> M4DelDyn(int x = 1, int y = 1)
{
return new MyStack<dynamic>();
}
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.formalParameter.cs b/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.formalParameter.cs
index 662483bad2..ff4bafbf27 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.formalParameter.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.formalParameter.cs
@@ -273,7 +273,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.formalParam
return ret ? 0 : 1;
}
- static public bool Varifier(int expected, string output)
+ public static bool Varifier(int expected, string output)
{
if (expected == MyType.Result)
return true;
@@ -551,7 +551,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.formalParam
return ret ? 0 : 1;
}
- static public bool Varifier(int expected, int actual, string output)
+ public static bool Varifier(int expected, int actual, string output)
{
if (expected == actual)
return true;
@@ -702,7 +702,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.formalParam
return ret ? 0 : 1;
}
- static public bool Varifier(int expected, string output)
+ public static bool Varifier(int expected, string output)
{
if (expected == MyType.Result)
return true;
@@ -883,7 +883,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.formalParam
return ret ? 0 : 1;
}
- static public bool Varifier(int expected, string output)
+ public static bool Varifier(int expected, string output)
{
if (expected == MyType.Result)
return true;
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.overloadResolution.method.1class.2param.cs b/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.overloadResolution.method.1class.2param.cs
index 7bf91038ba..9eef34e620 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.overloadResolution.method.1class.2param.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.overloadResolution.method.1class.2param.cs
@@ -19,7 +19,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.overloadRes
s_status = 1;
}
- internal protected void Method(long x, object o)
+ protected internal void Method(long x, object o)
{
s_status = 2;
}
@@ -66,7 +66,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.overloadRes
s_status = 1;
}
- internal protected void Method(long x, object o)
+ protected internal void Method(long x, object o)
{
s_status = 2;
}
@@ -437,7 +437,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.dynamicType.overloadRes
{
}
- internal protected void Method(long x, object o)
+ protected internal void Method(long x, object o)
{
}
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.NamedAndOptional/Conformance.dynamic.namedandoptional.decl.opOverload.cs b/src/System.Dynamic.Runtime/tests/Dynamic.NamedAndOptional/Conformance.dynamic.namedandoptional.decl.opOverload.cs
index a35ac56789..87b5940f8d 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.NamedAndOptional/Conformance.dynamic.namedandoptional.decl.opOverload.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.NamedAndOptional/Conformance.dynamic.namedandoptional.decl.opOverload.cs
@@ -16,7 +16,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.namedandoptional.decl.o
//<Expects Status=warning>\(10,39\).*CS1066</Expects>
public class Derived
{
- static public explicit operator int (Derived d = null)
+ public static explicit operator int (Derived d = null)
{
if (d != null)
return 0;
@@ -57,7 +57,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.namedandoptional.decl.o
//<Expects Status=warning>\(12,41\).*CS1066</Expects>
public class Derived
{
- static public explicit operator int (Derived d = default(Derived))
+ public static explicit operator int (Derived d = default(Derived))
{
if (d == null)
return 0;
@@ -109,7 +109,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.namedandoptional.decl.o
public class Derived
{
private const Derived x = null;
- static public explicit operator int (Derived d = x)
+ public static explicit operator int (Derived d = x)
{
if (d != null)
return 0;
@@ -150,7 +150,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.namedandoptional.decl.o
public class Derived
{
private const Derived x = null;
- static public explicit operator int (Derived d = true ? x : x)
+ public static explicit operator int (Derived d = true ? x : x)
{
if (d != null)
return 0;
@@ -190,7 +190,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.namedandoptional.decl.o
//<Expects Status=warning>\(10,39\).*CS1066</Expects>
public class Derived
{
- static public implicit operator int (Derived d = null)
+ public static implicit operator int (Derived d = null)
{
if (d != null)
return 0;
@@ -231,7 +231,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.namedandoptional.decl.o
//<Expects Status=warning>\(11,39\).*CS1066</Expects>
public class Derived
{
- static public implicit operator int (Derived d = default(Derived))
+ public static implicit operator int (Derived d = default(Derived))
{
if (d == null)
return 0;
@@ -283,7 +283,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.namedandoptional.decl.o
public class Derived
{
private const Derived x = null;
- static public implicit operator int (Derived d = x)
+ public static implicit operator int (Derived d = x)
{
if (d != null)
return 0;
@@ -324,7 +324,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.namedandoptional.decl.o
public class Derived
{
private const Derived x = null;
- static public implicit operator int (Derived d = true ? x : x)
+ public static implicit operator int (Derived d = true ? x : x)
{
if (d != null)
return 0;
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Other/Conformance.dynamic.ClsCompliance.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Other/Conformance.dynamic.ClsCompliance.cs
index f4a6f0a994..8afc8b7d19 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Other/Conformance.dynamic.ClsCompliance.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Other/Conformance.dynamic.ClsCompliance.cs
@@ -433,7 +433,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.ClsCompliance.namingchr
public class MyClass2 : MyClass
{
- //static public dynamic[,,,] array1; //cube array
+ //public static dynamic[,,,] array1; //cube array
private dynamic _classIdentifier;
private dynamic MEthod01(int n, ref dynamic d)
{
@@ -460,7 +460,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.ClsCompliance.namingchr
return default(object);
}
- internal protected dynamic method03(U x, ref V y, params dynamic[] ary)
+ protected internal dynamic method03(U x, ref V y, params dynamic[] ary)
{
return default(object);
}
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Methods.2class2methods.cs b/src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Methods.2class2methods.cs
index 6c05e63fa0..a7581e257a 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Methods.2class2methods.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Methods.2class2methods.cs
@@ -491,7 +491,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.overloadResolution.Meth
public class B
{
- static public int status = -1;
+ public static int status = -1;
public void Foo(out int x)
{
status = 1;
@@ -538,7 +538,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.overloadResolution.Meth
public class B
{
- static public int status = -1;
+ public static int status = -1;
public void Foo(out int x)
{
status = 1;
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.1class2operators.conversion.cs b/src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.1class2operators.conversion.cs
index 0c481ffa65..21b9cccfe9 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.1class2operators.conversion.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.OverloadResolution/Conformance.dynamic.overloadResolution.Operators.1class2operators.conversion.cs
@@ -887,7 +887,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.overloadResolution.Oper
public class Target
{
- static public int Status = 0;
+ public static int Status = 0;
public static implicit operator Target(ValueType x)
{
Target.Status = 1;
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.PointerOperator.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.PointerOperator.cs
index 0eeb89a043..5be1c4415a 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.PointerOperator.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.PointerOperator.cs
@@ -21,7 +21,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.PointegeregererOp
[TestClass]
- unsafe public class Test
+ public unsafe class Test
{
[Test]
[Priority(Priority.Priority0)]
@@ -65,7 +65,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.PointegeregererOp
[TestClass]
- unsafe public class Test
+ public unsafe class Test
{
[Test]
[Priority(Priority.Priority0)]
@@ -122,7 +122,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.PointegeregererOp
// <Code>
[TestClass]
- unsafe public class Test
+ public unsafe class Test
{
[Test]
[Priority(Priority.Priority1)]
@@ -153,7 +153,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.PointegeregererOp
// <Code>
[TestClass]
- unsafe public class Test
+ public unsafe class Test
{
[Test]
[Priority(Priority.Priority1)]
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.basic.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.basic.cs
index 209bea4ab2..9197e673a8 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.basic.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/Conformance.dynamic.unsafe.basic.cs
@@ -146,7 +146,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.attribute01
}
[MyAttr]
- unsafe public class US
+ public unsafe class US
{
public int* p;
}
@@ -184,7 +184,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.collection0
//<Expects Status=warning>\(14,17\).*CS0649</Expects>
using System.Collections.Generic;
- unsafe public class US
+ public unsafe class US
{
public int* p;
}
@@ -225,7 +225,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.collection0
//<Expects Status=warning>\(14,17\).*CS0649</Expects>
using System.Collections.Generic;
- unsafe public class US
+ public unsafe class US
{
public int* p;
}
@@ -271,7 +271,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.collection0
using System.Collections.Generic;
using Microsoft.CSharp.RuntimeBinder;
- unsafe public class US
+ public unsafe class US
{
public int* p;
}
@@ -445,7 +445,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.dlgate01.dl
//<Expects Status=success></Expects>
// <Code>
internal unsafe delegate void Foo(int* p);
- unsafe public class Test
+ public unsafe class Test
{
[Fact]
public static void DynamicCSharpRunTest()
@@ -518,7 +518,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.evnt01.evnt
//<Expects Status=success></Expects>
// <Code>
internal unsafe delegate void Foo(int* p);
- unsafe public class Test
+ public unsafe class Test
{
[Fact]
public static void DynamicCSharpRunTest()
@@ -610,7 +610,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.expressiont
public int* p;
}
- unsafe public class Test
+ public unsafe class Test
{
[Fact]
public static void DynamicCSharpRunTest()
@@ -645,7 +645,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.field01.fie
public class C
{
public unsafe int* p;
- public unsafe static char* q;
+ public static unsafe char* q;
}
public unsafe class Test
@@ -765,7 +765,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.indexer02.i
public class C
{
public const int field = 10;
- unsafe public int* this[int[] index]
+ public unsafe int* this[int[] index]
{
get
{
@@ -777,7 +777,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.indexer02.i
}
}
- static public class D
+ public static class D
{
public static int field = 1;
}
@@ -821,7 +821,7 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.indexer04.i
// <Code>
public class Unsafe
{
- unsafe public int* this[int index]
+ public unsafe int* this[int index]
{
get
{
@@ -882,14 +882,14 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.integereger
void Foo(dynamic p);
}
- unsafe public class C : IF
+ public unsafe class C : IF
{
public void Foo(dynamic p)
{
}
}
- unsafe public class Test
+ public unsafe class Test
{
[Fact]
public static void DynamicCSharpRunTest()
@@ -923,12 +923,12 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.lambda01.la
//<Expects Status=warning>\(14,17\).*CS0649</Expects>
using System;
- unsafe public class UC
+ public unsafe class UC
{
public int* p;
}
- unsafe public class Test
+ public unsafe class Test
{
[Fact]
public static void DynamicCSharpRunTest()
@@ -963,12 +963,12 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.lambda02.la
//<Expects Status=warning>\(14,17\).*CS0649</Expects>
using System;
- unsafe public class UC
+ public unsafe class UC
{
public int* p;
}
- unsafe public class Test
+ public unsafe class Test
{
[Fact]
public static void DynamicCSharpRunTest()
@@ -1010,12 +1010,12 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.method02.me
// <Code>
public class C
{
- unsafe public int Foo(dynamic p)
+ public unsafe int Foo(dynamic p)
{
return 1;
}
- unsafe public static int Bar(dynamic p)
+ public static unsafe int Bar(dynamic p)
{
return 2;
}
@@ -1057,12 +1057,12 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.method05.me
public class C
{
public static int field = 10;
- unsafe public dynamic Foo()
+ public unsafe dynamic Foo()
{
return 1;
}
- unsafe public static dynamic Bar()
+ public static unsafe dynamic Bar()
{
return 2;
}
@@ -1105,7 +1105,7 @@ public class US
public int* ptr;
}
- static public class Ext
+ public static class Ext
{
public static void Foo(this US u, dynamic d)
{
@@ -1193,12 +1193,12 @@ namespace ManagedTests.DynamicCSharp.Conformance.dynamic.unsfe.basic.objinit01.o
// <Code>
using System.Collections.Generic;
- unsafe public class US
+ public unsafe class US
{
public int* p;
}
- unsafe public class Test
+ public unsafe class Test
{
[Fact]
public static void DynamicCSharpRunTest()
diff --git a/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/conformance.dynamic.unsafe.context.cs b/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/conformance.dynamic.unsafe.context.cs
index a237f6b78f..18eac9d2ff 100644
--- a/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/conformance.dynamic.unsafe.context.cs
+++ b/src/System.Dynamic.Runtime/tests/Dynamic.Unsafe/conformance.dynamic.unsafe.context.cs
@@ -176,7 +176,7 @@ namespace ManagedTests.DynamicCSharp.conformance.dynamic.unsfe.context.freach03.
//}
//[TestClass]public class Test
//{
- //[Test][Priority(Priority.Priority2)]public void DynamicCSharpRunTest(){Assert.AreEqual(0, MainMethod(null));} public unsafe static int MainMethod(string[] args)
+ //[Test][Priority(Priority.Priority2)]public void DynamicCSharpRunTest(){Assert.AreEqual(0, MainMethod(null));} public static unsafe int MainMethod(string[] args)
//{
//int a = 1, b = 2, c = 3;
//dynamic arrayp = new int*[] { &a, &b, &c };
diff --git a/src/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetInstance.cs b/src/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetInstance.cs
index 8c158dede7..c48071044f 100644
--- a/src/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetInstance.cs
+++ b/src/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetInstance.cs
@@ -39,11 +39,43 @@ namespace System.Globalization.Tests
Assert.NotNull(DateTimeFormatInfo.GetInstance(provider));
}
+ private void AssertSameValues(DateTimeFormatInfo expected, DateTimeFormatInfo value)
+ {
+ if (value.Equals(expected))
+ {
+ // same instance, we don't have to test the values
+ return;
+ }
+
+ Assert.Equal(expected.AbbreviatedDayNames, value.AbbreviatedDayNames);
+ Assert.Equal(expected.AbbreviatedMonthGenitiveNames, value.AbbreviatedMonthGenitiveNames);
+ Assert.Equal(expected.AbbreviatedMonthNames, value.AbbreviatedMonthNames);
+ Assert.Equal(expected.DayNames, value.DayNames);
+ Assert.Equal(expected.MonthGenitiveNames, value.MonthGenitiveNames);
+ Assert.Equal(expected.MonthNames, value.MonthNames);
+ Assert.Equal(expected.ShortestDayNames, value.ShortestDayNames);
+
+ Assert.Equal(expected.AMDesignator, value.AMDesignator);
+ Assert.Equal(expected.FullDateTimePattern, value.FullDateTimePattern);
+ Assert.Equal(expected.LongDatePattern, value.LongDatePattern);
+ Assert.Equal(expected.LongTimePattern, value.LongTimePattern);
+ Assert.Equal(expected.MonthDayPattern, value.MonthDayPattern);
+ Assert.Equal(expected.PMDesignator, value.PMDesignator);
+ Assert.Equal(expected.RFC1123Pattern, value.RFC1123Pattern);
+ Assert.Equal(expected.ShortDatePattern, value.ShortDatePattern);
+ Assert.Equal(expected.ShortTimePattern, value.ShortTimePattern);
+ Assert.Equal(expected.SortableDateTimePattern, value.SortableDateTimePattern);
+ Assert.Equal(expected.UniversalSortableDateTimePattern, value.UniversalSortableDateTimePattern);
+ Assert.Equal(expected.YearMonthPattern, value.YearMonthPattern);
+ Assert.Equal(expected.CalendarWeekRule, value.CalendarWeekRule);
+ Assert.Equal(expected.FirstDayOfWeek, value.FirstDayOfWeek);
+ }
+
[Fact]
public void GetInstance_ExpectedCurrent()
{
- Assert.Same(DateTimeFormatInfo.CurrentInfo, DateTimeFormatInfo.GetInstance(null));
- Assert.Same(DateTimeFormatInfo.CurrentInfo, DateTimeFormatInfo.GetInstance(new TestIFormatProviderClass()));
+ AssertSameValues(DateTimeFormatInfo.CurrentInfo, DateTimeFormatInfo.GetInstance(null));
+ AssertSameValues(DateTimeFormatInfo.CurrentInfo, DateTimeFormatInfo.GetInstance(new TestIFormatProviderClass()));
}
}
}
diff --git a/src/System.IO.Compression/src/Interop/Interop.zlib.Unix.cs b/src/System.IO.Compression/src/Interop/Interop.zlib.Unix.cs
index 94f3927338..fb6bfc3c17 100644
--- a/src/System.IO.Compression/src/Interop/Interop.zlib.Unix.cs
+++ b/src/System.IO.Compression/src/Interop/Interop.zlib.Unix.cs
@@ -40,6 +40,6 @@ internal static partial class Interop
}
[DllImport(Libraries.CompressionNative, EntryPoint = "CompressionNative_Crc32")]
- private static unsafe extern uint Crc32(uint crc, byte* buffer, int len);
+ private static extern unsafe uint Crc32(uint crc, byte* buffer, int len);
}
}
diff --git a/src/System.IO.Compression/src/Interop/Interop.zlib.Windows.cs b/src/System.IO.Compression/src/Interop/Interop.zlib.Windows.cs
index 23c5561801..15bcf21469 100644
--- a/src/System.IO.Compression/src/Interop/Interop.zlib.Windows.cs
+++ b/src/System.IO.Compression/src/Interop/Interop.zlib.Windows.cs
@@ -16,26 +16,26 @@ internal static partial class Interop
private static readonly byte[] ZLibVersion = new byte[] { (byte)'1', (byte)'.', (byte)'2', (byte)'.', (byte)'3', 0 };
[DllImport(Libraries.Zlib)]
- private extern unsafe static int deflateInit2_(byte* stream, int level, int method, int windowBits, int memLevel, int strategy,
+ private extern static unsafe int deflateInit2_(byte* stream, int level, int method, int windowBits, int memLevel, int strategy,
byte* version, int stream_size);
[DllImport(Libraries.Zlib)]
- private extern unsafe static int deflate(byte* stream, int flush);
+ private extern static unsafe int deflate(byte* stream, int flush);
[DllImport(Libraries.Zlib)]
- private extern unsafe static int deflateEnd(byte* strm);
+ private extern static unsafe int deflateEnd(byte* strm);
[DllImport(Libraries.Zlib)]
- internal extern unsafe static uint crc32(uint crc, byte* buffer, int len);
+ internal extern static unsafe uint crc32(uint crc, byte* buffer, int len);
[DllImport(Libraries.Zlib)]
- private extern unsafe static int inflateInit2_(byte* stream, int windowBits, byte* version, int stream_size);
+ private extern static unsafe int inflateInit2_(byte* stream, int windowBits, byte* version, int stream_size);
[DllImport(Libraries.Zlib)]
- private extern unsafe static int inflate(byte* stream, int flush);
+ private extern static unsafe int inflate(byte* stream, int flush);
[DllImport(Libraries.Zlib)]
- private extern unsafe static int inflateEnd(byte* stream);
+ private extern static unsafe int inflateEnd(byte* stream);
internal static unsafe ZLibNative.ErrorCode DeflateInit2_(
ref ZLibNative.ZStream stream,
diff --git a/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoder.cs b/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoder.cs
index 1d7f917816..089cd09cad 100644
--- a/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoder.cs
+++ b/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoder.cs
@@ -156,7 +156,7 @@ namespace System.IO.Compression
output.WriteBits(code_len, code_info >> 5);
}
- static internal void WriteMatch(int matchLen, int matchPos, OutputBuffer output)
+ internal static void WriteMatch(int matchLen, int matchPos, OutputBuffer output)
{
Debug.Assert(matchLen >= FastEncoderWindow.MinMatch && matchLen <= FastEncoderWindow.MaxMatch, "Illegal currentMatch length!");
@@ -184,7 +184,7 @@ namespace System.IO.Compression
}
}
- static internal void WriteChar(byte b, OutputBuffer output)
+ internal static void WriteChar(byte b, OutputBuffer output)
{
uint code = FastEncoderStatics.FastEncoderLiteralCodeInfo[b];
output.WriteBits((int)code & 31, code >> 5);
@@ -197,7 +197,7 @@ namespace System.IO.Compression
// FastEncoderLiteralTreeLength
// FastEncoderDistanceTreeLength
//
- static internal void WriteDeflatePreamble(OutputBuffer output)
+ internal static void WriteDeflatePreamble(OutputBuffer output)
{
//Debug.Assert( bitCount == 0, "bitCount must be zero before writing tree bit!");
diff --git a/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoderStatus.cs b/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoderStatus.cs
index 44ab16517a..ed31f9888a 100644
--- a/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoderStatus.cs
+++ b/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/FastEncoderStatus.cs
@@ -167,7 +167,7 @@ namespace System.IO.Compression
internal const int BFinalNoCompressionHeaderBitCount = 3;
internal const int MaxCodeLen = 16;
- static private byte[] s_distLookup;
+ private static byte[] s_distLookup;
static FastEncoderStatics()
{
@@ -218,7 +218,7 @@ namespace System.IO.Compression
}
// Return the position slot (0...29) of a match offset (0...32767)
- static internal int GetSlot(int pos)
+ internal static int GetSlot(int pos)
{
return s_distLookup[((pos) < 256) ? (pos) : (256 + ((pos) >> 7))];
}
diff --git a/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs b/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs
index a45cf603d6..1cc1792248 100644
--- a/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs
+++ b/src/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs
@@ -51,7 +51,7 @@ namespace System.IO.Compression
s_staticDistanceTree = new HuffmanTree(GetStaticDistanceTreeLength());
}
- static public HuffmanTree StaticLiteralLengthTree
+ public static HuffmanTree StaticLiteralLengthTree
{
get
{
@@ -59,7 +59,7 @@ namespace System.IO.Compression
}
}
- static public HuffmanTree StaticDistanceTree
+ public static HuffmanTree StaticDistanceTree
{
get
{
diff --git a/src/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs b/src/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs
index 1729fd4cbd..90a57b5f4b 100644
--- a/src/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs
+++ b/src/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs
@@ -387,7 +387,7 @@ namespace System.IO.Compression
public const int OffsetToBitFlagFromHeaderStart = 6;
public const int SizeOfLocalHeader = 30;
- static public List<ZipGenericExtraField> GetExtraFields(BinaryReader reader)
+ public static List<ZipGenericExtraField> GetExtraFields(BinaryReader reader)
{
//assumes that TrySkipBlock has already been called, so we don't have to validate twice
@@ -413,7 +413,7 @@ namespace System.IO.Compression
}
//will not throw end of stream exception
- static public bool TrySkipBlock(BinaryReader reader)
+ public static bool TrySkipBlock(BinaryReader reader)
{
const int OffsetToFilenameLength = 22; //from the point after the signature
@@ -464,7 +464,7 @@ namespace System.IO.Compression
//if saveExtraFieldsAndComments is false, FileComment and ExtraFields will be null
//in either case, the zip64 extra field info will be incorporated into other fields
- static public bool TryReadBlock(BinaryReader reader, bool saveExtraFieldsAndComments, out ZipCentralDirectoryFileHeader header)
+ public static bool TryReadBlock(BinaryReader reader, bool saveExtraFieldsAndComments, out ZipCentralDirectoryFileHeader header)
{
header = new ZipCentralDirectoryFileHeader();
diff --git a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs
index 84cb7a5c23..83014abf58 100644
--- a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs
+++ b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs
@@ -316,28 +316,19 @@ namespace System.IO
// If the action is RENAMED_FROM, save the name of the file
if (action == Interop.Kernel32.FileOperations.FILE_ACTION_RENAMED_OLD_NAME)
{
- Debug.Assert(oldName == null, "Two FILE_ACTION_RENAMED_OLD_NAME in a row! [" + oldName + "], [ " + name + "]");
oldName = name;
}
else if (action == Interop.Kernel32.FileOperations.FILE_ACTION_RENAMED_NEW_NAME)
{
- if (oldName != null)
- {
- NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName);
- oldName = null;
- }
- else
- {
- Debug.Fail("FILE_ACTION_RENAMED_NEW_NAME with no old name! [ " + name + "]");
- NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName);
- oldName = null;
- }
+ // oldName may be null here if we received a FILE_ACTION_RENAMED_NEW_NAME with no old name
+ NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName);
+ oldName = null;
}
else
{
if (oldName != null)
{
- Debug.Fail("Previous FILE_ACTION_RENAMED_OLD_NAME with no new name! [" + oldName + "]");
+ // Previous FILE_ACTION_RENAMED_OLD_NAME with no new name
NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName);
oldName = null;
}
@@ -364,7 +355,7 @@ namespace System.IO
if (oldName != null)
{
- Debug.Fail("FILE_ACTION_RENAMED_OLD_NAME with no new name! [" + oldName + "]");
+ // Previous FILE_ACTION_RENAMED_OLD_NAME with no new name
NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName);
oldName = null;
}
diff --git a/src/System.IO.FileSystem/src/System/IO/FileStream.Win32.cs b/src/System.IO.FileSystem/src/System/IO/FileStream.Win32.cs
index 99b3c044ee..70a49d21bb 100644
--- a/src/System.IO.FileSystem/src/System/IO/FileStream.Win32.cs
+++ b/src/System.IO.FileSystem/src/System/IO/FileStream.Win32.cs
@@ -211,7 +211,7 @@ namespace System.IO
return handle.IsAsync.HasValue ? handle.IsAsync.Value : false;
}
- private unsafe static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share)
+ private static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share)
{
Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES);
if ((share & FileShare.Inheritable) != 0)
@@ -895,7 +895,7 @@ namespace System.IO
}
}
- unsafe private Task<int> ReadNativeAsync(byte[] bytes, int offset, int numBytes, int numBufferedBytesRead, CancellationToken cancellationToken)
+ private unsafe Task<int> ReadNativeAsync(byte[] bytes, int offset, int numBytes, int numBufferedBytesRead, CancellationToken cancellationToken)
{
AssertCanRead(bytes, offset, numBytes);
Debug.Assert(_useAsyncIO, "ReadNativeAsync doesn't work on synchronous file streams!");
@@ -1607,7 +1607,7 @@ namespace System.IO
private sealed unsafe class AsyncCopyToAwaitable : ICriticalNotifyCompletion
{
/// <summary>Sentinel object used to indicate that the I/O operation has completed before being awaited.</summary>
- private readonly static Action s_sentinel = () => { };
+ private static readonly Action s_sentinel = () => { };
/// <summary>Cached delegate to IOCallback.</summary>
internal static readonly IOCompletionCallback s_callback = IOCallback;
@@ -1648,7 +1648,7 @@ namespace System.IO
}
/// <summary>Overlapped callback: store the results, then invoke the continuation delegate.</summary>
- internal unsafe static void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOVERLAP)
+ internal static unsafe void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOVERLAP)
{
var awaitable = (AsyncCopyToAwaitable)ThreadPoolBoundHandle.GetNativeOverlappedState(pOVERLAP);
diff --git a/src/System.IO.FileSystem/src/System/IO/FileStreamCompletionSource.Win32.cs b/src/System.IO.FileSystem/src/System/IO/FileStreamCompletionSource.Win32.cs
index db5f582d69..8aa1dd08a3 100644
--- a/src/System.IO.FileSystem/src/System/IO/FileStreamCompletionSource.Win32.cs
+++ b/src/System.IO.FileSystem/src/System/IO/FileStreamCompletionSource.Win32.cs
@@ -15,7 +15,7 @@ namespace System.IO
// This is an internal object extending TaskCompletionSource with fields
// for all of the relevant data necessary to complete the IO operation.
// This is used by IOCallback and all of the async methods.
- unsafe private sealed class FileStreamCompletionSource : TaskCompletionSource<int>
+ private unsafe sealed class FileStreamCompletionSource : TaskCompletionSource<int>
{
private const long NoResult = 0;
private const long ResultSuccess = (long)1 << 32;
diff --git a/src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs b/src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs
index e3e13faba2..e470534c38 100644
--- a/src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs
+++ b/src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs
@@ -2,13 +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;
-using System.IO;
+using System.Diagnostics;
using Xunit;
namespace System.IO.Tests
{
- public class FileStream_LockUnlock : FileSystemTest
+ public class FileStream_LockUnlock : RemoteExecutorTestBase
{
[Fact]
public void InvalidArgs_Throws()
@@ -28,7 +27,6 @@ namespace System.IO.Tests
}
}
- [ActiveIssue(5964, TestPlatforms.AnyUnix)]
[Fact]
public void FileClosed_Throws()
{
@@ -40,7 +38,7 @@ namespace System.IO.Tests
Assert.Throws<ObjectDisposedException>(() => fs.Lock(0, 1));
}
- [ActiveIssue(5964, TestPlatforms.AnyUnix)]
+ [ActiveIssue(5964, TestPlatforms.OSX)]
[Theory]
[InlineData(100, 0, 100)]
[InlineData(200, 0, 100)]
@@ -59,7 +57,7 @@ namespace System.IO.Tests
}
}
- [ActiveIssue(5964, TestPlatforms.AnyUnix)]
+ [ActiveIssue(5964, TestPlatforms.OSX)]
[Theory]
[InlineData(10, 0, 2, 3, 5)]
public void NonOverlappingRegions_Success(long fileLength, long firstPosition, long firstLength, long secondPosition, long secondLength)
@@ -90,8 +88,8 @@ namespace System.IO.Tests
}
}
- [ActiveIssue(5964, TestPlatforms.AnyUnix)]
[Theory]
+ [PlatformSpecific(TestPlatforms.Windows)] // Unix locks are on a per-process basis, so overlapping locks from the same process are allowed.
[InlineData(10, 0, 10, 1, 2)]
[InlineData(10, 3, 5, 3, 5)]
[InlineData(10, 3, 5, 3, 4)]
@@ -99,7 +97,7 @@ namespace System.IO.Tests
[InlineData(10, 3, 5, 2, 6)]
[InlineData(10, 3, 5, 2, 4)]
[InlineData(10, 3, 5, 4, 6)]
- public void OverlappingRegions_ThrowsException(long fileLength, long firstPosition, long firstLength, long secondPosition, long secondLength)
+ public void OverlappingRegionsFromSameProcess_ThrowsExceptionOnWindows(long fileLength, long firstPosition, long firstLength, long secondPosition, long secondLength)
{
string path = GetTestFilePath();
File.WriteAllBytes(path, new byte[fileLength]);
@@ -115,5 +113,70 @@ namespace System.IO.Tests
fs2.Unlock(secondPosition, secondLength);
}
}
+
+ [ActiveIssue(5964, TestPlatforms.OSX)]
+ [Theory]
+ [PlatformSpecific(TestPlatforms.AnyUnix)] // Unix locks are on a per-process basis, so overlapping locks from the same process are allowed.
+ [InlineData(10, 0, 10, 1, 2)]
+ [InlineData(10, 3, 5, 3, 5)]
+ [InlineData(10, 3, 5, 3, 4)]
+ [InlineData(10, 3, 5, 4, 5)]
+ [InlineData(10, 3, 5, 2, 6)]
+ [InlineData(10, 3, 5, 2, 4)]
+ [InlineData(10, 3, 5, 4, 6)]
+ public void OverlappingRegionsFromSameProcess_AllowedOnUnix(long fileLength, long firstPosition, long firstLength, long secondPosition, long secondLength)
+ {
+ string path = GetTestFilePath();
+ File.WriteAllBytes(path, new byte[fileLength]);
+
+ using (FileStream fs1 = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
+ using (FileStream fs2 = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
+ {
+ fs1.Lock(firstPosition, firstLength);
+ fs2.Lock(secondPosition, secondLength);
+ fs1.Unlock(firstPosition, firstLength);
+ fs2.Unlock(secondPosition, secondLength);
+ }
+ }
+
+ [ActiveIssue(5964, TestPlatforms.OSX)]
+ [Theory]
+ [InlineData(10, 0, 10, 1, 2)]
+ [InlineData(10, 3, 5, 3, 5)]
+ [InlineData(10, 3, 5, 3, 4)]
+ [InlineData(10, 3, 5, 4, 5)]
+ [InlineData(10, 3, 5, 2, 6)]
+ [InlineData(10, 3, 5, 2, 4)]
+ [InlineData(10, 3, 5, 4, 6)]
+ public void OverlappingRegionsFromOtherProcess_ThrowsException(long fileLength, long firstPosition, long firstLength, long secondPosition, long secondLength)
+ {
+ string path = GetTestFilePath();
+ File.WriteAllBytes(path, new byte[fileLength]);
+
+ using (FileStream fs1 = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
+ {
+ fs1.Lock(firstPosition, firstLength);
+
+ RemoteInvoke((secondPath, secondPos, secondLen) =>
+ {
+ using (FileStream fs2 = File.Open(secondPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
+ {
+ Assert.Throws<IOException>(() => fs2.Lock(long.Parse(secondPos), long.Parse(secondLen)));
+ }
+ return SuccessExitCode;
+ }, path, secondPosition.ToString(), secondLength.ToString()).Dispose();
+
+ fs1.Unlock(firstPosition, firstLength);
+ RemoteInvoke((secondPath, secondPos, secondLen) =>
+ {
+ using (FileStream fs2 = File.Open(secondPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
+ {
+ fs2.Lock(long.Parse(secondPos), long.Parse(secondLen));
+ fs2.Unlock(long.Parse(secondPos), long.Parse(secondLen));
+ }
+ return SuccessExitCode;
+ }, path, secondPosition.ToString(), secondLength.ToString()).Dispose();
+ }
+ }
}
}
diff --git a/src/System.IO.FileSystem/tests/FileStream/ctor_str_fm_fa_fs_buffer_fo.cs b/src/System.IO.FileSystem/tests/FileStream/ctor_str_fm_fa_fs_buffer_fo.cs
index f87f7c851a..675bf7df5a 100644
--- a/src/System.IO.FileSystem/tests/FileStream/ctor_str_fm_fa_fs_buffer_fo.cs
+++ b/src/System.IO.FileSystem/tests/FileStream/ctor_str_fm_fa_fs_buffer_fo.cs
@@ -29,19 +29,17 @@ namespace System.IO.Tests
[ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))]
[InlineData(FileOptions.None)]
[InlineData(FileOptions.DeleteOnClose)]
- [InlineData(FileOptions.Encrypted)]
[InlineData(FileOptions.RandomAccess)]
[InlineData(FileOptions.SequentialScan)]
[InlineData(FileOptions.WriteThrough)]
[InlineData((FileOptions)0x20000000)] // FILE_FLAG_NO_BUFFERING on Windows
[InlineData(FileOptions.Asynchronous)]
[InlineData(FileOptions.Asynchronous | FileOptions.DeleteOnClose)]
- [InlineData(FileOptions.Asynchronous | FileOptions.Encrypted)]
[InlineData(FileOptions.Asynchronous | FileOptions.RandomAccess)]
[InlineData(FileOptions.Asynchronous | FileOptions.SequentialScan)]
[InlineData(FileOptions.Asynchronous | FileOptions.WriteThrough)]
[InlineData(FileOptions.Asynchronous | (FileOptions)0x20000000)]
- [InlineData(FileOptions.Asynchronous | FileOptions.DeleteOnClose | FileOptions.Encrypted | FileOptions.RandomAccess | FileOptions.SequentialScan | FileOptions.WriteThrough)]
+ [InlineData(FileOptions.Asynchronous | FileOptions.DeleteOnClose | FileOptions.RandomAccess | FileOptions.SequentialScan | FileOptions.WriteThrough)]
public void ValidFileOptions(FileOptions option)
{
byte[] data = new byte[c_DefaultBufferSize];
@@ -66,6 +64,16 @@ namespace System.IO.Tests
}
}
+ [ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotWindowsNanoServer))]
+ [InlineData(FileOptions.Encrypted)]
+ [InlineData(FileOptions.Asynchronous | FileOptions.Encrypted)]
+ [InlineData(FileOptions.Asynchronous | FileOptions.DeleteOnClose | FileOptions.Encrypted | FileOptions.RandomAccess | FileOptions.SequentialScan | FileOptions.WriteThrough)]
+ public void ValidFileOptions_Encrypted(FileOptions option)
+ {
+ try { ValidFileOptions(option); }
+ catch (UnauthorizedAccessException) { /* may not be allowed for some users */ }
+ }
+
[Theory]
[InlineData(FileOptions.DeleteOnClose)]
[InlineData(FileOptions.DeleteOnClose | FileOptions.Asynchronous)]
diff --git a/src/System.IO.IsolatedStorage/pkg/System.IO.IsolatedStorage.pkgproj b/src/System.IO.IsolatedStorage/pkg/System.IO.IsolatedStorage.pkgproj
index 99710eb51c..b38d23338e 100644
--- a/src/System.IO.IsolatedStorage/pkg/System.IO.IsolatedStorage.pkgproj
+++ b/src/System.IO.IsolatedStorage/pkg/System.IO.IsolatedStorage.pkgproj
@@ -3,7 +3,7 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.IO.IsolatedStorage.csproj">
- <SupportedFramework>uap10.1;netcoreapp1.1;net463;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>uap10.1;netcoreapp1.1;net461;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.IO.IsolatedStorage.builds" />
</ItemGroup>
diff --git a/src/System.IO.IsolatedStorage/src/Configurations.props b/src/System.IO.IsolatedStorage/src/Configurations.props
index 9c336c0be9..53b62c64fe 100644
--- a/src/System.IO.IsolatedStorage/src/Configurations.props
+++ b/src/System.IO.IsolatedStorage/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj b/src/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj
index e18e90890d..eeaec53f72 100644
--- a/src/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj
+++ b/src/System.IO.IsolatedStorage/src/System.IO.IsolatedStorage.csproj
@@ -5,8 +5,8 @@
<AssemblyName>System.IO.IsolatedStorage</AssemblyName>
<ProjectGuid>{FAF5D1E4-BA43-4663-8429-C069066D75CB}</ProjectGuid>
<EnableWinRT Condition="'$(TargetGroup)' == 'uap101'">true</EnableWinRT>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net463'">true</IsPartialFacadeAssembly>
- <ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net463'">None</ResourcesSourceOutputDirectory>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net461'">true</IsPartialFacadeAssembly>
+ <ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net461'">None</ResourcesSourceOutputDirectory>
<PackageTargetFramework Condition="'$(TargetGroup)'=='netstandard'">netstandard1.7;uap10.1</PackageTargetFramework>
</PropertyGroup>
<!-- Default configurations to help VS understand the options -->
@@ -14,8 +14,8 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup Condition="'$(EnableWinRT)' == 'true'">
<ProjectReference Include="$(SourceDir)mscorlib.WinRT-Facade\mscorlib.WinRT-Facade.csproj" />
<TargetingPackReference Include="Windows" />
@@ -28,6 +28,9 @@
<Compile Include="System\IO\IsolatedStorage\IsolatedStorageScope.cs" />
<Compile Include="System\IO\IsolatedStorage\Helper.cs" />
<Compile Include="System\IO\IsolatedStorage\INormalizeForIsolatedStorage.cs" />
+ <Compile Include="$(CommonPath)\System\Security\IdentityHelper.cs">
+ <Link>Common\System\Security\IdentityHelper.cs</Link>
+ </Compile>
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\IO\IsolatedStorage\IsolatedStorageException.Serialization.cs" />
@@ -38,7 +41,7 @@
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard' and '$(EnableWinRT)' == 'true'">
<Compile Include="System\IO\IsolatedStorage\Helper.WinRT.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
</ItemGroup>
<ItemGroup>
diff --git a/src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32.Unix.cs b/src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32.Unix.cs
index e3ede79618..221db2ee23 100644
--- a/src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32.Unix.cs
+++ b/src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.Win32.Unix.cs
@@ -4,6 +4,7 @@
using System.Reflection;
using System.Runtime.InteropServices;
+using System.Security;
using System.Security.AccessControl;
using System.Security.Principal;
@@ -24,7 +25,6 @@ namespace System.IO.IsolatedStorage
{
// SpecialFolder.CommonApplicationData -> C:\ProgramData
dataDirectory = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
- dataDirectory = @"/usr/local/share";
}
else if (IsRoaming(scope))
{
@@ -126,7 +126,7 @@ namespace System.IO.IsolatedStorage
AssemblyName assemblyName = assembly.GetName();
Uri codeBase = new Uri(assembly.CodeBase);
- hash = GetNormalizedStrongNameHash(assemblyName);
+ hash = IdentityHelper.GetNormalizedStrongNameHash(assemblyName);
if (hash != null)
{
hash = "StrongName" + separator + hash;
@@ -134,7 +134,7 @@ namespace System.IO.IsolatedStorage
}
else
{
- hash = GetNormalizedUriHash(codeBase);
+ hash = IdentityHelper.GetNormalizedUriHash(codeBase);
hash = "Url" + separator + hash;
identity = codeBase;
}
diff --git a/src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.cs b/src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.cs
index e13b634c3c..770168a942 100644
--- a/src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.cs
+++ b/src/System.IO.IsolatedStorage/src/System/IO/IsolatedStorage/Helper.cs
@@ -2,10 +2,7 @@
// 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.Reflection;
-using System.Security.Cryptography;
-using System.Text;
+using System.Security;
using System.Threading;
namespace System.IO.IsolatedStorage
@@ -18,14 +15,6 @@ namespace System.IO.IsolatedStorage
private static string s_roamingUserRootDirectory;
private static string s_userRootDirectory;
- private static readonly char[] s_base32Char =
- {
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
- 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
- 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
- 'y', 'z', '0', '1', '2', '3', '4', '5'
- };
-
/// <summary>
/// The full root directory is the relevant special folder from Environment.GetFolderPath() plus "IsolatedStorage"
/// and a set of random directory names if not roaming.
@@ -126,119 +115,7 @@ namespace System.IO.IsolatedStorage
private static Mutex CreateMutexNotOwned(string pathName)
{
- return new Mutex(initiallyOwned: false, name: @"Global\" + GetStrongHashSuitableForObjectName(pathName));
- }
-
- internal static string GetNormalizedUriHash(Uri uri)
- {
- // On desktop System.Security.Url is used as evidence, it has an internal Normalize() method.
- // Uri.ToString() appears to be functionally equivalent.
- return GetStrongHashSuitableForObjectName(uri.ToString());
- }
-
- internal static string GetNormalizedStrongNameHash(AssemblyName name)
- {
- byte[] publicKey = name.GetPublicKey();
-
- // If we don't have a key, we're not strong named
- if (publicKey == null || publicKey.Length == 0)
- return null;
-
- // Emulate what we get from StrongName.Normalize().
- using (MemoryStream ms = new MemoryStream())
- {
- using (BinaryWriter bw = new BinaryWriter(ms))
- {
- bw.Write(publicKey);
- bw.Write(name.Version.Major);
- bw.Write(name.Name);
-
- ms.Position = 0;
- return GetStrongHashSuitableForObjectName(ms);
- }
- }
- }
-
- internal static string GetStrongHashSuitableForObjectName(string name)
- {
- using (MemoryStream ms = new MemoryStream())
- {
- using (BinaryWriter b = new BinaryWriter(ms))
- {
- b.Write(name.ToUpperInvariant());
-
- ms.Position = 0;
- return GetStrongHashSuitableForObjectName(ms);
- }
- }
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "Compat: Used to generate an 8.3 filename.")]
- internal static string GetStrongHashSuitableForObjectName(Stream stream)
- {
- using (SHA1 sha1 = SHA1.Create())
- {
- return ToBase32StringSuitableForDirName(sha1.ComputeHash(stream));
- }
- }
-
- // This is from the NetFX Path class. The implementation in CoreFx was optimized for internal Path usage so
- // we can't share the implementation.
- internal static string ToBase32StringSuitableForDirName(byte[] buff)
- {
- // This routine is optimised to be used with buffs of length 20
- Debug.Assert(((buff.Length % 5) == 0), "Unexpected hash length");
-
- StringBuilder sb = new StringBuilder();
- byte b0, b1, b2, b3, b4;
- int l, i;
-
- l = buff.Length;
- i = 0;
-
- // Create l chars using the last 5 bits of each byte.
- // Consume 3 MSB bits 5 bytes at a time.
-
- do
- {
- b0 = (i < l) ? buff[i++] : (byte)0;
- b1 = (i < l) ? buff[i++] : (byte)0;
- b2 = (i < l) ? buff[i++] : (byte)0;
- b3 = (i < l) ? buff[i++] : (byte)0;
- b4 = (i < l) ? buff[i++] : (byte)0;
-
- // Consume the 5 Least significant bits of each byte
- sb.Append(s_base32Char[b0 & 0x1F]);
- sb.Append(s_base32Char[b1 & 0x1F]);
- sb.Append(s_base32Char[b2 & 0x1F]);
- sb.Append(s_base32Char[b3 & 0x1F]);
- sb.Append(s_base32Char[b4 & 0x1F]);
-
- // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4
- sb.Append(s_base32Char[(
- ((b0 & 0xE0) >> 5) |
- ((b3 & 0x60) >> 2))]);
-
- sb.Append(s_base32Char[(
- ((b1 & 0xE0) >> 5) |
- ((b4 & 0x60) >> 2))]);
-
- // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4
-
- b2 >>= 5;
-
- Debug.Assert(((b2 & 0xF8) == 0), "Unexpected set bits");
-
- if ((b3 & 0x80) != 0)
- b2 |= 0x08;
- if ((b4 & 0x80) != 0)
- b2 |= 0x10;
-
- sb.Append(s_base32Char[b2]);
-
- } while (i < l);
-
- return sb.ToString();
+ return new Mutex(initiallyOwned: false, name: @"Global\" + IdentityHelper.GetStrongHashSuitableForObjectName(pathName));
}
internal static bool IsMachine(IsolatedStorageScope scope) => ((scope & IsolatedStorageScope.Machine) != 0);
diff --git a/src/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj b/src/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj
index a4fe166487..7ccfbe0950 100644
--- a/src/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj
+++ b/src/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj
@@ -28,6 +28,9 @@
<Compile Include="..\src\System\IO\IsolatedStorage\Helper.Win32.Unix.cs">
<Link>Internals\Helper.Win32.Unix.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\System\Security\IdentityHelper.cs">
+ <Link>Common\System\Security\IdentityHelper.cs</Link>
+ </Compile>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="StoreTestsFixture.cs" />
<Compile Include="System\IO\IsolatedStorage\ContainsUnknownFilesTests.cs" />
diff --git a/src/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/HelperTests.cs b/src/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/HelperTests.cs
index 0ffc23fef4..dc75cfddfd 100644
--- a/src/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/HelperTests.cs
+++ b/src/System.IO.IsolatedStorage/tests/System/IO/IsolatedStorage/HelperTests.cs
@@ -9,63 +9,6 @@ namespace System.IO.IsolatedStorage.Tests
{
public class HelperTests
{
- [Theory
- InlineData(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00 }, @"aaaaaaaa")
- InlineData(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, @"55555555")
- InlineData(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @"aaaaaaaaaaaaaaaa")
- InlineData(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }, @"abcdeaaafghijaaa")
- InlineData(
- new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
- ]
- public void ToBase32StringSuitableForDirName(byte[] buff, string expected)
- {
- // Validating that the legacy Path.ToBase32StringSuitableForDirName results match
- // our copy of the code. Results should NOT change as IsolatedStorage depends
- // on this for creating a stable hash based directory name.
- Assert.Equal(expected, Helper.ToBase32StringSuitableForDirName(buff));
- }
-
- [Fact]
- public void GetNormalizedStrongNameHash()
- {
- // Validating that we match the exact hash the desktop IsolatedStorage implementation would create.
- Assert.Equal(@"10nbq10da2m1qfsisndjihnhqmilalwl", Helper.GetNormalizedStrongNameHash(GetAssemblyNameWithFullKey()));
- }
-
- [Fact]
- public void GetNormalizedUrlHash()
- {
- // Validating that we match the exact hash the desktop IsolatedStorage implementation would create.
- Uri uri = new Uri(@"file://C:/Users/jerem/Documents/Visual Studio 2015/Projects/LongPath/LongPath/bin/Debug/TestAssembly.EXE");
- Assert.Equal(@"qgeirsoc3cznuklvq5xlalurh1m0unxl", Helper.GetNormalizedUriHash(uri));
- }
-
- private static AssemblyName GetAssemblyNameWithFullKey()
- {
- byte[] publicKey = new byte[]
- {
- 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
- 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x37, 0x52, 0x6e, 0xdf, 0xc0, 0x62, 0x17, 0x9f,
- 0x9d, 0x24, 0xe5, 0x0d, 0x3f, 0x9b, 0xb1, 0x34, 0xe1, 0x7e, 0x14, 0x9e, 0xb5, 0x19, 0xcc, 0x2f, 0xd1, 0x9c, 0x39, 0x08,
- 0x46, 0xf4, 0x18, 0xba, 0x6b, 0x2b, 0xe1, 0xc2, 0xb7, 0xe9, 0x06, 0x59, 0x57, 0xed, 0xe1, 0x83, 0x9c, 0xc8, 0x66, 0x4f,
- 0xba, 0x3a, 0x05, 0x6b, 0x73, 0x98, 0x56, 0x0a, 0x34, 0x8e, 0x69, 0xf1, 0x4a, 0x69, 0x4f, 0x4f, 0xea, 0xc7, 0x3e, 0x27,
- 0xf6, 0x6f, 0xd5, 0x4c, 0xcb, 0xeb, 0xe3, 0xa7, 0x5f, 0x3c, 0x11, 0xd3, 0x82, 0xc7, 0xee, 0x1a, 0x5c, 0xf6, 0x37, 0x8c,
- 0xc9, 0x81, 0xbb, 0xb8, 0xa4, 0xab, 0xe6, 0x9d, 0x10, 0x96, 0x3a, 0xf8, 0xa0, 0xaa, 0x42, 0xb4, 0x45, 0xb1, 0x6c, 0xe3,
- 0x9b, 0xc5, 0xb0, 0x84, 0x29, 0x32, 0x20, 0xc8, 0xb9, 0x5b, 0x1d, 0x40, 0xec, 0xbe, 0x23, 0x2e, 0x6b, 0xdd, 0x5d, 0xc4
- };
-
- AssemblyName name = new AssemblyName();
- name.Name = "TestAssembly";
- name.Version = new Version(1, 0);
- name.SetPublicKey(publicKey);
-
- return name;
-
- // C:\Users\jerem\AppData\Local\IsolatedStorage\10v31ho4.bo2\eeolfu22.f2w\Url.qgeirsoc3cznuklvq5xlalurh1m0unxl\AssemFiles\
- // C:\Users\jerem\AppData\Local\IsolatedStorage\10v31ho4.bo2\eeolfu22.f2w\StrongName.10nbq10da2m1qfsisndjihnhqmilalwl\AssemFiles\
- }
-
[Fact]
public void GetDefaultIdentityAndHash()
{
diff --git a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
index 53141fbbf5..38d4d411ac 100644
--- a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
+++ b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
@@ -245,7 +245,7 @@ namespace System.IO.MemoryMappedFiles
/// type. If pinningHandle is not null, caller must free it AFTER the call to CreateFile has returned.
/// </summary>
[SecurityCritical]
- private unsafe static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability)
+ private static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability)
{
Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES);
if ((inheritability & HandleInheritability.Inheritable) != 0)
diff --git a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Unix.cs b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Unix.cs
index 5d2ca8c8dc..12207ff2c0 100644
--- a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Unix.cs
+++ b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Unix.cs
@@ -12,7 +12,7 @@ namespace System.IO.MemoryMappedFiles
internal partial class MemoryMappedView
{
[SecurityCritical]
- public unsafe static MemoryMappedView CreateView(
+ public static unsafe MemoryMappedView CreateView(
SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access,
long requestedOffset, long requestedSize)
{
diff --git a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs
index 0c27a8ac4d..711b40a0eb 100644
--- a/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs
+++ b/src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs
@@ -18,7 +18,7 @@ namespace System.IO.MemoryMappedFiles
private const int MaxFlushRetriesPerWait = 20;
[SecurityCritical]
- public unsafe static MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle,
+ public static unsafe MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle,
MemoryMappedFileAccess access, long offset, long size)
{
// MapViewOfFile can only create views that start at a multiple of the system memory allocation
diff --git a/src/System.IO.Packaging/src/System/IO/Packaging/XmlCompatibilityReader.cs b/src/System.IO.Packaging/src/System/IO/Packaging/XmlCompatibilityReader.cs
index 95e63395de..941b1acbad 100644
--- a/src/System.IO.Packaging/src/System/IO/Packaging/XmlCompatibilityReader.cs
+++ b/src/System.IO.Packaging/src/System/IO/Packaging/XmlCompatibilityReader.cs
@@ -1978,7 +1978,7 @@ namespace System.IO.Packaging
private const string XmlnsDeclaration = "xmlns";
private const string MarkupCompatibilityURI = "http://schemas.openxmlformats.org/markup-compatibility/2006";
- static private string[] s_predefinedNamespaces = new string[4] {
+ private static string[] s_predefinedNamespaces = new string[4] {
"http://www.w3.org/2000/xmlns/",
"http://www.w3.org/XML/1998/namespace",
"http://www.w3.org/2001/XMLSchema-instance",
diff --git a/src/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs b/src/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs
index b4f7409ba0..3b656cf394 100644
--- a/src/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs
+++ b/src/System.IO.Packaging/src/System/IO/Packaging/ZipPackage.cs
@@ -449,7 +449,7 @@ namespace System.IO.Packaging
}
// convert from Zip CompressionMethodEnum and DeflateOptionEnum to Metro CompressionOption
- static private CompressionOption GetCompressionOptionFromZipFileInfo(ZipArchiveEntry zipFileInfo)
+ private static CompressionOption GetCompressionOptionFromZipFileInfo(ZipArchiveEntry zipFileInfo)
{
// Note: we can't determine compression method / level from the ZipArchiveEntry.
CompressionOption result = CompressionOption.Normal;
diff --git a/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs b/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs
index 656020886c..6618063b7f 100644
--- a/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs
+++ b/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs
@@ -22,10 +22,10 @@ namespace System.IO.Pipes
internal const bool CheckOperationsRequiresSetHandle = false;
/// <summary>Characters that can't be used in a pipe's name.</summary>
- private readonly static char[] s_invalidFileNameChars = Path.GetInvalidFileNameChars();
+ private static readonly char[] s_invalidFileNameChars = Path.GetInvalidFileNameChars();
/// <summary>Prefix to prepend to all pipe names.</summary>
- private readonly static string s_pipePrefix = Path.Combine(Path.GetTempPath(), "CoreFxPipe_");
+ private static readonly string s_pipePrefix = Path.Combine(Path.GetTempPath(), "CoreFxPipe_");
internal static string GetPipePath(string serverName, string pipeName)
{
diff --git a/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs b/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs
index 6e39ec85de..840ba11513 100644
--- a/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs
+++ b/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs
@@ -429,7 +429,7 @@ namespace System.IO.Pipes
}
[SecurityCritical]
- internal unsafe static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability)
+ internal static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability)
{
Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES);
if ((inheritability & HandleInheritability.Inheritable) != 0)
diff --git a/src/System.IO.Pipes/tests/Interop.cs b/src/System.IO.Pipes/tests/Interop.cs
index d159781b3f..abcb3933e8 100644
--- a/src/System.IO.Pipes/tests/Interop.cs
+++ b/src/System.IO.Pipes/tests/Interop.cs
@@ -16,7 +16,7 @@ namespace System.IO.Pipes.Tests
{
#region Windows
- [DllImport("api-ms-win-core-io-l1-1-0.dll", SetLastError = true)]
+ [DllImport("kernel32.dll", SetLastError = true)]
private static extern unsafe bool CancelIoEx(SafeHandle handle, NativeOverlapped* lpOverlapped);
internal static unsafe bool CancelIoEx(SafeHandle handle)
@@ -24,7 +24,7 @@ namespace System.IO.Pipes.Tests
return CancelIoEx(handle, null);
}
- [DllImport("api-ms-win-core-namedpipe-l1-2-1.dll", CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "GetNamedPipeHandleStateW")]
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "GetNamedPipeHandleStateW")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetNamedPipeHandleState(
SafePipeHandle hNamedPipe,
diff --git a/src/System.IO/pkg/System.IO.pkgproj b/src/System.IO/pkg/System.IO.pkgproj
index 4f26174b1b..316d930d07 100644
--- a/src/System.IO/pkg/System.IO.pkgproj
+++ b/src/System.IO/pkg/System.IO.pkgproj
@@ -3,10 +3,10 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.IO.builds">
- <SupportedFramework>net463;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.IO.csproj">
- <TargetGroup>net463</TargetGroup>
+ <TargetGroup>net461</TargetGroup>
</ProjectReference>
<ProjectReference Include="any\System.IO.pkgproj" />
<ProjectReference Include="aot\System.IO.pkgproj" />
@@ -23,6 +23,10 @@
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
+ <!-- the previous version of this package supported a different API version for
+ net462, but since netstandard2.0 supports the latest and net461 supports
+ netstandard2.0 we need to suppress the old net462 assembly. -->
+ <HarvestSuppressPaths Include="ref/net462;lib/net462" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.IO/src/Configurations.props b/src/System.IO/src/Configurations.props
index f013d10b8c..d561a2dc29 100644
--- a/src/System.IO/src/Configurations.props
+++ b/src/System.IO/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
uap101aot-Windows_NT;
netstandard;
</BuildConfigurations>
diff --git a/src/System.IO/src/System.IO.csproj b/src/System.IO/src/System.IO.csproj
index afe0b6a690..f7ce1ecec7 100644
--- a/src/System.IO/src/System.IO.csproj
+++ b/src/System.IO/src/System.IO.csproj
@@ -14,21 +14,19 @@
<!-- Default configurations to help VS understand the options -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net462_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net462_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101aot_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101aot_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(TargetGroup)' == 'net462' or '$(TargetGroup)' == 'net463'">
+ <PropertyGroup Condition="'$(TargetGroup)' == 'net462' or '$(TargetGroup)' == 'net461'">
<ResourcesSourceOutputDirectory>None</ResourcesSourceOutputDirectory>
</PropertyGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<ContractProject Include="..\ref\System.IO.csproj">
<TargetGroup>netstandard1.7</TargetGroup>
</ContractProject>
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net462' or '$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System" />
</ItemGroup>
diff --git a/src/System.IO/tests/BufferedStream/BufferedStream.FlushTests.cs b/src/System.IO/tests/BufferedStream/BufferedStream.FlushTests.cs
new file mode 100644
index 0000000000..c1f9b60fb8
--- /dev/null
+++ b/src/System.IO/tests/BufferedStream/BufferedStream.FlushTests.cs
@@ -0,0 +1,77 @@
+// 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.Threading.Tasks;
+using Xunit;
+
+namespace System.IO.Tests
+{
+ public class BufferedStreamFlushTests
+ {
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public async Task ShouldNotFlushUnderlyingStreamIfReadOnly(bool underlyingCanSeek)
+ {
+ var underlying = new DelegateStream(
+ canReadFunc: () => true,
+ canWriteFunc: () => false,
+ canSeekFunc: () => underlyingCanSeek,
+ readFunc: (_, __, ___) => 123,
+ writeFunc: (_, __, ___) =>
+ {
+ throw new NotSupportedException();
+ },
+ seekFunc: (_, __) => 123L
+ );
+
+ var wrapper = new CallTrackingStream(underlying);
+
+ var buffered = new BufferedStream(wrapper);
+ buffered.ReadByte();
+
+ buffered.Flush();
+ Assert.Equal(0, wrapper.TimesCalled(nameof(wrapper.Flush)));
+
+ await buffered.FlushAsync();
+ Assert.Equal(0, wrapper.TimesCalled(nameof(wrapper.FlushAsync)));
+ }
+
+ [Theory]
+ [InlineData(true, true)]
+ [InlineData(true, false)]
+ [InlineData(false, true)]
+ [InlineData(false, false)]
+ public async Task ShouldAlwaysFlushUnderlyingStreamIfWritable(bool underlyingCanRead, bool underlyingCanSeek)
+ {
+ var underlying = new DelegateStream(
+ canReadFunc: () => underlyingCanRead,
+ canWriteFunc: () => true,
+ canSeekFunc: () => underlyingCanSeek,
+ readFunc: (_, __, ___) => 123,
+ writeFunc: (_, __, ___) => { },
+ seekFunc: (_, __) => 123L
+ );
+
+ var wrapper = new CallTrackingStream(underlying);
+
+ var buffered = new BufferedStream(wrapper);
+
+ buffered.Flush();
+ Assert.Equal(1, wrapper.TimesCalled(nameof(wrapper.Flush)));
+
+ await buffered.FlushAsync();
+ Assert.Equal(1, wrapper.TimesCalled(nameof(wrapper.FlushAsync)));
+
+ buffered.WriteByte(0);
+
+ buffered.Flush();
+ Assert.Equal(2, wrapper.TimesCalled(nameof(wrapper.Flush)));
+
+ await buffered.FlushAsync();
+ Assert.Equal(2, wrapper.TimesCalled(nameof(wrapper.FlushAsync)));
+ }
+ }
+}
diff --git a/src/System.IO/tests/System.IO.Tests.csproj b/src/System.IO/tests/System.IO.Tests.csproj
index dce6629af3..bc66c5924f 100644
--- a/src/System.IO/tests/System.IO.Tests.csproj
+++ b/src/System.IO/tests/System.IO.Tests.csproj
@@ -25,6 +25,7 @@
<Compile Include="BinaryWriter\BinaryWriter.WriteByteCharTests.cs" />
<Compile Include="BinaryWriter\BinaryWriter.WriteTests.cs" />
<Compile Include="BinaryWriter\BinaryWriterTests.cs" />
+ <Compile Include="BufferedStream\BufferedStream.FlushTests.cs" />
<Compile Include="BufferedStream\BufferedStream.InvalidParameters.cs" />
<Compile Include="BufferedStream\BufferedStreamTests.cs" />
<Compile Include="BufferedStream\BufferedStreamTests.netcoreapp1.1.cs" Condition="'$(TargetGroup)' == 'netcoreapp1.1'" />
@@ -58,4 +59,4 @@
</Compile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/System.Linq.Expressions/pkg/System.Linq.Expressions.pkgproj b/src/System.Linq.Expressions/pkg/System.Linq.Expressions.pkgproj
index 71a1fdc2f8..5db552454f 100644
--- a/src/System.Linq.Expressions/pkg/System.Linq.Expressions.pkgproj
+++ b/src/System.Linq.Expressions/pkg/System.Linq.Expressions.pkgproj
@@ -6,7 +6,7 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Linq.Expressions.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Linq.Expressions.builds" />
<InboxOnTargetFramework Include="MonoAndroid10" />
@@ -22,6 +22,10 @@
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
+ <!-- the previous version of this package supported a different API version for
+ net463, but since netstandard2.0 supports the latest and net461 supports
+ netstandard2.0 we need to suppress the old net463 assembly. -->
+ <HarvestSuppressPaths Include="ref/net463;lib/net463" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Linq.Expressions/src/ApiCompatBaseline.net463.txt b/src/System.Linq.Expressions/src/ApiCompatBaseline.net461.txt
index efededb89f..efededb89f 100644
--- a/src/System.Linq.Expressions/src/ApiCompatBaseline.net463.txt
+++ b/src/System.Linq.Expressions/src/ApiCompatBaseline.net461.txt
diff --git a/src/System.Linq.Expressions/src/Configurations.props b/src/System.Linq.Expressions/src/Configurations.props
index 9c336c0be9..53b62c64fe 100644
--- a/src/System.Linq.Expressions/src/Configurations.props
+++ b/src/System.Linq.Expressions/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Linq.Expressions/src/Resources/Strings.resx b/src/System.Linq.Expressions/src/Resources/Strings.resx
index 309bff93db..031da8a631 100644
--- a/src/System.Linq.Expressions/src/Resources/Strings.resx
+++ b/src/System.Linq.Expressions/src/Resources/Strings.resx
@@ -156,6 +156,9 @@
<data name="SetterMustBeVoid" xml:space="preserve">
<value>Setter should have void type.</value>
</data>
+ <data name="PropertyTypeMustMatchGetter" xml:space="preserve">
+ <value>Property type must match the value type of getter</value>
+ </data>
<data name="PropertyTypeMustMatchSetter" xml:space="preserve">
<value>Property type must match the value type of setter</value>
</data>
@@ -277,7 +280,7 @@
<value>Argument for array index must be of type Int32</value>
</data>
<data name="ArgumentMustBeSingleDimensionalArrayType" xml:space="preserve">
- <value>Argument must be single dimensional array type</value>
+ <value>Argument must be single-dimensional, zero-based array type</value>
</data>
<data name="ArgumentTypesMustMatch" xml:space="preserve">
<value>Argument types do not match</value>
diff --git a/src/System.Linq.Expressions/src/System.Linq.Expressions.csproj b/src/System.Linq.Expressions/src/System.Linq.Expressions.csproj
index 08002ff9c4..a1716d2331 100644
--- a/src/System.Linq.Expressions/src/System.Linq.Expressions.csproj
+++ b/src/System.Linq.Expressions/src/System.Linq.Expressions.csproj
@@ -14,8 +14,8 @@
<IsInterpreting Condition="'$(PackageTargetFramework)' == 'netcore50'">true</IsInterpreting>
<DefineConstants Condition=" '$(IsInterpreting)' != 'true' ">$(DefineConstants);FEATURE_COMPILE</DefineConstants>
<DefineConstants Condition=" '$(FeatureInterpret)' == 'true' ">$(DefineConstants);FEATURE_INTERPRET</DefineConstants>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net463'">true</IsPartialFacadeAssembly>
- <ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net463'">None</ResourcesSourceOutputDirectory>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net461'">true</IsPartialFacadeAssembly>
+ <ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net461'">None</ResourcesSourceOutputDirectory>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
@@ -26,8 +26,8 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcore50aot_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcore50_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcore50_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<!-- netcore50 project.json fork is shared for both netcore50 and netcore50aot. This redirects netcore50aot. -->
<PropertyGroup Condition="'$(TargetGroup)' == 'netcore50aot'">
<ProjectJson>netcore50/project.json</ProjectJson>
@@ -38,7 +38,7 @@
<EmbeddedResource Include="Resources\$(AssemblyName).rd.xml" />
<TargetingPackReference Include="System.Private.CoreLib.DynamicDelegate" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' != 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' != 'net461'">
<Compile Include="$(CommonPath)\System\Collections\Generic\ArrayBuilder.cs">
<Link>Common\System\Collections\Generic\ArrayBuilder.cs</Link>
</Compile>
@@ -54,30 +54,15 @@
<Compile Include="$(CommonPath)\System\Dynamic\Utils\CacheDict.cs">
<Link>Common\System\Dynamic\Utils\CacheDict.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Dynamic\Utils\CollectionExtensions.cs">
- <Link>Common\System\Dynamic\Utils\CollectionExtensions.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\Dynamic\Utils\CollectionExtensions.Map.cs">
- <Link>Common\System\Dynamic\Utils\CollectionExtensions.Map.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\System\Dynamic\Utils\ContractUtils.cs">
<Link>Common\System\Dynamic\Utils\ContractUtils.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Dynamic\Utils\EmptyReadOnlyCollection.cs">
- <Link>Common\System\Dynamic\Utils\EmptyReadOnlyCollection.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\System\Dynamic\Utils\Error.cs">
<Link>Common\System\Dynamic\Utils\Error.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Dynamic\Utils\ExpressionUtils.cs">
<Link>Common\System\Dynamic\Utils\ExpressionUtils.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Dynamic\Utils\ExpressionVisitorUtils.cs">
- <Link>Common\System\Dynamic\Utils\ExpressionVisitorUtils.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\Dynamic\Utils\ListArgumentProvider.cs">
- <Link>Common\System\Dynamic\Utils\ListArgumentProvider.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\System\Dynamic\Utils\Strings.cs">
<Link>Common\System\Dynamic\Utils\Strings.cs</Link>
</Compile>
@@ -96,11 +81,9 @@
<Compile Include="$(CommonPath)\System\NotImplemented.cs">
<Link>Common\System\NotImplemented.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Runtime\CompilerServices\TrueReadOnlyCollection.cs">
- <Link>Common\System\Runtime\CompilerServices\TrueReadOnlyCollection.cs</Link>
- </Compile>
<Compile Include="System\Dynamic\Utils\ExpressionUtils.cs" />
<Compile Include="System\Dynamic\Utils\ExpressionVisitorUtils.cs" />
+ <Compile Include="System\Dynamic\Utils\ListArgumentProvider.cs" />
<Compile Include="System\Dynamic\Utils\ListParameterProvider.cs" />
<Compile Include="System\Dynamic\Utils\TypeExtensions.cs" />
<Compile Include="System\Dynamic\Utils\TypeUtils.cs" />
@@ -191,8 +174,10 @@
<Compile Include="System\Runtime\CompilerServices\CallSiteHelpers.cs" />
<Compile Include="System\Runtime\CompilerServices\DynamicAttribute.cs" />
<Compile Include="System\Runtime\CompilerServices\DebugInfoGenerator.cs" />
+ <Compile Include="System\Runtime\CompilerServices\TrueReadOnlyCollection.cs" />
<Compile Include="System\Dynamic\Utils\CachedReflectionInfo.cs" />
<Compile Include="System\Dynamic\Utils\CollectionExtensions.cs" />
+ <Compile Include="System\Dynamic\Utils\EmptyReadOnlyCollection.cs" />
<Compile Include="System\Dynamic\UpdateDelegates.Generated.cs" />
<Compile Include="System\Dynamic\DynamicMetaObjectBinder.cs" />
<Compile Include="System\Dynamic\DynamicMetaObject.cs" />
@@ -216,21 +201,10 @@
<Compile Include="System\Dynamic\UnaryOperationBinder.cs" />
<Compile Include="System\Dynamic\IInvokeOnGetBinder.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)'=='netstandard1.6'">
- <Compile Include="$(CommonPath)\System\SerializableAttribute.cs">
- <Link>Common\System\SerializableAttribute.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\NonSerializedAttribute.cs">
- <Link>Common\System\NonSerializedAttribute.cs</Link>
- </Compile>
- </ItemGroup>
- <ItemGroup Condition=" '$(IsInterpreting)' != 'true' And '$(TargetGroup)' != 'net463'">
+ <ItemGroup Condition=" '$(IsInterpreting)' != 'true' And '$(TargetGroup)' != 'net461'">
<Compile Include="$(CommonPath)\System\Collections\Generic\ReferenceEqualityComparer.cs">
<Link>Common\System\Collections\Generic\ReferenceEqualityComparer.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Dynamic\Utils\CollectionExtensions.AddFirst.cs">
- <Link>Common\System\Dynamic\Utils\CollectionExtensions.AddFirst.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\System\Dynamic\Utils\ContractUtils.RequiresArrayRange.cs">
<Link>Common\System\Dynamic\Utils\ContractUtils.RequiresArrayRange.cs</Link>
</Compile>
@@ -267,7 +241,7 @@
<Compile Include="System\Runtime\CompilerServices\RuntimeOps.ExpressionQuoter.cs" />
<Compile Include="System\Runtime\CompilerServices\RuntimeOps.RuntimeVariableList.cs" />
</ItemGroup>
- <ItemGroup Condition=" ('$(IsInterpreting)' == 'true' Or '$(FeatureInterpret)' == 'true') And '$(TargetGroup)' != 'net463' ">
+ <ItemGroup Condition=" ('$(IsInterpreting)' == 'true' Or '$(FeatureInterpret)' == 'true') And '$(TargetGroup)' != 'net461' ">
<Compile Include="$(CommonPath)\System\Dynamic\Utils\DelegateHelpers.cs">
<Link>Common\System\Dynamic\Utils\DelegateHelpers.cs</Link>
</Compile>
@@ -285,6 +259,7 @@
<Compile Include="System\Linq\Expressions\Interpreter\ExclusiveOrInstruction.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\FieldOperations.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\GreaterThanInstruction.cs" />
+ <Compile Include="System\Linq\Expressions\Interpreter\GreaterThanOrEqualInstruction.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\IncrementInstruction.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\Instruction.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\InstructionList.cs" />
@@ -293,12 +268,14 @@
<Compile Include="System\Linq\Expressions\Interpreter\LabelInfo.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\LeftShiftInstruction.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\LessThanInstruction.cs" />
+ <Compile Include="System\Linq\Expressions\Interpreter\LessThanOrEqualInstruction.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\LightCompiler.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\LightDelegateCreator.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\LightLambda.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\LightLambda.Generated.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\LocalAccess.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\LocalVariables.cs" />
+ <Compile Include="System\Linq\Expressions\Interpreter\ModuloInstruction.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\MulInstruction.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\NegateInstruction.cs" />
<Compile Include="System\Linq\Expressions\Interpreter\NewInstruction.cs" />
@@ -316,7 +293,7 @@
<Compile Include="System\Linq\Expressions\Interpreter\Utilities.cs" />
<Compile Include="System\Linq\Expressions\Compiler\DelegateHelpers.Generated.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System.Core" />
</ItemGroup>
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/BinaryOperationBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/BinaryOperationBinder.cs
index 4da988f28a..e0fb0e4ba0 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/BinaryOperationBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/BinaryOperationBinder.cs
@@ -70,7 +70,9 @@ namespace System.Dynamic
return target.BindBinaryOperation(this, arg0);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/BindingRestrictions.cs b/src/System.Linq.Expressions/src/System/Dynamic/BindingRestrictions.cs
index e4e0b6c6c8..b281210c17 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/BindingRestrictions.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/BindingRestrictions.cs
@@ -19,7 +19,7 @@ namespace System.Dynamic
public abstract class BindingRestrictions
{
/// <summary>
- /// Represents an empty set of binding restrictions. This field is read only.
+ /// Represents an empty set of binding restrictions. This field is read-only.
/// </summary>
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
public static readonly BindingRestrictions Empty = new CustomRestriction(AstUtils.Constant(true));
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/CallInfo.cs b/src/System.Linq.Expressions/src/System/Dynamic/CallInfo.cs
index 094a652558..f8dea21dd7 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/CallInfo.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/CallInfo.cs
@@ -12,38 +12,40 @@ namespace System.Dynamic
/// Describes arguments in the dynamic binding process.
/// </summary>
/// <remarks>
- /// ArgumentCount - all inclusive number of arguments.
- /// ArgumentNames - names for those arguments that are named.
+ /// <see cref="ArgumentCount"/> - all inclusive number of arguments.
+ /// <see cref="ArgumentNames"/> - names for those arguments that are named.
///
/// Argument names match to the argument values in left to right order
/// and last name corresponds to the last argument.
- ///
- /// Example:
- /// Foo(arg1, arg2, arg3, name1 = arg4, name2 = arg5, name3 = arg6)
- ///
- /// will correspond to:
- /// ArgumentCount: 6
- /// ArgumentNames: {"name1", "name2", "name3"}
/// </remarks>
+ /// <example>
+ /// <code>
+ /// Foo(arg1, arg2, arg3, name1 = arg4, name2 = arg5, name3 = arg6)
+ /// </code>
+ /// will correspond to
+ /// <code>
+ /// new CallInfo(6, "name1", "name2", "name3")
+ /// </code>
+ /// </example>
public sealed class CallInfo
{
/// <summary>
- /// Creates a new CallInfo that represents arguments in the dynamic binding process.
+ /// Creates a new <see cref="CallInfo"/> that represents arguments in the dynamic binding process.
/// </summary>
/// <param name="argCount">The number of arguments.</param>
/// <param name="argNames">The argument names.</param>
- /// <returns>The new CallInfo</returns>
+ /// <returns>The new <see cref="CallInfo"/> instance.</returns>
public CallInfo(int argCount, params string[] argNames)
: this(argCount, (IEnumerable<string>)argNames)
{
}
/// <summary>
- /// Creates a new CallInfo that represents arguments in the dynamic binding process.
+ /// Creates a new <see cref="CallInfo"/> that represents arguments in the dynamic binding process.
/// </summary>
/// <param name="argCount">The number of arguments.</param>
/// <param name="argNames">The argument names.</param>
- /// <returns>The new CallInfo</returns>
+ /// <returns>The new <see cref="CallInfo"/> instance.</returns>
public CallInfo(int argCount, IEnumerable<string> argNames)
{
ContractUtils.RequiresNotNull(argNames, nameof(argNames));
@@ -68,18 +70,18 @@ namespace System.Dynamic
public ReadOnlyCollection<string> ArgumentNames { get; }
/// <summary>
- /// Serves as a hash function for the current CallInfo.
+ /// Serves as a hash function for the current <see cref="CallInfo"/>.
/// </summary>
- /// <returns>A hash code for the current CallInfo.</returns>
+ /// <returns>A hash code for the current <see cref="CallInfo"/>.</returns>
public override int GetHashCode()
{
return ArgumentCount ^ ArgumentNames.ListHashCode();
}
/// <summary>
- /// Determines whether the specified CallInfo instance is considered equal to the current.
+ /// Determines whether the specified <see cref="CallInfo"/> instance is considered equal to the current instance.
/// </summary>
- /// <param name="obj">The instance of CallInfo to compare with the current instance.</param>
+ /// <param name="obj">The instance of <see cref="CallInfo"/> to compare with the current instance.</param>
/// <returns>true if the specified instance is equal to the current one otherwise, false.</returns>
public override bool Equals(object obj)
{
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/ConvertBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/ConvertBinder.cs
index 1b1f7f46c2..117743dae1 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/ConvertBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/ConvertBinder.cs
@@ -67,7 +67,9 @@ namespace System.Dynamic
return target.BindConvert(this);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
/// <summary>
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/CreateInstanceBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/CreateInstanceBinder.cs
index f5847a5fe9..19626151be 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/CreateInstanceBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/CreateInstanceBinder.cs
@@ -65,7 +65,9 @@ namespace System.Dynamic
return target.BindCreateInstance(this, args);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
}
}
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/DeleteIndexBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/DeleteIndexBinder.cs
index 1f31af0178..05da09ac0d 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/DeleteIndexBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/DeleteIndexBinder.cs
@@ -45,7 +45,9 @@ namespace System.Dynamic
return target.BindDeleteIndex(this, args);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
/// <summary>
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/DeleteMemberBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/DeleteMemberBinder.cs
index 1627ba200b..dba203a6e8 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/DeleteMemberBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/DeleteMemberBinder.cs
@@ -71,7 +71,9 @@ namespace System.Dynamic
return target.BindDeleteMember(this);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
}
}
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObject.cs b/src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObject.cs
index d29dbcdd59..c7ef29162f 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObject.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObject.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Diagnostics;
using System.Dynamic.Utils;
using System.Linq.Expressions;
using System.Reflection;
@@ -15,7 +16,7 @@ namespace System.Dynamic
public class DynamicMetaObject
{
/// <summary>
- /// Represents an empty array of type <see cref="DynamicMetaObject"/>. This field is read only.
+ /// Represents an empty array of type <see cref="DynamicMetaObject"/>. This field is read-only.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
public static readonly DynamicMetaObject[] EmptyMetaObjects = Array.Empty<DynamicMetaObject>();
@@ -244,10 +245,7 @@ namespace System.Dynamic
/// </summary>
/// <returns>The list of dynamic member names.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
- public virtual IEnumerable<string> GetDynamicMemberNames()
- {
- return Array.Empty<string>();
- }
+ public virtual IEnumerable<string> GetDynamicMemberNames() => Array.Empty<string>();
/// <summary>
/// Returns the list of expressions represented by the <see cref="DynamicMetaObject"/> instances.
@@ -264,7 +262,7 @@ namespace System.Dynamic
DynamicMetaObject mo = objects[i];
ContractUtils.RequiresNotNull(mo, nameof(objects));
Expression expr = mo.Expression;
- ContractUtils.RequiresNotNull(expr, nameof(objects));
+ Debug.Assert(expr != null, "Unexpected null expression; ctor should have caught this.");
res[i] = expr;
}
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs
index d0d18e2c35..13384dd0cc 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/DynamicMetaObjectBinder.cs
@@ -228,7 +228,9 @@ namespace System.Dynamic
);
}
- // used to detect standard MetaObjectBinders.
+ /// <summary>
+ /// Returns <c>true</c> for standard <see cref="DynamicMetaObjectBinder"/>s; otherwise, <c>false</c>.
+ /// </summary>
internal virtual bool IsStandardBinder => false;
}
}
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs b/src/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs
index 1c30bff51c..741736bcc3 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs
@@ -2,6 +2,7 @@
// 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.Collections.ObjectModel;
using System.Diagnostics;
using System.Dynamic.Utils;
@@ -15,19 +16,23 @@ namespace System.Dynamic
{
/// <summary>
/// Provides a simple class that can be inherited from to create an object with dynamic behavior
- /// at runtime. Subclasses can override the various binder methods (GetMember, SetMember, Call, etc.)
- /// to provide custom behavior that will be invoked at runtime.
+ /// at runtime. Subclasses can override the various binder methods (<see cref="TryGetMember"/>,
+ /// <see cref="TrySetMember"/>, <see cref="TryInvokeMember"/>, etc.) to provide custom behavior
+ /// that will be invoked at runtime.
///
- /// If a method is not overridden then the DynamicObject does not directly support that behavior and
- /// the call site will determine how the binding should be performed.
+ /// If a method is not overridden then the <see cref="DynamicObject"/> does not directly support
+ /// that behavior and the call site will determine how the binding should be performed.
/// </summary>
[Serializable]
public class DynamicObject : IDynamicMetaObjectProvider
{
/// <summary>
- /// Enables derived types to create a new instance of DynamicObject. DynamicObject instances cannot be
- /// directly instantiated because they have no implementation of dynamic behavior.
+ /// Enables derived types to create a new instance of <see cref="DynamicObject"/>.
/// </summary>
+ /// <remarks>
+ /// <see cref="DynamicObject"/> instances cannot be directly instantiated because they have no
+ /// implementation of dynamic behavior.
+ /// </remarks>
protected DynamicObject()
{
}
@@ -57,10 +62,7 @@ namespace System.Dynamic
/// <param name="binder">The binder provided by the call site.</param>
/// <param name="value">The value to set.</param>
/// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
- public virtual bool TrySetMember(SetMemberBinder binder, object value)
- {
- return false;
- }
+ public virtual bool TrySetMember(SetMemberBinder binder, object value) => false;
/// <summary>
/// Provides the implementation of deleting a member. Derived classes can override
@@ -69,10 +71,7 @@ namespace System.Dynamic
/// </summary>
/// <param name="binder">The binder provided by the call site.</param>
/// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
- public virtual bool TryDeleteMember(DeleteMemberBinder binder)
- {
- return false;
- }
+ public virtual bool TryDeleteMember(DeleteMemberBinder binder) => false;
/// <summary>
/// Provides the implementation of calling a member. Derived classes can override
@@ -91,9 +90,9 @@ namespace System.Dynamic
}
/// <summary>
- /// Provides the implementation of converting the DynamicObject to another type. Derived classes
- /// can override this method to customize behavior. When not overridden the call site
- /// requesting the binder determines the behavior.
+ /// Provides the implementation of converting the <see cref="DynamicObject"/> to another type.
+ /// Derived classes can override this method to customize behavior. When not overridden the
+ /// call site requesting the binder determines the behavior.
/// </summary>
/// <param name="binder">The binder provided by the call site.</param>
/// <param name="result">The result of the conversion.</param>
@@ -106,9 +105,9 @@ namespace System.Dynamic
}
/// <summary>
- /// Provides the implementation of creating an instance of the DynamicObject. Derived classes
- /// can override this method to customize behavior. When not overridden the call site requesting
- /// the binder determines the behavior.
+ /// Provides the implementation of creating an instance of the <see cref="DynamicObject"/>.
+ /// Derived classes can override this method to customize behavior. When not overridden the
+ /// call site requesting the binder determines the behavior.
/// </summary>
/// <param name="binder">The binder provided by the call site.</param>
/// <param name="args">The arguments used for creation.</param>
@@ -122,7 +121,7 @@ namespace System.Dynamic
}
/// <summary>
- /// Provides the implementation of invoking the DynamicObject. Derived classes can
+ /// Provides the implementation of invoking the <see cref="DynamicObject"/>. Derived classes can
/// override this method to customize behavior. When not overridden the call site requesting
/// the binder determines the behavior.
/// </summary>
@@ -194,10 +193,7 @@ namespace System.Dynamic
/// <param name="value">The value to set.</param>
/// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
- public virtual bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
- {
- return false;
- }
+ public virtual bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) => false;
/// <summary>
/// Provides the implementation of performing a delete index operation. Derived classes
@@ -207,20 +203,14 @@ namespace System.Dynamic
/// <param name="binder">The binder provided by the call site.</param>
/// <param name="indexes">The indexes to be deleted.</param>
/// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
- public virtual bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes)
- {
- return false;
- }
+ public virtual bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes) => false;
/// <summary>
/// Returns the enumeration of all dynamic member names.
/// </summary>
/// <returns>The list of dynamic member names.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
- public virtual System.Collections.Generic.IEnumerable<string> GetDynamicMemberNames()
- {
- return Array.Empty<string>();
- }
+ public virtual IEnumerable<string> GetDynamicMemberNames() => Array.Empty<string>();
#endregion
@@ -233,16 +223,18 @@ namespace System.Dynamic
{
}
- public override System.Collections.Generic.IEnumerable<string> GetDynamicMemberNames()
- {
- return Value.GetDynamicMemberNames();
- }
+ public override IEnumerable<string> GetDynamicMemberNames() => Value.GetDynamicMemberNames();
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
- if (IsOverridden(nameof(DynamicObject.TryGetMember)))
+ if (IsOverridden(DynamicObject_TryGetMember))
{
- return CallMethodWithResult(nameof(DynamicObject.TryGetMember), binder, s_noArgs, (e) => binder.FallbackGetMember(this, e));
+ return CallMethodWithResult(
+ DynamicObject_TryGetMember,
+ binder,
+ s_noArgs,
+ (MetaDynamic @this, GetMemberBinder b, DynamicMetaObject e) => b.FallbackGetMember(@this, e)
+ );
}
return base.BindGetMember(binder);
@@ -250,9 +242,17 @@ namespace System.Dynamic
public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
{
- if (IsOverridden(nameof(DynamicObject.TrySetMember)))
+ if (IsOverridden(DynamicObject_TrySetMember))
{
- return CallMethodReturnLast(nameof(DynamicObject.TrySetMember), binder, s_noArgs, value.Expression, (e) => binder.FallbackSetMember(this, value, e));
+ DynamicMetaObject localValue = value;
+
+ return CallMethodReturnLast(
+ DynamicObject_TrySetMember,
+ binder,
+ s_noArgs,
+ value.Expression,
+ (MetaDynamic @this, SetMemberBinder b, DynamicMetaObject e) => b.FallbackSetMember(@this, localValue, e)
+ );
}
return base.BindSetMember(binder, value);
@@ -260,9 +260,14 @@ namespace System.Dynamic
public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
{
- if (IsOverridden(nameof(DynamicObject.TryDeleteMember)))
+ if (IsOverridden(DynamicObject_TryDeleteMember))
{
- return CallMethodNoResult(nameof(DynamicObject.TryDeleteMember), binder, s_noArgs, (e) => binder.FallbackDeleteMember(this, e));
+ return CallMethodNoResult(
+ DynamicObject_TryDeleteMember,
+ binder,
+ s_noArgs,
+ (MetaDynamic @this, DeleteMemberBinder b, DynamicMetaObject e) => b.FallbackDeleteMember(@this, e)
+ );
}
return base.BindDeleteMember(binder);
@@ -270,9 +275,14 @@ namespace System.Dynamic
public override DynamicMetaObject BindConvert(ConvertBinder binder)
{
- if (IsOverridden(nameof(DynamicObject.TryConvert)))
+ if (IsOverridden(DynamicObject_TryConvert))
{
- return CallMethodWithResult(nameof(DynamicObject.TryConvert), binder, s_noArgs, (e) => binder.FallbackConvert(this, e));
+ return CallMethodWithResult(
+ DynamicObject_TryConvert,
+ binder,
+ s_noArgs,
+ (MetaDynamic @this, ConvertBinder b, DynamicMetaObject e) => b.FallbackConvert(@this, e)
+ );
}
return base.BindConvert(binder);
@@ -295,30 +305,35 @@ namespace System.Dynamic
// "error", giving the language the option of using this
// tree or doing .NET binding.
//
- Fallback fallback = e => binder.FallbackInvokeMember(this, args, e);
-
DynamicMetaObject call = BuildCallMethodWithResult(
- nameof(DynamicObject.TryInvokeMember),
+ DynamicObject_TryInvokeMember,
binder,
- DynamicMetaObject.GetExpressions(args),
+ GetExpressions(args),
BuildCallMethodWithResult<GetMemberBinder>(
- nameof(DynamicObject.TryGetMember),
+ DynamicObject_TryGetMember,
new GetBinderAdapter(binder),
s_noArgs,
- fallback(null),
- (e) => binder.FallbackInvoke(e, args, null)
+ binder.FallbackInvokeMember(this, args, null),
+ (MetaDynamic @this, GetMemberBinder ignored, DynamicMetaObject e) => binder.FallbackInvoke(e, args, null)
),
null
);
- return fallback(call);
+ return binder.FallbackInvokeMember(this, args, call);
}
public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args)
{
- if (IsOverridden(nameof(DynamicObject.TryCreateInstance)))
+ if (IsOverridden(DynamicObject_TryCreateInstance))
{
- return CallMethodWithResult(nameof(DynamicObject.TryCreateInstance), binder, DynamicMetaObject.GetExpressions(args), (e) => binder.FallbackCreateInstance(this, args, e));
+ DynamicMetaObject[] localArgs = args;
+
+ return CallMethodWithResult(
+ DynamicObject_TryCreateInstance,
+ binder,
+ GetExpressions(args),
+ (MetaDynamic @this, CreateInstanceBinder b, DynamicMetaObject e) => b.FallbackCreateInstance(@this, localArgs, e)
+ );
}
return base.BindCreateInstance(binder, args);
@@ -326,9 +341,16 @@ namespace System.Dynamic
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
{
- if (IsOverridden(nameof(DynamicObject.TryInvoke)))
+ if (IsOverridden(DynamicObject_TryInvoke))
{
- return CallMethodWithResult(nameof(DynamicObject.TryInvoke), binder, DynamicMetaObject.GetExpressions(args), (e) => binder.FallbackInvoke(this, args, e));
+ DynamicMetaObject[] localArgs = args;
+
+ return CallMethodWithResult(
+ DynamicObject_TryInvoke,
+ binder,
+ GetExpressions(args),
+ (MetaDynamic @this, InvokeBinder b, DynamicMetaObject e) => b.FallbackInvoke(@this, localArgs, e)
+ );
}
return base.BindInvoke(binder, args);
@@ -336,9 +358,16 @@ namespace System.Dynamic
public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
{
- if (IsOverridden(nameof(DynamicObject.TryBinaryOperation)))
+ if (IsOverridden(DynamicObject_TryBinaryOperation))
{
- return CallMethodWithResult(nameof(DynamicObject.TryBinaryOperation), binder, DynamicMetaObject.GetExpressions(new DynamicMetaObject[] { arg }), (e) => binder.FallbackBinaryOperation(this, arg, e));
+ DynamicMetaObject localArg = arg;
+
+ return CallMethodWithResult(
+ DynamicObject_TryBinaryOperation,
+ binder,
+ new[] { arg.Expression },
+ (MetaDynamic @this, BinaryOperationBinder b, DynamicMetaObject e) => b.FallbackBinaryOperation(@this, localArg, e)
+ );
}
return base.BindBinaryOperation(binder, arg);
@@ -346,9 +375,14 @@ namespace System.Dynamic
public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder)
{
- if (IsOverridden(nameof(DynamicObject.TryUnaryOperation)))
+ if (IsOverridden(DynamicObject_TryUnaryOperation))
{
- return CallMethodWithResult(nameof(DynamicObject.TryUnaryOperation), binder, s_noArgs, (e) => binder.FallbackUnaryOperation(this, e));
+ return CallMethodWithResult(
+ DynamicObject_TryUnaryOperation,
+ binder,
+ s_noArgs,
+ (MetaDynamic @this, UnaryOperationBinder b, DynamicMetaObject e) => b.FallbackUnaryOperation(@this, e)
+ );
}
return base.BindUnaryOperation(binder);
@@ -356,9 +390,16 @@ namespace System.Dynamic
public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)
{
- if (IsOverridden(nameof(DynamicObject.TryGetIndex)))
+ if (IsOverridden(DynamicObject_TryGetIndex))
{
- return CallMethodWithResult(nameof(DynamicObject.TryGetIndex), binder, DynamicMetaObject.GetExpressions(indexes), (e) => binder.FallbackGetIndex(this, indexes, e));
+ DynamicMetaObject[] localIndexes = indexes;
+
+ return CallMethodWithResult(
+ DynamicObject_TryGetIndex,
+ binder,
+ GetExpressions(indexes),
+ (MetaDynamic @this, GetIndexBinder b, DynamicMetaObject e) => b.FallbackGetIndex(@this, localIndexes, e)
+ );
}
return base.BindGetIndex(binder, indexes);
@@ -366,9 +407,18 @@ namespace System.Dynamic
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
{
- if (IsOverridden(nameof(DynamicObject.TrySetIndex)))
+ if (IsOverridden(DynamicObject_TrySetIndex))
{
- return CallMethodReturnLast(nameof(DynamicObject.TrySetIndex), binder, DynamicMetaObject.GetExpressions(indexes), value.Expression, (e) => binder.FallbackSetIndex(this, indexes, value, e));
+ DynamicMetaObject[] localIndexes = indexes;
+ DynamicMetaObject localValue = value;
+
+ return CallMethodReturnLast(
+ DynamicObject_TrySetIndex,
+ binder,
+ GetExpressions(indexes),
+ value.Expression,
+ (MetaDynamic @this, SetIndexBinder b, DynamicMetaObject e) => b.FallbackSetIndex(@this, localIndexes, localValue, e)
+ );
}
return base.BindSetIndex(binder, indexes, value);
@@ -376,17 +426,24 @@ namespace System.Dynamic
public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes)
{
- if (IsOverridden(nameof(DynamicObject.TryDeleteIndex)))
+ if (IsOverridden(DynamicObject_TryDeleteIndex))
{
- return CallMethodNoResult(nameof(DynamicObject.TryDeleteIndex), binder, DynamicMetaObject.GetExpressions(indexes), (e) => binder.FallbackDeleteIndex(this, indexes, e));
+ DynamicMetaObject[] localIndexes = indexes;
+
+ return CallMethodNoResult(
+ DynamicObject_TryDeleteIndex,
+ binder,
+ GetExpressions(indexes),
+ (MetaDynamic @this, DeleteIndexBinder b, DynamicMetaObject e) => b.FallbackDeleteIndex(@this, localIndexes, e)
+ );
}
return base.BindDeleteIndex(binder, indexes);
}
- private delegate DynamicMetaObject Fallback(DynamicMetaObject errorSuggestion);
+ private delegate DynamicMetaObject Fallback<TBinder>(MetaDynamic @this, TBinder binder, DynamicMetaObject errorSuggestion);
- private readonly static Expression[] s_noArgs = new Expression[0]; // used in reference comparison, requires unique object identity
+ private static readonly Expression[] s_noArgs = new Expression[0]; // used in reference comparison, requires unique object identity
private static ReadOnlyCollection<Expression> GetConvertedArgs(params Expression[] args)
{
@@ -410,21 +467,23 @@ namespace System.Dynamic
for (int i = 0; i < args.Length; i++)
{
- ContractUtils.Requires(args[i] is ParameterExpression, nameof(args));
- if (((ParameterExpression)args[i]).IsByRef)
+ ParameterExpression variable = args[i] as ParameterExpression;
+ ContractUtils.Requires(variable != null, nameof(args));
+
+ if (variable.IsByRef)
{
if (block == null)
block = new ReadOnlyCollectionBuilder<Expression>();
block.Add(
Expression.Assign(
- args[i],
+ variable,
Expression.Convert(
Expression.ArrayIndex(
callArgs,
AstUtils.Constant(i)
),
- args[i].Type
+ variable.Type
)
)
);
@@ -461,26 +520,26 @@ namespace System.Dynamic
/// Helper method for generating a MetaObject which calls a
/// specific method on Dynamic that returns a result
/// </summary>
- private DynamicMetaObject CallMethodWithResult<TBinder>(string methodName, TBinder binder, Expression[] args, Fallback fallback)
+ private DynamicMetaObject CallMethodWithResult<TBinder>(MethodInfo method, TBinder binder, Expression[] args, Fallback<TBinder> fallback)
where TBinder : DynamicMetaObjectBinder
{
- return CallMethodWithResult(methodName, binder, args, fallback, null);
+ return CallMethodWithResult(method, binder, args, fallback, null);
}
/// <summary>
/// Helper method for generating a MetaObject which calls a
/// specific method on Dynamic that returns a result
/// </summary>
- private DynamicMetaObject CallMethodWithResult<TBinder>(string methodName, TBinder binder, Expression[] args, Fallback fallback, Fallback fallbackInvoke)
+ private DynamicMetaObject CallMethodWithResult<TBinder>(MethodInfo method, TBinder binder, Expression[] args, Fallback<TBinder> fallback, Fallback<TBinder> fallbackInvoke)
where TBinder : DynamicMetaObjectBinder
{
//
// First, call fallback to do default binding
// This produces either an error or a call to a .NET member
//
- DynamicMetaObject fallbackResult = fallback(null);
+ DynamicMetaObject fallbackResult = fallback(this, binder, null);
- DynamicMetaObject callDynamic = BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke);
+ DynamicMetaObject callDynamic = BuildCallMethodWithResult(method, binder, args, fallbackResult, fallbackInvoke);
//
// Now, call fallback again using our new MO as the error
@@ -490,7 +549,7 @@ namespace System.Dynamic
// 2. Binding will fail, and it will use the MO we created
// above.
//
- return fallback(callDynamic);
+ return fallback(this, binder, callDynamic);
}
/// <summary>
@@ -501,10 +560,10 @@ namespace System.Dynamic
/// to the method as an object[] or NoArgs to signify that
/// the target method takes no parameters.
/// </summary>
- private DynamicMetaObject BuildCallMethodWithResult<TBinder>(string methodName, TBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke)
+ private DynamicMetaObject BuildCallMethodWithResult<TBinder>(MethodInfo method, TBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback<TBinder> fallbackInvoke)
where TBinder : DynamicMetaObjectBinder
{
- if (!IsOverridden(methodName))
+ if (!IsOverridden(method))
{
return fallbackResult;
}
@@ -517,7 +576,7 @@ namespace System.Dynamic
// }
//
ParameterExpression result = Expression.Parameter(typeof(object), null);
- ParameterExpression callArgs = methodName != nameof(DynamicObject.TryBinaryOperation) ? Expression.Parameter(typeof(object[]), null) : Expression.Parameter(typeof(object), null);
+ ParameterExpression callArgs = method != DynamicObject_TryBinaryOperation ? Expression.Parameter(typeof(object[]), null) : Expression.Parameter(typeof(object), null);
ReadOnlyCollection<Expression> callArgsValue = GetConvertedArgs(args);
var resultMO = new DynamicMetaObject(result, BindingRestrictions.Empty);
@@ -589,18 +648,18 @@ namespace System.Dynamic
if (fallbackInvoke != null)
{
- resultMO = fallbackInvoke(resultMO);
+ resultMO = fallbackInvoke(this, binder, resultMO);
}
var callDynamic = new DynamicMetaObject(
Expression.Block(
new TrueReadOnlyCollection<ParameterExpression>(result, callArgs),
new TrueReadOnlyCollection<Expression>(
- methodName != nameof(DynamicObject.TryBinaryOperation) ? Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)) : Expression.Assign(callArgs, callArgsValue[0]),
+ method != DynamicObject_TryBinaryOperation ? Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)) : Expression.Assign(callArgs, callArgsValue[0]),
Expression.Condition(
Expression.Call(
GetLimitedSelf(),
- typeof(DynamicObject).GetMethod(methodName),
+ method,
BuildCallArgs(
binder,
args,
@@ -609,7 +668,7 @@ namespace System.Dynamic
)
),
Expression.Block(
- methodName != nameof(DynamicObject.TryBinaryOperation) ? ReferenceArgAssign(callArgs, args) : AstUtils.Empty,
+ method != DynamicObject_TryBinaryOperation ? ReferenceArgAssign(callArgs, args) : AstUtils.Empty,
resultMO.Expression
),
fallbackResult.Expression,
@@ -631,14 +690,14 @@ namespace System.Dynamic
/// to the method as an object[] or NoArgs to signify that
/// the target method takes no parameters.
/// </summary>
- private DynamicMetaObject CallMethodReturnLast<TBinder>(string methodName, TBinder binder, Expression[] args, Expression value, Fallback fallback)
+ private DynamicMetaObject CallMethodReturnLast<TBinder>(MethodInfo method, TBinder binder, Expression[] args, Expression value, Fallback<TBinder> fallback)
where TBinder : DynamicMetaObjectBinder
{
//
// First, call fallback to do default binding
// This produces either an error or a call to a .NET member
//
- DynamicMetaObject fallbackResult = fallback(null);
+ DynamicMetaObject fallbackResult = fallback(this, binder, null);
//
// Build a new expression like:
@@ -660,7 +719,7 @@ namespace System.Dynamic
Expression.Condition(
Expression.Call(
GetLimitedSelf(),
- typeof(DynamicObject).GetMethod(methodName),
+ method,
BuildCallArgs(
binder,
args,
@@ -688,7 +747,7 @@ namespace System.Dynamic
// 2. Binding will fail, and it will use the MO we created
// above.
//
- return fallback(callDynamic);
+ return fallback(this, binder, callDynamic);
}
/// <summary>
@@ -700,14 +759,14 @@ namespace System.Dynamic
/// to the method as an object[] or NoArgs to signify that
/// the target method takes no parameters.
/// </summary>
- private DynamicMetaObject CallMethodNoResult<TBinder>(string methodName, TBinder binder, Expression[] args, Fallback fallback)
+ private DynamicMetaObject CallMethodNoResult<TBinder>(MethodInfo method, TBinder binder, Expression[] args, Fallback<TBinder> fallback)
where TBinder : DynamicMetaObjectBinder
{
//
// First, call fallback to do default binding
// This produces either an error or a call to a .NET member
//
- DynamicMetaObject fallbackResult = fallback(null);
+ DynamicMetaObject fallbackResult = fallback(this, binder, null);
ParameterExpression callArgs = Expression.Parameter(typeof(object[]), null);
ReadOnlyCollection<Expression> callArgsValue = GetConvertedArgs(args);
@@ -723,7 +782,7 @@ namespace System.Dynamic
Expression.Condition(
Expression.Call(
GetLimitedSelf(),
- typeof(DynamicObject).GetMethod(methodName),
+ method,
BuildCallArgs(
binder,
args,
@@ -751,7 +810,7 @@ namespace System.Dynamic
// 2. Binding will fail, and it will use the MO we created
// above.
//
- return fallback(callDynamic);
+ return fallback(this, binder, callDynamic);
}
/// <summary>
@@ -759,44 +818,15 @@ namespace System.Dynamic
/// implementation for the method provided then Dynamic falls back to the base class
/// behavior which lets the call site determine how the binder is performed.
/// </summary>
- private bool IsOverridden(string method)
+ private bool IsOverridden(MethodInfo method)
{
- MemberInfo[] members = Value.GetType().GetMember(method, BindingFlags.Public | BindingFlags.Instance);
+ MemberInfo[] methods = Value.GetType().GetMember(method.Name, MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance);
- foreach (MemberInfo member in members)
+ foreach (MethodInfo mi in methods)
{
- var mi = member as MethodInfo;
-
- if (mi != null && mi.DeclaringType != typeof(DynamicObject))
+ if (mi.DeclaringType != typeof(DynamicObject) && mi.GetBaseDefinition() == method)
{
- MemberInfo[] baseMembers = typeof(DynamicObject).GetMember(method, BindingFlags.Public | BindingFlags.Instance);
-
- foreach (MemberInfo baseMember in baseMembers)
- {
- var baseMethod = baseMember as MethodInfo;
-
- if (baseMethod != null)
- {
- ParameterInfo[] baseParams = baseMethod.GetParameters();
- ParameterInfo[] miParams = mi.GetParameters();
-
- if (baseParams.Length == miParams.Length)
- {
- bool mismatch = false;
- for (int i = 0; i < baseParams.Length; i++)
- {
- if (baseParams[i].ParameterType != miParams[i].ParameterType)
- {
- mismatch = true;
- }
- }
- if (!mismatch)
- {
- return true;
- }
- }
- }
- }
+ return true;
}
}
@@ -853,14 +883,15 @@ namespace System.Dynamic
#region IDynamicMetaObjectProvider Members
/// <summary>
- /// The provided MetaObject will dispatch to the Dynamic virtual methods.
- /// The object can be encapsulated inside of another MetaObject to
- /// provide custom behavior for individual actions.
+ /// Returns the <see cref="DynamicMetaObject" /> responsible for binding operations performed on this object,
+ /// using the virtual methods provided by this class.
/// </summary>
- public virtual DynamicMetaObject GetMetaObject(Expression parameter)
- {
- return new MetaDynamic(parameter, this);
- }
+ /// <param name="parameter">The expression tree representation of the runtime value.</param>
+ /// <returns>
+ /// The <see cref="DynamicMetaObject" /> to bind this object. The object can be encapsulated inside of another
+ /// <see cref="DynamicMetaObject"/> to provide custom behavior for individual actions.
+ /// </returns>
+ public virtual DynamicMetaObject GetMetaObject(Expression parameter) => new MetaDynamic(parameter, this);
#endregion
}
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs b/src/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs
index b692c25f28..0015c5d476 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/ExpandoObject.cs
@@ -39,7 +39,7 @@ namespace System.Dynamic
private ExpandoData _data; // the data currently being held by the Expando object
private int _count; // the count of available members
- internal readonly static object Uninitialized = new object(); // A marker object used to identify that a value is uninitialized.
+ internal static readonly object Uninitialized = new object(); // A marker object used to identify that a value is uninitialized.
internal const int AmbiguousMatchFound = -2; // The value is used to indicate there exists ambiguous match in the Expando object
internal const int NoMatch = -1; // The value is used to indicate there is no matching member
@@ -239,6 +239,7 @@ namespace System.Dynamic
/// </summary>
internal bool IsDeletedMember(int index)
{
+ ContractUtils.AssertLockHeld(LockObject);
Debug.Assert(index >= 0 && index <= _data.Length);
if (index == _data.Length)
@@ -263,15 +264,14 @@ namespace System.Dynamic
private ExpandoData PromoteClassCore(ExpandoClass oldClass, ExpandoClass newClass)
{
Debug.Assert(oldClass != newClass);
+ ContractUtils.AssertLockHeld(LockObject);
- lock (LockObject)
+ if (_data.Class == oldClass)
{
- if (_data.Class == oldClass)
- {
- _data = _data.UpdateClass(newClass);
- }
- return _data;
+ _data = _data.UpdateClass(newClass);
}
+
+ return _data;
}
/// <summary>
@@ -281,7 +281,10 @@ namespace System.Dynamic
/// </summary>
internal void PromoteClass(object oldClass, object newClass)
{
- PromoteClassCore((ExpandoClass)oldClass, (ExpandoClass)newClass);
+ lock (LockObject)
+ {
+ PromoteClassCore((ExpandoClass)oldClass, (ExpandoClass)newClass);
+ }
}
#endregion
@@ -311,6 +314,7 @@ namespace System.Dynamic
private bool ExpandoContainsKey(string key)
{
+ ContractUtils.AssertLockHeld(LockObject);
return _data.Class.GetValueIndexCaseSensitive(key) >= 0;
}
@@ -712,11 +716,11 @@ namespace System.Dynamic
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
ContractUtils.RequiresNotNull(array, nameof(array));
- ContractUtils.RequiresArrayRange(array, arrayIndex, _count, nameof(arrayIndex), nameof(ICollection<KeyValuePair<string, object>>.Count));
- // We want this to be atomic and not throw
+ // We want this to be atomic and not throw, though we must do the range checks inside this lock.
lock (LockObject)
{
+ ContractUtils.RequiresArrayRange(array, arrayIndex, _count, nameof(arrayIndex), nameof(ICollection<KeyValuePair<string, object>>.Count));
foreach (KeyValuePair<string, object> item in this)
{
array[arrayIndex++] = item;
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/GetIndexBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/GetIndexBinder.cs
index 508db6a842..bd8e4b285d 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/GetIndexBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/GetIndexBinder.cs
@@ -45,7 +45,9 @@ namespace System.Dynamic
return target.BindGetIndex(this, args);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
/// <summary>
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/GetMemberBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/GetMemberBinder.cs
index 58d10ae33c..9f9da19bed 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/GetMemberBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/GetMemberBinder.cs
@@ -71,7 +71,9 @@ namespace System.Dynamic
return target.BindGetMember(this);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
}
}
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/IDynamicMetaObjectProvider.cs b/src/System.Linq.Expressions/src/System/Dynamic/IDynamicMetaObjectProvider.cs
index 958f6ec81b..e705a72d39 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/IDynamicMetaObjectProvider.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/IDynamicMetaObjectProvider.cs
@@ -10,8 +10,8 @@ namespace System.Dynamic
/// Represents a dynamic object, that can have its operations bound at runtime.
/// </summary>
/// <remarks>
- /// Objects that want to participate in the binding process should implement an IDynamicMetaObjectProvider interface,
- /// and implement <see cref="IDynamicMetaObjectProvider.GetMetaObject" /> to return a <see cref="DynamicMetaObject" />.
+ /// Objects that want to participate in the binding process should implement an <see cref="IDynamicMetaObjectProvider"/> interface,
+ /// and implement <see cref="GetMetaObject" /> to return a <see cref="DynamicMetaObject" />.
/// </remarks>
public interface IDynamicMetaObjectProvider
{
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/InvokeBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/InvokeBinder.cs
index 04243bacf2..5a3e5ef033 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/InvokeBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/InvokeBinder.cs
@@ -65,7 +65,9 @@ namespace System.Dynamic
return target.BindInvoke(this, args);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
}
}
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/InvokeMemberBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/InvokeMemberBinder.cs
index bb43dcf4d9..52f4339fa8 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/InvokeMemberBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/InvokeMemberBinder.cs
@@ -7,8 +7,7 @@ using System.Dynamic.Utils;
namespace System.Dynamic
{
/// <summary>
- /// Represents the invoke member dynamic operation at the call site,
- /// providing the binding semantic and the details about the operation.
+ /// Represents the invoke member dynamic operation at the call site, providing the binding semantic and the details about the operation.
/// </summary>
public abstract class InvokeMemberBinder : DynamicMetaObjectBinder
{
@@ -62,7 +61,9 @@ namespace System.Dynamic
return target.BindInvokeMember(this, args);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
/// <summary>
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/SetIndexBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/SetIndexBinder.cs
index 2c0a97a838..4b9f57ef1d 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/SetIndexBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/SetIndexBinder.cs
@@ -52,7 +52,9 @@ namespace System.Dynamic
return target.BindSetIndex(this, indexes, value);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
/// <summary>
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/SetMemberBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/SetMemberBinder.cs
index 6277756d61..743743ca6e 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/SetMemberBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/SetMemberBinder.cs
@@ -57,7 +57,9 @@ namespace System.Dynamic
return target.BindSetMember(this, arg0);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
/// <summary>
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/UnaryOperationBinder.cs b/src/System.Linq.Expressions/src/System/Dynamic/UnaryOperationBinder.cs
index 12e0c479c2..2cc309614e 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/UnaryOperationBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/UnaryOperationBinder.cs
@@ -77,7 +77,9 @@ namespace System.Dynamic
return target.BindUnaryOperation(this);
}
- // this is a standard DynamicMetaObjectBinder
+ /// <summary>
+ /// Always returns <c>true</c> because this is a standard <see cref="DynamicMetaObjectBinder"/>.
+ /// </summary>
internal override sealed bool IsStandardBinder => true;
internal static bool OperationIsValid(ExpressionType operation)
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/Utils/CachedReflectionInfo.cs b/src/System.Linq.Expressions/src/System/Dynamic/Utils/CachedReflectionInfo.cs
index ca37370300..1d36702fe7 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/Utils/CachedReflectionInfo.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/Utils/CachedReflectionInfo.cs
@@ -2,6 +2,7 @@
// 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.Dynamic;
using System.Reflection;
using System.Runtime.CompilerServices;
@@ -73,5 +74,65 @@ namespace System.Linq.Expressions
public static MethodInfo CallSiteOps_Bind =>
s_CallSiteOps_Bind ??
(s_CallSiteOps_Bind = typeof(CallSiteOps).GetMethod(nameof(CallSiteOps.Bind)));
+
+ private static MethodInfo s_DynamicObject_TryGetMember;
+ public static MethodInfo DynamicObject_TryGetMember =>
+ s_DynamicObject_TryGetMember ??
+ (s_DynamicObject_TryGetMember = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryGetMember)));
+
+ private static MethodInfo s_DynamicObject_TrySetMember;
+ public static MethodInfo DynamicObject_TrySetMember =>
+ s_DynamicObject_TrySetMember ??
+ (s_DynamicObject_TrySetMember = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TrySetMember)));
+
+ private static MethodInfo s_DynamicObject_TryDeleteMember;
+ public static MethodInfo DynamicObject_TryDeleteMember =>
+ s_DynamicObject_TryDeleteMember ??
+ (s_DynamicObject_TryDeleteMember = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryDeleteMember)));
+
+ private static MethodInfo s_DynamicObject_TryGetIndex;
+ public static MethodInfo DynamicObject_TryGetIndex =>
+ s_DynamicObject_TryGetIndex ??
+ (s_DynamicObject_TryGetIndex = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryGetIndex)));
+
+ private static MethodInfo s_DynamicObject_TrySetIndex;
+ public static MethodInfo DynamicObject_TrySetIndex =>
+ s_DynamicObject_TrySetIndex ??
+ (s_DynamicObject_TrySetIndex = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TrySetIndex)));
+
+ private static MethodInfo s_DynamicObject_TryDeleteIndex;
+ public static MethodInfo DynamicObject_TryDeleteIndex =>
+ s_DynamicObject_TryDeleteIndex ??
+ (s_DynamicObject_TryDeleteIndex = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryDeleteIndex)));
+
+ private static MethodInfo s_DynamicObject_TryConvert;
+ public static MethodInfo DynamicObject_TryConvert =>
+ s_DynamicObject_TryConvert ??
+ (s_DynamicObject_TryConvert = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryConvert)));
+
+ private static MethodInfo s_DynamicObject_TryInvoke;
+ public static MethodInfo DynamicObject_TryInvoke =>
+ s_DynamicObject_TryInvoke ??
+ (s_DynamicObject_TryInvoke = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryInvoke)));
+
+ private static MethodInfo s_DynamicObject_TryInvokeMember;
+ public static MethodInfo DynamicObject_TryInvokeMember =>
+ s_DynamicObject_TryInvokeMember ??
+ (s_DynamicObject_TryInvokeMember = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryInvokeMember)));
+
+ private static MethodInfo s_DynamicObject_TryBinaryOperation;
+ public static MethodInfo DynamicObject_TryBinaryOperation =>
+ s_DynamicObject_TryBinaryOperation ??
+ (s_DynamicObject_TryBinaryOperation = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryBinaryOperation)));
+
+ private static MethodInfo s_DynamicObject_TryUnaryOperation;
+ public static MethodInfo DynamicObject_TryUnaryOperation =>
+ s_DynamicObject_TryUnaryOperation ??
+ (s_DynamicObject_TryUnaryOperation = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryUnaryOperation)));
+
+ private static MethodInfo s_DynamicObject_TryCreateInstance;
+ public static MethodInfo DynamicObject_TryCreateInstance =>
+ s_DynamicObject_TryCreateInstance ??
+ (s_DynamicObject_TryCreateInstance = typeof(DynamicObject).GetMethod(nameof(DynamicObject.TryCreateInstance)));
}
}
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/Utils/CollectionExtensions.cs b/src/System.Linq.Expressions/src/System/Dynamic/Utils/CollectionExtensions.cs
index 62435c1563..701809b06b 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/Utils/CollectionExtensions.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/Utils/CollectionExtensions.cs
@@ -3,17 +3,119 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Runtime.CompilerServices;
namespace System.Dynamic.Utils
{
- internal static partial class CollectionExtensions
+ internal static class CollectionExtensions
{
- public static T[] AddLast<T>(this IList<T> list, T item)
+ public static TrueReadOnlyCollection<T> AddFirst<T>(this ReadOnlyCollection<T> list, T item)
{
T[] res = new T[list.Count + 1];
- list.CopyTo(res, 0);
- res[list.Count] = item;
+ res[0] = item;
+ list.CopyTo(res, 1);
+ return new TrueReadOnlyCollection<T>(res);
+ }
+
+ public static T[] AddFirst<T>(this T[] array, T item)
+ {
+ T[] res = new T[array.Length + 1];
+ res[0] = item;
+ array.CopyTo(res, 1);
+ return res;
+ }
+
+ public static T[] AddLast<T>(this T[] array, T item)
+ {
+ T[] res = new T[array.Length + 1];
+ array.CopyTo(res, 0);
+ res[array.Length] = item;
return res;
}
+
+ public static T[] RemoveFirst<T>(this T[] array)
+ {
+ T[] result = new T[array.Length - 1];
+ Array.Copy(array, 1, result, 0, result.Length);
+ return result;
+ }
+
+ public static T[] RemoveLast<T>(this T[] array)
+ {
+ T[] result = new T[array.Length - 1];
+ Array.Copy(array, 0, result, 0, result.Length);
+ return result;
+ }
+
+ /// <summary>
+ /// Wraps the provided enumerable into a ReadOnlyCollection{T}
+ ///
+ /// Copies all of the data into a new array, so the data can't be
+ /// changed after creation. The exception is if the enumerable is
+ /// already a ReadOnlyCollection{T}, in which case we just return it.
+ /// </summary>
+ public static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> enumerable)
+ {
+ if (enumerable == null)
+ {
+ return EmptyReadOnlyCollection<T>.Instance;
+ }
+
+ var troc = enumerable as TrueReadOnlyCollection<T>;
+ if (troc != null)
+ {
+ return troc;
+ }
+
+ var builder = enumerable as ReadOnlyCollectionBuilder<T>;
+ if (builder != null)
+ {
+ return builder.ToReadOnlyCollection();
+ }
+
+ T[] array = EnumerableHelpers.ToArray(enumerable);
+ return array.Length == 0 ?
+ EmptyReadOnlyCollection<T>.Instance :
+ new TrueReadOnlyCollection<T>(array);
+ }
+
+ // We could probably improve the hashing here
+ public static int ListHashCode<T>(this ReadOnlyCollection<T> list)
+ {
+ EqualityComparer<T> cmp = EqualityComparer<T>.Default;
+ int h = 6551;
+ foreach (T t in list)
+ {
+ h ^= (h << 5) ^ cmp.GetHashCode(t);
+ }
+ return h;
+ }
+
+ public static bool ListEquals<T>(this ReadOnlyCollection<T> first, ReadOnlyCollection<T> second)
+ {
+ if (first == second)
+ {
+ return true;
+ }
+
+ int count = first.Count;
+
+ if (count != second.Count)
+ {
+ return false;
+ }
+
+ EqualityComparer<T> cmp = EqualityComparer<T>.Default;
+ for (int i = 0; i != count; ++i)
+ {
+ if (!cmp.Equals(first[i], second[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
}
}
diff --git a/src/Common/src/System/Dynamic/Utils/EmptyReadOnlyCollection.cs b/src/System.Linq.Expressions/src/System/Dynamic/Utils/EmptyReadOnlyCollection.cs
index 047aed59b6..abc90e1557 100644
--- a/src/Common/src/System/Dynamic/Utils/EmptyReadOnlyCollection.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/Utils/EmptyReadOnlyCollection.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// 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.
@@ -9,6 +9,6 @@ namespace System.Dynamic.Utils
{
internal static class EmptyReadOnlyCollection<T>
{
- public readonly static ReadOnlyCollection<T> Instance = new TrueReadOnlyCollection<T>(Array.Empty<T>());
+ public static readonly ReadOnlyCollection<T> Instance = new TrueReadOnlyCollection<T>(Array.Empty<T>());
}
}
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/Utils/ExpressionVisitorUtils.cs b/src/System.Linq.Expressions/src/System/Dynamic/Utils/ExpressionVisitorUtils.cs
index 1df458fbb1..18226dd6fc 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/Utils/ExpressionVisitorUtils.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/Utils/ExpressionVisitorUtils.cs
@@ -6,7 +6,7 @@ using System.Linq.Expressions;
namespace System.Dynamic.Utils
{
- internal static partial class ExpressionVisitorUtils
+ internal static class ExpressionVisitorUtils
{
public static Expression[] VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block)
{
@@ -57,5 +57,30 @@ namespace System.Dynamic.Utils
}
return newNodes;
}
+
+ public static Expression[] VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
+ {
+ Expression[] newNodes = null;
+ for (int i = 0, n = nodes.ArgumentCount; i < n; i++)
+ {
+ Expression curNode = nodes.GetArgument(i);
+ Expression node = visitor.Visit(curNode);
+
+ if (newNodes != null)
+ {
+ newNodes[i] = node;
+ }
+ else if (!object.ReferenceEquals(node, curNode))
+ {
+ newNodes = new Expression[n];
+ for (int j = 0; j < i; j++)
+ {
+ newNodes[j] = nodes.GetArgument(j);
+ }
+ newNodes[i] = node;
+ }
+ }
+ return newNodes;
+ }
}
}
diff --git a/src/Common/src/System/Dynamic/Utils/ListArgumentProvider.cs b/src/System.Linq.Expressions/src/System/Dynamic/Utils/ListArgumentProvider.cs
index 9d5b6f7aba..9d5b6f7aba 100644
--- a/src/Common/src/System/Dynamic/Utils/ListArgumentProvider.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/Utils/ListArgumentProvider.cs
diff --git a/src/System.Linq.Expressions/src/System/Dynamic/Utils/TypeExtensions.cs b/src/System.Linq.Expressions/src/System/Dynamic/Utils/TypeExtensions.cs
index 5f0908b5af..677181f2b4 100644
--- a/src/System.Linq.Expressions/src/System/Dynamic/Utils/TypeExtensions.cs
+++ b/src/System.Linq.Expressions/src/System/Dynamic/Utils/TypeExtensions.cs
@@ -23,6 +23,7 @@ namespace System.Dynamic.Utils
return method;
}
}
+
return null;
}
@@ -41,7 +42,8 @@ namespace System.Dynamic.Utils
{
return false;
}
- ParameterInfo[] ps = mi.GetParameters();
+
+ ParameterInfo[] ps = mi.GetParametersCached();
if (ps.Length != argTypes.Length)
{
@@ -55,6 +57,7 @@ namespace System.Dynamic.Utils
return false;
}
}
+
return true;
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/HoistedLocals.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/HoistedLocals.cs
index 4ab06c83e1..db0812b86c 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/HoistedLocals.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/HoistedLocals.cs
@@ -63,7 +63,7 @@ namespace System.Linq.Expressions.Compiler
if (parent != null)
{
// Add the parent locals array as the 0th element in the array
- vars = new TrueReadOnlyCollection<ParameterExpression>(vars.AddFirst(parent.SelfVariable));
+ vars = vars.AddFirst(parent.SelfVariable);
}
Dictionary<Expression, int> indexes = new Dictionary<Expression, int>(vars.Count);
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/DynamicExpression.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/DynamicExpression.cs
index 9490baeb61..037b83c031 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/DynamicExpression.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/DynamicExpression.cs
@@ -2,7 +2,6 @@
// 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.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
@@ -10,7 +9,6 @@ using System.Dynamic.Utils;
using System.Linq.Expressions.Compiler;
using System.Reflection;
using System.Runtime.CompilerServices;
-using System.Dynamic;
using DelegateHelpers = System.Linq.Expressions.Compiler.DelegateHelpers;
@@ -21,27 +19,25 @@ namespace System.Linq.Expressions
/// </summary>
public class DynamicExpression : Expression, IDynamicExpression
{
- private readonly CallSiteBinder _binder;
- private readonly Type _delegateType;
-
internal DynamicExpression(Type delegateType, CallSiteBinder binder)
{
Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == typeof(object) || GetType() != typeof(DynamicExpression));
- _delegateType = delegateType;
- _binder = binder;
+ DelegateType = delegateType;
+ Binder = binder;
}
- public override bool CanReduce
- {
- get
- {
- return true;
- }
- }
+ /// <summary>
+ /// Gets a value that indicates whether the expression tree node can be reduced.
+ /// </summary>
+ public override bool CanReduce => true;
+ /// <summary>
+ /// Reduces the dynamic expression node to a simpler expression.
+ /// </summary>
+ /// <returns>The reduced expression.</returns>
public override Expression Reduce()
{
- var site = Expression.Constant(CallSite.Create(_delegateType, _binder));
+ var site = Expression.Constant(CallSite.Create(DelegateType, Binder));
return Expression.Invoke(
Expression.Field(
site,
@@ -113,45 +109,30 @@ namespace System.Linq.Expressions
/// Gets the static type of the expression that this <see cref="Expression" /> represents.
/// </summary>
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
- public override Type Type
- {
- get { return typeof(object); }
- }
+ public override Type Type => typeof(object);
/// <summary>
/// Returns the node type of this Expression. Extension nodes should return
/// ExpressionType.Extension when overriding this method.
/// </summary>
/// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
- public sealed override ExpressionType NodeType
- {
- get { return ExpressionType.Dynamic; }
- }
+ public sealed override ExpressionType NodeType => ExpressionType.Dynamic;
/// <summary>
/// Gets the <see cref="CallSiteBinder" />, which determines the runtime behavior of the
/// dynamic site.
/// </summary>
- public CallSiteBinder Binder
- {
- get { return _binder; }
- }
+ public CallSiteBinder Binder { get; }
/// <summary>
/// Gets the type of the delegate used by the <see cref="CallSite" />.
/// </summary>
- public Type DelegateType
- {
- get { return _delegateType; }
- }
+ public Type DelegateType { get; }
/// <summary>
/// Gets the arguments to the dynamic operation.
/// </summary>
- public ReadOnlyCollection<Expression> Arguments
- {
- get { return GetOrMakeArguments(); }
- }
+ public ReadOnlyCollection<Expression> Arguments => GetOrMakeArguments();
internal virtual ReadOnlyCollection<Expression> GetOrMakeArguments()
{
@@ -216,6 +197,7 @@ namespace System.Linq.Expressions
#endregion
#region Members that forward to Expression
+
/// <summary>
/// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
/// </summary>
@@ -225,12 +207,12 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.Binder">Binder</see> and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="Binder">Binder</see> and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
/// <remarks>
- /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
- /// result will be inferred from the types of the arguments and the specified return type.
+ /// The <see cref="DelegateType">DelegateType</see> property of the result will be inferred
+ /// from the types of the arguments and the specified return type.
/// </remarks>
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, params Expression[] arguments)
{
@@ -246,12 +228,12 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.Binder">Binder</see> and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="Binder">Binder</see> and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
/// <remarks>
- /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
- /// result will be inferred from the types of the arguments and the specified return type.
+ /// The <see cref="DelegateType">DelegateType</see> property of the result will be inferred
+ /// from the types of the arguments and the specified return type.
/// </remarks>
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, IEnumerable<Expression> arguments)
{
@@ -267,12 +249,12 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.Binder">Binder</see> and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="Binder">Binder</see> and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
/// <remarks>
- /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
- /// result will be inferred from the types of the arguments and the specified return type.
+ /// The <see cref="DelegateType">DelegateType</see> property of the result will be inferred
+ /// from the types of the arguments and the specified return type.
/// </remarks>
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0)
{
@@ -289,12 +271,12 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.Binder">Binder</see> and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="Binder">Binder</see> and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
/// <remarks>
- /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
- /// result will be inferred from the types of the arguments and the specified return type.
+ /// The <see cref="DelegateType">DelegateType</see> property of the result will be inferred
+ /// from the types of the arguments and the specified return type.
/// </remarks>
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1)
{
@@ -312,12 +294,12 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.Binder">Binder</see> and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="Binder">Binder</see> and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
/// <remarks>
- /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
- /// result will be inferred from the types of the arguments and the specified return type.
+ /// The <see cref="DelegateType">DelegateType</see> property of the result will be inferred
+ /// from the types of the arguments and the specified return type.
/// </remarks>
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2)
{
@@ -336,12 +318,12 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.Binder">Binder</see> and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="Binder">Binder</see> and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
/// <remarks>
- /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
- /// result will be inferred from the types of the arguments and the specified return type.
+ /// The <see cref="DelegateType">DelegateType</see> property of the result will be inferred
+ /// from the types of the arguments and the specified return type.
/// </remarks>
public static new DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
{
@@ -357,9 +339,9 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
- /// <see cref="DynamicExpression.Binder">Binder</see>, and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="DelegateType">DelegateType</see>,
+ /// <see cref="Binder">Binder</see>, and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
public static new DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, IEnumerable<Expression> arguments)
{
@@ -375,9 +357,9 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
- /// <see cref="DynamicExpression.Binder">Binder</see>, and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="DelegateType">DelegateType</see>,
+ /// <see cref="Binder">Binder</see>, and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
public static new DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, params Expression[] arguments)
{
@@ -393,9 +375,9 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
- /// <see cref="DynamicExpression.Binder">Binder</see>, and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="DelegateType">DelegateType</see>,
+ /// <see cref="Binder">Binder</see>, and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
public static new DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0)
{
@@ -412,9 +394,9 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
- /// <see cref="DynamicExpression.Binder">Binder</see>, and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="DelegateType">DelegateType</see>,
+ /// <see cref="Binder">Binder</see>, and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
public static new DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
{
@@ -432,9 +414,9 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
- /// <see cref="DynamicExpression.Binder">Binder</see>, and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="DelegateType">DelegateType</see>,
+ /// <see cref="Binder">Binder</see>, and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
public static new DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
{
@@ -453,20 +435,18 @@ namespace System.Linq.Expressions
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
- /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
- /// <see cref="DynamicExpression.Binder">Binder</see>, and
- /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// <see cref="DelegateType">DelegateType</see>,
+ /// <see cref="Binder">Binder</see>, and
+ /// <see cref="Arguments">Arguments</see> set to the specified values.
/// </returns>
public static new DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
{
return ExpressionExtension.MakeDynamic(delegateType, binder, arg0, arg1, arg2, arg3);
}
+
#endregion
- Expression IDynamicExpression.Rewrite(Expression[] args)
- {
- return this.Rewrite(args);
- }
+ Expression IDynamicExpression.Rewrite(Expression[] args) => Rewrite(args);
object IDynamicExpression.CreateCallSite()
{
@@ -486,18 +466,9 @@ namespace System.Linq.Expressions
_arguments = arguments;
}
- Expression IArgumentProvider.GetArgument(int index)
- {
- return _arguments[index];
- }
+ Expression IArgumentProvider.GetArgument(int index) => _arguments[index];
- int IArgumentProvider.ArgumentCount
- {
- get
- {
- return _arguments.Count;
- }
- }
+ int IArgumentProvider.ArgumentCount => _arguments.Count;
internal override ReadOnlyCollection<Expression> GetOrMakeArguments()
{
@@ -514,19 +485,14 @@ namespace System.Linq.Expressions
internal class TypedDynamicExpressionN : DynamicExpressionN
{
- private readonly Type _returnType;
-
internal TypedDynamicExpressionN(Type returnType, Type delegateType, CallSiteBinder binder, IReadOnlyList<Expression> arguments)
: base(delegateType, binder, arguments)
{
Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == returnType);
- _returnType = returnType;
+ Type = returnType;
}
- public sealed override Type Type
- {
- get { return _returnType; }
- }
+ public sealed override Type Type { get; }
}
internal class DynamicExpression1 : DynamicExpression, IArgumentProvider
@@ -548,13 +514,7 @@ namespace System.Linq.Expressions
}
}
- int IArgumentProvider.ArgumentCount
- {
- get
- {
- return 1;
- }
- }
+ int IArgumentProvider.ArgumentCount => 1;
internal override ReadOnlyCollection<Expression> GetOrMakeArguments()
{
@@ -571,18 +531,13 @@ namespace System.Linq.Expressions
internal sealed class TypedDynamicExpression1 : DynamicExpression1
{
- private readonly Type _retType;
-
internal TypedDynamicExpression1(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0)
: base(delegateType, binder, arg0)
{
- _retType = retType;
+ Type = retType;
}
- public sealed override Type Type
- {
- get { return _retType; }
- }
+ public sealed override Type Type { get; }
}
internal class DynamicExpression2 : DynamicExpression, IArgumentProvider
@@ -607,13 +562,7 @@ namespace System.Linq.Expressions
}
}
- int IArgumentProvider.ArgumentCount
- {
- get
- {
- return 2;
- }
- }
+ int IArgumentProvider.ArgumentCount => 2;
internal override ReadOnlyCollection<Expression> GetOrMakeArguments()
{
@@ -630,18 +579,13 @@ namespace System.Linq.Expressions
internal sealed class TypedDynamicExpression2 : DynamicExpression2
{
- private readonly Type _retType;
-
internal TypedDynamicExpression2(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
: base(delegateType, binder, arg0, arg1)
{
- _retType = retType;
+ Type = retType;
}
- public sealed override Type Type
- {
- get { return _retType; }
- }
+ public sealed override Type Type { get; }
}
internal class DynamicExpression3 : DynamicExpression, IArgumentProvider
@@ -668,13 +612,7 @@ namespace System.Linq.Expressions
}
}
- int IArgumentProvider.ArgumentCount
- {
- get
- {
- return 3;
- }
- }
+ int IArgumentProvider.ArgumentCount => 3;
internal override ReadOnlyCollection<Expression> GetOrMakeArguments()
{
@@ -691,18 +629,13 @@ namespace System.Linq.Expressions
internal sealed class TypedDynamicExpression3 : DynamicExpression3
{
- private readonly Type _retType;
-
internal TypedDynamicExpression3(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
: base(delegateType, binder, arg0, arg1, arg2)
{
- _retType = retType;
+ Type = retType;
}
- public sealed override Type Type
- {
- get { return _retType; }
- }
+ public sealed override Type Type { get; }
}
internal class DynamicExpression4 : DynamicExpression, IArgumentProvider
@@ -731,13 +664,7 @@ namespace System.Linq.Expressions
}
}
- int IArgumentProvider.ArgumentCount
- {
- get
- {
- return 4;
- }
- }
+ int IArgumentProvider.ArgumentCount => 4;
internal override ReadOnlyCollection<Expression> GetOrMakeArguments()
{
@@ -754,18 +681,13 @@ namespace System.Linq.Expressions
internal sealed class TypedDynamicExpression4 : DynamicExpression4
{
- private readonly Type _retType;
-
internal TypedDynamicExpression4(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
: base(delegateType, binder, arg0, arg1, arg2, arg3)
{
- _retType = retType;
+ Type = retType;
}
- public sealed override Type Type
- {
- get { return _retType; }
- }
+ public sealed override Type Type { get; }
}
#endregion
@@ -1168,33 +1090,35 @@ namespace System.Linq.Expressions
ContractUtils.RequiresNotNull(returnType, nameof(returnType));
var args = arguments.ToReadOnly();
- ContractUtils.RequiresNotEmpty(args, nameof(args));
+ ContractUtils.RequiresNotEmpty(args, nameof(arguments));
return MakeDynamic(binder, returnType, args);
}
- private static DynamicExpression MakeDynamic(CallSiteBinder binder, Type returnType, ReadOnlyCollection<Expression> args)
+ private static DynamicExpression MakeDynamic(CallSiteBinder binder, Type returnType, ReadOnlyCollection<Expression> arguments)
{
ContractUtils.RequiresNotNull(binder, nameof(binder));
- for (int i = 0; i < args.Count; i++)
+ int n = arguments.Count;
+
+ for (int i = 0; i < n; i++)
{
- Expression arg = args[i];
+ Expression arg = arguments[i];
- ValidateDynamicArgument(arg, "arguments", i);
+ ValidateDynamicArgument(arg, nameof(arguments), i);
}
- Type delegateType = DelegateHelpers.MakeCallSiteDelegate(args, returnType);
+ Type delegateType = DelegateHelpers.MakeCallSiteDelegate(arguments, returnType);
// Since we made a delegate with argument types that exactly match,
// we can skip delegate and argument validation
- switch (args.Count)
+ switch (n)
{
- case 1: return DynamicExpression.Make(returnType, delegateType, binder, args[0]);
- case 2: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1]);
- case 3: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2]);
- case 4: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2], args[3]);
- default: return DynamicExpression.Make(returnType, delegateType, binder, args);
+ case 1: return DynamicExpression.Make(returnType, delegateType, binder, arguments[0]);
+ case 2: return DynamicExpression.Make(returnType, delegateType, binder, arguments[0], arguments[1]);
+ case 3: return DynamicExpression.Make(returnType, delegateType, binder, arguments[0], arguments[1], arguments[2]);
+ case 4: return DynamicExpression.Make(returnType, delegateType, binder, arguments[0], arguments[1], arguments[2], arguments[3]);
+ default: return DynamicExpression.Make(returnType, delegateType, binder, arguments);
}
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Error.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Error.cs
index 8210ef62c5..56dccfc19f 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Error.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Error.cs
@@ -44,7 +44,7 @@ namespace System.Linq.Expressions
/// </summary>
internal static Exception SameKeyExistsInExpando(object p0)
{
- return new ArgumentException(Strings.SameKeyExistsInExpando(p0));
+ return new ArgumentException(Strings.SameKeyExistsInExpando(p0), "key");
}
/// <summary>
/// System.Collections.Generic.KeyNotFoundException with message like "The specified key '{0}' does not exist in the ExpandoObject."
@@ -223,6 +223,15 @@ namespace System.Linq.Expressions
{
return new ArgumentException(Strings.SetterMustBeVoid, paramName);
}
+
+ /// <summary>
+ /// ArgumentException with message like "Property type must match the value type of getter"
+ /// </summary>
+ internal static Exception PropertyTypeMustMatchGetter(string paramName)
+ {
+ return new ArgumentException(Strings.PropertyTypeMustMatchGetter, paramName);
+ }
+
/// <summary>
/// ArgumentException with message like "Property type must match the value type of setter"
/// </summary>
@@ -553,7 +562,7 @@ namespace System.Linq.Expressions
return ArgumentMustBeArrayIndexType(GetParamName(paramName, index));
}
/// <summary>
- /// ArgumentException with message like "Argument must be single dimensional array type"
+ /// ArgumentException with message like "Argument must be single-dimensional, zero-based array type"
/// </summary>
internal static Exception ArgumentMustBeSingleDimensionalArrayType(string paramName)
{
@@ -864,9 +873,9 @@ namespace System.Linq.Expressions
/// <summary>
/// ArgumentException with message like "Instance property '{0}{1}' is not defined for type '{2}'"
/// </summary>
- internal static Exception InstancePropertyWithSpecifiedParametersNotDefinedForType(object p0, object p1, object p2)
+ internal static Exception InstancePropertyWithSpecifiedParametersNotDefinedForType(object p0, object p1, object p2, string paramName)
{
- return new ArgumentException(Strings.InstancePropertyWithSpecifiedParametersNotDefinedForType(p0, p1, p2));
+ return new ArgumentException(Strings.InstancePropertyWithSpecifiedParametersNotDefinedForType(p0, p1, p2), paramName);
}
/// <summary>
/// ArgumentException with message like "Method '{0}' declared on type '{1}' cannot be called with instance of type '{2}'"
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/ExpressionStringBuilder.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/ExpressionStringBuilder.cs
index dd5385bd36..ccf312ea37 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/ExpressionStringBuilder.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/ExpressionStringBuilder.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
@@ -115,12 +116,12 @@ namespace System.Linq.Expressions
return esb.ToString();
}
- private void VisitExpressions<T>(char open, IReadOnlyList<T> expressions, char close) where T : Expression
+ private void VisitExpressions<T>(char open, ReadOnlyCollection<T> expressions, char close) where T : Expression
{
VisitExpressions(open, expressions, close, ", ");
}
- private void VisitExpressions<T>(char open, IReadOnlyList<T> expressions, char close, string seperator) where T : Expression
+ private void VisitExpressions<T>(char open, ReadOnlyCollection<T> expressions, char close, string seperator) where T : Expression
{
Out(open);
if (expressions != null)
@@ -508,7 +509,7 @@ namespace System.Linq.Expressions
Out("new ");
Out(node.Type.Name);
Out('(');
- Collections.ObjectModel.ReadOnlyCollection<MemberInfo> members = node.Members;
+ ReadOnlyCollection<MemberInfo> members = node.Members;
for (int i = 0; i < node.ArgumentCount; i++)
{
if (i > 0)
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/IndexExpression.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/IndexExpression.cs
index d1a196ca29..a5788d84e3 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/IndexExpression.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/IndexExpression.cs
@@ -210,7 +210,7 @@ namespace System.Linq.Expressions
RequiresCanRead(instance, nameof(instance));
ContractUtils.RequiresNotNull(propertyName, nameof(propertyName));
PropertyInfo pi = FindInstanceProperty(instance.Type, propertyName, arguments);
- return Property(instance, pi, arguments);
+ return MakeIndexProperty(instance, pi, nameof(propertyName), arguments.ToReadOnly());
}
#region methods for finding a PropertyInfo by its name
@@ -237,7 +237,7 @@ namespace System.Linq.Expressions
}
else
{
- throw Error.InstancePropertyWithSpecifiedParametersNotDefinedForType(propertyName, GetArgTypesString(arguments), type);
+ throw Error.InstancePropertyWithSpecifiedParametersNotDefinedForType(propertyName, GetArgTypesString(arguments), type, nameof(propertyName));
}
}
return pi;
@@ -253,7 +253,7 @@ namespace System.Linq.Expressions
{
argTypesStr.Append(", ");
}
- argTypesStr.Append(arguments[i].Type.Name);
+ argTypesStr.Append(arguments[i]?.Type.Name);
}
argTypesStr.Append(')');
return argTypesStr.ToString();
@@ -292,15 +292,20 @@ namespace System.Linq.Expressions
else
{
mi = pi.GetSetMethod(nonPublic: true);
+ if (mi == null)
+ {
+ return false;
+ }
//The setter has an additional parameter for the value to set,
//need to remove the last type to match the arguments.
- parms = mi.GetParametersCached().RemoveLast();
+ parms = mi.GetParametersCached();
+ if (parms.Length == 0)
+ {
+ return false;
+ }
+ parms = parms.RemoveLast();
}
- if (mi == null)
- {
- return false;
- }
if (args == null)
{
return parms.Length == 0;
@@ -340,10 +345,12 @@ namespace System.Linq.Expressions
/// <param name="indexer">The <see cref="PropertyInfo"/> that represents the property to index.</param>
/// <param name="arguments">An <see cref="IEnumerable{T}"/> of <see cref="Expression"/> objects that are used to index the property.</param>
/// <returns>The created <see cref="IndexExpression"/>.</returns>
- public static IndexExpression Property(Expression instance, PropertyInfo indexer, IEnumerable<Expression> arguments)
+ public static IndexExpression Property(Expression instance, PropertyInfo indexer, IEnumerable<Expression> arguments) =>
+ MakeIndexProperty(instance, indexer, nameof(indexer), arguments.ToReadOnly());
+
+ private static IndexExpression MakeIndexProperty(Expression instance, PropertyInfo indexer, string paramName, ReadOnlyCollection<Expression> argList)
{
- ReadOnlyCollection<Expression> argList = arguments.ToReadOnly();
- ValidateIndexedProperty(instance, indexer, ref argList);
+ ValidateIndexedProperty(instance, indexer, paramName, ref argList);
return new IndexExpression(instance, indexer, argList);
}
@@ -352,29 +359,34 @@ namespace System.Linq.Expressions
//
// Does reflection help us out at all? Expression.Property skips all of
// these checks, so either it needs more checks or we need less here.
- private static void ValidateIndexedProperty(Expression instance, PropertyInfo indexer, ref ReadOnlyCollection<Expression> argList)
+ private static void ValidateIndexedProperty(Expression instance, PropertyInfo indexer, string paramName, ref ReadOnlyCollection<Expression> argList)
{
// If both getter and setter specified, all their parameter types
// should match, with exception of the last setter parameter which
// should match the type returned by the get method.
// Accessor parameters cannot be ByRef.
- ContractUtils.RequiresNotNull(indexer, nameof(indexer));
+ ContractUtils.RequiresNotNull(indexer, paramName);
if (indexer.PropertyType.IsByRef)
{
- throw Error.PropertyCannotHaveRefType(nameof(indexer));
+ throw Error.PropertyCannotHaveRefType(paramName);
}
if (indexer.PropertyType == typeof(void))
{
- throw Error.PropertyTypeCannotBeVoid(nameof(indexer));
+ throw Error.PropertyTypeCannotBeVoid(paramName);
}
ParameterInfo[] getParameters = null;
MethodInfo getter = indexer.GetGetMethod(nonPublic: true);
if (getter != null)
{
+ if (getter.ReturnType != indexer.PropertyType)
+ {
+ throw Error.PropertyTypeMustMatchGetter(paramName);
+ }
+
getParameters = getter.GetParametersCached();
- ValidateAccessor(instance, getter, getParameters, ref argList, nameof(indexer));
+ ValidateAccessor(instance, getter, getParameters, ref argList, paramName);
}
MethodInfo setter = indexer.GetSetMethod(nonPublic: true);
@@ -383,52 +395,51 @@ namespace System.Linq.Expressions
ParameterInfo[] setParameters = setter.GetParametersCached();
if (setParameters.Length == 0)
{
- throw Error.SetterHasNoParams(nameof(indexer));
+ throw Error.SetterHasNoParams(paramName);
}
// valueType is the type of the value passed to the setter (last parameter)
Type valueType = setParameters[setParameters.Length - 1].ParameterType;
if (valueType.IsByRef)
{
- throw Error.PropertyCannotHaveRefType(nameof(indexer));
+ throw Error.PropertyCannotHaveRefType(paramName);
}
if (setter.ReturnType != typeof(void))
{
- throw Error.SetterMustBeVoid(nameof(indexer));
+ throw Error.SetterMustBeVoid(paramName);
}
if (indexer.PropertyType != valueType)
{
- throw Error.PropertyTypeMustMatchSetter(nameof(indexer));
+ throw Error.PropertyTypeMustMatchSetter(paramName);
}
if (getter != null)
{
if (getter.IsStatic ^ setter.IsStatic)
{
- throw Error.BothAccessorsMustBeStatic(nameof(indexer));
+ throw Error.BothAccessorsMustBeStatic(paramName);
}
if (getParameters.Length != setParameters.Length - 1)
{
- throw Error.IndexesOfSetGetMustMatch(nameof(indexer));
+ throw Error.IndexesOfSetGetMustMatch(paramName);
}
for (int i = 0; i < getParameters.Length; i++)
{
if (getParameters[i].ParameterType != setParameters[i].ParameterType)
{
- throw Error.IndexesOfSetGetMustMatch(nameof(indexer));
+ throw Error.IndexesOfSetGetMustMatch(paramName);
}
}
}
else
{
- ValidateAccessor(instance, setter, setParameters.RemoveLast(), ref argList, nameof(indexer));
+ ValidateAccessor(instance, setter, setParameters.RemoveLast(), ref argList, paramName);
}
}
-
- if (getter == null && setter == null)
+ else if (getter == null)
{
- throw Error.PropertyDoesNotHaveAccessor(indexer, nameof(indexer));
+ throw Error.PropertyDoesNotHaveAccessor(indexer, paramName);
}
}
@@ -437,14 +448,25 @@ namespace System.Linq.Expressions
ContractUtils.RequiresNotNull(arguments, nameof(arguments));
ValidateMethodInfo(method, nameof(method));
- if ((method.CallingConvention & CallingConventions.VarArgs) != 0) throw Error.AccessorsCannotHaveVarArgs(nameof(method));
+ if ((method.CallingConvention & CallingConventions.VarArgs) != 0)
+ {
+ throw Error.AccessorsCannotHaveVarArgs(paramName);
+ }
+
if (method.IsStatic)
{
- if (instance != null) throw Error.OnlyStaticMethodsHaveNullInstance();
+ if (instance != null)
+ {
+ throw Error.OnlyStaticPropertiesHaveNullInstance(nameof(instance));
+ }
}
else
{
- if (instance == null) throw Error.OnlyStaticMethodsHaveNullInstance();
+ if (instance == null)
+ {
+ throw Error.OnlyStaticPropertiesHaveNullInstance(nameof(instance));
+ }
+
RequiresCanRead(instance, nameof(instance));
ValidateCallInstanceType(instance.Type, method);
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AddInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AddInstruction.cs
index aa909f74a2..b508a4555e 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AddInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AddInstruction.cs
@@ -9,7 +9,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class AddInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -17,7 +17,7 @@ namespace System.Linq.Expressions.Interpreter
private AddInstruction() { }
- private sealed class AddInt32 : AddInstruction
+ private sealed class AddInt16 : AddInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -29,14 +29,14 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(unchecked((int)l + (int)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((short)((short)l + (short)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
- private sealed class AddInt16 : AddInstruction
+ private sealed class AddInt32 : AddInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -48,10 +48,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((short)((short)l + (short)r));
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(unchecked((int)l + (int)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -67,10 +67,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((long)((long)l + (long)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((long)l + (long)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -89,7 +89,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Data[frame.StackIndex - 2] = unchecked((ushort)((ushort)l + (ushort)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -105,10 +105,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((uint)((uint)l + (uint)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((uint)l + (uint)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -124,10 +124,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((ulong)((ulong)l + (ulong)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((ulong)l + (ulong)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -143,10 +143,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = (float)((float)l + (float)r);
+ frame.Data[frame.StackIndex - 2] = (float)l + (float)r;
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -165,7 +165,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Data[frame.StackIndex - 2] = (double)l + (double)r;
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -174,14 +174,14 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(type.IsArithmetic());
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new AddInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new AddInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new AddInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new AddInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new AddInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new AddInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new AddUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new AddUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new AddUInt64());
- case TypeCode.Single: return s_single ?? (s_single = new AddSingle());
- case TypeCode.Double: return s_double ?? (s_double = new AddDouble());
+ case TypeCode.Single: return s_Single ?? (s_Single = new AddSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new AddDouble());
default:
throw ContractUtils.Unreachable;
}
@@ -190,7 +190,7 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class AddOvfInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -198,7 +198,7 @@ namespace System.Linq.Expressions.Interpreter
private AddOvfInstruction() { }
- private sealed class AddOvfInt32 : AddOvfInstruction
+ private sealed class AddOvfInt16 : AddOvfInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -210,14 +210,14 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(checked((int)l + (int)r));
+ frame.Data[frame.StackIndex - 2] = checked((short)((short)l + (short)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
- private sealed class AddOvfInt16 : AddOvfInstruction
+ private sealed class AddOvfInt32 : AddOvfInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -229,10 +229,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((short)((short)l + (short)r));
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(checked((int)l + (int)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -248,10 +248,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((long)((long)l + (long)r));
+ frame.Data[frame.StackIndex - 2] = checked((long)l + (long)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -270,7 +270,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Data[frame.StackIndex - 2] = checked((ushort)((ushort)l + (ushort)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -286,10 +286,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((uint)((uint)l + (uint)r));
+ frame.Data[frame.StackIndex - 2] = checked((uint)l + (uint)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -305,10 +305,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((ulong)((ulong)l + (ulong)r));
+ frame.Data[frame.StackIndex - 2] = checked((ulong)l + (ulong)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -317,13 +317,12 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(type.IsArithmetic());
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new AddOvfInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new AddOvfInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new AddOvfInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new AddOvfInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new AddOvfInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new AddOvfInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new AddOvfUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new AddOvfUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new AddOvfUInt64());
-
default:
return AddInstruction.Create(type);
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AndInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AndInstruction.cs
index 70453a0618..c536a3e528 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AndInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/AndInstruction.cs
@@ -9,7 +9,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class AndInstruction : Instruction
{
- private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_bool;
+ private static Instruction s_SByte, s_Int16, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Boolean;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -26,10 +26,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((sbyte)(((sbyte)left) & ((sbyte)right)));
- return +1;
+ frame.Push((sbyte)((sbyte)left & (sbyte)right));
+ return 1;
}
}
@@ -42,10 +42,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((short)(((short)left) & ((short)right)));
- return +1;
+ frame.Push((short)((short)left & (short)right));
+ return 1;
}
}
@@ -58,10 +58,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((int)left) & ((int)right));
- return +1;
+ frame.Push((int)left & (int)right);
+ return 1;
}
}
@@ -74,10 +74,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((long)left) & ((long)right));
- return +1;
+ frame.Push((long)left & (long)right);
+ return 1;
}
}
@@ -90,10 +90,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((byte)(((byte)left) & ((byte)right)));
- return +1;
+ frame.Push((byte)((byte)left & (byte)right));
+ return 1;
}
}
@@ -106,10 +106,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((ushort)(((ushort)left) & ((ushort)right)));
- return +1;
+ frame.Push((ushort)((ushort)left & (ushort)right));
+ return 1;
}
}
@@ -122,10 +122,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((uint)left) & ((uint)right));
- return +1;
+ frame.Push((uint)left & (uint)right);
+ return 1;
}
}
@@ -138,14 +138,14 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((ulong)left) & ((ulong)right));
- return +1;
+ frame.Push((ulong)left & (ulong)right);
+ return 1;
}
}
- private sealed class AndBool : AndInstruction
+ private sealed class AndBoolean : AndInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -161,15 +161,15 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((bool)right ? null : Utils.BoxedFalse);
}
- return +1;
+ return 1;
}
else if (right == null)
{
frame.Push((bool)left ? null : Utils.BoxedFalse);
- return +1;
+ return 1;
}
- frame.Push(((bool)left) & ((bool)right));
- return +1;
+ frame.Push((bool)left & (bool)right);
+ return 1;
}
}
@@ -182,15 +182,14 @@ namespace System.Linq.Expressions.Interpreter
switch (underlyingType.GetTypeCode())
{
case TypeCode.SByte: return s_SByte ?? (s_SByte = new AndSByte());
- case TypeCode.Byte: return s_byte ?? (s_byte = new AndByte());
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new AndInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new AndInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new AndInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new AndInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new AndInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new AndInt64());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new AndByte());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new AndUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new AndUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new AndUInt64());
- case TypeCode.Boolean: return s_bool ?? (s_bool = new AndBool());
-
+ case TypeCode.Boolean: return s_Boolean ?? (s_Boolean = new AndBoolean());
default:
throw Error.ExpressionNotSupportedForType("And", type);
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ArrayOperations.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ArrayOperations.cs
index ca26e04eae..7ae8fb944e 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ArrayOperations.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ArrayOperations.cs
@@ -27,7 +27,7 @@ namespace System.Linq.Expressions.Interpreter
array.SetValue(frame.Pop(), i);
}
frame.Push(array);
- return +1;
+ return 1;
}
}
@@ -53,7 +53,7 @@ namespace System.Linq.Expressions.Interpreter
throw new OverflowException();
}
frame.Push(Array.CreateInstance(_elementType, length));
- return +1;
+ return 1;
}
}
@@ -89,7 +89,7 @@ namespace System.Linq.Expressions.Interpreter
}
Array array = Array.CreateInstance(_elementType, lengths);
frame.Push(array);
- return +1;
+ return 1;
}
}
@@ -108,7 +108,7 @@ namespace System.Linq.Expressions.Interpreter
int index = ConvertHelper.ToInt32NoNull(frame.Pop());
Array array = (Array)frame.Pop();
frame.Push(array.GetValue(index));
- return +1;
+ return 1;
}
}
@@ -128,7 +128,7 @@ namespace System.Linq.Expressions.Interpreter
int index = ConvertHelper.ToInt32NoNull(frame.Pop());
Array array = (Array)frame.Pop();
array.SetValue(value, index);
- return +1;
+ return 1;
}
}
@@ -146,7 +146,7 @@ namespace System.Linq.Expressions.Interpreter
{
object obj = frame.Pop();
frame.Push(((Array)obj).Length);
- return +1;
+ return 1;
}
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs
index bfcc444763..469810d56c 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs
@@ -28,7 +28,7 @@ namespace System.Linq.Expressions.Interpreter
public static CallInstruction Create(MethodInfo info)
{
- return Create(info, info.GetParameters());
+ return Create(info, info.GetParametersCached());
}
/// <summary>
@@ -247,7 +247,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
}
#endif
@@ -329,7 +330,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
}
else
@@ -353,7 +355,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
}
}
@@ -425,7 +428,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
}
else
@@ -449,7 +453,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
}
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ControlFlowInstructions.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ControlFlowInstructions.cs
index 48054cebc2..90efb83c78 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ControlFlowInstructions.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ControlFlowInstructions.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Dynamic.Utils;
using System.Reflection;
using System.Runtime.CompilerServices;
@@ -75,7 +76,7 @@ namespace System.Linq.Expressions.Interpreter
return _offset;
}
- return +1;
+ return 1;
}
}
@@ -109,7 +110,7 @@ namespace System.Linq.Expressions.Interpreter
return _offset;
}
- return +1;
+ return 1;
}
}
@@ -144,7 +145,7 @@ namespace System.Linq.Expressions.Interpreter
return _offset;
}
- return +1;
+ return 1;
}
}
@@ -523,7 +524,7 @@ namespace System.Linq.Expressions.Interpreter
/// </summary>
internal sealed class EnterFinallyInstruction : IndexedBranchInstruction
{
- private readonly static EnterFinallyInstruction[] s_cache = new EnterFinallyInstruction[CacheSize];
+ private static readonly EnterFinallyInstruction[] s_cache = new EnterFinallyInstruction[CacheSize];
private EnterFinallyInstruction(int labelIndex)
: base(labelIndex)
@@ -585,7 +586,7 @@ namespace System.Linq.Expressions.Interpreter
internal sealed class EnterFaultInstruction : IndexedBranchInstruction
{
- private readonly static EnterFaultInstruction[] s_cache = new EnterFaultInstruction[CacheSize];
+ private static readonly EnterFaultInstruction[] s_cache = new EnterFaultInstruction[CacheSize];
private EnterFaultInstruction(int labelIndex)
: base(labelIndex)
@@ -787,7 +788,7 @@ namespace System.Linq.Expressions.Interpreter
ConstructorInfo ctor = _runtimeWrappedExceptionCtor
?? (_runtimeWrappedExceptionCtor = typeof(RuntimeWrappedException)
.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)
- .First(c => c.GetParameters().Length == 1));
+ .First(c => c.GetParametersCached().Length == 1));
return (RuntimeWrappedException)ctor.Invoke(new [] {thrown});
}
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DecrementInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DecrementInstruction.cs
index b8aa4ce761..48109c83e8 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DecrementInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DecrementInstruction.cs
@@ -10,7 +10,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class DecrementInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
public override int ConsumedStack => 1;
public override int ProducedStack => 1;
@@ -18,7 +18,7 @@ namespace System.Linq.Expressions.Interpreter
private DecrementInstruction() { }
- private sealed class DecrementInt32 : DecrementInstruction
+ private sealed class DecrementInt16 : DecrementInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -29,13 +29,13 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(ScriptingRuntimeHelpers.Int32ToObject(unchecked((int)obj - 1)));
+ frame.Push(unchecked((short)((short)obj - 1)));
}
- return +1;
+ return 1;
}
}
- private sealed class DecrementInt16 : DecrementInstruction
+ private sealed class DecrementInt32 : DecrementInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -46,9 +46,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((short)((short)obj - 1)));
+ frame.Push(unchecked((int)obj - 1));
}
- return +1;
+ return 1;
}
}
@@ -63,9 +63,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((long)((long)obj - 1)));
+ frame.Push(unchecked((long)obj - 1));
}
- return +1;
+ return 1;
}
}
@@ -82,7 +82,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push(unchecked((ushort)((ushort)obj - 1)));
}
- return +1;
+ return 1;
}
}
@@ -97,9 +97,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((uint)((uint)obj - 1)));
+ frame.Push(unchecked((uint)obj - 1));
}
- return +1;
+ return 1;
}
}
@@ -114,9 +114,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((ulong)((ulong)obj - 1)));
+ frame.Push(unchecked((ulong)obj - 1));
}
- return +1;
+ return 1;
}
}
@@ -131,9 +131,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((float)((float)obj - 1)));
+ frame.Push(unchecked((float)obj - 1));
}
- return +1;
+ return 1;
}
}
@@ -148,9 +148,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((double)((double)obj - 1)));
+ frame.Push(unchecked((double)obj - 1));
}
- return +1;
+ return 1;
}
}
@@ -159,18 +159,17 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(!type.GetTypeInfo().IsEnum);
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new DecrementInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new DecrementInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new DecrementInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new DecrementInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new DecrementInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new DecrementInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new DecrementUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new DecrementUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new DecrementUInt64());
- case TypeCode.Single: return s_single ?? (s_single = new DecrementSingle());
- case TypeCode.Double: return s_double ?? (s_double = new DecrementDouble());
-
+ case TypeCode.Single: return s_Single ?? (s_Single = new DecrementSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new DecrementDouble());
default:
throw Error.ExpressionNotSupportedForType("Decrement", type);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DefaultValueInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DefaultValueInstruction.cs
index 9b5fe4c296..14499ca59e 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DefaultValueInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DefaultValueInstruction.cs
@@ -23,9 +23,9 @@ namespace System.Linq.Expressions.Interpreter
{
object value = _type.GetTypeInfo().IsValueType ? Activator.CreateInstance(_type) : null;
frame.Push(value);
- return +1;
+ return 1;
}
- public override string ToString() => "New " + _type;
+ public override string ToString() => "DefaultValue " + _type;
}
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DivInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DivInstruction.cs
index e3f8295d51..3aaaaaba79 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DivInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DivInstruction.cs
@@ -10,7 +10,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class DivInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -18,7 +18,7 @@ namespace System.Linq.Expressions.Interpreter
private DivInstruction() { }
- private sealed class DivInt32 : DivInstruction
+ private sealed class DivInt16 : DivInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -30,14 +30,14 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject((int)l / (int)r);
+ frame.Data[frame.StackIndex - 2] = (short)((short)l / (short)r);
}
frame.StackIndex--;
return 1;
}
}
- private sealed class DivInt16 : DivInstruction
+ private sealed class DivInt32 : DivInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -49,7 +49,7 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = (short)((short)l / (short)r);
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject((int)l / (int)r);
}
frame.StackIndex--;
return 1;
@@ -68,7 +68,7 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = (long)((long)l / (long)r);
+ frame.Data[frame.StackIndex - 2] = (long)l / (long)r;
}
frame.StackIndex--;
return 1;
@@ -106,7 +106,7 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = (uint)((uint)l / (uint)r);
+ frame.Data[frame.StackIndex - 2] = (uint)l / (uint)r;
}
frame.StackIndex--;
return 1;
@@ -125,7 +125,7 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = (ulong)((ulong)l / (ulong)r);
+ frame.Data[frame.StackIndex - 2] = (ulong)l / (ulong)r;
}
frame.StackIndex--;
return 1;
@@ -144,7 +144,7 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = (float)((float)l / (float)r);
+ frame.Data[frame.StackIndex - 2] = (float)l / (float)r;
}
frame.StackIndex--;
return 1;
@@ -175,200 +175,17 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(!type.GetTypeInfo().IsEnum);
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new DivInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new DivInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new DivInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new DivInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new DivInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new DivInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new DivUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new DivUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new DivUInt64());
- case TypeCode.Single: return s_single ?? (s_single = new DivSingle());
- case TypeCode.Double: return s_double ?? (s_double = new DivDouble());
-
+ case TypeCode.Single: return s_Single ?? (s_Single = new DivSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new DivDouble());
default:
throw Error.ExpressionNotSupportedForType("Div", type);
}
}
}
-
- internal abstract class ModuloInstruction : Instruction
- {
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
-
- public override int ConsumedStack => 2;
- public override int ProducedStack => 1;
- public override string InstructionName => "Modulo";
-
- private ModuloInstruction() { }
-
- private sealed class ModuloInt32 : ModuloInstruction
- {
- public override int Run(InterpretedFrame frame)
- {
- object l = frame.Data[frame.StackIndex - 2];
- object r = frame.Data[frame.StackIndex - 1];
- if (l == null || r == null)
- {
- frame.Data[frame.StackIndex - 2] = null;
- }
- else
- {
- frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject((int)l % (int)r);
- }
- frame.StackIndex--;
- return 1;
- }
- }
-
- private sealed class ModuloInt16 : ModuloInstruction
- {
- public override int Run(InterpretedFrame frame)
- {
- object l = frame.Data[frame.StackIndex - 2];
- object r = frame.Data[frame.StackIndex - 1];
- if (l == null || r == null)
- {
- frame.Data[frame.StackIndex - 2] = null;
- }
- else
- {
- frame.Data[frame.StackIndex - 2] = (short)((short)l % (short)r);
- }
- frame.StackIndex--;
- return 1;
- }
- }
-
- private sealed class ModuloInt64 : ModuloInstruction
- {
- public override int Run(InterpretedFrame frame)
- {
- object l = frame.Data[frame.StackIndex - 2];
- object r = frame.Data[frame.StackIndex - 1];
- if (l == null || r == null)
- {
- frame.Data[frame.StackIndex - 2] = null;
- }
- else
- {
- frame.Data[frame.StackIndex - 2] = (long)((long)l % (long)r);
- }
- frame.StackIndex--;
- return 1;
- }
- }
-
- private sealed class ModuloUInt16 : ModuloInstruction
- {
- public override int Run(InterpretedFrame frame)
- {
- object l = frame.Data[frame.StackIndex - 2];
- object r = frame.Data[frame.StackIndex - 1];
- if (l == null || r == null)
- {
- frame.Data[frame.StackIndex - 2] = null;
- }
- else
- {
- frame.Data[frame.StackIndex - 2] = (ushort)((ushort)l % (ushort)r);
- }
- frame.StackIndex--;
- return 1;
- }
- }
-
- private sealed class ModuloUInt32 : ModuloInstruction
- {
- public override int Run(InterpretedFrame frame)
- {
- object l = frame.Data[frame.StackIndex - 2];
- object r = frame.Data[frame.StackIndex - 1];
- if (l == null || r == null)
- {
- frame.Data[frame.StackIndex - 2] = null;
- }
- else
- {
- frame.Data[frame.StackIndex - 2] = (uint)((uint)l % (uint)r);
- }
- frame.StackIndex--;
- return 1;
- }
- }
-
- private sealed class ModuloUInt64 : ModuloInstruction
- {
- public override int Run(InterpretedFrame frame)
- {
- object l = frame.Data[frame.StackIndex - 2];
- object r = frame.Data[frame.StackIndex - 1];
- if (l == null || r == null)
- {
- frame.Data[frame.StackIndex - 2] = null;
- }
- else
- {
- frame.Data[frame.StackIndex - 2] = (ulong)((ulong)l % (ulong)r);
- }
- frame.StackIndex--;
- return 1;
- }
- }
-
- private sealed class ModuloSingle : ModuloInstruction
- {
- public override int Run(InterpretedFrame frame)
- {
- object l = frame.Data[frame.StackIndex - 2];
- object r = frame.Data[frame.StackIndex - 1];
- if (l == null || r == null)
- {
- frame.Data[frame.StackIndex - 2] = null;
- }
- else
- {
- frame.Data[frame.StackIndex - 2] = (float)((float)l % (float)r);
- }
- frame.StackIndex--;
- return 1;
- }
- }
-
- private sealed class ModuloDouble : ModuloInstruction
- {
- public override int Run(InterpretedFrame frame)
- {
- object l = frame.Data[frame.StackIndex - 2];
- object r = frame.Data[frame.StackIndex - 1];
- if (l == null || r == null)
- {
- frame.Data[frame.StackIndex - 2] = null;
- }
- else
- {
- frame.Data[frame.StackIndex - 2] = (double)l % (double)r;
- }
- frame.StackIndex--;
- return 1;
- }
- }
-
- public static Instruction Create(Type type)
- {
- Debug.Assert(!type.GetTypeInfo().IsEnum);
- switch (type.GetNonNullableType().GetTypeCode())
- {
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new ModuloInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new ModuloInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new ModuloInt64());
- case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new ModuloUInt16());
- case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new ModuloUInt32());
- case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new ModuloUInt64());
- case TypeCode.Single: return s_single ?? (s_single = new ModuloSingle());
- case TypeCode.Double: return s_double ?? (s_double = new ModuloDouble());
-
- default:
- throw Error.ExpressionNotSupportedForType("Modulo", type);
- }
- }
- }
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/EqualInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/EqualInstruction.cs
index 35121b2328..f4c85a77d1 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/EqualInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/EqualInstruction.cs
@@ -11,8 +11,8 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class EqualInstruction : Instruction
{
// Perf: EqualityComparer<T> but is 3/2 to 2 times slower.
- private static Instruction s_reference, s_boolean, s_SByte, s_int16, s_char, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
- private static Instruction s_booleanLiftedToNull, s_SByteLiftedToNull, s_int16LiftedToNull, s_charLiftedToNull, s_int32LiftedToNull, s_int64LiftedToNull, s_byteLiftedToNull, s_UInt16LiftedToNull, s_UInt32LiftedToNull, s_UInt64LiftedToNull, s_singleLiftedToNull, s_doubleLiftedToNull;
+ private static Instruction s_reference, s_Boolean, s_SByte, s_Int16, s_Char, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
+ private static Instruction s_BooleanLiftedToNull, s_SByteLiftedToNull, s_Int16LiftedToNull, s_CharLiftedToNull, s_Int32LiftedToNull, s_Int64LiftedToNull, s_ByteLiftedToNull, s_UInt16LiftedToNull, s_UInt32LiftedToNull, s_UInt64LiftedToNull, s_SingleLiftedToNull, s_DoubleLiftedToNull;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -38,7 +38,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((bool)left == (bool)right);
}
- return +1;
+ return 1;
}
}
@@ -60,7 +60,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((sbyte)left == (sbyte)right);
}
- return +1;
+ return 1;
}
}
@@ -82,7 +82,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((short)left == (short)right);
}
- return +1;
+ return 1;
}
}
@@ -104,7 +104,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((char)left == (char)right);
}
- return +1;
+ return 1;
}
}
@@ -126,7 +126,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((int)left == (int)right);
}
- return +1;
+ return 1;
}
}
@@ -148,7 +148,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((long)left == (long)right);
}
- return +1;
+ return 1;
}
}
@@ -170,7 +170,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((byte)left == (byte)right);
}
- return +1;
+ return 1;
}
}
@@ -192,7 +192,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ushort)left == (ushort)right);
}
- return +1;
+ return 1;
}
}
@@ -214,7 +214,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((uint)left == (uint)right);
}
- return +1;
+ return 1;
}
}
@@ -236,7 +236,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ulong)left == (ulong)right);
}
- return +1;
+ return 1;
}
}
@@ -258,7 +258,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((float)left == (float)right);
}
- return +1;
+ return 1;
}
}
@@ -280,7 +280,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((double)left == (double)right);
}
- return +1;
+ return 1;
}
}
@@ -289,7 +289,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Push(frame.Pop() == frame.Pop());
- return +1;
+ return 1;
}
}
@@ -307,7 +307,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((bool)left == (bool)right);
}
- return +1;
+ return 1;
}
}
@@ -325,7 +325,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((sbyte)left == (sbyte)right);
}
- return +1;
+ return 1;
}
}
@@ -343,7 +343,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((short)left == (short)right);
}
- return +1;
+ return 1;
}
}
@@ -361,7 +361,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((char)left == (char)right);
}
- return +1;
+ return 1;
}
}
@@ -379,7 +379,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((int)left == (int)right);
}
- return +1;
+ return 1;
}
}
@@ -397,7 +397,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((long)left == (long)right);
}
- return +1;
+ return 1;
}
}
@@ -415,7 +415,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((byte)left == (byte)right);
}
- return +1;
+ return 1;
}
}
@@ -433,7 +433,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ushort)left == (ushort)right);
}
- return +1;
+ return 1;
}
}
@@ -451,7 +451,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((uint)left == (uint)right);
}
- return +1;
+ return 1;
}
}
@@ -469,7 +469,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ulong)left == (ulong)right);
}
- return +1;
+ return 1;
}
}
@@ -487,7 +487,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((float)left == (float)right);
}
- return +1;
+ return 1;
}
}
@@ -505,7 +505,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((double)left == (double)right);
}
- return +1;
+ return 1;
}
}
@@ -519,48 +519,42 @@ namespace System.Linq.Expressions.Interpreter
{
switch (underlyingType.GetTypeCode())
{
- case TypeCode.Boolean: return s_booleanLiftedToNull ?? (s_booleanLiftedToNull = new EqualBooleanLiftedToNull());
+ case TypeCode.Boolean: return s_BooleanLiftedToNull ?? (s_BooleanLiftedToNull = new EqualBooleanLiftedToNull());
case TypeCode.SByte: return s_SByteLiftedToNull ?? (s_SByteLiftedToNull = new EqualSByteLiftedToNull());
- case TypeCode.Byte: return s_byteLiftedToNull ?? (s_byteLiftedToNull = new EqualByteLiftedToNull());
- case TypeCode.Char: return s_charLiftedToNull ?? (s_charLiftedToNull = new EqualCharLiftedToNull());
- case TypeCode.Int16: return s_int16LiftedToNull ?? (s_int16LiftedToNull = new EqualInt16LiftedToNull());
- case TypeCode.Int32: return s_int32LiftedToNull ?? (s_int32LiftedToNull = new EqualInt32LiftedToNull());
- case TypeCode.Int64: return s_int64LiftedToNull ?? (s_int64LiftedToNull = new EqualInt64LiftedToNull());
-
+ case TypeCode.Int16: return s_Int16LiftedToNull ?? (s_Int16LiftedToNull = new EqualInt16LiftedToNull());
+ case TypeCode.Char: return s_CharLiftedToNull ?? (s_CharLiftedToNull = new EqualCharLiftedToNull());
+ case TypeCode.Int32: return s_Int32LiftedToNull ?? (s_Int32LiftedToNull = new EqualInt32LiftedToNull());
+ case TypeCode.Int64: return s_Int64LiftedToNull ?? (s_Int64LiftedToNull = new EqualInt64LiftedToNull());
+ case TypeCode.Byte: return s_ByteLiftedToNull ?? (s_ByteLiftedToNull = new EqualByteLiftedToNull());
case TypeCode.UInt16: return s_UInt16LiftedToNull ?? (s_UInt16LiftedToNull = new EqualUInt16LiftedToNull());
case TypeCode.UInt32: return s_UInt32LiftedToNull ?? (s_UInt32LiftedToNull = new EqualUInt32LiftedToNull());
case TypeCode.UInt64: return s_UInt64LiftedToNull ?? (s_UInt64LiftedToNull = new EqualUInt64LiftedToNull());
-
- case TypeCode.Single: return s_singleLiftedToNull ?? (s_singleLiftedToNull = new EqualSingleLiftedToNull());
+ case TypeCode.Single: return s_SingleLiftedToNull ?? (s_SingleLiftedToNull = new EqualSingleLiftedToNull());
default:
Debug.Assert(underlyingType.GetTypeCode() == TypeCode.Double);
- return s_doubleLiftedToNull ?? (s_doubleLiftedToNull = new EqualDoubleLiftedToNull());
+ return s_DoubleLiftedToNull ?? (s_DoubleLiftedToNull = new EqualDoubleLiftedToNull());
}
}
else
{
switch (underlyingType.GetTypeCode())
{
- case TypeCode.Boolean: return s_boolean ?? (s_boolean = new EqualBoolean());
+ case TypeCode.Boolean: return s_Boolean ?? (s_Boolean = new EqualBoolean());
case TypeCode.SByte: return s_SByte ?? (s_SByte = new EqualSByte());
- case TypeCode.Byte: return s_byte ?? (s_byte = new EqualByte());
- case TypeCode.Char: return s_char ?? (s_char = new EqualChar());
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new EqualInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new EqualInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new EqualInt64());
-
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new EqualInt16());
+ case TypeCode.Char: return s_Char ?? (s_Char = new EqualChar());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new EqualInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new EqualInt64());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new EqualByte());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new EqualUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new EqualUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new EqualUInt64());
-
- case TypeCode.Single: return s_single ?? (s_single = new EqualSingle());
- case TypeCode.Double: return s_double ?? (s_double = new EqualDouble());
-
+ case TypeCode.Single: return s_Single ?? (s_Single = new EqualSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new EqualDouble());
default:
// Nullable only valid if one operand is constant null, so this assert is slightly too broad.
Debug.Assert(type.IsNullableOrReferenceType());
return s_reference ?? (s_reference = new EqualReference());
-
}
}
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ExclusiveOrInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ExclusiveOrInstruction.cs
index ea88327c5c..c74fa6871c 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ExclusiveOrInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ExclusiveOrInstruction.cs
@@ -9,7 +9,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class ExclusiveOrInstruction : Instruction
{
- private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_bool;
+ private static Instruction s_SByte, s_Int16, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Boolean;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -26,10 +26,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((sbyte)(((sbyte)left) ^ ((sbyte)right)));
- return +1;
+ frame.Push((sbyte)((sbyte)left ^ (sbyte)right));
+ return 1;
}
}
@@ -42,10 +42,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((short)(((short)left) ^ ((short)right)));
- return +1;
+ frame.Push((short)((short)left ^ (short)right));
+ return 1;
}
}
@@ -58,10 +58,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((int)left) ^ ((int)right));
- return +1;
+ frame.Push((int)left ^ (int)right);
+ return 1;
}
}
@@ -74,10 +74,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((long)left) ^ ((long)right));
- return +1;
+ frame.Push((long)left ^ (long)right);
+ return 1;
}
}
@@ -90,10 +90,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((byte)(((byte)left) ^ ((byte)right)));
- return +1;
+ frame.Push((byte)((byte)left ^ (byte)right));
+ return 1;
}
}
@@ -106,10 +106,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((ushort)(((ushort)left) ^ ((ushort)right)));
- return +1;
+ frame.Push((ushort)((ushort)left ^ (ushort)right));
+ return 1;
}
}
@@ -122,10 +122,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((uint)left) ^ ((uint)right));
- return +1;
+ frame.Push((uint)left ^ (uint)right);
+ return 1;
}
}
@@ -138,14 +138,14 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((ulong)left) ^ ((ulong)right));
- return +1;
+ frame.Push((ulong)left ^ (ulong)right);
+ return 1;
}
}
- private sealed class ExclusiveOrBool : ExclusiveOrInstruction
+ private sealed class ExclusiveOrBoolean : ExclusiveOrInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -154,10 +154,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((bool)left) ^ ((bool)right));
- return +1;
+ frame.Push((bool)left ^ (bool)right);
+ return 1;
}
}
@@ -170,16 +170,14 @@ namespace System.Linq.Expressions.Interpreter
switch (underlyingType.GetTypeCode())
{
case TypeCode.SByte: return s_SByte ?? (s_SByte = new ExclusiveOrSByte());
- case TypeCode.Byte: return s_byte ?? (s_byte = new ExclusiveOrByte());
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new ExclusiveOrInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new ExclusiveOrInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new ExclusiveOrInt64());
-
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new ExclusiveOrInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new ExclusiveOrInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new ExclusiveOrInt64());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new ExclusiveOrByte());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new ExclusiveOrUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new ExclusiveOrUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new ExclusiveOrUInt64());
- case TypeCode.Boolean: return s_bool ?? (s_bool = new ExclusiveOrBool());
-
+ case TypeCode.Boolean: return s_Boolean ?? (s_Boolean = new ExclusiveOrBoolean());
default:
throw Error.ExpressionNotSupportedForType("ExclusiveOr", type);
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/FieldOperations.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/FieldOperations.cs
index bee38fe546..73f4cac882 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/FieldOperations.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/FieldOperations.cs
@@ -34,7 +34,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Push(_field.GetValue(obj: null));
- return +1;
+ return 1;
}
}
@@ -55,7 +55,7 @@ namespace System.Linq.Expressions.Interpreter
NullCheck(self);
frame.Push(_field.GetValue(self));
- return +1;
+ return 1;
}
}
@@ -78,7 +78,7 @@ namespace System.Linq.Expressions.Interpreter
NullCheck(self);
_field.SetValue(self, value);
- return +1;
+ return 1;
}
}
@@ -98,7 +98,7 @@ namespace System.Linq.Expressions.Interpreter
{
object value = frame.Pop();
_field.SetValue(null, value);
- return +1;
+ return 1;
}
}
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/GreaterThanInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/GreaterThanInstruction.cs
index b8480b7809..f46a569a06 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/GreaterThanInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/GreaterThanInstruction.cs
@@ -11,7 +11,7 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class GreaterThanInstruction : Instruction
{
private readonly object _nullValue;
- private static Instruction s_SByte, s_int16, s_char, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
+ private static Instruction s_SByte, s_Int16, s_Char, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
private static Instruction s_liftedToNullSByte, s_liftedToNullInt16, s_liftedToNullChar, s_liftedToNullInt32, s_liftedToNullInt64, s_liftedToNullByte, s_liftedToNullUInt16, s_liftedToNullUInt32, s_liftedToNullUInt64, s_liftedToNullSingle, s_liftedToNullDouble;
public override int ConsumedStack => 2;
@@ -40,9 +40,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((sbyte)left) > (sbyte)right);
+ frame.Push((sbyte)left > (sbyte)right);
}
- return +1;
+ return 1;
}
}
@@ -63,9 +63,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((short)left) > (short)right);
+ frame.Push((short)left > (short)right);
}
- return +1;
+ return 1;
}
}
@@ -86,9 +86,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((char)left) > (char)right);
+ frame.Push((char)left > (char)right);
}
- return +1;
+ return 1;
}
}
@@ -109,9 +109,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((int)left) > (int)right);
+ frame.Push((int)left > (int)right);
}
- return +1;
+ return 1;
}
}
@@ -132,9 +132,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((long)left) > (long)right);
+ frame.Push((long)left > (long)right);
}
- return +1;
+ return 1;
}
}
@@ -155,9 +155,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((byte)left) > (byte)right);
+ frame.Push((byte)left > (byte)right);
}
- return +1;
+ return 1;
}
}
@@ -178,9 +178,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((ushort)left) > (ushort)right);
+ frame.Push((ushort)left > (ushort)right);
}
- return +1;
+ return 1;
}
}
@@ -201,9 +201,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((uint)left) > (uint)right);
+ frame.Push((uint)left > (uint)right);
}
- return +1;
+ return 1;
}
}
@@ -224,9 +224,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((ulong)left) > (ulong)right);
+ frame.Push((ulong)left > (ulong)right);
}
- return +1;
+ return 1;
}
}
@@ -247,9 +247,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((float)left) > (float)right);
+ frame.Push((float)left > (float)right);
}
- return +1;
+ return 1;
}
}
@@ -270,9 +270,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((double)left) > (double)right);
+ frame.Push((double)left > (double)right);
}
- return +1;
+ return 1;
}
}
@@ -284,17 +284,16 @@ namespace System.Linq.Expressions.Interpreter
switch (type.GetNonNullableType().GetTypeCode())
{
case TypeCode.SByte: return s_liftedToNullSByte ?? (s_liftedToNullSByte = new GreaterThanSByte(null));
- case TypeCode.Byte: return s_liftedToNullByte ?? (s_liftedToNullByte = new GreaterThanByte(null));
- case TypeCode.Char: return s_liftedToNullChar ?? (s_liftedToNullChar = new GreaterThanChar(null));
case TypeCode.Int16: return s_liftedToNullInt16 ?? (s_liftedToNullInt16 = new GreaterThanInt16(null));
+ case TypeCode.Char: return s_liftedToNullChar ?? (s_liftedToNullChar = new GreaterThanChar(null));
case TypeCode.Int32: return s_liftedToNullInt32 ?? (s_liftedToNullInt32 = new GreaterThanInt32(null));
case TypeCode.Int64: return s_liftedToNullInt64 ?? (s_liftedToNullInt64 = new GreaterThanInt64(null));
+ case TypeCode.Byte: return s_liftedToNullByte ?? (s_liftedToNullByte = new GreaterThanByte(null));
case TypeCode.UInt16: return s_liftedToNullUInt16 ?? (s_liftedToNullUInt16 = new GreaterThanUInt16(null));
case TypeCode.UInt32: return s_liftedToNullUInt32 ?? (s_liftedToNullUInt32 = new GreaterThanUInt32(null));
case TypeCode.UInt64: return s_liftedToNullUInt64 ?? (s_liftedToNullUInt64 = new GreaterThanUInt64(null));
case TypeCode.Single: return s_liftedToNullSingle ?? (s_liftedToNullSingle = new GreaterThanSingle(null));
case TypeCode.Double: return s_liftedToNullDouble ?? (s_liftedToNullDouble = new GreaterThanDouble(null));
-
default:
throw Error.ExpressionNotSupportedForType("GreaterThan", type);
}
@@ -304,17 +303,16 @@ namespace System.Linq.Expressions.Interpreter
switch (type.GetNonNullableType().GetTypeCode())
{
case TypeCode.SByte: return s_SByte ?? (s_SByte = new GreaterThanSByte(Utils.BoxedFalse));
- case TypeCode.Byte: return s_byte ?? (s_byte = new GreaterThanByte(Utils.BoxedFalse));
- case TypeCode.Char: return s_char ?? (s_char = new GreaterThanChar(Utils.BoxedFalse));
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new GreaterThanInt16(Utils.BoxedFalse));
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new GreaterThanInt32(Utils.BoxedFalse));
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new GreaterThanInt64(Utils.BoxedFalse));
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new GreaterThanInt16(Utils.BoxedFalse));
+ case TypeCode.Char: return s_Char ?? (s_Char = new GreaterThanChar(Utils.BoxedFalse));
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new GreaterThanInt32(Utils.BoxedFalse));
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new GreaterThanInt64(Utils.BoxedFalse));
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new GreaterThanByte(Utils.BoxedFalse));
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new GreaterThanUInt16(Utils.BoxedFalse));
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new GreaterThanUInt32(Utils.BoxedFalse));
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new GreaterThanUInt64(Utils.BoxedFalse));
- case TypeCode.Single: return s_single ?? (s_single = new GreaterThanSingle(Utils.BoxedFalse));
- case TypeCode.Double: return s_double ?? (s_double = new GreaterThanDouble(Utils.BoxedFalse));
-
+ case TypeCode.Single: return s_Single ?? (s_Single = new GreaterThanSingle(Utils.BoxedFalse));
+ case TypeCode.Double: return s_Double ?? (s_Double = new GreaterThanDouble(Utils.BoxedFalse));
default:
throw Error.ExpressionNotSupportedForType("GreaterThan", type);
}
@@ -323,320 +321,4 @@ namespace System.Linq.Expressions.Interpreter
public override string ToString() => "GreaterThan()";
}
-
- internal abstract class GreaterThanOrEqualInstruction : Instruction
- {
- private readonly object _nullValue;
- private static Instruction s_SByte, s_int16, s_char, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
- private static Instruction s_liftedToNullSByte, s_liftedToNullInt16, s_liftedToNullChar, s_liftedToNullInt32, s_liftedToNullInt64, s_liftedToNullByte, s_liftedToNullUInt16, s_liftedToNullUInt32, s_liftedToNullUInt64, s_liftedToNullSingle, s_liftedToNullDouble;
-
- public override int ConsumedStack => 2;
- public override int ProducedStack => 1;
- public override string InstructionName => "GreaterThanOrEqual";
-
- private GreaterThanOrEqualInstruction(object nullValue)
- {
- _nullValue = nullValue;
- }
-
- private sealed class GreaterThanOrEqualSByte : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualSByte(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((sbyte)left) >= (sbyte)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualInt16 : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualInt16(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((short)left) >= (short)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualChar : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualChar(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((char)left) >= (char)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualInt32 : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualInt32(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((int)left) >= (int)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualInt64 : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualInt64(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((long)left) >= (long)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualByte : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualByte(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((byte)left) >= (byte)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualUInt16 : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualUInt16(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((ushort)left) >= (ushort)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualUInt32 : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualUInt32(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((uint)left) >= (uint)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualUInt64 : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualUInt64(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((ulong)left) >= (ulong)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualSingle : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualSingle(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((float)left) >= (float)right);
- }
- return +1;
- }
- }
-
- private sealed class GreaterThanOrEqualDouble : GreaterThanOrEqualInstruction
- {
- public GreaterThanOrEqualDouble(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((double)left) >= (double)right);
- }
- return +1;
- }
- }
-
- public static Instruction Create(Type type, bool liftedToNull = false)
- {
- Debug.Assert(!type.GetTypeInfo().IsEnum);
- if (liftedToNull)
- {
- switch (type.GetNonNullableType().GetTypeCode())
- {
- case TypeCode.SByte: return s_liftedToNullSByte ?? (s_liftedToNullSByte = new GreaterThanOrEqualSByte(null));
- case TypeCode.Byte: return s_liftedToNullByte ?? (s_liftedToNullByte = new GreaterThanOrEqualByte(null));
- case TypeCode.Char: return s_liftedToNullChar ?? (s_liftedToNullChar = new GreaterThanOrEqualChar(null));
- case TypeCode.Int16: return s_liftedToNullInt16 ?? (s_liftedToNullInt16 = new GreaterThanOrEqualInt16(null));
- case TypeCode.Int32: return s_liftedToNullInt32 ?? (s_liftedToNullInt32 = new GreaterThanOrEqualInt32(null));
- case TypeCode.Int64: return s_liftedToNullInt64 ?? (s_liftedToNullInt64 = new GreaterThanOrEqualInt64(null));
- case TypeCode.UInt16: return s_liftedToNullUInt16 ?? (s_liftedToNullUInt16 = new GreaterThanOrEqualUInt16(null));
- case TypeCode.UInt32: return s_liftedToNullUInt32 ?? (s_liftedToNullUInt32 = new GreaterThanOrEqualUInt32(null));
- case TypeCode.UInt64: return s_liftedToNullUInt64 ?? (s_liftedToNullUInt64 = new GreaterThanOrEqualUInt64(null));
- case TypeCode.Single: return s_liftedToNullSingle ?? (s_liftedToNullSingle = new GreaterThanOrEqualSingle(null));
- case TypeCode.Double: return s_liftedToNullDouble ?? (s_liftedToNullDouble = new GreaterThanOrEqualDouble(null));
-
- default:
- throw Error.ExpressionNotSupportedForType("GreaterThanOrEqual", type);
- }
- }
- else
- {
- switch (type.GetNonNullableType().GetTypeCode())
- {
- case TypeCode.SByte: return s_SByte ?? (s_SByte = new GreaterThanOrEqualSByte(Utils.BoxedFalse));
- case TypeCode.Byte: return s_byte ?? (s_byte = new GreaterThanOrEqualByte(Utils.BoxedFalse));
- case TypeCode.Char: return s_char ?? (s_char = new GreaterThanOrEqualChar(Utils.BoxedFalse));
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new GreaterThanOrEqualInt16(Utils.BoxedFalse));
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new GreaterThanOrEqualInt32(Utils.BoxedFalse));
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new GreaterThanOrEqualInt64(Utils.BoxedFalse));
- case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new GreaterThanOrEqualUInt16(Utils.BoxedFalse));
- case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new GreaterThanOrEqualUInt32(Utils.BoxedFalse));
- case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new GreaterThanOrEqualUInt64(Utils.BoxedFalse));
- case TypeCode.Single: return s_single ?? (s_single = new GreaterThanOrEqualSingle(Utils.BoxedFalse));
- case TypeCode.Double: return s_double ?? (s_double = new GreaterThanOrEqualDouble(Utils.BoxedFalse));
-
- default:
- throw Error.ExpressionNotSupportedForType("GreaterThanOrEqual", type);
- }
- }
- }
-
- public override string ToString() => "GreaterThanOrEqual()";
- }
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/GreaterThanOrEqualInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/GreaterThanOrEqualInstruction.cs
new file mode 100644
index 0000000000..64d2cd2dbd
--- /dev/null
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/GreaterThanOrEqualInstruction.cs
@@ -0,0 +1,324 @@
+// 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.Dynamic.Utils;
+using System.Reflection;
+
+namespace System.Linq.Expressions.Interpreter
+{
+ internal abstract class GreaterThanOrEqualInstruction : Instruction
+ {
+ private readonly object _nullValue;
+ private static Instruction s_SByte, s_Int16, s_Char, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
+ private static Instruction s_liftedToNullSByte, s_liftedToNullInt16, s_liftedToNullChar, s_liftedToNullInt32, s_liftedToNullInt64, s_liftedToNullByte, s_liftedToNullUInt16, s_liftedToNullUInt32, s_liftedToNullUInt64, s_liftedToNullSingle, s_liftedToNullDouble;
+
+ public override int ConsumedStack => 2;
+ public override int ProducedStack => 1;
+ public override string InstructionName => "GreaterThanOrEqual";
+
+ private GreaterThanOrEqualInstruction(object nullValue)
+ {
+ _nullValue = nullValue;
+ }
+
+ private sealed class GreaterThanOrEqualSByte : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualSByte(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((sbyte)left >= (sbyte)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualInt16 : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualInt16(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((short)left >= (short)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualChar : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualChar(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((char)left >= (char)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualInt32 : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualInt32(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((int)left >= (int)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualInt64 : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualInt64(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((long)left >= (long)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualByte : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualByte(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((byte)left >= (byte)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualUInt16 : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualUInt16(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((ushort)left >= (ushort)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualUInt32 : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualUInt32(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((uint)left >= (uint)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualUInt64 : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualUInt64(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((ulong)left >= (ulong)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualSingle : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualSingle(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((float)left >= (float)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class GreaterThanOrEqualDouble : GreaterThanOrEqualInstruction
+ {
+ public GreaterThanOrEqualDouble(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((double)left >= (double)right);
+ }
+ return 1;
+ }
+ }
+
+ public static Instruction Create(Type type, bool liftedToNull = false)
+ {
+ Debug.Assert(!type.GetTypeInfo().IsEnum);
+ if (liftedToNull)
+ {
+ switch (type.GetNonNullableType().GetTypeCode())
+ {
+ case TypeCode.SByte: return s_liftedToNullSByte ?? (s_liftedToNullSByte = new GreaterThanOrEqualSByte(null));
+ case TypeCode.Int16: return s_liftedToNullInt16 ?? (s_liftedToNullInt16 = new GreaterThanOrEqualInt16(null));
+ case TypeCode.Char: return s_liftedToNullChar ?? (s_liftedToNullChar = new GreaterThanOrEqualChar(null));
+ case TypeCode.Int32: return s_liftedToNullInt32 ?? (s_liftedToNullInt32 = new GreaterThanOrEqualInt32(null));
+ case TypeCode.Int64: return s_liftedToNullInt64 ?? (s_liftedToNullInt64 = new GreaterThanOrEqualInt64(null));
+ case TypeCode.Byte: return s_liftedToNullByte ?? (s_liftedToNullByte = new GreaterThanOrEqualByte(null));
+ case TypeCode.UInt16: return s_liftedToNullUInt16 ?? (s_liftedToNullUInt16 = new GreaterThanOrEqualUInt16(null));
+ case TypeCode.UInt32: return s_liftedToNullUInt32 ?? (s_liftedToNullUInt32 = new GreaterThanOrEqualUInt32(null));
+ case TypeCode.UInt64: return s_liftedToNullUInt64 ?? (s_liftedToNullUInt64 = new GreaterThanOrEqualUInt64(null));
+ case TypeCode.Single: return s_liftedToNullSingle ?? (s_liftedToNullSingle = new GreaterThanOrEqualSingle(null));
+ case TypeCode.Double: return s_liftedToNullDouble ?? (s_liftedToNullDouble = new GreaterThanOrEqualDouble(null));
+ default:
+ throw Error.ExpressionNotSupportedForType("GreaterThanOrEqual", type);
+ }
+ }
+ else
+ {
+ switch (type.GetNonNullableType().GetTypeCode())
+ {
+ case TypeCode.SByte: return s_SByte ?? (s_SByte = new GreaterThanOrEqualSByte(Utils.BoxedFalse));
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new GreaterThanOrEqualInt16(Utils.BoxedFalse));
+ case TypeCode.Char: return s_Char ?? (s_Char = new GreaterThanOrEqualChar(Utils.BoxedFalse));
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new GreaterThanOrEqualInt32(Utils.BoxedFalse));
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new GreaterThanOrEqualInt64(Utils.BoxedFalse));
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new GreaterThanOrEqualByte(Utils.BoxedFalse));
+ case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new GreaterThanOrEqualUInt16(Utils.BoxedFalse));
+ case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new GreaterThanOrEqualUInt32(Utils.BoxedFalse));
+ case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new GreaterThanOrEqualUInt64(Utils.BoxedFalse));
+ case TypeCode.Single: return s_Single ?? (s_Single = new GreaterThanOrEqualSingle(Utils.BoxedFalse));
+ case TypeCode.Double: return s_Double ?? (s_Double = new GreaterThanOrEqualDouble(Utils.BoxedFalse));
+ default:
+ throw Error.ExpressionNotSupportedForType("GreaterThanOrEqual", type);
+ }
+ }
+ }
+
+ public override string ToString() => "GreaterThanOrEqual()";
+ }
+}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/IncrementInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/IncrementInstruction.cs
index 83046d45b9..1261af1e74 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/IncrementInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/IncrementInstruction.cs
@@ -10,7 +10,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class IncrementInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
public override int ConsumedStack => 1;
public override int ProducedStack => 1;
@@ -18,7 +18,7 @@ namespace System.Linq.Expressions.Interpreter
private IncrementInstruction() { }
- private sealed class IncrementInt32 : IncrementInstruction
+ private sealed class IncrementInt16 : IncrementInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -29,13 +29,13 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(ScriptingRuntimeHelpers.Int32ToObject(unchecked(1 + (int)obj)));
+ frame.Push(unchecked((short)(1 + (short)obj)));
}
- return +1;
+ return 1;
}
}
- private sealed class IncrementInt16 : IncrementInstruction
+ private sealed class IncrementInt32 : IncrementInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -46,9 +46,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((short)(1 + (short)obj)));
+ frame.Push(unchecked(1 + (int)obj));
}
- return +1;
+ return 1;
}
}
@@ -63,9 +63,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((long)(1 + (long)obj)));
+ frame.Push(unchecked(1 + (long)obj));
}
- return +1;
+ return 1;
}
}
@@ -82,7 +82,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push(unchecked((ushort)(1 + (ushort)obj)));
}
- return +1;
+ return 1;
}
}
@@ -97,9 +97,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((uint)(1 + (uint)obj)));
+ frame.Push(unchecked(1 + (uint)obj));
}
- return +1;
+ return 1;
}
}
@@ -114,9 +114,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((ulong)(1 + (ulong)obj)));
+ frame.Push(unchecked(1 + (ulong)obj));
}
- return +1;
+ return 1;
}
}
@@ -131,9 +131,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((float)(1 + (float)obj)));
+ frame.Push(unchecked(1 + (float)obj));
}
- return +1;
+ return 1;
}
}
@@ -148,9 +148,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((double)(1 + (double)obj)));
+ frame.Push(unchecked(1 + (double)obj));
}
- return +1;
+ return 1;
}
}
@@ -159,18 +159,17 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(!type.GetTypeInfo().IsEnum);
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new IncrementInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new IncrementInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new IncrementInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new IncrementInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new IncrementInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new IncrementInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new IncrementUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new IncrementUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new IncrementUInt64());
- case TypeCode.Single: return s_single ?? (s_single = new IncrementSingle());
- case TypeCode.Double: return s_double ?? (s_double = new IncrementDouble());
-
+ case TypeCode.Single: return s_Single ?? (s_Single = new IncrementSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new IncrementDouble());
default:
throw Error.ExpressionNotSupportedForType("Increment", type);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/InstructionList.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/InstructionList.cs
index d37ad5119e..2c64980d46 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/InstructionList.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/InstructionList.cs
@@ -318,7 +318,7 @@ namespace System.Linq.Expressions.Interpreter
private static Instruction s_null;
private static Instruction s_true;
private static Instruction s_false;
- private static Instruction[] s_ints;
+ private static Instruction[] s_Ints;
private static Instruction[] s_loadObjectCached;
public void EmitLoad(object value)
@@ -359,12 +359,12 @@ namespace System.Linq.Expressions.Interpreter
int i = (int)value;
if (i >= PushIntMinCachedValue && i <= PushIntMaxCachedValue)
{
- if (s_ints == null)
+ if (s_Ints == null)
{
- s_ints = new Instruction[PushIntMaxCachedValue - PushIntMinCachedValue + 1];
+ s_Ints = new Instruction[PushIntMaxCachedValue - PushIntMinCachedValue + 1];
}
i -= PushIntMinCachedValue;
- Emit(s_ints[i] ?? (s_ints[i] = new LoadObjectInstruction(value)));
+ Emit(s_Ints[i] ?? (s_Ints[i] = new LoadObjectInstruction(value)));
return;
}
}
@@ -697,7 +697,6 @@ namespace System.Linq.Expressions.Interpreter
}
}
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
public void EmitSub(Type type, bool @checked)
{
if (@checked)
@@ -710,7 +709,6 @@ namespace System.Linq.Expressions.Interpreter
}
}
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
public void EmitMul(Type type, bool @checked)
{
if (@checked)
@@ -842,7 +840,7 @@ namespace System.Linq.Expressions.Interpreter
public void EmitNew(ConstructorInfo constructorInfo)
{
- EmitNew(constructorInfo, constructorInfo.GetParameters());
+ EmitNew(constructorInfo, constructorInfo.GetParametersCached());
}
public void EmitNew(ConstructorInfo constructorInfo, ParameterInfo[] parameters)
@@ -852,7 +850,7 @@ namespace System.Linq.Expressions.Interpreter
public void EmitByRefNew(ConstructorInfo constructorInfo, ByRefUpdater[] updaters)
{
- EmitByRefNew(constructorInfo, constructorInfo.GetParameters(), updaters);
+ EmitByRefNew(constructorInfo, constructorInfo.GetParametersCached(), updaters);
}
public void EmitByRefNew(ConstructorInfo constructorInfo, ParameterInfo[] parameters, ByRefUpdater[] updaters)
@@ -961,7 +959,7 @@ namespace System.Linq.Expressions.Interpreter
public void EmitCall(MethodInfo method)
{
- EmitCall(method, method.GetParameters());
+ EmitCall(method, method.GetParametersCached());
}
public void EmitCall(MethodInfo method, ParameterInfo[] parameters)
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LeftShiftInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LeftShiftInstruction.cs
index 1f4200d1ce..d319da4f27 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LeftShiftInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LeftShiftInstruction.cs
@@ -9,7 +9,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class LeftShiftInstruction : Instruction
{
- private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64;
+ private static Instruction s_SByte, s_Int16, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -29,9 +29,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((sbyte)(((sbyte)value) << ((int)shift)));
+ frame.Push((sbyte)((sbyte)value << (int)shift));
}
- return +1;
+ return 1;
}
}
@@ -47,9 +47,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((short)(((short)value) << ((int)shift)));
+ frame.Push((short)((short)value << (int)shift));
}
- return +1;
+ return 1;
}
}
@@ -65,9 +65,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((int)value) << ((int)shift));
+ frame.Push((int)value << (int)shift);
}
- return +1;
+ return 1;
}
}
@@ -83,9 +83,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((long)value) << ((int)shift));
+ frame.Push((long)value << (int)shift);
}
- return +1;
+ return 1;
}
}
@@ -101,9 +101,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((byte)(((byte)value) << ((int)shift)));
+ frame.Push((byte)((byte)value << (int)shift));
}
- return +1;
+ return 1;
}
}
@@ -119,9 +119,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((ushort)(((ushort)value) << ((int)shift)));
+ frame.Push((ushort)((ushort)value << (int)shift));
}
- return +1;
+ return 1;
}
}
@@ -137,9 +137,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((uint)value) << ((int)shift));
+ frame.Push((uint)value << (int)shift);
}
- return +1;
+ return 1;
}
}
@@ -155,9 +155,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((ulong)value) << ((int)shift));
+ frame.Push((ulong)value << (int)shift);
}
- return +1;
+ return 1;
}
}
@@ -170,18 +170,16 @@ namespace System.Linq.Expressions.Interpreter
switch (underlyingType.GetTypeCode())
{
case TypeCode.SByte: return s_SByte ?? (s_SByte = new LeftShiftSByte());
- case TypeCode.Byte: return s_byte ?? (s_byte = new LeftShiftByte());
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new LeftShiftInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new LeftShiftInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new LeftShiftInt64());
-
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new LeftShiftInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new LeftShiftInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new LeftShiftInt64());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new LeftShiftByte());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new LeftShiftUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new LeftShiftUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new LeftShiftUInt64());
-
default:
throw Error.ExpressionNotSupportedForType("LeftShift", type);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LessThanInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LessThanInstruction.cs
index 7762cfa885..20eab22a5a 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LessThanInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LessThanInstruction.cs
@@ -11,8 +11,7 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class LessThanInstruction : Instruction
{
private readonly object _nullValue;
-
- private static Instruction s_SByte, s_int16, s_char, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
+ private static Instruction s_SByte, s_Int16, s_Char, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
private static Instruction s_liftedToNullSByte, s_liftedToNullInt16, s_liftedToNullChar, s_liftedToNullInt32, s_liftedToNullInt64, s_liftedToNullByte, s_liftedToNullUInt16, s_liftedToNullUInt32, s_liftedToNullUInt64, s_liftedToNullSingle, s_liftedToNullDouble;
public override int ConsumedStack => 2;
@@ -41,9 +40,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((sbyte)left) < (sbyte)right);
+ frame.Push((sbyte)left < (sbyte)right);
}
- return +1;
+ return 1;
}
}
@@ -64,9 +63,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((short)left) < (short)right);
+ frame.Push((short)left < (short)right);
}
- return +1;
+ return 1;
}
}
@@ -87,9 +86,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((char)left) < (char)right);
+ frame.Push((char)left < (char)right);
}
- return +1;
+ return 1;
}
}
@@ -110,9 +109,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((int)left) < (int)right);
+ frame.Push((int)left < (int)right);
}
- return +1;
+ return 1;
}
}
@@ -133,9 +132,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((long)left) < (long)right);
+ frame.Push((long)left < (long)right);
}
- return +1;
+ return 1;
}
}
@@ -156,9 +155,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((byte)left) < (byte)right);
+ frame.Push((byte)left < (byte)right);
}
- return +1;
+ return 1;
}
}
@@ -179,9 +178,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((ushort)left) < (ushort)right);
+ frame.Push((ushort)left < (ushort)right);
}
- return +1;
+ return 1;
}
}
@@ -202,9 +201,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((uint)left) < (uint)right);
+ frame.Push((uint)left < (uint)right);
}
- return +1;
+ return 1;
}
}
@@ -225,9 +224,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((ulong)left) < (ulong)right);
+ frame.Push((ulong)left < (ulong)right);
}
- return +1;
+ return 1;
}
}
@@ -248,9 +247,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((float)left) < (float)right);
+ frame.Push((float)left < (float)right);
}
- return +1;
+ return 1;
}
}
@@ -271,9 +270,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((double)left) < (double)right);
+ frame.Push((double)left < (double)right);
}
- return +1;
+ return 1;
}
}
public static Instruction Create(Type type, bool liftedToNull = false)
@@ -284,17 +283,16 @@ namespace System.Linq.Expressions.Interpreter
switch (type.GetNonNullableType().GetTypeCode())
{
case TypeCode.SByte: return s_liftedToNullSByte ?? (s_liftedToNullSByte = new LessThanSByte(null));
- case TypeCode.Byte: return s_liftedToNullByte ?? (s_liftedToNullByte = new LessThanByte(null));
- case TypeCode.Char: return s_liftedToNullChar ?? (s_liftedToNullChar = new LessThanChar(null));
case TypeCode.Int16: return s_liftedToNullInt16 ?? (s_liftedToNullInt16 = new LessThanInt16(null));
+ case TypeCode.Char: return s_liftedToNullChar ?? (s_liftedToNullChar = new LessThanChar(null));
case TypeCode.Int32: return s_liftedToNullInt32 ?? (s_liftedToNullInt32 = new LessThanInt32(null));
case TypeCode.Int64: return s_liftedToNullInt64 ?? (s_liftedToNullInt64 = new LessThanInt64(null));
+ case TypeCode.Byte: return s_liftedToNullByte ?? (s_liftedToNullByte = new LessThanByte(null));
case TypeCode.UInt16: return s_liftedToNullUInt16 ?? (s_liftedToNullUInt16 = new LessThanUInt16(null));
case TypeCode.UInt32: return s_liftedToNullUInt32 ?? (s_liftedToNullUInt32 = new LessThanUInt32(null));
case TypeCode.UInt64: return s_liftedToNullUInt64 ?? (s_liftedToNullUInt64 = new LessThanUInt64(null));
case TypeCode.Single: return s_liftedToNullSingle ?? (s_liftedToNullSingle = new LessThanSingle(null));
case TypeCode.Double: return s_liftedToNullDouble ?? (s_liftedToNullDouble = new LessThanDouble(null));
-
default:
throw Error.ExpressionNotSupportedForType("LessThan", type);
}
@@ -304,335 +302,20 @@ namespace System.Linq.Expressions.Interpreter
switch (type.GetNonNullableType().GetTypeCode())
{
case TypeCode.SByte: return s_SByte ?? (s_SByte = new LessThanSByte(Utils.BoxedFalse));
- case TypeCode.Byte: return s_byte ?? (s_byte = new LessThanByte(Utils.BoxedFalse));
- case TypeCode.Char: return s_char ?? (s_char = new LessThanChar(Utils.BoxedFalse));
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new LessThanInt16(Utils.BoxedFalse));
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new LessThanInt32(Utils.BoxedFalse));
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new LessThanInt64(Utils.BoxedFalse));
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new LessThanInt16(Utils.BoxedFalse));
+ case TypeCode.Char: return s_Char ?? (s_Char = new LessThanChar(Utils.BoxedFalse));
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new LessThanInt32(Utils.BoxedFalse));
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new LessThanInt64(Utils.BoxedFalse));
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new LessThanByte(Utils.BoxedFalse));
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new LessThanUInt16(Utils.BoxedFalse));
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new LessThanUInt32(Utils.BoxedFalse));
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new LessThanUInt64(Utils.BoxedFalse));
- case TypeCode.Single: return s_single ?? (s_single = new LessThanSingle(Utils.BoxedFalse));
- case TypeCode.Double: return s_double ?? (s_double = new LessThanDouble(Utils.BoxedFalse));
-
+ case TypeCode.Single: return s_Single ?? (s_Single = new LessThanSingle(Utils.BoxedFalse));
+ case TypeCode.Double: return s_Double ?? (s_Double = new LessThanDouble(Utils.BoxedFalse));
default:
throw Error.ExpressionNotSupportedForType("LessThan", type);
}
}
}
}
-
- internal abstract class LessThanOrEqualInstruction : Instruction
- {
- private readonly object _nullValue;
- private static Instruction s_SByte, s_int16, s_char, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
- private static Instruction s_liftedToNullSByte, s_liftedToNullInt16, s_liftedToNullChar, s_liftedToNullInt32, s_liftedToNullInt64, s_liftedToNullByte, s_liftedToNullUInt16, s_liftedToNullUInt32, s_liftedToNullUInt64, s_liftedToNullSingle, s_liftedToNullDouble;
-
- public override int ConsumedStack => 2;
- public override int ProducedStack => 1;
- public override string InstructionName => "LessThanOrEqual";
-
- private LessThanOrEqualInstruction(object nullValue)
- {
- _nullValue = nullValue;
- }
-
- private sealed class LessThanOrEqualSByte : LessThanOrEqualInstruction
- {
- public LessThanOrEqualSByte(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((sbyte)left) <= (sbyte)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualInt16 : LessThanOrEqualInstruction
- {
- public LessThanOrEqualInt16(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((short)left) <= (short)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualChar : LessThanOrEqualInstruction
- {
- public LessThanOrEqualChar(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((char)left) <= (char)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualInt32 : LessThanOrEqualInstruction
- {
- public LessThanOrEqualInt32(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((int)left) <= (int)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualInt64 : LessThanOrEqualInstruction
- {
- public LessThanOrEqualInt64(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((long)left) <= (long)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualByte : LessThanOrEqualInstruction
- {
- public LessThanOrEqualByte(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((byte)left) <= (byte)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualUInt16 : LessThanOrEqualInstruction
- {
- public LessThanOrEqualUInt16(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((ushort)left) <= (ushort)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualUInt32 : LessThanOrEqualInstruction
- {
- public LessThanOrEqualUInt32(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((uint)left) <= (uint)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualUInt64 : LessThanOrEqualInstruction
- {
- public LessThanOrEqualUInt64(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((ulong)left) <= (ulong)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualSingle : LessThanOrEqualInstruction
- {
- public LessThanOrEqualSingle(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((float)left) <= (float)right);
- }
- return +1;
- }
- }
-
- private sealed class LessThanOrEqualDouble : LessThanOrEqualInstruction
- {
- public LessThanOrEqualDouble(object nullValue)
- : base(nullValue)
- {
- }
-
- public override int Run(InterpretedFrame frame)
- {
- object right = frame.Pop();
- object left = frame.Pop();
- if (left == null || right == null)
- {
- frame.Push(_nullValue);
- }
- else
- {
- frame.Push(((double)left) <= (double)right);
- }
- return +1;
- }
- }
-
- public static Instruction Create(Type type, bool liftedToNull = false)
- {
- Debug.Assert(!type.GetTypeInfo().IsEnum);
- if (liftedToNull)
- {
- switch (type.GetNonNullableType().GetTypeCode())
- {
- case TypeCode.SByte: return s_liftedToNullSByte ?? (s_liftedToNullSByte = new LessThanOrEqualSByte(null));
- case TypeCode.Byte: return s_liftedToNullByte ?? (s_liftedToNullByte = new LessThanOrEqualByte(null));
- case TypeCode.Char: return s_liftedToNullChar ?? (s_liftedToNullChar = new LessThanOrEqualChar(null));
- case TypeCode.Int16: return s_liftedToNullInt16 ?? (s_liftedToNullInt16 = new LessThanOrEqualInt16(null));
- case TypeCode.Int32: return s_liftedToNullInt32 ?? (s_liftedToNullInt32 = new LessThanOrEqualInt32(null));
- case TypeCode.Int64: return s_liftedToNullInt64 ?? (s_liftedToNullInt64 = new LessThanOrEqualInt64(null));
- case TypeCode.UInt16: return s_liftedToNullUInt16 ?? (s_liftedToNullUInt16 = new LessThanOrEqualUInt16(null));
- case TypeCode.UInt32: return s_liftedToNullUInt32 ?? (s_liftedToNullUInt32 = new LessThanOrEqualUInt32(null));
- case TypeCode.UInt64: return s_liftedToNullUInt64 ?? (s_liftedToNullUInt64 = new LessThanOrEqualUInt64(null));
- case TypeCode.Single: return s_liftedToNullSingle ?? (s_liftedToNullSingle = new LessThanOrEqualSingle(null));
- case TypeCode.Double: return s_liftedToNullDouble ?? (s_liftedToNullDouble = new LessThanOrEqualDouble(null));
-
- default:
- throw Error.ExpressionNotSupportedForType("LessThanOrEqual", type);
- }
- }
- else
- {
- switch (type.GetNonNullableType().GetTypeCode())
- {
- case TypeCode.SByte: return s_SByte ?? (s_SByte = new LessThanOrEqualSByte(Utils.BoxedFalse));
- case TypeCode.Byte: return s_byte ?? (s_byte = new LessThanOrEqualByte(Utils.BoxedFalse));
- case TypeCode.Char: return s_char ?? (s_char = new LessThanOrEqualChar(Utils.BoxedFalse));
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new LessThanOrEqualInt16(Utils.BoxedFalse));
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new LessThanOrEqualInt32(Utils.BoxedFalse));
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new LessThanOrEqualInt64(Utils.BoxedFalse));
- case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new LessThanOrEqualUInt16(Utils.BoxedFalse));
- case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new LessThanOrEqualUInt32(Utils.BoxedFalse));
- case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new LessThanOrEqualUInt64(Utils.BoxedFalse));
- case TypeCode.Single: return s_single ?? (s_single = new LessThanOrEqualSingle(Utils.BoxedFalse));
- case TypeCode.Double: return s_double ?? (s_double = new LessThanOrEqualDouble(Utils.BoxedFalse));
-
- default:
- throw Error.ExpressionNotSupportedForType("LessThanOrEqual", type);
- }
- }
- }
- }
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LessThanOrEqualInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LessThanOrEqualInstruction.cs
new file mode 100644
index 0000000000..192fdf710a
--- /dev/null
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LessThanOrEqualInstruction.cs
@@ -0,0 +1,322 @@
+// 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.Dynamic.Utils;
+using System.Reflection;
+
+namespace System.Linq.Expressions.Interpreter
+{
+ internal abstract class LessThanOrEqualInstruction : Instruction
+ {
+ private readonly object _nullValue;
+ private static Instruction s_SByte, s_Int16, s_Char, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
+ private static Instruction s_liftedToNullSByte, s_liftedToNullInt16, s_liftedToNullChar, s_liftedToNullInt32, s_liftedToNullInt64, s_liftedToNullByte, s_liftedToNullUInt16, s_liftedToNullUInt32, s_liftedToNullUInt64, s_liftedToNullSingle, s_liftedToNullDouble;
+
+ public override int ConsumedStack => 2;
+ public override int ProducedStack => 1;
+ public override string InstructionName => "LessThanOrEqual";
+
+ private LessThanOrEqualInstruction(object nullValue)
+ {
+ _nullValue = nullValue;
+ }
+
+ private sealed class LessThanOrEqualSByte : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualSByte(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((sbyte)left <= (sbyte)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualInt16 : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualInt16(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((short)left <= (short)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualChar : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualChar(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((char)left <= (char)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualInt32 : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualInt32(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((int)left <= (int)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualInt64 : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualInt64(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((long)left <= (long)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualByte : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualByte(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((byte)left <= (byte)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualUInt16 : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualUInt16(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((ushort)left <= (ushort)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualUInt32 : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualUInt32(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((uint)left <= (uint)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualUInt64 : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualUInt64(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((ulong)left <= (ulong)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualSingle : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualSingle(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((float)left <= (float)right);
+ }
+ return 1;
+ }
+ }
+
+ private sealed class LessThanOrEqualDouble : LessThanOrEqualInstruction
+ {
+ public LessThanOrEqualDouble(object nullValue)
+ : base(nullValue)
+ {
+ }
+
+ public override int Run(InterpretedFrame frame)
+ {
+ object right = frame.Pop();
+ object left = frame.Pop();
+ if (left == null || right == null)
+ {
+ frame.Push(_nullValue);
+ }
+ else
+ {
+ frame.Push((double)left <= (double)right);
+ }
+ return 1;
+ }
+ }
+
+ public static Instruction Create(Type type, bool liftedToNull = false)
+ {
+ Debug.Assert(!type.GetTypeInfo().IsEnum);
+ if (liftedToNull)
+ {
+ switch (type.GetNonNullableType().GetTypeCode())
+ {
+ case TypeCode.SByte: return s_liftedToNullSByte ?? (s_liftedToNullSByte = new LessThanOrEqualSByte(null));
+ case TypeCode.Int16: return s_liftedToNullInt16 ?? (s_liftedToNullInt16 = new LessThanOrEqualInt16(null));
+ case TypeCode.Char: return s_liftedToNullChar ?? (s_liftedToNullChar = new LessThanOrEqualChar(null));
+ case TypeCode.Int32: return s_liftedToNullInt32 ?? (s_liftedToNullInt32 = new LessThanOrEqualInt32(null));
+ case TypeCode.Int64: return s_liftedToNullInt64 ?? (s_liftedToNullInt64 = new LessThanOrEqualInt64(null));
+ case TypeCode.Byte: return s_liftedToNullByte ?? (s_liftedToNullByte = new LessThanOrEqualByte(null));
+ case TypeCode.UInt16: return s_liftedToNullUInt16 ?? (s_liftedToNullUInt16 = new LessThanOrEqualUInt16(null));
+ case TypeCode.UInt32: return s_liftedToNullUInt32 ?? (s_liftedToNullUInt32 = new LessThanOrEqualUInt32(null));
+ case TypeCode.UInt64: return s_liftedToNullUInt64 ?? (s_liftedToNullUInt64 = new LessThanOrEqualUInt64(null));
+ case TypeCode.Single: return s_liftedToNullSingle ?? (s_liftedToNullSingle = new LessThanOrEqualSingle(null));
+ case TypeCode.Double: return s_liftedToNullDouble ?? (s_liftedToNullDouble = new LessThanOrEqualDouble(null));
+ default:
+ throw Error.ExpressionNotSupportedForType("LessThanOrEqual", type);
+ }
+ }
+ else
+ {
+ switch (type.GetNonNullableType().GetTypeCode())
+ {
+ case TypeCode.SByte: return s_SByte ?? (s_SByte = new LessThanOrEqualSByte(Utils.BoxedFalse));
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new LessThanOrEqualInt16(Utils.BoxedFalse));
+ case TypeCode.Char: return s_Char ?? (s_Char = new LessThanOrEqualChar(Utils.BoxedFalse));
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new LessThanOrEqualInt32(Utils.BoxedFalse));
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new LessThanOrEqualInt64(Utils.BoxedFalse));
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new LessThanOrEqualByte(Utils.BoxedFalse));
+ case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new LessThanOrEqualUInt16(Utils.BoxedFalse));
+ case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new LessThanOrEqualUInt32(Utils.BoxedFalse));
+ case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new LessThanOrEqualUInt64(Utils.BoxedFalse));
+ case TypeCode.Single: return s_Single ?? (s_Single = new LessThanOrEqualSingle(Utils.BoxedFalse));
+ case TypeCode.Double: return s_Double ?? (s_Double = new LessThanOrEqualDouble(Utils.BoxedFalse));
+ default:
+ throw Error.ExpressionNotSupportedForType("LessThanOrEqual", type);
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightCompiler.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightCompiler.cs
index 37a3de84b4..c4b6f4005b 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightCompiler.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightCompiler.cs
@@ -2126,7 +2126,7 @@ namespace System.Linq.Expressions.Interpreter
private void CompileMethodCallExpression(Expression @object, MethodInfo method, IArgumentProvider arguments)
{
- ParameterInfo[] parameters = method.GetParameters();
+ ParameterInfo[] parameters = method.GetParametersCached();
// TODO: Support pass by reference.
List<ByRefUpdater> updaters = null;
@@ -2380,7 +2380,7 @@ namespace System.Linq.Expressions.Interpreter
if (node.Constructor.DeclaringType.GetTypeInfo().IsAbstract)
throw Error.NonAbstractConstructorRequired();
- ParameterInfo[] parameters = node.Constructor.GetParameters();
+ ParameterInfo[] parameters = node.Constructor.GetParametersCached();
List<ByRefUpdater> updaters = null;
for (int i = 0; i < parameters.Length; i++)
@@ -2657,7 +2657,6 @@ namespace System.Linq.Expressions.Interpreter
}
}
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "expr")]
private void CompileListInitExpression(Expression expr)
{
var node = (ListInitExpression)expr;
@@ -2683,7 +2682,6 @@ namespace System.Linq.Expressions.Interpreter
}
}
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "expr")]
private void CompileMemberInitExpression(Expression expr)
{
var node = (MemberInitExpression)expr;
@@ -2739,7 +2737,6 @@ namespace System.Linq.Expressions.Interpreter
throw new InvalidOperationException("MemberNotFieldOrProperty");
}
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "expr")]
private void CompileQuoteUnaryExpression(Expression expr)
{
var unary = (UnaryExpression)expr;
@@ -3200,8 +3197,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- ExceptionHelpers.UpdateForRethrow(e.InnerException);
- throw e.InnerException;
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
}
@@ -3245,8 +3242,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- ExceptionHelpers.UpdateForRethrow(e.InnerException);
- throw e.InnerException;
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.Generated.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.Generated.cs
index 18c161d255..62c1c4d588 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.Generated.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.Generated.cs
@@ -11,7 +11,7 @@ namespace System.Linq.Expressions.Interpreter
{
#if NO_FEATURE_STATIC_DELEGATE
internal const int MaxParameters = 16;
- [EnableInvokeTesting]
+
internal TRet Run0<TRet>()
{
var frame = MakeFrame();
@@ -19,7 +19,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid0()
{
var frame = MakeFrame();
@@ -37,7 +36,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action(lambda.RunVoid0);
}
#endif
- [EnableInvokeTesting]
internal TRet Run1<T0, TRet>(T0 arg0)
{
/*Console.WriteLine("Running method: {0}", arg0);
@@ -52,7 +50,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid1<T0>(T0 arg0)
{
var frame = MakeFrame();
@@ -70,7 +67,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0>(lambda.RunVoid1<T0>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run2<T0, T1, TRet>(T0 arg0, T1 arg1)
{
var frame = MakeFrame();
@@ -80,7 +76,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid2<T0, T1>(T0 arg0, T1 arg1)
{
var frame = MakeFrame();
@@ -99,7 +94,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1>(lambda.RunVoid2<T0, T1>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run3<T0, T1, T2, TRet>(T0 arg0, T1 arg1, T2 arg2)
{
var frame = MakeFrame();
@@ -111,7 +105,6 @@ namespace System.Linq.Expressions.Interpreter
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid3<T0, T1, T2>(T0 arg0, T1 arg1, T2 arg2)
{
var frame = MakeFrame();
@@ -132,7 +125,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2>(lambda.RunVoid3<T0, T1, T2>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run4<T0, T1, T2, T3, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3)
{
var frame = MakeFrame();
@@ -144,7 +136,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid4<T0, T1, T2, T3>(T0 arg0, T1 arg1, T2 arg2, T3 arg3)
{
var frame = MakeFrame();
@@ -165,7 +156,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3>(lambda.RunVoid4<T0, T1, T2, T3>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run5<T0, T1, T2, T3, T4, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
var frame = MakeFrame();
@@ -178,7 +168,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid5<T0, T1, T2, T3, T4>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
var frame = MakeFrame();
@@ -200,7 +189,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4>(lambda.RunVoid5<T0, T1, T2, T3, T4>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run6<T0, T1, T2, T3, T4, T5, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
{
var frame = MakeFrame();
@@ -215,7 +203,6 @@ namespace System.Linq.Expressions.Interpreter
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid6<T0, T1, T2, T3, T4, T5>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
{
var frame = MakeFrame();
@@ -238,7 +225,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4, T5>(lambda.RunVoid6<T0, T1, T2, T3, T4, T5>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run7<T0, T1, T2, T3, T4, T5, T6, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
{
var frame = MakeFrame();
@@ -254,7 +240,6 @@ namespace System.Linq.Expressions.Interpreter
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid7<T0, T1, T2, T3, T4, T5, T6>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
{
var frame = MakeFrame();
@@ -278,7 +263,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4, T5, T6>(lambda.RunVoid7<T0, T1, T2, T3, T4, T5, T6>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run8<T0, T1, T2, T3, T4, T5, T6, T7, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
{
var frame = MakeFrame();
@@ -294,7 +278,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid8<T0, T1, T2, T3, T4, T5, T6, T7>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
{
var frame = MakeFrame();
@@ -319,7 +302,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4, T5, T6, T7>(lambda.RunVoid8<T0, T1, T2, T3, T4, T5, T6, T7>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run9<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
{
var frame = MakeFrame();
@@ -336,7 +318,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid9<T0, T1, T2, T3, T4, T5, T6, T7, T8>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
{
var frame = MakeFrame();
@@ -362,7 +343,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4, T5, T6, T7, T8>(lambda.RunVoid9<T0, T1, T2, T3, T4, T5, T6, T7, T8>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
{
var frame = MakeFrame();
@@ -380,7 +360,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
{
var frame = MakeFrame();
@@ -407,7 +386,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(lambda.RunVoid10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run11<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10)
{
var frame = MakeFrame();
@@ -426,7 +404,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid11<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10)
{
var frame = MakeFrame();
@@ -454,7 +431,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(lambda.RunVoid11<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run12<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11)
{
var frame = MakeFrame();
@@ -474,7 +450,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid12<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11)
{
var frame = MakeFrame();
@@ -503,7 +478,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(lambda.RunVoid12<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run13<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12)
{
var frame = MakeFrame();
@@ -524,7 +498,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid13<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12)
{
var frame = MakeFrame();
@@ -554,7 +527,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(lambda.RunVoid13<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run14<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13)
{
var frame = MakeFrame();
@@ -576,7 +548,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid14<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13)
{
var frame = MakeFrame();
@@ -607,7 +578,6 @@ namespace System.Linq.Expressions.Interpreter
return new Action<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(lambda.RunVoid14<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>);
}
#endif
- [EnableInvokeTesting]
internal TRet Run15<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRet>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14)
{
var frame = MakeFrame();
@@ -630,7 +600,6 @@ namespace System.Linq.Expressions.Interpreter
try { _interpreter.Run(frame); } finally { frame.Leave(current); }
return (TRet)frame.Pop();
}
- [EnableInvokeTesting]
internal void RunVoid15<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14)
{
var frame = MakeFrame();
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.cs
index 609caa8fb6..832245fac0 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.cs
@@ -212,8 +212,8 @@ namespace System.Linq.Expressions.Interpreter
private static Func<LightLambda, Delegate> MakeRunDelegateCtor(Type delegateType)
{
- var method = delegateType.GetMethod("Invoke");
- var paramInfos = method.GetParameters();
+ MethodInfo method = delegateType.GetMethod("Invoke");
+ ParameterInfo[] paramInfos = method.GetParametersCached();
Type[] paramTypes;
string name = "Run";
@@ -292,8 +292,8 @@ namespace System.Linq.Expressions.Interpreter
{
//PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Synchronously compiling a custom delegate");
- var method = delegateType.GetMethod("Invoke");
- var paramInfos = method.GetParameters();
+ MethodInfo method = delegateType.GetMethod("Invoke");
+ ParameterInfo[] paramInfos = method.GetParametersCached();
var parameters = new ParameterExpression[paramInfos.Length];
var parametersAsObject = new Expression[paramInfos.Length];
bool hasByRef = false;
@@ -305,13 +305,12 @@ namespace System.Linq.Expressions.Interpreter
parametersAsObject[i] = Expression.Convert(parameter, typeof(object));
}
- var data = Expression.NewArrayInit(typeof(object), parametersAsObject);
+ NewArrayExpression data = Expression.NewArrayInit(typeof(object), parametersAsObject);
var dlg = new Func<object[], object>(Run);
- var dlgExpr = AstUtils.Constant(dlg);
+ ConstantExpression dlgExpr = Expression.Constant(dlg);
-
- var argsParam = Expression.Parameter(typeof(object[]), "$args");
+ ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "$args");
Expression body;
if (method.ReturnType == typeof(void))
@@ -330,7 +329,6 @@ namespace System.Linq.Expressions.Interpreter
{
if (paramInfos[i].ParameterType.IsByRef)
{
-
updates.Add(
Expression.Assign(
parameters[i],
@@ -390,7 +388,6 @@ namespace System.Linq.Expressions.Interpreter
}
#if NO_FEATURE_STATIC_DELEGATE
- [EnableInvokeTesting]
internal void RunVoidRef2<T0, T1>(ref T0 arg0, ref T1 arg1)
{
// copy in and copy out for today...
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs
index 3b6f7004c5..286552d99a 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
+using System.Dynamic.Utils;
using System.Reflection;
using System.Runtime.CompilerServices;
@@ -46,7 +47,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Data[frame.StackIndex++] = frame.Data[_index];
- return +1;
+ return 1;
}
public Instruction BoxIfIndexMatches(int index)
@@ -69,7 +70,7 @@ namespace System.Linq.Expressions.Interpreter
{
var box = (IStrongBox)frame.Data[_index];
frame.Data[frame.StackIndex++] = box.Value;
- return +1;
+ return 1;
}
}
@@ -87,7 +88,7 @@ namespace System.Linq.Expressions.Interpreter
{
IStrongBox box = frame.Closure[_index];
frame.Data[frame.StackIndex++] = box.Value;
- return +1;
+ return 1;
}
}
@@ -105,7 +106,7 @@ namespace System.Linq.Expressions.Interpreter
{
IStrongBox box = frame.Closure[_index];
frame.Data[frame.StackIndex++] = box;
- return +1;
+ return 1;
}
}
@@ -127,7 +128,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Data[_index] = frame.Peek();
- return +1;
+ return 1;
}
public Instruction BoxIfIndexMatches(int index)
@@ -149,7 +150,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Data[_index] = frame.Pop();
- return +1;
+ return 1;
}
public Instruction BoxIfIndexMatches(int index)
@@ -173,7 +174,7 @@ namespace System.Linq.Expressions.Interpreter
{
var box = (IStrongBox)frame.Data[_index];
box.Value = frame.Peek();
- return +1;
+ return 1;
}
}
@@ -192,7 +193,7 @@ namespace System.Linq.Expressions.Interpreter
{
var box = (IStrongBox)frame.Data[_index];
box.Value = frame.Data[--frame.StackIndex];
- return +1;
+ return 1;
}
}
@@ -211,7 +212,7 @@ namespace System.Linq.Expressions.Interpreter
{
IStrongBox box = frame.Closure[_index];
box.Value = frame.Peek();
- return +1;
+ return 1;
}
}
@@ -229,7 +230,7 @@ namespace System.Linq.Expressions.Interpreter
{
object o = frame.Pop();
frame.Push(o == null ? o : RuntimeHelpers.GetObjectValue(o));
- return +1;
+ return 1;
}
}
@@ -388,8 +389,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- ExceptionHelpers.UpdateForRethrow(e.InnerException);
- throw e.InnerException;
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
return 1;
@@ -423,8 +424,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- ExceptionHelpers.UpdateForRethrow(e.InnerException);
- throw e.InnerException;
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
frame.Data[_index] = new StrongBox<object>(value);
@@ -461,7 +462,7 @@ namespace System.Linq.Expressions.Interpreter
ret[i] = (IStrongBox)frame.Pop();
}
frame.Push(RuntimeVariables.Create(ret));
- return +1;
+ return 1;
}
public override string ToString() => "GetRuntimeVariables()";
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ModuloInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ModuloInstruction.cs
new file mode 100644
index 0000000000..bf612086e4
--- /dev/null
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/ModuloInstruction.cs
@@ -0,0 +1,191 @@
+// 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.Dynamic.Utils;
+using System.Reflection;
+
+namespace System.Linq.Expressions.Interpreter
+{
+ internal abstract class ModuloInstruction : Instruction
+ {
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
+
+ public override int ConsumedStack => 2;
+ public override int ProducedStack => 1;
+ public override string InstructionName => "Modulo";
+
+ private ModuloInstruction() { }
+
+ private sealed class ModuloInt16 : ModuloInstruction
+ {
+ public override int Run(InterpretedFrame frame)
+ {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ if (l == null || r == null)
+ {
+ frame.Data[frame.StackIndex - 2] = null;
+ }
+ else
+ {
+ frame.Data[frame.StackIndex - 2] = (short)((short)l % (short)r);
+ }
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ private sealed class ModuloInt32 : ModuloInstruction
+ {
+ public override int Run(InterpretedFrame frame)
+ {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ if (l == null || r == null)
+ {
+ frame.Data[frame.StackIndex - 2] = null;
+ }
+ else
+ {
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject((int)l % (int)r);
+ }
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ private sealed class ModuloInt64 : ModuloInstruction
+ {
+ public override int Run(InterpretedFrame frame)
+ {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ if (l == null || r == null)
+ {
+ frame.Data[frame.StackIndex - 2] = null;
+ }
+ else
+ {
+ frame.Data[frame.StackIndex - 2] = (long)l % (long)r;
+ }
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ private sealed class ModuloUInt16 : ModuloInstruction
+ {
+ public override int Run(InterpretedFrame frame)
+ {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ if (l == null || r == null)
+ {
+ frame.Data[frame.StackIndex - 2] = null;
+ }
+ else
+ {
+ frame.Data[frame.StackIndex - 2] = (ushort)((ushort)l % (ushort)r);
+ }
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ private sealed class ModuloUInt32 : ModuloInstruction
+ {
+ public override int Run(InterpretedFrame frame)
+ {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ if (l == null || r == null)
+ {
+ frame.Data[frame.StackIndex - 2] = null;
+ }
+ else
+ {
+ frame.Data[frame.StackIndex - 2] = (uint)l % (uint)r;
+ }
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ private sealed class ModuloUInt64 : ModuloInstruction
+ {
+ public override int Run(InterpretedFrame frame)
+ {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ if (l == null || r == null)
+ {
+ frame.Data[frame.StackIndex - 2] = null;
+ }
+ else
+ {
+ frame.Data[frame.StackIndex - 2] = (ulong)l % (ulong)r;
+ }
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ private sealed class ModuloSingle : ModuloInstruction
+ {
+ public override int Run(InterpretedFrame frame)
+ {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ if (l == null || r == null)
+ {
+ frame.Data[frame.StackIndex - 2] = null;
+ }
+ else
+ {
+ frame.Data[frame.StackIndex - 2] = (float)l % (float)r;
+ }
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ private sealed class ModuloDouble : ModuloInstruction
+ {
+ public override int Run(InterpretedFrame frame)
+ {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ if (l == null || r == null)
+ {
+ frame.Data[frame.StackIndex - 2] = null;
+ }
+ else
+ {
+ frame.Data[frame.StackIndex - 2] = (double)l % (double)r;
+ }
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ public static Instruction Create(Type type)
+ {
+ Debug.Assert(!type.GetTypeInfo().IsEnum);
+ switch (type.GetNonNullableType().GetTypeCode())
+ {
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new ModuloInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new ModuloInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new ModuloInt64());
+ case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new ModuloUInt16());
+ case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new ModuloUInt32());
+ case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new ModuloUInt64());
+ case TypeCode.Single: return s_Single ?? (s_Single = new ModuloSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new ModuloDouble());
+ default:
+ throw Error.ExpressionNotSupportedForType("Modulo", type);
+ }
+ }
+ }
+}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/MulInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/MulInstruction.cs
index 04e0e4f028..ccb9d6c450 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/MulInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/MulInstruction.cs
@@ -9,7 +9,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class MulInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -17,7 +17,7 @@ namespace System.Linq.Expressions.Interpreter
private MulInstruction() { }
- private sealed class MulInt32 : MulInstruction
+ private sealed class MulInt16 : MulInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -29,14 +29,14 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(unchecked((int)l * (int)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((short)((short)l * (short)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
- private sealed class MulInt16 : MulInstruction
+ private sealed class MulInt32 : MulInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -48,10 +48,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((short)((short)l * (short)r));
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(unchecked((int)l * (int)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -67,10 +67,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((long)((long)l * (long)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((long)l * (long)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -89,7 +89,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Data[frame.StackIndex - 2] = unchecked((ushort)((ushort)l * (ushort)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -105,10 +105,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((uint)((uint)l * (uint)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((uint)l * (uint)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -124,10 +124,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((ulong)((ulong)l * (ulong)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((ulong)l * (ulong)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -143,10 +143,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = (float)((float)l * (float)r);
+ frame.Data[frame.StackIndex - 2] = (float)l * (float)r;
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -165,7 +165,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Data[frame.StackIndex - 2] = (double)l * (double)r;
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -174,14 +174,14 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(type.IsArithmetic());
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new MulInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new MulInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new MulInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new MulInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new MulInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new MulInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new MulUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new MulUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new MulUInt64());
- case TypeCode.Single: return s_single ?? (s_single = new MulSingle());
- case TypeCode.Double: return s_double ?? (s_double = new MulDouble());
+ case TypeCode.Single: return s_Single ?? (s_Single = new MulSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new MulDouble());
default:
throw ContractUtils.Unreachable;
@@ -191,7 +191,7 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class MulOvfInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -199,7 +199,7 @@ namespace System.Linq.Expressions.Interpreter
private MulOvfInstruction() { }
- private sealed class MulOvfInt32 : MulOvfInstruction
+ private sealed class MulOvfInt16 : MulOvfInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -211,14 +211,14 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(checked((int)l * (int)r));
+ frame.Data[frame.StackIndex - 2] = checked((short)((short)l * (short)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
- private sealed class MulOvfInt16 : MulOvfInstruction
+ private sealed class MulOvfInt32 : MulOvfInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -230,10 +230,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((short)((short)l * (short)r));
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(checked((int)l * (int)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -249,10 +249,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((long)((long)l * (long)r));
+ frame.Data[frame.StackIndex - 2] = checked((long)l * (long)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -271,7 +271,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Data[frame.StackIndex - 2] = checked((ushort)((ushort)l * (ushort)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -287,10 +287,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((uint)((uint)l * (uint)r));
+ frame.Data[frame.StackIndex - 2] = checked((uint)l * (uint)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -306,10 +306,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((ulong)((ulong)l * (ulong)r));
+ frame.Data[frame.StackIndex - 2] = checked((ulong)l * (ulong)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -318,9 +318,9 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(type.IsArithmetic());
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new MulOvfInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new MulOvfInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new MulOvfInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new MulOvfInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new MulOvfInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new MulOvfInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new MulOvfUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new MulOvfUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new MulOvfUInt64());
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NegateInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NegateInstruction.cs
index 327d5e3127..2e9a7cb259 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NegateInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NegateInstruction.cs
@@ -10,7 +10,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class NegateInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_single, s_double;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_Single, s_Double;
public override int ConsumedStack => 1;
public override int ProducedStack => 1;
@@ -18,7 +18,7 @@ namespace System.Linq.Expressions.Interpreter
private NegateInstruction() { }
- private sealed class NegateInt32 : NegateInstruction
+ private sealed class NegateInt16 : NegateInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -29,13 +29,13 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(ScriptingRuntimeHelpers.Int32ToObject(unchecked(-(int)obj)));
+ frame.Push(unchecked((short)(-(short)obj)));
}
- return +1;
+ return 1;
}
}
- private sealed class NegateInt16 : NegateInstruction
+ private sealed class NegateInt32 : NegateInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -46,9 +46,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((short)(-(short)obj)));
+ frame.Push(unchecked(-(int)obj));
}
- return +1;
+ return 1;
}
}
@@ -63,9 +63,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((long)(-(long)obj)));
+ frame.Push(unchecked(-(long)obj));
}
- return +1;
+ return 1;
}
}
@@ -80,9 +80,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((float)(-(float)obj)));
+ frame.Push(unchecked(-(float)obj));
}
- return +1;
+ return 1;
}
}
@@ -97,9 +97,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(unchecked((double)(-(double)obj)));
+ frame.Push(unchecked(-(double)obj));
}
- return +1;
+ return 1;
}
}
@@ -108,12 +108,11 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(!type.GetTypeInfo().IsEnum);
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new NegateInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new NegateInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new NegateInt64());
- case TypeCode.Single: return s_single ?? (s_single = new NegateSingle());
- case TypeCode.Double: return s_double ?? (s_double = new NegateDouble());
-
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new NegateInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new NegateInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new NegateInt64());
+ case TypeCode.Single: return s_Single ?? (s_Single = new NegateSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new NegateDouble());
default:
throw Error.ExpressionNotSupportedForType("Negate", type);
}
@@ -122,7 +121,7 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class NegateCheckedInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_single, s_double;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_Single, s_Double;
public override int ConsumedStack => 1;
public override int ProducedStack => 1;
@@ -141,9 +140,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(ScriptingRuntimeHelpers.Int32ToObject(checked(-(int)obj)));
+ frame.Push(checked(-(int)obj));
}
- return +1;
+ return 1;
}
}
@@ -160,7 +159,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push(checked((short)(-(short)obj)));
}
- return +1;
+ return 1;
}
}
@@ -175,11 +174,12 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(checked((long)(-(long)obj)));
+ frame.Push(checked(-(long)obj));
}
- return +1;
+ return 1;
}
}
+
private sealed class NegateCheckedSingle : NegateCheckedInstruction
{
public override int Run(InterpretedFrame frame)
@@ -191,9 +191,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(checked((float)(-(float)obj)));
+ frame.Push(checked(-(float)obj));
}
- return +1;
+ return 1;
}
}
@@ -208,9 +208,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(checked((double)(-(double)obj)));
+ frame.Push(checked(-(double)obj));
}
- return +1;
+ return 1;
}
}
@@ -219,11 +219,11 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(!type.GetTypeInfo().IsEnum);
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new NegateCheckedInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new NegateCheckedInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new NegateCheckedInt64());
- case TypeCode.Single: return s_single ?? (s_single = new NegateCheckedSingle());
- case TypeCode.Double: return s_double ?? (s_double = new NegateCheckedDouble());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new NegateCheckedInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new NegateCheckedInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new NegateCheckedInt64());
+ case TypeCode.Single: return s_Single ?? (s_Single = new NegateCheckedSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new NegateCheckedDouble());
default:
throw Error.ExpressionNotSupportedForType("NegateChecked", type);
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NewInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NewInstruction.cs
index e818ba4f2a..ddbfe7fd61 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NewInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NewInstruction.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Dynamic.Utils;
using System.Reflection;
namespace System.Linq.Expressions.Interpreter
@@ -35,14 +36,14 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- ExceptionHelpers.UpdateForRethrow(e.InnerException);
- throw e.InnerException;
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
frame.Data[first] = ret;
frame.StackIndex = first + 1;
- return +1;
+ return 1;
}
protected object[] GetArgs(InterpretedFrame frame, int first)
@@ -95,7 +96,8 @@ namespace System.Linq.Expressions.Interpreter
}
catch (TargetInvocationException e)
{
- throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ ExceptionHelpers.UnwrapAndRethrow(e);
+ throw ContractUtils.Unreachable;
}
frame.Data[first] = ret;
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotEqualInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotEqualInstruction.cs
index 08c7b98015..7c839d9f11 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotEqualInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotEqualInstruction.cs
@@ -11,8 +11,8 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class NotEqualInstruction : Instruction
{
// Perf: EqualityComparer<T> but is 3/2 to 2 times slower.
- private static Instruction s_reference, s_boolean, s_SByte, s_int16, s_char, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
- private static Instruction s_booleanLiftedToNull, s_SByteLiftedToNull, s_int16LiftedToNull, s_charLiftedToNull, s_int32LiftedToNull, s_int64LiftedToNull, s_byteLiftedToNull, s_UInt16LiftedToNull, s_UInt32LiftedToNull, s_UInt64LiftedToNull, s_singleLiftedToNull, s_doubleLiftedToNull;
+ private static Instruction s_reference, s_Boolean, s_SByte, s_Int16, s_Char, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
+ private static Instruction s_BooleanLiftedToNull, s_SByteLiftedToNull, s_Int16LiftedToNull, s_CharLiftedToNull, s_Int32LiftedToNull, s_Int64LiftedToNull, s_ByteLiftedToNull, s_UInt16LiftedToNull, s_UInt32LiftedToNull, s_UInt64LiftedToNull, s_SingleLiftedToNull, s_DoubleLiftedToNull;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -38,7 +38,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((bool)left != (bool)right);
}
- return +1;
+ return 1;
}
}
@@ -60,7 +60,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((sbyte)left != (sbyte)right);
}
- return +1;
+ return 1;
}
}
@@ -82,7 +82,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((short)left != (short)right);
}
- return +1;
+ return 1;
}
}
@@ -104,7 +104,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((char)left != (char)right);
}
- return +1;
+ return 1;
}
}
@@ -126,7 +126,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((int)left != (int)right);
}
- return +1;
+ return 1;
}
}
@@ -148,7 +148,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((long)left != (long)right);
}
- return +1;
+ return 1;
}
}
@@ -170,7 +170,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((byte)left != (byte)right);
}
- return +1;
+ return 1;
}
}
@@ -192,7 +192,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ushort)left != (ushort)right);
}
- return +1;
+ return 1;
}
}
@@ -214,7 +214,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((uint)left != (uint)right);
}
- return +1;
+ return 1;
}
}
@@ -236,7 +236,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ulong)left != (ulong)right);
}
- return +1;
+ return 1;
}
}
@@ -258,7 +258,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((float)left != (float)right);
}
- return +1;
+ return 1;
}
}
@@ -280,7 +280,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((double)left != (double)right);
}
- return +1;
+ return 1;
}
}
@@ -289,7 +289,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Push(frame.Pop() != frame.Pop());
- return +1;
+ return 1;
}
}
@@ -307,7 +307,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((bool)left != (bool)right);
}
- return +1;
+ return 1;
}
}
@@ -325,7 +325,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((sbyte)left != (sbyte)right);
}
- return +1;
+ return 1;
}
}
@@ -343,7 +343,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((short)left != (short)right);
}
- return +1;
+ return 1;
}
}
@@ -361,7 +361,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((char)left != (char)right);
}
- return +1;
+ return 1;
}
}
@@ -379,7 +379,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((int)left != (int)right);
}
- return +1;
+ return 1;
}
}
@@ -397,7 +397,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((long)left != (long)right);
}
- return +1;
+ return 1;
}
}
@@ -415,7 +415,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((byte)left != (byte)right);
}
- return +1;
+ return 1;
}
}
@@ -433,7 +433,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ushort)left != (ushort)right);
}
- return +1;
+ return 1;
}
}
@@ -451,7 +451,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((uint)left != (uint)right);
}
- return +1;
+ return 1;
}
}
@@ -469,7 +469,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ulong)left != (ulong)right);
}
- return +1;
+ return 1;
}
}
@@ -487,7 +487,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((float)left != (float)right);
}
- return +1;
+ return 1;
}
}
@@ -505,7 +505,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((double)left != (double)right);
}
- return +1;
+ return 1;
}
}
@@ -519,43 +519,38 @@ namespace System.Linq.Expressions.Interpreter
{
switch (underlyingType.GetTypeCode())
{
- case TypeCode.Boolean: return s_booleanLiftedToNull ?? (s_booleanLiftedToNull = new NotEqualBooleanLiftedToNull());
+ case TypeCode.Boolean: return s_BooleanLiftedToNull ?? (s_BooleanLiftedToNull = new NotEqualBooleanLiftedToNull());
case TypeCode.SByte: return s_SByteLiftedToNull ?? (s_SByteLiftedToNull = new NotEqualSByteLiftedToNull());
- case TypeCode.Byte: return s_byteLiftedToNull ?? (s_byteLiftedToNull = new NotEqualByteLiftedToNull());
- case TypeCode.Char: return s_charLiftedToNull ?? (s_charLiftedToNull = new NotEqualCharLiftedToNull());
- case TypeCode.Int16: return s_int16LiftedToNull ?? (s_int16LiftedToNull = new NotEqualInt16LiftedToNull());
- case TypeCode.Int32: return s_int32LiftedToNull ?? (s_int32LiftedToNull = new NotEqualInt32LiftedToNull());
- case TypeCode.Int64: return s_int64LiftedToNull ?? (s_int64LiftedToNull = new NotEqualInt64LiftedToNull());
-
+ case TypeCode.Int16: return s_Int16LiftedToNull ?? (s_Int16LiftedToNull = new NotEqualInt16LiftedToNull());
+ case TypeCode.Char: return s_CharLiftedToNull ?? (s_CharLiftedToNull = new NotEqualCharLiftedToNull());
+ case TypeCode.Int32: return s_Int32LiftedToNull ?? (s_Int32LiftedToNull = new NotEqualInt32LiftedToNull());
+ case TypeCode.Int64: return s_Int64LiftedToNull ?? (s_Int64LiftedToNull = new NotEqualInt64LiftedToNull());
+ case TypeCode.Byte: return s_ByteLiftedToNull ?? (s_ByteLiftedToNull = new NotEqualByteLiftedToNull());
case TypeCode.UInt16: return s_UInt16LiftedToNull ?? (s_UInt16LiftedToNull = new NotEqualUInt16LiftedToNull());
case TypeCode.UInt32: return s_UInt32LiftedToNull ?? (s_UInt32LiftedToNull = new NotEqualUInt32LiftedToNull());
case TypeCode.UInt64: return s_UInt64LiftedToNull ?? (s_UInt64LiftedToNull = new NotEqualUInt64LiftedToNull());
-
- case TypeCode.Single: return s_singleLiftedToNull ?? (s_singleLiftedToNull = new NotEqualSingleLiftedToNull());
+ case TypeCode.Single: return s_SingleLiftedToNull ?? (s_SingleLiftedToNull = new NotEqualSingleLiftedToNull());
default:
Debug.Assert(underlyingType.GetTypeCode() == TypeCode.Double);
- return s_doubleLiftedToNull ?? (s_doubleLiftedToNull = new NotEqualDoubleLiftedToNull());
+ return s_DoubleLiftedToNull ?? (s_DoubleLiftedToNull = new NotEqualDoubleLiftedToNull());
}
}
else
{
switch (underlyingType.GetTypeCode())
{
- case TypeCode.Boolean: return s_boolean ?? (s_boolean = new NotEqualBoolean());
+ case TypeCode.Boolean: return s_Boolean ?? (s_Boolean = new NotEqualBoolean());
case TypeCode.SByte: return s_SByte ?? (s_SByte = new NotEqualSByte());
- case TypeCode.Byte: return s_byte ?? (s_byte = new NotEqualByte());
- case TypeCode.Char: return s_char ?? (s_char = new NotEqualChar());
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new NotEqualInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new NotEqualInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new NotEqualInt64());
-
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new NotEqualInt16());
+ case TypeCode.Char: return s_Char ?? (s_Char = new NotEqualChar());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new NotEqualInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new NotEqualInt64());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new NotEqualByte());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new NotEqualUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new NotEqualUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new NotEqualUInt64());
-
- case TypeCode.Single: return s_single ?? (s_single = new NotEqualSingle());
- case TypeCode.Double: return s_double ?? (s_double = new NotEqualDouble());
-
+ case TypeCode.Single: return s_Single ?? (s_Single = new NotEqualSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new NotEqualDouble());
default:
// Nullable only valid if one operand is constant null, so this assert is slightly too broad.
Debug.Assert(type.IsNullableOrReferenceType());
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotInstruction.cs
index 501d4236be..e2fc2037d6 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NotInstruction.cs
@@ -8,7 +8,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class NotInstruction : Instruction
{
- public static Instruction _Bool, _Int64, _Int32, _Int16, _UInt64, _UInt32, _UInt16, _Byte, _SByte;
+ public static Instruction s_Boolean, s_Int64, s_Int32, s_Int16, s_UInt64, s_UInt32, s_UInt16, s_Byte, s_SByte;
private NotInstruction() { }
@@ -16,7 +16,7 @@ namespace System.Linq.Expressions.Interpreter
public override int ProducedStack => 1;
public override string InstructionName => "Not";
- private sealed class BoolNot : NotInstruction
+ private sealed class NotBoolean : NotInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -29,11 +29,11 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push(!(bool)value);
}
- return +1;
+ return 1;
}
}
- private sealed class Int64Not : NotInstruction
+ private sealed class NotInt64 : NotInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -44,13 +44,13 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((long)~(long)value);
+ frame.Push(~(long)value);
}
- return +1;
+ return 1;
}
}
- private sealed class Int32Not : NotInstruction
+ private sealed class NotInt32 : NotInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -61,13 +61,13 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((int)(~(int)value));
+ frame.Push(~(int)value);
}
- return +1;
+ return 1;
}
}
- private sealed class Int16Not : NotInstruction
+ private sealed class NotInt16 : NotInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -80,11 +80,11 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((short)(~(short)value));
}
- return +1;
+ return 1;
}
}
- private sealed class UInt64Not : NotInstruction
+ private sealed class NotUInt64 : NotInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -95,13 +95,13 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((ulong)(~(ulong)value));
+ frame.Push(~(ulong)value);
}
- return +1;
+ return 1;
}
}
- private sealed class UInt32Not : NotInstruction
+ private sealed class NotUInt32 : NotInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -112,13 +112,13 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((uint)(~(uint)value));
+ frame.Push(~(uint)value);
}
- return +1;
+ return 1;
}
}
- private sealed class UInt16Not : NotInstruction
+ private sealed class NotUInt16 : NotInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -131,11 +131,11 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ushort)(~(ushort)value));
}
- return +1;
+ return 1;
}
}
- private sealed class ByteNot : NotInstruction
+ private sealed class NotByte : NotInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -146,13 +146,13 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((object)(byte)(~(byte)value));
+ frame.Push((byte)(~(byte)value));
}
- return +1;
+ return 1;
}
}
- private sealed class SByteNot : NotInstruction
+ private sealed class NotSByte : NotInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -163,9 +163,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((object)(sbyte)(~(sbyte)value));
+ frame.Push((sbyte)(~(sbyte)value));
}
- return +1;
+ return 1;
}
}
@@ -173,16 +173,15 @@ namespace System.Linq.Expressions.Interpreter
{
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Boolean: return _Bool ?? (_Bool = new BoolNot());
- case TypeCode.Int64: return _Int64 ?? (_Int64 = new Int64Not());
- case TypeCode.Int32: return _Int32 ?? (_Int32 = new Int32Not());
- case TypeCode.Int16: return _Int16 ?? (_Int16 = new Int16Not());
- case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new UInt64Not());
- case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new UInt32Not());
- case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new UInt16Not());
- case TypeCode.Byte: return _Byte ?? (_Byte = new ByteNot());
- case TypeCode.SByte: return _SByte ?? (_SByte = new SByteNot());
-
+ case TypeCode.Boolean: return s_Boolean ?? (s_Boolean = new NotBoolean());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new NotInt64());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new NotInt32());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new NotInt16());
+ case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new NotUInt64());
+ case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new NotUInt32());
+ case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new NotUInt16());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new NotByte());
+ case TypeCode.SByte: return s_SByte ?? (s_SByte = new NotSByte());
default:
throw Error.ExpressionNotSupportedForType("Not", type);
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NullCheckInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NullCheckInstruction.cs
index eac4f994cc..532651ec24 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NullCheckInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NullCheckInstruction.cs
@@ -21,7 +21,7 @@ namespace System.Linq.Expressions.Interpreter
throw new NullReferenceException();
}
- return +1;
+ return 1;
}
}
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NumericConvertInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NumericConvertInstruction.cs
index 2660c829c8..56f0a8e4fe 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NumericConvertInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/NumericConvertInstruction.cs
@@ -42,7 +42,7 @@ namespace System.Linq.Expressions.Interpreter
}
frame.Push(converted);
- return +1;
+ return 1;
}
protected abstract object Convert(object obj);
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OnesComplementInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OnesComplementInstruction.cs
index 60a12d527c..73dd84820c 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OnesComplementInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OnesComplementInstruction.cs
@@ -10,7 +10,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class OnesComplementInstruction : Instruction
{
- private static Instruction s_byte, s_sbyte, s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64;
+ private static Instruction s_SByte, s_Int16, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64;
public override int ConsumedStack => 1;
public override int ProducedStack => 1;
@@ -18,7 +18,7 @@ namespace System.Linq.Expressions.Interpreter
private OnesComplementInstruction() { }
- private sealed class OnesComplementInt32 : OnesComplementInstruction
+ private sealed class OnesComplementInt16 : OnesComplementInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -29,13 +29,13 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(ScriptingRuntimeHelpers.Int32ToObject(~(int)obj));
+ frame.Push((short)(~(short)obj));
}
- return +1;
+ return 1;
}
}
- private sealed class OnesComplementInt16 : OnesComplementInstruction
+ private sealed class OnesComplementInt32 : OnesComplementInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -46,9 +46,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((short)(~(short)obj));
+ frame.Push(~(int)obj);
}
- return +1;
+ return 1;
}
}
@@ -63,9 +63,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((long)(~(long)obj));
+ frame.Push(~(long)obj);
}
- return +1;
+ return 1;
}
}
@@ -82,7 +82,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((ushort)(~(ushort)obj));
}
- return +1;
+ return 1;
}
}
@@ -97,9 +97,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((uint)(~(uint)obj));
+ frame.Push(~(uint)obj);
}
- return +1;
+ return 1;
}
}
@@ -114,9 +114,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((ulong)(~(ulong)obj));
+ frame.Push(~(ulong)obj);
}
- return +1;
+ return 1;
}
}
@@ -133,7 +133,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((byte)(~(byte)obj));
}
- return +1;
+ return 1;
}
}
@@ -150,7 +150,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((sbyte)(~(sbyte)obj));
}
- return +1;
+ return 1;
}
}
@@ -159,15 +159,14 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(!type.GetTypeInfo().IsEnum);
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Byte: return s_byte ?? (s_byte = new OnesComplementByte());
- case TypeCode.SByte: return s_sbyte ?? (s_sbyte = new OnesComplementSByte());
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new OnesComplementInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new OnesComplementInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new OnesComplementInt64());
+ case TypeCode.SByte: return s_SByte ?? (s_SByte = new OnesComplementSByte());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new OnesComplementInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new OnesComplementInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new OnesComplementInt64());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new OnesComplementByte());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new OnesComplementUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new OnesComplementUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new OnesComplementUInt64());
-
default:
throw Error.ExpressionNotSupportedForType("OnesComplement", type);
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OrInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OrInstruction.cs
index 786a903aa0..6f0eb6a580 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OrInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/OrInstruction.cs
@@ -9,7 +9,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class OrInstruction : Instruction
{
- private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_bool;
+ private static Instruction s_SByte, s_Int16, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Boolean;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -26,10 +26,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((sbyte)(((sbyte)left) | ((sbyte)right)));
- return +1;
+ frame.Push((sbyte)((sbyte)left | (sbyte)right));
+ return 1;
}
}
@@ -42,10 +42,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((short)(((short)left) | ((short)right)));
- return +1;
+ frame.Push((short)((short)left | (short)right));
+ return 1;
}
}
@@ -58,10 +58,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((int)left) | ((int)right));
- return +1;
+ frame.Push((int)left | (int)right);
+ return 1;
}
}
@@ -74,10 +74,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((long)left) | ((long)right));
- return +1;
+ frame.Push((long)left | (long)right);
+ return 1;
}
}
@@ -90,10 +90,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((byte)(((byte)left) | ((byte)right)));
- return +1;
+ frame.Push((byte)((byte)left | (byte)right));
+ return 1;
}
}
@@ -106,10 +106,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push((ushort)(((ushort)left) | ((ushort)right)));
- return +1;
+ frame.Push((ushort)((ushort)left | (ushort)right));
+ return 1;
}
}
@@ -122,10 +122,10 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((uint)left) | ((uint)right));
- return +1;
+ frame.Push((uint)left | (uint)right);
+ return 1;
}
}
@@ -138,14 +138,14 @@ namespace System.Linq.Expressions.Interpreter
if (left == null || right == null)
{
frame.Push(null);
- return +1;
+ return 1;
}
- frame.Push(((ulong)left) | ((ulong)right));
- return +1;
+ frame.Push((ulong)left | (ulong)right);
+ return 1;
}
}
- private sealed class OrBool : OrInstruction
+ private sealed class OrBoolean : OrInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -161,17 +161,17 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push((bool)right ? Utils.BoxedTrue : null);
}
- return +1;
+ return 1;
}
if (right == null)
{
frame.Push((bool)left ? Utils.BoxedTrue : null);
- return +1;
+ return 1;
}
frame.Push((bool)left | (bool)right);
- return +1;
+ return 1;
}
}
@@ -184,16 +184,14 @@ namespace System.Linq.Expressions.Interpreter
switch (underlyingType.GetTypeCode())
{
case TypeCode.SByte: return s_SByte ?? (s_SByte = new OrSByte());
- case TypeCode.Byte: return s_byte ?? (s_byte = new OrByte());
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new OrInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new OrInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new OrInt64());
-
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new OrInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new OrInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new OrInt64());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new OrByte());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new OrUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new OrUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new OrUInt64());
- case TypeCode.Boolean: return s_bool ?? (s_bool = new OrBool());
-
+ case TypeCode.Boolean: return s_Boolean ?? (s_Boolean = new OrBoolean());
default:
throw Error.ExpressionNotSupportedForType("Or", type);
}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/RightShiftInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/RightShiftInstruction.cs
index 5511cc2a95..ec1326af3d 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/RightShiftInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/RightShiftInstruction.cs
@@ -9,7 +9,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class RightShiftInstruction : Instruction
{
- private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64;
+ private static Instruction s_SByte, s_Int16, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -29,9 +29,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((sbyte)(((sbyte)value) >> ((int)shift)));
+ frame.Push((sbyte)((sbyte)value >> (int)shift));
}
- return +1;
+ return 1;
}
}
@@ -47,9 +47,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((short)(((short)value) >> ((int)shift)));
+ frame.Push((short)((short)value >> (int)shift));
}
- return +1;
+ return 1;
}
}
@@ -65,9 +65,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((int)value) >> ((int)shift));
+ frame.Push((int)value >> (int)shift);
}
- return +1;
+ return 1;
}
}
@@ -83,9 +83,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((long)value) >> ((int)shift));
+ frame.Push((long)value >> (int)shift);
}
- return +1;
+ return 1;
}
}
@@ -101,9 +101,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((byte)(((byte)value) >> ((int)shift)));
+ frame.Push((byte)((byte)value >> (int)shift));
}
- return +1;
+ return 1;
}
}
@@ -119,9 +119,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push((ushort)(((ushort)value) >> ((int)shift)));
+ frame.Push((ushort)((ushort)value >> (int)shift));
}
- return +1;
+ return 1;
}
}
@@ -137,9 +137,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((uint)value) >> ((int)shift));
+ frame.Push((uint)value >> (int)shift);
}
- return +1;
+ return 1;
}
}
@@ -155,9 +155,9 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Push(((ulong)value) >> ((int)shift));
+ frame.Push((ulong)value >> (int)shift);
}
- return +1;
+ return 1;
}
}
@@ -170,18 +170,16 @@ namespace System.Linq.Expressions.Interpreter
switch (underlyingType.GetTypeCode())
{
case TypeCode.SByte: return s_SByte ?? (s_SByte = new RightShiftSByte());
- case TypeCode.Byte: return s_byte ?? (s_byte = new RightShiftByte());
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new RightShiftInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new RightShiftInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new RightShiftInt64());
-
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new RightShiftInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new RightShiftInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new RightShiftInt64());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new RightShiftByte());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new RightShiftUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new RightShiftUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new RightShiftUInt64());
-
default:
throw Error.ExpressionNotSupportedForType("RightShift", type);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/StackOperations.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/StackOperations.cs
index 99512c9443..dba0c62184 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/StackOperations.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/StackOperations.cs
@@ -22,7 +22,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Data[frame.StackIndex++] = _value;
- return +1;
+ return 1;
}
public override string ToString() => "LoadObject(" + (_value ?? "null") + ")";
@@ -43,7 +43,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Data[frame.StackIndex++] = frame.Interpreter._objects[_index];
- return +1;
+ return 1;
}
public override string ToDebugString(int instructionIndex, object cookie, Func<int, int> labelIndexer, IReadOnlyList<object> objects)
@@ -66,7 +66,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Pop();
- return +1;
+ return 1;
}
public override string ToString() => "Pop()";
@@ -74,7 +74,7 @@ namespace System.Linq.Expressions.Interpreter
internal sealed class DupInstruction : Instruction
{
- internal readonly static DupInstruction Instance = new DupInstruction();
+ internal static readonly DupInstruction Instance = new DupInstruction();
private DupInstruction() { }
@@ -84,9 +84,8 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
- object value = frame.Peek();
- frame.Data[frame.StackIndex++] = value;
- return +1;
+ frame.Dup();
+ return 1;
}
public override string ToString() => "Dup()";
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/SubInstruction.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/SubInstruction.cs
index 39f8200894..47720939ac 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/SubInstruction.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/SubInstruction.cs
@@ -9,7 +9,7 @@ namespace System.Linq.Expressions.Interpreter
{
internal abstract class SubInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64, s_single, s_double;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -17,7 +17,7 @@ namespace System.Linq.Expressions.Interpreter
private SubInstruction() { }
- private sealed class SubInt32 : SubInstruction
+ private sealed class SubInt16 : SubInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -29,14 +29,14 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(unchecked((int)l - (int)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((short)((short)l - (short)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
- private sealed class SubInt16 : SubInstruction
+ private sealed class SubInt32 : SubInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -48,10 +48,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((short)((short)l - (short)r));
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(unchecked((int)l - (int)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -67,10 +67,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((long)((long)l - (long)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((long)l - (long)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -89,7 +89,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Data[frame.StackIndex - 2] = unchecked((ushort)((ushort)l - (ushort)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -105,10 +105,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((uint)((uint)l - (uint)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((uint)l - (uint)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -124,10 +124,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = unchecked((ulong)((ulong)l - (ulong)r));
+ frame.Data[frame.StackIndex - 2] = unchecked((ulong)l - (ulong)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -143,10 +143,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = (float)((float)l - (float)r);
+ frame.Data[frame.StackIndex - 2] = (float)l - (float)r;
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -165,7 +165,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Data[frame.StackIndex - 2] = (double)l - (double)r;
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -174,14 +174,14 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(type.IsArithmetic());
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new SubInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new SubInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new SubInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new SubInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new SubInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new SubInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new SubUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new SubUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new SubUInt64());
- case TypeCode.Single: return s_single ?? (s_single = new SubSingle());
- case TypeCode.Double: return s_double ?? (s_double = new SubDouble());
+ case TypeCode.Single: return s_Single ?? (s_Single = new SubSingle());
+ case TypeCode.Double: return s_Double ?? (s_Double = new SubDouble());
default:
throw ContractUtils.Unreachable;
}
@@ -190,7 +190,7 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class SubOvfInstruction : Instruction
{
- private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_UInt64;
+ private static Instruction s_Int16, s_Int32, s_Int64, s_UInt16, s_UInt32, s_UInt64;
public override int ConsumedStack => 2;
public override int ProducedStack => 1;
@@ -198,7 +198,7 @@ namespace System.Linq.Expressions.Interpreter
private SubOvfInstruction() { }
- private sealed class SubOvfInt32 : SubOvfInstruction
+ private sealed class SubOvfInt16 : SubOvfInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -210,14 +210,14 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(checked((int)l - (int)r));
+ frame.Data[frame.StackIndex - 2] = checked((short)((short)l - (short)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
- private sealed class SubOvfInt16 : SubOvfInstruction
+ private sealed class SubOvfInt32 : SubOvfInstruction
{
public override int Run(InterpretedFrame frame)
{
@@ -229,10 +229,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((short)((short)l - (short)r));
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(checked((int)l - (int)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -248,10 +248,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((long)((long)l - (long)r));
+ frame.Data[frame.StackIndex - 2] = checked((long)l - (long)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -270,7 +270,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Data[frame.StackIndex - 2] = checked((ushort)((ushort)l - (ushort)r));
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -286,10 +286,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((uint)((uint)l - (uint)r));
+ frame.Data[frame.StackIndex - 2] = checked((uint)l - (uint)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -305,10 +305,10 @@ namespace System.Linq.Expressions.Interpreter
}
else
{
- frame.Data[frame.StackIndex - 2] = checked((ulong)((ulong)l - (ulong)r));
+ frame.Data[frame.StackIndex - 2] = checked((ulong)l - (ulong)r);
}
frame.StackIndex--;
- return +1;
+ return 1;
}
}
@@ -317,9 +317,9 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(type.IsArithmetic());
switch (type.GetNonNullableType().GetTypeCode())
{
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new SubOvfInt16());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new SubOvfInt32());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new SubOvfInt64());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new SubOvfInt16());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new SubOvfInt32());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new SubOvfInt64());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new SubOvfUInt16());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new SubOvfUInt32());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new SubOvfUInt64());
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs
index dd5fe4b3d7..492819c7e2 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs
@@ -42,7 +42,7 @@ namespace System.Linq.Expressions.Interpreter
Delegate d = _creator.CreateDelegate(closure);
frame.Push(d);
- return +1;
+ return 1;
}
}
@@ -62,7 +62,7 @@ namespace System.Linq.Expressions.Interpreter
public override int Run(InterpretedFrame frame)
{
frame.Push(_type.IsInstanceOfType(frame.Pop()));
- return +1;
+ return 1;
}
public override string ToString() => "TypeIs " + _type.ToString();
@@ -92,7 +92,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push(null);
}
- return +1;
+ return 1;
}
public override string ToString() => "TypeAs " + _type.ToString();
@@ -113,7 +113,7 @@ namespace System.Linq.Expressions.Interpreter
object type = frame.Pop();
object obj = frame.Pop();
frame.Push((object)obj?.GetType() == type);
- return +1;
+ return 1;
}
}
@@ -132,7 +132,7 @@ namespace System.Linq.Expressions.Interpreter
object type = frame.Pop();
object obj = frame.Pop();
frame.Push((object)obj?.GetType() == type);
- return +1;
+ return 1;
}
}
@@ -152,7 +152,7 @@ namespace System.Linq.Expressions.Interpreter
{
object obj = frame.Pop();
frame.Push(obj != null);
- return +1;
+ return 1;
}
}
@@ -165,7 +165,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Pop();
throw new InvalidOperationException();
}
- return +1;
+ return 1;
}
}
@@ -185,7 +185,7 @@ namespace System.Linq.Expressions.Interpreter
frame.Pop();
frame.Push(Activator.CreateInstance(defaultValueType));
}
- return +1;
+ return 1;
}
}
@@ -198,7 +198,7 @@ namespace System.Linq.Expressions.Interpreter
object dflt = frame.Pop();
object obj = frame.Pop();
frame.Push(obj ?? dflt);
- return +1;
+ return 1;
}
}
@@ -222,7 +222,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push(obj.Equals(other));
}
- return +1;
+ return 1;
}
}
@@ -239,7 +239,7 @@ namespace System.Linq.Expressions.Interpreter
{
frame.Push(obj.ToString());
}
- return +1;
+ return 1;
}
}
@@ -250,13 +250,13 @@ namespace System.Linq.Expressions.Interpreter
object obj = frame.Pop();
if (obj == null)
{
- frame.Push(ScriptingRuntimeHelpers.Int32ToObject(0));
+ frame.Push(0);
}
else
{
frame.Push(obj.GetHashCode());
}
- return +1;
+ return 1;
}
}
@@ -292,7 +292,7 @@ namespace System.Linq.Expressions.Interpreter
internal abstract class CastInstruction : Instruction
{
- private static CastInstruction s_boolean, s_byte, s_char, s_dateTime, s_decimal, s_double, s_int16, s_int32, s_int64, s_SByte, s_single, s_string, s_UInt16, s_UInt32, s_UInt64;
+ private static CastInstruction s_Boolean, s_Byte, s_Char, s_DateTime, s_Decimal, s_Double, s_Int16, s_Int32, s_Int64, s_SByte, s_Single, s_String, s_UInt16, s_UInt32, s_UInt64;
public override int ConsumedStack => 1;
public override int ProducedStack => 1;
@@ -304,7 +304,7 @@ namespace System.Linq.Expressions.Interpreter
{
object value = frame.Pop();
frame.Push((T)value);
- return +1;
+ return 1;
}
}
@@ -353,7 +353,7 @@ namespace System.Linq.Expressions.Interpreter
{
ConvertNull(frame);
}
- return +1;
+ return 1;
}
protected abstract void ConvertNull(InterpretedFrame frame);
@@ -390,18 +390,18 @@ namespace System.Linq.Expressions.Interpreter
Debug.Assert(!t.GetTypeInfo().IsEnum);
switch (t.GetTypeCode())
{
- case TypeCode.Boolean: return s_boolean ?? (s_boolean = new CastInstructionT<bool>());
- case TypeCode.Byte: return s_byte ?? (s_byte = new CastInstructionT<byte>());
- case TypeCode.Char: return s_char ?? (s_char = new CastInstructionT<char>());
- case TypeCode.DateTime: return s_dateTime ?? (s_dateTime = new CastInstructionT<DateTime>());
- case TypeCode.Decimal: return s_decimal ?? (s_decimal = new CastInstructionT<decimal>());
- case TypeCode.Double: return s_double ?? (s_double = new CastInstructionT<double>());
- case TypeCode.Int16: return s_int16 ?? (s_int16 = new CastInstructionT<short>());
- case TypeCode.Int32: return s_int32 ?? (s_int32 = new CastInstructionT<int>());
- case TypeCode.Int64: return s_int64 ?? (s_int64 = new CastInstructionT<long>());
+ case TypeCode.Boolean: return s_Boolean ?? (s_Boolean = new CastInstructionT<bool>());
+ case TypeCode.Byte: return s_Byte ?? (s_Byte = new CastInstructionT<byte>());
+ case TypeCode.Char: return s_Char ?? (s_Char = new CastInstructionT<char>());
+ case TypeCode.DateTime: return s_DateTime ?? (s_DateTime = new CastInstructionT<DateTime>());
+ case TypeCode.Decimal: return s_Decimal ?? (s_Decimal = new CastInstructionT<decimal>());
+ case TypeCode.Double: return s_Double ?? (s_Double = new CastInstructionT<double>());
+ case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new CastInstructionT<short>());
+ case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new CastInstructionT<int>());
+ case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new CastInstructionT<long>());
case TypeCode.SByte: return s_SByte ?? (s_SByte = new CastInstructionT<sbyte>());
- case TypeCode.Single: return s_single ?? (s_single = new CastInstructionT<float>());
- case TypeCode.String: return s_string ?? (s_string = new CastInstructionT<string>());
+ case TypeCode.Single: return s_Single ?? (s_Single = new CastInstructionT<float>());
+ case TypeCode.String: return s_String ?? (s_String = new CastInstructionT<string>());
case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new CastInstructionT<ushort>());
case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new CastInstructionT<uint>());
case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new CastInstructionT<ulong>());
@@ -431,7 +431,7 @@ namespace System.Linq.Expressions.Interpreter
TypeCode.Byte, TypeCode.UInt16, TypeCode.UInt64, TypeCode.Char, TypeCode.Boolean
}.Contains(Convert.GetTypeCode(from)));
frame.Push(from == null ? null : Enum.ToObject(_t, from));
- return +1;
+ return 1;
}
}
@@ -450,55 +450,47 @@ namespace System.Linq.Expressions.Interpreter
object from = frame.Pop();
Debug.Assert(from != null);
Type underlying = Enum.GetUnderlyingType(_t);
- // Order checks in order of likelihood. int first as the vast majority of enums
- // are int-based, then long as that is sometimes used when required for a large set of flags
- // and so-on.
- if (underlying == typeof(int))
- {
- // If from is neither an int nor a type assignable to int (viz. an int-backed enum)
- // this will cause an InvalidCastException, which is what this operation should
- // throw in this case.
- frame.Push(Enum.ToObject(_t, (int)from));
- }
- else if (underlying == typeof(long))
- {
- frame.Push(Enum.ToObject(_t, (long)from));
- }
- else if (underlying == typeof(uint))
- {
- frame.Push(Enum.ToObject(_t, (uint)from));
- }
- else if (underlying == typeof(ulong))
- {
- frame.Push(Enum.ToObject(_t, (ulong)from));
- }
- else if (underlying == typeof(byte))
- {
- frame.Push(Enum.ToObject(_t, (byte)from));
- }
- else if (underlying == typeof(sbyte))
- {
- frame.Push(Enum.ToObject(_t, (sbyte)from));
- }
- else if (underlying == typeof(short))
- {
- frame.Push(Enum.ToObject(_t, (short)from));
- }
- else if (underlying == typeof(ushort))
- {
- frame.Push(Enum.ToObject(_t, (ushort)from));
- }
- else if (underlying == typeof(char))
- {
- // Disallowed in C#, but allowed in CIL
- frame.Push(Enum.ToObject(_t, (char)from));
- }
- else
- {
- // Only remaining possible type.
- // Disallowed in C#, but allowed in CIL
- Debug.Assert(underlying == typeof(bool));
- frame.Push(Enum.ToObject(_t, (bool)from));
+
+ // If from is neither a T nor a type assignable to T (viz. an T-backed enum)
+ // this will cause an InvalidCastException, which is what this operation should
+ // throw in this case.
+
+ switch (underlying.GetTypeCode())
+ {
+ case TypeCode.Int32:
+ frame.Push(Enum.ToObject(_t, (int)from));
+ break;
+ case TypeCode.Int64:
+ frame.Push(Enum.ToObject(_t, (long)from));
+ break;
+ case TypeCode.UInt32:
+ frame.Push(Enum.ToObject(_t, (uint)from));
+ break;
+ case TypeCode.UInt64:
+ frame.Push(Enum.ToObject(_t, (ulong)from));
+ break;
+ case TypeCode.Byte:
+ frame.Push(Enum.ToObject(_t, (byte)from));
+ break;
+ case TypeCode.SByte:
+ frame.Push(Enum.ToObject(_t, (sbyte)from));
+ break;
+ case TypeCode.Int16:
+ frame.Push(Enum.ToObject(_t, (short)from));
+ break;
+ case TypeCode.UInt16:
+ frame.Push(Enum.ToObject(_t, (ushort)from));
+ break;
+ case TypeCode.Char:
+ // Disallowed in C#, but allowed in CIL
+ frame.Push(Enum.ToObject(_t, (char)from));
+ break;
+ default:
+ // Only remaining possible type.
+ // Disallowed in C#, but allowed in CIL
+ Debug.Assert(underlying == typeof(bool));
+ frame.Push(Enum.ToObject(_t, (bool)from));
+ break;
}
return 1;
@@ -528,7 +520,7 @@ namespace System.Linq.Expressions.Interpreter
operand = new ExpressionQuoter(_hoistedVariables, frame).Visit(operand);
}
frame.Push(operand);
- return +1;
+ return 1;
}
// Modifies a quoted Expression instance by changing hoisted variables and
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/Utilities.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/Utilities.cs
index 3361b3b0f8..0b477b41ea 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/Utilities.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/Utilities.cs
@@ -7,6 +7,7 @@ using System.Diagnostics;
using System.Dynamic.Utils;
using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
using System.Threading;
namespace System.Linq.Expressions.Interpreter
@@ -26,7 +27,7 @@ namespace System.Linq.Expressions.Interpreter
// the arity is small enough to fit in Func<...> or Action<...>
if (types.Length > MaximumArity || types.Any(t => t.IsByRef))
{
- throw Assert.Unreachable;
+ throw ContractUtils.Unreachable;
}
Type returnType = types[types.Length - 1];
@@ -78,7 +79,7 @@ namespace System.Linq.Expressions.Interpreter
case 17: return typeof(Func<,,,,,,,,,,,,,,,,>).MakeGenericType(types);
}
}
- throw Assert.Unreachable;
+ throw ContractUtils.Unreachable;
}
}
#endif
@@ -114,40 +115,40 @@ namespace System.Linq.Expressions.Interpreter
result = Utils.BoxedFalse;
break;
case TypeCode.SByte:
- result = default(sbyte);
+ result = Utils.BoxedDefaultSByte;
break;
case TypeCode.Byte:
- result = default(byte);
+ result = Utils.BoxedDefaultByte;
break;
case TypeCode.Char:
- result = default(char);
+ result = Utils.BoxedDefaultChar;
break;
case TypeCode.Int16:
- result = default(short);
+ result = Utils.BoxedDefaultInt16;
break;
case TypeCode.Int32:
result = Utils.BoxedInt0;
break;
case TypeCode.Int64:
- result = default(long);
+ result = Utils.BoxedDefaultInt64;
break;
case TypeCode.UInt16:
- result = default(ushort);
+ result = Utils.BoxedDefaultUInt16;
break;
case TypeCode.UInt32:
- result = default(uint);
+ result = Utils.BoxedDefaultUInt32;
break;
case TypeCode.UInt64:
- result = default(ulong);
+ result = Utils.BoxedDefaultUInt64;
break;
case TypeCode.Single:
- return default(float);
+ return Utils.BoxedDefaultSingle;
case TypeCode.Double:
- return default(double);
+ return Utils.BoxedDefaultDouble;
case TypeCode.DateTime:
- return default(DateTime);
+ return Utils.BoxedDefaultDateTime;
case TypeCode.Decimal:
- return default(decimal);
+ return Utils.BoxedDefaultDecimal;
default:
// Also covers DBNull which is a class.
return null;
@@ -164,55 +165,14 @@ namespace System.Linq.Expressions.Interpreter
internal static class ExceptionHelpers
{
-#if FEATURE_STACK_TRACES
- private const string prevStackTraces = "PreviousStackTraces";
-#endif
-
/// <summary>
/// Updates an exception before it's getting re-thrown so
/// we can present a reasonable stack trace to the user.
/// </summary>
- public static Exception UpdateForRethrow(Exception rethrow)
- {
-#if FEATURE_STACK_TRACES
- List<StackTrace> prev;
-
- // we don't have any dynamic stack trace data, capture the data we can
- // from the raw exception object.
- StackTrace st = new StackTrace(rethrow, true);
-
- if (!TryGetAssociatedStackTraces(rethrow, out prev))
- {
- prev = new List<StackTrace>();
- AssociateStackTraces(rethrow, prev);
- }
-
- prev.Add(st);
-
-#endif // FEATURE_STACK_TRACES
- return rethrow;
- }
-#if FEATURE_STACK_TRACES
- /// <summary>
- /// Returns all the stack traces associates with an exception
- /// </summary>
- public static IList<StackTrace> GetExceptionStackTraces(Exception rethrow)
- {
- List<StackTrace> result;
- return TryGetAssociatedStackTraces(rethrow, out result) ? result : null;
- }
-
- private static void AssociateStackTraces(Exception e, List<StackTrace> traces)
- {
- e.Data[prevStackTraces] = traces;
- }
-
- private static bool TryGetAssociatedStackTraces(Exception e, out List<StackTrace> traces)
+ public static void UnwrapAndRethrow(TargetInvocationException exception)
{
- traces = e.Data[prevStackTraces] as List<StackTrace>;
- return traces != null;
+ ExceptionDispatchInfo.Capture(exception.InnerException).Throw();
}
-#endif // FEATURE_STACK_TRACES
}
/// <summary>
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs
index 19973c7778..b0b48a1be3 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs
@@ -36,6 +36,8 @@ namespace System.Linq.Expressions
internal abstract Type TypeCore { get; }
+ internal abstract Type PublicType { get; }
+
/// <summary>
/// Returns the node type of this <see cref="Expression"/>. (Inherited from <see cref="Expression"/>.)
/// </summary>
@@ -168,6 +170,8 @@ namespace System.Linq.Expressions
internal sealed override Type TypeCore => typeof(TDelegate);
+ internal override Type PublicType => typeof(Expression<TDelegate>);
+
/// <summary>
/// Produces a delegate that represents the lambda expression.
/// </summary>
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/ListInitExpression.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/ListInitExpression.cs
index 69d4f38ac2..7b331d9b8a 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/ListInitExpression.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/ListInitExpression.cs
@@ -123,7 +123,7 @@ namespace System.Linq.Expressions
}
MethodInfo addMethod = FindMethod(newExpression.Type, "Add", null, new Expression[] { initializerlist[0] }, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
- return ListInit(newExpression, addMethod, initializers);
+ return ListInit(newExpression, addMethod, initializerlist);
}
/// <summary>
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/NewArrayExpression.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/NewArrayExpression.cs
index 60af5a97c2..b138c52458 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/NewArrayExpression.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/NewArrayExpression.cs
@@ -250,7 +250,7 @@ namespace System.Linq.Expressions
arrayType = type.MakeArrayType(dimensions);
}
- return NewArrayExpression.Make(ExpressionType.NewArrayBounds, arrayType, bounds.ToReadOnly());
+ return NewArrayExpression.Make(ExpressionType.NewArrayBounds, arrayType, boundsList);
}
#endregion
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/NewExpression.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/NewExpression.cs
index 40289b7e87..b9b74107a8 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/NewExpression.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/NewExpression.cs
@@ -193,7 +193,7 @@ namespace System.Linq.Expressions
if (!type.GetTypeInfo().IsValueType)
{
- ConstructorInfo ci = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SingleOrDefault(c => c.GetParameters().Length == 0);
+ ConstructorInfo ci = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SingleOrDefault(c => c.GetParametersCached().Length == 0);
if (ci == null)
{
throw Error.TypeMissingDefaultConstructor(type, nameof(type));
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Strings.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Strings.cs
index 0b8a339d5c..0a43a84b61 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Strings.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Strings.cs
@@ -75,6 +75,11 @@ namespace System.Linq.Expressions
internal static string SetterMustBeVoid => SR.SetterMustBeVoid;
/// <summary>
+ /// A string like "Property type must match the value type of getter"
+ /// </summary>
+ internal static string PropertyTypeMustMatchGetter => SR.PropertyTypeMustMatchGetter;
+
+ /// <summary>
/// A string like "Property type must match the value type of setter"
/// </summary>
internal static string PropertyTypeMustMatchSetter => SR.PropertyTypeMustMatchSetter;
@@ -360,7 +365,7 @@ namespace System.Linq.Expressions
internal static string ArgumentMustBeArrayIndexType => SR.ArgumentMustBeArrayIndexType;
/// <summary>
- /// A string like "Argument must be single dimensional array type"
+ /// A string like "Argument must be single-dimensional, zero-based array type"
/// </summary>
internal static string ArgumentMustBeSingleDimensionalArrayType => SR.ArgumentMustBeSingleDimensionalArrayType;
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/UnaryExpression.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/UnaryExpression.cs
index 6a671473ca..6bc67e1013 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/UnaryExpression.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/UnaryExpression.cs
@@ -844,16 +844,16 @@ namespace System.Linq.Expressions
return GetMethodBasedCoercionOperator(ExpressionType.ConvertChecked, expression, type, method);
}
- /// <summary>Creates a <see cref="UnaryExpression"/> that represents getting the length of a one-dimensional array.</summary>
+ /// <summary>Creates a <see cref="UnaryExpression"/> that represents getting the length of a one-dimensional, zero-based array.</summary>
/// <returns>A <see cref="UnaryExpression"/> that has the <see cref="NodeType"/> property equal to <see cref="ExpressionType.ArrayLength"/> and the <see cref="UnaryExpression.Operand"/> property equal to <paramref name="array"/>.</returns>
/// <param name="array">An <see cref="Expression"/> to set the <see cref="UnaryExpression.Operand"/> property equal to.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="array"/> is null.</exception>
/// <exception cref="ArgumentException">
- /// <paramref name="array"/>.Type does not represent an array type.</exception>
+ /// <paramref name="array"/>.Type does not represent a single-dimensional, zero-based array type.</exception>
public static UnaryExpression ArrayLength(Expression array)
{
- ContractUtils.RequiresNotNull(array, nameof(array));
+ RequiresCanRead(array, nameof(array));
if (!array.Type.IsArray || !typeof(Array).IsAssignableFrom(array.Type))
{
throw Error.ArgumentMustBeArray(nameof(array));
@@ -873,9 +873,13 @@ namespace System.Linq.Expressions
public static UnaryExpression Quote(Expression expression)
{
RequiresCanRead(expression, nameof(expression));
- bool validQuote = expression is LambdaExpression;
- if (!validQuote) throw Error.QuotedExpressionMustBeLambda(nameof(expression));
- return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null);
+ LambdaExpression lambda = expression as LambdaExpression;
+ if (lambda == null)
+ {
+ throw Error.QuotedExpressionMustBeLambda(nameof(expression));
+ }
+
+ return new UnaryExpression(ExpressionType.Quote, lambda, lambda.PublicType, null);
}
/// <summary>
diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Utils.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Utils.cs
index 9e62bee278..815668c460 100644
--- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Utils.cs
+++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Utils.cs
@@ -8,12 +8,26 @@ namespace System.Linq.Expressions
{
public static readonly object BoxedFalse = false;
public static readonly object BoxedTrue = true;
+
public static readonly object BoxedIntM1 = -1;
public static readonly object BoxedInt0 = 0;
public static readonly object BoxedInt1 = 1;
public static readonly object BoxedInt2 = 2;
public static readonly object BoxedInt3 = 3;
+ public static readonly object BoxedDefaultSByte = default(sbyte);
+ public static readonly object BoxedDefaultChar = default(char);
+ public static readonly object BoxedDefaultInt16 = default(short);
+ public static readonly object BoxedDefaultInt64 = default(long);
+ public static readonly object BoxedDefaultByte = default(byte);
+ public static readonly object BoxedDefaultUInt16 = default(ushort);
+ public static readonly object BoxedDefaultUInt32 = default(uint);
+ public static readonly object BoxedDefaultUInt64 = default(ulong);
+ public static readonly object BoxedDefaultSingle = default(float);
+ public static readonly object BoxedDefaultDouble = default(double);
+ public static readonly object BoxedDefaultDecimal = default(decimal);
+ public static readonly object BoxedDefaultDateTime = default(DateTime);
+
private static readonly ConstantExpression s_true = Expression.Constant(BoxedTrue);
private static readonly ConstantExpression s_false = Expression.Constant(BoxedFalse);
diff --git a/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSite.cs b/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSite.cs
index c25c3dafd9..fa99ef68c0 100644
--- a/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSite.cs
+++ b/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSite.cs
@@ -364,44 +364,47 @@ namespace System.Runtime.CompilerServices
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
private T CreateCustomUpdateDelegate(MethodInfo invoke)
{
- var body = new List<Expression>();
- var vars = new List<ParameterExpression>();
+ Type returnType = invoke.GetReturnType();
+ bool isVoid = returnType == typeof(void);
- ParameterExpression[] @params = invoke.GetParametersCached().Map(p => Expression.Parameter(p.ParameterType, p.Name));
- LabelTarget @return = Expression.Label(invoke.GetReturnType());
+ var body = new ArrayBuilder<Expression>(13);
+ var vars = new ArrayBuilder<ParameterExpression>(8 + (isVoid ? 0 : 1));
+
+ ParameterExpression[] @params = Array.ConvertAll(invoke.GetParametersCached(), p => Expression.Parameter(p.ParameterType, p.Name));
+ LabelTarget @return = Expression.Label(returnType);
Type[] typeArgs = new[] { typeof(T) };
ParameterExpression site = @params[0];
ParameterExpression[] arguments = @params.RemoveFirst();
ParameterExpression @this = Expression.Variable(typeof(CallSite<T>), "this");
- vars.Add(@this);
- body.Add(Expression.Assign(@this, Expression.Convert(site, @this.Type)));
+ vars.UncheckedAdd(@this);
+ body.UncheckedAdd(Expression.Assign(@this, Expression.Convert(site, @this.Type)));
ParameterExpression applicable = Expression.Variable(typeof(T[]), "applicable");
- vars.Add(applicable);
+ vars.UncheckedAdd(applicable);
ParameterExpression rule = Expression.Variable(typeof(T), "rule");
- vars.Add(rule);
+ vars.UncheckedAdd(rule);
ParameterExpression originalRule = Expression.Variable(typeof(T), "originalRule");
- vars.Add(originalRule);
+ vars.UncheckedAdd(originalRule);
Expression target = Expression.Field(@this, nameof(Target));
- body.Add(Expression.Assign(originalRule, target));
+ body.UncheckedAdd(Expression.Assign(originalRule, target));
ParameterExpression result = null;
- if (@return.Type != typeof(void))
+ if (!isVoid)
{
- vars.Add(result = Expression.Variable(@return.Type, "result"));
+ vars.UncheckedAdd(result = Expression.Variable(@return.Type, "result"));
}
ParameterExpression count = Expression.Variable(typeof(int), "count");
- vars.Add(count);
+ vars.UncheckedAdd(count);
ParameterExpression index = Expression.Variable(typeof(int), "index");
- vars.Add(index);
+ vars.UncheckedAdd(index);
- body.Add(
+ body.UncheckedAdd(
Expression.Assign(
site,
Expression.Call(
@@ -411,22 +414,24 @@ namespace System.Runtime.CompilerServices
)
);
- Expression invokeRule;
+ Expression processRule;
Expression getMatch = Expression.Call(CallSiteOps_GetMatch, site);
Expression resetMatch = Expression.Call(CallSiteOps_ClearMatch, site);
+ Expression invokeRule = Expression.Invoke(rule, new TrueReadOnlyCollection<Expression>(@params));
+
Expression onMatch = Expression.Call(
CallSiteOps_UpdateRules.MakeGenericMethod(typeArgs),
@this,
index
);
- if (@return.Type == typeof(void))
+ if (isVoid)
{
- invokeRule = Expression.Block(
- Expression.Invoke(rule, new TrueReadOnlyCollection<Expression>(@params)),
+ processRule = Expression.Block(
+ invokeRule,
Expression.IfThen(
getMatch,
Expression.Block(onMatch, Expression.Return(@return))
@@ -435,8 +440,8 @@ namespace System.Runtime.CompilerServices
}
else
{
- invokeRule = Expression.Block(
- Expression.Assign(result, Expression.Invoke(rule, new TrueReadOnlyCollection<Expression>(@params))),
+ processRule = Expression.Block(
+ Expression.Assign(result, invokeRule),
Expression.IfThen(
getMatch,
Expression.Block(onMatch, Expression.Return(@return, result))
@@ -444,7 +449,8 @@ namespace System.Runtime.CompilerServices
);
}
- Expression getRule = Expression.Assign(rule, Expression.ArrayAccess(applicable, index));
+ Expression getApplicableRuleAtIndex = Expression.Assign(rule, Expression.ArrayAccess(applicable, new TrueReadOnlyCollection<Expression>(index)));
+ Expression getRule = getApplicableRuleAtIndex;
LabelTarget @break = Expression.Label();
@@ -455,7 +461,7 @@ namespace System.Runtime.CompilerServices
Expression incrementIndex = Expression.PreIncrementAssign(index);
- body.Add(
+ body.UncheckedAdd(
Expression.IfThen(
Expression.NotEqual(
Expression.Assign(
@@ -484,7 +490,7 @@ namespace System.Runtime.CompilerServices
target,
rule
),
- invokeRule,
+ processRule,
resetMatch
)
),
@@ -505,16 +511,16 @@ namespace System.Runtime.CompilerServices
//// Any applicable rules in level 2 cache?
////
ParameterExpression cache = Expression.Variable(typeof(RuleCache<T>), "cache");
- vars.Add(cache);
+ vars.UncheckedAdd(cache);
- body.Add(
+ body.UncheckedAdd(
Expression.Assign(
cache,
Expression.Call(CallSiteOps_GetRuleCache.MakeGenericMethod(typeArgs), @this)
)
);
- body.Add(
+ body.UncheckedAdd(
Expression.Assign(
applicable,
Expression.Call(CallSiteOps_GetCachedRules.MakeGenericMethod(typeArgs), cache)
@@ -522,10 +528,10 @@ namespace System.Runtime.CompilerServices
);
// L2 invokeRule is different (no onMatch)
- if (@return.Type == typeof(void))
+ if (isVoid)
{
- invokeRule = Expression.Block(
- Expression.Invoke(rule, new TrueReadOnlyCollection<Expression>(@params)),
+ processRule = Expression.Block(
+ invokeRule,
Expression.IfThen(
getMatch,
Expression.Return(@return)
@@ -534,8 +540,8 @@ namespace System.Runtime.CompilerServices
}
else
{
- invokeRule = Expression.Block(
- Expression.Assign(result, Expression.Invoke(rule, new TrueReadOnlyCollection<Expression>(@params))),
+ processRule = Expression.Block(
+ Expression.Assign(result, invokeRule),
Expression.IfThen(
getMatch,
Expression.Return(@return, result)
@@ -544,7 +550,7 @@ namespace System.Runtime.CompilerServices
}
Expression tryRule = Expression.TryFinally(
- invokeRule,
+ processRule,
Expression.IfThen(
getMatch,
Expression.Block(
@@ -556,12 +562,12 @@ namespace System.Runtime.CompilerServices
getRule = Expression.Assign(
target,
- Expression.Assign(rule, Expression.ArrayAccess(applicable, index))
+ getApplicableRuleAtIndex
);
- body.Add(Expression.Assign(index, Utils.Constant(0)));
- body.Add(Expression.Assign(count, Expression.ArrayLength(applicable)));
- body.Add(
+ body.UncheckedAdd(Expression.Assign(index, Utils.Constant(0)));
+ body.UncheckedAdd(Expression.Assign(count, Expression.ArrayLength(applicable)));
+ body.UncheckedAdd(
Expression.Loop(
Expression.Block(
breakIfDone,
@@ -578,12 +584,12 @@ namespace System.Runtime.CompilerServices
////
//// Miss on Level 0, 1 and 2 caches. Create new rule
////
- body.Add(Expression.Assign(rule, Expression.Constant(null, rule.Type)));
+ body.UncheckedAdd(Expression.Assign(rule, Expression.Constant(null, rule.Type)));
ParameterExpression args = Expression.Variable(typeof(object[]), "args");
- Expression[] argsElements = arguments.Map(p => Convert(p, typeof(object)));
- vars.Add(args);
- body.Add(
+ Expression[] argsElements = Array.ConvertAll(arguments, p => Convert(p, typeof(object)));
+ vars.UncheckedAdd(args);
+ body.UncheckedAdd(
Expression.Assign(
args,
Expression.NewArrayInit(typeof(object), new TrueReadOnlyCollection<Expression>(argsElements))
@@ -609,7 +615,7 @@ namespace System.Runtime.CompilerServices
);
tryRule = Expression.TryFinally(
- invokeRule,
+ processRule,
Expression.IfThen(
getMatch,
Expression.Call(
@@ -620,7 +626,7 @@ namespace System.Runtime.CompilerServices
)
);
- body.Add(
+ body.UncheckedAdd(
Expression.Loop(
Expression.Block(setOldTarget, getRule, tryRule, resetMatch),
@break: null,
@@ -628,7 +634,7 @@ namespace System.Runtime.CompilerServices
)
);
- body.Add(Expression.Default(@return.Type));
+ body.UncheckedAdd(Expression.Default(@return.Type));
Expression<T> lambda = Expression.Lambda<T>(
Expression.Label(
@@ -651,7 +657,7 @@ namespace System.Runtime.CompilerServices
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
private T CreateCustomNoMatchDelegate(MethodInfo invoke)
{
- ParameterExpression[] @params = invoke.GetParametersCached().Map(p => Expression.Parameter(p.ParameterType, p.Name));
+ ParameterExpression[] @params = Array.ConvertAll(invoke.GetParametersCached(), p => Expression.Parameter(p.ParameterType, p.Name));
return Expression.Lambda<T>(
Expression.Block(
Expression.Call(
diff --git a/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSiteBinder.cs b/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSiteBinder.cs
index ec4b5e9b0e..45f0328f02 100644
--- a/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSiteBinder.cs
+++ b/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSiteBinder.cs
@@ -194,7 +194,7 @@ namespace System.Runtime.CompilerServices
Expression.Convert(site, siteType),
typeof(CallSite<T>).GetProperty(nameof(CallSite<T>.Update))
),
- new TrueReadOnlyCollection<Expression>(@params)
+ @params
)
)
)
@@ -204,7 +204,7 @@ namespace System.Runtime.CompilerServices
Expression.Block(body),
CallSite.CallSiteTargetMethodName,
true, // always compile the rules with tail call optimization
- new TrueReadOnlyCollection<ParameterExpression>(@params)
+ @params
);
}
diff --git a/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/ReadOnlyCollectionBuilder.cs b/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/ReadOnlyCollectionBuilder.cs
index 5959bf286b..2af520353a 100644
--- a/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/ReadOnlyCollectionBuilder.cs
+++ b/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/ReadOnlyCollectionBuilder.cs
@@ -2,6 +2,7 @@
// 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.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic.Utils;
@@ -14,7 +15,7 @@ namespace System.Runtime.CompilerServices
/// <typeparam name="T">The type of the collection element.</typeparam>
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
- public sealed class ReadOnlyCollectionBuilder<T> : IList<T>, System.Collections.IList
+ public sealed class ReadOnlyCollectionBuilder<T> : IList<T>, IList
{
private const int DefaultCapacity = 4;
@@ -22,9 +23,6 @@ namespace System.Runtime.CompilerServices
private int _size;
private int _version;
- [NonSerialized]
- private Object _syncRoot;
-
/// <summary>
/// Constructs a <see cref="ReadOnlyCollectionBuilder{T}"/>.
/// </summary>
@@ -41,7 +39,9 @@ namespace System.Runtime.CompilerServices
/// <param name="capacity">Initial capacity of the builder.</param>
public ReadOnlyCollectionBuilder(int capacity)
{
- ContractUtils.Requires(capacity >= 0, nameof(capacity));
+ if (capacity < 0)
+ throw new ArgumentOutOfRangeException(nameof(capacity));
+
_items = new T[capacity];
}
@@ -51,7 +51,8 @@ namespace System.Runtime.CompilerServices
/// <param name="collection">The collection whose elements to copy to the builder.</param>
public ReadOnlyCollectionBuilder(IEnumerable<T> collection)
{
- ContractUtils.Requires(collection != null, nameof(collection));
+ if (collection == null)
+ throw new ArgumentNullException(nameof(collection));
ICollection<T> c = collection as ICollection<T>;
if (c != null)
@@ -84,7 +85,8 @@ namespace System.Runtime.CompilerServices
get { return _items.Length; }
set
{
- ContractUtils.Requires(value >= _size, nameof(value));
+ if (value < _size)
+ throw new ArgumentOutOfRangeException(nameof(value));
if (value != _items.Length)
{
@@ -129,7 +131,8 @@ namespace System.Runtime.CompilerServices
/// <param name="item">The object to insert into the <see cref="ReadOnlyCollectionBuilder{T}"/>.</param>
public void Insert(int index, T item)
{
- ContractUtils.Requires(index <= _size, nameof(index));
+ if (index > _size)
+ throw new ArgumentOutOfRangeException(nameof(index));
if (_size == _items.Length)
{
@@ -150,7 +153,8 @@ namespace System.Runtime.CompilerServices
/// <param name="index">The zero-based index of the item to remove.</param>
public void RemoveAt(int index)
{
- ContractUtils.Requires(index >= 0 && index < _size, nameof(index));
+ if (index < 0 || index >= _size)
+ throw new ArgumentOutOfRangeException(nameof(index));
_size--;
if (index < _size)
@@ -170,12 +174,16 @@ namespace System.Runtime.CompilerServices
{
get
{
- ContractUtils.Requires(index < _size, nameof(index));
+ if (index >= _size)
+ throw new ArgumentOutOfRangeException(nameof(index));
+
return _items[index];
}
set
{
- ContractUtils.Requires(index < _size, nameof(index));
+ if (index >= _size)
+ throw new ArgumentOutOfRangeException(nameof(index));
+
_items[index] = value;
_version++;
}
@@ -219,11 +227,11 @@ namespace System.Runtime.CompilerServices
/// <returns>true if item is found in the <see cref="ReadOnlyCollectionBuilder{T}"/>; otherwise, false.</returns>
public bool Contains(T item)
{
- if ((Object)item == null)
+ if ((object)item == null)
{
for (int i = 0; i < _size; i++)
{
- if ((Object)_items[i] == null)
+ if ((object)_items[i] == null)
{
return true;
}
@@ -284,27 +292,21 @@ namespace System.Runtime.CompilerServices
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.</returns>
- public IEnumerator<T> GetEnumerator()
- {
- return new Enumerator(this);
- }
+ public IEnumerator<T> GetEnumerator() => new Enumerator(this);
#endregion
#region IEnumerable Members
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
#endregion
#region IList Members
- bool System.Collections.IList.IsReadOnly => false;
+ bool IList.IsReadOnly => false;
- int System.Collections.IList.Add(object value)
+ int IList.Add(object value)
{
ValidateNullValue(value, nameof(value));
try
@@ -313,12 +315,12 @@ namespace System.Runtime.CompilerServices
}
catch (InvalidCastException)
{
- ThrowInvalidTypeException(value, nameof(value));
+ throw InvalidTypeException(value, nameof(value));
}
return Count - 1;
}
- bool System.Collections.IList.Contains(object value)
+ bool IList.Contains(object value)
{
if (IsCompatibleObject(value))
{
@@ -327,7 +329,7 @@ namespace System.Runtime.CompilerServices
else return false;
}
- int System.Collections.IList.IndexOf(object value)
+ int IList.IndexOf(object value)
{
if (IsCompatibleObject(value))
{
@@ -336,7 +338,7 @@ namespace System.Runtime.CompilerServices
return -1;
}
- void System.Collections.IList.Insert(int index, object value)
+ void IList.Insert(int index, object value)
{
ValidateNullValue(value, nameof(value));
try
@@ -345,13 +347,13 @@ namespace System.Runtime.CompilerServices
}
catch (InvalidCastException)
{
- ThrowInvalidTypeException(value, nameof(value));
+ throw InvalidTypeException(value, nameof(value));
}
}
- bool System.Collections.IList.IsFixedSize => false;
+ bool IList.IsFixedSize => false;
- void System.Collections.IList.Remove(object value)
+ void IList.Remove(object value)
{
if (IsCompatibleObject(value))
{
@@ -359,7 +361,7 @@ namespace System.Runtime.CompilerServices
}
}
- object System.Collections.IList.this[int index]
+ object IList.this[int index]
{
get
{
@@ -375,7 +377,7 @@ namespace System.Runtime.CompilerServices
}
catch (InvalidCastException)
{
- ThrowInvalidTypeException(value, nameof(value));
+ throw InvalidTypeException(value, nameof(value));
}
}
}
@@ -384,26 +386,19 @@ namespace System.Runtime.CompilerServices
#region ICollection Members
- void System.Collections.ICollection.CopyTo(Array array, int index)
+ void ICollection.CopyTo(Array array, int index)
{
- ContractUtils.RequiresNotNull(array, nameof(array));
- ContractUtils.Requires(array.Rank == 1, nameof(array));
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+ if (array.Rank != 1)
+ throw new ArgumentException(nameof(array));
+
Array.Copy(_items, 0, array, index, _size);
}
- bool System.Collections.ICollection.IsSynchronized => false;
+ bool ICollection.IsSynchronized => false;
- object System.Collections.ICollection.SyncRoot
- {
- get
- {
- if (_syncRoot == null)
- {
- System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), comparand: null);
- }
- return _syncRoot;
- }
- }
+ object ICollection.SyncRoot => this;
#endregion
@@ -422,8 +417,10 @@ namespace System.Runtime.CompilerServices
/// <param name="count">The number of elements in the range to reverse.</param>
public void Reverse(int index, int count)
{
- ContractUtils.Requires(index >= 0, nameof(index));
- ContractUtils.Requires(count >= 0, nameof(count));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count));
Array.Reverse(_items, index, count);
_version++;
@@ -495,13 +492,13 @@ namespace System.Runtime.CompilerServices
}
}
- private static void ThrowInvalidTypeException(object value, string argument)
+ private static Exception InvalidTypeException(object value, string argument)
{
- throw new ArgumentException(Strings.InvalidObjectType(value != null ? value.GetType() : (object)"null", typeof(T)), argument);
+ return new ArgumentException(Strings.InvalidObjectType(value != null ? value.GetType() : (object)"null", typeof(T)), argument);
}
[Serializable]
- private class Enumerator : IEnumerator<T>, System.Collections.IEnumerator
+ private class Enumerator : IEnumerator<T>, IEnumerator
{
private readonly ReadOnlyCollectionBuilder<T> _builder;
private readonly int _version;
@@ -533,7 +530,7 @@ namespace System.Runtime.CompilerServices
#region IEnumerator Members
- object System.Collections.IEnumerator.Current
+ object IEnumerator.Current
{
get
{
@@ -571,7 +568,7 @@ namespace System.Runtime.CompilerServices
#region IEnumerator Members
- void System.Collections.IEnumerator.Reset()
+ void IEnumerator.Reset()
{
if (_version != _builder._version)
{
@@ -580,6 +577,7 @@ namespace System.Runtime.CompilerServices
_index = 0;
_current = default(T);
}
+
#endregion
}
}
diff --git a/src/Common/src/System/Runtime/CompilerServices/TrueReadOnlyCollection.cs b/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/TrueReadOnlyCollection.cs
index 03b038cb19..03b038cb19 100644
--- a/src/Common/src/System/Runtime/CompilerServices/TrueReadOnlyCollection.cs
+++ b/src/System.Linq.Expressions/src/System/Runtime/CompilerServices/TrueReadOnlyCollection.cs
diff --git a/src/System.Linq.Expressions/tests/Array/ArrayAccessTests.cs b/src/System.Linq.Expressions/tests/Array/ArrayAccessTests.cs
index 35357ab3a4..8ae11e8660 100644
--- a/src/System.Linq.Expressions/tests/Array/ArrayAccessTests.cs
+++ b/src/System.Linq.Expressions/tests/Array/ArrayAccessTests.cs
@@ -2,6 +2,7 @@
// 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.Reflection;
using Xunit;
@@ -9,6 +10,8 @@ namespace System.Linq.Expressions.Tests
{
public static class ArrayAccessTests
{
+ private static IEnumerable<object[]> Ranks() => Enumerable.Range(1, 5).Select(i => new object[] {i});
+
[Theory]
[ClassData(typeof(CompilationTypes))]
public static void ArrayAccess_MultiDimensionalOf1(bool useInterpreter)
@@ -41,5 +44,78 @@ namespace System.Linq.Expressions.Tests
Func<int> get = Expression.Lambda<Func<int>>(e).Compile(useInterpreter);
Assert.Equal(42, get());
}
+
+ [Fact]
+ public static void InstanceIsNotArray()
+ {
+ ConstantExpression instance = Expression.Constant(46);
+ ConstantExpression index = Expression.Constant(2);
+ Assert.Throws<ArgumentException>("array", () => Expression.ArrayAccess(instance, index));
+ }
+
+ [Fact]
+ public static void WrongNumberIndices()
+ {
+ ConstantExpression instance = Expression.Constant(new int[2,3]);
+ ConstantExpression index = Expression.Constant(2);
+ Assert.Throws<ArgumentException>(() => Expression.ArrayAccess(instance, index));
+ }
+
+ [Fact]
+ public static void NonInt32Index()
+ {
+ ConstantExpression instance = Expression.Constant(new int[4]);
+ ConstantExpression index = Expression.Constant("2");
+ Assert.Throws<ArgumentException>("indexes", () => Expression.ArrayAccess(instance, index));
+ }
+
+ [Fact]
+ public static void UnreadableIndex()
+ {
+ ConstantExpression instance = Expression.Constant(new int[4]);
+ MemberExpression index = Expression.Property(null, typeof(Unreadable<int>).GetProperty(nameof(Unreadable<int>.WriteOnly)));
+ Assert.Throws<ArgumentException>("indexes", () => Expression.ArrayAccess(instance, index));
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public static void NonZeroBasedOneDimensionalArrayAccess(bool useInterpreter)
+ {
+ Array arrayObj = Array.CreateInstance(typeof(int), new[] { 3 }, new[] { -1 });
+ arrayObj.SetValue(5, -1);
+ arrayObj.SetValue(6, 0);
+ arrayObj.SetValue(7, 1);
+ ConstantExpression array = Expression.Constant(arrayObj);
+ IndexExpression indexM1 = Expression.ArrayAccess(array, Expression.Constant(-1));
+ IndexExpression index0 = Expression.ArrayAccess(array, Expression.Constant(0));
+ IndexExpression index1 = Expression.ArrayAccess(array, Expression.Constant(1));
+ Action setValues = Expression.Lambda<Action>(
+ Expression.Block(
+ Expression.Assign(indexM1, Expression.Constant(5)),
+ Expression.Assign(index0, Expression.Constant(6)),
+ Expression.Assign(index1, Expression.Constant(7)))).Compile(useInterpreter);
+ setValues();
+ Assert.Equal(5, arrayObj.GetValue(-1));
+ Assert.Equal(6, arrayObj.GetValue(0));
+ Assert.Equal(7, arrayObj.GetValue(1));
+ Func<bool> testValues = Expression.Lambda<Func<bool>>(
+ Expression.And(
+ Expression.Equal(indexM1, Expression.Constant(5)),
+ Expression.And(
+ Expression.Equal(index0, Expression.Constant(6)),
+ Expression.Equal(index1, Expression.Constant(7))))).Compile(useInterpreter);
+ Assert.True(testValues());
+ }
+
+ [Theory, PerCompilationType(nameof(Ranks))]
+ public static void DifferentRanks(int rank, bool useInterpreter)
+ {
+ Array arrayObj = Array.CreateInstance(typeof(string), Enumerable.Repeat(1, rank).ToArray());
+ arrayObj.SetValue("solitary value", Enumerable.Repeat(0, rank).ToArray());
+ ConstantExpression array = Expression.Constant(arrayObj);
+ IEnumerable<DefaultExpression> indices = Enumerable.Repeat(Expression.Default(typeof(int)), rank);
+ Func<string> func = Expression.Lambda<Func<string>>(
+ Expression.ArrayAccess(array, indices)).Compile(useInterpreter);
+ Assert.Equal("solitary value", func());
+ }
}
}
diff --git a/src/System.Linq.Expressions/tests/Array/ArrayArrayIndexTests.cs b/src/System.Linq.Expressions/tests/Array/ArrayArrayIndexTests.cs
index f0553520f1..e9dcb59e9d 100644
--- a/src/System.Linq.Expressions/tests/Array/ArrayArrayIndexTests.cs
+++ b/src/System.Linq.Expressions/tests/Array/ArrayArrayIndexTests.cs
@@ -2669,5 +2669,61 @@ namespace System.Linq.Expressions.Tests
}
#endregion
+
+ [Fact]
+ public static void ArrayIndexNotArray()
+ {
+ Expression intExp = Expression.Constant(1);
+ Assert.Throws<ArgumentException>("array", () => Expression.ArrayIndex(intExp, intExp, intExp));
+ Assert.Throws<ArgumentException>("array", () => Expression.ArrayIndex(intExp, Enumerable.Repeat(intExp, 1)));
+ }
+
+ [Fact]
+ public static void ArrayIndexNullArray()
+ {
+ Assert.Throws<ArgumentNullException>("array", () => Expression.ArrayIndex(null));
+ Assert.Throws<ArgumentNullException>(
+ "array", () => Expression.ArrayIndex(null, Enumerable.Empty<Expression>()));
+ }
+
+ [Fact]
+ public static void ArrayIndexNullIndices()
+ {
+ Expression array = Expression.Constant(new[,] { { 1, 2 }, { 2, 1 } });
+ Assert.Throws<ArgumentNullException>("indexes", () => Expression.ArrayIndex(array, default(Expression[])));
+ Assert.Throws<ArgumentNullException>("indexes[1]",
+ () => Expression.ArrayIndex(array, Expression.Constant(1), null));
+ }
+
+ [Fact]
+ public static void ArrayIndexWrongRank()
+ {
+ Expression array = Expression.Constant(new[,] { { 1, 2 }, { 2, 1 } });
+ Assert.Throws<ArgumentException>(null, () => Expression.ArrayIndex(array, new[] { Expression.Constant(2) }));
+ Assert.Throws<ArgumentException>(null, () =>
+ Expression.ArrayIndex(array, Expression.Constant(2), Expression.Constant(1), Expression.Constant(2)));
+ }
+
+ [Fact]
+ public static void ArrayIndexWrongType()
+ {
+ Expression array = Expression.Constant(new[,] { { 1, 2 }, { 2, 1 } });
+ Assert.Throws<ArgumentException>("indexes[0]", () => Expression.ArrayIndex(array, Expression.Constant(2L), Expression.Constant(1)));
+ }
+
+ [Fact]
+ public static void UnreadableArray()
+ {
+ Expression array = Expression.Property(null, typeof(Unreadable<int[,]>), nameof(Unreadable<int[,]>.WriteOnly));
+ Assert.Throws<ArgumentException>("array", () => Expression.ArrayIndex(array, Expression.Constant(0), Expression.Constant(0)));
+ }
+
+ [Fact]
+ public static void UnreadableIndex()
+ {
+ Expression array = Expression.Constant(new[,] { { 1, 2 }, { 2, 1 } });
+ Expression index = Expression.Property(null, typeof(Unreadable<int>), nameof(Unreadable<int>.WriteOnly));
+ Assert.Throws<ArgumentException>("indexes[0]", () => Expression.ArrayIndex(array, index, index));
+ }
}
}
diff --git a/src/System.Linq.Expressions/tests/Array/ArrayIndexTests.cs b/src/System.Linq.Expressions/tests/Array/ArrayIndexTests.cs
index b054859b71..feab3582d6 100644
--- a/src/System.Linq.Expressions/tests/Array/ArrayIndexTests.cs
+++ b/src/System.Linq.Expressions/tests/Array/ArrayIndexTests.cs
@@ -2720,5 +2720,106 @@ namespace System.Linq.Expressions.Tests
}
#endregion
+
+ [Fact]
+ public static void ArrayIndexNotArray()
+ {
+ Expression intExp = Expression.Constant(1);
+ Assert.Throws<ArgumentException>("array", () => Expression.ArrayIndex(intExp, intExp));
+ }
+
+ [Fact]
+ public static void ArrayIndexNullArray()
+ {
+ Assert.Throws<ArgumentNullException>("array", () => Expression.ArrayIndex(null, Expression.Constant(0)));
+ }
+
+ [Fact]
+ public static void ArrayIndexNullIndices()
+ {
+ Expression array = Expression.Constant(new[] {1, 2});
+ Assert.Throws<ArgumentNullException>("index", () => Expression.ArrayIndex(array, default(Expression)));
+ }
+
+ [Fact]
+ public static void ArrayIndexWrongRank()
+ {
+ Expression array = Expression.Constant(new[,] { { 1, 2 }, { 2, 1 } });
+ Assert.Throws<ArgumentException>(null, () => Expression.ArrayIndex(array, Expression.Constant(2)));
+ }
+
+ [Fact]
+ public static void ArrayIndexWrongType()
+ {
+ Expression array = Expression.Constant(new[] {1, 2});
+ Assert.Throws<ArgumentException>("index", () => Expression.ArrayIndex(array, Expression.Constant(2L)));
+ }
+
+ [Fact]
+ public static void UnreadableArray()
+ {
+ Expression array = Expression.Property(null, typeof(Unreadable<int[]>), nameof(Unreadable<int>.WriteOnly));
+ Assert.Throws<ArgumentException>(() => Expression.ArrayIndex(array, Expression.Constant(0)));
+ }
+
+ [Fact]
+ public static void UnreadableIndex()
+ {
+ Expression array = Expression.Constant(new[] { 1, 2 });
+ Expression index = Expression.Property(null, typeof(Unreadable<int>), nameof(Unreadable<int>.WriteOnly));
+ Assert.Throws<ArgumentException>("index", () => Expression.ArrayIndex(array, index));
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public static void NonZeroBasedOneDimensionalArrayIndex(bool useInterpreter)
+ {
+ Array arrayObj = Array.CreateInstance(typeof(int), new[] { 3 }, new[] { -1 });
+ arrayObj.SetValue(5, -1);
+ arrayObj.SetValue(6, 0);
+ arrayObj.SetValue(7, 1);
+ ConstantExpression array = Expression.Constant(arrayObj);
+ BinaryExpression indexM1 = Expression.ArrayIndex(array, Expression.Constant(-1));
+ BinaryExpression index0 = Expression.ArrayIndex(array, Expression.Constant(0));
+ BinaryExpression index1 = Expression.ArrayIndex(array, Expression.Constant(1));
+ Func<bool> testValues = Expression.Lambda<Func<bool>>(
+ Expression.And(
+ Expression.Equal(indexM1, Expression.Constant(5)),
+ Expression.And(
+ Expression.Equal(index0, Expression.Constant(6)),
+ Expression.Equal(index1, Expression.Constant(7))))).Compile(useInterpreter);
+ Assert.True(testValues());
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public static void NonZeroBasedOneDimensionalArrayIndexMethod(bool useInterpreter)
+ {
+ Array arrayObj = Array.CreateInstance(typeof(int), new[] { 3 }, new[] { -1 });
+ arrayObj.SetValue(5, -1);
+ arrayObj.SetValue(6, 0);
+ arrayObj.SetValue(7, 1);
+ ConstantExpression array = Expression.Constant(arrayObj);
+ MethodCallExpression indexM1 = Expression.ArrayIndex(array, new [] { Expression.Constant(-1)});
+ MethodCallExpression index0 = Expression.ArrayIndex(array, new[] { Expression.Constant(0)});
+ MethodCallExpression index1 = Expression.ArrayIndex(array, new[] { Expression.Constant(1)});
+ Func<bool> testValues = Expression.Lambda<Func<bool>>(
+ Expression.And(
+ Expression.Equal(indexM1, Expression.Constant(5)),
+ Expression.And(
+ Expression.Equal(index0, Expression.Constant(6)),
+ Expression.Equal(index1, Expression.Constant(7))))).Compile(useInterpreter);
+ Assert.True(testValues());
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public static void HighRankArrayIndex(bool useInterpreter)
+ {
+ string[,,,,,,,,,] arrayObj = {{{{{{{{{{"hugz"}}}}}}}}}};
+ ConstantExpression array = Expression.Constant(arrayObj);
+ Func<string> func = Expression.Lambda<Func<string>>(
+ Expression.ArrayIndex(array, Enumerable.Repeat(Expression.Constant(0), 10))).Compile(useInterpreter);
+ Assert.Equal("hugz", func());
+ }
+
+
}
}
diff --git a/src/System.Linq.Expressions/tests/Array/ArrayLengthTests.cs b/src/System.Linq.Expressions/tests/Array/ArrayLengthTests.cs
index d81886bc9e..87007ab788 100644
--- a/src/System.Linq.Expressions/tests/Array/ArrayLengthTests.cs
+++ b/src/System.Linq.Expressions/tests/Array/ArrayLengthTests.cs
@@ -1566,5 +1566,34 @@ namespace System.Linq.Expressions.Tests
}
#endregion
+
+ [Fact]
+ public static void NullArray()
+ {
+ Assert.Throws<ArgumentNullException>("array", () => Expression.ArrayLength(null));
+ }
+
+ [Fact]
+ public static void IsNotArray()
+ {
+ Expression notArray = Expression.Constant(8);
+ Assert.Throws<ArgumentException>("array", () => Expression.ArrayLength(notArray));
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public static void ArrayTypeArrayAllowed(bool useInterpreter)
+ {
+ Array arr = new[] {1, 2, 3};
+ Func<int> func =
+ Expression.Lambda<Func<int>>(Expression.ArrayLength(Expression.Constant(arr))).Compile(useInterpreter);
+ Assert.Equal(3, func());
+ }
+
+ [Fact]
+ public static void UnreadableArray()
+ {
+ Expression array = Expression.Property(null, typeof(Unreadable<int[]>), nameof(Unreadable<int>.WriteOnly));
+ Assert.Throws<ArgumentException>(() => Expression.ArrayLength(array));
+ }
}
}
diff --git a/src/System.Linq.Expressions/tests/Cast/AsNullable.cs b/src/System.Linq.Expressions/tests/Cast/AsNullable.cs
index 480b30530a..37c3080235 100644
--- a/src/System.Linq.Expressions/tests/Cast/AsNullable.cs
+++ b/src/System.Linq.Expressions/tests/Cast/AsNullable.cs
@@ -28,6 +28,46 @@ namespace System.Linq.Expressions.Tests
}
[Theory, ClassData(typeof(CompilationTypes))]
+ public static void CheckEnumAsNullableEnumTypeTest(bool useInterpreter)
+ {
+ E[] array = { 0, E.A, E.B, (E)int.MaxValue, (E)int.MinValue };
+ for (int i = 0; i < array.Length; i++)
+ {
+ VerifyEnumAsNullableEnumType(array[i], useInterpreter);
+ }
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public static void CheckNullableEnumAsNullableEnumTypeTest(bool useInterpreter)
+ {
+ E?[] array = { null, 0, E.A, E.B, (E)int.MaxValue, (E)int.MinValue };
+ for (int i = 0; i < array.Length; i++)
+ {
+ VerifyNullableEnumAsNullableEnumType(array[i], useInterpreter);
+ }
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public static void CheckLongAsNullableEnumTypeTest(bool useInterpreter)
+ {
+ long[] array = { 0, 1, long.MinValue, long.MaxValue };
+ foreach (long value in array)
+ {
+ VerifyLongAsNullableEnumType(value, useInterpreter);
+ }
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public static void CheckNullableLongAsNullableEnumTypeTest(bool useInterpreter)
+ {
+ long?[] array = { null, 0, 1, long.MinValue, long.MaxValue };
+ foreach (long? value in array)
+ {
+ VerifyNullableLongAsNullableEnumType(value, useInterpreter);
+ }
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
public static void CheckNullableEnumAsObjectTest(bool useInterpreter)
{
E?[] array = new E?[] { null, (E)0, E.A, E.B, (E)int.MaxValue, (E)int.MinValue };
@@ -160,6 +200,38 @@ namespace System.Linq.Expressions.Tests
Assert.Equal(value as ValueType, f());
}
+ private static void VerifyEnumAsNullableEnumType(E value, bool useInterpreter)
+ {
+ Expression<Func<E?>> e = Expression.Lambda<Func<E?>>(
+ Expression.TypeAs(Expression.Constant(value), typeof(E?)));
+ Func<E?> f = e.Compile(useInterpreter);
+ Assert.Equal(value, f());
+ }
+
+ private static void VerifyNullableEnumAsNullableEnumType(E? value, bool useInterpreter)
+ {
+ Expression<Func<E?>> e = Expression.Lambda<Func<E?>>(
+ Expression.TypeAs(Expression.Constant(value, typeof(E?)), typeof(E?)));
+ Func<E?> f = e.Compile(useInterpreter);
+ Assert.Equal(value, f());
+ }
+
+ private static void VerifyLongAsNullableEnumType(long value, bool useInterpreter)
+ {
+ Expression<Func<E?>> e = Expression.Lambda<Func<E?>>(
+ Expression.TypeAs(Expression.Constant(value), typeof(E?)));
+ Func<E?> f = e.Compile(useInterpreter);
+ Assert.False(f().HasValue);
+ }
+
+ private static void VerifyNullableLongAsNullableEnumType(long? value, bool useInterpreter)
+ {
+ Expression<Func<E?>> e = Expression.Lambda<Func<E?>>(
+ Expression.TypeAs(Expression.Constant(value, typeof(long?)), typeof(E?)));
+ Func<E?> f = e.Compile(useInterpreter);
+ Assert.False(f().HasValue);
+ }
+
private static void VerifyNullableEnumAsObject(E? value, bool useInterpreter)
{
Expression<Func<object>> e =
diff --git a/src/System.Linq.Expressions/tests/CompilerTests.cs b/src/System.Linq.Expressions/tests/CompilerTests.cs
index 1b55caa765..822414f9b8 100644
--- a/src/System.Linq.Expressions/tests/CompilerTests.cs
+++ b/src/System.Linq.Expressions/tests/CompilerTests.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Runtime.CompilerServices;
+using System.Threading;
using Xunit;
namespace System.Linq.Expressions.Tests
@@ -26,6 +27,28 @@ namespace System.Linq.Expressions.Tests
Assert.Equal(n, f());
}
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public static void CompileDeepTree_NoStackOverflowFast(bool useInterpreter)
+ {
+ Expression e = Expression.Constant(0);
+
+ int n = 100;
+
+ for (int i = 0; i < n; i++)
+ e = Expression.Add(e, Expression.Constant(1));
+
+ Func<int> f = null;
+ // Request a stack size of 1 to get the minimum size allowed.
+ // This reduces the size of tree needed to risk a stack overflow.
+ // This though will only risk overflow once, so the outerloop test
+ // above is still needed.
+ Thread t = new Thread(() => f = Expression.Lambda<Func<int>>(e).Compile(useInterpreter), 1);
+ t.Start();
+ t.Join();
+
+ Assert.Equal(n, f());
+ }
+
#if FEATURE_COMPILE
[Fact]
public static void EmitConstantsToIL_NonNullableValueTypes()
diff --git a/src/System.Linq.Expressions/tests/Dynamic/BinaryOperationTests.cs b/src/System.Linq.Expressions/tests/Dynamic/BinaryOperationTests.cs
index e71f3ab41c..9fb4490e5d 100644
--- a/src/System.Linq.Expressions/tests/Dynamic/BinaryOperationTests.cs
+++ b/src/System.Linq.Expressions/tests/Dynamic/BinaryOperationTests.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
+using System.Linq.Expressions.Tests;
using Microsoft.CSharp.RuntimeBinder;
using Xunit;
@@ -698,5 +699,37 @@ namespace System.Dynamic.Tests
dY = 49;
Assert.Throws<RuntimeBinderException>(() => dX && dY);
}
+
+ [Theory]
+ [ClassData(typeof(CompilationTypes))]
+ public void BinaryCallSiteBinder_DynamicExpression(bool useInterpreter)
+ {
+ DynamicExpression expression = DynamicExpression.Dynamic(
+ new BinaryCallSiteBinder(),
+ typeof(object),
+ Expression.Constant(40, typeof(object)),
+ Expression.Constant(2, typeof(object)));
+ Func<object> func = Expression.Lambda<Func<object>>(expression).Compile(useInterpreter);
+ Assert.Equal("42", func().ToString());
+ }
+
+ private class BinaryCallSiteBinder : BinaryOperationBinder
+ {
+ public BinaryCallSiteBinder() : base(ExpressionType.Add) {}
+
+ public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
+ {
+ return new DynamicMetaObject(
+ Expression.Convert(
+ Expression.Add(
+ Expression.Convert(target.Expression, typeof(int)),
+ Expression.Convert(arg.Expression, typeof(int))
+ ), typeof(object)),
+
+ BindingRestrictions.GetTypeRestriction(target.Expression, typeof(int)).Merge(
+ BindingRestrictions.GetTypeRestriction(arg.Expression, typeof(int))
+ ));
+ }
+ }
}
}
diff --git a/src/System.Linq.Expressions/tests/Dynamic/DynamicObjectTests.cs b/src/System.Linq.Expressions/tests/Dynamic/DynamicObjectTests.cs
new file mode 100644
index 0000000000..c77acfaa78
--- /dev/null
+++ b/src/System.Linq.Expressions/tests/Dynamic/DynamicObjectTests.cs
@@ -0,0 +1,812 @@
+// 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.Generic;
+using System.Linq.Expressions;
+using Microsoft.CSharp.RuntimeBinder;
+using Xunit;
+
+namespace System.Dynamic.Tests
+{
+ public class DynamicObjectTests
+ {
+ // We'll test trying to access fields dynamically, but the compiler won't see that
+ // so disable CS0649.
+#pragma warning disable 649
+ private class TestDynamicBase : DynamicObject
+ {
+ private Dictionary<int, int> _dictionary = new Dictionary<int, int>();
+ public int Field;
+ public readonly int ReadonlyField;
+ public int HideField;
+
+ public int Property { get; set; }
+
+ public int ReadonlyProperty => 0;
+
+ public int Method(int argument) => argument;
+
+ public virtual int VirtualProperty { get; set; }
+ public virtual int VirtualReadonlyProperty => 1;
+
+ public virtual int VirtualMethod(int argument) => argument;
+ public int HideProperty { get; set; }
+
+ public int HideMethod(int argument) => argument;
+
+ public int this[int index]
+ {
+ get { return _dictionary[index]; }
+ set { _dictionary[index] = value; }
+ }
+ }
+
+ private class TestDynamic : TestDynamicBase
+ {
+ public new int HideField;
+ public override int VirtualProperty { get; set; }
+
+ public override int VirtualReadonlyProperty => 2;
+
+ public override int VirtualMethod(int argument) => argument * 2;
+
+ public new int HideProperty { get; set; }
+ public new int HideMethod { get; set; }
+ }
+#pragma warning restore 649
+
+ private class TestDynamicFagile : TestDynamic
+ {
+ public override bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+ throw new Exception();
+ }
+ }
+
+ private class TestDynamicNameReflective : TestDynamic
+ {
+ // Returns the name of the property back as the result, but is a stickler for .NET naming
+ // conventions and returns false if the first character isn't uppercase
+ // (Correct handling of Unicode category Lt omitted)
+ public override bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+ string name = binder.Name;
+ if (char.IsUpper(name[0]))
+ {
+ result = binder.Name;
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+
+ public override bool TrySetMember(SetMemberBinder binder, object value)
+ {
+ string name = binder.Name;
+ if (char.IsUpper(name[0]))
+ {
+ // Allows set (as noop) if it means that it's being given the same value the get
+ // above would return anyway.
+ if (value as string != name)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ private class TestDynamicNameReflectiveNotOverride : TestDynamic
+ {
+ // Like TestDynamicNameReflective but hides rather than overiding.
+ // Because DynamicObject reflects upon itself to see if these methods are
+ // overridden, we test this override-detection against finding hiding
+ // methods.
+ public new bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+ string name = binder.Name;
+ if (char.IsUpper(name[0]))
+ {
+ result = binder.Name;
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+
+ public new bool TrySetMember(SetMemberBinder binder, object value)
+ {
+ string name = binder.Name;
+ if (char.IsUpper(name[0]))
+ {
+ // Allows set (as noop) if it means that it's being given the same value the get
+ // above would return anyway.
+ if (value as string != name)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ private class SetOnlyProperties : DynamicObject
+ {
+ public override bool TrySetMember(SetMemberBinder binder, object value)
+ {
+ return true;
+ }
+ }
+
+ private class DynamicallyConvertable : DynamicObject
+ {
+ public override bool TryConvert(ConvertBinder binder, out object result)
+ {
+ if (binder.ReturnType == typeof(string))
+ {
+ result = nameof(DynamicallyConvertable);
+ return true;
+ }
+
+ if (binder.ReturnType == typeof(DateTime) && binder.Explicit)
+ {
+ result = new DateTime(1991, 8, 6);
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+
+ public static explicit operator DateTimeOffset(DynamicallyConvertable source) =>
+ new DateTimeOffset(1991, 8, 6, 0, 0, 0, new TimeSpan(2, 0, 0));
+
+ public static implicit operator Uri(DynamicallyConvertable source) =>
+ new Uri("http://example.net/");
+ }
+
+ private class DynamicallyConvertableNotOverride : DynamicObject
+ {
+ public new bool TryConvert(ConvertBinder binder, out object result)
+ {
+ if (binder.ReturnType == typeof(string))
+ {
+ result = nameof(DynamicallyConvertable);
+ return true;
+ }
+
+ if (binder.ReturnType == typeof(DateTime) && binder.Explicit)
+ {
+ result = new DateTime(1991, 8, 6);
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+
+ public static explicit operator DateTimeOffset(DynamicallyConvertableNotOverride source) =>
+ new DateTimeOffset(1991, 8, 6, 0, 0, 0, new TimeSpan(2, 0, 0));
+
+ public static implicit operator Uri(DynamicallyConvertableNotOverride source) =>
+ new Uri("http://example.net/");
+ }
+
+ private class DynamicallyInvokableIntPower : DynamicObject
+ {
+ public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
+ {
+ if (args.Length == 2)
+ {
+ int x;
+ int y;
+ try
+ {
+ x = Convert.ToInt32(args[0]);
+ y = Convert.ToInt32(args[1]);
+ }
+ catch (Exception)
+ {
+ result = null;
+ return false;
+ }
+
+ result = checked((int)Math.Pow(x, y));
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+ }
+
+ private class DynamicallyInvokableIntPowerNotOverride : DynamicObject
+ {
+ public new bool TryInvoke(InvokeBinder binder, object[] args, out object result)
+ {
+ if (args.Length == 2)
+ {
+ int x;
+ int y;
+ try
+ {
+ x = Convert.ToInt32(args[0]);
+ y = Convert.ToInt32(args[1]);
+ }
+ catch (Exception)
+ {
+ result = null;
+ return false;
+ }
+
+ result = checked((int)Math.Pow(x, y));
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+ }
+
+ private class DynamicallyInvokableIntPowerMember : DynamicObject
+ {
+ public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
+ {
+ if (binder.Name.Equals(
+ "Power", binder.IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)
+ && args.Length == 2)
+ {
+ int x;
+ int y;
+ try
+ {
+ x = Convert.ToInt32(args[0]);
+ y = Convert.ToInt32(args[1]);
+ }
+ catch (Exception)
+ {
+ result = null;
+ return false;
+ }
+
+ result = checked((int)Math.Pow(x, y));
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+
+ public int Modulo(int x, int y) => x % y;
+ }
+
+ private class Swapper : DynamicObject
+ {
+ public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
+ {
+ result = null;
+ if (args.Length == 2)
+ {
+ object temp = args[0];
+ args[0] = args[1];
+ args[1] = temp;
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ private class IndexableObject : DynamicObject
+ {
+ Dictionary<int, int> _oneDimension = new Dictionary<int, int>();
+ Dictionary<Tuple<int, int>, string> _twoDimensions = new Dictionary<Tuple<int, int>, string>();
+
+ public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
+ {
+ switch (indexes.Length)
+ {
+ case 1:
+ if (indexes[0] is int)
+ {
+ int value = _oneDimension[(int)indexes[0]];
+ result = value;
+ return true;
+ }
+
+ break;
+ case 2:
+ if (indexes[0] is int && indexes[1] is int)
+ {
+ string value = _twoDimensions[Tuple.Create((int)indexes[0], (int)indexes[1])];
+ result = value;
+ return true;
+ }
+
+ break;
+ }
+
+ result = null;
+ return false;
+ }
+
+ public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
+ {
+ switch (indexes.Length)
+ {
+ case 1:
+ if (indexes[0] is int && value is int)
+ {
+ _oneDimension[(int)indexes[0]] = (int)value;
+ return true;
+ }
+
+ break;
+ case 2:
+ if (indexes[0] is int && indexes[1] is int && value is string)
+ {
+ _twoDimensions[Tuple.Create((int)indexes[0], (int)indexes[1])] = (string)value;
+ return true;
+ }
+
+ break;
+ }
+
+ return false;
+ }
+ }
+
+ private class NegatableNum : DynamicObject
+ {
+ public NegatableNum(int value)
+ {
+ Value = value;
+ }
+
+ public int Value { get; }
+
+ public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result)
+ {
+ if (binder.Operation == ExpressionType.Negate)
+ {
+ result = new NegatableNum(unchecked(-Value));
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+ }
+
+ private class AddableNum : DynamicObject
+ {
+ public AddableNum(int value)
+ {
+ Value = value;
+ }
+
+ public int Value { get; }
+
+ public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
+ {
+ if (binder.Operation == ExpressionType.Add)
+ {
+ AddableNum addend = arg as AddableNum;
+ if (addend != null)
+ {
+ result = new AddableNum(Value + addend.Value);
+ return true;
+ }
+ }
+
+ result = null;
+ return false;
+ }
+ }
+
+ private class Accumulator : DynamicObject
+ {
+ // Allows addition with itself on the lhs, but not with it on the rhs
+ public Accumulator(int value)
+ {
+ Value = value;
+ }
+
+ public int Value { get; }
+
+ public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
+ {
+ if (binder.Operation == ExpressionType.Add)
+ {
+ AddableNum addend = arg as AddableNum;
+ if (addend != null)
+ {
+ result = new Accumulator(Value + addend.Value);
+ return true;
+ }
+ }
+
+ result = null;
+ return false;
+ }
+ }
+
+ private class TraditionalDynamicObject : DynamicObject
+ {
+ private static readonly string[] Names =
+ {
+ "Foo", "Bar", "Baz", "Quux", "Quuux", "Quuuux", "Quuuuux",
+ "Quuuuuux"
+ };
+
+ public override IEnumerable<string> GetDynamicMemberNames() => Names;
+
+ public override bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+ for (int idx = 0; idx != Names.Length; ++idx)
+ {
+ if (binder.Name == Names[idx])
+ {
+ result = idx;
+ return true;
+ }
+ }
+
+ result = null;
+ return false;
+ }
+ }
+
+ [Fact]
+ public void GetSetDefinedField()
+ {
+ var test = new TestDynamicFagile();
+ test.Field = 43;
+ dynamic d = test;
+ Assert.Equal(43, d.Field);
+ d.Field = 93;
+ Assert.Equal(93, test.Field);
+ }
+
+ [Fact]
+ public void GetDynamicProperty()
+ {
+ dynamic d = new TestDynamicNameReflective();
+ Assert.Equal("DynProp", d.DynProp);
+ }
+
+ [Fact]
+ public void FailToGetDynamicProperty()
+ {
+ dynamic d = new TestDynamicNameReflective();
+ Assert.Throws<RuntimeBinderException>(() => d.notToBeFound);
+ }
+
+ [Fact]
+ public void GetDynamicPropertyWithHidingTryGetMember()
+ {
+ dynamic d = new TestDynamicNameReflectiveNotOverride();
+ Assert.Throws<RuntimeBinderException>(() => d.DynProp);
+ Assert.Equal(2, d.VirtualReadonlyProperty);
+ }
+
+ [Fact]
+ public void SetDynamicProperty()
+ {
+ dynamic d = new TestDynamicNameReflective();
+ d.DynProp = nameof(d.DynProp);
+ Assert.Throws<ArgumentOutOfRangeException>("value", () => d.DynProp = "I wandered lonely as a cloud.");
+ }
+
+ [Fact]
+ public void FailToSetDynamicProperty()
+ {
+ dynamic d = new TestDynamicNameReflective();
+ Assert.Throws<RuntimeBinderException>(() => d.notToBeFound = nameof(d.notToBeFound));
+ }
+
+ [Fact]
+ public void SetDynamicPropertyWithHidingTrySetMember()
+ {
+ dynamic d = new TestDynamicNameReflectiveNotOverride();
+ Assert.Throws<RuntimeBinderException>(() => d.DynProp = nameof(d.DynProp));
+ }
+
+ [Fact]
+ public void SetPropertyReturnsValueWithoutUsingGetter()
+ {
+ dynamic d = new SetOnlyProperties();
+ object value = new object();
+ object result = d.SomeProperty = value;
+ Assert.Same(value, result);
+ }
+
+ [Fact]
+ public void AttemptWriteReadonlyField()
+ {
+ TestDynamic td = new TestDynamic();
+ dynamic d = td;
+ Assert.Throws<RuntimeBinderException>(() => d.ReadonlyField = 3);
+ Assert.Equal(0, td.ReadonlyField); // Confirm exception happened before a write, rather than after.
+ }
+
+ [Fact]
+ public void ReadWriteHidingField()
+ {
+ TestDynamic td = new TestDynamic();
+ dynamic d = td;
+ td.HideField = 9;
+ Assert.Equal(9, d.HideField);
+ Assert.Equal(9, td.HideField);
+ Assert.Equal(0, ((TestDynamicBase)td).HideField);
+ }
+
+ [Fact]
+ public void MetaDynamicKnowsNamesFromDynamic()
+ {
+ var trad = new TraditionalDynamicObject();
+ Assert.Same(trad.GetDynamicMemberNames(), trad.GetMetaObject(Expression.Parameter(typeof(object))).GetDynamicMemberNames());
+ }
+
+ [Fact]
+ public void ConvertBuiltInImplicit()
+ {
+ dynamic d = new DynamicallyConvertable();
+ Uri u = d;
+ Assert.Equal(new Uri("http://example.net/"), u);
+ }
+
+ [Fact]
+ public void ConvertBuiltInExplicit()
+ {
+ dynamic d = new DynamicallyConvertable();
+ DateTimeOffset dto = (DateTimeOffset)d;
+ Assert.Equal(new DateTimeOffset(1991, 8, 6, 0, 0, 0, new TimeSpan(2, 0, 0)), dto);
+ }
+
+ [Fact]
+ public void ConvertFailImplicitWhenMatchingExplicit()
+ {
+ dynamic d = new DynamicallyConvertable();
+ DateTimeOffset dto = default(DateTimeOffset);
+ Assert.Throws<RuntimeBinderException>(() => dto = d);
+ }
+
+ [Fact]
+ public void ConvertDynamicImplicit()
+ {
+ dynamic d = new DynamicallyConvertable();
+ string name = d;
+ Assert.Equal(nameof(DynamicallyConvertable), name);
+ }
+
+ [Fact]
+ public void ConvertDynamicExplicit()
+ {
+ dynamic d = new DynamicallyConvertable();
+ DateTime dt = (DateTime)d;
+ Assert.Equal(new DateTime(1991, 8, 6), dt);
+ }
+
+ [Fact]
+ public void ConvertFailImplicitOfferedDynamicallyExplicit()
+ {
+ dynamic d = new DynamicallyConvertable();
+ DateTime dt = default(DateTime);
+ Assert.Throws<RuntimeBinderException>(() => dt = d);
+ }
+
+ [Fact]
+ public void ConvertFailNotOfferedConversion()
+ {
+ dynamic d = new DynamicallyConvertable();
+ Expression ex = null;
+ Assert.Throws<RuntimeBinderException>(() => ex = d);
+ Assert.Throws<RuntimeBinderException>(() => ex = (Expression)d);
+ }
+
+ [Fact]
+ public void ConvertHidingTryConvert()
+ {
+ dynamic d = new DynamicallyConvertableNotOverride();
+ Uri u = d;
+ Assert.Equal(new Uri("http://example.net/"), u);
+ DateTimeOffset dto = (DateTimeOffset)d;
+ Assert.Equal(new DateTimeOffset(1991, 8, 6, 0, 0, 0, new TimeSpan(2, 0, 0)), dto);
+ DateTime dt = default(DateTime);
+ string s = null;
+ Assert.Throws<RuntimeBinderException>(() => dt = d);
+ Assert.Throws<RuntimeBinderException>(() => dto = d);
+ Assert.Throws<RuntimeBinderException>(() => s = d);
+ }
+
+ [Fact]
+ public void DynamicInvoke()
+ {
+ dynamic d = new DynamicallyInvokableIntPower();
+ int pow = d(8, 9);
+ Assert.Equal(134217728, pow);
+ Assert.Throws<OverflowException>(() => d(int.MaxValue, int.MaxValue));
+ }
+
+ [Fact]
+ public void DynamicInvokeMismatch()
+ {
+ dynamic d = new DynamicallyInvokableIntPower();
+ Assert.Throws<RuntimeBinderException>(() => d(9));
+ Assert.Throws<RuntimeBinderException>(() => d());
+ Assert.Throws<RuntimeBinderException>(() => d(1, 2, 3));
+ Assert.Throws<RuntimeBinderException>(() => d("eight", "nine"));
+ }
+
+ [Fact]
+ public void DynamicInvokeNotOverride()
+ {
+ dynamic d = new DynamicallyInvokableIntPowerNotOverride();
+ Assert.Throws<RuntimeBinderException>(() => d(8, 9));
+ Assert.Throws<RuntimeBinderException>(() => d(int.MaxValue, int.MaxValue));
+ }
+
+ [Fact]
+ public void DynamicInvokeMember()
+ {
+ dynamic d = new DynamicallyInvokableIntPowerMember();
+ int pow = d.Power(8, 9);
+ Assert.Equal(134217728, pow);
+ Assert.Throws<OverflowException>(() => d.Power(int.MaxValue, int.MaxValue));
+ }
+
+ [Fact]
+ public void DynamicInvokeMemberMismatch()
+ {
+ dynamic d = new DynamicallyInvokableIntPowerMember();
+ Assert.Throws<RuntimeBinderException>(() => d.Power(9));
+ Assert.Throws<RuntimeBinderException>(() => d.Power());
+ Assert.Throws<RuntimeBinderException>(() => d.Power(1, 2, 3));
+ Assert.Throws<RuntimeBinderException>(() => d.Power("eight", "nine"));
+ Assert.Throws<RuntimeBinderException>(() => d.power(8, 9));
+ }
+
+ [Fact]
+ public void DynamicInvokeMemberStaticMember()
+ {
+ dynamic d = new DynamicallyInvokableIntPowerMember();
+ int mod = d.Modulo(233, 12);
+ Assert.Equal(5, mod);
+ Assert.Throws<RuntimeBinderException>(() => d.Modulo(2));
+ Assert.Throws<RuntimeBinderException>(() => d.modulo(233, 12));
+ Assert.Throws<RuntimeBinderException>(() => d.Modulo());
+ Assert.Throws<RuntimeBinderException>(() => d.Modulo(233, 12, 9));
+ Assert.Throws<RuntimeBinderException>(() => d.Modulo("two hundred and thirty-three", "twelve"));
+ }
+
+ [Fact]
+ public void DynamicUnaryOperation()
+ {
+ dynamic d = new NegatableNum(23);
+ dynamic r = -d;
+ Assert.Equal(-23, r.Value);
+ d = new NegatableNum(int.MinValue);
+ r = -d;
+ Assert.Equal(int.MinValue, r.Value);
+ }
+
+ [Fact]
+ public void DynamicUnaryOperationNotSupported()
+ {
+ dynamic d = new NegatableNum(23);
+ Assert.Throws<RuntimeBinderException>(() => ~d);
+ }
+
+ [Fact]
+ public void DynamicUnaryOperationNoOverrides()
+ {
+ dynamic d = new TestDynamic();
+ Assert.Throws<RuntimeBinderException>(() => -d);
+ }
+
+ [Fact]
+ public void DynamicAddition()
+ {
+ dynamic x = new AddableNum(23);
+ dynamic y = new AddableNum(42);
+ dynamic r = x + y;
+ Assert.Equal(23 + 42, r.Value);
+ }
+
+ [Fact]
+ public void DynamicBinaryUnsupported()
+ {
+ dynamic x = new AddableNum(23);
+ dynamic y = new AddableNum(42);
+ Assert.Throws<RuntimeBinderException>(() => x * y);
+ }
+
+ [Fact]
+ public void DynamicBinaryUnidirectional()
+ {
+ dynamic x = new Accumulator(23);
+ dynamic y = new AddableNum(42);
+ dynamic r = x + y;
+ Assert.Equal(23 + 42, r.Value);
+ Assert.Throws<RuntimeBinderException>(() => y + x);
+ }
+
+ [Fact]
+ public void DynamicBinaryNoOverride()
+ {
+ dynamic x = new TestDynamic();
+ dynamic y = new TestDynamic();
+ Assert.Throws<RuntimeBinderException>(() => x + y);
+ }
+
+ [Fact]
+ public void ByRefInvoke()
+ {
+ dynamic d = new Swapper();
+ int x = 23;
+ int y = 42;
+ d(ref x, ref y);
+ Assert.Equal(42, x);
+ Assert.Equal(23, y);
+ }
+
+ [Fact]
+ public void ByRefMismatch()
+ {
+ dynamic d = new Swapper();
+ long x = 23;
+ int y = 42;
+ d(x, y); // Okay because no write-back.
+ Assert.Throws<InvalidCastException>(() => d(ref x, ref y));
+ }
+
+ [Fact]
+ public void IndexGetAndRetrieve()
+ {
+ dynamic d = new IndexableObject();
+ d[23] = 42;
+ Assert.Equal(42, d[23]);
+ d[1, 2] = "Hello";
+ Assert.Equal("Hello", d[1, 2]);
+ Assert.Throws<KeyNotFoundException>(() => d[1]);
+ Assert.Throws<KeyNotFoundException>(() => d[2, 3]);
+ Assert.Throws<RuntimeBinderException>(() => d[2] = "Test");
+ Assert.Throws<RuntimeBinderException>(() => d[2, 4] = 1);
+ Assert.Throws<RuntimeBinderException>(() => d["index"]);
+ Assert.Throws<RuntimeBinderException>(() => d["index"] = 2);
+ Assert.Throws<RuntimeBinderException>(() =>
+ {
+ string val = d[23];
+ });
+ Assert.Throws<RuntimeBinderException>(() =>
+ {
+ int val = d[1, 2];
+ });
+ Assert.Throws<RuntimeBinderException>(() => d[1, 2, 3]);
+ }
+
+ [Fact]
+ public void IndexingFromStaticMember()
+ {
+ dynamic d = new TestDynamic();
+ d[0] = 1;
+ Assert.Equal(1, d[0]);
+ Assert.Throws<RuntimeBinderException>(() => d[0] = "One");
+ Assert.Throws<RuntimeBinderException>(() =>
+ {
+ string val = d[0];
+ });
+ Assert.Throws<RuntimeBinderException>(() => d["index"]);
+ }
+ }
+}
diff --git a/src/System.Linq.Expressions/tests/Dynamic/ExpandoObjectTests.cs b/src/System.Linq.Expressions/tests/Dynamic/ExpandoObjectTests.cs
new file mode 100644
index 0000000000..c13297a9b5
--- /dev/null
+++ b/src/System.Linq.Expressions/tests/Dynamic/ExpandoObjectTests.cs
@@ -0,0 +1,188 @@
+// 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.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using Xunit;
+
+namespace System.Dynamic.Tests
+{
+ // Tests for ExpandoObject accessed directly, rather than through dynamic.
+ public class ExpandoObjectTests
+ {
+ [Fact]
+ public void InitialState()
+ {
+ IDictionary<string, object> eo = new ExpandoObject();
+ Assert.Equal(0, eo.Count);
+ Assert.False(eo.IsReadOnly);
+ }
+
+ [Fact]
+ public void Indexer()
+ {
+ // Deliberately using keys that the C# syntax won't use, to check they're covered too.
+ var boxedInts = Enumerable.Range(0, 10).Select(i => (object)i).ToArray();
+ IDictionary<string, object> eo = new ExpandoObject();
+ foreach (var boxed in boxedInts)
+ eo[boxed.ToString()] = boxed;
+
+ Assert.Equal(10, eo.Count);
+ foreach (var boxed in boxedInts)
+ Assert.Same(boxed, eo[boxed.ToString()]);
+
+ var knfe = Assert.Throws<KeyNotFoundException>(() => eo["A string that's a key"]);
+ Assert.Contains("A string that's a key", knfe.Message);
+
+ Assert.Throws<KeyNotFoundException>(() => eo[null]);
+ Assert.Throws<ArgumentNullException>("key", () => eo[null] = 0);
+ // Can overwrite
+ eo["1"] = 1;
+ }
+
+ [Fact]
+ public void AddDup()
+ {
+ IDictionary<string, object> eo = new ExpandoObject();
+ eo.Add("The test key to add.", "value");
+ var ae = Assert.Throws<ArgumentException>("key", () => eo.Add("The test key to add.", "value"));
+ Assert.Contains("The test key to add.", ae.Message);
+ }
+
+ [Fact]
+ public void DeleteAndReInsert()
+ {
+ IDictionary<string, object> eo = new ExpandoObject();
+ eo.Add("key", 1);
+ Assert.Equal(Enumerable.Repeat(new KeyValuePair<string, object>("key", 1), 1), eo);
+ eo.Remove("key");
+ Assert.Empty(eo);
+ eo.Add("key", 2);
+ Assert.Equal(Enumerable.Repeat(new KeyValuePair<string, object>("key", 2), 1), eo);
+ }
+
+ [Fact, ActiveIssue(13541)]
+ public void DictionaryMatchesProperties()
+ {
+ dynamic eo = new ExpandoObject();
+ IDictionary<string, object> dict = eo;
+ eo.X = 1;
+ eo.Y = 2;
+ Assert.Equal(2, dict.Count);
+ Assert.Equal(1, dict["X"]);
+ Assert.Equal(2, dict["Y"]);
+ }
+
+ [Fact]
+ public void PropertyNotify()
+ {
+ var eo = new ExpandoObject();
+ IDictionary<string, object> dict = eo;
+ INotifyPropertyChanged note = eo;
+ int changeCount = 0;
+ string lastKey = null;
+ note.PropertyChanged += (sender, args) =>
+ {
+ Assert.Same(eo, sender);
+ ++changeCount;
+ lastKey = args.PropertyName;
+ };
+ Assert.Equal(0, changeCount);
+ dict.Add("X", 1);
+ Assert.Equal(1, changeCount);
+ Assert.Equal(lastKey, "X");
+ dict["Y"] = 2;
+ Assert.Equal(2, changeCount);
+ Assert.Equal(lastKey, "Y");
+ object boxed = 0;
+ dict["Z"] = boxed;
+ Assert.Equal(3, changeCount);
+ Assert.Equal("Z", lastKey);
+ dict["Z"] = boxed; // exact same object.
+ Assert.Equal(3, changeCount);
+ dict["Z"] = 0; // same value but different instance.
+ Assert.Equal(4, changeCount);
+ dict.Remove("Not there");
+ Assert.Equal(4, changeCount);
+ dict.Remove("Z");
+ Assert.Equal(5, changeCount);
+ dict.Clear();
+ Assert.Equal(7, changeCount); // trigger for each key.
+ }
+
+ [Fact]
+ public void KeyCollection()
+ {
+ IDictionary<string, object> dict = new ExpandoObject();
+ dict["X"] = 1;
+ dict["Z"] = 3;
+ dict["Y"] = 2;
+ dict.Remove("Z");
+ var keys = dict.Keys;
+ Assert.Equal(2, keys.Count);
+ Assert.True(keys.IsReadOnly);
+ Assert.Equal(new[] {"X", "Y"}, keys.OrderBy(k => k)); // OrderBy because order is not guaranteed.
+ Assert.Throws<NotSupportedException>(() => keys.Add("Z"));
+ Assert.Throws<NotSupportedException>(() => keys.Clear());
+ Assert.Throws<NotSupportedException>(() => keys.Remove("X"));
+ Assert.True(keys.Contains("X"));
+ Assert.False(keys.Contains("x"));
+ string[] array = new string[3];
+ keys.CopyTo(array, 1);
+ Assert.Null(array[0]);
+ Array.Sort(array); // Because order is not guaranteed.
+ Assert.Equal(new[] {null, "X", "Y"}, array);
+ var keysEnumerated = new List<object>();
+ foreach (var key in (IEnumerable)keys) // going through non-generic to test delegation to generic
+ {
+ keysEnumerated.Add(key);
+ }
+ Assert.Equal(new[] {"X", "Y"}, keysEnumerated.OrderBy(k => k));
+ using (var en = keys.GetEnumerator())
+ {
+ en.MoveNext();
+ dict["Z"] = 3;
+ Assert.Throws<InvalidOperationException>(() => en.MoveNext());
+ }
+ }
+
+ [Fact]
+ public void ValueCollection()
+ {
+ IDictionary<string, object> dict = new ExpandoObject();
+ dict["X"] = 1;
+ dict["Z"] = 3;
+ dict["Y"] = 2;
+ dict.Remove("Z");
+ var values = dict.Values;
+ Assert.Equal(2, values.Count);
+ Assert.True(values.IsReadOnly);
+ Assert.Equal(new object[] {1, 2}, values.OrderBy(k => k)); // OrderBy because order is not guaranteed.
+ Assert.Throws<NotSupportedException>(() => values.Add(3));
+ Assert.Throws<NotSupportedException>(() => values.Clear());
+ Assert.Throws<NotSupportedException>(() => values.Remove(1));
+ Assert.True(values.Contains(1));
+ Assert.False(values.Contains(1.0));
+ object[] array = new object[3];
+ values.CopyTo(array, 1);
+ Assert.Null(array[0]);
+ Array.Sort(array); // Because order is not guaranteed.
+ Assert.Equal(new object[] {null, 1, 2}, array);
+ var valuesEnumerated = new List<object>();
+ foreach (var value in (IEnumerable)values) // going through non-generic to test delegation to generic
+ {
+ valuesEnumerated.Add(value);
+ }
+ Assert.Equal(new object[] {1, 2}, valuesEnumerated.OrderBy(k => k));
+ using (var en = values.GetEnumerator())
+ {
+ en.MoveNext();
+ dict["Z"] = 3;
+ Assert.Throws<InvalidOperationException>(() => en.MoveNext());
+ }
+ }
+ }
+}
diff --git a/src/System.Linq.Expressions/tests/Dynamic/SetIndexBinderTests.cs b/src/System.Linq.Expressions/tests/Dynamic/SetIndexBinderTests.cs
new file mode 100644
index 0000000000..75a508b721
--- /dev/null
+++ b/src/System.Linq.Expressions/tests/Dynamic/SetIndexBinderTests.cs
@@ -0,0 +1,144 @@
+// 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.Generic;
+using System.Linq.Expressions;
+using Microsoft.CSharp.RuntimeBinder;
+using Xunit;
+
+namespace System.Dynamic.Tests
+{
+ public class SetIndexBinderTests
+ {
+ private class MinimumOverrideSetIndexBinder : SetIndexBinder
+ {
+ public MinimumOverrideSetIndexBinder(CallInfo callInfo) : base(callInfo)
+ {
+ }
+
+ public override DynamicMetaObject FallbackSetIndex(
+ DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value,
+ DynamicMetaObject errorSuggestion)
+ {
+ throw new NotSupportedException();
+ }
+ }
+
+ [Fact]
+ public void ArrayIndexing()
+ {
+ int[] array = {-1, -1, -1, -1};
+ dynamic d = array;
+ for (int i = 0; i != 4; ++i)
+ {
+ d[i] = i;
+ }
+
+ Assert.Equal(new[] {0, 1, 2, 3}, array);
+ }
+
+ [Fact]
+ public void ListIndexing()
+ {
+ List<int> list = new List<int> {0, 1, 2, 3};
+ dynamic d = list;
+ for (int i = 0; i != 4; ++i)
+ {
+ d[i] = i;
+ }
+
+ Assert.Equal(new[] {0, 1, 2, 3}, list);
+ }
+
+ [Fact]
+ public void MultiDimensionalIndexing()
+ {
+ int[,] array = new[,] {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}};
+ dynamic d = array;
+ for (int i = 0; i != 4; ++i)
+ {
+ for (int j = 0; j != 4; ++j)
+ {
+ d[i, j] = i + j;
+ }
+ }
+
+ Assert.Equal(new[,] {{0, 1, 2, 3}, {1, 2, 3, 4}, {2, 3, 4, 5}, {3, 4, 5, 6}}, array);
+ }
+
+ [Fact]
+ public void NotIndexable()
+ {
+ dynamic d = 23;
+ Assert.Throws<RuntimeBinderException>(() => d[2] = 2);
+ }
+
+ [Fact]
+ public void TooFewIndices()
+ {
+ dynamic d = new[,] { { 0, 1, 2, 3 }, { 1, 2, 3, 4 }, { 2, 3, 4, 5 }, { 3, 4, 5, 6 } };
+ Assert.Throws<RuntimeBinderException>(() => d[2] = 2);
+ }
+
+ [Fact]
+ public void TooManyIndices()
+ {
+ dynamic d = new[] { 0, 1, 2, 3 };
+ Assert.Throws<RuntimeBinderException>(() => d[1, 3] = 2);
+ }
+
+ [Fact]
+ public void IndexErrorIsNotBindingError()
+ {
+ dynamic d = new[] { 0, 1, 2, 3 };
+ Assert.Throws<IndexOutOfRangeException>(() => d[9] = 8);
+ d = new List<int> { 0, 1, 2, 3 };
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => d[9] = 8);
+ }
+
+ [Fact]
+ public void NullCallInfo()
+ {
+ Assert.Throws<ArgumentNullException>("callInfo", () => new MinimumOverrideSetIndexBinder(null));
+ }
+
+ [Fact]
+ public void CallInfoStored()
+ {
+ CallInfo info = new CallInfo(0);
+ Assert.Same(info, new MinimumOverrideSetIndexBinder(info).CallInfo);
+ }
+
+ [Fact]
+ public void ReturnTypeObject()
+ {
+ Assert.Equal(typeof(object), new MinimumOverrideSetIndexBinder(new CallInfo(0)).ReturnType);
+ }
+
+ [Fact]
+ public void NullTarget()
+ {
+ var binder = new MinimumOverrideSetIndexBinder(new CallInfo(0));
+ var arg = new DynamicMetaObject(Expression.Parameter(typeof(object), null), BindingRestrictions.Empty);
+ Assert.Throws<ArgumentNullException>("target", () => binder.Bind(null, new[] { arg }));
+ }
+
+ [Fact]
+ public void NullArgs()
+ {
+ var binder = new MinimumOverrideSetIndexBinder(new CallInfo(0));
+ var target = new DynamicMetaObject(Expression.Parameter(typeof(object), null), BindingRestrictions.Empty);
+ Assert.Throws<ArgumentNullException>("args", () => binder.Bind(target, null));
+ }
+
+ [Fact]
+ public void NullArg()
+ {
+ var binder = new MinimumOverrideSetIndexBinder(new CallInfo(0));
+ var target = new DynamicMetaObject(Expression.Parameter(typeof(object), null), BindingRestrictions.Empty);
+ var arg = new DynamicMetaObject(Expression.Parameter(typeof(object), null), BindingRestrictions.Empty);
+ Assert.Throws<ArgumentNullException>("args[1]", () => binder.Bind(target, new[] { arg, null, arg }));
+ }
+ }
+}
diff --git a/src/System.Linq.Expressions/tests/Dynamic/SetMemberBinderTests.cs b/src/System.Linq.Expressions/tests/Dynamic/SetMemberBinderTests.cs
new file mode 100644
index 0000000000..cedc53192c
--- /dev/null
+++ b/src/System.Linq.Expressions/tests/Dynamic/SetMemberBinderTests.cs
@@ -0,0 +1,93 @@
+// 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.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.CSharp.RuntimeBinder;
+using Xunit;
+
+namespace System.Dynamic.Tests
+{
+ public class SetMemberBinderTests
+ {
+ private class MinimumOverrideSetMemberBinder : SetMemberBinder
+ {
+ public MinimumOverrideSetMemberBinder(string name, bool ignoreCase)
+ : base(name, ignoreCase)
+ {
+ }
+
+ public override DynamicMetaObject FallbackSetMember(
+ DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
+ {
+ throw new NotSupportedException();
+ }
+ }
+
+ private class TestBaseClass
+ {
+ public string Name { get; set; }
+ }
+
+ private class TestDerivedClass : TestBaseClass
+ {
+ public new string Name { get; set; }
+ }
+
+ private static readonly string[] Names =
+ {
+ "arg", "ARG", "Arg", "Argument name that isn’t a valid C♯ name 👿🤢",
+ "horrid name with" + (char)0xD800 + "a half surrogate", "new", "break"
+ };
+
+ private static IEnumerable<object[]> NamesAndBools() => Names.Select((n, i) => new object[] { n, i % 2 == 0 });
+
+ [Fact]
+ public void InvokeInstanceProperty()
+ {
+ StringBuilder sb = new StringBuilder();
+ dynamic d = sb;
+ d.Length = 4;
+ Assert.Equal(4, sb.Length);
+ }
+
+ [Fact]
+ public void InvokeCaseInsensitiveFails()
+ {
+ StringBuilder sb = new StringBuilder();
+ dynamic d = sb;
+ Assert.Throws<RuntimeBinderException>(() => d.LENGTH = 4);
+ }
+
+ [Fact]
+ public void MemberHiding()
+ {
+ TestDerivedClass tdc = new TestDerivedClass();
+ dynamic d = tdc;
+ d.Name = "test";
+ Assert.Equal("test", tdc.Name);
+ Assert.Null(((TestBaseClass)tdc).Name);
+ }
+
+ [Fact]
+ public void NullName()
+ {
+ Assert.Throws<ArgumentNullException>("name", () => new MinimumOverrideSetMemberBinder(null, false));
+ Assert.Throws<ArgumentNullException>("name", () => new MinimumOverrideSetMemberBinder(null, true));
+ }
+
+ [Theory, MemberData(nameof(NamesAndBools))]
+ public void CTorArgumentsStored(string name, bool ignoreCase)
+ {
+ SetMemberBinder binder = new MinimumOverrideSetMemberBinder(name, ignoreCase);
+ Assert.Equal(ignoreCase, binder.IgnoreCase);
+ Assert.Equal(binder.Name, name);
+ }
+
+ [Theory, MemberData(nameof(NamesAndBools))]
+ public void ReturnTypeObject(string name, bool ignoreCase) =>
+ Assert.Equal(typeof(object), new MinimumOverrideSetMemberBinder(name, ignoreCase).ReturnType);
+ }
+}
diff --git a/src/System.Linq.Expressions/tests/Dynamic/UnaryOperationTests.cs .cs b/src/System.Linq.Expressions/tests/Dynamic/UnaryOperationTests.cs
index 77d2b5b6f7..77d2b5b6f7 100644
--- a/src/System.Linq.Expressions/tests/Dynamic/UnaryOperationTests.cs .cs
+++ b/src/System.Linq.Expressions/tests/Dynamic/UnaryOperationTests.cs
diff --git a/src/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs b/src/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs
index b47d2cdabe..f57cb5a6da 100644
--- a/src/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs
+++ b/src/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs
@@ -526,6 +526,34 @@ namespace System.Linq.Expressions.Tests
FaultTriggeredOnThrow(false);
}
+ [Theory, InlineData(true)]
+ public void FinallyAndFaultAfterManyLabels(bool useInterpreter)
+ {
+ // There is a caching optimisation used below a certain number of faults or
+ // finally, so go past that to catch any regressions in the non-optimised
+ // path.
+ ParameterExpression variable = Expression.Parameter(typeof(int));
+ LabelTarget target = Expression.Label(typeof(int));
+ BlockExpression block = Expression.Block(
+ new[] { variable },
+ Expression.Assign(variable, Expression.Constant(1)),
+ Expression.TryCatch(
+ Expression.Block(
+ Enumerable.Repeat(Expression.TryFinally(Expression.Empty(), Expression.Empty()), 40).Append(
+ Expression.TryFault(
+ Expression.Throw(Expression.Constant(new TestException())),
+ Expression.Assign(variable, Expression.Constant(2))
+ )
+ )
+ ),
+ Expression.Catch(typeof(TestException), Expression.Empty())
+ ),
+ Expression.Return(target, variable),
+ Expression.Label(target, Expression.Default(typeof(int)))
+ );
+ Assert.Equal(2, Expression.Lambda<Func<int>>(block).Compile(useInterpreter)());
+ }
+
[Theory]
[ClassData(typeof(CompilationTypes))]
public void FinallyTriggeredOnNoThrow(bool useInterpreter)
diff --git a/src/System.Linq.Expressions/tests/IndexExpression/IndexExpressionTests.cs b/src/System.Linq.Expressions/tests/IndexExpression/IndexExpressionTests.cs
index 29abe2c0d0..fc8e847d91 100644
--- a/src/System.Linq.Expressions/tests/IndexExpression/IndexExpressionTests.cs
+++ b/src/System.Linq.Expressions/tests/IndexExpression/IndexExpressionTests.cs
@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
using Xunit;
namespace System.Linq.Expressions.Tests
@@ -12,7 +14,7 @@ namespace System.Linq.Expressions.Tests
[Fact]
public void UpdateSameTest()
{
- var instance = new SampleClassWithProperties { DefaultProperty = new List<int> { 100, 101 } };
+ SampleClassWithProperties instance = new SampleClassWithProperties { DefaultProperty = new List<int> { 100, 101 } };
IndexExpression expr = instance.DefaultIndexExpression;
IndexExpression exprUpdated = expr.Update(expr.Object, expr.Arguments);
@@ -28,7 +30,7 @@ namespace System.Linq.Expressions.Tests
[Fact]
public void UpdateTest()
{
- var instance = new SampleClassWithProperties
+ SampleClassWithProperties instance = new SampleClassWithProperties
{
DefaultProperty = new List<int> { 100, 101 },
AlternativeProperty = new List<int> { 200, 201 }
@@ -64,6 +66,580 @@ namespace System.Linq.Expressions.Tests
Assert.Equal("xs[i, j]", e3.ToString());
}
+ private static TypeBuilder GetTestTypeBuilder() =>
+ AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run)
+ .DefineDynamicModule("TestModule")
+ .DefineType("TestType");
+
+ [Fact]
+ public void NoAccessorIndexedProperty()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ typeBuild.DefineProperty("Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = info.DeclaredProperties.First();
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void ByRefIndexedProperty()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+ FieldBuilder field = typeBuild.DefineField("_value", typeof(int), FieldAttributes.Private);
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int).MakeByRefType(), new[] {typeof(int)});
+
+ MethodBuilder getter = typeBuild.DefineMethod(
+ "get_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(int).MakeByRefType(),
+ new[] {typeof(int)});
+
+ ILGenerator ilGen = getter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ldarg_0);
+ ilGen.Emit(OpCodes.Ldflda, field);
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetGetMethod(getter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void VoidIndexedProperty()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(void), new[] { typeof(int) });
+
+ MethodBuilder getter = typeBuild.DefineMethod(
+ "get_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(void),
+ new[] { typeof(int) });
+
+ ILGenerator ilGen = getter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetGetMethod(getter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void IndexedPropertyGetReturnsWrongType()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ MethodBuilder getter = typeBuild.DefineMethod(
+ "get_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(long),
+ new[] { typeof(int) });
+
+ ILGenerator ilGen = getter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetGetMethod(getter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void IndexedPropertySetterNoParams()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ MethodBuilder setter = typeBuild.DefineMethod(
+ "set_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(void),
+ Type.EmptyTypes);
+
+ ILGenerator ilGen = setter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetSetMethod(setter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void IndexedPropertySetterByrefValueType()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ MethodBuilder setter = typeBuild.DefineMethod(
+ "set_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(void),
+ new [] {typeof(int), typeof(int).MakeByRefType()});
+
+ ILGenerator ilGen = setter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetSetMethod(setter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void IndexedPropertySetterNotReturnVoid()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ MethodBuilder setter = typeBuild.DefineMethod(
+ "set_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(int),
+ new[] { typeof(int), typeof(int) });
+
+ ILGenerator ilGen = setter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetSetMethod(setter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void IndexedPropertyGetterInstanceSetterStatic()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ MethodBuilder getter = typeBuild.DefineMethod(
+ "get_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(int),
+ new[] { typeof(int) });
+
+ MethodBuilder setter = typeBuild.DefineMethod(
+ "set_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Static
+ | MethodAttributes.PrivateScope,
+ typeof(void),
+ new[] { typeof(int), typeof(int) });
+
+ ILGenerator ilGen = getter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ldc_I4_0);
+ ilGen.Emit(OpCodes.Ret);
+
+ ilGen = setter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetGetMethod(getter);
+ property.SetSetMethod(setter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void IndexedPropertySetterValueTypeNotMatchPropertyType()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ MethodBuilder setter = typeBuild.DefineMethod(
+ "set_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(void),
+ new[] { typeof(int), typeof(long) });
+
+ ILGenerator ilGen = setter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetSetMethod(setter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void IndexedPropertyGetterSetterArgCountMismatch()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ MethodBuilder getter = typeBuild.DefineMethod(
+ "get_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(int),
+ new[] { typeof(int) });
+
+ MethodBuilder setter = typeBuild.DefineMethod(
+ "set_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(void),
+ new[] { typeof(int), typeof(int), typeof(int) });
+
+ ILGenerator ilGen = getter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ldc_I4_0);
+ ilGen.Emit(OpCodes.Ret);
+
+ ilGen = setter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetGetMethod(getter);
+ property.SetSetMethod(setter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void IndexedPropertyGetterSetterArgumentTypeMismatch()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int), typeof(int), typeof(int) });
+
+ MethodBuilder getter = typeBuild.DefineMethod(
+ "get_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(int),
+ new[] { typeof(int), typeof(int), typeof(int) });
+
+ MethodBuilder setter = typeBuild.DefineMethod(
+ "set_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(void),
+ new[] { typeof(int), typeof(int), typeof(long), typeof(int) });
+
+ ILGenerator ilGen = getter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ldc_I4_0);
+ ilGen.Emit(OpCodes.Ret);
+
+ ilGen = setter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetGetMethod(getter);
+ property.SetSetMethod(setter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0), Expression.Constant(0), Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0), Expression.Constant(0), Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void IndexedPropertyVarArgs()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ MethodBuilder getter = typeBuild.DefineMethod(
+ "get_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ CallingConventions.VarArgs,
+ typeof(int),
+ Type.EmptyTypes);
+
+ ILGenerator ilGen = getter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ldc_I4_0);
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetGetMethod(getter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, Expression.Constant(0), Expression.Constant(0), Expression.Constant(0)));
+ Assert.Throws<ArgumentException>("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0), Expression.Constant(0), Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void NullInstanceInstanceProperty()
+ {
+ PropertyInfo prop = typeof(Dictionary<int, int>).GetProperty("Item");
+ ConstantExpression index = Expression.Constant(0);
+ Assert.Throws<ArgumentException>("instance", () => Expression.Property(null, prop, index));
+ }
+
+ [Fact]
+ public void InstanceToStaticProperty()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int) });
+
+ MethodBuilder getter = typeBuild.DefineMethod(
+ "get_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Static
+ | MethodAttributes.PrivateScope,
+ typeof(int),
+ new[] { typeof(int) });
+
+ ILGenerator ilGen = getter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ldc_I4_0);
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetGetMethod(getter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>(() => Expression.Property(instance, prop, Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void ByRefIndexer()
+ {
+ TypeBuilder typeBuild = GetTestTypeBuilder();
+
+ PropertyBuilder property = typeBuild.DefineProperty(
+ "Item", PropertyAttributes.None, typeof(int), new[] { typeof(int).MakeByRefType() });
+
+ MethodBuilder getter = typeBuild.DefineMethod(
+ "get_Item",
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
+ | MethodAttributes.PrivateScope,
+ typeof(int),
+ new[] { typeof(int).MakeByRefType() });
+
+ ILGenerator ilGen = getter.GetILGenerator();
+ ilGen.Emit(OpCodes.Ldc_I4_0);
+ ilGen.Emit(OpCodes.Ret);
+
+ property.SetGetMethod(getter);
+
+ TypeInfo info = typeBuild.CreateTypeInfo();
+ Type type = info.AsType();
+ PropertyInfo prop = type.GetProperties()[0];
+ Expression instance = Expression.Default(type);
+ Assert.Throws<ArgumentException>("indexes[0]", () => Expression.Property(instance, prop, Expression.Constant(0)));
+ }
+
+ [Fact]
+ public void CallWithoutIndices()
+ {
+ PropertyInfo prop = typeof(Dictionary<int, int>).GetProperty("Item");
+ DefaultExpression dict = Expression.Default(typeof(Dictionary<int, int>));
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(dict, prop, Array.Empty<Expression>()));
+ }
+
+ [Fact]
+ public void CallWithExcessiveIndices()
+ {
+ PropertyInfo prop = typeof(Dictionary<int, int>).GetProperty("Item");
+ DefaultExpression dict = Expression.Default(typeof(Dictionary<int, int>));
+ ConstantExpression index = Expression.Constant(0);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(dict, prop, index, index));
+ }
+
+ [Fact]
+ public void CallWithUnassignableIndex()
+ {
+ PropertyInfo prop = typeof(Dictionary<int, int>).GetProperty("Item");
+ DefaultExpression dict = Expression.Default(typeof(Dictionary<int, int>));
+ ConstantExpression index = Expression.Constant(0L);
+ Assert.Throws<ArgumentException>("arguments[0]", () => Expression.Property(dict, prop, index));
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public void CallWithLambdaIndex(bool useInterpreter)
+ {
+ // An exception to the rule against unassignable indices, lamdba expressions
+ // can be automatically quoted.
+ PropertyInfo prop = typeof(Dictionary<Expression<Func<int>>, int>).GetProperty("Item");
+ Expression<Func<int>> index = () => 2;
+ ConstantExpression dict = Expression.Constant(new Dictionary<Expression<Func<int>>, int>{{index, 9}});
+ Func<int> f = Expression.Lambda<Func<int>>(Expression.Property(dict, prop, index)).Compile(useInterpreter);
+ Assert.Equal(9, f());
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public void CallWithIntAndLambdaIndex(bool useInterpreter)
+ {
+ PropertyInfo prop = typeof(IntAndExpressionIndexed).GetProperty("Item");
+ ConstantExpression instance = Expression.Constant(new IntAndExpressionIndexed());
+ Expression<Action> index = Expression.Lambda<Action>(Expression.Empty());
+ ConstantExpression intIdx = Expression.Constant(0);
+ Func<bool> f = Expression.Lambda<Func<bool>>(Expression.Property(instance, prop, intIdx, index)).Compile(useInterpreter);
+ Assert.True(f());
+ }
+
+ [Fact]
+ public void TryIndexedAccessNonIndexedProperty()
+ {
+ ConstantExpression instance = Expression.Constant("");
+ PropertyInfo prop = typeof(string).GetProperty(nameof(string.Length));
+ ConstantExpression index = Expression.Constant(0);
+ Assert.Throws<ArgumentException>("indexer", () => Expression.Property(instance, prop, index));
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public void OverloadedIndexer(bool useInterpreter)
+ {
+ ConstantExpression instance = Expression.Constant(new OverloadedIndexers());
+ ConstantExpression index = Expression.Constant("");
+ Expression<Func<int>> exp = Expression.Lambda<Func<int>>(Expression.Property(instance, "Item", index));
+ Func<int> f = exp.Compile(useInterpreter);
+ Assert.Equal(2, f());
+ }
+
+ [Fact]
+ public void OverloadedIndexerBothMatch()
+ {
+ ConstantExpression instance = Expression.Constant(new OverloadedIndexersBothMatchString());
+ ConstantExpression index = Expression.Constant("");
+ Assert.Throws<InvalidOperationException>(() => Expression.Property(instance, "Item", index));
+ }
+
+ [Fact]
+ public void NoSuchPropertyExplicitlyNoIndices()
+ {
+ ConstantExpression instance = Expression.Constant("");
+ Assert.Throws<ArgumentException>(() => Expression.Property(instance, "ThisDoesNotExist", Array.Empty<Expression>()));
+ Assert.Throws<ArgumentException>(() => Expression.Property(instance, "ThisDoesNotExist", null));
+ }
+
+ [Theory, ClassData(typeof(CompilationTypes))]
+ public void NonIndexedPropertyExplicitlyNoIndices(bool useInterpreter)
+ {
+ ConstantExpression instance = Expression.Constant("123");
+ IndexExpression prop = Expression.Property(instance, "Length", null);
+ Expression<Func<int>> exp = Expression.Lambda<Func<int>>(prop);
+ Func<int> func = exp.Compile(useInterpreter);
+ Assert.Equal(3, func());
+ }
+
+ [Fact]
+ public void FindNothingForNullArgument()
+ {
+ ConstantExpression instance = Expression.Constant("123");
+ Assert.Throws<ArgumentException>(() => Expression.Property(instance, "Length", new Expression[] {null}));
+ }
+
+ [Fact]
+ public void NullArgument()
+ {
+ ConstantExpression instance = Expression.Constant(new Dictionary<int, int>());
+ PropertyInfo prop = typeof(Dictionary<int, int>).GetProperty("Item");
+ Assert.Throws<ArgumentException>(() => Expression.Property(instance, "Item", new Expression[] {null}));
+ Assert.Throws<ArgumentNullException>("arguments[0]", () => Expression.Property(instance, prop, new Expression[] {null}));
+ }
+
+ [Fact]
+ public void UnreadableIndex()
+ {
+ ConstantExpression instance = Expression.Constant(new Dictionary<int, int>());
+ PropertyInfo prop = typeof(Dictionary<int, int>).GetProperty("Item");
+ MemberExpression index = Expression.Property(null, typeof(Unreadable<int>).GetProperty(nameof(Unreadable<int>.WriteOnly)));
+ Assert.Throws<ArgumentException>("arguments[0]", () => Expression.Property(instance, "Item", index));
+ Assert.Throws<ArgumentException>("arguments[0]", () => Expression.Property(instance, prop, index));
+ }
+
+ private class IntAndExpressionIndexed
+ {
+ public bool this[int x, Expression<Action> y] => true;
+ }
+
+ private class OverloadedIndexers
+ {
+ public int this[int index] => 0;
+
+ public int this[int x, int y] => 1;
+
+ public int this[string index] => 2;
+ }
+
+ private class OverloadedIndexersBothMatchString
+ {
+ public int this[IComparable index] => 0;
+
+ public int this[ICloneable index] => 1;
+ }
+
class Vector1
{
public int this[int x]
diff --git a/src/System.Linq.Expressions/tests/InterpreterTests.cs b/src/System.Linq.Expressions/tests/InterpreterTests.cs
index 0a6185424b..9a9f7d443c 100644
--- a/src/System.Linq.Expressions/tests/InterpreterTests.cs
+++ b/src/System.Linq.Expressions/tests/InterpreterTests.cs
@@ -99,6 +99,57 @@ namespace System.Linq.Expressions.Tests
}");
}
+ [Fact]
+ public static void ConstructorThrows_StackTrace()
+ {
+ Expression<Func<Thrower>> e = () => new Thrower(true);
+ Func<Thrower> f = e.Compile(preferInterpretation: true);
+ AssertStackTrace(() => f(), "Thrower..ctor");
+ }
+
+ [Fact]
+ public static void PropertyGetterThrows_StackTrace()
+ {
+ Expression<Func<Thrower, int>> e = t => t.Bar;
+ Func<Thrower, int> f = e.Compile(preferInterpretation: true);
+ AssertStackTrace(() => f(new Thrower(error: false)), "Thrower.get_Bar");
+ }
+
+ [Fact]
+ public static void PropertySetterThrows_StackTrace()
+ {
+ ParameterExpression t = Expression.Parameter(typeof(Thrower), "t");
+ Expression<Action<Thrower>> e = Expression.Lambda<Action<Thrower>>(Expression.Assign(Expression.Property(t, nameof(Thrower.Bar)), Expression.Constant(0)), t);
+ Action<Thrower> f = e.Compile(preferInterpretation: true);
+ AssertStackTrace(() => f(new Thrower(error: false)), "Thrower.set_Bar");
+ }
+
+ [Fact]
+ public static void IndexerGetterThrows_StackTrace()
+ {
+ ParameterExpression t = Expression.Parameter(typeof(Thrower), "t");
+ Expression<Func<Thrower, int>> e = Expression.Lambda<Func<Thrower, int>>(Expression.MakeIndex(t, typeof(Thrower).GetProperty("Item"), new[] { Expression.Constant(0) }), t);
+ Func<Thrower, int> f = e.Compile(preferInterpretation: true);
+ AssertStackTrace(() => f(new Thrower(error: false)), "Thrower.get_Item");
+ }
+
+ [Fact]
+ public static void IndexerSetterThrows_StackTrace()
+ {
+ ParameterExpression t = Expression.Parameter(typeof(Thrower), "t");
+ Expression<Action<Thrower>> e = Expression.Lambda<Action<Thrower>>(Expression.Assign(Expression.MakeIndex(t, typeof(Thrower).GetProperty("Item"), new[] { Expression.Constant(0) }), Expression.Constant(0)), t);
+ Action<Thrower> f = e.Compile(preferInterpretation: true);
+ AssertStackTrace(() => f(new Thrower(error: false)), "Thrower.set_Item");
+ }
+
+ [Fact]
+ public static void MethodThrows_StackTrace()
+ {
+ Expression<Action<Thrower>> e = t => t.Foo();
+ Action<Thrower> f = e.Compile(preferInterpretation: true);
+ AssertStackTrace(() => f(new Thrower(error: false)), "Thrower.Foo");
+ }
+
public static void VerifyInstructions(this LambdaExpression expression, string expected)
{
string actual = expression.GetInstructions();
@@ -129,6 +180,53 @@ namespace System.Linq.Expressions.Tests
var debugView = (string)s_debugView.GetValue(lambda);
return debugView;
}
+
+ private static void AssertStackTrace(Action a, string searchTerm)
+ {
+ bool hasThrown = false;
+ try
+ {
+ a();
+ }
+ catch (Exception ex)
+ {
+ AssertStackTrace(ex, searchTerm);
+ hasThrown = true;
+ }
+
+ Assert.True(hasThrown);
+ }
+
+ private static void AssertStackTrace(Exception ex, string searchTerm)
+ {
+ Assert.True(ex.StackTrace.Contains(searchTerm));
+ }
+
+ private sealed class Thrower
+ {
+ public Thrower(bool error)
+ {
+ if (error)
+ throw new Exception();
+ }
+
+ public int this[int x]
+ {
+ get { throw new Exception(); }
+ set { throw new Exception(); }
+ }
+
+ public int Bar
+ {
+ get { throw new Exception(); }
+ set { throw new Exception(); }
+ }
+
+ public void Foo()
+ {
+ throw new Exception();
+ }
+ }
}
}
diff --git a/src/System.Linq.Expressions/tests/MemberInit/BindTests.cs b/src/System.Linq.Expressions/tests/MemberInit/BindTests.cs
index 4e47402f83..c35f663d6b 100644
--- a/src/System.Linq.Expressions/tests/MemberInit/BindTests.cs
+++ b/src/System.Linq.Expressions/tests/MemberInit/BindTests.cs
@@ -19,7 +19,7 @@ namespace System.Linq.Expressions.Tests
public static string StaticStringProperty { get; set; }
public static string StaticStringField;
public static string StaticReadonlyStringProperty => "";
- public readonly static string StaticReadonlyStringField = "";
+ public static readonly string StaticReadonlyStringField = "";
public const string ConstantString = "Constant";
#pragma warning restore 649
}
diff --git a/src/System.Linq.Expressions/tests/ReadOnlyCollectionBuilderTests.cs b/src/System.Linq.Expressions/tests/ReadOnlyCollectionBuilderTests.cs
new file mode 100644
index 0000000000..b19afad6f4
--- /dev/null
+++ b/src/System.Linq.Expressions/tests/ReadOnlyCollectionBuilderTests.cs
@@ -0,0 +1,914 @@
+// 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.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+namespace System.Linq.Expressions.Tests
+{
+ public class ReadOnlyCollectionBuilderTests
+ {
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Ctor_Default()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>();
+
+ Assert.Equal(0, rocb.Capacity);
+
+ AssertEmpty(rocb);
+ }
+
+ [Theory]
+ [InlineData(-2)]
+ [InlineData(-1)]
+ public void ReadOnlyCollectionBuilder_Ctor_Capacity_ArgumentChecking(int capacity)
+ {
+ Assert.Throws<ArgumentOutOfRangeException>("capacity", () => new ReadOnlyCollectionBuilder<int>(capacity));
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(2)]
+ public void ReadOnlyCollectionBuilder_Ctor_Capacity(int capacity)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(capacity);
+
+ Assert.Equal(capacity, rocb.Capacity);
+
+ AssertEmpty(rocb);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Ctor_Collection_ArgumentChecking()
+ {
+ Assert.Throws<ArgumentNullException>("collection", () => new ReadOnlyCollectionBuilder<int>(null));
+ }
+
+ [Theory]
+ [MemberData(nameof(InitialCollections))]
+ public void ReadOnlyCollectionBuilder_Ctor_Collection(IEnumerable<int> collection)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(collection);
+
+ Assert.Equal(collection.Count(), rocb.Count);
+ Assert.True(collection.SequenceEqual(rocb));
+
+ int[] array = rocb.ToArray();
+
+ Assert.Equal(collection.Count(), array.Length);
+ Assert.True(collection.SequenceEqual(array));
+
+ ReadOnlyCollection<int> roc = rocb.ToReadOnlyCollection();
+
+ Assert.Equal(collection.Count(), roc.Count);
+ Assert.True(collection.SequenceEqual(roc));
+
+ AssertEmpty(rocb); // ToReadOnlyCollection behavior is to empty the builder
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Capacity1()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>();
+
+ Assert.Equal(0, rocb.Capacity);
+ Assert.Equal(0, rocb.Count);
+
+ Assert.Throws<ArgumentOutOfRangeException>(() => rocb.Capacity = -1);
+
+ rocb.Capacity = 0;
+
+ Assert.Equal(0, rocb.Capacity);
+ Assert.Equal(0, rocb.Count);
+
+ rocb.Capacity = 1;
+
+ Assert.Equal(1, rocb.Capacity);
+ Assert.Equal(0, rocb.Count);
+
+ rocb.Capacity = 2;
+
+ Assert.Equal(2, rocb.Capacity);
+ Assert.Equal(0, rocb.Count);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Capacity2()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1 });
+
+ Assert.Equal(1, rocb.Capacity);
+ Assert.Equal(1, rocb.Count);
+
+ Assert.Throws<ArgumentOutOfRangeException>("value", () => { rocb.Capacity = 0; });
+ Assert.Throws<ArgumentOutOfRangeException>("value", () => { rocb.Capacity = -1; });
+
+ rocb.Capacity = 1;
+
+ Assert.Equal(1, rocb.Capacity);
+ Assert.Equal(1, rocb.Count);
+
+ rocb.Capacity = 2;
+
+ Assert.Equal(2, rocb.Capacity);
+ Assert.Equal(1, rocb.Count);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Capacity3()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1 });
+
+ Assert.Equal(1, rocb.Capacity);
+ Assert.Equal(1, rocb.Count);
+
+ rocb.RemoveAt(0);
+
+ Assert.Equal(1, rocb.Capacity);
+ Assert.Equal(0, rocb.Count);
+
+ rocb.Capacity = 0;
+
+ Assert.Equal(0, rocb.Capacity);
+ Assert.Equal(0, rocb.Count);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IList_IsReadOnly()
+ {
+ IList rocb = new ReadOnlyCollectionBuilder<int>();
+
+ Assert.False(rocb.IsReadOnly);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_ICollectionOfT_IsReadOnly()
+ {
+ ICollection<int> rocb = new ReadOnlyCollectionBuilder<int>();
+
+ Assert.False(rocb.IsReadOnly);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IList_IsFixedSize()
+ {
+ IList rocb = new ReadOnlyCollectionBuilder<int>();
+
+ Assert.False(rocb.IsFixedSize);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IList_IsSynchronized()
+ {
+ ICollection rocb = new ReadOnlyCollectionBuilder<int>();
+
+ Assert.False(rocb.IsSynchronized);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_ICollection_SyncRoot()
+ {
+ ICollection rocb = new ReadOnlyCollectionBuilder<int>();
+
+ object root1 = rocb.SyncRoot;
+ Assert.NotNull(root1);
+
+ object root2 = rocb.SyncRoot;
+ Assert.Same(root1, root2);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IndexOf()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 3 });
+
+ Assert.Equal(4, rocb.Count);
+
+ Assert.Equal(0, rocb.IndexOf(1));
+ Assert.Equal(1, rocb.IndexOf(2));
+ Assert.Equal(3, rocb.IndexOf(3));
+
+ Assert.InRange(rocb.IndexOf(0), int.MinValue, -1);
+ Assert.InRange(rocb.IndexOf(4), int.MinValue, -1);
+
+ rocb.Capacity = 5;
+
+ Assert.Equal(4, rocb.Count);
+ Assert.InRange(rocb.IndexOf(0), int.MinValue, -1); // No default values leak in through underlying array
+
+ Assert.True(rocb.Remove(3));
+
+ Assert.Equal(3, rocb.Count);
+ Assert.InRange(rocb.IndexOf(0), int.MinValue, -1); // No default values leak in through underlying array
+ Assert.InRange(rocb.IndexOf(3), int.MinValue, -1);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IList_IndexOf()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 3 });
+ IList list = rocb;
+
+ Assert.Equal(4, list.Count);
+
+ Assert.Equal(0, list.IndexOf(1));
+ Assert.Equal(1, list.IndexOf(2));
+ Assert.Equal(3, list.IndexOf(3));
+
+ Assert.InRange(list.IndexOf(0), int.MinValue, -1);
+ Assert.InRange(list.IndexOf(4), int.MinValue, -1);
+
+ rocb.Capacity = 5;
+
+ Assert.Equal(4, list.Count);
+ Assert.InRange(list.IndexOf(0), int.MinValue, -1); // No default values leak in through underlying array
+
+ list.Remove(3);
+
+ Assert.Equal(3, list.Count);
+ Assert.InRange(list.IndexOf(0), int.MinValue, -1); // No default values leak in through underlying array
+ Assert.InRange(list.IndexOf(3), int.MinValue, -1);
+
+ Assert.InRange(list.IndexOf("bar"), int.MinValue, -1);
+ Assert.InRange(list.IndexOf(null), int.MinValue, -1);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Insert()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>();
+
+ Assert.Equal(0, rocb.Count);
+
+ Assert.Throws<ArgumentOutOfRangeException>(() => rocb.Insert(-1, 1));
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb.Insert(1, 1));
+
+ rocb.Insert(0, 1);
+
+ Assert.True(new[] { 1 }.SequenceEqual(rocb));
+
+ rocb.Insert(0, 2);
+
+ Assert.True(new[] { 2, 1 }.SequenceEqual(rocb));
+
+ rocb.Insert(0, 3);
+
+ Assert.True(new[] { 3, 2, 1 }.SequenceEqual(rocb));
+
+ rocb.Insert(1, 4);
+
+ Assert.True(new[] { 3, 4, 2, 1 }.SequenceEqual(rocb));
+
+ rocb.Insert(4, 5);
+
+ Assert.True(new[] { 3, 4, 2, 1, 5 }.SequenceEqual(rocb));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IList_Insert()
+ {
+ IList rocb = new ReadOnlyCollectionBuilder<int>();
+
+ Assert.Equal(0, rocb.Count);
+
+ Assert.Throws<ArgumentOutOfRangeException>(() => rocb.Insert(-1, 1));
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb.Insert(1, 1));
+
+ Assert.Throws<ArgumentException>("value", () => rocb.Insert(1, "bar"));
+ Assert.Throws<ArgumentException>("value", () => rocb.Insert(1, null));
+
+ rocb.Insert(0, 1);
+
+ Assert.True(new[] { 1 }.SequenceEqual(rocb.Cast<int>()));
+
+ rocb.Insert(0, 2);
+
+ Assert.True(new[] { 2, 1 }.SequenceEqual(rocb.Cast<int>()));
+
+ rocb.Insert(0, 3);
+
+ Assert.True(new[] { 3, 2, 1 }.SequenceEqual(rocb.Cast<int>()));
+
+ rocb.Insert(1, 4);
+
+ Assert.True(new[] { 3, 4, 2, 1 }.SequenceEqual(rocb.Cast<int>()));
+
+ rocb.Insert(4, 5);
+
+ Assert.True(new[] { 3, 4, 2, 1, 5 }.SequenceEqual(rocb.Cast<int>()));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_RemoveAt()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 });
+
+ Assert.True(new[] { 1, 2, 3, 4 }.SequenceEqual(rocb));
+
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(-1));
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(4));
+
+ rocb.RemoveAt(0);
+
+ Assert.True(new[] { 2, 3, 4 }.SequenceEqual(rocb));
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(3));
+
+ rocb.RemoveAt(1);
+
+ Assert.True(new[] { 2, 4 }.SequenceEqual(rocb));
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(2));
+
+ rocb.RemoveAt(1);
+
+ Assert.True(new[] { 2 }.SequenceEqual(rocb));
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(1));
+
+ rocb.RemoveAt(0);
+
+ Assert.Equal(0, rocb.Count);
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(0));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Remove()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 4 });
+
+ Assert.True(new[] { 1, 2, 2, 4 }.SequenceEqual(rocb));
+
+ Assert.False(rocb.Remove(0));
+
+ Assert.True(new[] { 1, 2, 2, 4 }.SequenceEqual(rocb));
+
+ Assert.True(rocb.Remove(2));
+
+ Assert.True(new[] { 1, 2, 4 }.SequenceEqual(rocb));
+
+ Assert.True(rocb.Remove(1));
+
+ Assert.True(new[] { 2, 4 }.SequenceEqual(rocb));
+
+ Assert.True(rocb.Remove(4));
+
+ Assert.True(new[] { 2 }.SequenceEqual(rocb));
+
+ Assert.True(rocb.Remove(2));
+
+ Assert.Equal(0, rocb.Count);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IList_Remove()
+ {
+ IList rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 4 });
+
+ Assert.True(new[] { 1, 2, 2, 4 }.SequenceEqual(rocb.Cast<int>()));
+
+ rocb.Remove(0);
+ rocb.Remove("bar");
+ rocb.Remove(null);
+
+ Assert.True(new[] { 1, 2, 2, 4 }.SequenceEqual(rocb.Cast<int>()));
+
+ rocb.Remove(2);
+
+ Assert.True(new[] { 1, 2, 4 }.SequenceEqual(rocb.Cast<int>()));
+
+ rocb.Remove(1);
+
+ Assert.True(new[] { 2, 4 }.SequenceEqual(rocb.Cast<int>()));
+
+ rocb.Remove(4);
+
+ Assert.True(new[] { 2 }.SequenceEqual(rocb.Cast<int>()));
+
+ rocb.Remove(2);
+
+ Assert.Equal(0, rocb.Count);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Indexer_Get()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 });
+
+ // CONSIDER: Throw ArgumentOutOfRangeException instead, see https://github.com/dotnet/corefx/issues/14059
+ Assert.Throws<IndexOutOfRangeException>(() => rocb[-1]);
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb[4]);
+
+ Assert.Equal(1, rocb[0]);
+ Assert.Equal(2, rocb[1]);
+ Assert.Equal(3, rocb[2]);
+ Assert.Equal(4, rocb[3]);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Indexer_IList_Get()
+ {
+ IList rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 });
+
+ // CONSIDER: Throw ArgumentOutOfRangeException instead, see https://github.com/dotnet/corefx/issues/14059
+ Assert.Throws<IndexOutOfRangeException>(() => rocb[-1]);
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb[4]);
+
+ Assert.Equal(1, rocb[0]);
+ Assert.Equal(2, rocb[1]);
+ Assert.Equal(3, rocb[2]);
+ Assert.Equal(4, rocb[3]);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Indexer_Set()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 });
+
+ // CONSIDER: Throw ArgumentOutOfRangeException instead, see https://github.com/dotnet/corefx/issues/14059
+ Assert.Throws<IndexOutOfRangeException>(() => rocb[-1] = -1);
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb[4] = -1);
+
+ rocb[0] = -1;
+ Assert.Equal(-1, rocb[0]);
+
+ rocb[1] = -2;
+ Assert.Equal(-2, rocb[1]);
+
+ rocb[2] = -3;
+ Assert.Equal(-3, rocb[2]);
+
+ rocb[3] = -4;
+ Assert.Equal(-4, rocb[3]);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Indexer_IList_Set()
+ {
+ IList rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 });
+
+ // CONSIDER: Throw ArgumentOutOfRangeException instead, see https://github.com/dotnet/corefx/issues/14059
+ Assert.Throws<IndexOutOfRangeException>(() => rocb[-1] = -1);
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb[4] = -1);
+
+ Assert.Throws<ArgumentException>("value", () => rocb[0] = "bar");
+ Assert.Throws<ArgumentException>("value", () => rocb[0] = null);
+
+ rocb[0] = -1;
+ Assert.Equal(-1, rocb[0]);
+
+ rocb[1] = -2;
+ Assert.Equal(-2, rocb[1]);
+
+ rocb[2] = -3;
+ Assert.Equal(-3, rocb[2]);
+
+ rocb[3] = -4;
+ Assert.Equal(-4, rocb[3]);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Add()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>();
+
+ for (int i = 1; i <= 10; i++)
+ {
+ rocb.Add(i);
+
+ Assert.True(Enumerable.Range(1, i).SequenceEqual(rocb));
+ }
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IList_Add()
+ {
+ IList rocb = new ReadOnlyCollectionBuilder<int>();
+
+ for (int i = 1; i <= 10; i++)
+ {
+ rocb.Add(i);
+
+ Assert.True(Enumerable.Range(1, i).SequenceEqual(rocb.Cast<int>()));
+ }
+
+ Assert.Throws<ArgumentException>(() => rocb.Add(null));
+ Assert.Throws<ArgumentException>(() => rocb.Add("foo"));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Clear1()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ rocb.Clear();
+
+ Assert.Equal(0, rocb.Count);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Clear2()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>();
+
+ rocb.Clear();
+
+ Assert.Equal(0, rocb.Count);
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Contains1()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 3 });
+
+ Assert.True(rocb.Contains(1));
+ Assert.True(rocb.Contains(2));
+ Assert.True(rocb.Contains(3));
+
+ Assert.False(rocb.Contains(-1));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Contains2()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<string>(new[] { "bar", "foo", "qux" });
+
+ Assert.True(rocb.Contains("bar"));
+ Assert.True(rocb.Contains("foo"));
+ Assert.True(rocb.Contains("qux"));
+
+ Assert.False(rocb.Contains(null));
+ Assert.False(rocb.Contains("baz"));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Contains3()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<string>(new[] { "bar", "foo", "qux", null });
+
+ Assert.True(rocb.Contains("bar"));
+ Assert.True(rocb.Contains("foo"));
+ Assert.True(rocb.Contains("qux"));
+ Assert.True(rocb.Contains(null));
+
+ Assert.False(rocb.Contains("baz"));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IList_Contains1()
+ {
+ IList rocb = new ReadOnlyCollectionBuilder<string>(new[] { "bar", "foo", "qux", null });
+
+ Assert.True(rocb.Contains("bar"));
+ Assert.True(rocb.Contains("foo"));
+ Assert.True(rocb.Contains("qux"));
+ Assert.True(rocb.Contains(null));
+
+ Assert.False(rocb.Contains("baz"));
+ Assert.False(rocb.Contains(42));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_IList_Contains2()
+ {
+ IList rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ Assert.True(rocb.Contains(1));
+ Assert.True(rocb.Contains(2));
+ Assert.True(rocb.Contains(3));
+
+ Assert.False(rocb.Contains("baz"));
+ Assert.False(rocb.Contains(0));
+ Assert.False(rocb.Contains(null));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Reverse()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ rocb.Reverse();
+
+ Assert.True(new[] { 3, 2, 1 }.SequenceEqual(rocb));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Reverse_Range_ArgumentChecking()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ Assert.Throws<ArgumentOutOfRangeException>("index", () => rocb.Reverse(-1, 1));
+ Assert.Throws<ArgumentOutOfRangeException>("count", () => rocb.Reverse(1, -1));
+
+ // CONSIDER: Throw ArgumentException just like List<T> does, see https://github.com/dotnet/corefx/issues/14059
+ // Assert.Throws<ArgumentException>(() => rocb.Reverse(3, 1));
+ // Assert.Throws<ArgumentException>(() => rocb.Reverse(1, 3));
+ // Assert.Throws<ArgumentException>(() => rocb.Reverse(2, 2));
+ // Assert.Throws<ArgumentException>(() => rocb.Reverse(3, 1));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_Reverse_Range()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4, 5 });
+
+ rocb.Reverse(1, 3);
+
+ Assert.True(new[] { 1, 4, 3, 2, 5 }.SequenceEqual(rocb));
+ }
+
+ [Theory]
+ [MemberData(nameof(Lengths))]
+ public void ReadOnlyCollectionBuilder_ToArray(int length)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>();
+
+ for (int i = 0; i < length; i++)
+ {
+ rocb.Add(i);
+ }
+
+ int[] array = rocb.ToArray();
+
+ Assert.True(Enumerable.Range(0, length).SequenceEqual(array));
+ }
+
+ [Theory]
+ [MemberData(nameof(Lengths))]
+ public void ReadOnlyCollectionBuilder_ToReadOnlyCollection(int length)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>();
+
+ for (int i = 0; i < length; i++)
+ {
+ rocb.Add(i);
+ }
+
+ ReadOnlyCollection<int> collection = rocb.ToReadOnlyCollection();
+
+ Assert.Equal(length, collection.Count);
+
+ Assert.True(Enumerable.Range(0, length).SequenceEqual(collection));
+
+ AssertEmpty(rocb);
+ }
+
+ [Theory]
+ [MemberData(nameof(Lengths))]
+ public void ReadOnlyCollectionBuilder_GetEnumerator(int length)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>();
+
+ for (int i = 0; i < length; i++)
+ {
+ rocb.Add(i);
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ IEnumerator<int> enumerator = rocb.GetEnumerator();
+
+ // NB: Current property on generic enumerator doesn't throw; this is consistent with List<T>.
+
+ for (int i = 0; i < length; i++)
+ {
+ Assert.True(enumerator.MoveNext());
+ Assert.Equal(i, enumerator.Current);
+ Assert.Equal(i, ((IEnumerator)enumerator).Current);
+
+ enumerator.Dispose(); // NB: Similar to List<T>, calling Dispose does not have an effect here
+ }
+
+ Assert.False(enumerator.MoveNext());
+ Assert.False(enumerator.MoveNext());
+
+ // NB: Current property on generic enumerator doesn't throw; this is consistent with List<T>.
+
+ enumerator.Reset();
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(Lengths))]
+ public void ReadOnlyCollectionBuilder_IEnumerable_GetEnumerator(int length)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>();
+
+ for (int i = 0; i < length; i++)
+ {
+ rocb.Add(i);
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ IEnumerator enumerator = ((IEnumerable)rocb).GetEnumerator();
+
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current);
+
+ for (int i = 0; i < length; i++)
+ {
+ Assert.True(enumerator.MoveNext());
+ Assert.Equal(i, enumerator.Current);
+ Assert.Equal(i, ((IEnumerator)enumerator).Current);
+
+ ((IDisposable)enumerator).Dispose(); // NB: Similar to List<T>, calling Dispose does not have an effect here
+ }
+
+ Assert.False(enumerator.MoveNext());
+ Assert.False(enumerator.MoveNext());
+
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current);
+
+ enumerator.Reset();
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(Versioning))]
+ public void ReadOnlyCollectionBuilder_IEnumeratorOfT_Versioning_MoveNext(int index, Action<ReadOnlyCollectionBuilder<int>> edit)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ IEnumerator<int> enumerator = rocb.GetEnumerator();
+
+ Assert.True(enumerator.MoveNext());
+
+ edit(rocb);
+
+ Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ }
+
+ [Theory]
+ [MemberData(nameof(Versioning))]
+ public void ReadOnlyCollectionBuilder_IEnumeratorOfT_Versioning_Reset(int index, Action<ReadOnlyCollectionBuilder<int>> edit)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ IEnumerator<int> enumerator = rocb.GetEnumerator();
+
+ Assert.True(enumerator.MoveNext());
+
+ edit(rocb);
+
+ Assert.Throws<InvalidOperationException>(() => enumerator.Reset());
+ }
+
+ [Theory]
+ [MemberData(nameof(Versioning))]
+ public void ReadOnlyCollectionBuilder_IEnumerator_Versioning_MoveNext(int index, Action<ReadOnlyCollectionBuilder<int>> edit)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ IEnumerator enumerator = ((IEnumerable)rocb).GetEnumerator();
+
+ Assert.True(enumerator.MoveNext());
+
+ edit(rocb);
+
+ Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext());
+ }
+
+ [Theory]
+ [MemberData(nameof(Versioning))]
+ public void ReadOnlyCollectionBuilder_IEnumerator_Versioning_Reset(int index, Action<ReadOnlyCollectionBuilder<int>> edit)
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ IEnumerator enumerator = ((IEnumerable)rocb).GetEnumerator();
+
+ Assert.True(enumerator.MoveNext());
+
+ edit(rocb);
+
+ Assert.Throws<InvalidOperationException>(() => enumerator.Reset());
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_CopyTo_ArgumentChecking()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ Assert.Throws<ArgumentNullException>(() => rocb.CopyTo(null, 0));
+ Assert.Throws<ArgumentOutOfRangeException>(() => rocb.CopyTo(new int[3], -1));
+ Assert.Throws<ArgumentException>(() => rocb.CopyTo(new int[3], 3)); // NB: Consistent with List<T> behavior
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_CopyTo1()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ var array = new int[3];
+
+ rocb.CopyTo(array, 0);
+
+ Assert.True(new[] { 1, 2, 3 }.SequenceEqual(array));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_CopyTo2()
+ {
+ var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ var array = new int[5] { 1, 2, 3, 4, 5 };
+
+ rocb.CopyTo(array, 1);
+
+ Assert.True(new[] { 1, 1, 2, 3, 5 }.SequenceEqual(array));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_ICollection_CopyTo_ArgumentChecking()
+ {
+ ICollection rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ Assert.Throws<ArgumentNullException>(() => rocb.CopyTo(null, 0));
+ Assert.Throws<ArgumentOutOfRangeException>(() => rocb.CopyTo(new int[3], -1));
+ Assert.Throws<ArgumentException>(() => rocb.CopyTo(new int[3], 3)); // NB: Consistent with List<T> behavior
+ Assert.Throws<ArgumentException>(() => rocb.CopyTo(new int[3, 3], 0));
+
+ // CONSIDER: Throw ArgumentException instead to be consistent with List<T>, see https://github.com/dotnet/corefx/issues/14059
+ Assert.Throws<ArrayTypeMismatchException>(() => rocb.CopyTo(new string[3], 0));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_ICollection_CopyTo1()
+ {
+ ICollection rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ var array = new int[3];
+
+ rocb.CopyTo(array, 0);
+
+ Assert.True(new[] { 1, 2, 3 }.SequenceEqual(array));
+ }
+
+ [Fact]
+ public void ReadOnlyCollectionBuilder_ICollection_CopyTo2()
+ {
+ ICollection rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 });
+
+ var array = new int[5] { 1, 2, 3, 4, 5 };
+
+ rocb.CopyTo(array, 1);
+
+ Assert.True(new[] { 1, 1, 2, 3, 5 }.SequenceEqual(array));
+ }
+
+ private static void AssertEmpty<T>(ReadOnlyCollectionBuilder<T> rocb)
+ {
+ Assert.Equal(0, rocb.Count);
+
+ Assert.False(rocb.Contains(default(T)));
+ Assert.False(rocb.Remove(default(T)));
+ Assert.InRange(rocb.IndexOf(default(T)), int.MinValue, -1);
+
+ IEnumerator<T> e = rocb.GetEnumerator();
+ Assert.False(e.MoveNext());
+ }
+
+ private static IEnumerable<object[]> InitialCollections() =>
+ new IEnumerable<int>[]
+ {
+ new int[0],
+ new int[] { 1 },
+ new int[] { 1, 2 },
+ new int[] { 1, 2, 3 },
+ new int[] { 1, 2, 3, 4 },
+ new int[] { 1, 2, 3, 4, 5 },
+
+ new List<int>(),
+ new List<int>() { 1 },
+ new List<int>() { 1, 2 },
+ new List<int>() { 1, 2, 3 },
+ new List<int>() { 1, 2, 3, 4 },
+ new List<int>() { 1, 2, 3, 4, 5 },
+
+ Enumerable.Empty<int>(),
+ Enumerable.Range(1, 1),
+ Enumerable.Range(1, 2),
+ Enumerable.Range(1, 3),
+ Enumerable.Range(1, 4),
+ Enumerable.Range(1, 5),
+ }.Select(x => new object[] { x });
+
+ private static IEnumerable<object[]> Lengths() => Enumerable.Range(0, 10).Select(i => new object[] { i });
+
+ private static IEnumerable<object[]> Versioning() =>
+ new Action<ReadOnlyCollectionBuilder<int>>[]
+ {
+ e => e.Add(1),
+ e => ((IList)e).Add(1),
+ e => e[0] = 1,
+ e => ((IList)e)[0] = 1,
+ e => e.Insert(0, 1),
+ e => ((IList)e).Insert(0, 1),
+ e => e.Remove(1),
+ e => ((IList)e).Remove(1),
+ e => e.RemoveAt(0),
+ e => e.Reverse(),
+ }.Select((x, i) => new object[] { i, x });
+ }
+}
diff --git a/src/System.Linq.Expressions/tests/StackSpillerTests.cs b/src/System.Linq.Expressions/tests/StackSpillerTests.cs
index e64d7440cf..38b49e24e8 100644
--- a/src/System.Linq.Expressions/tests/StackSpillerTests.cs
+++ b/src/System.Linq.Expressions/tests/StackSpillerTests.cs
@@ -1257,7 +1257,7 @@ namespace System.Linq.Expressions.Tests
.maxcontinuation 1
IP_0000: InitMutableValue(0)
- IP_0001: New System.Linq.Expressions.Tests.StackSpillerTests+ValueList
+ IP_0001: DefaultValue System.Linq.Expressions.Tests.StackSpillerTests+ValueList
IP_0002: Dup()
.try
{
@@ -1364,7 +1364,7 @@ namespace System.Linq.Expressions.Tests
.maxcontinuation 1
IP_0000: InitMutableValue(0)
- IP_0001: New System.Linq.Expressions.Tests.StackSpillerTests+ValueBar
+ IP_0001: DefaultValue System.Linq.Expressions.Tests.StackSpillerTests+ValueBar
IP_0002: Dup()
.try
{
@@ -1471,7 +1471,7 @@ namespace System.Linq.Expressions.Tests
.maxcontinuation 1
IP_0000: InitMutableValue(0)
- IP_0001: New System.Linq.Expressions.Tests.StackSpillerTests+ValueBar
+ IP_0001: DefaultValue System.Linq.Expressions.Tests.StackSpillerTests+ValueBar
IP_0002: Dup()
.try
{
@@ -1653,7 +1653,7 @@ namespace System.Linq.Expressions.Tests
.maxcontinuation 1
IP_0000: InitMutableValue(0)
- IP_0001: New System.Linq.Expressions.Tests.StackSpillerTests+ValueBar
+ IP_0001: DefaultValue System.Linq.Expressions.Tests.StackSpillerTests+ValueBar
IP_0002: Dup()
IP_0003: Call(System.Collections.Generic.List`1[System.Int32] get_Xs())
IP_0004: Dup()
diff --git a/src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj b/src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj
index bc69a4c2b0..4501155e16 100644
--- a/src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj
+++ b/src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj
@@ -102,13 +102,17 @@
<Compile Include="Dynamic\CallSiteBinderDefaultBehaviourTests.cs" />
<Compile Include="Dynamic\CallSiteTests.cs" />
<Compile Include="Dynamic\ConvertBinderTests.cs" />
+ <Compile Include="Dynamic\DynamicObjectTests.cs" />
<Compile Include="Dynamic\DynamicObjectDefaultBehaviorTests.cs" />
<Compile Include="Dynamic\ExpandoObjectProxyTests.cs" />
+ <Compile Include="Dynamic\ExpandoObjectTests.cs" />
<Compile Include="Dynamic\GetIndexBinderTests.cs" />
<Compile Include="Dynamic\GetMemberBinderTests.cs" />
<Compile Include="Dynamic\InvokeBinderTests.cs" />
<Compile Include="Dynamic\InvokeMemberBindingTests.cs" />
- <Compile Include="Dynamic\UnaryOperationTests.cs .cs" />
+ <Compile Include="Dynamic\SetIndexBinderTests.cs" />
+ <Compile Include="Dynamic\SetMemberBinderTests.cs" />
+ <Compile Include="Dynamic\UnaryOperationTests.cs" />
<Compile Include="ExceptionHandling\ExceptionHandlingExpressions.cs" />
<Compile Include="ExpressionTests.cs" />
<Compile Include="Goto\Break.cs" />
@@ -180,6 +184,7 @@
<Compile Include="New\NewWithParameterTests.cs" />
<Compile Include="New\NewWithTwoParametersTests.cs" />
<Compile Include="New\TypeExtensions.cs" />
+ <Compile Include="ReadOnlyCollectionBuilderTests.cs" />
<Compile Include="SequenceTests\SequenceTests.cs" />
<Compile Include="StackSpillerTests.cs" />
<Compile Include="Switch\SwitchTests.cs" />
@@ -199,6 +204,7 @@
<Compile Include="Unary\IncDecAssign\PostIncrementAssignTests.cs" />
<Compile Include="Unary\IncDecAssign\PreDecrementAssignTests.cs" />
<Compile Include="Unary\IncDecAssign\PreIncrementAssignTests.cs" />
+ <Compile Include="Unary\IncrementDecrementTests.cs" />
<Compile Include="Unary\UnaryArithmeticNegateNullableOneOffTests.cs" />
<Compile Include="Unary\UnaryArithmeticNegateCheckedNullableTests.cs" />
<Compile Include="Unary\UnaryArithmeticNegateNullableTests.cs" />
@@ -247,4 +253,4 @@
<Compile Include="ILReader\SigParser.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/System.Linq.Expressions/tests/Unary/IncrementDecrementTests.cs b/src/System.Linq.Expressions/tests/Unary/IncrementDecrementTests.cs
new file mode 100644
index 0000000000..fd442ce093
--- /dev/null
+++ b/src/System.Linq.Expressions/tests/Unary/IncrementDecrementTests.cs
@@ -0,0 +1,132 @@
+// 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.Generic;
+
+namespace System.Linq.Expressions.Tests
+{
+ public abstract class IncrementDecrementTests
+ {
+ public struct Decrementable
+ {
+ public Decrementable(int value)
+ {
+ Value = value;
+ }
+
+ public int Value { get; }
+
+ public static Decrementable operator --(Decrementable operand) => new Decrementable(operand.Value - 1);
+ }
+
+ public struct Incrementable
+ {
+ public Incrementable(int value)
+ {
+ Value = value;
+ }
+
+ public int Value { get; }
+
+ public static Incrementable operator ++(Incrementable operand) => new Incrementable(operand.Value + 1);
+ }
+
+ public static Incrementable DoublyIncrement(Incrementable operand) => new Incrementable(operand.Value + 2);
+
+ public static int DoublyIncrementInt32(int operand) => operand + 2;
+
+ public static Decrementable DoublyDecrement(Decrementable operand) => new Decrementable(operand.Value - 2);
+
+ public static int DoublyDecrementInt32(int operand) => operand - 2;
+
+ protected static IEnumerable<object[]> NonArithmeticObjects(bool includeReferenceTypes)
+ {
+ if (includeReferenceTypes)
+ {
+ yield return new object[] {"One"};
+ }
+
+ yield return new object[] {DateTime.MaxValue};
+ yield return new object[] {ExpressionType.Decrement};
+ }
+
+ protected static IEnumerable<object[]> IncrementableValues(bool includeNulls)
+ {
+ yield return new object[] {new Incrementable(0), new Incrementable(1)};
+ yield return new object[] {new Incrementable(-1), new Incrementable(0)};
+ yield return new object[] {new Incrementable(int.MinValue), new Incrementable(int.MinValue + 1)};
+ yield return new object[] {new Incrementable(int.MaxValue), new Incrementable(int.MinValue)};
+
+ if (includeNulls)
+ {
+ yield return new object[] {null, null};
+ }
+ }
+
+ protected static IEnumerable<object[]> DoublyIncrementedIncrementableValues(bool includeNulls)
+ {
+ yield return new object[] {new Incrementable(0), new Incrementable(2)};
+ yield return new object[] {new Incrementable(-1), new Incrementable(1)};
+ yield return new object[] {new Incrementable(int.MinValue), new Incrementable(int.MinValue + 2)};
+ yield return new object[] {new Incrementable(int.MaxValue), new Incrementable(int.MinValue + 1)};
+
+ if (includeNulls)
+ {
+ yield return new object[] {null, null};
+ }
+ }
+
+ protected static IEnumerable<object[]> DoublyIncrementedInt32s(bool includeNulls)
+ {
+ yield return new object[] {0, 2};
+ yield return new object[] {-1, 1};
+ yield return new object[] {int.MinValue, int.MinValue + 2};
+ yield return new object[] {int.MaxValue, int.MinValue + 1};
+
+ if (includeNulls)
+ {
+ yield return new object[] {null, null};
+ }
+ }
+
+ protected static IEnumerable<object[]> DecrementableValues(bool includeNulls)
+ {
+ yield return new object[] {new Decrementable(0), new Decrementable(-1)};
+ yield return new object[] {new Decrementable(1), new Decrementable(0)};
+ yield return new object[] {new Decrementable(int.MaxValue), new Decrementable(int.MaxValue - 1)};
+ yield return new object[] {new Decrementable(int.MinValue), new Decrementable(int.MaxValue)};
+
+ if (includeNulls)
+ {
+ yield return new object[] {null, null};
+ }
+ }
+
+ protected static IEnumerable<object[]> DoublyDecrementedDecrementableValues(bool includeNulls)
+ {
+ yield return new object[] {new Decrementable(0), new Decrementable(-2)};
+ yield return new object[] {new Decrementable(1), new Decrementable(-1)};
+ yield return new object[] {new Decrementable(int.MaxValue), new Decrementable(int.MaxValue - 2)};
+ yield return new object[] {new Decrementable(int.MinValue), new Decrementable(int.MaxValue - 1)};
+
+ if (includeNulls)
+ {
+ yield return new object[] {null, null};
+ }
+ }
+
+ protected static IEnumerable<object[]> DoublyDecrementedInt32s(bool includeNulls)
+ {
+ yield return new object[] {0, -2};
+ yield return new object[] {1, -1};
+ yield return new object[] {int.MaxValue, int.MaxValue - 2};
+ yield return new object[] {int.MinValue, int.MaxValue - 1};
+
+ if (includeNulls)
+ {
+ yield return new object[] {null, null};
+ }
+ }
+ }
+}
diff --git a/src/System.Linq.Expressions/tests/Unary/UnaryDecrementNullableTests.cs b/src/System.Linq.Expressions/tests/Unary/UnaryDecrementNullableTests.cs
index 8f1555ec78..7b0395a964 100644
--- a/src/System.Linq.Expressions/tests/Unary/UnaryDecrementNullableTests.cs
+++ b/src/System.Linq.Expressions/tests/Unary/UnaryDecrementNullableTests.cs
@@ -2,12 +2,49 @@
// 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.Reflection;
using Xunit;
namespace System.Linq.Expressions.Tests
{
- public static class UnaryDecrementNullableTests
+ public class UnaryDecrementNullableTests : IncrementDecrementTests
{
+ public struct DecrementableWhenNullable
+ {
+ public DecrementableWhenNullable(int value)
+ {
+ Value = value;
+ }
+
+ public int Value { get; }
+
+ public static DecrementableWhenNullable? operator --(DecrementableWhenNullable? operand)
+ {
+ if (operand.HasValue)
+ {
+ int dec = operand.GetValueOrDefault().Value - 1;
+ if (dec == 0)
+ {
+ return null;
+ }
+
+ return new DecrementableWhenNullable(dec);
+ }
+
+ return new DecrementableWhenNullable(-1);
+ }
+ }
+
+ private static IEnumerable<object[]> DecrementableWhenNullableValues()
+ {
+ yield return new object[] { new DecrementableWhenNullable(0), new DecrementableWhenNullable(-1) };
+ yield return new object[] { new DecrementableWhenNullable(1), null };
+ yield return new object[] { new DecrementableWhenNullable(int.MaxValue), new DecrementableWhenNullable(int.MaxValue - 1) };
+ yield return new object[] { new DecrementableWhenNullable(int.MinValue), new DecrementableWhenNullable(int.MaxValue) };
+ yield return new object[] { null, new DecrementableWhenNullable(-1) };
+ }
+
#region Test methods
[Theory, ClassData(typeof(CompilationTypes))]
@@ -90,6 +127,48 @@ namespace System.Linq.Expressions.Tests
}
}
+ [Theory, MemberData(nameof(NonArithmeticObjects), false)]
+ public static void DecrementNonArithmetic(object value)
+ {
+ Expression ex = Expression.Constant(value, typeof(Nullable<>).MakeGenericType(value.GetType()));
+ Assert.Throws<InvalidOperationException>(() => Expression.Decrement(ex));
+ }
+
+ [Theory, PerCompilationType(nameof(DecrementableValues), true)]
+ public static void CustomOpDecrement(Decrementable? operand, Decrementable? expected, bool useInterpreter)
+ {
+ Func<Decrementable?> func = Expression.Lambda<Func<Decrementable?>>(
+ Expression.Decrement(Expression.Constant(operand, typeof(Decrementable?)))).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
+ [Theory, PerCompilationType(nameof(DecrementableWhenNullableValues))]
+ public static void NonLiftedNullableOpDecrement(
+ DecrementableWhenNullable? operand, DecrementableWhenNullable? expected, bool useInterpreter)
+ {
+ Func<DecrementableWhenNullable?> func = Expression.Lambda<Func<DecrementableWhenNullable?>>(
+ Expression.Decrement(Expression.Constant(operand, typeof(DecrementableWhenNullable?)))).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
+ [Theory, PerCompilationType(nameof(DoublyDecrementedDecrementableValues), true)]
+ public static void UserDefinedOpDecrement(Decrementable? operand, Decrementable? expected, bool useInterpreter)
+ {
+ MethodInfo method = typeof(IncrementDecrementTests).GetMethod(nameof(DoublyDecrement));
+ Func<Decrementable?> func = Expression.Lambda<Func<Decrementable?>>(
+ Expression.Decrement(Expression.Constant(operand, typeof(Decrementable?)), method)).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
+ [Theory, PerCompilationType(nameof(DoublyDecrementedInt32s), true)]
+ public static void UserDefinedOpDecrementArithmeticType(int? operand, int? expected, bool useInterpreter)
+ {
+ MethodInfo method = typeof(IncrementDecrementTests).GetMethod(nameof(DoublyDecrementInt32));
+ Func<int?> func = Expression.Lambda<Func<int?>>(
+ Expression.Decrement(Expression.Constant(operand, typeof(int?)), method)).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
#endregion
#region Test verifiers
diff --git a/src/System.Linq.Expressions/tests/Unary/UnaryDecrementTests.cs b/src/System.Linq.Expressions/tests/Unary/UnaryDecrementTests.cs
index 63c9e1470b..be18a1b17e 100644
--- a/src/System.Linq.Expressions/tests/Unary/UnaryDecrementTests.cs
+++ b/src/System.Linq.Expressions/tests/Unary/UnaryDecrementTests.cs
@@ -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.Collections.Generic;
+using System.Reflection;
using Xunit;
namespace System.Linq.Expressions.Tests
{
- public static class UnaryDecrementTests
+ public class UnaryDecrementTests : IncrementDecrementTests
{
#region Test methods
@@ -97,6 +99,52 @@ namespace System.Linq.Expressions.Tests
Assert.Equal("Decrement(x)", e.ToString());
}
+ [Theory, MemberData(nameof(NonArithmeticObjects), true)]
+ public static void DecrementNonArithmetic(object value)
+ {
+ Expression ex = Expression.Constant(value);
+ Assert.Throws<InvalidOperationException>(() => Expression.Decrement(ex));
+ }
+
+ [Theory, PerCompilationType(nameof(DecrementableValues), false)]
+ public static void CustomOpDecrement(Decrementable operand, Decrementable expected, bool useInterpreter)
+ {
+ Func<Decrementable> func = Expression.Lambda<Func<Decrementable>>(
+ Expression.Decrement(Expression.Constant(operand))).Compile(useInterpreter);
+ Assert.Equal(expected.Value, func().Value);
+ }
+
+ [Theory, PerCompilationType(nameof(DoublyDecrementedDecrementableValues), false)]
+ public static void UserDefinedOpDecrement(Decrementable operand, Decrementable expected, bool useInterpreter)
+ {
+ MethodInfo method = typeof(IncrementDecrementTests).GetMethod(nameof(DoublyDecrement));
+ Func<Decrementable> func = Expression.Lambda<Func<Decrementable>>(
+ Expression.Decrement(Expression.Constant(operand), method)).Compile(useInterpreter);
+ Assert.Equal(expected.Value, func().Value);
+ }
+
+ [Theory, PerCompilationType(nameof(DoublyDecrementedInt32s), false)]
+ public static void UserDefinedOpDecrementArithmeticType(int operand, int expected, bool useInterpreter)
+ {
+ MethodInfo method = typeof(IncrementDecrementTests).GetMethod(nameof(DoublyDecrementInt32));
+ Func<int> func = Expression.Lambda<Func<int>>(
+ Expression.Decrement(Expression.Constant(operand), method)).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
+ [Fact]
+ public static void NullOperand()
+ {
+ Assert.Throws<ArgumentNullException>("expression", () => Expression.Decrement(null));
+ }
+
+ [Fact]
+ public static void UnreadableOperand()
+ {
+ Expression operand = Expression.Property(null, typeof(Unreadable<int>), nameof(Unreadable<int>.WriteOnly));
+ Assert.Throws<ArgumentException>("expression", () => Expression.Decrement(operand));
+ }
+
#endregion
#region Test verifiers
diff --git a/src/System.Linq.Expressions/tests/Unary/UnaryIncrementNullableTests.cs b/src/System.Linq.Expressions/tests/Unary/UnaryIncrementNullableTests.cs
index 2c4dae98f4..c22df0735c 100644
--- a/src/System.Linq.Expressions/tests/Unary/UnaryIncrementNullableTests.cs
+++ b/src/System.Linq.Expressions/tests/Unary/UnaryIncrementNullableTests.cs
@@ -2,12 +2,49 @@
// 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.Reflection;
using Xunit;
namespace System.Linq.Expressions.Tests
{
- public static class UnaryIncrementNullableTests
+ public class UnaryIncrementNullableTests : IncrementDecrementTests
{
+ public struct IncrementableWhenNullable
+ {
+ public IncrementableWhenNullable(int value)
+ {
+ Value = value;
+ }
+
+ public int Value { get; }
+
+ public static IncrementableWhenNullable? operator ++(IncrementableWhenNullable? operand)
+ {
+ if (operand.HasValue)
+ {
+ int dec = operand.GetValueOrDefault().Value + 1;
+ if (dec == 0)
+ {
+ return null;
+ }
+
+ return new IncrementableWhenNullable(dec);
+ }
+
+ return new IncrementableWhenNullable(1);
+ }
+ }
+
+ private static IEnumerable<object[]> IncrementableWhenNullableValues()
+ {
+ yield return new object[] { new IncrementableWhenNullable(0), new IncrementableWhenNullable(1) };
+ yield return new object[] { new IncrementableWhenNullable(-1), null };
+ yield return new object[] { new IncrementableWhenNullable(int.MinValue), new IncrementableWhenNullable(int.MinValue + 1) };
+ yield return new object[] { new IncrementableWhenNullable(int.MaxValue), new IncrementableWhenNullable(int.MinValue) };
+ yield return new object[] { null, new IncrementableWhenNullable(1) };
+ }
+
#region Test methods
[Theory, ClassData(typeof(CompilationTypes))]
@@ -92,6 +129,48 @@ namespace System.Linq.Expressions.Tests
#endregion
+ [Theory, MemberData(nameof(NonArithmeticObjects), false)]
+ public static void DecrementNonArithmetic(object value)
+ {
+ Expression ex = Expression.Constant(value, typeof(Nullable<>).MakeGenericType(value.GetType()));
+ Assert.Throws<InvalidOperationException>(() => Expression.Decrement(ex));
+ }
+
+ [Theory, PerCompilationType(nameof(IncrementableValues), true)]
+ public static void CustomOpIncrement(Incrementable? operand, Incrementable? expected, bool useInterpreter)
+ {
+ Func<Incrementable?> func = Expression.Lambda<Func<Incrementable?>>(
+ Expression.Increment(Expression.Constant(operand, typeof(Incrementable?)))).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
+ [Theory, PerCompilationType(nameof(IncrementableWhenNullableValues))]
+ public static void NonLiftedNullableOpIncrement(
+ IncrementableWhenNullable? operand, IncrementableWhenNullable? expected, bool useInterpreter)
+ {
+ Func<IncrementableWhenNullable?> func = Expression.Lambda<Func<IncrementableWhenNullable?>>(
+ Expression.Increment(Expression.Constant(operand, typeof(IncrementableWhenNullable?)))).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
+ [Theory, PerCompilationType(nameof(DoublyIncrementedIncrementableValues), true)]
+ public static void UserDefinedOpIncrement(Incrementable? operand, Incrementable? expected, bool useInterpreter)
+ {
+ MethodInfo method = typeof(IncrementDecrementTests).GetMethod(nameof(DoublyIncrement));
+ Func<Incrementable?> func = Expression.Lambda<Func<Incrementable?>>(
+ Expression.Increment(Expression.Constant(operand, typeof(Incrementable?)), method)).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
+ [Theory, PerCompilationType(nameof(DoublyIncrementedInt32s), true)]
+ public static void UserDefinedOpIncrementArithmeticType(int? operand, int? expected, bool useInterpreter)
+ {
+ MethodInfo method = typeof(IncrementDecrementTests).GetMethod(nameof(DoublyIncrementInt32));
+ Func<int?> func = Expression.Lambda<Func<int?>>(
+ Expression.Increment(Expression.Constant(operand, typeof(int?)), method)).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
#region Test verifiers
private static void VerifyIncrementNullableShort(short? value, bool useInterpreter)
diff --git a/src/System.Linq.Expressions/tests/Unary/UnaryIncrementTests.cs b/src/System.Linq.Expressions/tests/Unary/UnaryIncrementTests.cs
index 04fdb7289d..ea57f523fd 100644
--- a/src/System.Linq.Expressions/tests/Unary/UnaryIncrementTests.cs
+++ b/src/System.Linq.Expressions/tests/Unary/UnaryIncrementTests.cs
@@ -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.Collections.Generic;
+using System.Reflection;
using Xunit;
namespace System.Linq.Expressions.Tests
{
- public static class UnaryIncrementTests
+ public class UnaryIncrementTests : IncrementDecrementTests
{
#region Test methods
@@ -97,6 +99,52 @@ namespace System.Linq.Expressions.Tests
Assert.Equal("Increment(x)", e.ToString());
}
+ [Theory, MemberData(nameof(NonArithmeticObjects), true)]
+ public static void IncrementNonArithmetic(object value)
+ {
+ Expression ex = Expression.Constant(value);
+ Assert.Throws<InvalidOperationException>(() => Expression.Increment(ex));
+ }
+
+ [Theory, PerCompilationType(nameof(IncrementableValues), false)]
+ public static void CustomOpIncrement(Incrementable operand, Incrementable expected, bool useInterpreter)
+ {
+ Func<Incrementable> func = Expression.Lambda<Func<Incrementable>>(
+ Expression.Increment(Expression.Constant(operand))).Compile(useInterpreter);
+ Assert.Equal(expected.Value, func().Value);
+ }
+
+ [Theory, PerCompilationType(nameof(DoublyIncrementedIncrementableValues), false)]
+ public static void UserDefinedOpIncrement(Incrementable operand, Incrementable expected, bool useInterpreter)
+ {
+ MethodInfo method = typeof(IncrementDecrementTests).GetMethod(nameof(DoublyIncrement));
+ Func<Incrementable> func = Expression.Lambda<Func<Incrementable>>(
+ Expression.Increment(Expression.Constant(operand), method)).Compile(useInterpreter);
+ Assert.Equal(expected.Value, func().Value);
+ }
+
+ [Theory, PerCompilationType(nameof(DoublyIncrementedInt32s), false)]
+ public static void UserDefinedOpIncrementArithmeticType(int operand, int expected, bool useInterpreter)
+ {
+ MethodInfo method = typeof(IncrementDecrementTests).GetMethod(nameof(DoublyIncrementInt32));
+ Func<int> func = Expression.Lambda<Func<int>>(
+ Expression.Increment(Expression.Constant(operand), method)).Compile(useInterpreter);
+ Assert.Equal(expected, func());
+ }
+
+ [Fact]
+ public static void NullOperand()
+ {
+ Assert.Throws<ArgumentNullException>("expression", () => Expression.Decrement(null));
+ }
+
+ [Fact]
+ public static void UnreadableOperand()
+ {
+ Expression operand = Expression.Property(null, typeof(Unreadable<int>), nameof(Unreadable<int>.WriteOnly));
+ Assert.Throws<ArgumentException>("expression", () => Expression.Decrement(operand));
+ }
+
#endregion
#region Test verifiers
diff --git a/src/System.Linq.Expressions/tests/Unary/UnaryQuoteTests.cs b/src/System.Linq.Expressions/tests/Unary/UnaryQuoteTests.cs
index 2542c4a105..9b95b36613 100644
--- a/src/System.Linq.Expressions/tests/Unary/UnaryQuoteTests.cs
+++ b/src/System.Linq.Expressions/tests/Unary/UnaryQuoteTests.cs
@@ -464,6 +464,38 @@ namespace System.Linq.Expressions.Tests
Assert.Equal(4, vars[1]);
}
+ [Fact]
+ public void NullLambda()
+ {
+ Assert.Throws<ArgumentNullException>("expression", () => Quote(null));
+ }
+
+ [Fact]
+ public void QuoteNonLamdba()
+ {
+ Func<int> zero = () => 0;
+ Expression funcConst = Constant(zero);
+ Assert.Throws<ArgumentException>("expression", () => Quote(funcConst));
+ }
+
+ [Fact]
+ public void CannotReduce()
+ {
+ Expression<Func<int>> exp = () => 2;
+ Expression q = Expression.Quote(exp);
+ Assert.False(q.CanReduce);
+ Assert.Same(q, q.Reduce());
+ Assert.Throws<ArgumentException>(() => q.ReduceAndCheck());
+ }
+
+ [Fact]
+ public void TypeExplicitWithGeneralLambdaArgument()
+ {
+ LambdaExpression lambda = Lambda(Constant(2));
+ Expression q = Quote(lambda);
+ Assert.Equal(typeof(Expression<Func<int>>), q.Type);
+ }
+
private void AssertIsBox<T>(Expression expression, T value, bool isInterpreted)
{
if (isInterpreted)
diff --git a/src/System.Linq/pkg/System.Linq.pkgproj b/src/System.Linq/pkg/System.Linq.pkgproj
index 0557d1f148..eb6fcfbcc3 100644
--- a/src/System.Linq/pkg/System.Linq.pkgproj
+++ b/src/System.Linq/pkg/System.Linq.pkgproj
@@ -3,7 +3,7 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Linq.builds">
- <SupportedFramework>net463;netcoreapp1.0;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.0;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Linq.builds" />
<InboxOnTargetFramework Include="MonoAndroid10" />
@@ -19,6 +19,10 @@
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
+ <!-- the previous version of this package supported a different API version for
+ net463, but since netstandard2.0 supports the latest and net461 supports
+ netstandard2.0 we need to suppress the old net463 assembly. -->
+ <HarvestSuppressPaths Include="ref/net463;lib/net463" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/System.Linq/ref/System.Linq.cs b/src/System.Linq/ref/System.Linq.cs
index 8ec46d79fa..f56fa5ee2a 100644
--- a/src/System.Linq/ref/System.Linq.cs
+++ b/src/System.Linq/ref/System.Linq.cs
@@ -202,7 +202,7 @@ namespace System.Linq
System.Collections.Generic.IEnumerable<TElement> this[TKey key] { get; }
bool Contains(TKey key);
}
- public partial interface IOrderedEnumerable<TElement> : System.Collections.Generic.IEnumerable<TElement>, System.Collections.IEnumerable
+ public partial interface IOrderedEnumerable<out TElement> : System.Collections.Generic.IEnumerable<TElement>, System.Collections.IEnumerable
{
System.Linq.IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(System.Func<TElement, TKey> keySelector, System.Collections.Generic.IComparer<TKey> comparer, bool descending);
}
diff --git a/src/System.Linq/src/ApiCompatBaseline.net463.txt b/src/System.Linq/src/ApiCompatBaseline.net461.txt
index d0aed91013..d0aed91013 100644
--- a/src/System.Linq/src/ApiCompatBaseline.net463.txt
+++ b/src/System.Linq/src/ApiCompatBaseline.net461.txt
diff --git a/src/System.Linq/src/Configurations.props b/src/System.Linq/src/Configurations.props
index 9e1403e16a..a502feeae3 100644
--- a/src/System.Linq/src/Configurations.props
+++ b/src/System.Linq/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard1.6;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Linq/src/System.Linq.csproj b/src/System.Linq/src/System.Linq.csproj
index d18da5b8f2..e13cb48f77 100644
--- a/src/System.Linq/src/System.Linq.csproj
+++ b/src/System.Linq/src/System.Linq.csproj
@@ -6,9 +6,9 @@
<AssemblyName>System.Linq</AssemblyName>
<AssemblyVersion>4.2.0.0</AssemblyVersion>
<RootNamespace>System.Linq</RootNamespace>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net463'">true</IsPartialFacadeAssembly>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net461'">true</IsPartialFacadeAssembly>
<!-- The following line needs to be removed once we have a targeting pack for 4.6.3 -->
- <TargetingPackNugetPackageId Condition="'$(TargetGroup)' == 'net463'">Microsoft.TargetingPack.NETFramework.v4.6.1</TargetingPackNugetPackageId>
+ <TargetingPackNugetPackageId Condition="'$(TargetGroup)' == 'net461'">Microsoft.TargetingPack.NETFramework.v4.6.1</TargetingPackNugetPackageId>
<DefineConstants Condition="'$(TargetGroup)' == 'netstandard1.6'">$(DefineConstants);netcoreapp11</DefineConstants>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
@@ -80,7 +80,7 @@
<Compile Include="System\Linq\Where.cs" />
<Compile Include="System\Linq\Zip.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System.Core" />
</ItemGroup>
diff --git a/src/System.Linq/src/System/Linq/AppendPrepend.cs b/src/System.Linq/src/System/Linq/AppendPrepend.cs
index c5ae31b201..e1cf0cf6c5 100644
--- a/src/System.Linq/src/System/Linq/AppendPrepend.cs
+++ b/src/System.Linq/src/System/Linq/AppendPrepend.cs
@@ -41,6 +41,10 @@ namespace System.Linq
return new AppendPrepend1Iterator<TSource>(source, element, false);
}
+ /// <summary>
+ /// Represents the insertion of one or more items before or after an <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerable.</typeparam>
private abstract class AppendPrependIterator<TSource> : Iterator<TSource>, IIListProvider<TSource>
{
protected readonly IEnumerable<TSource> _source;
@@ -92,6 +96,10 @@ namespace System.Linq
public abstract int GetCount(bool onlyIfCheap);
}
+ /// <summary>
+ /// Represents the insertion of an item before or after an <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerable.</typeparam>
private class AppendPrepend1Iterator<TSource> : AppendPrependIterator<TSource>
{
private readonly TSource _item;
@@ -260,8 +268,17 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An immutable node in a singly-linked list of items.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the node's item.</typeparam>
private sealed class SingleLinkedNode<TSource>
{
+ /// <summary>
+ /// Constructs a node linked to the tail node.
+ /// </summary>
+ /// <param name="first">The first item, to be placed in the tail node.</param>
+ /// <param name="second">The second item, to be placed in this node.</param>
public SingleLinkedNode(TSource first, TSource second)
{
Linked = new SingleLinkedNode<TSource>(first);
@@ -269,12 +286,21 @@ namespace System.Linq
Count = 2;
}
+ /// <summary>
+ /// Constructs a tail node.
+ /// </summary>
+ /// <param name="item">The item to place in the tail node.</param>
public SingleLinkedNode(TSource item)
{
Item = item;
Count = 1;
}
+ /// <summary>
+ /// Constructs a node linked to the specified node.
+ /// </summary>
+ /// <param name="linked">The linked node.</param>
+ /// <param name="item">The item to place in this node.</param>
private SingleLinkedNode(SingleLinkedNode<TSource> linked, TSource item)
{
Debug.Assert(linked != null);
@@ -283,19 +309,38 @@ namespace System.Linq
Count = linked.Count + 1;
}
+ /// <summary>
+ /// The item held by this node.
+ /// </summary>
public TSource Item { get; }
+ /// <summary>
+ /// The next node in the singly-linked list.
+ /// </summary>
public SingleLinkedNode<TSource> Linked { get; }
+ /// <summary>
+ /// The number of items stored in this and subsequent nodes.
+ /// </summary>
public int Count { get; }
+ /// <summary>
+ /// Creates a new node that holds the specified item and is linked to this node.
+ /// </summary>
+ /// <param name="item">The item to place in the new node.</param>
public SingleLinkedNode<TSource> Add(TSource item) => new SingleLinkedNode<TSource>(this, item);
+ /// <summary>
+ /// Gets an <see cref="IEnumerator{TSource}"/> that enumerates the items of this node's singly-linked list in reverse.
+ /// </summary>
public IEnumerator<TSource> GetEnumerator()
{
return ((IEnumerable<TSource>)ToArray()).GetEnumerator();
}
+ /// <summary>
+ /// Returns an <see cref="T:TSource[]"/> that contains the items of this node's singly-linked list in reverse.
+ /// </summary>
public TSource[] ToArray()
{
TSource[] array = new TSource[Count];
@@ -311,6 +356,10 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// Represents the insertion of multiple items before or after an <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerable.</typeparam>
private class AppendPrependN<TSource> : AppendPrependIterator<TSource>
{
private readonly SingleLinkedNode<TSource> _prepended;
diff --git a/src/System.Linq/src/System/Linq/Buffer.cs b/src/System.Linq/src/System/Linq/Buffer.cs
index 839e1450fb..16d5cc1ee4 100644
--- a/src/System.Linq/src/System/Linq/Buffer.cs
+++ b/src/System.Linq/src/System/Linq/Buffer.cs
@@ -6,11 +6,26 @@ using System.Collections.Generic;
namespace System.Linq
{
+ /// <summary>
+ /// A buffer into which the contents of an <see cref="IEnumerable{TElement}"/> can be stored.
+ /// </summary>
+ /// <typeparam name="TElement">The type of the buffer's elements.</typeparam>
internal struct Buffer<TElement>
{
+ /// <summary>
+ /// The stored items.
+ /// </summary>
internal readonly TElement[] _items;
+
+ /// <summary>
+ /// The number of stored items.
+ /// </summary>
internal readonly int _count;
+ /// <summary>
+ /// Fully enumerates the provided enumerable and stores its items into an array.
+ /// </summary>
+ /// <param name="source">The enumerable to be store.</param>
internal Buffer(IEnumerable<TElement> source)
{
IIListProvider<TElement> iterator = source as IIListProvider<TElement>;
diff --git a/src/System.Linq/src/System/Linq/Concat.cs b/src/System.Linq/src/System/Linq/Concat.cs
index aae66235ad..feda438775 100644
--- a/src/System.Linq/src/System/Linq/Concat.cs
+++ b/src/System.Linq/src/System/Linq/Concat.cs
@@ -44,6 +44,10 @@ namespace System.Linq
return new Concat2EnumerableIterator<TSource>(first, second);
}
+ /// <summary>
+ /// Represents the concatenation of two <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerables.</typeparam>
private sealed class Concat2EnumerableIterator<TSource> : ConcatIterator<TSource>
{
private readonly IEnumerable<TSource> _first;
@@ -83,6 +87,11 @@ namespace System.Linq
// only have to traverse all of the previous sources once per chained enumerable. An
// alternative would be to use an array to store all of the enumerables, but this has
// a much better memory profile and without much additional run-time cost.
+
+ /// <summary>
+ /// Represents the concatenation of three or more <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerables.</typeparam>
private sealed class ConcatNEnumerableIterator<TSource> : ConcatIterator<TSource>
{
private readonly ConcatIterator<TSource> _previousConcat;
@@ -162,6 +171,10 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// Represents the concatenation of two <see cref="ICollection{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source collections.</typeparam>
private sealed class Concat2CollectionIterator<TSource> : ConcatIterator<TSource>
{
private readonly ICollection<TSource> _first;
@@ -232,6 +245,10 @@ namespace System.Linq
public override int GetCount(bool onlyIfCheap) => Count; // Getting the count is always cheap.
}
+ /// <summary>
+ /// Represents the concatenation of three or more <see cref="ICollection{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source collections.</typeparam>
private sealed class ConcatNCollectionIterator<TSource> : ConcatIterator<TSource>
{
private readonly ConcatIterator<TSource> _previous;
@@ -387,6 +404,10 @@ namespace System.Linq
public override int GetCount(bool onlyIfCheap) => Count; // Getting the count is always cheap relative to manually iterating.
}
+ /// <summary>
+ /// Represents the concatenation of two or more <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerables.</typeparam>
private abstract class ConcatIterator<TSource> : Iterator<TSource>, IIListProvider<TSource>
{
private IEnumerator<TSource> _enumerator;
diff --git a/src/System.Linq/src/System/Linq/Distinct.cs b/src/System.Linq/src/System/Linq/Distinct.cs
index 054b96b649..65d0a02d6c 100644
--- a/src/System.Linq/src/System/Linq/Distinct.cs
+++ b/src/System.Linq/src/System/Linq/Distinct.cs
@@ -24,6 +24,10 @@ namespace System.Linq
return new DistinctIterator<TSource>(source, comparer);
}
+ /// <summary>
+ /// An iterator that yields the distinct values in an <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerable.</typeparam>
private sealed class DistinctIterator<TSource> : Iterator<TSource>, IIListProvider<TSource>
{
private readonly IEnumerable<TSource> _source;
diff --git a/src/System.Linq/src/System/Linq/First.cs b/src/System.Linq/src/System/Linq/First.cs
index 74f687c0a3..7abe939014 100644
--- a/src/System.Linq/src/System/Linq/First.cs
+++ b/src/System.Linq/src/System/Linq/First.cs
@@ -10,76 +10,43 @@ namespace System.Linq
{
public static TSource First<TSource>(this IEnumerable<TSource> source)
{
- if (source == null)
+ bool found;
+ TSource first = source.TryGetFirst(out found);
+
+ if (!found)
{
- throw Error.ArgumentNull(nameof(source));
+ throw Error.NoElements();
}
- IPartition<TSource> partition = source as IPartition<TSource>;
- if (partition != null)
- {
- bool found;
- TSource first = partition.TryGetFirst(out found);
- if (found)
- {
- return first;
- }
- }
- else
- {
- IList<TSource> list = source as IList<TSource>;
- if (list != null)
- {
- if (list.Count > 0)
- {
- return list[0];
- }
- }
- else
- {
- using (IEnumerator<TSource> e = source.GetEnumerator())
- {
- if (e.MoveNext())
- {
- return e.Current;
- }
- }
- }
- }
-
- throw Error.NoElements();
+ return first;
}
public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
- if (source == null)
- {
- throw Error.ArgumentNull(nameof(source));
- }
+ bool found;
+ TSource first = source.TryGetFirst(predicate, out found);
- if (predicate == null)
+ if (!found)
{
- throw Error.ArgumentNull(nameof(predicate));
+ throw Error.NoMatch();
}
- OrderedEnumerable<TSource> ordered = source as OrderedEnumerable<TSource>;
- if (ordered != null)
- {
- return ordered.First(predicate);
- }
+ return first;
+ }
- foreach (TSource element in source)
- {
- if (predicate(element))
- {
- return element;
- }
- }
+ public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source)
+ {
+ bool found;
+ return source.TryGetFirst(out found);
+ }
- throw Error.NoMatch();
+ public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
+ {
+ bool found;
+ return source.TryGetFirst(predicate, out found);
}
- public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source)
+ internal static TSource TryGetFirst<TSource>(this IEnumerable<TSource> source, out bool found)
{
if (source == null)
{
@@ -89,15 +56,15 @@ namespace System.Linq
IPartition<TSource> partition = source as IPartition<TSource>;
if (partition != null)
{
- bool found;
return partition.TryGetFirst(out found);
}
-
+
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
if (list.Count > 0)
{
+ found = true;
return list[0];
}
}
@@ -107,15 +74,17 @@ namespace System.Linq
{
if (e.MoveNext())
{
+ found = true;
return e.Current;
}
}
}
+ found = false;
return default(TSource);
}
- public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
+ internal static TSource TryGetFirst<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate, out bool found)
{
if (source == null)
{
@@ -130,17 +99,19 @@ namespace System.Linq
OrderedEnumerable<TSource> ordered = source as OrderedEnumerable<TSource>;
if (ordered != null)
{
- return ordered.FirstOrDefault(predicate);
+ return ordered.TryGetFirst(predicate, out found);
}
foreach (TSource element in source)
{
if (predicate(element))
{
+ found = true;
return element;
}
}
+ found = false;
return default(TSource);
}
}
diff --git a/src/System.Linq/src/System/Linq/Iterator.cs b/src/System.Linq/src/System/Linq/Iterator.cs
index 7425046e26..27a15c2e42 100644
--- a/src/System.Linq/src/System/Linq/Iterator.cs
+++ b/src/System.Linq/src/System/Linq/Iterator.cs
@@ -9,30 +9,74 @@ namespace System.Linq
{
public static partial class Enumerable
{
+ /// <summary>
+ /// A base class for enumerables that are loaded on-demand.
+ /// </summary>
+ /// <typeparam name="TSource">The type of each item to yield.</typeparam>
+ /// <remarks>
+ /// <list type="bullet">
+ /// <item><description>
+ /// The value of an iterator is immutable; the operation it represents cannot be changed.
+ /// </description></item>
+ /// <item><description>
+ /// However, an iterator also serves as its own enumerator, so the state of an iterator
+ /// may change as it is being enumerated.
+ /// </description></item>
+ /// <item><description>
+ /// Hence, state that is relevant to an iterator's value should be kept in readonly fields.
+ /// State that is relevant to an iterator's enumeration (such as the currently yielded item)
+ /// should be kept in non-readonly fields.
+ /// </description></item>
+ /// </list>
+ /// </remarks>
internal abstract class Iterator<TSource> : IEnumerable<TSource>, IEnumerator<TSource>
{
private readonly int _threadId;
internal int _state;
internal TSource _current;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Iterator{TSource}"/> class.
+ /// </summary>
protected Iterator()
{
_threadId = Environment.CurrentManagedThreadId;
}
- public TSource Current
- {
- get { return _current; }
- }
+ /// <summary>
+ /// The item currently yielded by this iterator.
+ /// </summary>
+ public TSource Current => _current;
+ /// <summary>
+ /// Makes a shallow copy of this iterator.
+ /// </summary>
+ /// <remarks>
+ /// This method is called if <see cref="GetEnumerator"/> is called more than once.
+ /// </remarks>
public abstract Iterator<TSource> Clone();
+ /// <summary>
+ /// Puts this iterator in a state whereby no further enumeration will take place.
+ /// </summary>
+ /// <remarks>
+ /// Derived classes should override this method if necessary to clean up any
+ /// mutable state they hold onto (for example, calling Dispose on other enumerators).
+ /// </remarks>
public virtual void Dispose()
{
_current = default(TSource);
_state = -1;
}
+ /// <summary>
+ /// Gets the enumerator used to yield values from this iterator.
+ /// </summary>
+ /// <remarks>
+ /// If <see cref="GetEnumerator"/> is called for the first time on the same thread
+ /// that created this iterator, the result will be this iterator. Otherwise, the result
+ /// will be a shallow copy of this iterator.
+ /// </remarks>
public IEnumerator<TSource> GetEnumerator()
{
Iterator<TSource> enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone();
@@ -40,27 +84,34 @@ namespace System.Linq
return enumerator;
}
+ /// <summary>
+ /// Retrieves the next item in this iterator and yields it via <see cref="Current"/>.
+ /// </summary>
+ /// <returns><c>true</c> if there was another value to be yielded; otherwise, <c>false</c>.</returns>
public abstract bool MoveNext();
+ /// <summary>
+ /// Returns an enumerable that maps each item in this iterator based on a selector.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
+ /// <param name="selector">The selector used to map each item.</param>
public virtual IEnumerable<TResult> Select<TResult>(Func<TSource, TResult> selector)
{
return new SelectEnumerableIterator<TSource, TResult>(this, selector);
}
+ /// <summary>
+ /// Returns an enumerable that filters each item in this iterator based on a predicate.
+ /// </summary>
+ /// <param name="predicate">The predicate used to filter each item.</param>
public virtual IEnumerable<TSource> Where(Func<TSource, bool> predicate)
{
return new WhereEnumerableIterator<TSource>(this, predicate);
}
- object IEnumerator.Current
- {
- get { return Current; }
- }
+ object IEnumerator.Current => Current;
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
void IEnumerator.Reset()
{
diff --git a/src/System.Linq/src/System/Linq/Last.cs b/src/System.Linq/src/System/Linq/Last.cs
index 04625d1e52..d57048efcd 100644
--- a/src/System.Linq/src/System/Linq/Last.cs
+++ b/src/System.Linq/src/System/Linq/Last.cs
@@ -10,112 +10,43 @@ namespace System.Linq
{
public static TSource Last<TSource>(this IEnumerable<TSource> source)
{
- if (source == null)
- {
- throw Error.ArgumentNull(nameof(source));
- }
-
- IPartition<TSource> partition = source as IPartition<TSource>;
- if (partition != null)
+ bool found;
+ TSource last = source.TryGetLast(out found);
+
+ if (!found)
{
- bool found;
- TSource last = partition.TryGetLast(out found);
- if (found)
- {
- return last;
- }
- }
- else
- {
- IList<TSource> list = source as IList<TSource>;
- if (list != null)
- {
- int count = list.Count;
- if (count > 0)
- {
- return list[count - 1];
- }
- }
- else
- {
- using (IEnumerator<TSource> e = source.GetEnumerator())
- {
- if (e.MoveNext())
- {
- TSource result;
- do
- {
- result = e.Current;
- }
- while (e.MoveNext());
-
- return result;
- }
- }
- }
+ throw Error.NoElements();
}
- throw Error.NoElements();
+ return last;
}
public static TSource Last<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
- if (source == null)
- {
- throw Error.ArgumentNull(nameof(source));
- }
+ bool found;
+ TSource last = source.TryGetLast(predicate, out found);
- if (predicate == null)
+ if (!found)
{
- throw Error.ArgumentNull(nameof(predicate));
+ throw Error.NoMatch();
}
- OrderedEnumerable<TSource> ordered = source as OrderedEnumerable<TSource>;
- if (ordered != null)
- {
- return ordered.Last(predicate);
- }
-
- IList<TSource> list = source as IList<TSource>;
- if (list != null)
- {
- for (int i = list.Count - 1; i >= 0; --i)
- {
- TSource result = list[i];
- if (predicate(result))
- {
- return result;
- }
- }
- }
- else
- {
- using (IEnumerator<TSource> e = source.GetEnumerator())
- {
- while (e.MoveNext())
- {
- TSource result = e.Current;
- if (predicate(result))
- {
- while (e.MoveNext())
- {
- TSource element = e.Current;
- if (predicate(element))
- {
- result = element;
- }
- }
+ return last;
+ }
- return result;
- }
- }
- }
- }
+ public static TSource LastOrDefault<TSource>(this IEnumerable<TSource> source)
+ {
+ bool found;
+ return source.TryGetLast(out found);
+ }
- throw Error.NoMatch();
+ public static TSource LastOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
+ {
+ bool found;
+ return source.TryGetLast(predicate, out found);
}
- public static TSource LastOrDefault<TSource>(this IEnumerable<TSource> source)
+ internal static TSource TryGetLast<TSource>(this IEnumerable<TSource> source, out bool found)
{
if (source == null)
{
@@ -125,16 +56,16 @@ namespace System.Linq
IPartition<TSource> partition = source as IPartition<TSource>;
if (partition != null)
{
- bool found;
return partition.TryGetLast(out found);
}
-
+
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
int count = list.Count;
if (count > 0)
{
+ found = true;
return list[count - 1];
}
}
@@ -151,15 +82,17 @@ namespace System.Linq
}
while (e.MoveNext());
+ found = true;
return result;
}
}
}
-
+
+ found = false;
return default(TSource);
}
- public static TSource LastOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
+ internal static TSource TryGetLast<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate, out bool found)
{
if (source == null)
{
@@ -174,7 +107,7 @@ namespace System.Linq
OrderedEnumerable<TSource> ordered = source as OrderedEnumerable<TSource>;
if (ordered != null)
{
- return ordered.LastOrDefault(predicate);
+ return ordered.TryGetLast(predicate, out found);
}
IList<TSource> list = source as IList<TSource>;
@@ -182,28 +115,41 @@ namespace System.Linq
{
for (int i = list.Count - 1; i >= 0; --i)
{
- TSource element = list[i];
- if (predicate(element))
+ TSource result = list[i];
+ if (predicate(result))
{
- return element;
+ found = true;
+ return result;
}
}
-
- return default(TSource);
}
else
{
- TSource result = default(TSource);
- foreach (TSource element in source)
+ using (IEnumerator<TSource> e = source.GetEnumerator())
{
- if (predicate(element))
+ while (e.MoveNext())
{
- result = element;
+ TSource result = e.Current;
+ if (predicate(result))
+ {
+ while (e.MoveNext())
+ {
+ TSource element = e.Current;
+ if (predicate(element))
+ {
+ result = element;
+ }
+ }
+
+ found = true;
+ return result;
+ }
}
}
-
- return result;
}
+
+ found = false;
+ return default(TSource);
}
}
}
diff --git a/src/System.Linq/src/System/Linq/OrderBy.cs b/src/System.Linq/src/System/Linq/OrderBy.cs
index cd3c789f4f..1ba58cab46 100644
--- a/src/System.Linq/src/System/Linq/OrderBy.cs
+++ b/src/System.Linq/src/System/Linq/OrderBy.cs
@@ -69,7 +69,7 @@ namespace System.Linq
}
}
- public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>
+ public interface IOrderedEnumerable<out TElement> : IEnumerable<TElement>
{
IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);
}
diff --git a/src/System.Linq/src/System/Linq/OrderedEnumerable.cs b/src/System.Linq/src/System/Linq/OrderedEnumerable.cs
index 44ae5e5a72..6c7a9207fd 100644
--- a/src/System.Linq/src/System/Linq/OrderedEnumerable.cs
+++ b/src/System.Linq/src/System/Linq/OrderedEnumerable.cs
@@ -270,38 +270,7 @@ namespace System.Linq
}
}
- public TElement First(Func<TElement, bool> predicate)
- {
- CachingComparer<TElement> comparer = GetComparer();
- using (IEnumerator<TElement> e = _source.GetEnumerator())
- {
- TElement value;
- do
- {
- if (!e.MoveNext())
- {
- throw Error.NoMatch();
- }
-
- value = e.Current;
- }
- while (!predicate(value));
-
- comparer.SetElement(value);
- while (e.MoveNext())
- {
- TElement x = e.Current;
- if (predicate(x) && comparer.Compare(x, true) < 0)
- {
- value = x;
- }
- }
-
- return value;
- }
- }
-
- public TElement FirstOrDefault(Func<TElement, bool> predicate)
+ public TElement TryGetFirst(Func<TElement, bool> predicate, out bool found)
{
CachingComparer<TElement> comparer = GetComparer();
using (IEnumerator<TElement> e = _source.GetEnumerator())
@@ -311,6 +280,7 @@ namespace System.Linq
{
if (!e.MoveNext())
{
+ found = false;
return default(TElement);
}
@@ -328,6 +298,7 @@ namespace System.Linq
}
}
+ found = true;
return value;
}
}
@@ -392,38 +363,7 @@ namespace System.Linq
return value;
}
- public TElement Last(Func<TElement, bool> predicate)
- {
- CachingComparer<TElement> comparer = GetComparer();
- using (IEnumerator<TElement> e = _source.GetEnumerator())
- {
- TElement value;
- do
- {
- if (!e.MoveNext())
- {
- throw Error.NoMatch();
- }
-
- value = e.Current;
- }
- while (!predicate(value));
-
- comparer.SetElement(value);
- while (e.MoveNext())
- {
- TElement x = e.Current;
- if (predicate(x) && comparer.Compare(x, false) >= 0)
- {
- value = x;
- }
- }
-
- return value;
- }
- }
-
- public TElement LastOrDefault(Func<TElement, bool> predicate)
+ public TElement TryGetLast(Func<TElement, bool> predicate, out bool found)
{
CachingComparer<TElement> comparer = GetComparer();
using (IEnumerator<TElement> e = _source.GetEnumerator())
@@ -433,6 +373,7 @@ namespace System.Linq
{
if (!e.MoveNext())
{
+ found = false;
return default(TElement);
}
@@ -444,12 +385,13 @@ namespace System.Linq
while (e.MoveNext())
{
TElement x = e.Current;
- if (predicate(x) && comparer.Compare(x, false) > 0)
+ if (predicate(x) && comparer.Compare(x, false) >= 0)
{
value = x;
}
}
+ found = true;
return value;
}
}
diff --git a/src/System.Linq/src/System/Linq/Partition.cs b/src/System.Linq/src/System/Linq/Partition.cs
index 1bbf847401..2013018a3e 100644
--- a/src/System.Linq/src/System/Linq/Partition.cs
+++ b/src/System.Linq/src/System/Linq/Partition.cs
@@ -77,40 +77,36 @@ namespace System.Linq
TElement TryGetLast(out bool found);
}
+ /// <summary>
+ /// Represents an enumerable with zero elements.
+ /// </summary>
+ /// <typeparam name="TElement">The element type.</typeparam>
+ /// <remarks>
+ /// Returning an instance of this type is useful to quickly handle scenarios where it is known
+ /// that an operation will result in zero elements.
+ /// </remarks>
internal sealed class EmptyPartition<TElement> : IPartition<TElement>, IEnumerator<TElement>
{
+ /// <summary>
+ /// A cached, immutable instance of an empty enumerable.
+ /// </summary>
public static readonly IPartition<TElement> Instance = new EmptyPartition<TElement>();
private EmptyPartition()
{
}
- public IEnumerator<TElement> GetEnumerator()
- {
- return this;
- }
+ public IEnumerator<TElement> GetEnumerator() => this;
- IEnumerator IEnumerable.GetEnumerator()
- {
- return this;
- }
+ IEnumerator IEnumerable.GetEnumerator() => this;
- public bool MoveNext()
- {
- return false;
- }
+ public bool MoveNext() => false;
[ExcludeFromCodeCoverage] // Shouldn't be called, and as undefined can return or throw anything anyway.
- public TElement Current
- {
- get { return default(TElement); }
- }
+ public TElement Current => default(TElement);
[ExcludeFromCodeCoverage] // Shouldn't be called, and as undefined can return or throw anything anyway.
- object IEnumerator.Current
- {
- get { return default(TElement); }
- }
+ object IEnumerator.Current => default(TElement);
void IEnumerator.Reset()
{
@@ -122,15 +118,9 @@ namespace System.Linq
// Do nothing.
}
- public IPartition<TElement> Skip(int count)
- {
- return this;
- }
+ public IPartition<TElement> Skip(int count) => this;
- public IPartition<TElement> Take(int count)
- {
- return this;
- }
+ public IPartition<TElement> Take(int count) => this;
public TElement TryGetElementAt(int index, out bool found)
{
@@ -150,20 +140,11 @@ namespace System.Linq
return default(TElement);
}
- public TElement[] ToArray()
- {
- return Array.Empty<TElement>();
- }
+ public TElement[] ToArray() => Array.Empty<TElement>();
- public List<TElement> ToList()
- {
- return new List<TElement>();
- }
+ public List<TElement> ToList() => new List<TElement>();
- public int GetCount(bool onlyIfCheap)
- {
- return 0;
- }
+ public int GetCount(bool onlyIfCheap) => 0;
}
internal sealed class OrderedPartition<TElement> : IPartition<TElement>
@@ -245,6 +226,10 @@ namespace System.Linq
public static partial class Enumerable
{
+ /// <summary>
+ /// An iterator that yields the items of part of an <see cref="IList{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source list.</typeparam>
private sealed class ListPartition<TSource> : Iterator<TSource>, IPartition<TSource>
{
private readonly IList<TSource> _source;
@@ -389,5 +374,319 @@ namespace System.Linq
return Count;
}
}
+
+ /// <summary>
+ /// An iterator that yields the items of part of an <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerable.</typeparam>
+ private sealed class EnumerablePartition<TSource> : Iterator<TSource>, IPartition<TSource>
+ {
+ private readonly IEnumerable<TSource> _source;
+ private readonly int _minIndexInclusive;
+ private readonly int _maxIndexInclusive; // -1 if we want everything past _minIndexInclusive.
+ // If this is -1, it's impossible to set a limit on the count.
+ private IEnumerator<TSource> _enumerator;
+
+ internal EnumerablePartition(IEnumerable<TSource> source, int minIndexInclusive, int maxIndexInclusive)
+ {
+ Debug.Assert(source != null);
+ Debug.Assert(!(source is IList<TSource>), $"The caller needs to check for {nameof(IList<TSource>)}.");
+ Debug.Assert(minIndexInclusive >= 0);
+ Debug.Assert(maxIndexInclusive >= -1);
+ // Note that although maxIndexInclusive can't grow, it can still be int.MaxValue.
+ // We support partitioning enumerables with > 2B elements. For example, e.Skip(1).Take(int.MaxValue) should work.
+ // But if it is int.MaxValue, then minIndexInclusive must != 0. Otherwise, our count may overflow.
+ Debug.Assert(maxIndexInclusive == -1 || (maxIndexInclusive - minIndexInclusive < int.MaxValue), $"{nameof(Limit)} will overflow!");
+ Debug.Assert(maxIndexInclusive == -1 || minIndexInclusive <= maxIndexInclusive);
+
+ _source = source;
+ _minIndexInclusive = minIndexInclusive;
+ _maxIndexInclusive = maxIndexInclusive;
+ }
+
+ // If this is true (e.g. at least one Take call was made), then we have an upper bound
+ // on how many elements we can have.
+ private bool HasLimit => _maxIndexInclusive != -1;
+
+ private int Limit => (_maxIndexInclusive + 1) - _minIndexInclusive; // This is that upper bound.
+
+ public override Iterator<TSource> Clone()
+ {
+ return new EnumerablePartition<TSource>(_source, _minIndexInclusive, _maxIndexInclusive);
+ }
+
+ public int GetCount(bool onlyIfCheap)
+ {
+ if (onlyIfCheap)
+ {
+ return -1;
+ }
+
+ if (!HasLimit)
+ {
+ // If HasLimit is false, we contain everything past _minIndexInclusive.
+ // Therefore, we have to iterate the whole enumerable.
+ return Math.Max(_source.Count() - _minIndexInclusive, 0);
+ }
+
+ using (IEnumerator<TSource> en = _source.GetEnumerator())
+ {
+ // We only want to iterate up to _maxIndexInclusive + 1.
+ // Past that, we know the enumerable will be able to fit this partition,
+ // so the count will just be _maxIndexInclusive + 1 - _minIndexInclusive.
+
+ // Note that it is possible for _maxIndexInclusive to be int.MaxValue here,
+ // so + 1 may result in signed integer overflow. We need to handle this.
+ // At the same time, however, we are guaranteed that our max count can fit
+ // in an int because if that is true, then _minIndexInclusive must > 0.
+
+ uint count = SkipAndCount((uint)_maxIndexInclusive + 1, en);
+ Debug.Assert(count != (uint)int.MaxValue + 1 || _minIndexInclusive > 0, "Our return value will be incorrect.");
+ return Math.Max((int)count - _minIndexInclusive, 0);
+ }
+
+ }
+
+ public override bool MoveNext()
+ {
+ // Cases where GetEnumerator has not been called or Dispose has already
+ // been called need to be handled explicitly, due to the default: clause.
+ int taken = _state - 3;
+ if (taken < -2)
+ {
+ Dispose();
+ return false;
+ }
+
+ switch (_state)
+ {
+ case 1:
+ _enumerator = _source.GetEnumerator();
+ _state = 2;
+ goto case 2;
+ case 2:
+ if (!SkipBeforeFirst(_enumerator))
+ {
+ // Reached the end before we finished skipping.
+ break;
+ }
+
+ _state = 3;
+ goto default;
+ default:
+ if ((!HasLimit || taken < Limit) && _enumerator.MoveNext())
+ {
+ if (HasLimit)
+ {
+ // If we are taking an unknown number of elements, it's important not to increment _state.
+ // _state - 3 may eventually end up overflowing & we'll hit the Dispose branch even though
+ // we haven't finished enumerating.
+ _state++;
+ }
+ _current = _enumerator.Current;
+ return true;
+ }
+
+ break;
+ }
+
+ Dispose();
+ return false;
+ }
+
+ public override IEnumerable<TResult> Select<TResult>(Func<TSource, TResult> selector)
+ {
+ return new SelectIPartitionIterator<TSource, TResult>(this, selector);
+ }
+
+ public IPartition<TSource> Skip(int count)
+ {
+ int minIndex = _minIndexInclusive + count;
+ if (!HasLimit)
+ {
+ if (minIndex < 0)
+ {
+ // If we don't know our max count and minIndex can no longer fit in a positive int,
+ // then we will need to wrap ourselves in another iterator.
+ // This can happen, for example, during e.Skip(int.MaxValue).Skip(int.MaxValue).
+ return new EnumerablePartition<TSource>(this, count, -1);
+ }
+ }
+ else if ((uint)minIndex > (uint)_maxIndexInclusive)
+ {
+ // If minIndex overflows and we have an upper bound, we will go down this branch.
+ // We know our upper bound must be smaller than minIndex, since our upper bound fits in an int.
+ // This branch should not be taken if we don't have a bound.
+ return EmptyPartition<TSource>.Instance;
+ }
+
+ Debug.Assert(minIndex >= 0, $"We should have taken care of all cases when {nameof(minIndex)} overflows.");
+ return new EnumerablePartition<TSource>(_source, minIndex, _maxIndexInclusive);
+ }
+
+ public IPartition<TSource> Take(int count)
+ {
+ int maxIndex = _minIndexInclusive + count - 1;
+ if (!HasLimit)
+ {
+ if (maxIndex < 0)
+ {
+ // If we don't know our max count and maxIndex can no longer fit in a positive int,
+ // then we will need to wrap ourselves in another iterator.
+ // Note that although maxIndex may be too large, the difference between it and
+ // _minIndexInclusive (which is count - 1) must fit in an int.
+ // Example: e.Skip(50).Take(int.MaxValue).
+
+ return new EnumerablePartition<TSource>(this, 0, count - 1);
+ }
+ }
+ else if ((uint)maxIndex >= (uint)_maxIndexInclusive)
+ {
+ // If we don't know our max count, we can't go down this branch.
+ // It's always possible for us to contain more than count items, as the rest
+ // of the enumerable past _minIndexInclusive can be arbitrarily long.
+ return this;
+ }
+
+ Debug.Assert(maxIndex >= 0, $"We should have taken care of all cases when {nameof(maxIndex)} overflows.");
+ return new EnumerablePartition<TSource>(_source, _minIndexInclusive, maxIndex);
+ }
+
+ public TSource TryGetElementAt(int index, out bool found)
+ {
+ // If the index is negative or >= our max count, return early.
+ if (index >= 0 && (!HasLimit || index < Limit))
+ {
+ using (IEnumerator<TSource> en = _source.GetEnumerator())
+ {
+ Debug.Assert(_minIndexInclusive + index >= 0, $"Adding {nameof(index)} caused {nameof(_minIndexInclusive)} to overflow.");
+
+ if (SkipBefore(_minIndexInclusive + index, en) && en.MoveNext())
+ {
+ found = true;
+ return en.Current;
+ }
+ }
+ }
+
+ found = false;
+ return default(TSource);
+ }
+
+ public TSource TryGetFirst(out bool found)
+ {
+ using (IEnumerator<TSource> en = _source.GetEnumerator())
+ {
+ if (SkipBeforeFirst(en) && en.MoveNext())
+ {
+ found = true;
+ return en.Current;
+ }
+ }
+
+ found = false;
+ return default(TSource);
+ }
+
+ public TSource TryGetLast(out bool found)
+ {
+ using (IEnumerator<TSource> en = _source.GetEnumerator())
+ {
+ if (SkipBeforeFirst(en) && en.MoveNext())
+ {
+ int remaining = Limit - 1; // Max number of items left, not counting the current element.
+ int comparand = HasLimit ? 0 : int.MinValue; // If we don't have an upper bound, have the comparison always return true.
+ TSource result;
+
+ do
+ {
+ remaining--;
+ result = en.Current;
+ }
+ while (remaining >= comparand && en.MoveNext());
+
+ found = true;
+ return result;
+ }
+ }
+
+ found = false;
+ return default(TSource);
+ }
+
+ public TSource[] ToArray()
+ {
+ using (IEnumerator<TSource> en = _source.GetEnumerator())
+ {
+ if (SkipBeforeFirst(en) && en.MoveNext())
+ {
+ int remaining = Limit - 1; // Max number of items left, not counting the current element.
+ int comparand = HasLimit ? 0 : int.MinValue; // If we don't have an upper bound, have the comparison always return true.
+
+ int maxCapacity = HasLimit ? Limit : int.MaxValue;
+ var builder = new LargeArrayBuilder<TSource>(maxCapacity);
+
+ do
+ {
+ remaining--;
+ builder.Add(en.Current);
+ }
+ while (remaining >= comparand && en.MoveNext());
+
+ return builder.ToArray();
+ }
+ }
+
+ return Array.Empty<TSource>();
+ }
+
+ public List<TSource> ToList()
+ {
+ var list = new List<TSource>();
+
+ using (IEnumerator<TSource> en = _source.GetEnumerator())
+ {
+ if (SkipBeforeFirst(en) && en.MoveNext())
+ {
+ int remaining = Limit - 1; // Max number of items left, not counting the current element.
+ int comparand = HasLimit ? 0 : int.MinValue; // If we don't have an upper bound, have the comparison always return true.
+
+ do
+ {
+ remaining--;
+ list.Add(en.Current);
+ }
+ while (remaining >= comparand && en.MoveNext());
+ }
+ }
+
+ return list;
+ }
+
+ private bool SkipBeforeFirst(IEnumerator<TSource> en) => SkipBefore(_minIndexInclusive, en);
+
+ private static bool SkipBefore(int index, IEnumerator<TSource> en) => SkipAndCount(index, en) == index;
+
+ private static int SkipAndCount(int index, IEnumerator<TSource> en)
+ {
+ Debug.Assert(index >= 0);
+ return (int)SkipAndCount((uint)index, en);
+ }
+
+ private static uint SkipAndCount(uint index, IEnumerator<TSource> en)
+ {
+ Debug.Assert(en != null);
+
+ for (uint i = 0; i < index; i++)
+ {
+ if (!en.MoveNext())
+ {
+ return i;
+ }
+ }
+
+ return index;
+ }
+ }
}
}
diff --git a/src/System.Linq/src/System/Linq/Range.cs b/src/System.Linq/src/System/Linq/Range.cs
index 603e971385..2f5ecbac3a 100644
--- a/src/System.Linq/src/System/Linq/Range.cs
+++ b/src/System.Linq/src/System/Linq/Range.cs
@@ -25,6 +25,9 @@ namespace System.Linq
return new RangeIterator(start, count);
}
+ /// <summary>
+ /// An iterator that yields a range of consecutive integers.
+ /// </summary>
private sealed class RangeIterator : Iterator<int>, IPartition<int>
{
private readonly int _start;
diff --git a/src/System.Linq/src/System/Linq/Repeat.cs b/src/System.Linq/src/System/Linq/Repeat.cs
index e2535f3986..e3fe9c0f72 100644
--- a/src/System.Linq/src/System/Linq/Repeat.cs
+++ b/src/System.Linq/src/System/Linq/Repeat.cs
@@ -24,6 +24,10 @@ namespace System.Linq
return new RepeatIterator<TResult>(element, count);
}
+ /// <summary>
+ /// An iterator that yields the same item multiple times.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the item.</typeparam>
private sealed class RepeatIterator<TResult> : Iterator<TResult>, IPartition<TResult>
{
private readonly int _count;
diff --git a/src/System.Linq/src/System/Linq/Reverse.cs b/src/System.Linq/src/System/Linq/Reverse.cs
index 81edc65ae0..594eb89a77 100644
--- a/src/System.Linq/src/System/Linq/Reverse.cs
+++ b/src/System.Linq/src/System/Linq/Reverse.cs
@@ -20,6 +20,10 @@ namespace System.Linq
return new ReverseIterator<TSource>(source);
}
+ /// <summary>
+ /// An iterator that yields the items of an <see cref="IEnumerable{TSource}"/> in reverse.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerable.</typeparam>
private sealed class ReverseIterator<TSource> : Iterator<TSource>, IIListProvider<TSource>
{
private readonly IEnumerable<TSource> _source;
diff --git a/src/System.Linq/src/System/Linq/Select.cs b/src/System.Linq/src/System/Linq/Select.cs
index 2ed2dd85f8..3e7331982d 100644
--- a/src/System.Linq/src/System/Linq/Select.cs
+++ b/src/System.Linq/src/System/Linq/Select.cs
@@ -86,6 +86,11 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that maps each item of an <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerable.</typeparam>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
internal sealed class SelectEnumerableIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult>
{
private readonly IEnumerable<TSource> _source;
@@ -155,11 +160,48 @@ namespace System.Linq
return builder.ToArray();
}
- public List<TResult> ToList() => new List<TResult>(this);
+ public List<TResult> ToList()
+ {
+ var list = new List<TResult>();
+
+ foreach (TSource item in _source)
+ {
+ list.Add(_selector(item));
+ }
+
+ return list;
+ }
+
+ public int GetCount(bool onlyIfCheap)
+ {
+ // In case someone uses Count() to force evaluation of
+ // the selector, run it provided `onlyIfCheap` is false.
+
+ if (onlyIfCheap)
+ {
+ return -1;
+ }
- public int GetCount(bool onlyIfCheap) => onlyIfCheap ? -1 : _source.Count();
+ int count = 0;
+
+ foreach (TSource item in _source)
+ {
+ _selector(item);
+ checked
+ {
+ count++;
+ }
+ }
+
+ return count;
+ }
}
+ /// <summary>
+ /// An iterator that maps each item of a <see cref="T:TSource[]"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source array.</typeparam>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
internal sealed class SelectArrayIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult>
{
private readonly TSource[] _source;
@@ -226,6 +268,17 @@ namespace System.Linq
public int GetCount(bool onlyIfCheap)
{
+ // In case someone uses Count() to force evaluation of
+ // the selector, run it provided `onlyIfCheap` is false.
+
+ if (!onlyIfCheap)
+ {
+ foreach (TSource item in _source)
+ {
+ _selector(item);
+ }
+ }
+
return _source.Length;
}
@@ -274,6 +327,11 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that maps each item of a <see cref="List{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source list.</typeparam>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
internal sealed class SelectListIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult>
{
private readonly List<TSource> _source;
@@ -351,7 +409,20 @@ namespace System.Linq
public int GetCount(bool onlyIfCheap)
{
- return _source.Count;
+ // In case someone uses Count() to force evaluation of
+ // the selector, run it provided `onlyIfCheap` is false.
+
+ int count = _source.Count;
+
+ if (!onlyIfCheap)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ _selector(_source[i]);
+ }
+ }
+
+ return count;
}
public IPartition<TResult> Skip(int count)
@@ -403,6 +474,11 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that maps each item of an <see cref="IList{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source list.</typeparam>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
internal sealed class SelectIListIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult>
{
private readonly IList<TSource> _source;
@@ -491,7 +567,20 @@ namespace System.Linq
public int GetCount(bool onlyIfCheap)
{
- return _source.Count;
+ // In case someone uses Count() to force evaluation of
+ // the selector, run it provided `onlyIfCheap` is false.
+
+ int count = _source.Count;
+
+ if (!onlyIfCheap)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ _selector(_source[i]);
+ }
+ }
+
+ return count;
}
public IPartition<TResult> Skip(int count)
@@ -543,6 +632,11 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that maps each item of an <see cref="IPartition{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source partition.</typeparam>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
internal sealed class SelectIPartitionIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult>
{
private readonly IPartition<TSource> _source;
@@ -703,10 +797,26 @@ namespace System.Linq
public int GetCount(bool onlyIfCheap)
{
+ // In case someone uses Count() to force evaluation of
+ // the selector, run it provided `onlyIfCheap` is false.
+
+ if (!onlyIfCheap)
+ {
+ foreach (TSource item in _source)
+ {
+ _selector(item);
+ }
+ }
+
return _source.GetCount(onlyIfCheap);
}
}
+ /// <summary>
+ /// An iterator that maps each item of part of an <see cref="IList{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source list.</typeparam>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
private sealed class SelectListPartitionIterator<TSource, TResult> : Iterator<TResult>, IPartition<TResult>
{
private readonly IList<TSource> _source;
@@ -852,7 +962,21 @@ namespace System.Linq
public int GetCount(bool onlyIfCheap)
{
- return Count;
+ // In case someone uses Count() to force evaluation of
+ // the selector, run it provided `onlyIfCheap` is false.
+
+ int count = Count;
+
+ if (!onlyIfCheap)
+ {
+ int end = _minIndexInclusive + count;
+ for (int i = _minIndexInclusive; i != end; ++i)
+ {
+ _selector(_source[i]);
+ }
+ }
+
+ return count;
}
}
}
diff --git a/src/System.Linq/src/System/Linq/SelectMany.cs b/src/System.Linq/src/System/Linq/SelectMany.cs
index 518aec61ab..3d13c125cc 100644
--- a/src/System.Linq/src/System/Linq/SelectMany.cs
+++ b/src/System.Linq/src/System/Linq/SelectMany.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Diagnostics;
namespace System.Linq
{
@@ -20,18 +21,7 @@ namespace System.Linq
throw Error.ArgumentNull(nameof(selector));
}
- return SelectManyIterator(source, selector);
- }
-
- private static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
- {
- foreach (TSource element in source)
- {
- foreach (TResult subElement in selector(element))
- {
- yield return subElement;
- }
- }
+ return new SelectManySingleSelectorIterator<TSource, TResult>(source, selector);
}
public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
@@ -133,5 +123,128 @@ namespace System.Linq
}
}
}
+
+ private sealed class SelectManySingleSelectorIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult>
+ {
+ private readonly IEnumerable<TSource> _source;
+ private readonly Func<TSource, IEnumerable<TResult>> _selector;
+ private IEnumerator<TSource> _sourceEnumerator;
+ private IEnumerator<TResult> _subEnumerator;
+
+ internal SelectManySingleSelectorIterator(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
+ {
+ Debug.Assert(source != null);
+ Debug.Assert(selector != null);
+
+ _source = source;
+ _selector = selector;
+ }
+
+ public override Iterator<TResult> Clone()
+ {
+ return new SelectManySingleSelectorIterator<TSource, TResult>(_source, _selector);
+ }
+
+ public override void Dispose()
+ {
+ if (_subEnumerator != null)
+ {
+ _subEnumerator.Dispose();
+ _subEnumerator = null;
+ }
+
+ if (_sourceEnumerator != null)
+ {
+ _sourceEnumerator.Dispose();
+ _sourceEnumerator = null;
+ }
+
+ base.Dispose();
+ }
+
+ public int GetCount(bool onlyIfCheap)
+ {
+ if (onlyIfCheap)
+ {
+ return -1;
+ }
+
+ int count = 0;
+
+ foreach (TSource element in _source)
+ {
+ checked
+ {
+ count += _selector(element).Count();
+ }
+ }
+
+ return count;
+ }
+
+ public override bool MoveNext()
+ {
+ switch (_state)
+ {
+ case 1:
+ // Retrieve the source enumerator.
+ _sourceEnumerator = _source.GetEnumerator();
+ _state = 2;
+ goto case 2;
+ case 2:
+ // Take the next element from the source enumerator.
+ if (!_sourceEnumerator.MoveNext())
+ {
+ break;
+ }
+
+ TSource element = _sourceEnumerator.Current;
+
+ // Project it into a sub-collection and get its enumerator.
+ _subEnumerator = _selector(element).GetEnumerator();
+ _state = 3;
+ goto case 3;
+ case 3:
+ // Take the next element from the sub-collection and yield.
+ if (!_subEnumerator.MoveNext())
+ {
+ _subEnumerator.Dispose();
+ _subEnumerator = null;
+ _state = 2;
+ goto case 2;
+ }
+
+ _current = _subEnumerator.Current;
+ return true;
+ }
+
+ Dispose();
+ return false;
+ }
+
+ public TResult[] ToArray()
+ {
+ var builder = new LargeArrayBuilder<TResult>(initialize: true);
+
+ foreach (TSource element in _source)
+ {
+ builder.AddRange(_selector(element));
+ }
+
+ return builder.ToArray();
+ }
+
+ public List<TResult> ToList()
+ {
+ var list = new List<TResult>();
+
+ foreach (TSource element in _source)
+ {
+ list.AddRange(_selector(element));
+ }
+
+ return list;
+ }
+ }
}
}
diff --git a/src/System.Linq/src/System/Linq/Set.cs b/src/System.Linq/src/System/Linq/Set.cs
index 60bf491b30..ac0c0afdd5 100644
--- a/src/System.Linq/src/System/Linq/Set.cs
+++ b/src/System.Linq/src/System/Linq/Set.cs
@@ -7,16 +7,51 @@ using System.Diagnostics;
namespace System.Linq
{
+ /// <summary>
+ /// A lightweight hash set.
+ /// </summary>
+ /// <typeparam name="TElement">The type of the set's items.</typeparam>
internal sealed class Set<TElement>
{
+ /// <summary>
+ /// The comparer used to hash and compare items in the set.
+ /// </summary>
private readonly IEqualityComparer<TElement> _comparer;
+
+ /// <summary>
+ /// The hash buckets, which are used to index into the slots.
+ /// </summary>
private int[] _buckets;
+
+ /// <summary>
+ /// The slots, each of which store an item and its hash code.
+ /// </summary>
private Slot[] _slots;
+
+ /// <summary>
+ /// The number of items in this set.
+ /// </summary>
private int _count;
+
#if DEBUG
+ /// <summary>
+ /// Whether <see cref="Remove"/> has been called on this set.
+ /// </summary>
+ /// <remarks>
+ /// When <see cref="Remove"/> runs in debug builds, this flag is set to <c>true</c>.
+ /// Other methods assert that this flag is <c>false</c> in debug builds, because
+ /// they make optimizations that may not be correct if <see cref="Remove"/> is called
+ /// beforehand.
+ /// </remarks>
private bool _haveRemoved;
#endif
+ /// <summary>
+ /// Constructs a set that compares items with the specified comparer.
+ /// </summary>
+ /// <param name="comparer">
+ /// The comparer. If this is <c>null</c>, it defaults to <see cref="EqualityComparer{TElement}.Default"/>.
+ /// </param>
public Set(IEqualityComparer<TElement> comparer)
{
_comparer = comparer ?? EqualityComparer<TElement>.Default;
@@ -24,7 +59,13 @@ namespace System.Linq
_slots = new Slot[7];
}
- // If value is not in set, add it and return true; otherwise return false
+ /// <summary>
+ /// Attempts to add an item to this set.
+ /// </summary>
+ /// <param name="value">The item to add.</param>
+ /// <returns>
+ /// <c>true</c> if the item was not in the set; otherwise, <c>false</c>.
+ /// </returns>
public bool Add(TElement value)
{
#if DEBUG
@@ -54,7 +95,13 @@ namespace System.Linq
return true;
}
- // If value is in set, remove it and return true; otherwise return false
+ /// <summary>
+ /// Attempts to remove an item from this set.
+ /// </summary>
+ /// <param name="value">The item to remove.</param>
+ /// <returns>
+ /// <c>true</c> if the item was in the set; otherwise, <c>false</c>.
+ /// </returns>
public bool Remove(TElement value)
{
#if DEBUG
@@ -86,6 +133,9 @@ namespace System.Linq
return false;
}
+ /// <summary>
+ /// Expands the capacity of this set to double the current capacity, plus one.
+ /// </summary>
private void Resize()
{
int newSize = checked((_count * 2) + 1);
@@ -103,6 +153,10 @@ namespace System.Linq
_slots = newSlots;
}
+ /// <summary>
+ /// Creates an array from the items in this set.
+ /// </summary>
+ /// <returns>An array of the items in this set.</returns>
internal TElement[] ToArray()
{
#if DEBUG
@@ -117,6 +171,10 @@ namespace System.Linq
return array;
}
+ /// <summary>
+ /// Creates a list from the items in this set.
+ /// </summary>
+ /// <returns>A list of the items in this set.</returns>
internal List<TElement> ToList()
{
#if DEBUG
@@ -132,21 +190,40 @@ namespace System.Linq
return list;
}
- internal int Count
- {
- get { return _count; }
- }
+ /// <summary>
+ /// The number of items in this set.
+ /// </summary>
+ internal int Count => _count;
+ /// <summary>
+ /// Gets the hash code of the provided value with its sign bit zeroed out, so that modulo has a positive result.
+ /// </summary>
+ /// <param name="value">The value to hash.</param>
+ /// <returns>The lower 31 bits of the value's hash code.</returns>
internal int InternalGetHashCode(TElement value)
{
// Handle comparer implementations that throw when passed null
return (value == null) ? 0 : _comparer.GetHashCode(value) & 0x7FFFFFFF;
}
+ /// <summary>
+ /// An entry in the hash set.
+ /// </summary>
internal struct Slot
{
+ /// <summary>
+ /// The hash code of the item.
+ /// </summary>
internal int _hashCode;
+
+ /// <summary>
+ /// In the case of a hash collision, the index of the next slot to probe.
+ /// </summary>
internal int _next;
+
+ /// <summary>
+ /// The item held by this slot.
+ /// </summary>
internal TElement _value;
}
}
diff --git a/src/System.Linq/src/System/Linq/Skip.cs b/src/System.Linq/src/System/Linq/Skip.cs
index 81fd83ed2a..bd3be6eec3 100644
--- a/src/System.Linq/src/System/Linq/Skip.cs
+++ b/src/System.Linq/src/System/Linq/Skip.cs
@@ -41,26 +41,7 @@ namespace System.Linq
return new ListPartition<TSource>(sourceList, count, int.MaxValue);
}
- return SkipIterator(source, count);
- }
-
- private static IEnumerable<TSource> SkipIterator<TSource>(IEnumerable<TSource> source, int count)
- {
- using (IEnumerator<TSource> e = source.GetEnumerator())
- {
- while (count > 0 && e.MoveNext())
- {
- count--;
- }
-
- if (count <= 0)
- {
- while (e.MoveNext())
- {
- yield return e.Current;
- }
- }
- }
+ return new EnumerablePartition<TSource>(source, count, -1);
}
public static IEnumerable<TSource> SkipWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
diff --git a/src/System.Linq/src/System/Linq/Take.cs b/src/System.Linq/src/System/Linq/Take.cs
index 527dc3553d..7c2b9dfbc8 100644
--- a/src/System.Linq/src/System/Linq/Take.cs
+++ b/src/System.Linq/src/System/Linq/Take.cs
@@ -32,19 +32,7 @@ namespace System.Linq
return new ListPartition<TSource>(sourceList, 0, count - 1);
}
- return TakeIterator(source, count);
- }
-
- private static IEnumerable<TSource> TakeIterator<TSource>(IEnumerable<TSource> source, int count)
- {
- foreach (TSource element in source)
- {
- yield return element;
- if (--count == 0)
- {
- break;
- }
- }
+ return new EnumerablePartition<TSource>(source, 0, count - 1);
}
public static IEnumerable<TSource> TakeWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
diff --git a/src/System.Linq/src/System/Linq/Union.cs b/src/System.Linq/src/System/Linq/Union.cs
index 97c79f701d..431928d3c3 100644
--- a/src/System.Linq/src/System/Linq/Union.cs
+++ b/src/System.Linq/src/System/Linq/Union.cs
@@ -31,6 +31,10 @@ namespace System.Linq
return union != null && AreEqualityComparersEqual(comparer, union._comparer) ? union.Union(second) : new UnionIterator2<TSource>(first, second, comparer);
}
+ /// <summary>
+ /// An iterator that yields distinct values from two or more <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerables.</typeparam>
private abstract class UnionIterator<TSource> : Iterator<TSource>, IIListProvider<TSource>
{
internal readonly IEqualityComparer<TSource> _comparer;
@@ -166,7 +170,11 @@ namespace System.Linq
return onlyIfCheap ? -1 : FillSet().Count;
}
}
-
+
+ /// <summary>
+ /// An iterator that yields distinct values from two <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerables.</typeparam>
private sealed class UnionIterator2<TSource> : UnionIterator<TSource>
{
private readonly IEnumerable<TSource> _first;
@@ -206,6 +214,10 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that yields distinct values from three or more <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerables.</typeparam>
private sealed class UnionIteratorN<TSource> : UnionIterator<TSource>
{
private readonly UnionIterator<TSource> _previous;
diff --git a/src/System.Linq/src/System/Linq/Utilities.cs b/src/System.Linq/src/System/Linq/Utilities.cs
index 9dd80d917f..7c226f0a52 100644
--- a/src/System.Linq/src/System/Linq/Utilities.cs
+++ b/src/System.Linq/src/System/Linq/Utilities.cs
@@ -11,6 +11,13 @@ namespace System.Linq
/// </summary>
internal static class Utilities
{
+ /// <summary>
+ /// Decides if two equality comparers are equivalent.
+ /// </summary>
+ /// <typeparam name="TSource">The type of each comparer.</typeparam>
+ /// <param name="left">The first comparer.</param>
+ /// <param name="right">The second comparer.</param>
+ /// <returns><c>true</c> if the equality comparers are equal; otherwise, <c>false</c>.</returns>
public static bool AreEqualityComparersEqual<TSource>(IEqualityComparer<TSource> left, IEqualityComparer<TSource> right)
{
if (left == right)
@@ -36,11 +43,33 @@ namespace System.Linq
return left.Equals(right);
}
+ /// <summary>
+ /// Combines two predicates.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the predicate argument.</typeparam>
+ /// <param name="predicate1">The first predicate to run.</param>
+ /// <param name="predicate2">The second predicate to run.</param>
+ /// <returns>
+ /// A new predicate that will evaluate to <c>true</c> only if both the first and
+ /// second predicates return true. If the first predicate returns <c>false</c>,
+ /// the second predicate will not be run.
+ /// </returns>
public static Func<TSource, bool> CombinePredicates<TSource>(Func<TSource, bool> predicate1, Func<TSource, bool> predicate2)
{
return x => predicate1(x) && predicate2(x);
}
+ /// <summary>
+ /// Combines two selectors.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the first selector's argument.</typeparam>
+ /// <typeparam name="TMiddle">The type of the second selector's argument.</typeparam>
+ /// <typeparam name="TResult">The type of the second selector's return value.</typeparam>
+ /// <param name="selector1">The first selector to run.</param>
+ /// <param name="selector2">The second selector to run.</param>
+ /// <returns>
+ /// A new selector that represents the composition of the first selector with the second selector.
+ /// </returns>
public static Func<TSource, TResult> CombineSelectors<TSource, TMiddle, TResult>(Func<TSource, TMiddle> selector1, Func<TMiddle, TResult> selector2)
{
return x => selector2(selector1(x));
diff --git a/src/System.Linq/src/System/Linq/Where.cs b/src/System.Linq/src/System/Linq/Where.cs
index 0e28a94020..d2f8e42d5b 100644
--- a/src/System.Linq/src/System/Linq/Where.cs
+++ b/src/System.Linq/src/System/Linq/Where.cs
@@ -77,6 +77,10 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that filters each item of an <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerable.</typeparam>
internal sealed class WhereEnumerableIterator<TSource> : Iterator<TSource>, IIListProvider<TSource>
{
private readonly IEnumerable<TSource> _source;
@@ -197,6 +201,10 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that filters each item of a <see cref="T:TSource[]"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source array.</typeparam>
internal sealed class WhereArrayIterator<TSource> : Iterator<TSource>, IIListProvider<TSource>
{
private readonly TSource[] _source;
@@ -265,7 +273,7 @@ namespace System.Linq
public TSource[] ToArray()
{
- var builder = new LargeArrayBuilder<TSource>(initialize: true);
+ var builder = new LargeArrayBuilder<TSource>(_source.Length);
foreach (TSource item in _source)
{
@@ -299,6 +307,10 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that filters each item of a <see cref="List{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source list.</typeparam>
internal sealed class WhereListIterator<TSource> : Iterator<TSource>, IIListProvider<TSource>
{
private readonly List<TSource> _source;
@@ -375,7 +387,7 @@ namespace System.Linq
public TSource[] ToArray()
{
- var builder = new LargeArrayBuilder<TSource>(initialize: true);
+ var builder = new LargeArrayBuilder<TSource>(_source.Count);
for (int i = 0; i < _source.Count; i++)
{
@@ -411,6 +423,11 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that filters, then maps, each item of a <see cref="T:TSource[]"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source array.</typeparam>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
internal sealed class WhereSelectArrayIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult>
{
private readonly TSource[] _source;
@@ -434,6 +451,9 @@ namespace System.Linq
public int GetCount(bool onlyIfCheap)
{
+ // In case someone uses Count() to force evaluation of
+ // the selector, run it provided `onlyIfCheap` is false.
+
if (onlyIfCheap)
{
return -1;
@@ -483,7 +503,7 @@ namespace System.Linq
public TResult[] ToArray()
{
- var builder = new LargeArrayBuilder<TResult>(initialize: true);
+ var builder = new LargeArrayBuilder<TResult>(_source.Length);
foreach (TSource item in _source)
{
@@ -512,6 +532,11 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that filters, then maps, each item of a <see cref="List{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source list.</typeparam>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
internal sealed class WhereSelectListIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult>
{
private readonly List<TSource> _source;
@@ -536,6 +561,9 @@ namespace System.Linq
public int GetCount(bool onlyIfCheap)
{
+ // In case someone uses Count() to force evaluation of
+ // the selector, run it provided `onlyIfCheap` is false.
+
if (onlyIfCheap)
{
return -1;
@@ -592,7 +620,7 @@ namespace System.Linq
public TResult[] ToArray()
{
- var builder = new LargeArrayBuilder<TResult>(initialize: true);
+ var builder = new LargeArrayBuilder<TResult>(_source.Count);
for (int i = 0; i < _source.Count; i++)
{
@@ -623,6 +651,11 @@ namespace System.Linq
}
}
+ /// <summary>
+ /// An iterator that filters, then maps, each item of an <see cref="IEnumerable{TSource}"/>.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source enumerable.</typeparam>
+ /// <typeparam name="TResult">The type of the mapped items.</typeparam>
internal sealed class WhereSelectEnumerableIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult>
{
private readonly IEnumerable<TSource> _source;
@@ -658,6 +691,9 @@ namespace System.Linq
public int GetCount(bool onlyIfCheap)
{
+ // In case someone uses Count() to force evaluation of
+ // the selector, run it provided `onlyIfCheap` is false.
+
if (onlyIfCheap)
{
return -1;
diff --git a/src/System.Linq/tests/AggregateTests.cs b/src/System.Linq/tests/AggregateTests.cs
index 84d55284b7..5d6d5873c0 100644
--- a/src/System.Linq/tests/AggregateTests.cs
+++ b/src/System.Linq/tests/AggregateTests.cs
@@ -35,7 +35,7 @@ namespace System.Linq.Tests
{
int[] source = { };
- Assert.Throws<InvalidOperationException>(() => source.Aggregate((x, y) => x + y));
+ Assert.Throws<InvalidOperationException>(() => source.RunOnce().Aggregate((x, y) => x + y));
}
[Fact]
@@ -45,7 +45,15 @@ namespace System.Linq.Tests
int expected = 5;
Assert.Equal(expected, source.Aggregate((x, y) => x + y));
+ }
+
+ [Fact]
+ public void SingleElementRunOnce()
+ {
+ int[] source = { 5 };
+ int expected = 5;
+ Assert.Equal(expected, source.RunOnce().Aggregate((x, y) => x + y));
}
[Fact]
@@ -67,6 +75,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void MultipleElementsRunOnce()
+ {
+ int[] source = { 5, 6, 0, -4 };
+ int expected = 7;
+
+ Assert.Equal(expected, source.RunOnce().Aggregate((x, y) => x + y));
+ }
+
+ [Fact]
public void EmptySourceAndSeed()
{
int[] source = { };
@@ -107,6 +124,16 @@ namespace System.Linq.Tests
}
[Fact]
+ public void MultipleElementsAndSeedRunOnce()
+ {
+ int[] source = { 5, 6, 2, -4 };
+ long seed = 2;
+ long expected = -480;
+
+ Assert.Equal(expected, source.RunOnce().Aggregate(seed, (x, y) => x * y));
+ }
+
+ [Fact]
public void NoElementsSeedResultSeletor()
{
int[] source = { };
@@ -147,6 +174,16 @@ namespace System.Linq.Tests
}
[Fact]
+ public void MultipleElementsSeedResultSelectorRunOnce()
+ {
+ int[] source = { 5, 6, 2, -4 };
+ long seed = 2;
+ long expected = -475;
+
+ Assert.Equal(expected, source.RunOnce().Aggregate(seed, (x, y) => x * y, x => x + 5.0));
+ }
+
+ [Fact]
public void NullSource()
{
Assert.Throws<ArgumentNullException>("source", () => ((IEnumerable<int>)null).Aggregate((x, y) => x + y));
diff --git a/src/System.Linq/tests/AllTests.cs b/src/System.Linq/tests/AllTests.cs
index 9755bc536b..4c1f069bfc 100644
--- a/src/System.Linq/tests/AllTests.cs
+++ b/src/System.Linq/tests/AllTests.cs
@@ -57,6 +57,12 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.All(predicate));
}
+ [Theory, MemberData(nameof(All_TestData))]
+ public void AllRunOnce(IEnumerable<int> source, Func<int, bool> predicate, bool expected)
+ {
+ Assert.Equal(expected, source.RunOnce().All(predicate));
+ }
+
[Fact]
public void NullSource_ThrowsArgumentNullException()
{
diff --git a/src/System.Linq/tests/AnyTests.cs b/src/System.Linq/tests/AnyTests.cs
index 6d522e2c48..9355ba83ab 100644
--- a/src/System.Linq/tests/AnyTests.cs
+++ b/src/System.Linq/tests/AnyTests.cs
@@ -65,6 +65,19 @@ namespace System.Linq.Tests
}
}
+ [Theory, MemberData(nameof(TestData))]
+ public void AnyRunOnce(IEnumerable<int> source, Func<int, bool> predicate, bool expected)
+ {
+ if (predicate == null)
+ {
+ Assert.Equal(expected, source.RunOnce().Any());
+ }
+ else
+ {
+ Assert.Equal(expected, source.RunOnce().Any(predicate));
+ }
+ }
+
[Fact]
public void NullObjectsInArray_Included()
{
diff --git a/src/System.Linq/tests/AppendPrependTests.cs b/src/System.Linq/tests/AppendPrependTests.cs
index 0f22a286d9..d701fe3af9 100644
--- a/src/System.Linq/tests/AppendPrependTests.cs
+++ b/src/System.Linq/tests/AppendPrependTests.cs
@@ -255,5 +255,14 @@ namespace System.Linq.Tests
Assert.Equal(Enumerable.Range(0, 6), source.ToList());
Assert.Equal(Enumerable.Range(0, 6), source.ToArray());
}
+
+ [Fact]
+ public void AppendPrependRunOnce()
+ {
+ var source = NumberRangeGuaranteedNotCollectionType(2, 2).RunOnce().Prepend(1).RunOnce().Prepend(0).RunOnce().Append(4).RunOnce().Append(5).RunOnce();
+ Assert.Equal(Enumerable.Range(0, 6), source.ToList());
+ source = NumberRangeGuaranteedNotCollectionType(2, 2).Prepend(1).Prepend(0).Append(4).Append(5).RunOnce();
+ Assert.Equal(Enumerable.Range(0, 6), source.ToList());
+ }
}
}
diff --git a/src/System.Linq/tests/AsEnumerableTests.cs b/src/System.Linq/tests/AsEnumerableTests.cs
index a7d7a422ce..eecc1ea6aa 100644
--- a/src/System.Linq/tests/AsEnumerableTests.cs
+++ b/src/System.Linq/tests/AsEnumerableTests.cs
@@ -53,5 +53,13 @@ namespace System.Linq.Tests
Assert.Equal(source, source.AsEnumerable());
}
+
+ [Fact]
+ public void SomeElementsRunOnce()
+ {
+ int?[] source = { -5, 0, 1, -4, 3, null, 10 };
+
+ Assert.Equal(source, source.RunOnce().AsEnumerable());
+ }
}
}
diff --git a/src/System.Linq/tests/AverageTests.cs b/src/System.Linq/tests/AverageTests.cs
index d22e950758..4d84492581 100644
--- a/src/System.Linq/tests/AverageTests.cs
+++ b/src/System.Linq/tests/AverageTests.cs
@@ -48,6 +48,13 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Average(x => x));
}
+ [Theory, MemberData(nameof(NullableFloat_TestData))]
+ public void NullableFoatRunOnce(float?[] source, float? expected)
+ {
+ Assert.Equal(expected, source.RunOnce().Average());
+ Assert.Equal(expected, source.RunOnce().Average(x => x));
+ }
+
[Fact]
public void NullableFloat_NullSource_ThrowsArgumentNullException()
{
@@ -114,6 +121,13 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Average(x => x));
}
+ [Theory, MemberData(nameof(Int_TestData))]
+ public void IntRunOnce(int[] source, double expected)
+ {
+ Assert.Equal(expected, source.RunOnce().Average());
+ Assert.Equal(expected, source.RunOnce().Average(x => x));
+ }
+
[Fact]
public void Int_WithSelector()
{
diff --git a/src/System.Linq/tests/CastTests.cs b/src/System.Linq/tests/CastTests.cs
index ef9008d7e4..0d74305956 100644
--- a/src/System.Linq/tests/CastTests.cs
+++ b/src/System.Linq/tests/CastTests.cs
@@ -48,7 +48,17 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Cast<int?>());
}
-
+
+ [Fact]
+ public void NullableIntFromAppropriateObjectsRunOnce()
+ {
+ int? i = 10;
+ object[] source = { -4, 1, 2, 3, 9, i };
+ int?[] expected = { -4, 1, 2, 3, 9, i };
+
+ Assert.Equal(expected, source.RunOnce().Cast<int?>());
+ }
+
[Fact]
public void LongFromNullableIntInObjectsThrows()
{
@@ -127,6 +137,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void CastToStringRunOnce()
+ {
+ object[] source = { "Test1", "4.5", null, "Test2" };
+ string[] expected = { "Test1", "4.5", null, "Test2" };
+
+ Assert.Equal(expected, source.RunOnce().Cast<string>());
+ }
+
+ [Fact]
public void ArrayConversionThrows()
{
Assert.Throws<InvalidCastException>(() => new[] { -4 }.Cast<long>().ToList());
diff --git a/src/System.Linq/tests/ConcatTests.cs b/src/System.Linq/tests/ConcatTests.cs
index c16dae4d7e..c758cc416e 100644
--- a/src/System.Linq/tests/ConcatTests.cs
+++ b/src/System.Linq/tests/ConcatTests.cs
@@ -221,6 +221,22 @@ namespace System.Linq.Tests
}
}
+ [Theory]
+ [MemberData(nameof(ManyConcatsData))]
+ public void ManyConcatsRunOnce(IEnumerable<IEnumerable<int>> sources, IEnumerable<int> expected)
+ {
+ foreach (var transform in IdentityTransforms<int>())
+ {
+ IEnumerable<int> concatee = Enumerable.Empty<int>();
+ foreach (var source in sources)
+ {
+ concatee = concatee.RunOnce().Concat(transform(source));
+ }
+
+ Assert.Equal(sources.Sum(s => s.Count()), concatee.Count());
+ }
+ }
+
public static IEnumerable<object[]> ManyConcatsData()
{
yield return new object[] { Enumerable.Repeat(Enumerable.Empty<int>(), 256), Enumerable.Empty<int>() };
diff --git a/src/System.Linq/tests/ContainsTests.cs b/src/System.Linq/tests/ContainsTests.cs
index edf3808f1f..7473136045 100644
--- a/src/System.Linq/tests/ContainsTests.cs
+++ b/src/System.Linq/tests/ContainsTests.cs
@@ -52,6 +52,13 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Contains(value, null));
}
+ [Theory, MemberData(nameof(Int_TestData))]
+ public void IntRunOnce(IEnumerable<int> source, int value, bool expected)
+ {
+ Assert.Equal(expected, source.RunOnce().Contains(value));
+ Assert.Equal(expected, source.RunOnce().Contains(value, null));
+ }
+
public static IEnumerable<object> String_TestData()
{
yield return new object[] { new string[] { null }, StringComparer.Ordinal, null, true };
@@ -72,6 +79,16 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Contains(value, comparer));
}
+ [Theory, MemberData(nameof(String_TestData))]
+ public void StringRunOnce(IEnumerable<string> source, IEqualityComparer<string> comparer, string value, bool expected)
+ {
+ if (comparer == null)
+ {
+ Assert.Equal(expected, source.RunOnce().Contains(value));
+ }
+ Assert.Equal(expected, source.RunOnce().Contains(value, comparer));
+ }
+
public static IEnumerable<object> NullableInt_TestData()
{
yield return new object[] { new int?[] { 8, 0, 10, 3, 0, -8, 0 }, null, false };
@@ -97,5 +114,33 @@ namespace System.Linq.Tests
Assert.Throws<ArgumentNullException>("source", () => source.Contains(42));
Assert.Throws<ArgumentNullException>("source", () => source.Contains(42, EqualityComparer<int>.Default));
}
+
+ [Fact]
+ public void ExplicitNullComparerDoesNotDeferToCollection()
+ {
+ IEnumerable<string> source = new HashSet<string>(new AnagramEqualityComparer()) {"ABC"};
+ Assert.False(source.Contains("BAC", null));
+ }
+
+ [Fact]
+ public void ExplicitComparerDoesNotDeferToCollection()
+ {
+ IEnumerable<string> source = new HashSet<string> {"ABC"};
+ Assert.True(source.Contains("abc", StringComparer.OrdinalIgnoreCase));
+ }
+
+ [Fact]
+ public void ExplicitComparerDoestNotDeferToCollectionWithComparer()
+ {
+ IEnumerable<string> source = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {"ABC"};
+ Assert.True(source.Contains("BAC", new AnagramEqualityComparer()));
+ }
+
+ [Fact]
+ public void NoComparerDoesDeferToCollection()
+ {
+ IEnumerable<string> source = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {"ABC"};
+ Assert.True(source.Contains("abc"));
+ }
}
}
diff --git a/src/System.Linq/tests/CountTests.cs b/src/System.Linq/tests/CountTests.cs
index b1910665e6..dc402c0dfd 100644
--- a/src/System.Linq/tests/CountTests.cs
+++ b/src/System.Linq/tests/CountTests.cs
@@ -59,6 +59,19 @@ namespace System.Linq.Tests
}
}
+ [Theory, MemberData(nameof(Int_TestData))]
+ public void IntRunOnce(IEnumerable<int> source, Func<int, bool> predicate, int expected)
+ {
+ if (predicate == null)
+ {
+ Assert.Equal(expected, source.RunOnce().Count());
+ }
+ else
+ {
+ Assert.Equal(expected, source.RunOnce().Count(predicate));
+ }
+ }
+
[Fact]
public void NullableIntArray_IncludesNullObjects()
{
@@ -74,6 +87,13 @@ namespace System.Linq.Tests
Assert.Equal(count, enumerable.Count());
}
+ [Theory, MemberData(nameof(CountsAndTallies))]
+ public void RunOnce<T, TEn>(T unusedArgumentToForceTypeInference, int count, TEn enumerable)
+ where TEn : IEnumerable<T>
+ {
+ Assert.Equal(count, enumerable.RunOnce().Count());
+ }
+
private static IEnumerable<object[]> EnumerateCollectionTypesAndCounts<T>(int count, IEnumerable<T> enumerable)
{
yield return new object[] { default(T), count, enumerable };
diff --git a/src/System.Linq/tests/DefaultIfEmptyTests.cs b/src/System.Linq/tests/DefaultIfEmptyTests.cs
index 67a31e2e2d..b3fd7c9685 100644
--- a/src/System.Linq/tests/DefaultIfEmptyTests.cs
+++ b/src/System.Linq/tests/DefaultIfEmptyTests.cs
@@ -63,6 +63,17 @@ namespace System.Linq.Tests
Assert.Equal(expected, result.ToArray());
}
+ [Theory, MemberData(nameof(TestData))]
+ public static void DefaultIfEmptyRunOnce(IEnumerable<int> source, int defaultValue, int[] expected)
+ {
+ if (defaultValue == 0)
+ {
+ Assert.Equal(expected, source.RunOnce().DefaultIfEmpty());
+ }
+
+ Assert.Equal(expected, source.RunOnce().DefaultIfEmpty(defaultValue));
+ }
+
[Fact]
public void NullableArray_Empty_WithoutDefaultValue()
{
diff --git a/src/System.Linq/tests/DistinctTests.cs b/src/System.Linq/tests/DistinctTests.cs
index 48ee19c3ea..47a8bdbf4f 100644
--- a/src/System.Linq/tests/DistinctTests.cs
+++ b/src/System.Linq/tests/DistinctTests.cs
@@ -39,6 +39,13 @@ namespace System.Linq.Tests
}
[Fact]
+ public void EmptySourceRunOnce()
+ {
+ int[] source = { };
+ Assert.Empty(source.RunOnce().Distinct());
+ }
+
+ [Fact]
public void SingleNullElementExplicitlyUseDefaultComparer()
{
string[] source = { null };
@@ -92,6 +99,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void SomeDuplicatesIncludingNullsRunOnce()
+ {
+ int?[] source = { 1, 1, 1, 2, 2, 2, null, null };
+ int?[] expected = { 1, 2, null };
+
+ Assert.Equal(expected, source.RunOnce().Distinct());
+ }
+
+ [Fact]
public void LastSameAsFirst()
{
int[] source = { 1, 2, 3, 4, 5, 1 };
@@ -111,6 +127,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RepeatsNonConsecutiveRunOnce()
+ {
+ int[] source = { 1, 1, 2, 2, 4, 3, 1, 3, 2 };
+ int[] expected = { 1, 2, 4, 3 };
+
+ Assert.Equal(expected, source.RunOnce().Distinct());
+ }
+
+ [Fact]
public void NullComparer()
{
string[] source = { "Bob", "Tim", "bBo", "miT", "Robert", "iTm" };
@@ -144,6 +169,15 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Distinct(new AnagramEqualityComparer()), new AnagramEqualityComparer());
}
+ [Fact]
+ public void CustomEqualityComparerRunOnce()
+ {
+ string[] source = { "Bob", "Tim", "bBo", "miT", "Robert", "iTm" };
+ string[] expected = { "Bob", "Tim", "Robert" };
+
+ Assert.Equal(expected, source.RunOnce().Distinct(new AnagramEqualityComparer()), new AnagramEqualityComparer());
+ }
+
[Theory, MemberData(nameof(SequencesWithDuplicates))]
public void FindDistinctAndValidate<T>(T unusedArgumentToForceTypeInference, IEnumerable<T> original)
{
diff --git a/src/System.Linq/tests/ElementAtOrDefaultTests.cs b/src/System.Linq/tests/ElementAtOrDefaultTests.cs
index 4f67298b3c..697b4c64b7 100644
--- a/src/System.Linq/tests/ElementAtOrDefaultTests.cs
+++ b/src/System.Linq/tests/ElementAtOrDefaultTests.cs
@@ -52,6 +52,13 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.ElementAtOrDefault(index));
}
+ [Theory]
+ [MemberData(nameof(TestData))]
+ public void ElementAtOrDefaultRunOnce(IEnumerable<int> source, int index, int expected)
+ {
+ Assert.Equal(expected, source.RunOnce().ElementAtOrDefault(index));
+ }
+
[Fact]
public void NullableArray_NegativeIndex_ReturnsNull()
{
diff --git a/src/System.Linq/tests/ElementAtTests.cs b/src/System.Linq/tests/ElementAtTests.cs
index ce86cb6f5d..c2421d0842 100644
--- a/src/System.Linq/tests/ElementAtTests.cs
+++ b/src/System.Linq/tests/ElementAtTests.cs
@@ -46,6 +46,13 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.ElementAt(index));
}
+ [Theory]
+ [MemberData(nameof(TestData))]
+ public void ElementAtRunOnce(IEnumerable<int> source, int index, int expected)
+ {
+ Assert.Equal(expected, source.RunOnce().ElementAt(index));
+ }
+
[Fact]
public void InvalidIndex_ThrowsArgumentOutOfRangeException()
{
diff --git a/src/System.Linq/tests/EnumerableTests.cs b/src/System.Linq/tests/EnumerableTests.cs
index 4c5540f12f..3901be878c 100644
--- a/src/System.Linq/tests/EnumerableTests.cs
+++ b/src/System.Linq/tests/EnumerableTests.cs
@@ -285,5 +285,29 @@ namespace System.Linq.Tests
e => e.Where(i => true)
};
}
+
+ protected class DelegateBasedEnumerator<T> : IEnumerator<T>
+ {
+ public Func<bool> MoveNextWorker { get; set; }
+ public Func<T> CurrentWorker { get; set; }
+ public Action DisposeWorker { get; set; }
+ public Func<object> NonGenericCurrentWorker { get; set; }
+ public Action ResetWorker { get; set; }
+
+ public T Current => CurrentWorker();
+ public bool MoveNext() => MoveNextWorker();
+ public void Dispose() => DisposeWorker();
+ void IEnumerator.Reset() => ResetWorker();
+ object IEnumerator.Current => NonGenericCurrentWorker();
+ }
+
+ protected class DelegateBasedEnumerable<T> : IEnumerable<T>
+ {
+ public Func<IEnumerator<T>> GetEnumeratorWorker { get; set; }
+ public Func<IEnumerator> NonGenericGetEnumeratorWorker { get; set; }
+
+ public IEnumerator<T> GetEnumerator() => GetEnumeratorWorker();
+ IEnumerator IEnumerable.GetEnumerator() => NonGenericGetEnumeratorWorker();
+ }
}
}
diff --git a/src/System.Linq/tests/ExceptTests.cs b/src/System.Linq/tests/ExceptTests.cs
index a9fb3db9b4..7711c0bbb4 100644
--- a/src/System.Linq/tests/ExceptTests.cs
+++ b/src/System.Linq/tests/ExceptTests.cs
@@ -87,7 +87,14 @@ namespace System.Linq.Tests
[MemberData(nameof(NullableInt_TestData))]
public void NullableInt(IEnumerable<int?> first, IEnumerable<int?> second, IEnumerable<int?> expected)
{
- Assert.Equal(expected, first.Except(second));
+ Assert.Equal(expected, first.Except(second));
+ }
+
+ [Theory]
+ [MemberData(nameof(NullableInt_TestData))]
+ public void NullableIntRunOnce(IEnumerable<int?> first, IEnumerable<int?> second, IEnumerable<int?> expected)
+ {
+ Assert.Equal(expected, first.RunOnce().Except(second.RunOnce()));
}
[Fact]
@@ -118,5 +125,22 @@ namespace System.Linq.Tests
var en = iterator as IEnumerator<int>;
Assert.False(en != null && en.MoveNext());
}
+
+ [Fact]
+ public void HashSetWithBuiltInComparer_HashSetContainsNotUsed()
+ {
+ IEnumerable<string> input1 = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "a" };
+ IEnumerable<string> input2 = new[] { "A" };
+
+ Assert.Equal(new[] { "a" }, input1.Except(input2));
+ Assert.Equal(new[] { "a" }, input1.Except(input2, null));
+ Assert.Equal(new[] { "a" }, input1.Except(input2, EqualityComparer<string>.Default));
+ Assert.Equal(Enumerable.Empty<string>(), input1.Except(input2, StringComparer.OrdinalIgnoreCase));
+
+ Assert.Equal(new[] { "A" }, input2.Except(input1));
+ Assert.Equal(new[] { "A" }, input2.Except(input1, null));
+ Assert.Equal(new[] { "A" }, input2.Except(input1, EqualityComparer<string>.Default));
+ Assert.Equal(Enumerable.Empty<string>(), input2.Except(input1, StringComparer.OrdinalIgnoreCase));
+ }
}
}
diff --git a/src/System.Linq/tests/FirstOrDefaultTests.cs b/src/System.Linq/tests/FirstOrDefaultTests.cs
index c7b2663bf4..e8aa5f9b61 100644
--- a/src/System.Linq/tests/FirstOrDefaultTests.cs
+++ b/src/System.Linq/tests/FirstOrDefaultTests.cs
@@ -37,7 +37,7 @@ namespace System.Linq.Tests
Assert.IsAssignableFrom<IList<T>>(source);
- Assert.Equal(expected, source.FirstOrDefault());
+ Assert.Equal(expected, source.RunOnce().FirstOrDefault());
}
[Fact]
@@ -94,7 +94,7 @@ namespace System.Linq.Tests
Assert.Null(source as IList<T>);
- Assert.Equal(expected, source.FirstOrDefault());
+ Assert.Equal(expected, source.RunOnce().FirstOrDefault());
}
[Fact]
@@ -178,6 +178,16 @@ namespace System.Linq.Tests
}
[Fact]
+ public void PredicateTrueForSomeRunOnce()
+ {
+ int[] source = { 3, 7, 10, 7, 9, 2, 11, 17, 13, 8 };
+ Func<int, bool> predicate = IsEven;
+ int expected = 10;
+
+ Assert.Equal(expected, source.RunOnce().FirstOrDefault(predicate));
+ }
+
+ [Fact]
public void NullSource()
{
Assert.Throws<ArgumentNullException>("source", () => ((IEnumerable<int>)null).FirstOrDefault());
diff --git a/src/System.Linq/tests/FirstTests.cs b/src/System.Linq/tests/FirstTests.cs
index fa7cebb2a5..4ec47d0325 100644
--- a/src/System.Linq/tests/FirstTests.cs
+++ b/src/System.Linq/tests/FirstTests.cs
@@ -36,7 +36,7 @@ namespace System.Linq.Tests
Assert.NotNull(source as IList<T>);
- Assert.Throws<InvalidOperationException>(() => source.First());
+ Assert.Throws<InvalidOperationException>(() => source.RunOnce().First());
}
[Fact]
@@ -92,7 +92,7 @@ namespace System.Linq.Tests
Assert.Null(source as IList<T>);
- Assert.Throws<InvalidOperationException>(() => source.First());
+ Assert.Throws<InvalidOperationException>(() => source.RunOnce().First());
}
[Fact]
@@ -175,6 +175,16 @@ namespace System.Linq.Tests
}
[Fact]
+ public void PredicateTrueForSomeRunOnce()
+ {
+ int[] source = { 3, 7, 10, 7, 9, 2, 11, 17, 13, 8 };
+ Func<int, bool> predicate = IsEven;
+ int expected = 10;
+
+ Assert.Equal(expected, source.RunOnce().First(predicate));
+ }
+
+ [Fact]
public void NullSource()
{
Assert.Throws<ArgumentNullException>("source", () => ((IEnumerable<int>)null).First());
diff --git a/src/System.Linq/tests/GroupByTests.cs b/src/System.Linq/tests/GroupByTests.cs
index 52ebdcb47b..3d0cf10c23 100644
--- a/src/System.Linq/tests/GroupByTests.cs
+++ b/src/System.Linq/tests/GroupByTests.cs
@@ -211,6 +211,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void EmptySourceRunOnce()
+ {
+ string[] key = { };
+ int[] element = { };
+ Record[] source = { };
+ Assert.Empty(new Record[] { }.RunOnce().GroupBy(e => e.Name, e => e.Score, new AnagramEqualityComparer()));
+ }
+
+ [Fact]
public void SourceIsNull()
{
Record[] source = null;
@@ -427,6 +436,24 @@ namespace System.Linq.Tests
}
[Fact]
+ public void DuplicateKeysCustomComparerRunOnce()
+ {
+ string[] key = { "Tim", "Tim", "Chris", "Chris", "Robert", "Prakash" };
+ int[] element = { 55, 25, 49, 24, -100, 9 };
+ Record[] source = {
+ new Record { Name = "Tim", Score = 55 },
+ new Record { Name = "Chris", Score = 49 },
+ new Record { Name = "Robert", Score = -100 },
+ new Record { Name = "Chris", Score = 24 },
+ new Record { Name = "Prakash", Score = 9 },
+ new Record { Name = "miT", Score = 25 }
+ };
+ long[] expected = { 240, 365, -600, 63 };
+
+ Assert.Equal(expected, source.RunOnce().GroupBy(e => e.Name, e => e.Score, (k, es) => (long)(k ?? " ").Length * es.Sum(), new AnagramEqualityComparer()));
+ }
+
+ [Fact]
public void NullComparer()
{
string[] key = { "Tim", null, null, "Robert", "Chris", "miT" };
@@ -445,6 +472,24 @@ namespace System.Linq.Tests
}
[Fact]
+ public void NullComparerRunOnce()
+ {
+ string[] key = { "Tim", null, null, "Robert", "Chris", "miT" };
+ int[] element = { 55, 49, 9, -100, 24, 25 };
+ Record[] source = {
+ new Record { Name = "Tim", Score = 55 },
+ new Record { Name = null, Score = 49 },
+ new Record { Name = "Robert", Score = -100 },
+ new Record { Name = "Chris", Score = 24 },
+ new Record { Name = null, Score = 9 },
+ new Record { Name = "miT", Score = 25 }
+ };
+ long[] expected = { 165, 58, -600, 120, 75 };
+
+ Assert.Equal(expected, source.RunOnce().GroupBy(e => e.Name, e => e.Score, (k, es) => (long)(k ?? " ").Length * es.Sum(), null));
+ }
+
+ [Fact]
public void SingleNonNullElement()
{
string[] key = { "Tim" };
diff --git a/src/System.Linq/tests/GroupJoinTests.cs b/src/System.Linq/tests/GroupJoinTests.cs
index 84a306e03b..3fa53f4cec 100644
--- a/src/System.Linq/tests/GroupJoinTests.cs
+++ b/src/System.Linq/tests/GroupJoinTests.cs
@@ -367,18 +367,18 @@ namespace System.Linq.Tests
[Fact]
public void InnerSameKeyMoreThanOneElementAndMatches()
{
- CustomerRec[] outer = new []
+ CustomerRec[] outer = new[]
{
new CustomerRec{ name = "Tim", custID = 1234 },
new CustomerRec{ name = "Bob", custID = 9865 }
};
- OrderRec[] inner = new []
+ OrderRec[] inner = new[]
{
new OrderRec{ orderID = 97865, custID = 1234, total = 25 },
new OrderRec{ orderID = 34390, custID = 1234, total = 19 },
new OrderRec{ orderID = 34390, custID = 9865, total = 19 }
};
- JoinRec[] expected = new []
+ JoinRec[] expected = new[]
{
new JoinRec { name = "Tim", orderID = new int?[]{ 97865, 34390 }, total = new int?[] { 25, 19 } },
new JoinRec { name = "Bob", orderID = new int?[]{ 34390 }, total = new int?[]{ 19 } }
@@ -388,6 +388,29 @@ namespace System.Linq.Tests
}
[Fact]
+ public void InnerSameKeyMoreThanOneElementAndMatchesRunOnce()
+ {
+ CustomerRec[] outer = new[]
+ {
+ new CustomerRec{ name = "Tim", custID = 1234 },
+ new CustomerRec{ name = "Bob", custID = 9865 }
+ };
+ OrderRec[] inner = new[]
+ {
+ new OrderRec{ orderID = 97865, custID = 1234, total = 25 },
+ new OrderRec{ orderID = 34390, custID = 1234, total = 19 },
+ new OrderRec{ orderID = 34390, custID = 9865, total = 19 }
+ };
+ JoinRec[] expected = new[]
+ {
+ new JoinRec { name = "Tim", orderID = new int?[]{ 97865, 34390 }, total = new int?[] { 25, 19 } },
+ new JoinRec { name = "Bob", orderID = new int?[]{ 34390 }, total = new int?[]{ 19 } }
+ };
+
+ Assert.Equal(expected, outer.RunOnce().GroupJoin(inner.RunOnce(), e => e.custID, e => e.custID, createJoinRec));
+ }
+
+ [Fact]
public void OuterSameKeyMoreThanOneElementAndMatches()
{
CustomerRec[] outer = new []
@@ -438,18 +461,18 @@ namespace System.Linq.Tests
[Fact]
public void NullComparer()
{
- CustomerRec[] outer = new []
+ CustomerRec[] outer = new[]
{
new CustomerRec{ name = "Tim", custID = 1234 },
new CustomerRec{ name = "Bob", custID = 9865 },
new CustomerRec{ name = "Robert", custID = 9895 }
};
- AnagramRec[] inner = new []
+ AnagramRec[] inner = new[]
{
new AnagramRec{ name = "Robert", orderID = 93483, total = 19 },
new AnagramRec{ name = "miT", orderID = 93489, total = 45 }
};
- JoinRec[] expected = new []
+ JoinRec[] expected = new[]
{
new JoinRec{ name = "Tim", orderID = new int?[]{ }, total = new int?[]{ } },
new JoinRec{ name = "Bob", orderID = new int?[]{ }, total = new int?[]{ } },
@@ -460,6 +483,30 @@ namespace System.Linq.Tests
}
[Fact]
+ public void NullComparerRunOnce()
+ {
+ CustomerRec[] outer = new[]
+ {
+ new CustomerRec{ name = "Tim", custID = 1234 },
+ new CustomerRec{ name = "Bob", custID = 9865 },
+ new CustomerRec{ name = "Robert", custID = 9895 }
+ };
+ AnagramRec[] inner = new[]
+ {
+ new AnagramRec{ name = "Robert", orderID = 93483, total = 19 },
+ new AnagramRec{ name = "miT", orderID = 93489, total = 45 }
+ };
+ JoinRec[] expected = new[]
+ {
+ new JoinRec{ name = "Tim", orderID = new int?[]{ }, total = new int?[]{ } },
+ new JoinRec{ name = "Bob", orderID = new int?[]{ }, total = new int?[]{ } },
+ new JoinRec{ name = "Robert", orderID = new int?[]{ 93483 }, total = new int?[]{ 19 } }
+ };
+
+ Assert.Equal(expected, outer.RunOnce().GroupJoin(inner.RunOnce(), e => e.name, e => e.name, createJoinRec, null));
+ }
+
+ [Fact]
public void ForcedToEnumeratorDoesntEnumerate()
{
var iterator = NumberRangeGuaranteedNotCollectionType(0, 3).GroupJoin(Enumerable.Empty<int>(), i => i, i => i, (o, i) => i);
diff --git a/src/System.Linq/tests/IntersectTests.cs b/src/System.Linq/tests/IntersectTests.cs
index 22d955c222..dde5ea3f22 100644
--- a/src/System.Linq/tests/IntersectTests.cs
+++ b/src/System.Linq/tests/IntersectTests.cs
@@ -84,6 +84,13 @@ namespace System.Linq.Tests
Assert.Equal(expected, first.Intersect(second, null));
}
+ [Theory, MemberData(nameof(NullableInt_TestData))]
+ public void NullableIntRunOnce(IEnumerable<int?> first, IEnumerable<int?> second, int?[] expected)
+ {
+ Assert.Equal(expected, first.RunOnce().Intersect(second.RunOnce()));
+ Assert.Equal(expected, first.RunOnce().Intersect(second.RunOnce(), null));
+ }
+
[Fact]
public void FirstNull_ThrowsArgumentNullException()
{
@@ -112,5 +119,22 @@ namespace System.Linq.Tests
var en = iterator as IEnumerator<int>;
Assert.False(en != null && en.MoveNext());
}
+
+ [Fact]
+ public void HashSetWithBuiltInComparer_HashSetContainsNotUsed()
+ {
+ IEnumerable<string> input1 = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "a" };
+ IEnumerable<string> input2 = new[] { "A" };
+
+ Assert.Equal(Enumerable.Empty<string>(), input1.Intersect(input2));
+ Assert.Equal(Enumerable.Empty<string>(), input1.Intersect(input2, null));
+ Assert.Equal(Enumerable.Empty<string>(), input1.Intersect(input2, EqualityComparer<string>.Default));
+ Assert.Equal(new[] { "a" }, input1.Intersect(input2, StringComparer.OrdinalIgnoreCase));
+
+ Assert.Equal(Enumerable.Empty<string>(), input2.Intersect(input1));
+ Assert.Equal(Enumerable.Empty<string>(), input2.Intersect(input1, null));
+ Assert.Equal(Enumerable.Empty<string>(), input2.Intersect(input1, EqualityComparer<string>.Default));
+ Assert.Equal(new[] { "A" }, input2.Intersect(input1, StringComparer.OrdinalIgnoreCase));
+ }
}
}
diff --git a/src/System.Linq/tests/LastOrDefaultTests.cs b/src/System.Linq/tests/LastOrDefaultTests.cs
index d8fd1cfcc1..b1363dae2b 100644
--- a/src/System.Linq/tests/LastOrDefaultTests.cs
+++ b/src/System.Linq/tests/LastOrDefaultTests.cs
@@ -37,7 +37,7 @@ namespace System.Linq.Tests
Assert.IsAssignableFrom<IList<T>>(source);
- Assert.Equal(expected, source.LastOrDefault());
+ Assert.Equal(expected, source.RunOnce().LastOrDefault());
}
[Fact]
@@ -95,7 +95,7 @@ namespace System.Linq.Tests
Assert.Null(source as IList<T>);
- Assert.Equal(expected, source.LastOrDefault());
+ Assert.Equal(expected, source.RunOnce().LastOrDefault());
}
[Fact]
@@ -179,6 +179,16 @@ namespace System.Linq.Tests
}
[Fact]
+ public void IListPredicateTrueForSomeRunOnce()
+ {
+ int[] source = { 3, 7, 10, 7, 9, 2, 11, 18, 13, 9 };
+ Func<int, bool> predicate = IsEven;
+ int expected = 18;
+
+ Assert.Equal(expected, source.RunOnce().LastOrDefault(predicate));
+ }
+
+ [Fact]
public void EmptyNotIListSource()
{
IEnumerable<int?> source = Enumerable.Repeat((int?)4, 0);
@@ -228,6 +238,16 @@ namespace System.Linq.Tests
}
[Fact]
+ public void NotIListPredicateTrueForSomeRunOnce()
+ {
+ IEnumerable<int> source = ForceNotCollection(new int[] { 3, 7, 10, 7, 9, 2, 11, 18, 13, 9 });
+ Func<int, bool> predicate = IsEven;
+ int expected = 18;
+
+ Assert.Equal(expected, source.RunOnce().LastOrDefault(predicate));
+ }
+
+ [Fact]
public void NullSource()
{
Assert.Throws<ArgumentNullException>("source", () => ((IEnumerable<int>)null).LastOrDefault());
diff --git a/src/System.Linq/tests/LastTests.cs b/src/System.Linq/tests/LastTests.cs
index b4aca3eeed..b8864d9ff4 100644
--- a/src/System.Linq/tests/LastTests.cs
+++ b/src/System.Linq/tests/LastTests.cs
@@ -36,7 +36,7 @@ namespace System.Linq.Tests
Assert.NotNull(source as IList<T>);
- Assert.Throws<InvalidOperationException>(() => source.Last());
+ Assert.Throws<InvalidOperationException>(() => source.RunOnce().Last());
}
[Fact]
@@ -92,7 +92,7 @@ namespace System.Linq.Tests
Assert.Null(source as IList<T>);
- Assert.Throws<InvalidOperationException>(() => source.Last());
+ Assert.Throws<InvalidOperationException>(() => source.RunOnce().Last());
}
[Fact]
@@ -175,6 +175,16 @@ namespace System.Linq.Tests
}
[Fact]
+ public void IListPredicateTrueForSomeRunOnce()
+ {
+ int[] source = { 3, 7, 10, 7, 9, 2, 11, 18, 13, 9 };
+ Func<int, bool> predicate = IsEven;
+ int expected = 18;
+
+ Assert.Equal(expected, source.RunOnce().Last(predicate));
+ }
+
+ [Fact]
public void NotIListIListEmptySourcePredicate()
{
IEnumerable<int> source = Enumerable.Range(1, 0);
@@ -223,6 +233,16 @@ namespace System.Linq.Tests
}
[Fact]
+ public void NotIListPredicateTrueForSomeRunOnce()
+ {
+ IEnumerable<int> source = ForceNotCollection(new int[] { 3, 7, 10, 7, 9, 2, 11, 18, 13, 9 });
+ Func<int, bool> predicate = IsEven;
+ int expected = 18;
+
+ Assert.Equal(expected, source.RunOnce().Last(predicate));
+ }
+
+ [Fact]
public void NullSource()
{
Assert.Throws<ArgumentNullException>("source", () => ((IEnumerable<int>)null).Last());
diff --git a/src/System.Linq/tests/LongCountTests.cs b/src/System.Linq/tests/LongCountTests.cs
index 9a0faa3e65..dbbf2b6d44 100644
--- a/src/System.Linq/tests/LongCountTests.cs
+++ b/src/System.Linq/tests/LongCountTests.cs
@@ -56,6 +56,20 @@ namespace System.Linq.Tests
}
}
+ [Theory]
+ [MemberData(nameof(LongCount_TestData))]
+ public static void LongCountRunOnce(IEnumerable<int> source, Func<int, bool> predicate, long expected)
+ {
+ if (predicate == null)
+ {
+ Assert.Equal(expected, source.RunOnce().LongCount());
+ }
+ else
+ {
+ Assert.Equal(expected, source.RunOnce().LongCount(predicate));
+ }
+ }
+
[Fact]
public void NullableArray_IncludesNullValues()
{
diff --git a/src/System.Linq/tests/MaxTests.cs b/src/System.Linq/tests/MaxTests.cs
index 908dd3d251..8d06f5856b 100644
--- a/src/System.Linq/tests/MaxTests.cs
+++ b/src/System.Linq/tests/MaxTests.cs
@@ -308,6 +308,13 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Max(x => x));
}
+ [Theory, MemberData(nameof(Max_NullableInt_TestData))]
+ public void Max_NullableIntRunOnce(IEnumerable<int?> source, int? expected)
+ {
+ Assert.Equal(expected, source.RunOnce().Max());
+ Assert.Equal(expected, source.RunOnce().Max(x => x));
+ }
+
[Fact]
public void Max_NullableInt_NullSource_ThrowsArgumentNullException()
{
@@ -522,6 +529,13 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Max(x => x));
}
+ [Theory, MemberData(nameof(Max_String_TestData))]
+ public void Max_StringRunOnce(IEnumerable<string> source, string expected)
+ {
+ Assert.Equal(expected, source.RunOnce().Max());
+ Assert.Equal(expected, source.RunOnce().Max(x => x));
+ }
+
[Fact]
public void Max_String_NullSource_ThrowsArgumentNullException()
{
diff --git a/src/System.Linq/tests/MinTests.cs b/src/System.Linq/tests/MinTests.cs
index 92f1ec671a..abd7e31184 100644
--- a/src/System.Linq/tests/MinTests.cs
+++ b/src/System.Linq/tests/MinTests.cs
@@ -270,6 +270,12 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Min());
}
+ [Theory, MemberData(nameof(Min_NullableInt_TestData))]
+ public void Min_NullableIntRunOnce(IEnumerable<int?> source, int? expected)
+ {
+ Assert.Equal(expected, source.RunOnce().Min());
+ }
+
[Fact]
public void Min_NullableInt_NullSource_ThrowsArgumentNullException()
{
@@ -482,6 +488,13 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.Min(x => x));
}
+ [Theory, MemberData(nameof(Min_String_TestData))]
+ public void Min_StringRunOnce(IEnumerable<string> source, string expected)
+ {
+ Assert.Equal(expected, source.RunOnce().Min());
+ Assert.Equal(expected, source.RunOnce().Min(x => x));
+ }
+
[Fact]
public void Min_String_NullSource_ThrowsArgumentNullException()
{
diff --git a/src/System.Linq/tests/OfTypeTests.cs b/src/System.Linq/tests/OfTypeTests.cs
index e2b57a8815..67992d0f51 100644
--- a/src/System.Linq/tests/OfTypeTests.cs
+++ b/src/System.Linq/tests/OfTypeTests.cs
@@ -80,6 +80,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ object[] source = { 3.5m, -4, "Test", "Check", 4, 8.0, 10.5, 9 };
+ int[] expected = { -4, 4, 9 };
+
+ Assert.Equal(expected, source.RunOnce().OfType<int>());
+ }
+
+ [Fact]
public void IntFromNullableInt()
{
int[] source = { -4, 4, 9 };
diff --git a/src/System.Linq/tests/OrderByDescendingTests.cs b/src/System.Linq/tests/OrderByDescendingTests.cs
index 0a8976bb30..4876113983 100644
--- a/src/System.Linq/tests/OrderByDescendingTests.cs
+++ b/src/System.Linq/tests/OrderByDescendingTests.cs
@@ -88,6 +88,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ string[] source = { "Prakash", "Alpha", "DAN", "dan", "Prakash" };
+ string[] expected = { "Prakash", "Prakash", "DAN", "dan", "Alpha" };
+
+ Assert.Equal(expected, source.RunOnce().OrderByDescending(e => e, StringComparer.OrdinalIgnoreCase));
+ }
+
+ [Fact]
public void FirstAndLastAreDuplicatesNullPassedAsComparer()
{
int[] source = { 5, 1, 3, 2, 5 };
diff --git a/src/System.Linq/tests/OrderByTests.cs b/src/System.Linq/tests/OrderByTests.cs
index 6253b27db2..9dbff46c38 100644
--- a/src/System.Linq/tests/OrderByTests.cs
+++ b/src/System.Linq/tests/OrderByTests.cs
@@ -118,6 +118,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ string[] source = { "Prakash", "Alpha", "dan", "DAN", "Prakash" };
+ string[] expected = { "Alpha", "dan", "DAN", "Prakash", "Prakash" };
+
+ Assert.Equal(expected, source.RunOnce().OrderBy(e => e, StringComparer.OrdinalIgnoreCase));
+ }
+
+ [Fact]
public void FirstAndLastAreDuplicatesNullPassedAsComparer()
{
int[] source = { 5, 1, 3, 2, 5 };
@@ -297,6 +306,16 @@ namespace System.Linq.Tests
}
[Fact]
+ public void LastOnOrderedMatchingCases()
+ {
+ object[] boxedInts = new object[] {0, 1, 2, 9, 1, 2, 3, 9, 4, 5, 7, 8, 9, 0, 1};
+ Assert.Same(boxedInts[12], boxedInts.OrderBy(o => (int)o).Last());
+ Assert.Same(boxedInts[12], boxedInts.OrderBy(o => (int)o).LastOrDefault());
+ Assert.Same(boxedInts[12], boxedInts.OrderBy(o => (int)o).Last(o => (int)o % 2 == 1));
+ Assert.Same(boxedInts[12], boxedInts.OrderBy(o => (int)o).LastOrDefault(o => (int)o % 2 == 1));
+ }
+
+ [Fact]
public void LastOnEmptyOrderedThrows()
{
Assert.Throws<InvalidOperationException>(() => Enumerable.Empty<int>().OrderBy(i => i).Last());
@@ -318,5 +337,45 @@ namespace System.Linq.Tests
while (enumerator.MoveNext()) { }
Assert.False(enumerator.MoveNext());
}
+
+ [Fact]
+ public void OrderByIsCovariantTestWithCast()
+ {
+ var ordered = Enumerable.Range(0, 100).Select(i => i.ToString()).OrderBy(i => i.Length);
+ IOrderedEnumerable<IComparable> covariantOrdered = ordered;
+ covariantOrdered = covariantOrdered.ThenBy(i => i);
+ string[] expected =
+ Enumerable.Range(0, 100).Select(i => i.ToString()).OrderBy(i => i.Length).ThenBy(i => i).ToArray();
+ Assert.Equal(expected, covariantOrdered);
+ }
+
+ [Fact]
+ public void OrderByIsCovariantTestWithAssignToArgument()
+ {
+ var ordered = Enumerable.Range(0, 100).Select(i => i.ToString()).OrderBy(i => i.Length);
+ IOrderedEnumerable<IComparable> covariantOrdered = ordered.ThenByDescending<IComparable, IComparable>(i => i);
+ string[] expected = Enumerable.Range(0, 100)
+ .Select(i => i.ToString())
+ .OrderBy(i => i.Length)
+ .ThenByDescending(i => i)
+ .ToArray();
+ Assert.Equal(expected, covariantOrdered);
+ }
+
+ [Fact]
+ public void CanObtainFromCovariantIOrderedQueryable()
+ {
+ // If an ordered queryable is cast covariantly and then has ThenBy() called on it,
+ // it depends on IOrderedEnumerable<TElement> also being covariant to allow for
+ // that ThenBy() to be processed within Linq-to-objects, as otherwise there is no
+ // equivalent ThenBy() overload to translate the call to.
+
+ IOrderedQueryable<IComparable> ordered =
+ Enumerable.Range(0, 100).AsQueryable().Select(i => i.ToString()).OrderBy(i => i.Length);
+ ordered = ordered.ThenBy(i => i);
+ string[] expected =
+ Enumerable.Range(0, 100).Select(i => i.ToString()).OrderBy(i => i.Length).ThenBy(i => i).ToArray();
+ Assert.Equal(expected, ordered);
+ }
}
}
diff --git a/src/System.Linq/tests/OrderedSubsetting.cs b/src/System.Linq/tests/OrderedSubsetting.cs
index 3d585df908..0187e88d5f 100644
--- a/src/System.Linq/tests/OrderedSubsetting.cs
+++ b/src/System.Linq/tests/OrderedSubsetting.cs
@@ -470,5 +470,19 @@ namespace System.Linq.Tests
source = Enumerable.Range(0, 9).Shuffle().OrderBy(i => i).Skip(1).Take(1000).Select(i => i * 2);
Assert.Equal(8, source.Count());
}
+
+ [Fact]
+ public void RunOnce()
+ {
+ var source = Enumerable.Range(0, 100).Shuffle().ToArray();
+ Assert.Equal(Enumerable.Range(30, 20), source.RunOnce().OrderBy(i => i).Skip(20).Skip(10).Take(50).Take(20));
+ Assert.Empty(source.RunOnce().OrderBy(i => i).Skip(10).Take(9).Take(0));
+ Assert.Equal(20, source.RunOnce().OrderBy(i => i).Skip(20).Take(60).First());
+ Assert.Equal(79, source.RunOnce().OrderBy(i => i).Skip(20).Take(60).Last());
+ Assert.Equal(93, source.RunOnce().OrderBy(i => i).ElementAt(93));
+ Assert.Equal(42, source.RunOnce().OrderBy(i => i).ElementAtOrDefault(42));
+ Assert.Equal(20, source.RunOnce().OrderBy(i => i).Skip(10).Take(20).Count());
+ Assert.Equal(1, source.RunOnce().OrderBy(i => i).Take(2).Skip(1).Count());
+ }
}
}
diff --git a/src/System.Linq/tests/ReverseTests.cs b/src/System.Linq/tests/ReverseTests.cs
index 1d7ab287ae..c8b9cb6048 100644
--- a/src/System.Linq/tests/ReverseTests.cs
+++ b/src/System.Linq/tests/ReverseTests.cs
@@ -16,84 +16,66 @@ namespace System.Linq.Tests
}
[Theory]
- [InlineData(new int[] { })]
- [InlineData(new int[] { 1 })]
- [InlineData(new int[] { 5 })]
- [InlineData(new int[] { 1, 3, 5 })]
- [InlineData(new int[] { 2, 4, 6, 8 })]
- public void ReverseMatches(int[] input)
+ [MemberData(nameof(ReverseData))]
+ public void Reverse<T>(IEnumerable<T> source, T dummy)
{
- int[] expectedResults = new int[input.Length];
- for (int i = 0; i < input.Length; i++)
- {
- expectedResults[i] = input[input.Length - 1 - i];
- }
+ T[] expected = source.ToArray();
+ Array.Reverse(expected);
- Assert.NotSame(input, Enumerable.Reverse(input));
+ IEnumerable<T> actual = source.Reverse();
- Assert.Equal(expectedResults, input.Reverse());
- Assert.Equal(expectedResults, new TestCollection<int>(input).Reverse());
- Assert.Equal(expectedResults, new TestEnumerable<int>(input).Reverse());
- Assert.Equal(expectedResults, new TestReadOnlyCollection<int>(input).Reverse());
+ Assert.Equal(expected, actual);
+ Assert.Equal(expected.Count(), actual.Count()); // Count may be optimized.
+ Assert.Equal(expected, actual.ToArray());
+ Assert.Equal(expected, actual.ToList());
- Assert.Equal(expectedResults.Select(i => i * 2), input.Select(i => i * 2).Reverse());
- Assert.Equal(expectedResults.Where(i => true).Select(i => i * 2), input.Where(i => true).Select(i => i * 2).Reverse());
- Assert.Equal(expectedResults.Where(i => false).Select(i => i * 2), input.Where(i => false).Select(i => i * 2).Reverse());
- }
+ Assert.Equal(expected.FirstOrDefault(), actual.FirstOrDefault());
+ Assert.Equal(expected.LastOrDefault(), actual.LastOrDefault());
- [Fact]
- public void SameResultsRepeatCallsIntQuery()
- {
- var q = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 }
- where x > Int32.MinValue
- select x;
-
- Assert.Equal(q.Reverse(), q.Reverse());
- }
+ for (int i = 0; i < expected.Length; i++)
+ {
+ Assert.Equal(expected[i], actual.ElementAt(i));
- [Fact]
- public void SameResultsRepeatCallsStringQuery()
- {
- var q = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty }
- where !String.IsNullOrEmpty(x)
- select x;
+ Assert.Equal(expected.Skip(i), actual.Skip(i));
+ Assert.Equal(expected.Take(i), actual.Take(i));
+ }
- Assert.Equal(q.Reverse(), q.Reverse());
- }
+ Assert.Equal(default(T), actual.ElementAtOrDefault(-1));
+ Assert.Equal(default(T), actual.ElementAtOrDefault(expected.Length));
- [Fact]
- public void SomeRepeatedElements()
- {
- int?[] source = new int?[] { -10, 0, 5, null, 0, 9, 100, null, 9 };
- int?[] expected = new int?[] { 9, null, 100, 9, 0, null, 5, 0, -10 };
+ Assert.Equal(expected, actual.Select(_ => _));
+ Assert.Equal(expected, actual.Where(_ => true));
- Assert.Equal(expected, source.Reverse());
+ Assert.Equal(actual, actual); // Repeat the enumeration against itself.
}
- [Fact]
- public void ToArray()
+ [Theory, MemberData(nameof(ReverseData))]
+ public void RunOnce<T>(IEnumerable<T> source, T dummy)
{
- int?[] source = new int?[] { -10, 0, 5, null, 0, 9, 100, null, 9 };
- int?[] expected = new int?[] { 9, null, 100, 9, 0, null, 5, 0, -10 };
+ T[] expected = source.ToArray();
+ Array.Reverse(expected);
- Assert.Equal(expected, source.Reverse().ToArray());
- }
+ IEnumerable<T> actual = source.RunOnce().Reverse();
- [Fact]
- public void ToList()
- {
- int?[] source = new int?[] { -10, 0, 5, null, 0, 9, 100, null, 9 };
- int?[] expected = new int?[] { 9, null, 100, 9, 0, null, 5, 0, -10 };
-
- Assert.Equal(expected, source.Reverse().ToList());
+ Assert.Equal(expected, actual);
}
- [Fact]
- public void Count()
+ public static IEnumerable<object[]> ReverseData()
{
- int?[] source = new int?[] { -10, 0, 5, null, 0, 9, 100, null, 9 };
-
- Assert.Equal(9, source.Reverse().Count());
+ var integers = new[]
+ {
+ Array.Empty<int>(), // No elements.
+ new[] { 1 }, // One element.
+ new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 }, // Distinct elements.
+ new[] { -10, 0, 5, 0, 9, 100, 9 }, // Some repeating elements.
+ };
+
+ // TODO: Remove workarounds when xUnit is updated to include xunit/xunit#965.
+ return integers
+ .Select(collection => new object[] { collection, 0 })
+ .Concat(
+ integers.Select(c => new object[] { c.Select(i => i.ToString()), string.Empty })
+ );
}
[Fact]
@@ -104,13 +86,5 @@ namespace System.Linq.Tests
var en = iterator as IEnumerator<int>;
Assert.False(en != null && en.MoveNext());
}
-
- [Fact]
- public void RepeatEnumerating()
- {
- var reverse = new int?[] { -10, 0, 5, null, 0, 9, 100, null, 9 }.Reverse();
-
- Assert.Equal(reverse, reverse);
- }
}
}
diff --git a/src/System.Linq/tests/SelectManyTests.cs b/src/System.Linq/tests/SelectManyTests.cs
index d9bd553b7e..44e21dc9f4 100644
--- a/src/System.Linq/tests/SelectManyTests.cs
+++ b/src/System.Linq/tests/SelectManyTests.cs
@@ -122,6 +122,21 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ StringWithIntArray[] source =
+ {
+ new StringWithIntArray { name="Prakash", total=new int?[]{1, 2, 3, 4} },
+ new StringWithIntArray { name="Bob", total=new int?[]{5, 6} },
+ new StringWithIntArray { name="Chris", total=new int?[0] },
+ new StringWithIntArray { name=null, total=new int?[]{8, 9} },
+ new StringWithIntArray { name="Prakash", total=new int?[]{-10, 100} }
+ };
+ int?[] expected = { 1, 2, 3, 4, 5, 6, 8, 9, -10, 100 };
+ Assert.Equal(expected, source.RunOnce().SelectMany(e => e.total.RunOnce()));
+ }
+
+ [Fact]
public void SourceEmptyIndexUsed()
{
Assert.Empty(Enumerable.Empty<StringWithIntArray>().SelectMany((e, index) => e.total));
@@ -360,5 +375,121 @@ namespace System.Linq.Tests
var en = iterator as IEnumerator<int>;
Assert.False(en != null && en.MoveNext());
}
+
+ [Theory]
+ [MemberData(nameof(ParameterizedTestsData))]
+ public void ParameterizedTests(IEnumerable<int> source, Func<int, IEnumerable<int>> selector)
+ {
+ var expected = source.Select(i => selector(i)).Aggregate((l, r) => l.Concat(r));
+ var actual = source.SelectMany(selector);
+
+ Assert.Equal(expected, actual);
+ Assert.Equal(expected.Count(), actual.Count()); // SelectMany may employ an optimized Count implementation.
+ Assert.Equal(expected.ToArray(), actual.ToArray());
+ Assert.Equal(expected.ToList(), actual.ToList());
+ }
+
+ public static IEnumerable<object[]> ParameterizedTestsData()
+ {
+ for (int i = 1; i <= 20; i++)
+ {
+ Func<int, IEnumerable<int>> selector = n => Enumerable.Range(i, n);
+ yield return new object[] { Enumerable.Range(1, i), selector };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(DisposeAfterEnumerationData))]
+ public void DisposeAfterEnumeration(int sourceLength, int subLength)
+ {
+ int sourceState = 0;
+ int subIndex = 0; // Index within the arrays the sub-collection is supposed to be at.
+ int[] subState = new int[sourceLength];
+
+ bool sourceDisposed = false;
+ bool[] subCollectionDisposed = new bool[sourceLength];
+
+ var sourceEnumerator = new DelegateBasedEnumerator<int>
+ {
+ MoveNextWorker = () => ++sourceState <= sourceLength,
+ CurrentWorker = () => 0,
+ DisposeWorker = () => sourceDisposed = true
+ };
+
+ var source = new DelegateBasedEnumerable<int>
+ {
+ GetEnumeratorWorker = () => sourceEnumerator
+ };
+
+ var subEnumerator = new DelegateBasedEnumerator<int>
+ {
+ // MoveNext: Return true subLength times.
+ // Dispose: Record that Dispose was called & move to the next index.
+ MoveNextWorker = () => ++subState[subIndex] <= subLength,
+ CurrentWorker = () => subState[subIndex],
+ DisposeWorker = () => subCollectionDisposed[subIndex++] = true
+ };
+
+ var subCollection = new DelegateBasedEnumerable<int>
+ {
+ GetEnumeratorWorker = () => subEnumerator
+ };
+
+ var iterator = source.SelectMany(_ => subCollection);
+
+ int index = 0; // How much have we gone into the iterator?
+ IEnumerator<int> e = iterator.GetEnumerator();
+
+ using (e)
+ {
+ while (e.MoveNext())
+ {
+ int item = e.Current;
+
+ Assert.Equal(subState[subIndex], item); // Verify Current.
+ Assert.Equal(index / subLength, subIndex);
+
+ Assert.False(sourceDisposed); // Not yet.
+
+ // This represents whehter the sub-collection we're iterating thru right now
+ // has been disposed. Also not yet.
+ Assert.False(subCollectionDisposed[subIndex]);
+
+ // However, all of the sub-collections before us should have been disposed.
+ // Their indices should also be maxed out.
+ Assert.All(subState.Take(subIndex), s => Assert.Equal(subLength + 1, s));
+ Assert.All(subCollectionDisposed.Take(subIndex), t => Assert.True(t));
+
+ index++;
+ }
+ }
+
+ Assert.True(sourceDisposed);
+ Assert.Equal(sourceLength, subIndex);
+ Assert.All(subState, s => Assert.Equal(subLength + 1, s));
+ Assert.All(subCollectionDisposed, t => Assert.True(t));
+
+ // Make sure the iterator's enumerator has been disposed properly.
+ Assert.Equal(0, e.Current); // Default value.
+ Assert.False(e.MoveNext());
+ Assert.Equal(0, e.Current);
+ }
+
+ public static IEnumerable<object[]> DisposeAfterEnumerationData()
+ {
+ int[] lengths = { 1, 2, 3, 5, 8, 13, 21, 34 };
+
+ return lengths.SelectMany(l => lengths, (l1, l2) => new object[] { l1, l2 });
+ }
+
+ [Theory]
+ [InlineData(new[] { int.MaxValue, 1 })]
+ [InlineData(new[] { 2, int.MaxValue - 1 })]
+ [InlineData(new[] { 123, 456, int.MaxValue - 100000, 123456 })]
+ public void ThrowOverflowExceptionOnConstituentLargeCounts(int[] counts)
+ {
+ var iterator = counts.SelectMany(c => Enumerable.Range(1, c));
+ Assert.Throws<OverflowException>(() => iterator.Count());
+ }
}
}
diff --git a/src/System.Linq/tests/SelectTests.cs b/src/System.Linq/tests/SelectTests.cs
index 8fac6397f7..2714ab8639 100644
--- a/src/System.Linq/tests/SelectTests.cs
+++ b/src/System.Linq/tests/SelectTests.cs
@@ -55,6 +55,22 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ var source = new[]{
+ new { name="Prakash", custID=98088 },
+ new { name="Bob", custID=29099 },
+ new { name="Chris", custID=39033 },
+ new { name=(string)null, custID=30349 },
+ new { name="Prakash", custID=39030 }
+ };
+ string[] expected = { "Prakash", "Bob", "Chris", null, "Prakash" };
+ Assert.Equal(expected, source.RunOnce().Select(e => e.name));
+ Assert.Equal(expected, source.ToArray().RunOnce().Select(e => e.name));
+ Assert.Equal(expected, source.ToList().RunOnce().Select(e => e.name));
+ }
+
+ [Fact]
public void EmptyWithIndexedSelector()
{
Assert.Equal(Enumerable.Empty<int>(), Enumerable.Empty<string>().Select((s, i) => s.Length + i));
@@ -1152,5 +1168,65 @@ namespace System.Linq.Tests
yield return new object[] { new int[1] };
yield return new object[] { Enumerable.Range(1, 30) };
}
+
+ [Theory]
+ [MemberData(nameof(RunSelectorDuringCountData))]
+ public void RunSelectorDuringCount(IEnumerable<int> source)
+ {
+ int timesRun = 0;
+ var selected = source.Select(i => timesRun++);
+ selected.Count();
+
+ Assert.Equal(source.Count(), timesRun);
+ }
+
+ // [Theory]
+ [MemberData(nameof(RunSelectorDuringCountData))]
+ public void RunSelectorDuringPartitionCount(IEnumerable<int> source)
+ {
+ int timesRun = 0;
+
+ var selected = source.Select(i => timesRun++);
+
+ if (source.Any())
+ {
+ selected.Skip(1).Count();
+ Assert.Equal(source.Count() - 1, timesRun);
+
+ selected.Take(source.Count() - 1).Count();
+ Assert.Equal(source.Count() * 2 - 2, timesRun);
+ }
+ }
+
+ public static IEnumerable<object[]> RunSelectorDuringCountData()
+ {
+ var transforms = new Func<IEnumerable<int>, IEnumerable<int>>[]
+ {
+ e => e,
+ e => ForceNotCollection(e),
+ e => ForceNotCollection(e).Skip(1),
+ e => ForceNotCollection(e).Where(i => true),
+ e => e.ToArray().Where(i => true),
+ e => e.ToList().Where(i => true),
+ e => new LinkedList<int>(e).Where(i => true),
+ e => e.Select(i => i),
+ e => e.Take(e.Count()),
+ e => e.ToArray(),
+ e => e.ToList(),
+ e => new LinkedList<int>(e) // Implements IList<T>.
+ };
+
+ var r = new Random(unchecked((int)0x984bf1a3));
+
+ for (int i = 0; i <= 5; i++)
+ {
+ var enumerable = Enumerable.Range(1, i).Select(_ => r.Next());
+
+ foreach (var transform in transforms)
+ {
+ yield return new object[] { transform(enumerable) };
+ }
+ }
+ }
}
}
diff --git a/src/System.Linq/tests/SequenceEqualTests.cs b/src/System.Linq/tests/SequenceEqualTests.cs
index 5c98830cda..8426455b40 100644
--- a/src/System.Linq/tests/SequenceEqualTests.cs
+++ b/src/System.Linq/tests/SequenceEqualTests.cs
@@ -81,6 +81,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ string[] first = { "Bob", "Tim", "Chris" };
+ string[] second = { "Bbo", "mTi", "rishC" };
+
+ Assert.True(first.RunOnce().SequenceEqual(second.RunOnce(), new AnagramEqualityComparer()));
+ }
+
+ [Fact]
public void BothSingleNullExplicitComparer()
{
string[] first = { null };
diff --git a/src/System.Linq/tests/SingleOrDefaultTests.cs b/src/System.Linq/tests/SingleOrDefaultTests.cs
index 6a9971fd87..021121f43e 100644
--- a/src/System.Linq/tests/SingleOrDefaultTests.cs
+++ b/src/System.Linq/tests/SingleOrDefaultTests.cs
@@ -140,7 +140,15 @@ namespace System.Linq.Tests
{
Assert.Equal(target, Enumerable.Range(0, range).SingleOrDefault(i => i == target));
}
-
+
+ [Theory]
+ [InlineData(1, 100)]
+ [InlineData(42, 100)]
+ public void RunOnce(int target, int range)
+ {
+ Assert.Equal(target, Enumerable.Range(0, range).RunOnce().SingleOrDefault(i => i == target));
+ }
+
[Fact]
public void ThrowsOnNullSource()
{
diff --git a/src/System.Linq/tests/SingleTests.cs b/src/System.Linq/tests/SingleTests.cs
index ec6a04fe2c..7de92a49e2 100644
--- a/src/System.Linq/tests/SingleTests.cs
+++ b/src/System.Linq/tests/SingleTests.cs
@@ -144,7 +144,15 @@ namespace System.Linq.Tests
{
Assert.Equal(target, Enumerable.Range(0, range).Single(i => i == target));
}
-
+
+ [Theory]
+ [InlineData(1, 100)]
+ [InlineData(42, 100)]
+ public void RunOnce(int target, int range)
+ {
+ Assert.Equal(target, Enumerable.Range(0, range).RunOnce().Single(i => i == target));
+ }
+
[Fact]
public void ThrowsOnNullSource()
{
diff --git a/src/System.Linq/tests/SkipTests.cs b/src/System.Linq/tests/SkipTests.cs
index d730e9d72f..be7289ffe6 100644
--- a/src/System.Linq/tests/SkipTests.cs
+++ b/src/System.Linq/tests/SkipTests.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Reflection;
using Xunit;
using Xunit.Abstractions;
@@ -29,6 +30,13 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ Assert.Equal(Enumerable.Range(10, 10), Enumerable.Range(0, 20).RunOnce().Skip(10));
+ Assert.Equal(Enumerable.Range(10, 10), Enumerable.Range(0, 20).ToList().RunOnce().Skip(10));
+ }
+
+ [Fact]
public void SkipNone()
{
Assert.Equal(Enumerable.Range(0, 20), NumberRangeGuaranteedNotCollectionType(0, 20).Skip(0));
@@ -456,5 +464,49 @@ namespace System.Linq.Tests
var remaining = source.Skip(1);
Assert.Equal(remaining, remaining);
}
+
+ [Fact]
+ public void LazySkipMoreThan32Bits()
+ {
+ var range = NumberRangeGuaranteedNotCollectionType(1, 100);
+ var skipped = range.Skip(50).Skip(int.MaxValue); // Could cause an integer overflow.
+ Assert.Empty(skipped);
+ Assert.Equal(0, skipped.Count());
+ Assert.Empty(skipped.ToArray());
+ Assert.Empty(skipped.ToList());
+ }
+
+ [Fact]
+ public void IteratorStateShouldNotChangeIfNumberOfElementsIsUnbounded()
+ {
+ // With https://github.com/dotnet/corefx/pull/13628, Skip and Take return
+ // the same type of iterator. For Take, there is a limit, or upper bound,
+ // on how many items can be returned from the iterator. An integer field,
+ // _state, is incremented to keep track of this and to stop enumerating once
+ // we pass that limit. However, for Skip, there is no such limit and the
+ // iterator can contain an unlimited number of items (including past int.MaxValue).
+
+ // This test makes sure that, in Skip, _state is not incorrectly incremented,
+ // so that it does not overflow to a negative number and enumeration does not
+ // stop prematurely.
+
+ var iterator = new FastInfiniteEnumerator<int>().Skip(1).GetEnumerator();
+ iterator.MoveNext(); // Make sure the underlying enumerator has been initialized.
+
+ FieldInfo state = iterator.GetType().GetTypeInfo()
+ .GetField("_state", BindingFlags.Instance | BindingFlags.NonPublic);
+
+ // On platforms that do not have this change, the optimization may not be present
+ // and the iterator may not have a field named _state. In that case, nop.
+ if (state != null)
+ {
+ state.SetValue(iterator, int.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ Assert.True(iterator.MoveNext());
+ }
+ }
+ }
}
}
diff --git a/src/System.Linq/tests/SkipWhileTests.cs b/src/System.Linq/tests/SkipWhileTests.cs
index 58e47ae830..0ab5440186 100644
--- a/src/System.Linq/tests/SkipWhileTests.cs
+++ b/src/System.Linq/tests/SkipWhileTests.cs
@@ -43,7 +43,7 @@ namespace System.Linq.Tests
Assert.Throws<DivideByZeroException>(() => en.MoveNext());
}
}
-
+
[Fact]
public void SkipWhileHalf()
{
@@ -52,6 +52,13 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ Assert.Equal(Enumerable.Range(10, 10), Enumerable.Range(0, 20).RunOnce().SkipWhile(i => i < 10));
+ Assert.Equal(Enumerable.Range(10, 10), Enumerable.Range(0, 20).RunOnce().SkipWhile((i, idx) => idx < 10));
+ }
+
+ [Fact]
public void SkipErrorWhenSourceErrors()
{
var source = NumberRangeGuaranteedNotCollectionType(-2, 5).Select(i => (decimal)i).Select(m => 1 / m).Skip(4);
diff --git a/src/System.Linq/tests/SumTests.cs b/src/System.Linq/tests/SumTests.cs
index d80d5c7abe..47353f7634 100644
--- a/src/System.Linq/tests/SumTests.cs
+++ b/src/System.Linq/tests/SumTests.cs
@@ -549,6 +549,18 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ var source = new[]
+ {
+ new { name="Tim", num=(int?)10 },
+ new { name="John", num=default(int?) },
+ new { name="Bob", num=(int?)-30 }
+ };
+ Assert.Equal(-20, source.RunOnce().Sum(e => e.num));
+ }
+
+ [Fact]
public void SolitaryInt64()
{
long[] source = { int.MaxValue + 20L };
diff --git a/src/System.Linq/tests/System.Linq.Tests.csproj b/src/System.Linq/tests/System.Linq.Tests.csproj
index b35a88bca8..4a3eb15763 100644
--- a/src/System.Linq/tests/System.Linq.Tests.csproj
+++ b/src/System.Linq/tests/System.Linq.Tests.csproj
@@ -58,6 +58,7 @@
<Compile Include="SumTests.cs" />
<Compile Include="TakeTests.cs" />
<Compile Include="TakeWhileTests.cs" />
+ <Compile Include="TestExtensions.cs" />
<Compile Include="ThenByDescendingTests.cs" />
<Compile Include="ThenByTests.cs" />
<Compile Include="ToArrayTests.cs" />
diff --git a/src/System.Linq/tests/TakeTests.cs b/src/System.Linq/tests/TakeTests.cs
index 3506ef786c..3769f9c666 100644
--- a/src/System.Linq/tests/TakeTests.cs
+++ b/src/System.Linq/tests/TakeTests.cs
@@ -142,6 +142,15 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ int[] source = { 2, 5, 9, 1 };
+ int[] expected = { 2, 5, 9 };
+
+ Assert.Equal(expected, source.RunOnce().Take(3));
+ }
+
+ [Fact]
public void SourceNonEmptyTakeAllButOneNotIList()
{
var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 });
@@ -450,5 +459,80 @@ namespace System.Linq.Tests
var taken = source.Take(3);
Assert.Equal(taken, taken);
}
+
+ [Theory]
+ [InlineData(1000)]
+ [InlineData(1000000)]
+ [InlineData(int.MaxValue)]
+ public void LazySkipAllTakenForLargeNumbers(int largeNumber)
+ {
+ Assert.Empty(new FastInfiniteEnumerator<int>().Take(largeNumber).Skip(largeNumber));
+ Assert.Empty(new FastInfiniteEnumerator<int>().Take(largeNumber).Skip(largeNumber).Skip(42));
+ Assert.Empty(new FastInfiniteEnumerator<int>().Take(largeNumber).Skip(largeNumber / 2).Skip(largeNumber / 2 + 1));
+ }
+
+ [Fact]
+ public void LazyOverflowRegression()
+ {
+ var range = NumberRangeGuaranteedNotCollectionType(1, 100);
+ var skipped = range.Skip(42); // Min index is 42.
+ var taken = skipped.Take(int.MaxValue); // May try to calculate max index as 42 + int.MaxValue, leading to integer overflow.
+ Assert.Equal(Enumerable.Range(43, 100 - 42), taken);
+ Assert.Equal(100 - 42, taken.Count());
+ Assert.Equal(Enumerable.Range(43, 100 - 42), taken.ToArray());
+ Assert.Equal(Enumerable.Range(43, 100 - 42), taken.ToList());
+ }
+
+ [Theory]
+ [InlineData(0, 0, 0)]
+ [InlineData(1, 1, 1)]
+ [InlineData(0, int.MaxValue, 100)]
+ [InlineData(int.MaxValue, 0, 0)]
+ [InlineData(0xffff, 1, 0)]
+ [InlineData(1, 0xffff, 99)]
+ [InlineData(int.MaxValue, int.MaxValue, 0)]
+ [InlineData(1, int.MaxValue, 99)] // Regression test: The max index is precisely int.MaxValue.
+ [InlineData(0, 100, 100)]
+ [InlineData(10, 100, 90)]
+ public void CountOfLazySkipTakeChain(int skip, int take, int expected)
+ {
+ var partition = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(skip).Take(take);
+ Assert.Equal(expected, partition.Count());
+ Assert.Equal(expected, partition.Select(i => i).Count());
+ Assert.Equal(expected, partition.Select(i => i).ToArray().Length);
+ }
+
+ [Theory]
+ [InlineData(new[] { 1, 2, 3, 4 }, 1, 3, 2, 4)]
+ [InlineData(new[] { 1 }, 0, 1, 1, 1)]
+ [InlineData(new[] { 1, 2, 3, 5, 8, 13 }, 1, int.MaxValue, 2, 13)] // Regression test: The max index is precisely int.MaxValue.
+ [InlineData(new[] { 1, 2, 3, 5, 8, 13 }, 0, 2, 1, 2)]
+ [InlineData(new[] { 1, 2, 3, 5, 8, 13 }, 500, 2, 0, 0)]
+ [InlineData(new int[] { }, 10, 8, 0, 0)]
+ public void FirstAndLastOfLazySkipTakeChain(IEnumerable<int> source, int skip, int take, int first, int last)
+ {
+ var partition = ForceNotCollection(source).Skip(skip).Take(take);
+
+ Assert.Equal(first, partition.FirstOrDefault());
+ Assert.Equal(first, partition.ElementAtOrDefault(0));
+ Assert.Equal(last, partition.LastOrDefault());
+ Assert.Equal(last, partition.ElementAtOrDefault(partition.Count() - 1));
+ }
+
+ [Theory]
+ [InlineData(new[] { 1, 2, 3, 4, 5 }, 1, 3, new[] { -1, 0, 1, 2 }, new[] { 0, 2, 3, 4 })]
+ [InlineData(new[] { 0xfefe, 7000, 123 }, 0, 3, new[] { -1, 0, 1, 2 }, new[] { 0, 0xfefe, 7000, 123 })]
+ [InlineData(new[] { 0xfefe }, 100, 100, new[] { -1, 0, 1, 2 }, new[] { 0, 0, 0, 0 })]
+ [InlineData(new[] { 0xfefe, 123, 456, 7890, 5555, 55 }, 1, 10, new[] { -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, new[] { 0, 123, 456, 7890, 5555, 55, 0, 0, 0, 0, 0, 0, 0 })]
+ public void ElementAtOfLazySkipTakeChain(IEnumerable<int> source, int skip, int take, int[] indices, int[] expectedValues)
+ {
+ var partition = ForceNotCollection(source).Skip(skip).Take(take);
+
+ Assert.Equal(indices.Length, expectedValues.Length);
+ for (int i = 0; i < indices.Length; i++)
+ {
+ Assert.Equal(expectedValues[i], partition.ElementAtOrDefault(indices[i]));
+ }
+ }
}
}
diff --git a/src/System.Linq/tests/TakeWhileTests.cs b/src/System.Linq/tests/TakeWhileTests.cs
index da785d20af..a6b40695da 100644
--- a/src/System.Linq/tests/TakeWhileTests.cs
+++ b/src/System.Linq/tests/TakeWhileTests.cs
@@ -107,6 +107,17 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ int[] source = {8, 3, 12, 4, 6, 10};
+ int[] expected = {8};
+ Assert.Equal(expected, source.RunOnce().TakeWhile(x => x % 2 == 0));
+ source = new[] {6, 2, 5, 3, 8};
+ expected = new[] {6, 2, 5, 3};
+ Assert.Equal(expected, source.RunOnce().TakeWhile((element, index) => index < source.Length - 1));
+ }
+
+ [Fact]
[ActiveIssue("Valid test but too intensive to enable even in OuterLoop")]
public void IndexTakeWhileOverflowBeyondIntMaxValueElements()
{
diff --git a/src/System.Linq/tests/TestExtensions.cs b/src/System.Linq/tests/TestExtensions.cs
new file mode 100644
index 0000000000..3619e23890
--- /dev/null
+++ b/src/System.Linq/tests/TestExtensions.cs
@@ -0,0 +1,127 @@
+// 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.Collections.Generic;
+using Xunit;
+
+namespace System.Linq.Tests
+{
+ public static class TestExtensions
+ {
+ public static IEnumerable<T> RunOnce<T>(this IEnumerable<T> source) =>
+ source == null ? null : (source as IList<T>)?.RunOnce() ?? new RunOnceEnumerable<T>(source);
+
+ public static IEnumerable<T> RunOnce<T>(this IList<T> source)
+ => source == null ? null : new RunOnceList<T>(source);
+
+ private class RunOnceEnumerable<T> : IEnumerable<T>
+ {
+ private readonly IEnumerable<T> _source;
+ private bool _called;
+
+ public RunOnceEnumerable(IEnumerable<T> source)
+ {
+ _source = source;
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ Assert.False(_called);
+ _called = true;
+ return _source.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ }
+
+ private class RunOnceList<T> : IList<T>
+ {
+ private readonly IList<T> _source;
+ private readonly HashSet<int> _called = new HashSet<int>();
+
+ private void AssertAll()
+ {
+ Assert.Empty(_called);
+ _called.Add(-1);
+ }
+
+ private void AssertIndex(int index)
+ {
+ Assert.False(_called.Contains(-1));
+ Assert.True(_called.Add(index));
+ }
+
+ public RunOnceList(IList<T> source)
+ {
+ _source = source;
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ AssertAll();
+ return _source.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ public void Add(T item)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void Clear()
+ {
+ throw new NotSupportedException();
+ }
+
+ public bool Contains(T item)
+ {
+ AssertAll();
+ return _source.Contains(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ AssertAll();
+ _source.CopyTo(array, arrayIndex);
+ }
+
+ public bool Remove(T item)
+ {
+ throw new NotSupportedException();
+ }
+
+ public int Count => _source.Count;
+
+ public bool IsReadOnly => true;
+
+ public int IndexOf(T item)
+ {
+ AssertAll();
+ return _source.IndexOf(item);
+ }
+
+ public void Insert(int index, T item)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void RemoveAt(int index)
+ {
+ throw new NotSupportedException();
+ }
+
+ public T this[int index]
+ {
+ get
+ {
+ AssertIndex(index);
+ return _source[index];
+ }
+ set { throw new NotSupportedException(); }
+ }
+ }
+ }
+}
diff --git a/src/System.Linq/tests/ThenByDescendingTests.cs b/src/System.Linq/tests/ThenByDescendingTests.cs
index 7762e399fc..4dd504c6c4 100644
--- a/src/System.Linq/tests/ThenByDescendingTests.cs
+++ b/src/System.Linq/tests/ThenByDescendingTests.cs
@@ -123,6 +123,22 @@ And Immortality.".Split(new[] { ' ', '\n', '\r', '—' }, StringSplitOptions.Rem
}
[Fact]
+ public void RunOnce()
+ {
+ var source = @"Because I could not stop for Death —
+He kindly stopped for me —
+The Carriage held but just Ourselves —
+And Immortality.".Split(new[] { ' ', '\n', '\r', '—' }, StringSplitOptions.RemoveEmptyEntries);
+ var expected = new[]
+ {
+ "me", "not", "for", "for", "but", "stop", "held", "just", "could", "kindly", "stopped",
+ "I", "He", "The", "And", "Death", "Because", "Carriage", "Ourselves", "Immortality."
+ };
+
+ Assert.Equal(expected, source.RunOnce().OrderBy(word => char.IsUpper(word[0])).ThenByDescending(word => word.Length, Comparer<int>.Create((w1, w2) => w2.CompareTo(w1))));
+ }
+
+ [Fact]
public void NullSource()
{
IOrderedEnumerable<int> source = null;
diff --git a/src/System.Linq/tests/ThenByTests.cs b/src/System.Linq/tests/ThenByTests.cs
index fb03f81dd7..e4c682b5ab 100644
--- a/src/System.Linq/tests/ThenByTests.cs
+++ b/src/System.Linq/tests/ThenByTests.cs
@@ -110,24 +110,40 @@ namespace System.Linq.Tests
Assert.Equal(expected, source.OrderBy(e => e.Name).ThenBy(e => e.City, null));
}
-
+
[Fact]
public void OrderIsStable()
{
var source = @"Because I could not stop for Death —
He kindly stopped for me —
The Carriage held but just Ourselves —
-And Immortality.".Split(new []{ ' ', '\n', '\r', '—' }, StringSplitOptions.RemoveEmptyEntries);
- var expected = new []
+And Immortality.".Split(new[] { ' ', '\n', '\r', '—' }, StringSplitOptions.RemoveEmptyEntries);
+ var expected = new[]
{
"me", "not", "for", "for", "but", "stop", "held", "just", "could", "kindly", "stopped",
"I", "He", "The", "And", "Death", "Because", "Carriage", "Ourselves", "Immortality."
};
-
+
Assert.Equal(expected, source.OrderBy(word => char.IsUpper(word[0])).ThenBy(word => word.Length));
}
[Fact]
+ public void RunOnce()
+ {
+ var source = @"Because I could not stop for Death —
+He kindly stopped for me —
+The Carriage held but just Ourselves —
+And Immortality.".Split(new[] { ' ', '\n', '\r', '—' }, StringSplitOptions.RemoveEmptyEntries);
+ var expected = new[]
+ {
+ "me", "not", "for", "for", "but", "stop", "held", "just", "could", "kindly", "stopped",
+ "I", "He", "The", "And", "Death", "Because", "Carriage", "Ourselves", "Immortality."
+ };
+
+ Assert.Equal(expected, source.RunOnce().OrderBy(word => char.IsUpper(word[0])).ThenBy(word => word.Length));
+ }
+
+ [Fact]
public void NullSource()
{
IOrderedEnumerable<int> source = null;
diff --git a/src/System.Linq/tests/ToArrayTests.cs b/src/System.Linq/tests/ToArrayTests.cs
index 52323cf9aa..404cbaa0f6 100644
--- a/src/System.Linq/tests/ToArrayTests.cs
+++ b/src/System.Linq/tests/ToArrayTests.cs
@@ -89,6 +89,14 @@ namespace System.Linq.Tests
});
}
+ [Fact]
+ public void RunOnce()
+ {
+ Assert.Equal(new int[] {1, 2, 3, 4, 5, 6, 7}, Enumerable.Range(1, 7).RunOnce().ToArray());
+ Assert.Equal(
+ new string[] {"1", "2", "3", "4", "5", "6", "7", "8"},
+ Enumerable.Range(1, 8).Select(i => i.ToString()).RunOnce().ToArray());
+ }
[Fact]
public void ToArray_TouchCountWithICollection()
diff --git a/src/System.Linq/tests/ToDictionaryTests.cs b/src/System.Linq/tests/ToDictionaryTests.cs
index 5748a0bfbb..3202305eae 100644
--- a/src/System.Linq/tests/ToDictionaryTests.cs
+++ b/src/System.Linq/tests/ToDictionaryTests.cs
@@ -79,7 +79,13 @@ namespace System.Linq.Tests
});
}
-
+ [Fact]
+ public void RunOnce()
+ {
+ Assert.Equal(
+ new Dictionary<int, string> {{1, "0"}, {2, "1"}, {3, "2"}, {4, "3"}},
+ Enumerable.Range(0, 4).RunOnce().ToDictionary(i => i + 1, i => i.ToString()));
+ }
[Fact]
public void ToDictionary_PassCustomComparer()
diff --git a/src/System.Linq/tests/ToHashSetTests.netcoreapp1.1.cs b/src/System.Linq/tests/ToHashSetTests.netcoreapp1.1.cs
index 149f1ca2e5..e544386bc2 100644
--- a/src/System.Linq/tests/ToHashSetTests.netcoreapp1.1.cs
+++ b/src/System.Linq/tests/ToHashSetTests.netcoreapp1.1.cs
@@ -36,6 +36,12 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ Enumerable.Range(0, 50).RunOnce().ToHashSet(new CustomComparer<int>());
+ }
+
+ [Fact]
public void TolerateNullElements()
{
// Unlike the keys of a dictionary, HashSet tolerates null items.
diff --git a/src/System.Linq/tests/ToListTests.cs b/src/System.Linq/tests/ToListTests.cs
index d507b3f266..f37419cefb 100644
--- a/src/System.Linq/tests/ToListTests.cs
+++ b/src/System.Linq/tests/ToListTests.cs
@@ -67,6 +67,11 @@ namespace System.Linq.Tests
});
}
+ [Fact]
+ public void RunOnce()
+ {
+ Assert.Equal(Enumerable.Range(3, 9), Enumerable.Range(3, 9).RunOnce().ToList());
+ }
[Fact]
public void ToList_TouchCountWithICollection()
diff --git a/src/System.Linq/tests/ToLookupTests.cs b/src/System.Linq/tests/ToLookupTests.cs
index bf50a7b298..6e7671e22d 100644
--- a/src/System.Linq/tests/ToLookupTests.cs
+++ b/src/System.Linq/tests/ToLookupTests.cs
@@ -108,6 +108,24 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ string[] key = { "Chris", "Prakash", "Robert" };
+ int[] element = { 50, 80, 100, 95, 99, 56 };
+ var source = new[]
+ {
+ new { Name = key[0], Score = element[0] },
+ new { Name = key[1], Score = element[2] },
+ new { Name = key[2], Score = element[5] },
+ new { Name = key[1], Score = element[3] },
+ new { Name = key[0], Score = element[1] },
+ new { Name = key[1], Score = element[4] }
+ };
+
+ AssertMatches(key, element, source.RunOnce().ToLookup(e => e.Name, e => e.Score, new AnagramEqualityComparer()));
+ }
+
+ [Fact]
public void Count()
{
string[] key = { "Chris", "Prakash", "Robert" };
diff --git a/src/System.Linq/tests/UnionTests.cs b/src/System.Linq/tests/UnionTests.cs
index c2670dcb48..804ef33ea5 100644
--- a/src/System.Linq/tests/UnionTests.cs
+++ b/src/System.Linq/tests/UnionTests.cs
@@ -102,6 +102,17 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ string[] first = { "Bob", "Robert", "Tim", "Matt", "miT" };
+ string[] second = { "ttaM", "Charlie", "Bbo" };
+ string[] expected = { "Bob", "Robert", "Tim", "Matt", "Charlie" };
+
+ var comparer = new AnagramEqualityComparer();
+ Assert.Equal(expected, first.RunOnce().Union(second.RunOnce(), comparer), comparer);
+ }
+
+ [Fact]
public void FirstNullCustomComparer()
{
string[] first = null;
@@ -385,5 +396,22 @@ namespace System.Linq.Tests
Assert.Equal(result, result);
}
+
+ [Fact]
+ public void HashSetWithBuiltInComparer_HashSetContainsNotUsed()
+ {
+ IEnumerable<string> input1 = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "a" };
+ IEnumerable<string> input2 = new[] { "A" };
+
+ Assert.Equal(new[] { "a", "A" }, input1.Union(input2));
+ Assert.Equal(new[] { "a", "A" }, input1.Union(input2, null));
+ Assert.Equal(new[] { "a", "A" }, input1.Union(input2, EqualityComparer<string>.Default));
+ Assert.Equal(new[] { "a" }, input1.Union(input2, StringComparer.OrdinalIgnoreCase));
+
+ Assert.Equal(new[] { "A", "a" }, input2.Union(input1));
+ Assert.Equal(new[] { "A", "a" }, input2.Union(input1, null));
+ Assert.Equal(new[] { "A", "a" }, input2.Union(input1, EqualityComparer<string>.Default));
+ Assert.Equal(new[] { "A" }, input2.Union(input1, StringComparer.OrdinalIgnoreCase));
+ }
}
}
diff --git a/src/System.Linq/tests/WhereTests.cs b/src/System.Linq/tests/WhereTests.cs
index 9a7f337eb0..2772ac3ce6 100644
--- a/src/System.Linq/tests/WhereTests.cs
+++ b/src/System.Linq/tests/WhereTests.cs
@@ -913,6 +913,14 @@ namespace System.Linq.Tests
}
[Fact]
+ public void RunOnce()
+ {
+ int[] source = { 20, 7, 18, 9, 7, 10, 21 };
+ int[] expected = { 20, 18, 10 };
+ Assert.Equal(expected, source.RunOnce().Where(IsEven));
+ }
+
+ [Fact]
public void SourceAllNullsPredicateTrue()
{
int?[] source = { null, null, null, null };
diff --git a/src/System.Linq/tests/ZipTests.cs b/src/System.Linq/tests/ZipTests.cs
index 3de02583bd..ce0fbbd8cf 100644
--- a/src/System.Linq/tests/ZipTests.cs
+++ b/src/System.Linq/tests/ZipTests.cs
@@ -379,5 +379,16 @@ namespace System.Linq.Tests
var en = iterator as IEnumerator<int>;
Assert.False(en != null && en.MoveNext());
}
+
+ [Fact]
+ public void RunOnce()
+ {
+ IEnumerable<int?> first = new[] { 1, (int?)null, 3 };
+ IEnumerable<int> second = new[] { 2, 4, 6, 8 };
+ Func<int?, int, int?> func = (x, y) => x + y;
+ IEnumerable<int?> expected = new int?[] { 3, null, 9 };
+
+ Assert.Equal(expected, first.RunOnce().Zip(second.RunOnce(), func));
+ }
}
}
diff --git a/src/System.Memory/pkg/System.Memory.pkgproj b/src/System.Memory/pkg/System.Memory.pkgproj
index c516962793..b240b0eb96 100644
--- a/src/System.Memory/pkg/System.Memory.pkgproj
+++ b/src/System.Memory/pkg/System.Memory.pkgproj
@@ -2,12 +2,11 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
+ <PackageIndex Include="$(ProjectDir)\pkg\baseline\packageBaseline.1.1.json" />
<ProjectReference Include="..\ref\System.Memory.csproj">
<SupportedFramework>net45;netcore45;wp8;wpa81;netcoreapp1.0;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
- <ProjectReference Include="..\src\System.Memory.csproj">
- <SupportedFramework>net45;netcore45;wp8;wpa81;netcoreapp1.0;$(AllXamarinFrameworks)</SupportedFramework>
- </ProjectReference>
+ <ProjectReference Include="..\src\System.Memory.builds" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/System.Memory/ref/System.Memory.cs b/src/System.Memory/ref/System.Memory.cs
index b02b61dd3d..88b29aa6cc 100644
--- a/src/System.Memory/ref/System.Memory.cs
+++ b/src/System.Memory/ref/System.Memory.cs
@@ -11,7 +11,7 @@ namespace System
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct ReadOnlySpan<T>
{
- public static readonly System.ReadOnlySpan<T> Empty;
+ public static System.ReadOnlySpan<T> Empty { get { throw null; } }
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]public ReadOnlySpan(T[] array) { throw null;}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]public ReadOnlySpan(T[] array, int start) { throw null;}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]public ReadOnlySpan(T[] array, int start, int length) { throw null;}
@@ -48,7 +48,7 @@ namespace System
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct Span<T>
{
- public static readonly System.Span<T> Empty;
+ public static System.Span<T> Empty { get { throw null; } }
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]public Span(T[] array) { throw null;}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]public Span(T[] array, int start) { throw null;}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]public Span(T[] array, int start, int length) { throw null;}
diff --git a/src/System.Memory/src/ApiCompatBaseline.txt b/src/System.Memory/src/ApiCompatBaseline.txt
new file mode 100644
index 0000000000..c786c89e31
--- /dev/null
+++ b/src/System.Memory/src/ApiCompatBaseline.txt
@@ -0,0 +1,3 @@
+Compat issues with assembly System.Memory:
+MembersMustExist : Member 'System.Span<T>.GetItem(System.Int32)' does not exist in the implementation but it does exist in the contract.
+Total Issues: 1 \ No newline at end of file
diff --git a/src/System.Memory/src/Configurations.props b/src/System.Memory/src/Configurations.props
index 2576c6f5ea..584c4d47da 100644
--- a/src/System.Memory/src/Configurations.props
+++ b/src/System.Memory/src/Configurations.props
@@ -3,6 +3,7 @@
<PropertyGroup>
<BuildConfigurations>
netstandard1.0-Windows_NT;
+ netcoreapp1.1-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>
diff --git a/src/System.Memory/src/System.Memory.csproj b/src/System.Memory/src/System.Memory.csproj
index a39c389b4b..4aed71437a 100644
--- a/src/System.Memory/src/System.Memory.csproj
+++ b/src/System.Memory/src/System.Memory.csproj
@@ -7,9 +7,9 @@
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLSCompliant>false</CLSCompliant>
- <NuGetTargetMoniker>.NETStandard,Version=v1.0</NuGetTargetMoniker>
+ <NuGetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.0</NuGetTargetMoniker>
<DocumentationFile>$(OutputPath)$(AssemblyName).xml</DocumentationFile>
- <IsPartialFacadeAssembly>false</IsPartialFacadeAssembly>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netcoreapp1.1'">true</IsPartialFacadeAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
diff --git a/src/System.Memory/src/System/ReadOnlySpan.cs b/src/System.Memory/src/System/ReadOnlySpan.cs
index b5693ffd23..80d118c4b8 100644
--- a/src/System.Memory/src/System/ReadOnlySpan.cs
+++ b/src/System.Memory/src/System/ReadOnlySpan.cs
@@ -358,7 +358,7 @@ namespace System
/// <summary>
/// Returns a 0-length read-only span whose base is the null pointer.
/// </summary>
- public static readonly ReadOnlySpan<T> Empty = default(ReadOnlySpan<T>);
+ public static ReadOnlySpan<T> Empty => default(ReadOnlySpan<T>);
/// <summary>
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
diff --git a/src/System.Memory/src/System/Span.cs b/src/System.Memory/src/System/Span.cs
index 29b87b1a32..ff6e425fd5 100644
--- a/src/System.Memory/src/System/Span.cs
+++ b/src/System.Memory/src/System/Span.cs
@@ -403,7 +403,7 @@ namespace System
/// <summary>
/// Returns a 0-length span whose base is the null pointer.
/// </summary>
- public static readonly Span<T> Empty = default(Span<T>);
+ public static Span<T> Empty => default(Span<T>);
/// <summary>
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
diff --git a/src/System.Memory/tests/ReadOnlySpan/CtorArray.cs b/src/System.Memory/tests/ReadOnlySpan/CtorArray.cs
index 7869088b63..cd13494e3c 100644
--- a/src/System.Memory/tests/ReadOnlySpan/CtorArray.cs
+++ b/src/System.Memory/tests/ReadOnlySpan/CtorArray.cs
@@ -89,16 +89,6 @@ namespace System.SpanTests
}
[Fact]
- public static void CtorArrayWrongArrayType()
- {
- // Cannot pass variant array, if array type is not a valuetype.
- string[] a = { "Hello" };
- Assert.Throws<ArrayTypeMismatchException>(() => new ReadOnlySpan<object>(a).DontBox());
- Assert.Throws<ArrayTypeMismatchException>(() => new ReadOnlySpan<object>(a, 0).DontBox());
- Assert.Throws<ArrayTypeMismatchException>(() => new ReadOnlySpan<object>(a, 0, a.Length).DontBox());
- }
-
- [Fact]
public static void CtorArrayWrongValueType()
{
// Can pass variant array, if array type is a valuetype.
diff --git a/src/System.Memory/tests/Span/Overflow.cs b/src/System.Memory/tests/Span/Overflow.cs
index 228ee75bca..efafc7fb10 100644
--- a/src/System.Memory/tests/Span/Overflow.cs
+++ b/src/System.Memory/tests/Span/Overflow.cs
@@ -10,7 +10,7 @@ namespace System.SpanTests
{
public static partial class SpanTests
{
- [Fact]
+ [Fact(Skip = "Issue # 14484 - Disabling IndexOverflow test until FastSpan has a GetItem implementation. Related: issue # 13681")]
public static void IndexOverflow()
{
//
diff --git a/src/System.Memory/tests/System.Memory.Tests.builds b/src/System.Memory/tests/System.Memory.Tests.builds
index 75b5c3f9cb..c861eb834d 100644
--- a/src/System.Memory/tests/System.Memory.Tests.builds
+++ b/src/System.Memory/tests/System.Memory.Tests.builds
@@ -6,11 +6,13 @@
<OSGroup>Windows_NT</OSGroup>
<TestTFMs>netcore50;netcoreapp1.0;net46</TestTFMs>
</Project>
+ <!-- Add these tests back for fast span once the GC correctness work is done.
<Project Include="System.Memory.Tests.csproj">
<TargetGroup>netcoreapp1.1</TargetGroup>
<OSGroup>Windows_NT</OSGroup>
<TestTFMs>netcoreapp1.1</TestTFMs>
</Project>
+ -->
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
</Project>
diff --git a/src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseParser.cs b/src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseParser.cs
index 26dd7be98d..570ade6666 100644
--- a/src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseParser.cs
+++ b/src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseParser.cs
@@ -133,7 +133,7 @@ namespace System.Net.Http
return result;
}
- public unsafe static bool GetResponseHeader(
+ public static unsafe bool GetResponseHeader(
SafeWinHttpHandle requestHandle,
uint infoLevel,
ref char[] buffer,
@@ -195,7 +195,7 @@ namespace System.Net.Http
/// <summary>
/// Fills the buffer with the header value and returns the length, or returns 0 if the header isn't found.
/// </summary>
- private unsafe static int GetResponseHeader(SafeWinHttpHandle requestHandle, uint infoLevel, char[] buffer)
+ private static unsafe int GetResponseHeader(SafeWinHttpHandle requestHandle, uint infoLevel, char[] buffer)
{
Debug.Assert(buffer != null, "buffer must not be null.");
Debug.Assert(buffer.Length > 0, "buffer must not be empty.");
@@ -226,7 +226,7 @@ namespace System.Net.Http
/// <summary>
/// Returns the size of the char array buffer.
/// </summary>
- private unsafe static int GetResponseHeaderCharBufferLength(SafeWinHttpHandle requestHandle, uint infoLevel)
+ private static unsafe int GetResponseHeaderCharBufferLength(SafeWinHttpHandle requestHandle, uint infoLevel)
{
char* buffer = null;
int bufferLength = 0;
@@ -247,7 +247,7 @@ namespace System.Net.Http
return bufferLength;
}
- private unsafe static bool QueryHeaders(
+ private static unsafe bool QueryHeaders(
SafeWinHttpHandle requestHandle,
uint infoLevel,
char* buffer,
diff --git a/src/System.Net.Http.WinHttpHandler/tests/UnitTests/SafeWinHttpHandleTest.cs b/src/System.Net.Http.WinHttpHandler/tests/UnitTests/SafeWinHttpHandleTest.cs
index 2cfb30a5d9..53d03654d7 100644
--- a/src/System.Net.Http.WinHttpHandler/tests/UnitTests/SafeWinHttpHandleTest.cs
+++ b/src/System.Net.Http.WinHttpHandler/tests/UnitTests/SafeWinHttpHandleTest.cs
@@ -11,6 +11,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
{
public class SafeWinHttpHandleTest
{
+ [ActiveIssue(13951)]
[Fact]
public void CreateAddRefDispose_HandleIsNotClosed()
{
@@ -27,6 +28,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
safeHandle.DangerousRelease();
}
+ [ActiveIssue(13951)]
[Fact]
public void CreateAddRefDisposeDispose_HandleIsNotClosed()
{
@@ -44,6 +46,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
safeHandle.DangerousRelease();
}
+ [ActiveIssue(13951)]
[Fact]
public void CreateAddRefDisposeRelease_HandleIsClosed()
{
@@ -58,6 +61,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
Assert.Equal(0, FakeSafeWinHttpHandle.HandlesOpen);
}
+ [ActiveIssue(13951)]
[Fact]
public void CreateAddRefRelease_HandleIsNotClosed()
{
@@ -74,6 +78,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
safeHandle.Dispose();
}
+ [ActiveIssue(13951)]
[Fact]
public void CreateAddRefReleaseDispose_HandleIsClosed()
{
@@ -88,6 +93,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
Assert.Equal(0, FakeSafeWinHttpHandle.HandlesOpen);
}
+ [ActiveIssue(13951)]
[Fact]
public void CreateDispose_HandleIsClosed()
{
@@ -97,6 +103,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
Assert.True(safeHandle.IsClosed, "closed");
}
+ [ActiveIssue(13951)]
[Fact]
public void CreateDisposeDispose_HandleIsClosedAndSecondDisposeIsNoop()
{
@@ -106,6 +113,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
Assert.True(safeHandle.IsClosed, "closed");
}
+ [ActiveIssue(13951)]
[Fact]
public void CreateDisposeAddRef_ThrowsObjectDisposedException()
{
@@ -115,6 +123,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
{ bool ignore = false; safeHandle.DangerousAddRef(ref ignore); });
}
+ [ActiveIssue(13951)]
[Fact]
public void CreateDisposeRelease_ThrowsObjectDisposedException()
{
@@ -123,6 +132,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
Assert.Throws<ObjectDisposedException>(() => safeHandle.DangerousRelease());
}
+ [ActiveIssue(13951)]
[Fact]
public void SetParentHandle_CreateParentCreateChildDisposeParent_ParentNotClosed()
{
@@ -138,6 +148,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
childHandle.Dispose();
}
+ [ActiveIssue(13951)]
[Fact]
public void SetParentHandle_CreateParentCreateChildDisposeParentDisposeChild_HandlesClosed()
{
@@ -151,6 +162,7 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
Assert.True(childHandle.IsClosed, "closed");
}
+ [ActiveIssue(13951)]
[Fact]
public void SetParentHandle_CreateParentCreateChildDisposeChildDisposeParent_HandlesClosed()
{
diff --git a/src/System.Net.Http/src/System.Net.Http.csproj b/src/System.Net.Http/src/System.Net.Http.csproj
index 0d8620a8fe..eca86c5912 100644
--- a/src/System.Net.Http/src/System.Net.Http.csproj
+++ b/src/System.Net.Http/src/System.Net.Http.csproj
@@ -341,12 +341,6 @@
<Compile Include="netcore50\System\Net\HttpHandlerToFilter.cs" />
<Compile Include="netcore50\System\Net\HttpClientHandler.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'uap101'">
- <!-- ToDo: remove once we have new packages https://github.com/dotnet/corefx/issues/12838 -->
- <ProjectReference Include="..\..\System.Security.Principal\ref\System.Security.Principal.csproj">
- <UndefineProperties>TargetGroup;OSGroup</UndefineProperties>
- </ProjectReference>
- </ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'net46'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System" />
diff --git a/src/System.Net.Http/src/System/Net/Http/HttpRequestException.cs b/src/System.Net.Http/src/System/Net/Http/HttpRequestException.cs
index 72197b4c15..699afc9eec 100644
--- a/src/System.Net.Http/src/System/Net/Http/HttpRequestException.cs
+++ b/src/System.Net.Http/src/System/Net/Http/HttpRequestException.cs
@@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis;
namespace System.Net.Http
{
[Serializable]
+ [SuppressMessage("Microsoft.Serialization", "CA2229")]
public class HttpRequestException : Exception
{
public HttpRequestException()
diff --git a/src/System.Net.Http/src/netcore50/System/Net/HttpHandlerToFilter.cs b/src/System.Net.Http/src/netcore50/System/Net/HttpHandlerToFilter.cs
index 456f97341f..319f1ebf92 100644
--- a/src/System.Net.Http/src/netcore50/System/Net/HttpHandlerToFilter.cs
+++ b/src/System.Net.Http/src/netcore50/System/Net/HttpHandlerToFilter.cs
@@ -25,7 +25,7 @@ namespace System.Net.Http
{
internal class HttpHandlerToFilter : HttpMessageHandler
{
- private readonly static DiagnosticListener s_diagnosticListener = new DiagnosticListener(HttpHandlerLoggingStrings.DiagnosticListenerName);
+ private static readonly DiagnosticListener s_diagnosticListener = new DiagnosticListener(HttpHandlerLoggingStrings.DiagnosticListenerName);
private readonly RTHttpBaseProtocolFilter _next;
private int _filterMaxVersionSet;
diff --git a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.cs b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.cs
index 253f0ca279..a0ceba0551 100644
--- a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.cs
+++ b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.cs
@@ -153,7 +153,7 @@ namespace System.Net.Http.Functional.Tests
}
}
- public readonly static object[][] CertificateValidationServers =
+ public static readonly object[][] CertificateValidationServers =
{
new object[] { Configuration.Http.ExpiredCertRemoteServer },
new object[] { Configuration.Http.SelfSignedCertRemoteServer },
@@ -193,7 +193,7 @@ namespace System.Net.Http.Functional.Tests
}
}
- public readonly static object[][] CertificateValidationServersAndExpectedPolicies =
+ public static readonly object[][] CertificateValidationServersAndExpectedPolicies =
{
new object[] { Configuration.Http.ExpiredCertRemoteServer, SslPolicyErrors.RemoteCertificateChainErrors },
new object[] { Configuration.Http.SelfSignedCertRemoteServer, SslPolicyErrors.RemoteCertificateChainErrors },
diff --git a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.cs b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.cs
index 9277c475ce..74d0085500 100644
--- a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.cs
+++ b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.cs
@@ -106,7 +106,7 @@ namespace System.Net.Http.Functional.Tests
}
}
- public readonly static object [][] SupportedSSLVersionServers =
+ public static readonly object [][] SupportedSSLVersionServers =
{
new object[] {"TLSv1.0", Configuration.Http.TLSv10RemoteServer},
new object[] {"TLSv1.1", Configuration.Http.TLSv11RemoteServer},
@@ -128,7 +128,7 @@ namespace System.Net.Http.Functional.Tests
}
}
- public readonly static object[][] NotSupportedSSLVersionServers =
+ public static readonly object[][] NotSupportedSSLVersionServers =
{
new object[] {"SSLv2", Configuration.Http.SSLv2RemoteServer},
new object[] {"SSLv3", Configuration.Http.SSLv3RemoteServer},
diff --git a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs
index 259ea737bd..bc21a836c2 100644
--- a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs
+++ b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs
@@ -34,10 +34,10 @@ namespace System.Net.Http.Functional.Tests
private readonly NetworkCredential _credential = new NetworkCredential(Username, Password);
- public readonly static object[][] EchoServers = Configuration.Http.EchoServers;
- public readonly static object[][] VerifyUploadServers = Configuration.Http.VerifyUploadServers;
- public readonly static object[][] CompressedServers = Configuration.Http.CompressedServers;
- public readonly static object[][] HeaderValueAndUris = {
+ public static readonly object[][] EchoServers = Configuration.Http.EchoServers;
+ public static readonly object[][] VerifyUploadServers = Configuration.Http.VerifyUploadServers;
+ public static readonly object[][] CompressedServers = Configuration.Http.CompressedServers;
+ public static readonly object[][] HeaderValueAndUris = {
new object[] { "X-CustomHeader", "x-value", Configuration.Http.RemoteEchoServer },
new object[] { "X-Cust-Header-NoValue", "" , Configuration.Http.RemoteEchoServer },
new object[] { "X-CustomHeader", "x-value", Configuration.Http.RedirectUriForDestinationUri(
@@ -51,10 +51,10 @@ namespace System.Net.Http.Functional.Tests
destinationUri:Configuration.Http.RemoteEchoServer,
hops:1) },
};
- public readonly static object[][] Http2Servers = Configuration.Http.Http2Servers;
- public readonly static object[][] Http2NoPushServers = Configuration.Http.Http2NoPushServers;
+ public static readonly object[][] Http2Servers = Configuration.Http.Http2Servers;
+ public static readonly object[][] Http2NoPushServers = Configuration.Http.Http2NoPushServers;
- public readonly static object[][] RedirectStatusCodes = {
+ public static readonly object[][] RedirectStatusCodes = {
new object[] { 300 },
new object[] { 301 },
new object[] { 302 },
@@ -64,11 +64,11 @@ namespace System.Net.Http.Functional.Tests
// Standard HTTP methods defined in RFC7231: http://tools.ietf.org/html/rfc7231#section-4.3
// "GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "TRACE"
- public readonly static IEnumerable<object[]> HttpMethods =
+ public static readonly IEnumerable<object[]> HttpMethods =
GetMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "TRACE", "CUSTOM1");
- public readonly static IEnumerable<object[]> HttpMethodsThatAllowContent =
+ public static readonly IEnumerable<object[]> HttpMethodsThatAllowContent =
GetMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "CUSTOM1");
- public readonly static IEnumerable<object[]> HttpMethodsThatDontAllowContent =
+ public static readonly IEnumerable<object[]> HttpMethodsThatDontAllowContent =
GetMethods("HEAD", "TRACE");
private static bool IsWindows10Version1607OrGreater => PlatformDetection.IsWindows10Version1607OrGreater;
diff --git a/src/System.Net.Http/tests/FunctionalTests/PostScenarioTest.cs b/src/System.Net.Http/tests/FunctionalTests/PostScenarioTest.cs
index 0506e4bf2e..5a17c33bf2 100644
--- a/src/System.Net.Http/tests/FunctionalTests/PostScenarioTest.cs
+++ b/src/System.Net.Http/tests/FunctionalTests/PostScenarioTest.cs
@@ -24,16 +24,16 @@ namespace System.Net.Http.Functional.Tests
private const string ExpectedContent = "Test contest";
private const string UserName = "user1";
private const string Password = "password1";
- private readonly static Uri BasicAuthServerUri =
+ private static readonly Uri BasicAuthServerUri =
Configuration.Http.BasicAuthUriForCreds(false, UserName, Password);
- private readonly static Uri SecureBasicAuthServerUri =
+ private static readonly Uri SecureBasicAuthServerUri =
Configuration.Http.BasicAuthUriForCreds(true, UserName, Password);
private readonly ITestOutputHelper _output;
- public readonly static object[][] EchoServers = Configuration.Http.EchoServers;
+ public static readonly object[][] EchoServers = Configuration.Http.EchoServers;
- public readonly static object[][] BasicAuthEchoServers =
+ public static readonly object[][] BasicAuthEchoServers =
new object[][]
{
new object[] { BasicAuthServerUri },
diff --git a/src/System.Net.Http/tests/UnitTests/Headers/CurlResponseHeaderReaderTest.cs b/src/System.Net.Http/tests/UnitTests/Headers/CurlResponseHeaderReaderTest.cs
index e518c55a35..69389835d8 100644
--- a/src/System.Net.Http/tests/UnitTests/Headers/CurlResponseHeaderReaderTest.cs
+++ b/src/System.Net.Http/tests/UnitTests/Headers/CurlResponseHeaderReaderTest.cs
@@ -21,10 +21,10 @@ namespace System.Net.Http.Tests
private const string invalidChars = "()<>@,;\\\"/[]?={} \t";
- public readonly static IEnumerable<object[]> ValidStatusCodeLines = GetStatusCodeLines(StatusCodeTemplate);
- public readonly static IEnumerable<object[]> InvalidStatusCodeLines = GetStatusCodeLines(MissingSpaceFormat);
- public readonly static IEnumerable<object[]> StatusCodeVersionLines = GetStatusCodeLinesForVersions(1, 10);
- public readonly static IEnumerable<object[]> InvalidHeaderLines = GetInvalidHeaderLines();
+ public static readonly IEnumerable<object[]> ValidStatusCodeLines = GetStatusCodeLines(StatusCodeTemplate);
+ public static readonly IEnumerable<object[]> InvalidStatusCodeLines = GetStatusCodeLines(MissingSpaceFormat);
+ public static readonly IEnumerable<object[]> StatusCodeVersionLines = GetStatusCodeLinesForVersions(1, 10);
+ public static readonly IEnumerable<object[]> InvalidHeaderLines = GetInvalidHeaderLines();
private static IEnumerable<object[]> GetStatusCodeLines(string template)
{
diff --git a/src/System.Net.HttpListener/System.Net.HttpListener.sln b/src/System.Net.HttpListener/System.Net.HttpListener.sln
index d8269ddafd..c1de60d45b 100644
--- a/src/System.Net.HttpListener/System.Net.HttpListener.sln
+++ b/src/System.Net.HttpListener/System.Net.HttpListener.sln
@@ -17,8 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.HttpListener.Tes
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
- net463_Debug|Any CPU = net463_Debug|Any CPU
- net463_Release|Any CPU = net463_Release|Any CPU
+ net461_Debug|Any CPU = net461_Debug|Any CPU
+ net461_Release|Any CPU = net461_Release|Any CPU
netstandard1.7_Debug|Any CPU = netstandard1.7_Debug|Any CPU
netstandard1.7_Release|Any CPU = netstandard1.7_Release|Any CPU
Unix_Debug|Any CPU = Unix_Debug|Any CPU
@@ -27,14 +27,14 @@ Global
Windows_Release|Any CPU = Windows_Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {53D09AF4-0C13-4197-B8AD-9746F0374E88}.net463_Debug|Any CPU.ActiveCfg = net463_Debug|Any CPU
- {53D09AF4-0C13-4197-B8AD-9746F0374E88}.net463_Debug|Any CPU.Build.0 = net463_Debug|Any CPU
- {53D09AF4-0C13-4197-B8AD-9746F0374E88}.net463_Release|Any CPU.ActiveCfg = net463_Release|Any CPU
- {53D09AF4-0C13-4197-B8AD-9746F0374E88}.net463_Release|Any CPU.Build.0 = net463_Release|Any CPU
- {53D09AF4-0C13-4197-B8AD-9746F0374E88}.netstandard1.7_Debug|Any CPU.ActiveCfg = net463_Release|Any CPU
- {53D09AF4-0C13-4197-B8AD-9746F0374E88}.netstandard1.7_Debug|Any CPU.Build.0 = net463_Release|Any CPU
- {53D09AF4-0C13-4197-B8AD-9746F0374E88}.netstandard1.7_Release|Any CPU.ActiveCfg = net463_Release|Any CPU
- {53D09AF4-0C13-4197-B8AD-9746F0374E88}.netstandard1.7_Release|Any CPU.Build.0 = net463_Release|Any CPU
+ {53D09AF4-0C13-4197-B8AD-9746F0374E88}.net461_Debug|Any CPU.ActiveCfg = net461_Debug|Any CPU
+ {53D09AF4-0C13-4197-B8AD-9746F0374E88}.net461_Debug|Any CPU.Build.0 = net461_Debug|Any CPU
+ {53D09AF4-0C13-4197-B8AD-9746F0374E88}.net461_Release|Any CPU.ActiveCfg = net461_Release|Any CPU
+ {53D09AF4-0C13-4197-B8AD-9746F0374E88}.net461_Release|Any CPU.Build.0 = net461_Release|Any CPU
+ {53D09AF4-0C13-4197-B8AD-9746F0374E88}.netstandard1.7_Debug|Any CPU.ActiveCfg = net461_Release|Any CPU
+ {53D09AF4-0C13-4197-B8AD-9746F0374E88}.netstandard1.7_Debug|Any CPU.Build.0 = net461_Release|Any CPU
+ {53D09AF4-0C13-4197-B8AD-9746F0374E88}.netstandard1.7_Release|Any CPU.ActiveCfg = net461_Release|Any CPU
+ {53D09AF4-0C13-4197-B8AD-9746F0374E88}.netstandard1.7_Release|Any CPU.Build.0 = net461_Release|Any CPU
{53D09AF4-0C13-4197-B8AD-9746F0374E88}.Unix_Debug|Any CPU.ActiveCfg = Unix_Debug|Any CPU
{53D09AF4-0C13-4197-B8AD-9746F0374E88}.Unix_Debug|Any CPU.Build.0 = Unix_Debug|Any CPU
{53D09AF4-0C13-4197-B8AD-9746F0374E88}.Unix_Release|Any CPU.ActiveCfg = Unix_Release|Any CPU
@@ -43,10 +43,10 @@ Global
{53D09AF4-0C13-4197-B8AD-9746F0374E88}.Windows_Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
{53D09AF4-0C13-4197-B8AD-9746F0374E88}.Windows_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
{53D09AF4-0C13-4197-B8AD-9746F0374E88}.Windows_Release|Any CPU.Build.0 = Windows_Release|Any CPU
- {C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.net463_Debug|Any CPU.ActiveCfg = netstandard1.7_Release|Any CPU
- {C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.net463_Debug|Any CPU.Build.0 = netstandard1.7_Release|Any CPU
- {C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.net463_Release|Any CPU.ActiveCfg = netstandard1.7_Release|Any CPU
- {C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.net463_Release|Any CPU.Build.0 = netstandard1.7_Release|Any CPU
+ {C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.net461_Debug|Any CPU.ActiveCfg = netstandard1.7_Release|Any CPU
+ {C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.net461_Debug|Any CPU.Build.0 = netstandard1.7_Release|Any CPU
+ {C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.net461_Release|Any CPU.ActiveCfg = netstandard1.7_Release|Any CPU
+ {C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.net461_Release|Any CPU.Build.0 = netstandard1.7_Release|Any CPU
{C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.netstandard1.7_Debug|Any CPU.ActiveCfg = netstandard1.7_Debug|Any CPU
{C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.netstandard1.7_Debug|Any CPU.Build.0 = netstandard1.7_Debug|Any CPU
{C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.netstandard1.7_Release|Any CPU.ActiveCfg = netstandard1.7_Release|Any CPU
@@ -59,10 +59,10 @@ Global
{C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.Windows_Debug|Any CPU.Build.0 = netstandard1.7_Release|Any CPU
{C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.Windows_Release|Any CPU.ActiveCfg = netstandard1.7_Release|Any CPU
{C6A5999E-11CD-4213-AA4D-D3BA984F9CEA}.Windows_Release|Any CPU.Build.0 = netstandard1.7_Release|Any CPU
- {851A40FE-7F07-415D-8592-5FE2096E84D3}.net463_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
- {851A40FE-7F07-415D-8592-5FE2096E84D3}.net463_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
- {851A40FE-7F07-415D-8592-5FE2096E84D3}.net463_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
- {851A40FE-7F07-415D-8592-5FE2096E84D3}.net463_Release|Any CPU.Build.0 = Windows_Release|Any CPU
+ {851A40FE-7F07-415D-8592-5FE2096E84D3}.net461_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {851A40FE-7F07-415D-8592-5FE2096E84D3}.net461_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
+ {851A40FE-7F07-415D-8592-5FE2096E84D3}.net461_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
+ {851A40FE-7F07-415D-8592-5FE2096E84D3}.net461_Release|Any CPU.Build.0 = Windows_Release|Any CPU
{851A40FE-7F07-415D-8592-5FE2096E84D3}.netstandard1.7_Debug|Any CPU.ActiveCfg = Windows_Release|Any CPU
{851A40FE-7F07-415D-8592-5FE2096E84D3}.netstandard1.7_Debug|Any CPU.Build.0 = Windows_Release|Any CPU
{851A40FE-7F07-415D-8592-5FE2096E84D3}.netstandard1.7_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
diff --git a/src/System.Net.HttpListener/pkg/System.Net.HttpListener.pkgproj b/src/System.Net.HttpListener/pkg/System.Net.HttpListener.pkgproj
index 159822718a..800c1149b0 100644
--- a/src/System.Net.HttpListener/pkg/System.Net.HttpListener.pkgproj
+++ b/src/System.Net.HttpListener/pkg/System.Net.HttpListener.pkgproj
@@ -4,7 +4,7 @@
<ItemGroup>
<ProjectReference Include="..\ref\System.Net.HttpListener.csproj">
- <SupportedFramework>net463;netcoreapp1.1</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Net.HttpListener.builds" />
</ItemGroup>
diff --git a/src/System.Net.HttpListener/ref/System.Net.HttpListener.cs b/src/System.Net.HttpListener/ref/System.Net.HttpListener.cs
index 5a0cad0b46..30879d0312 100644
--- a/src/System.Net.HttpListener/ref/System.Net.HttpListener.cs
+++ b/src/System.Net.HttpListener/ref/System.Net.HttpListener.cs
@@ -5,6 +5,9 @@
// Changes to this file must follow the http://aka.ms/api-review process.
// ------------------------------------------------------------------------------
+using System.Runtime.Serialization;
+using System.Security.Authentication.ExtendedProtection;
+
namespace System.Net
{
public delegate System.Net.AuthenticationSchemes AuthenticationSchemeSelector(System.Net.HttpListenerRequest httpRequest);
@@ -25,6 +28,11 @@ namespace System.Net
public System.Net.HttpListenerContext EndGetContext(System.IAsyncResult asyncResult) { throw null; }
public System.Net.HttpListenerContext GetContext() { throw null; }
public System.Threading.Tasks.Task<System.Net.HttpListenerContext> GetContextAsync() { throw null; }
+ public ServiceNameCollection DefaultServiceNames { get { throw null; } }
+ public ExtendedProtectionPolicy ExtendedProtectionPolicy { get { throw null; } set { } }
+ public ExtendedProtectionSelector ExtendedProtectionSelectorDelegate { get { throw null; } set { } }
+ public HttpListenerTimeoutManager TimeoutManager { get { throw null; } }
+ public delegate ExtendedProtectionPolicy ExtendedProtectionSelector(HttpListenerRequest request);
public void Start() { }
public void Stop() { }
void System.IDisposable.Dispose() { }
@@ -43,12 +51,15 @@ namespace System.Net
public System.Threading.Tasks.Task<System.Net.WebSockets.HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol) { throw null; }
public System.Threading.Tasks.Task<System.Net.WebSockets.HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, System.TimeSpan keepAliveInterval) { throw null; }
public System.Threading.Tasks.Task<System.Net.WebSockets.HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, System.TimeSpan keepAliveInterval, System.ArraySegment<byte> internalBuffer) { throw null; }
+ public System.Threading.Tasks.Task<System.Net.WebSockets.HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, TimeSpan keepAliveInterval) { throw null; }
}
public partial class HttpListenerException : System.ComponentModel.Win32Exception
{
public HttpListenerException() { }
public HttpListenerException(int errorCode) { }
public HttpListenerException(int errorCode, string message) { }
+ protected HttpListenerException(SerializationInfo serializationInfo, StreamingContext streamingContext) { }
+ public override int ErrorCode { get; }
}
public partial class HttpListenerPrefixCollection : System.Collections.Generic.ICollection<string>, System.Collections.Generic.IEnumerable<string>, System.Collections.IEnumerable
{
@@ -128,6 +139,16 @@ namespace System.Net
public void SetCookie(System.Net.Cookie cookie) { }
void System.IDisposable.Dispose() { }
}
+ public partial class HttpListenerTimeoutManager
+ {
+ internal HttpListenerTimeoutManager() { }
+ public TimeSpan DrainEntityBody { get { throw null; } set { } }
+ public TimeSpan EntityBody { get { throw null; } set { } }
+ public TimeSpan HeaderWait { get { throw null; } set { } }
+ public TimeSpan IdleConnection { get { throw null; } set { } }
+ public long MinSendBytesPerSecond { get { throw null; } set { } }
+ public TimeSpan RequestQueue { get { throw null; } set { } }
+ }
}
namespace System.Net.WebSockets
{
diff --git a/src/System.Net.HttpListener/src/Configurations.props b/src/System.Net.HttpListener/src/Configurations.props
index 2d365bdaa4..8e79110983 100644
--- a/src/System.Net.HttpListener/src/Configurations.props
+++ b/src/System.Net.HttpListener/src/Configurations.props
@@ -4,7 +4,7 @@
<BuildConfigurations>
netstandard-Windows_NT;
netstandard-Unix;
- net463-Windows_NT;
+ net461-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>
diff --git a/src/System.Net.HttpListener/src/Resources/Strings.resx b/src/System.Net.HttpListener/src/Resources/Strings.resx
index bf6478ba00..a576f33af5 100644
--- a/src/System.Net.HttpListener/src/Resources/Strings.resx
+++ b/src/System.Net.HttpListener/src/Resources/Strings.resx
@@ -357,4 +357,49 @@
<data name="net_WebSockets_Argument_InvalidMessageType" xml:space="preserve">
<value>The message type '{0}' is not allowed for the '{1}' operation. Valid message types are: '{2}, {3}'. To close the WebSocket, use the '{4}' operation instead. </value>
</data>
-</root> \ No newline at end of file
+ <data name="net_securitypackagesupport" xml:space="preserve">
+ <value>The requested security package is not supported.</value>
+ </data>
+ <data name="net_log_operation_failed_with_error" xml:space="preserve">
+ <value>{0} failed with error {1}.</value>
+ </data>
+ <data name="net_MethodNotImplementedException" xml:space="preserve">
+ <value>This method is not implemented by this class.</value>
+ </data>
+ <data name="event_OperationReturnedSomething" xml:space="preserve">
+ <value>{0} returned {1}.</value>
+ </data>
+ <data name="net_invalid_enum" xml:space="preserve">
+ <value>The specified value is not valid in the '{0}' enumeration.</value>
+ </data>
+ <data name="net_auth_message_not_encrypted" xml:space="preserve">
+ <value>Protocol error: A received message contains a valid signature but it was not encrypted as required by the effective Protection Level.</value>
+ </data>
+ <data name="SSPIInvalidHandleType" xml:space="preserve">
+ <value>'{0}' is not a supported handle type.</value>
+ </data>
+ <data name="net_cannot_change_after_headers" xml:space="preserve">
+ <value>Cannot be changed after headers are sent.</value>
+ </data>
+ <data name="offset_out_of_range" xml:space="preserve">
+ <value>Offset exceeds the length of buffer.</value>
+ </data>
+ <data name="net_io_operation_aborted" xml:space="preserve">
+ <value>I/O operation aborted: '{0}'.</value>
+ </data>
+ <data name="net_invalid_path" xml:space="preserve">
+ <value>Invalid path.</value>
+ </data>
+ <data name="net_no_client_certificate" xml:space="preserve">
+ <value>Client certificate not found.</value>
+ </data>
+ <data name="net_listener_auth_errors" xml:space="preserve">
+ <value>Authentication errors.</value>
+ </data>
+ <data name="net_listener_close" xml:space="preserve">
+ <value>Listener closed.</value>
+ </data>
+ <data name="net_invalid_port" xml:space="preserve">
+ <value>Invalid port in prefix.</value>
+ </data>
+</root>
diff --git a/src/System.Net.HttpListener/src/System.Net.HttpListener.csproj b/src/System.Net.HttpListener/src/System.Net.HttpListener.csproj
index 6f5e057b48..ffe610cf02 100644
--- a/src/System.Net.HttpListener/src/System.Net.HttpListener.csproj
+++ b/src/System.Net.HttpListener/src/System.Net.HttpListener.csproj
@@ -4,15 +4,15 @@
<PropertyGroup>
<ProjectGuid>{53D09AF4-0C13-4197-B8AD-9746F0374E88}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net463'">true</IsPartialFacadeAssembly>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net461'">true</IsPartialFacadeAssembly>
</PropertyGroup>
<!-- Default configurations to help VS understand the options -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Unix_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Unix_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup>
<Reference Include="System.Runtime" />
<Reference Include="System.Resources.ResourceManager" />
@@ -49,38 +49,39 @@
<Compile Include="System\Net\HttpListenerBasicIdentity.cs" />
<Compile Include="System\Net\HttpListenerContext.cs" />
<Compile Include="System\Net\HttpListenerException.cs" />
- <Compile Include="System\Net\HttpListenerPrefixCollection.cs" />
- <Compile Include="System\Net\HttpListenerRequest.cs" />
<Compile Include="System\Net\HttpListenerResponse.cs" />
<Compile Include="System\Net\NetEventSource.HttpListener.cs" />
<Compile Include="System\Net\WebSockets\HttpListenerWebSocketContext.cs" />
<Compile Include="$(CommonPath)\System\Net\Logging\NetEventSource.Common.cs">
<Link>Common\System\Net\Logging\NetEventSource.Common.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\System\Net\HttpStatusDescription.cs">
+ <Link>Common\System\Net\HttpStatusDescription.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\HttpKnownHeaderNames.cs">
+ <Link>Common\System\Net\HttpKnownHeaderNames.cs</Link>
+ </Compile>
</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)' == 'true' AND '$(TargetGroup)' == 'netstandard'">
- <Compile Include="System\Net\BoundaryType.cs" />
- <Compile Include="System\Net\AuthConstants.cs" />
- <Compile Include="System\Net\ContextFlags.cs" />
- <Compile Include="System\Net\CookieExtensions.cs" />
- <Compile Include="System\Net\HttpRequestQueueV2Handle.cs" />
- <Compile Include="System\Net\HttpServerSessionHandle.cs" />
- <Compile Include="System\Net\HttpListenerContext.Windows.cs" />
- <Compile Include="System\Net\HttpListenerRequestContext.cs" />
- <Compile Include="System\Net\HttpListenerRequestUriBuilder.cs" />
- <Compile Include="System\Net\ListenerClientCertAsyncResult.cs" />
- <Compile Include="System\Net\AsyncRequestContext.cs" />
- <Compile Include="System\Net\ListenerClientCertState.cs" />
- <Compile Include="System\Net\EntitySendFormat.cs" />
- <Compile Include="System\Net\HttpListener.Windows.cs" />
- <Compile Include="System\Net\HttpListenerRequest.Windows.cs" />
- <Compile Include="System\Net\HttpListenerResponse.Windows.cs" />
- <Compile Include="System\Net\HttpListenerTimeoutManager.Windows.cs" />
- <Compile Include="System\Net\NTAuthentication.cs" />
- <Compile Include="System\Net\RequestContextBase.cs" />
- <Compile Include="System\Net\ServiceNameStore.cs" />
- <Compile Include="System\Net\SyncRequestContext.cs" />
- <Compile Include="System\Net\ListenerAsyncResult.cs" />
+ <Compile Include="System\Net\Windows\HttpListenerPrefixCollection.Windows.cs" />
+ <Compile Include="System\Net\Windows\HttpListener.Windows.cs" />
+ <Compile Include="System\Net\Windows\HttpListenerContext.Windows.cs" />
+ <Compile Include="System\Net\Windows\HttpListenerRequest.Windows.cs" />
+ <Compile Include="System\Net\Windows\HttpListenerResponse.Windows.cs" />
+ <Compile Include="System\Net\Windows\HttpListenerTimeoutManager.Windows.cs" />
+ <Compile Include="System\Net\Windows\BoundaryType.cs" />
+ <Compile Include="System\Net\Windows\ContextFlags.cs" />
+ <Compile Include="System\Net\Windows\CookieExtensions.cs" />
+ <Compile Include="System\Net\Windows\HttpRequestQueueV2Handle.cs" />
+ <Compile Include="System\Net\Windows\HttpServerSessionHandle.cs" />
+ <Compile Include="System\Net\Windows\HttpListenerRequestContext.cs" />
+ <Compile Include="System\Net\Windows\ListenerClientCertAsyncResult.Windows.cs" />
+ <Compile Include="System\Net\Windows\AsyncRequestContext.cs" />
+ <Compile Include="System\Net\Windows\ListenerClientCertState.cs" />
+ <Compile Include="System\Net\Windows\EntitySendFormat.cs" />
+ <Compile Include="System\Net\Windows\RequestContextBase.cs" />
+ <Compile Include="System\Net\Windows\SyncRequestContext.cs" />
+ <Compile Include="System\Net\Windows\ListenerAsyncResult.Windows.cs" />
<Compile Include="$(CommonPath)\System\Net\CaseInsensitiveAscii.cs">
<Link>Common\System\Net\CaseInsensitiveAscii.cs</Link>
</Compile>
@@ -93,12 +94,6 @@
<Compile Include="$(CommonPath)\System\Net\ExceptionCheck.cs">
<Link>Common\System\Net\ExceptionCheck.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Net\HttpStatusDescription.cs">
- <Link>Common\System\Net\HttpStatusDescription.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\Net\HttpKnownHeaderNames.cs">
- <Link>Common\System\Net\HttpKnownHeaderNames.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\System\Net\InternalException.cs">
<Link>Common\System\Net\InternalException.cs</Link>
</Compile>
@@ -111,14 +106,14 @@
<Compile Include="$(CommonPath)\System\Net\WebHeaderEncoding.cs">
<Link>Common\System\Net\WebHeaderEncoding.cs</Link>
</Compile>
- <Compile Include="System\Net\HttpResponseStream.cs" />
- <Compile Include="System\Net\HttpResponseStreamAsyncResult.cs" />
+ <Compile Include="System\Net\Windows\HttpResponseStream.Windows.cs" />
+ <Compile Include="System\Net\Windows\HttpResponseStreamAsyncResult.cs" />
<Compile Include="System\Net\WebSockets\ServerWebSocket.cs" />
<Compile Include="System\Net\WebSockets\WebSocketBase.cs" />
<Compile Include="System\Net\WebSockets\WebSocketBuffer.cs" />
<Compile Include="System\Net\WebSockets\SafeWebSocketHandle.cs" />
<Compile Include="System\Net\WebSockets\WebSocketHelpers.cs" />
- <Compile Include="System\Net\HttpRequestStream.cs" />
+ <Compile Include="System\Net\Windows\HttpRequestStream.Windows.cs" />
<Compile Include="System\Net\WebSockets\WebSocketHttpListenerDuplexStream.cs" />
<Compile Include="System\Net\WebSockets\WebSocketProtocolComponent.cs" />
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs">
@@ -196,15 +191,154 @@
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeLocalAllocHandle.cs">
<Link>Common\Microsoft\Win32\SafeHandles\SafeLocalAllocHandle.cs</Link>
</Compile>
+ <!-- Add NTAuthentication -->
+ <Compile Include="$(CommonPath)\System\Net\DebugCriticalHandleMinusOneIsInvalid.cs">
+ <Link>Common\System\Net\DebugCriticalHandleMinusOneIsInvalid.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\DebugCriticalHandleZeroOrMinusOneIsInvalid.cs">
+ <Link>Common\System\Net\DebugCriticalHandleZeroOrMinusOneIsInvalid.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\IntPtrHelper.cs">
+ <Link>Common\System\Net\IntPtrHelper.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Collections\Generic\BidirectionalDictionary.cs">
+ <Link>Common\System\Collections\Generic\BidirectionalDictionary.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\NotImplemented.cs">
+ <Link>Common\System\NotImplemented.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\Logging\DebugThreadTracking.cs">
+ <Link>Common\System\Net\Logging\DebugThreadTracking.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\ContextFlagsPal.cs">
+ <Link>Common\System\Net\ContextFlagsPal.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\NegotiationInfoClass.cs">
+ <Link>Common\System\Net\NegotiationInfoClass.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\NTAuthentication.Common.cs">
+ <Link>Common\System\Net\NTAuthentication.Common.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\SecurityStatusPal.cs">
+ <Link>Common\System\Net\SecurityStatusPal.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\Security\SecurityBuffer.cs">
+ <Link>Common\System\Net\Security\SecurityBuffer.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\Security\SecurityBufferType.cs">
+ <Link>Common\System\Net\Security\SecurityBufferType.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\Security\SSPIHandleCache.cs">
+ <Link>Common\System\Net\Security\SSPIHandleCache.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\Security\NetEventSource.Security.cs">
+ <Link>Common\System\Net\Security\NetEventSource.Security.cs</Link>
+ </Compile>
+ <!-- Windows specific NTAuthentication -->
+ <Compile Include="$(CommonPath)\System\Net\Security\SecurityContextTokenHandle.cs">
+ <Link>Common\System\Net\Security\SecurityContextTokenHandle.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\SecurityStatusAdapterPal.Windows.cs">
+ <Link>Common\System\Net\SecurityStatusAdapterPal.Windows.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\ContextFlagsAdapterPal.Windows.cs">
+ <Link>Common\System\Net\ContextFlagsAdapterPal.Windows.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\Security\NegotiateStreamPal.Windows.cs">
+ <Link>Common\System\Net\Security\NegotiateStreamPal.Windows.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Net\Security\NetEventSource.Security.Windows.cs">
+ <Link>Common\System\Net\Security\NetEventSource.Security.Windows.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\Crypt32\Interop.certificates_types.cs">
+ <Link>Common\Interop\Windows\Crypt32\Interop.certificates_types.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\Crypt32\Interop.certificates.cs">
+ <Link>Common\Interop\Windows\Crypt32\Interop.certificates.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SecPkgContext_Bindings.cs">
+ <Link>Common\Interop\Windows\sspicli\SecPkgContext_Bindings.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\SChannel\Interop.SECURITY_STATUS.cs">
+ <Link>Common\Interop\Windows\SChannel\Interop.SECURITY_STATUS.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.CloseHandle.cs">
+ <Link>Common\Interop\Windows\kernel32\Interop.CloseHandle.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SecPkgContext_StreamSizes.cs">
+ <Link>Common\Interop\Windows\sspicli\SecPkgContext_StreamSizes.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SecPkgContext_NegotiationInfoW.cs">
+ <Link>Common\Interop\Windows\sspicli\SecPkgContext_NegotiationInfoW.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\NegotiationInfoClass.cs">
+ <Link>Common\Interop\Windows\sspicli\NegotiationInfoClass.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\SChannel\SecPkgContext_ConnectionInfo.cs">
+ <Link>Common\Interop\Windows\SChannel\SecPkgContext_ConnectionInfo.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SSPISecureChannelType.cs">
+ <Link>Common\Interop\Windows\sspicli\SSPISecureChannelType.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SSPIInterface.cs">
+ <Link>Common\Interop\Windows\sspicli\SSPIInterface.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SSPIAuthType.cs">
+ <Link>Common\Interop\Windows\sspicli\SSPIAuthType.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SecurityPackageInfoClass.cs">
+ <Link>Common\Interop\Windows\sspicli\SecurityPackageInfoClass.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SecurityPackageInfo.cs">
+ <Link>Common\Interop\Windows\sspicli\SecurityPackageInfo.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SecPkgContext_Sizes.cs">
+ <Link>Common\Interop\Windows\sspicli\SecPkgContext_Sizes.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SafeDeleteContext.cs">
+ <Link>Common\Interop\Windows\sspicli\SafeDeleteContext.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\GlobalSSPI.cs">
+ <Link>Common\Interop\Windows\sspicli\GlobalSSPI.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\Interop.SSPI.cs">
+ <Link>Common\Interop\Windows\sspicli\Interop.SSPI.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SecuritySafeHandles.cs">
+ <Link>Common\Interop\Windows\sspicli\SecuritySafeHandles.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\sspicli\SSPIWrapper.cs">
+ <Link>Common\Interop\Windows\sspicli\SSPIWrapper.cs</Link>
+ </Compile>
</ItemGroup>
<ItemGroup Condition="'$(TargetsUnix)' == 'true' AND '$(TargetGroup)' == 'netstandard'">
- <Compile Include="System\Net\HttpListener.Unix.cs" />
- <Compile Include="System\Net\HttpListenerContext.Unix.cs" />
- <Compile Include="System\Net\HttpListenerRequest.Unix.cs" />
- <Compile Include="System\Net\HttpListenerResponse.Unix.cs" />
- <Compile Include="System\Net\HttpListenerTimeoutManager.Unix.cs" />
+ <Compile Include="System\Net\Managed\HttpEndPointListener.cs" />
+ <Compile Include="System\Net\Managed\HttpEndPointManager.cs" />
+ <Compile Include="System\Net\Managed\HttpConnection.cs" />
+ <Compile Include="System\Net\Managed\HttpStreamAsyncResult.cs" />
+ <Compile Include="System\Net\Managed\ListenerPrefix.cs" />
+ <Compile Include="System\Net\Managed\HttpRequestStream.Managed.cs" />
+ <Compile Include="System\Net\Managed\HttpListener.Managed.cs" />
+ <Compile Include="System\Net\Managed\HttpListenerContext.Managed.cs" />
+ <Compile Include="System\Net\Managed\HttpListenerRequest.Managed.cs" />
+ <Compile Include="System\Net\Managed\HttpListenerResponse.Managed.cs" />
+ <Compile Include="System\Net\Managed\HttpListenerTimeoutManager.Managed.cs" />
+ <Compile Include="System\Net\Managed\ListenerAsyncResult.Managed.cs" />
+ <Compile Include="System\Net\Managed\HttpHeaderStrings.cs" />
+ <Compile Include="System\Net\Managed\HttpListenerPrefixCollection.Managed.cs" />
+ <Compile Include="System\Net\Managed\ChunkedInputStream.cs" />
+ <Compile Include="System\Net\Managed\ChunkStream.cs" />
+ <Compile Include="System\Net\Managed\HttpResponseStream.Managed.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <PropertyGroup Condition=" '$(TargetsWindows)' == 'true' AND '$(ProjectJson)' == '' ">
+ <ProjectJson>win/project.json</ProjectJson>
+ <ProjectLockJson>win/project.lock.json</ProjectLockJson>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(TargetsUnix)' == 'true' and '$(ProjectJson)' == '' ">
+ <ProjectJson>unix/project.json</ProjectJson>
+ <ProjectLockJson>unix/project.lock.json</ProjectLockJson>
+ </PropertyGroup>
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System" />
</ItemGroup>
diff --git a/src/System.Net.HttpListener/src/System/Net/AuthConstants.cs b/src/System.Net.HttpListener/src/System/Net/AuthConstants.cs
deleted file mode 100644
index b2a2553c6c..0000000000
--- a/src/System.Net.HttpListener/src/System/Net/AuthConstants.cs
+++ /dev/null
@@ -1,15 +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.
-
-namespace System.Net
-{
- internal struct AuthConstants
- {
- public const string NTLM = "NTLM";
- public const string Negotiate = "Negotiate";
- public const string Digest = "Digest";
- public const string Basic = "Basic";
- }
-}
-
diff --git a/src/System.Net.HttpListener/src/System/Net/AuthenticationTypes.cs b/src/System.Net.HttpListener/src/System/Net/AuthenticationTypes.cs
new file mode 100644
index 0000000000..8dc90428f3
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/AuthenticationTypes.cs
@@ -0,0 +1,13 @@
+// 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.Net
+{
+ internal class AuthenticationTypes
+ {
+ internal const string NTLM = "NTLM";
+ internal const string Negotiate = "Negotiate";
+ internal const string Basic = "Basic";
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListener.Unix.cs b/src/System.Net.HttpListener/src/System/Net/HttpListener.Unix.cs
deleted file mode 100644
index bfc1db5b8b..0000000000
--- a/src/System.Net.HttpListener/src/System/Net/HttpListener.Unix.cs
+++ /dev/null
@@ -1,219 +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.Collections;
-using System.Security.Authentication.ExtendedProtection;
-using System.Threading.Tasks;
-
-namespace System.Net
-{
- // TODO: #13187
- public sealed unsafe partial class HttpListener
- {
- public static bool IsSupported
- {
- get
- {
- return false;
- }
- }
-
- public HttpListener()
- {
- throw new PlatformNotSupportedException();
- }
-
- internal void CheckDisposed()
- {
- throw new PlatformNotSupportedException();
- }
-
- internal ICollection PrefixCollection
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- internal void AddPrefix(string uriPrefix)
- {
- throw new PlatformNotSupportedException();
- }
-
- internal bool ContainsPrefix(string uriPrefix)
- {
- throw new PlatformNotSupportedException();
- }
-
- internal bool RemovePrefix(string uriPrefix)
- {
- throw new PlatformNotSupportedException();
- }
-
- internal void RemoveAll(bool clear)
- {
- throw new PlatformNotSupportedException();
- }
-
- public AuthenticationSchemeSelector AuthenticationSchemeSelectorDelegate
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public ExtendedProtectionSelector ExtendedProtectionSelectorDelegate
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public AuthenticationSchemes AuthenticationSchemes
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public ExtendedProtectionPolicy ExtendedProtectionPolicy
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public ServiceNameCollection DefaultServiceNames
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string Realm
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public HttpListenerTimeoutManager TimeoutManager
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool IsListening
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool IgnoreWriteExceptions
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool UnsafeConnectionNtlmAuthentication
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
-
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public HttpListenerPrefixCollection Prefixes
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public void Start()
- {
- throw new PlatformNotSupportedException();
- }
-
- public void Stop()
- {
- throw new PlatformNotSupportedException();
- }
-
- public void Abort()
- {
- throw new PlatformNotSupportedException();
- }
-
- private void Dispose(bool disposing)
- {
- throw new NotImplementedException();
- }
-
- public HttpListenerContext GetContext()
- {
- throw new PlatformNotSupportedException();
- }
-
- public IAsyncResult BeginGetContext(AsyncCallback callback, object state)
- {
- throw new PlatformNotSupportedException();
- }
-
- public HttpListenerContext EndGetContext(IAsyncResult asyncResult)
- {
- throw new PlatformNotSupportedException();
- }
-
- public Task<HttpListenerContext> GetContextAsync()
- {
- throw new PlatformNotSupportedException();
- }
-
- private void Dispose() { }
- }
-} \ No newline at end of file
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListener.cs b/src/System.Net.HttpListener/src/System/Net/HttpListener.cs
index ff61a504d0..d3dfb4ba93 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListener.cs
+++ b/src/System.Net.HttpListener/src/System/Net/HttpListener.cs
@@ -2,7 +2,9 @@
// 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.Security.Authentication.ExtendedProtection;
+using System.Threading.Tasks;
namespace System.Net
{
@@ -10,6 +12,149 @@ namespace System.Net
{
public delegate ExtendedProtectionPolicy ExtendedProtectionSelector(HttpListenerRequest request);
+ private readonly object _internalLock;
+ private volatile State _state; // _state is set only within lock blocks, but often read outside locks.
+ private HttpListenerPrefixCollection _prefixes;
+ internal Hashtable _uriPrefixes = new Hashtable();
+ private bool _ignoreWriteExceptions;
+ private ServiceNameStore _defaultServiceNames;
+ private HttpListenerTimeoutManager _timeoutManager;
+ private ExtendedProtectionPolicy _extendedProtectionPolicy;
+ private AuthenticationSchemeSelector _authenticationDelegate;
+ private AuthenticationSchemes _authenticationScheme = AuthenticationSchemes.Anonymous;
+ private ExtendedProtectionSelector _extendedProtectionSelectorDelegate;
+ private string _realm;
+
+ internal ICollection PrefixCollection => _uriPrefixes.Keys;
+
+ public HttpListener()
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+
+ _state = State.Stopped;
+ _internalLock = new object();
+ _defaultServiceNames = new ServiceNameStore();
+
+ _timeoutManager = new HttpListenerTimeoutManager(this);
+ _prefixes = new HttpListenerPrefixCollection(this);
+
+ // default: no CBT checks on any platform (appcompat reasons); applies also to PolicyEnforcement
+ // config element
+ _extendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never);
+
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
+ }
+
+ public AuthenticationSchemeSelector AuthenticationSchemeSelectorDelegate
+ {
+ get
+ {
+ return _authenticationDelegate;
+ }
+ set
+ {
+ CheckDisposed();
+ _authenticationDelegate = value;
+ }
+ }
+
+ public ExtendedProtectionSelector ExtendedProtectionSelectorDelegate
+ {
+ get
+ {
+ return _extendedProtectionSelectorDelegate;
+ }
+ set
+ {
+ CheckDisposed();
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ _extendedProtectionSelectorDelegate = value;
+ }
+ }
+
+ public AuthenticationSchemes AuthenticationSchemes
+ {
+ get
+ {
+ return _authenticationScheme;
+ }
+ set
+ {
+ CheckDisposed();
+ _authenticationScheme = value;
+ }
+ }
+
+ public ExtendedProtectionPolicy ExtendedProtectionPolicy
+ {
+ get
+ {
+ return _extendedProtectionPolicy;
+ }
+ set
+ {
+ CheckDisposed();
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+ if (value.CustomChannelBinding != null)
+ {
+ throw new ArgumentException(SR.net_listener_cannot_set_custom_cbt, nameof(value));
+ }
+
+ _extendedProtectionPolicy = value;
+ }
+ }
+
+ public ServiceNameCollection DefaultServiceNames
+ {
+ get
+ {
+ return _defaultServiceNames.ServiceNames;
+ }
+ }
+
+ public string Realm
+ {
+ get
+ {
+ return _realm;
+ }
+ set
+ {
+ CheckDisposed();
+ _realm = value;
+ }
+ }
+
+ public bool IsListening => _state == State.Started;
+
+ public bool IgnoreWriteExceptions
+ {
+ get
+ {
+ return _ignoreWriteExceptions;
+ }
+ set
+ {
+ CheckDisposed();
+ _ignoreWriteExceptions = value;
+ }
+ }
+
+ public Task<HttpListenerContext> GetContextAsync()
+ {
+ return Task.Factory.FromAsync(
+ (callback, state) => ((HttpListener)state).BeginGetContext(callback, state),
+ iar => ((HttpListener)iar.AsyncState).EndGetContext(iar),
+ this);
+ }
+
public void Close()
{
if (NetEventSource.IsEnabled) NetEventSource.Enter(this, nameof(Close));
@@ -29,6 +174,21 @@ namespace System.Net
}
}
+ internal void CheckDisposed()
+ {
+ if (_state == State.Closed)
+ {
+ throw new ObjectDisposedException(this.GetType().FullName);
+ }
+ }
+
+ private enum State
+ {
+ Stopped,
+ Started,
+ Closed,
+ }
+
void IDisposable.Dispose()
{
Dispose();
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerContext.Unix.cs b/src/System.Net.HttpListener/src/System/Net/HttpListenerContext.Unix.cs
deleted file mode 100644
index 5659eacf11..0000000000
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerContext.Unix.cs
+++ /dev/null
@@ -1,65 +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.Security.Principal;
-using System.ComponentModel;
-using System.Net.WebSockets;
-using System.Threading.Tasks;
-
-namespace System.Net
-{
- // TODO: #13187
- public sealed unsafe partial class HttpListenerContext
- {
- public HttpListenerRequest Request
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public HttpListenerResponse Response
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public IPrincipal User
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol)
- {
- throw new PlatformNotSupportedException();
- }
-
- public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, TimeSpan keepAliveInterval)
- {
- throw new PlatformNotSupportedException();
- }
-
- public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol,
- int receiveBufferSize,
- TimeSpan keepAliveInterval)
- {
- throw new PlatformNotSupportedException();
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol,
- int receiveBufferSize,
- TimeSpan keepAliveInterval,
- ArraySegment<byte> internalBuffer)
- {
- throw new PlatformNotSupportedException();
- }
- }
-}
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.Unix.cs b/src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.Unix.cs
deleted file mode 100644
index dd3ee0cc7a..0000000000
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.Unix.cs
+++ /dev/null
@@ -1,268 +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.Collections.Specialized;
-using System.IO;
-using System.Security.Cryptography.X509Certificates;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace System.Net
-{
- // TODO: #13187
- public sealed unsafe partial class HttpListenerRequest
- {
- internal ulong RequestId
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string[] AcceptTypes
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public Encoding ContentEncoding
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public long ContentLength64
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string ContentType
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public NameValueCollection Headers
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string HttpMethod
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public Stream InputStream
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool IsAuthenticated
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool IsLocal
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool IsSecureConnection
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool IsWebSocketRequest
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public NameValueCollection QueryString
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string RawUrl
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string ServiceName
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public Uri Url
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public Uri UrlReferrer
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string UserAgent
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string UserHostAddress
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string UserHostName
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string[] UserLanguages
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public int ClientCertificateError
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public X509Certificate2 GetClientCertificate()
- {
- throw new PlatformNotSupportedException();
- }
-
- public IAsyncResult BeginGetClientCertificate(AsyncCallback requestCallback, object state)
- {
- throw new PlatformNotSupportedException();
- }
-
- public X509Certificate2 EndGetClientCertificate(IAsyncResult asyncResult)
- {
- throw new PlatformNotSupportedException();
- }
-
- public Task<X509Certificate2> GetClientCertificateAsync()
- {
- throw new PlatformNotSupportedException();
- }
-
- public TransportContext TransportContext
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public CookieCollection Cookies
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public Version ProtocolVersion
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool HasEntityBody
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool KeepAlive
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public IPEndPoint RemoteEndPoint
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public IPEndPoint LocalEndPoint
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
- }
-}
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.cs b/src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.cs
deleted file mode 100644
index e1d6261853..0000000000
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.cs
+++ /dev/null
@@ -1,19 +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.
-
-namespace System.Net
-{
- public sealed unsafe partial class HttpListenerRequest
- {
- public Guid RequestTraceIdentifier
- {
- get
- {
- Guid guid = new Guid();
- *(1 + (ulong*)&guid) = RequestId;
- return guid;
- }
- }
- }
-}
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequestUriBuilder.cs b/src/System.Net.HttpListener/src/System/Net/HttpListenerRequestUriBuilder.cs
index a28c38fc58..25146bb865 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequestUriBuilder.cs
+++ b/src/System.Net.HttpListener/src/System/Net/HttpListenerRequestUriBuilder.cs
@@ -88,8 +88,8 @@ namespace System.Net
// Creating a Uri from the cooked Uri should really always work: If not, we log at least.
if (!isValid)
{
- if (NetEventSource.IsEnabled) NetEventSource.Error(this,
- SR.Format(SR.net_log_listener_cant_create_uri, _cookedUriScheme, _cookedUriHost, _cookedUriPath, _cookedUriQuery));
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_create_uri, _cookedUriScheme, _cookedUriHost, _cookedUriPath, _cookedUriQuery));
}
}
@@ -113,8 +113,8 @@ namespace System.Net
// Log that we weren't able to create a Uri from the raw string.
if (!isValid)
{
- if (NetEventSource.IsEnabled) NetEventSource.Error(this,
- SR.Format(SR.net_log_listener_cant_create_uri, _cookedUriScheme, _cookedUriHost, _rawPath, _cookedUriQuery));
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_create_uri, _cookedUriScheme, _cookedUriHost, _rawPath, _cookedUriQuery));
}
}
@@ -162,8 +162,8 @@ namespace System.Net
if (result != ParsingResult.Success)
{
- if (NetEventSource.IsEnabled) NetEventSource.Error(this,
- SR.Format(SR.net_log_listener_cant_convert_raw_path, _rawPath, encoding.EncodingName));
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_raw_path, _rawPath, encoding.EncodingName));
}
return result;
@@ -243,8 +243,8 @@ namespace System.Net
int codePointValue;
if (!int.TryParse(codePoint, NumberStyles.HexNumber, null, out codePointValue))
{
- if (NetEventSource.IsEnabled) NetEventSource.Error(this,
- SR.Format(SR.net_log_listener_cant_convert_percent_value, codePoint));
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_percent_value, codePoint));
return false;
}
@@ -258,8 +258,8 @@ namespace System.Net
}
catch (ArgumentOutOfRangeException)
{
- if (NetEventSource.IsEnabled) NetEventSource.Error(this,
- SR.Format(SR.net_log_listener_cant_convert_percent_value, codePoint));
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_percent_value, codePoint));
}
catch (EncoderFallbackException e)
{
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.Unix.cs b/src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.Unix.cs
deleted file mode 100644
index da68de7025..0000000000
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.Unix.cs
+++ /dev/null
@@ -1,198 +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.IO;
-using System.Text;
-
-namespace System.Net
-{
- // TODO: #13187
- public sealed unsafe partial class HttpListenerResponse
- {
- public Encoding ContentEncoding
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string ContentType
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public Stream OutputStream
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string RedirectLocation
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public int StatusCode
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public string StatusDescription
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public CookieCollection Cookies
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public void CopyFrom(HttpListenerResponse templateResponse)
- {
- throw new PlatformNotSupportedException();
- }
-
- public bool SendChunked
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public bool KeepAlive
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public WebHeaderCollection Headers
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public void AddHeader(string name, string value)
- {
- throw new PlatformNotSupportedException();
- }
-
- public void AppendHeader(string name, string value)
- {
- throw new PlatformNotSupportedException();
- }
-
- public void Redirect(string url)
- {
- throw new PlatformNotSupportedException();
- }
-
- public void AppendCookie(Cookie cookie)
- {
- throw new PlatformNotSupportedException();
- }
-
- public void SetCookie(Cookie cookie)
- {
- throw new PlatformNotSupportedException();
- }
-
- public long ContentLength64
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public Version ProtocolVersion
- {
- get
- {
- throw new PlatformNotSupportedException();
- }
- set
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- public void Abort()
- {
- throw new PlatformNotSupportedException();
- }
-
- public void Close(byte[] responseEntity, bool willBlock)
- {
- throw new PlatformNotSupportedException();
- }
-
- private void Dispose(bool disposing)
- {
- throw new PlatformNotSupportedException();
- }
- }
-}
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs b/src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs
index 9c3fb9ba1d..5db1bc91e2 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs
+++ b/src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs
@@ -2,28 +2,98 @@
// 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;
+
namespace System.Net
{
public sealed unsafe partial class HttpListenerResponse : IDisposable
{
- public void Close()
+ private CookieCollection _cookies;
+ private WebHeaderCollection _webHeaders = new WebHeaderCollection();
+
+ public WebHeaderCollection Headers
+ {
+ get
+ {
+ return _webHeaders;
+ }
+ set
+ {
+ _webHeaders = new WebHeaderCollection();
+ foreach (string headerName in value.AllKeys)
+ {
+ _webHeaders.Add(headerName, value[headerName]);
+ }
+ }
+ }
+
+ public CookieCollection Cookies
{
- if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+ get
+ {
+ if (_cookies == null)
+ {
+ _cookies = new CookieCollection();
+ }
+ return _cookies;
+ }
+ set
+ {
+ _cookies = value;
+ }
+ }
+
+ public void AddHeader(string name, string value)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"name={name}, value={value}");
+ Headers.Set(name, value);
+ }
+
+ public void AppendHeader(string name, string value)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"name={name}, value={value}");
+ Headers.Add(value);
+ }
+
+ public void AppendCookie(Cookie cookie)
+ {
+ if (cookie == null)
+ {
+ throw new ArgumentNullException(nameof(cookie));
+ }
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"cookie: {cookie}");
+ Cookies.Add(cookie);
+ }
+
+ public void SetCookie(Cookie cookie)
+ {
+ if (cookie == null)
+ {
+ throw new ArgumentNullException(nameof(cookie));
+ }
+ bool added = false;
try
{
- if (NetEventSource.IsEnabled) NetEventSource.Info(this);
- ((IDisposable)this).Dispose();
+ Cookies.Add(cookie);
+ added = true;
}
- finally
+ catch (CookieException)
+ {
+ Debug.Assert(!added);
+ }
+
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"cookie: {cookie}");
+
+ if (!added)
{
- if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
+ // cookie already existed and couldn't be replaced
+ throw new ArgumentException(SR.net_cookie_exists, nameof(cookie));
}
}
void IDisposable.Dispose()
{
- Dispose(true);
- GC.SuppressFinalize(this);
+ Dispose();
}
}
}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/ChunkStream.cs b/src/System.Net.HttpListener/src/System/Net/Managed/ChunkStream.cs
new file mode 100644
index 0000000000..46143c62f2
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/ChunkStream.cs
@@ -0,0 +1,406 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.ChunkStream
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2003 Ximian, Inc (http://www.ximian.com)
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+namespace System.Net
+{
+ internal sealed class ChunkStream
+ {
+ private enum State
+ {
+ None,
+ PartialSize,
+ Body,
+ BodyFinished,
+ Trailer
+ }
+
+ private class Chunk
+ {
+ public byte[] Bytes;
+ public int Offset;
+
+ public Chunk(byte[] chunk)
+ {
+ this.Bytes = chunk;
+ }
+
+ public int Read(byte[] buffer, int offset, int size)
+ {
+ int nread = (size > Bytes.Length - Offset) ? Bytes.Length - Offset : size;
+ Buffer.BlockCopy(Bytes, Offset, buffer, offset, nread);
+ Offset += nread;
+ return nread;
+ }
+ }
+
+ internal WebHeaderCollection headers;
+ private int _chunkSize;
+ private int _chunkRead;
+ private int _totalWritten;
+ private State _state;
+ private StringBuilder _saved;
+ private bool _sawCR;
+ private bool _gotit;
+ private int _trailerState;
+ private List<Chunk> _chunks;
+
+ public ChunkStream(byte[] buffer, int offset, int size, WebHeaderCollection headers)
+ : this(headers)
+ {
+ Write(buffer, offset, size);
+ }
+
+ public ChunkStream(WebHeaderCollection headers)
+ {
+ this.headers = headers;
+ _saved = new StringBuilder();
+ _chunks = new List<Chunk>();
+ _chunkSize = -1;
+ _totalWritten = 0;
+ }
+
+ public void ResetBuffer()
+ {
+ _chunkSize = -1;
+ _chunkRead = 0;
+ _totalWritten = 0;
+ _chunks.Clear();
+ }
+
+ public void WriteAndReadBack(byte[] buffer, int offset, int size, ref int read)
+ {
+ if (offset + read > 0)
+ Write(buffer, offset, offset + read);
+ read = Read(buffer, offset, size);
+ }
+
+ public int Read(byte[] buffer, int offset, int size)
+ {
+ return ReadFromChunks(buffer, offset, size);
+ }
+
+ private int ReadFromChunks(byte[] buffer, int offset, int size)
+ {
+ int count = _chunks.Count;
+ int nread = 0;
+
+ var chunksForRemoving = new List<Chunk>(count);
+ for (int i = 0; i < count; i++)
+ {
+ Chunk chunk = _chunks[i];
+
+ if (chunk.Offset == chunk.Bytes.Length)
+ {
+ chunksForRemoving.Add(chunk);
+ continue;
+ }
+
+ nread += chunk.Read(buffer, offset + nread, size - nread);
+ if (nread == size)
+ break;
+ }
+
+ foreach (var chunk in chunksForRemoving)
+ _chunks.Remove(chunk);
+
+ return nread;
+ }
+
+ public void Write(byte[] buffer, int offset, int size)
+ {
+ if (offset < size)
+ InternalWrite(buffer, ref offset, size);
+ }
+
+ private void InternalWrite(byte[] buffer, ref int offset, int size)
+ {
+ if (_state == State.None || _state == State.PartialSize)
+ {
+ _state = GetChunkSize(buffer, ref offset, size);
+ if (_state == State.PartialSize)
+ return;
+
+ _saved.Length = 0;
+ _sawCR = false;
+ _gotit = false;
+ }
+
+ if (_state == State.Body && offset < size)
+ {
+ _state = ReadBody(buffer, ref offset, size);
+ if (_state == State.Body)
+ return;
+ }
+
+ if (_state == State.BodyFinished && offset < size)
+ {
+ _state = ReadCRLF(buffer, ref offset, size);
+ if (_state == State.BodyFinished)
+ return;
+
+ _sawCR = false;
+ }
+
+ if (_state == State.Trailer && offset < size)
+ {
+ _state = ReadTrailer(buffer, ref offset, size);
+ if (_state == State.Trailer)
+ return;
+
+ _saved.Length = 0;
+ _sawCR = false;
+ _gotit = false;
+ }
+
+ if (offset < size)
+ InternalWrite(buffer, ref offset, size);
+ }
+
+ public bool WantMore
+ {
+ get { return (_chunkRead != _chunkSize || _chunkSize != 0 || _state != State.None); }
+ }
+
+ public bool DataAvailable
+ {
+ get
+ {
+ int count = _chunks.Count;
+ for (int i = 0; i < count; i++)
+ {
+ Chunk ch = _chunks[i];
+ if (ch == null || ch.Bytes == null)
+ continue;
+ if (ch.Bytes.Length > 0 && ch.Offset < ch.Bytes.Length)
+ return (_state != State.Body);
+ }
+ return false;
+ }
+ }
+
+ public int TotalDataSize
+ {
+ get { return _totalWritten; }
+ }
+
+ public int ChunkLeft
+ {
+ get { return _chunkSize - _chunkRead; }
+ }
+
+ private State ReadBody(byte[] buffer, ref int offset, int size)
+ {
+ if (_chunkSize == 0)
+ return State.BodyFinished;
+
+ int diff = size - offset;
+ if (diff + _chunkRead > _chunkSize)
+ diff = _chunkSize - _chunkRead;
+
+ byte[] chunk = new byte[diff];
+ Buffer.BlockCopy(buffer, offset, chunk, 0, diff);
+ _chunks.Add(new Chunk(chunk));
+ offset += diff;
+ _chunkRead += diff;
+ _totalWritten += diff;
+
+ return (_chunkRead == _chunkSize) ? State.BodyFinished : State.Body;
+ }
+
+ private State GetChunkSize(byte[] buffer, ref int offset, int size)
+ {
+ _chunkRead = 0;
+ _chunkSize = 0;
+ char c = '\0';
+ while (offset < size)
+ {
+ c = (char)buffer[offset++];
+ if (c == '\r')
+ {
+ if (_sawCR)
+ ThrowProtocolViolation("2 CR found");
+
+ _sawCR = true;
+ continue;
+ }
+
+ if (_sawCR && c == '\n')
+ break;
+
+ if (c == ' ')
+ _gotit = true;
+
+ if (!_gotit)
+ _saved.Append(c);
+
+ if (_saved.Length > 20)
+ ThrowProtocolViolation("chunk size too long.");
+ }
+
+ if (!_sawCR || c != '\n')
+ {
+ if (offset < size)
+ ThrowProtocolViolation("Missing \\n");
+
+ try
+ {
+ if (_saved.Length > 0)
+ {
+ _chunkSize = Int32.Parse(RemoveChunkExtension(_saved.ToString()), NumberStyles.HexNumber);
+ }
+ }
+ catch (Exception)
+ {
+ ThrowProtocolViolation("Cannot parse chunk size.");
+ }
+
+ return State.PartialSize;
+ }
+
+ _chunkRead = 0;
+ try
+ {
+ _chunkSize = Int32.Parse(RemoveChunkExtension(_saved.ToString()), NumberStyles.HexNumber);
+ }
+ catch (Exception)
+ {
+ ThrowProtocolViolation("Cannot parse chunk size.");
+ }
+
+ if (_chunkSize == 0)
+ {
+ _trailerState = 2;
+ return State.Trailer;
+ }
+
+ return State.Body;
+ }
+
+ private static string RemoveChunkExtension(string input)
+ {
+ int idx = input.IndexOf(';');
+ if (idx == -1)
+ return input;
+ return input.Substring(0, idx);
+ }
+
+ private State ReadCRLF(byte[] buffer, ref int offset, int size)
+ {
+ if (!_sawCR)
+ {
+ if ((char)buffer[offset++] != '\r')
+ ThrowProtocolViolation("Expecting \\r");
+
+ _sawCR = true;
+ if (offset == size)
+ return State.BodyFinished;
+ }
+
+ if (_sawCR && (char)buffer[offset++] != '\n')
+ ThrowProtocolViolation("Expecting \\n");
+
+ return State.None;
+ }
+
+ private State ReadTrailer(byte[] buffer, ref int offset, int size)
+ {
+ char c = '\0';
+
+ // short path
+ if (_trailerState == 2 && (char)buffer[offset] == '\r' && _saved.Length == 0)
+ {
+ offset++;
+ if (offset < size && (char)buffer[offset] == '\n')
+ {
+ offset++;
+ return State.None;
+ }
+ offset--;
+ }
+
+ int st = _trailerState;
+ string stString = "\r\n\r";
+ while (offset < size && st < 4)
+ {
+ c = (char)buffer[offset++];
+ if ((st == 0 || st == 2) && c == '\r')
+ {
+ st++;
+ continue;
+ }
+
+ if ((st == 1 || st == 3) && c == '\n')
+ {
+ st++;
+ continue;
+ }
+
+ if (st > 0)
+ {
+ _saved.Append(stString.Substring(0, _saved.Length == 0 ? st - 2 : st));
+ st = 0;
+ if (_saved.Length > 4196)
+ ThrowProtocolViolation("Error reading trailer (too long).");
+ }
+ }
+
+ if (st < 4)
+ {
+ _trailerState = st;
+ if (offset < size)
+ ThrowProtocolViolation("Error reading trailer.");
+
+ return State.Trailer;
+ }
+
+ StringReader reader = new StringReader(_saved.ToString());
+ string line;
+ while ((line = reader.ReadLine()) != null && line != "")
+ headers.Add(line);
+
+ return State.None;
+ }
+
+ private static void ThrowProtocolViolation(string message)
+ {
+ WebException we = new WebException(message, null, WebExceptionStatus.ServerProtocolViolation, null);
+ throw we;
+ }
+ }
+}
+
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/ChunkedInputStream.cs b/src/System.Net.HttpListener/src/System/Net/Managed/ChunkedInputStream.cs
new file mode 100644
index 0000000000..0236a8eb18
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/ChunkedInputStream.cs
@@ -0,0 +1,186 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.ChunkedInputStream
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+//
+// Copyright (c) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace System.Net
+{
+ internal sealed class ChunkedInputStream : HttpRequestStream
+ {
+ private bool _disposed;
+ private ChunkStream _decoder;
+ private readonly HttpListenerContext _context;
+ private bool _no_more_data;
+
+ private class ReadBufferState
+ {
+ public byte[] Buffer;
+ public int Offset;
+ public int Count;
+ public int InitialCount;
+ public HttpStreamAsyncResult Ares;
+ public ReadBufferState(byte[] buffer, int offset, int count,
+ HttpStreamAsyncResult ares)
+ {
+ Buffer = buffer;
+ Offset = offset;
+ Count = count;
+ InitialCount = count;
+ Ares = ares;
+ }
+ }
+
+ public ChunkedInputStream(HttpListenerContext context, Stream stream, byte[] buffer, int offset, int length)
+ : base(stream, buffer, offset, length)
+ {
+ _context = context;
+ WebHeaderCollection coll = (WebHeaderCollection)context.Request.Headers;
+ _decoder = new ChunkStream(coll);
+ }
+
+ public ChunkStream Decoder
+ {
+ get { return _decoder; }
+ set { _decoder = value; }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ IAsyncResult ares = BeginRead(buffer, offset, count, null, null);
+ return EndRead(ares);
+ }
+
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback cback, object state)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (buffer == null)
+ throw new ArgumentNullException(nameof(buffer));
+
+ int len = buffer.Length;
+ if (offset < 0 || offset > len)
+ throw new ArgumentOutOfRangeException(nameof(offset), SR.offset_out_of_range);
+
+ if (count < 0 || offset > len - count)
+ throw new ArgumentOutOfRangeException(nameof(count), SR.offset_out_of_range);
+
+ HttpStreamAsyncResult ares = new HttpStreamAsyncResult();
+ ares._callback = cback;
+ ares._state = state;
+ if (_no_more_data)
+ {
+ ares.Complete();
+ return ares;
+ }
+ int nread = _decoder.Read(buffer, offset, count);
+ offset += nread;
+ count -= nread;
+ if (count == 0)
+ {
+ // got all we wanted, no need to bother the decoder yet
+ ares._count = nread;
+ ares.Complete();
+ return ares;
+ }
+ if (!_decoder.WantMore)
+ {
+ _no_more_data = nread == 0;
+ ares._count = nread;
+ ares.Complete();
+ return ares;
+ }
+ ares._buffer = new byte[8192];
+ ares._offset = 0;
+ ares._count = 8192;
+ ReadBufferState rb = new ReadBufferState(buffer, offset, count, ares);
+ rb.InitialCount += nread;
+ base.BeginRead(ares._buffer, ares._offset, ares._count, OnRead, rb);
+ return ares;
+ }
+
+ private void OnRead(IAsyncResult base_ares)
+ {
+ ReadBufferState rb = (ReadBufferState)base_ares.AsyncState;
+ HttpStreamAsyncResult ares = rb.Ares;
+ try
+ {
+ int nread = base.EndRead(base_ares);
+ _decoder.Write(ares._buffer, ares._offset, nread);
+ nread = _decoder.Read(rb.Buffer, rb.Offset, rb.Count);
+ rb.Offset += nread;
+ rb.Count -= nread;
+ if (rb.Count == 0 || !_decoder.WantMore || nread == 0)
+ {
+ _no_more_data = !_decoder.WantMore && nread == 0;
+ ares._count = rb.InitialCount - rb.Count;
+ ares.Complete();
+ return;
+ }
+ ares._offset = 0;
+ ares._count = Math.Min(8192, _decoder.ChunkLeft + 6);
+ base.BeginRead(ares._buffer, ares._offset, ares._count, OnRead, rb);
+ }
+ catch (Exception e)
+ {
+ _context.Connection.SendError(e.Message, 400);
+ ares.Complete(e);
+ }
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ HttpStreamAsyncResult ares = asyncResult as HttpStreamAsyncResult;
+ if (asyncResult == null)
+ throw new ArgumentException(SR.net_io_invalidasyncresult, nameof(asyncResult));
+
+ if (!asyncResult.IsCompleted)
+ asyncResult.AsyncWaitHandle.WaitOne();
+
+ if (ares._error != null)
+ throw new HttpListenerException((int)HttpStatusCode.BadRequest, SR.Format(SR.net_io_operation_aborted, ares._error.Message));
+
+ return ares._count;
+ }
+
+ public override void Close()
+ {
+ if (!_disposed)
+ {
+ _disposed = true;
+ base.Close();
+ }
+ }
+ }
+}
+
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpConnection.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpConnection.cs
new file mode 100644
index 0000000000..f2ec3c1264
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpConnection.cs
@@ -0,0 +1,551 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.HttpConnection
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright (c) 2005-2009 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2012 Xamarin, Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.IO;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Threading;
+
+namespace System.Net
+{
+ internal sealed class HttpConnection
+ {
+ private static AsyncCallback s_onreadCallback = new AsyncCallback(OnRead);
+ private const int BufferSize = 8192;
+ private Socket _socket;
+ private Stream _stream;
+ private HttpEndPointListener _epl;
+ private MemoryStream _memoryStream;
+ private byte[] _buffer;
+ private HttpListenerContext _context;
+ private StringBuilder _currentLine;
+ private ListenerPrefix _prefix;
+ private HttpRequestStream _requestStream;
+ private HttpResponseStream _responseStream;
+ private bool _chunked;
+ private int _reuses;
+ private bool _contextBound;
+ private bool _secure;
+ private X509Certificate _cert;
+ private int _timeout = 90000; // 90k ms for first request, 15k ms from then on
+ private Timer _timer;
+ private IPEndPoint _localEndPoint;
+ private HttpListener _lastListener;
+ private int[] _clientCertErrors;
+ private X509Certificate2 _clientCert;
+ private SslStream _sslStream;
+ private InputState _inputState = InputState.RequestLine;
+ private LineState _lineState = LineState.None;
+ private int _position;
+
+ public HttpConnection(Socket sock, HttpEndPointListener epl, bool secure, X509Certificate cert)
+ {
+ _socket = sock;
+ _epl = epl;
+ _secure = secure;
+ _cert = cert;
+ if (secure == false)
+ {
+ _stream = new NetworkStream(sock, false);
+ }
+ else
+ {
+ _sslStream = epl.Listener.CreateSslStream(new NetworkStream(sock, false), false, (t, c, ch, e) =>
+ {
+ if (c == null)
+ {
+ return true;
+ }
+
+ var c2 = c as X509Certificate2;
+ if (c2 == null)
+ {
+ c2 = new X509Certificate2(c.GetRawCertData());
+ }
+
+ _clientCert = c2;
+ _clientCertErrors = new int[] { (int)e };
+ return true;
+ });
+
+ _stream = _sslStream;
+ }
+
+ _timer = new Timer(OnTimeout, null, Timeout.Infinite, Timeout.Infinite);
+ Init();
+ }
+
+ internal int[] ClientCertificateErrors
+ {
+ get { return _clientCertErrors; }
+ }
+
+ internal X509Certificate2 ClientCertificate
+ {
+ get { return _clientCert; }
+ }
+
+ private void Init()
+ {
+ if (_sslStream != null)
+ {
+ _sslStream.AuthenticateAsServer(_cert, true, (SslProtocols)ServicePointManager.SecurityProtocol, false);
+ }
+
+ _contextBound = false;
+ _requestStream = null;
+ _responseStream = null;
+ _prefix = null;
+ _chunked = false;
+ _memoryStream = new MemoryStream();
+ _position = 0;
+ _inputState = InputState.RequestLine;
+ _lineState = LineState.None;
+ _context = new HttpListenerContext(this);
+ }
+
+ public bool IsClosed
+ {
+ get { return (_socket == null); }
+ }
+
+ public int Reuses
+ {
+ get { return _reuses; }
+ }
+
+ public IPEndPoint LocalEndPoint
+ {
+ get
+ {
+ if (_localEndPoint != null)
+ return _localEndPoint;
+
+ _localEndPoint = (IPEndPoint)_socket.LocalEndPoint;
+ return _localEndPoint;
+ }
+ }
+
+ public IPEndPoint RemoteEndPoint
+ {
+ get { return (IPEndPoint)_socket.RemoteEndPoint; }
+ }
+
+ public bool IsSecure
+ {
+ get { return _secure; }
+ }
+
+ public ListenerPrefix Prefix
+ {
+ get { return _prefix; }
+ set { _prefix = value; }
+ }
+
+ private void OnTimeout(object unused)
+ {
+ CloseSocket();
+ Unbind();
+ }
+
+ public void BeginReadRequest()
+ {
+ if (_buffer == null)
+ _buffer = new byte[BufferSize];
+ try
+ {
+ if (_reuses == 1)
+ _timeout = 15000;
+ _timer.Change(_timeout, Timeout.Infinite);
+ _stream.BeginRead(_buffer, 0, BufferSize, s_onreadCallback, this);
+ }
+ catch
+ {
+ _timer.Change(Timeout.Infinite, Timeout.Infinite);
+ CloseSocket();
+ Unbind();
+ }
+ }
+
+ public HttpRequestStream GetRequestStream(bool chunked, long contentlength)
+ {
+ if (_requestStream == null)
+ {
+ byte[] buffer = _memoryStream.GetBuffer();
+ int length = (int)_memoryStream.Length;
+ _memoryStream = null;
+ if (chunked)
+ {
+ _chunked = true;
+ _context.Response.SendChunked = true;
+ _requestStream = new ChunkedInputStream(_context, _stream, buffer, _position, length - _position);
+ }
+ else
+ {
+ _requestStream = new HttpRequestStream(_stream, buffer, _position, length - _position, contentlength);
+ }
+ }
+ return _requestStream;
+ }
+
+ public HttpResponseStream GetResponseStream()
+ {
+ if (_responseStream == null)
+ {
+ HttpListener listener = _context.Listener;
+
+ if (listener == null)
+ return new HttpResponseStream(_stream, _context.Response, true);
+
+ _responseStream = new HttpResponseStream(_stream, _context.Response, listener.IgnoreWriteExceptions);
+ }
+ return _responseStream;
+ }
+
+ private static void OnRead(IAsyncResult ares)
+ {
+ HttpConnection cnc = (HttpConnection)ares.AsyncState;
+ cnc.OnReadInternal(ares);
+ }
+
+ private void OnReadInternal(IAsyncResult ares)
+ {
+ _timer.Change(Timeout.Infinite, Timeout.Infinite);
+ int nread = -1;
+ try
+ {
+ nread = _stream.EndRead(ares);
+ _memoryStream.Write(_buffer, 0, nread);
+ if (_memoryStream.Length > 32768)
+ {
+ SendError(HttpStatusDescription.Get(400), 400);
+ Close(true);
+ return;
+ }
+ }
+ catch
+ {
+ if (_memoryStream != null && _memoryStream.Length > 0)
+ SendError();
+ if (_socket != null)
+ {
+ CloseSocket();
+ Unbind();
+ }
+ return;
+ }
+
+ if (nread == 0)
+ {
+ CloseSocket();
+ Unbind();
+ return;
+ }
+
+ if (ProcessInput(_memoryStream))
+ {
+ if (!_context.HaveError)
+ _context.Request.FinishInitialization();
+
+ if (_context.HaveError)
+ {
+ SendError();
+ Close(true);
+ return;
+ }
+
+ if (!_epl.BindContext(_context))
+ {
+ SendError("Invalid host", 400);
+ Close(true);
+ return;
+ }
+ HttpListener listener = _context.Listener;
+ if (_lastListener != listener)
+ {
+ RemoveConnection();
+ listener.AddConnection(this);
+ _lastListener = listener;
+ }
+
+ _contextBound = true;
+ listener.RegisterContext(_context);
+ return;
+ }
+ _stream.BeginRead(_buffer, 0, BufferSize, s_onreadCallback, this);
+ }
+
+ private void RemoveConnection()
+ {
+ if (_lastListener == null)
+ _epl.RemoveConnection(this);
+ else
+ _lastListener.RemoveConnection(this);
+ }
+
+ private enum InputState
+ {
+ RequestLine,
+ Headers
+ }
+
+ private enum LineState
+ {
+ None,
+ CR,
+ LF
+ }
+
+ // true -> done processing
+ // false -> need more input
+ private bool ProcessInput(MemoryStream ms)
+ {
+ byte[] buffer = ms.GetBuffer();
+ int len = (int)ms.Length;
+ int used = 0;
+ string line;
+
+ while (true)
+ {
+ if (_context.HaveError)
+ return true;
+
+ if (_position >= len)
+ break;
+
+ try
+ {
+ line = ReadLine(buffer, _position, len - _position, ref used);
+ _position += used;
+ }
+ catch
+ {
+ _context.ErrorMessage = HttpStatusDescription.Get(400);
+ _context.ErrorStatus = 400;
+ return true;
+ }
+
+ if (line == null)
+ break;
+
+ if (line == "")
+ {
+ if (_inputState == InputState.RequestLine)
+ continue;
+ _currentLine = null;
+ ms = null;
+ return true;
+ }
+
+ if (_inputState == InputState.RequestLine)
+ {
+ _context.Request.SetRequestLine(line);
+ _inputState = InputState.Headers;
+ }
+ else
+ {
+ try
+ {
+ _context.Request.AddHeader(line);
+ }
+ catch (Exception e)
+ {
+ _context.ErrorMessage = e.Message;
+ _context.ErrorStatus = 400;
+ return true;
+ }
+ }
+ }
+
+ if (used == len)
+ {
+ ms.SetLength(0);
+ _position = 0;
+ }
+ return false;
+ }
+
+ private string ReadLine(byte[] buffer, int offset, int len, ref int used)
+ {
+ if (_currentLine == null)
+ _currentLine = new StringBuilder(128);
+ int last = offset + len;
+ used = 0;
+ for (int i = offset; i < last && _lineState != LineState.LF; i++)
+ {
+ used++;
+ byte b = buffer[i];
+ if (b == 13)
+ {
+ _lineState = LineState.CR;
+ }
+ else if (b == 10)
+ {
+ _lineState = LineState.LF;
+ }
+ else
+ {
+ _currentLine.Append((char)b);
+ }
+ }
+
+ string result = null;
+ if (_lineState == LineState.LF)
+ {
+ _lineState = LineState.None;
+ result = _currentLine.ToString();
+ _currentLine.Length = 0;
+ }
+
+ return result;
+ }
+
+ public void SendError(string msg, int status)
+ {
+ try
+ {
+ HttpListenerResponse response = _context.Response;
+ response.StatusCode = status;
+ response.ContentType = "text/html";
+ string description = HttpStatusDescription.Get(status);
+ string str;
+ if (msg != null)
+ str = string.Format("<h1>{0} ({1})</h1>", description, msg);
+ else
+ str = string.Format("<h1>{0}</h1>", description);
+
+ byte[] error = _context.Response.ContentEncoding.GetBytes(str);
+ response.Close(error, false);
+ }
+ catch
+ {
+ // response was already closed
+ }
+ }
+
+ public void SendError()
+ {
+ SendError(_context.ErrorMessage, _context.ErrorStatus);
+ }
+
+ private void Unbind()
+ {
+ if (_contextBound)
+ {
+ _epl.UnbindContext(_context);
+ _contextBound = false;
+ }
+ }
+
+ public void Close()
+ {
+ Close(false);
+ }
+
+ private void CloseSocket()
+ {
+ if (_socket == null)
+ return;
+
+ try
+ {
+ _socket.Close();
+ }
+ catch { }
+ finally
+ {
+ _socket = null;
+ }
+
+ RemoveConnection();
+ }
+
+ internal void Close(bool force)
+ {
+ if (_socket != null)
+ {
+ Stream st = GetResponseStream();
+ if (st != null)
+ st.Close();
+
+ _responseStream = null;
+ }
+
+ if (_socket != null)
+ {
+ force |= !_context.Request.KeepAlive;
+ if (!force)
+ force = (_context.Response.Headers[HttpKnownHeaderNames.Connection] == HttpHeaderStrings.Close);
+
+ if (!force && _context.Request.FlushInput())
+ {
+ if (_chunked && _context.Response.ForceCloseChunked == false)
+ {
+ // Don't close. Keep working.
+ _reuses++;
+ Unbind();
+ Init();
+ BeginReadRequest();
+ return;
+ }
+
+ _reuses++;
+ Unbind();
+ Init();
+ BeginReadRequest();
+ return;
+ }
+
+ Socket s = _socket;
+ _socket = null;
+ try
+ {
+ if (s != null)
+ s.Shutdown(SocketShutdown.Both);
+ }
+ catch
+ {
+ }
+ finally
+ {
+ if (s != null)
+ s.Close();
+ }
+ Unbind();
+ RemoveConnection();
+ return;
+ }
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointListener.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointListener.cs
new file mode 100644
index 0000000000..6171cb6787
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointListener.cs
@@ -0,0 +1,401 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.HttpEndPointListener
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2012 Xamarin, Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Collections.Generic;
+using System.Net.Sockets;
+using System.Security.Cryptography.X509Certificates;
+using System.Threading;
+
+namespace System.Net
+{
+ internal sealed class HttpEndPointListener
+ {
+ private HttpListener _listener;
+ private IPEndPoint _endpoint;
+ private Socket _socket;
+ private Dictionary<ListenerPrefix, HttpListener> _prefixes;
+ private List<ListenerPrefix> _unhandledPrefixes; // host = '*'
+ private List<ListenerPrefix> _allPrefixes; // host = '+'
+ private X509Certificate _cert;
+ private bool _secure;
+ private Dictionary<HttpConnection, HttpConnection> _unregisteredConnections;
+
+ public HttpEndPointListener(HttpListener listener, IPAddress addr, int port, bool secure)
+ {
+ _listener = listener;
+
+ if (secure)
+ {
+ _secure = secure;
+ // TODO #14691: Implement functionality to read SSL certificate.
+ _cert = null;
+ }
+
+ _endpoint = new IPEndPoint(addr, port);
+ _socket = new Socket(addr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+ _socket.Bind(_endpoint);
+ _socket.Listen(500);
+ SocketAsyncEventArgs args = new SocketAsyncEventArgs();
+ args.UserToken = this;
+ args.Completed += OnAccept;
+ Socket dummy = null;
+ Accept(_socket, args, ref dummy);
+ _prefixes = new Dictionary<ListenerPrefix, HttpListener>();
+ _unregisteredConnections = new Dictionary<HttpConnection, HttpConnection>();
+ }
+
+ internal HttpListener Listener
+ {
+ get { return _listener; }
+ }
+
+ private static void Accept(Socket socket, SocketAsyncEventArgs e, ref Socket accepted)
+ {
+ e.AcceptSocket = null;
+ bool asyn;
+ try
+ {
+ asyn = socket.AcceptAsync(e);
+ }
+ catch
+ {
+ if (accepted != null)
+ {
+ try
+ {
+ accepted.Close();
+ }
+ catch
+ {
+ }
+ accepted = null;
+ }
+ return;
+ }
+ if (!asyn)
+ {
+ ProcessAccept(e);
+ }
+ }
+
+ private static void ProcessAccept(SocketAsyncEventArgs args)
+ {
+ Socket accepted = null;
+ if (args.SocketError == SocketError.Success)
+ accepted = args.AcceptSocket;
+
+ HttpEndPointListener epl = (HttpEndPointListener)args.UserToken;
+
+ Accept(epl._socket, args, ref accepted);
+ if (accepted == null)
+ return;
+
+ if (epl._secure && epl._cert == null)
+ {
+ accepted.Close();
+ return;
+ }
+ HttpConnection conn = new HttpConnection(accepted, epl, epl._secure, epl._cert);
+ lock (epl._unregisteredConnections)
+ {
+ epl._unregisteredConnections[conn] = conn;
+ }
+ conn.BeginReadRequest();
+ }
+
+ private static void OnAccept(object sender, SocketAsyncEventArgs e)
+ {
+ ProcessAccept(e);
+ }
+
+ internal void RemoveConnection(HttpConnection conn)
+ {
+ lock (_unregisteredConnections)
+ {
+ _unregisteredConnections.Remove(conn);
+ }
+ }
+
+ public bool BindContext(HttpListenerContext context)
+ {
+ HttpListenerRequest req = context.Request;
+ ListenerPrefix prefix;
+ HttpListener listener = SearchListener(req.Url, out prefix);
+ if (listener == null)
+ return false;
+
+ context.Listener = listener;
+ context.Connection.Prefix = prefix;
+ return true;
+ }
+
+ public void UnbindContext(HttpListenerContext context)
+ {
+ if (context == null || context.Request == null)
+ return;
+
+ context.Listener.UnregisterContext(context);
+ }
+
+ private HttpListener SearchListener(Uri uri, out ListenerPrefix prefix)
+ {
+ prefix = null;
+ if (uri == null)
+ return null;
+
+ string host = uri.Host;
+ int port = uri.Port;
+ string path = WebUtility.UrlDecode(uri.AbsolutePath);
+ string pathSlash = path[path.Length - 1] == '/' ? path : path + "/";
+
+ HttpListener bestMatch = null;
+ int bestLength = -1;
+
+ if (host != null && host != "")
+ {
+ Dictionary<ListenerPrefix, HttpListener> localPrefixes = _prefixes;
+ foreach (ListenerPrefix p in localPrefixes.Keys)
+ {
+ string ppath = p.Path;
+ if (ppath.Length < bestLength)
+ continue;
+
+ if (p.Host != host || p.Port != port)
+ continue;
+
+ if (path.StartsWith(ppath) || pathSlash.StartsWith(ppath))
+ {
+ bestLength = ppath.Length;
+ bestMatch = localPrefixes[p];
+ prefix = p;
+ }
+ }
+ if (bestLength != -1)
+ return bestMatch;
+ }
+
+ List<ListenerPrefix> list = _unhandledPrefixes;
+ bestMatch = MatchFromList(host, path, list, out prefix);
+
+ if (path != pathSlash && bestMatch == null)
+ bestMatch = MatchFromList(host, pathSlash, list, out prefix);
+
+ if (bestMatch != null)
+ return bestMatch;
+
+ list = _allPrefixes;
+ bestMatch = MatchFromList(host, path, list, out prefix);
+
+ if (path != pathSlash && bestMatch == null)
+ bestMatch = MatchFromList(host, pathSlash, list, out prefix);
+
+ if (bestMatch != null)
+ return bestMatch;
+
+ return null;
+ }
+
+ private HttpListener MatchFromList(string host, string path, List<ListenerPrefix> list, out ListenerPrefix prefix)
+ {
+ prefix = null;
+ if (list == null)
+ return null;
+
+ HttpListener bestMatch = null;
+ int bestLength = -1;
+
+ foreach (ListenerPrefix p in list)
+ {
+ string ppath = p.Path;
+ if (ppath.Length < bestLength)
+ continue;
+
+ if (path.StartsWith(ppath))
+ {
+ bestLength = ppath.Length;
+ bestMatch = p._listener;
+ prefix = p;
+ }
+ }
+
+ return bestMatch;
+ }
+
+ private void AddSpecial(List<ListenerPrefix> list, ListenerPrefix prefix)
+ {
+ if (list == null)
+ return;
+
+ foreach (ListenerPrefix p in list)
+ {
+ if (p.Path == prefix.Path)
+ throw new HttpListenerException((int)HttpStatusCode.BadRequest, SR.Format(SR.net_listener_already, prefix));
+ }
+ list.Add(prefix);
+ }
+
+ private bool RemoveSpecial(List<ListenerPrefix> list, ListenerPrefix prefix)
+ {
+ if (list == null)
+ return false;
+
+ int c = list.Count;
+ for (int i = 0; i < c; i++)
+ {
+ ListenerPrefix p = list[i];
+ if (p.Path == prefix.Path)
+ {
+ list.RemoveAt(i);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void CheckIfRemove()
+ {
+ if (_prefixes.Count > 0)
+ return;
+
+ List<ListenerPrefix> list = _unhandledPrefixes;
+ if (list != null && list.Count > 0)
+ return;
+
+ list = _allPrefixes;
+ if (list != null && list.Count > 0)
+ return;
+
+ HttpEndPointManager.RemoveEndPoint(this, _endpoint);
+ }
+
+ public void Close()
+ {
+ _socket.Close();
+ lock (_unregisteredConnections)
+ {
+ // Clone the list because RemoveConnection can be called from Close
+ var connections = new List<HttpConnection>(_unregisteredConnections.Keys);
+
+ foreach (HttpConnection c in connections)
+ c.Close(true);
+ _unregisteredConnections.Clear();
+ }
+ }
+
+ public void AddPrefix(ListenerPrefix prefix, HttpListener listener)
+ {
+ List<ListenerPrefix> current;
+ List<ListenerPrefix> future;
+ if (prefix.Host == "*")
+ {
+ do
+ {
+ current = _unhandledPrefixes;
+ future = current != null ? new List<ListenerPrefix>(current) : new List<ListenerPrefix>();
+ prefix._listener = listener;
+ AddSpecial(future, prefix);
+ } while (Interlocked.CompareExchange(ref _unhandledPrefixes, future, current) != current);
+ return;
+ }
+
+ if (prefix.Host == "+")
+ {
+ do
+ {
+ current = _allPrefixes;
+ future = current != null ? new List<ListenerPrefix>(current) : new List<ListenerPrefix>();
+ prefix._listener = listener;
+ AddSpecial(future, prefix);
+ } while (Interlocked.CompareExchange(ref _allPrefixes, future, current) != current);
+ return;
+ }
+
+ Dictionary<ListenerPrefix, HttpListener> prefs, p2;
+ do
+ {
+ prefs = _prefixes;
+ if (prefs.ContainsKey(prefix))
+ {
+ HttpListener other = (HttpListener)prefs[prefix];
+ if (other != listener)
+ throw new HttpListenerException((int)HttpStatusCode.BadRequest, SR.Format(SR.net_listener_already, prefix));
+ return;
+ }
+ p2 = new Dictionary<ListenerPrefix, HttpListener>(prefs);
+ p2[prefix] = listener;
+ } while (Interlocked.CompareExchange(ref _prefixes, p2, prefs) != prefs);
+ }
+
+ public void RemovePrefix(ListenerPrefix prefix, HttpListener listener)
+ {
+ List<ListenerPrefix> current;
+ List<ListenerPrefix> future;
+ if (prefix.Host == "*")
+ {
+ do
+ {
+ current = _unhandledPrefixes;
+ future = current != null ? new List<ListenerPrefix>(current) : new List<ListenerPrefix>();
+ if (!RemoveSpecial(future, prefix))
+ break; // Prefix not found
+ } while (Interlocked.CompareExchange(ref _unhandledPrefixes, future, current) != current);
+
+ CheckIfRemove();
+ return;
+ }
+
+ if (prefix.Host == "+")
+ {
+ do
+ {
+ current = _allPrefixes;
+ future = current != null ? new List<ListenerPrefix>(current) : new List<ListenerPrefix>();
+ if (!RemoveSpecial(future, prefix))
+ break; // Prefix not found
+ } while (Interlocked.CompareExchange(ref _allPrefixes, future, current) != current);
+ CheckIfRemove();
+ return;
+ }
+
+ Dictionary<ListenerPrefix, HttpListener> prefs, p2;
+ do
+ {
+ prefs = _prefixes;
+ if (!prefs.ContainsKey(prefix))
+ break;
+
+ p2 = new Dictionary<ListenerPrefix, HttpListener>(prefs);
+ p2.Remove(prefix);
+ } while (Interlocked.CompareExchange(ref _prefixes, p2, prefs) != prefs);
+ CheckIfRemove();
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointManager.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointManager.cs
new file mode 100644
index 0000000000..8bc866ac2d
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointManager.cs
@@ -0,0 +1,182 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.HttpEndPointManager
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Net
+{
+ internal sealed class HttpEndPointManager
+ {
+ private static Dictionary<IPAddress, Dictionary<int, HttpEndPointListener>> s_ipEndPoints = new Dictionary<IPAddress, Dictionary<int, HttpEndPointListener>>();
+
+ private HttpEndPointManager()
+ {
+ }
+
+ public static void AddListener(HttpListener listener)
+ {
+ List<string> added = new List<string>();
+ try
+ {
+ lock ((s_ipEndPoints as ICollection).SyncRoot)
+ {
+ foreach (string prefix in listener.Prefixes)
+ {
+ AddPrefixInternal(prefix, listener);
+ added.Add(prefix);
+ }
+ }
+ }
+ catch
+ {
+ foreach (string prefix in added)
+ {
+ RemovePrefix(prefix, listener);
+ }
+ throw;
+ }
+ }
+
+ public static void AddPrefix(string prefix, HttpListener listener)
+ {
+ lock ((s_ipEndPoints as ICollection).SyncRoot)
+ {
+ AddPrefixInternal(prefix, listener);
+ }
+ }
+
+ private static void AddPrefixInternal(string p, HttpListener listener)
+ {
+ ListenerPrefix lp = new ListenerPrefix(p);
+ if (lp.Path.IndexOf('%') != -1)
+ throw new HttpListenerException((int)HttpStatusCode.BadRequest, SR.net_invalid_path);
+
+ if (lp.Path.IndexOf("//", StringComparison.Ordinal) != -1)
+ throw new HttpListenerException((int)HttpStatusCode.BadRequest, SR.net_invalid_path);
+
+ // listens on all the interfaces if host name cannot be parsed by IPAddress.
+ HttpEndPointListener epl = GetEPListener(lp.Host, lp.Port, listener, lp.Secure);
+ epl.AddPrefix(lp, listener);
+ }
+
+ private static HttpEndPointListener GetEPListener(string host, int port, HttpListener listener, bool secure)
+ {
+ IPAddress addr;
+ if (host == "*")
+ addr = IPAddress.Any;
+ else if (IPAddress.TryParse(host, out addr) == false)
+ {
+ try
+ {
+ IPHostEntry iphost = Dns.GetHostEntry(host);
+ if (iphost != null)
+ addr = iphost.AddressList[0];
+ else
+ addr = IPAddress.Any;
+ }
+ catch
+ {
+ addr = IPAddress.Any;
+ }
+ }
+ Dictionary<int, HttpEndPointListener> p = null;
+ if (s_ipEndPoints.ContainsKey(addr))
+ {
+ p = s_ipEndPoints[addr];
+ }
+ else
+ {
+ p = new Dictionary<int, HttpEndPointListener>();
+ s_ipEndPoints[addr] = p;
+ }
+
+ HttpEndPointListener epl = null;
+ if (p.ContainsKey(port))
+ {
+ epl = p[port];
+ }
+ else
+ {
+ epl = new HttpEndPointListener(listener, addr, port, secure);
+ p[port] = epl;
+ }
+
+ return epl;
+ }
+
+ public static void RemoveEndPoint(HttpEndPointListener epl, IPEndPoint ep)
+ {
+ lock ((s_ipEndPoints as ICollection).SyncRoot)
+ {
+ Dictionary<int, HttpEndPointListener> p = null;
+ p = s_ipEndPoints[ep.Address];
+ p.Remove(ep.Port);
+ if (p.Count == 0)
+ {
+ s_ipEndPoints.Remove(ep.Address);
+ }
+ epl.Close();
+ }
+ }
+
+ public static void RemoveListener(HttpListener listener)
+ {
+ lock ((s_ipEndPoints as ICollection).SyncRoot)
+ {
+ foreach (string prefix in listener.Prefixes)
+ {
+ RemovePrefixInternal(prefix, listener);
+ }
+ }
+ }
+
+ public static void RemovePrefix(string prefix, HttpListener listener)
+ {
+ lock ((s_ipEndPoints as ICollection).SyncRoot)
+ {
+ RemovePrefixInternal(prefix, listener);
+ }
+ }
+
+ private static void RemovePrefixInternal(string prefix, HttpListener listener)
+ {
+ ListenerPrefix lp = new ListenerPrefix(prefix);
+ if (lp.Path.IndexOf('%') != -1)
+ return;
+
+ if (lp.Path.IndexOf("//", StringComparison.Ordinal) != -1)
+ return;
+
+ HttpEndPointListener epl = GetEPListener(lp.Host, lp.Port, listener, lp.Secure);
+ epl.RemovePrefix(lp, listener);
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpHeaderStrings.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpHeaderStrings.cs
new file mode 100644
index 0000000000..981471e952
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpHeaderStrings.cs
@@ -0,0 +1,15 @@
+// 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.Net
+{
+ internal class HttpHeaderStrings
+ {
+ internal const string Charset = "charset=";
+ internal const string NetCoreServerName = ".NETCore";
+ internal const string Close = "close";
+ internal const string Chunked = "chunked";
+ internal const string KeepAlive = "keep-alive";
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpListener.Managed.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListener.Managed.cs
new file mode 100644
index 0000000000..92c87e20e9
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListener.Managed.cs
@@ -0,0 +1,384 @@
+// 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.Collections.Generic;
+using System.IO;
+using System.Net.Security;
+
+namespace System.Net
+{
+ public sealed unsafe partial class HttpListener
+ {
+ public static bool IsSupported => true;
+
+ private Dictionary<HttpListenerContext, HttpListenerContext> _listenerContexts = new Dictionary<HttpListenerContext, HttpListenerContext>();
+ private List<HttpListenerContext> _contextQueue = new List<HttpListenerContext>();
+ private List<ListenerAsyncResult> _asyncWaitQueue = new List<ListenerAsyncResult>();
+ private Dictionary<HttpConnection, HttpConnection> _connections = new Dictionary<HttpConnection, HttpConnection>();
+
+ internal SslStream CreateSslStream(Stream innerStream, bool ownsStream, RemoteCertificateValidationCallback callback)
+ {
+ return new SslStream(innerStream, ownsStream, callback);
+ }
+
+ public HttpListenerTimeoutManager TimeoutManager
+ {
+ get
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ public HttpListenerPrefixCollection Prefixes
+ {
+ get
+ {
+ CheckDisposed();
+ return _prefixes;
+ }
+ }
+
+ public void Start()
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+ lock (_internalLock)
+ {
+ try
+ {
+ CheckDisposed();
+ if (_state == State.Started)
+ return;
+
+ HttpEndPointManager.AddListener(this);
+
+ _state = State.Started;
+ }
+ catch (Exception exception)
+ {
+ _state = State.Closed;
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, $"Start {exception}");
+ throw;
+ }
+ finally
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
+ }
+ }
+ }
+
+ public bool UnsafeConnectionNtlmAuthentication
+ {
+ get
+ {
+ throw new PlatformNotSupportedException();
+ }
+ set
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ public void Stop()
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+ try
+ {
+ lock (_internalLock)
+ {
+ CheckDisposed();
+ if (_state == State.Stopped)
+ {
+ return;
+ }
+
+ Close(false);
+
+ _state = State.Stopped;
+ }
+ }
+ catch (Exception exception)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, $"Stop {exception}");
+ throw;
+ }
+ finally
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
+ }
+ }
+
+ public void Abort()
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+
+ lock (_internalLock)
+ {
+ try
+ {
+ if (_state == State.Closed)
+ {
+ return;
+ }
+
+ // Just detach and free resources. Don't call Stop (which may throw).
+ if (_state == State.Started)
+ {
+ Close(true);
+ }
+ }
+ catch (Exception exception)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, $"Abort {exception}");
+ throw;
+ }
+ finally
+ {
+ _state = State.Closed;
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
+ }
+ }
+ }
+
+ private void Dispose()
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+
+ lock (_internalLock)
+ {
+ try
+ {
+ if (_state == State.Closed)
+ {
+ return;
+ }
+
+ Close(true);
+ }
+ catch (Exception exception)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, $"Dispose {exception}");
+ throw;
+ }
+ finally
+ {
+ _state = State.Closed;
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
+ }
+ }
+ }
+
+ private void Close(bool force)
+ {
+ CheckDisposed();
+ HttpEndPointManager.RemoveListener(this);
+ Cleanup(force);
+ }
+
+ internal void UnregisterContext(HttpListenerContext context)
+ {
+ lock ((_listenerContexts as ICollection).SyncRoot)
+ {
+ _listenerContexts.Remove(context);
+ }
+ lock ((_contextQueue as ICollection).SyncRoot)
+ {
+ int idx = _contextQueue.IndexOf(context);
+ if (idx >= 0)
+ _contextQueue.RemoveAt(idx);
+ }
+ }
+
+ internal void AddConnection(HttpConnection cnc)
+ {
+ lock ((_connections as ICollection).SyncRoot)
+ {
+ _connections[cnc] = cnc;
+ }
+ }
+
+ internal void RemoveConnection(HttpConnection cnc)
+ {
+ lock ((_connections as ICollection).SyncRoot)
+ {
+ _connections.Remove(cnc);
+ }
+ }
+
+ internal void RegisterContext(HttpListenerContext context)
+ {
+ lock ((_listenerContexts as ICollection).SyncRoot)
+ {
+ _listenerContexts[context] = context;
+ }
+
+ ListenerAsyncResult ares = null;
+ lock ((_asyncWaitQueue as ICollection).SyncRoot)
+ {
+ if (_asyncWaitQueue.Count == 0)
+ {
+ lock ((_contextQueue as ICollection).SyncRoot)
+ _contextQueue.Add(context);
+ }
+ else
+ {
+ ares = _asyncWaitQueue[0];
+ _asyncWaitQueue.RemoveAt(0);
+ }
+ }
+
+ if (ares != null)
+ {
+ ares.Complete(context);
+ }
+ }
+
+ private void Cleanup(bool close_existing)
+ {
+ lock ((_listenerContexts as ICollection).SyncRoot)
+ {
+ if (close_existing)
+ {
+ // Need to copy this since closing will call UnregisterContext
+ ICollection keys = _listenerContexts.Keys;
+ var all = new HttpListenerContext[keys.Count];
+ keys.CopyTo(all, 0);
+ _listenerContexts.Clear();
+ for (int i = all.Length - 1; i >= 0; i--)
+ all[i].Connection.Close(true);
+ }
+
+ lock ((_connections as ICollection).SyncRoot)
+ {
+ ICollection keys = _connections.Keys;
+ var conns = new HttpConnection[keys.Count];
+ keys.CopyTo(conns, 0);
+ _connections.Clear();
+ for (int i = conns.Length - 1; i >= 0; i--)
+ conns[i].Close(true);
+ }
+ lock ((_contextQueue as ICollection).SyncRoot)
+ {
+ var ctxs = (HttpListenerContext[])_contextQueue.ToArray();
+ _contextQueue.Clear();
+ for (int i = ctxs.Length - 1; i >= 0; i--)
+ ctxs[i].Connection.Close(true);
+ }
+
+ lock ((_asyncWaitQueue as ICollection).SyncRoot)
+ {
+ Exception exc = new ObjectDisposedException("listener");
+ foreach (ListenerAsyncResult ares in _asyncWaitQueue)
+ {
+ ares.Complete(exc);
+ }
+ _asyncWaitQueue.Clear();
+ }
+ }
+ }
+
+ private HttpListenerContext GetContextFromQueue()
+ {
+ lock ((_contextQueue as ICollection).SyncRoot)
+ {
+ if (_contextQueue.Count == 0)
+ {
+ return null;
+ }
+
+ HttpListenerContext context = _contextQueue[0];
+ _contextQueue.RemoveAt(0);
+
+ return context;
+ }
+ }
+
+ public IAsyncResult BeginGetContext(AsyncCallback callback, Object state)
+ {
+ CheckDisposed();
+ if (_state != State.Started)
+ {
+ throw new InvalidOperationException(SR.Format(SR.net_listener_mustcall, "Start()"));
+ }
+
+ ListenerAsyncResult ares = new ListenerAsyncResult(callback, state);
+
+ // lock wait_queue early to avoid race conditions
+ lock ((_asyncWaitQueue as ICollection).SyncRoot)
+ {
+ lock ((_contextQueue as ICollection).SyncRoot)
+ {
+ HttpListenerContext ctx = GetContextFromQueue();
+ if (ctx != null)
+ {
+ ares.Complete(ctx, true);
+ return ares;
+ }
+ }
+
+ _asyncWaitQueue.Add(ares);
+ }
+
+ return ares;
+ }
+
+ public HttpListenerContext EndGetContext(IAsyncResult asyncResult)
+ {
+ CheckDisposed();
+ if (asyncResult == null)
+ {
+ throw new ArgumentNullException(nameof(asyncResult));
+ }
+
+ ListenerAsyncResult ares = asyncResult as ListenerAsyncResult;
+ if (ares == null)
+ {
+ throw new ArgumentException(SR.net_io_invalidasyncresult, nameof(asyncResult));
+ }
+ if (ares._endCalled)
+ {
+ throw new InvalidOperationException(SR.Format(SR.net_io_invalidendcall, nameof(EndGetContext)));
+ }
+
+ ares._endCalled = true;
+
+ if (!ares.IsCompleted)
+ ares.AsyncWaitHandle.WaitOne();
+
+ lock ((_asyncWaitQueue as ICollection).SyncRoot)
+ {
+ int idx = _asyncWaitQueue.IndexOf(ares);
+ if (idx >= 0)
+ _asyncWaitQueue.RemoveAt(idx);
+ }
+
+ HttpListenerContext context = ares.GetContext();
+ context.ParseAuthentication(SelectAuthenticationScheme(context));
+
+ return context;
+ }
+
+ internal AuthenticationSchemes SelectAuthenticationScheme(HttpListenerContext context)
+ {
+ return AuthenticationSchemeSelectorDelegate != null ? AuthenticationSchemeSelectorDelegate(context.Request) : _authenticationScheme;
+ }
+
+ public HttpListenerContext GetContext()
+ {
+ if (_state == State.Stopped)
+ {
+ throw new InvalidOperationException(SR.Format(SR.net_listener_mustcall, "Start()"));
+ }
+ if (_prefixes.Count == 0)
+ {
+ throw new InvalidOperationException(SR.Format(SR.net_listener_mustcall, "AddPrefix()"));
+ }
+
+ ListenerAsyncResult ares = (ListenerAsyncResult)BeginGetContext(null, null);
+ ares._inGet = true;
+
+ return EndGetContext(ares);
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerContext.Managed.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerContext.Managed.cs
new file mode 100644
index 0000000000..0b30b24a67
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerContext.Managed.cs
@@ -0,0 +1,144 @@
+// 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.Net.WebSockets;
+using System.Security.Principal;
+using System.Threading.Tasks;
+
+namespace System.Net
+{
+ public sealed unsafe partial class HttpListenerContext
+ {
+ private HttpListenerRequest _request;
+ private HttpListenerResponse _response;
+ private IPrincipal _user;
+ private HttpConnection _connection;
+ private string _error;
+ private int _err_status = 400;
+ internal HttpListener Listener;
+
+ internal HttpListenerContext(HttpConnection cnc)
+ {
+ _connection = cnc;
+ _request = new HttpListenerRequest(this);
+ _response = new HttpListenerResponse(this);
+ }
+
+ internal int ErrorStatus
+ {
+ get { return _err_status; }
+ set { _err_status = value; }
+ }
+
+ internal string ErrorMessage
+ {
+ get { return _error; }
+ set { _error = value; }
+ }
+
+ internal bool HaveError
+ {
+ get { return (_error != null); }
+ }
+
+ internal HttpConnection Connection
+ {
+ get { return _connection; }
+ }
+
+ public HttpListenerRequest Request
+ {
+ get { return _request; }
+ }
+
+ public HttpListenerResponse Response
+ {
+ get { return _response; }
+ }
+
+ public IPrincipal User
+ {
+ get { return _user; }
+ }
+
+ internal void ParseAuthentication(AuthenticationSchemes expectedSchemes)
+ {
+ if (expectedSchemes == AuthenticationSchemes.Anonymous)
+ return;
+
+ string header = _request.Headers[HttpKnownHeaderNames.Authorization];
+ if (header == null || header.Length < 2)
+ return;
+
+ string[] authenticationData = header.Split(new char[] { ' ' }, 2);
+ if (string.Compare(authenticationData[0], AuthenticationTypes.Basic, true) == 0)
+ {
+ _user = ParseBasicAuthentication(authenticationData[1]);
+ }
+ }
+
+ internal IPrincipal ParseBasicAuthentication(string authData)
+ {
+ try
+ {
+ // Basic AUTH Data is a formatted Base64 String
+ string user = null;
+ string password = null;
+ int pos = -1;
+ string authString = Text.Encoding.Default.GetString(Convert.FromBase64String(authData));
+
+ // The format is DOMAIN\username:password
+ // Domain is optional
+
+ pos = authString.IndexOf(':');
+
+ // parse the password off the end
+ password = authString.Substring(pos + 1);
+
+ // discard the password
+ authString = authString.Substring(0, pos);
+
+ // check if there is a domain
+ pos = authString.IndexOf('\\');
+
+ if (pos > 0)
+ {
+ user = authString.Substring(pos);
+ }
+ else
+ {
+ user = authString;
+ }
+
+ HttpListenerBasicIdentity identity = new HttpListenerBasicIdentity(user, password);
+ return new GenericPrincipal(identity, new string[0]);
+ }
+ catch (Exception)
+ {
+ // Invalid auth data is swallowed silently
+ return null;
+ }
+ }
+
+ public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, TimeSpan keepAliveInterval)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment<byte> internalBuffer)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerPrefixCollection.Managed.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerPrefixCollection.Managed.cs
new file mode 100644
index 0000000000..8fb1be85bf
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerPrefixCollection.Managed.cs
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.HttpListenerPrefixCollection.cs
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+//
+// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Net
+{
+ public class HttpListenerPrefixCollection : ICollection<string>
+ {
+ private List<string> _prefixes = new List<string>();
+ private HttpListener _listener;
+
+ internal HttpListenerPrefixCollection(HttpListener listener)
+ {
+ _listener = listener;
+ }
+
+ public int Count
+ {
+ get { return _prefixes.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public bool IsSynchronized
+ {
+ get { return false; }
+ }
+
+ public void Add(string uriPrefix)
+ {
+ _listener.CheckDisposed();
+ ListenerPrefix.CheckUri(uriPrefix);
+ if (_prefixes.Contains(uriPrefix))
+ return;
+
+ _prefixes.Add(uriPrefix);
+ if (_listener.IsListening)
+ HttpEndPointManager.AddPrefix(uriPrefix, _listener);
+ }
+
+ public void Clear()
+ {
+ _listener.CheckDisposed();
+ _prefixes.Clear();
+ if (_listener.IsListening)
+ HttpEndPointManager.RemoveListener(_listener);
+ }
+
+ public bool Contains(string uriPrefix)
+ {
+ _listener.CheckDisposed();
+ return _prefixes.Contains(uriPrefix);
+ }
+
+ public void CopyTo(string[] array, int offset)
+ {
+ _listener.CheckDisposed();
+ _prefixes.CopyTo(array, offset);
+ }
+
+ public void CopyTo(Array array, int offset)
+ {
+ _listener.CheckDisposed();
+ ((ICollection)_prefixes).CopyTo(array, offset);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _prefixes.GetEnumerator();
+ }
+
+ public bool Remove(string uriPrefix)
+ {
+ _listener.CheckDisposed();
+ if (uriPrefix == null)
+ throw new ArgumentNullException(nameof(uriPrefix));
+
+ bool result = _prefixes.Remove(uriPrefix);
+ if (result && _listener.IsListening)
+ HttpEndPointManager.RemovePrefix(uriPrefix, _listener);
+
+ return result;
+ }
+
+ public IEnumerator<string> GetEnumerator()
+ {
+ return _prefixes.GetEnumerator();
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerRequest.Managed.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerRequest.Managed.cs
new file mode 100644
index 0000000000..3b75eec916
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerRequest.Managed.cs
@@ -0,0 +1,656 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.HttpListenerRequest
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+// Marek Safar (marek.safar@gmail.com)
+//
+// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2011-2012 Xamarin, Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Collections;
+using System.Collections.Specialized;
+using System.Globalization;
+using System.IO;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Security.Authentication.ExtendedProtection;
+using System.Threading.Tasks;
+using System.Net;
+
+namespace System.Net
+{
+ public sealed partial class HttpListenerRequest
+ {
+ private class Context : TransportContext
+ {
+ public override ChannelBinding GetChannelBinding(ChannelBindingKind kind)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ private string[] _accept_types;
+ private Encoding _content_encoding;
+ private long _content_length;
+ private bool _cl_set;
+ private CookieCollection _cookies;
+ private WebHeaderCollection _headers;
+ private string _method;
+ private Stream _input_stream;
+ private Version _version;
+ private NameValueCollection _query_string; // check if null is ok, check if read-only, check case-sensitiveness
+ private string _raw_url;
+ private Uri _url;
+ private Uri _referrer;
+ private string[] _user_languages;
+ private HttpListenerContext _context;
+ private bool _is_chunked;
+ private bool _ka_set;
+ private bool _keep_alive;
+ private delegate X509Certificate2 GCCDelegate();
+ private GCCDelegate _gccDelegate;
+
+ private static byte[] s_100continue = Encoding.ASCII.GetBytes("HTTP/1.1 100 Continue\r\n\r\n");
+
+ internal HttpListenerRequest(HttpListenerContext context)
+ {
+ _context = context;
+ _headers = new WebHeaderCollection();
+ _version = HttpVersion.Version10;
+ }
+
+ private static char[] s_separators = new char[] { ' ' };
+
+ internal void SetRequestLine(string req)
+ {
+ string[] parts = req.Split(s_separators, 3);
+ if (parts.Length != 3)
+ {
+ _context.ErrorMessage = "Invalid request line (parts).";
+ return;
+ }
+
+ _method = parts[0];
+ foreach (char c in _method)
+ {
+ int ic = (int)c;
+
+ if ((ic >= 'A' && ic <= 'Z') ||
+ (ic > 32 && c < 127 && c != '(' && c != ')' && c != '<' &&
+ c != '<' && c != '>' && c != '@' && c != ',' && c != ';' &&
+ c != ':' && c != '\\' && c != '"' && c != '/' && c != '[' &&
+ c != ']' && c != '?' && c != '=' && c != '{' && c != '}'))
+ continue;
+
+ _context.ErrorMessage = "(Invalid verb)";
+ return;
+ }
+
+ _raw_url = parts[1];
+ if (parts[2].Length != 8 || !parts[2].StartsWith("HTTP/"))
+ {
+ _context.ErrorMessage = "Invalid request line (version).";
+ return;
+ }
+
+ try
+ {
+ _version = new Version(parts[2].Substring(5));
+ if (_version.Major < 1)
+ throw new Exception();
+ }
+ catch
+ {
+ _context.ErrorMessage = "Invalid request line (version).";
+ return;
+ }
+ }
+
+ private void CreateQueryString(string query)
+ {
+ if (query == null || query.Length == 0)
+ {
+ _query_string = new NameValueCollection(1);
+ return;
+ }
+
+ _query_string = new NameValueCollection();
+ if (query[0] == '?')
+ query = query.Substring(1);
+ string[] components = query.Split('&');
+ foreach (string kv in components)
+ {
+ int pos = kv.IndexOf('=');
+ if (pos == -1)
+ {
+ _query_string.Add(null, WebUtility.UrlDecode(kv));
+ }
+ else
+ {
+ string key = WebUtility.UrlDecode(kv.Substring(0, pos));
+ string val = WebUtility.UrlDecode(kv.Substring(pos + 1));
+
+ _query_string.Add(key, val);
+ }
+ }
+ }
+
+ private static bool MaybeUri(string s)
+ {
+ int p = s.IndexOf(':');
+ if (p == -1)
+ return false;
+
+ if (p >= 10)
+ return false;
+
+ return IsPredefinedScheme(s.Substring(0, p));
+ }
+
+ private static bool IsPredefinedScheme(string scheme)
+ {
+ if (scheme == null || scheme.Length < 3)
+ return false;
+
+ char c = scheme[0];
+ if (c == 'h')
+ return (scheme == "http" || scheme == "https");
+ if (c == 'f')
+ return (scheme == "file" || scheme == "ftp");
+
+ if (c == 'n')
+ {
+ c = scheme[1];
+ if (c == 'e')
+ return (scheme == "news" || scheme == "net.pipe" || scheme == "net.tcp");
+ if (scheme == "nntp")
+ return true;
+ return false;
+ }
+ if ((c == 'g' && scheme == "gopher") || (c == 'm' && scheme == "mailto"))
+ return true;
+
+ return false;
+ }
+
+ internal void FinishInitialization()
+ {
+ string host = UserHostName;
+ if (_version > HttpVersion.Version10 && (host == null || host.Length == 0))
+ {
+ _context.ErrorMessage = "Invalid host name";
+ return;
+ }
+
+ string path;
+ Uri raw_uri = null;
+ if (MaybeUri(_raw_url.ToLowerInvariant()) && Uri.TryCreate(_raw_url, UriKind.Absolute, out raw_uri))
+ path = raw_uri.PathAndQuery;
+ else
+ path = _raw_url;
+
+ if ((host == null || host.Length == 0))
+ host = UserHostAddress;
+
+ if (raw_uri != null)
+ host = raw_uri.Host;
+
+ int colon = host.IndexOf(':');
+ if (colon >= 0)
+ host = host.Substring(0, colon);
+
+ string base_uri = String.Format("{0}://{1}:{2}",
+ (IsSecureConnection) ? "https" : "http",
+ host, LocalEndPoint.Port);
+
+ if (!Uri.TryCreate(base_uri + path, UriKind.Absolute, out _url))
+ {
+ _context.ErrorMessage = WebUtility.HtmlEncode("Invalid url: " + base_uri + path);
+ return;
+ }
+
+ CreateQueryString(_url.Query);
+
+ _url = HttpListenerRequestUriBuilder.GetRequestUri(_raw_url, _url.Scheme,
+ _url.Authority, _url.LocalPath, _url.Query);
+
+ if (_version >= HttpVersion.Version11)
+ {
+ string t_encoding = Headers["Transfer-Encoding"];
+ _is_chunked = (t_encoding != null && String.Compare(t_encoding, "chunked", StringComparison.OrdinalIgnoreCase) == 0);
+ // 'identity' is not valid!
+ if (t_encoding != null && !_is_chunked)
+ {
+ _context.Connection.SendError(null, 501);
+ return;
+ }
+ }
+
+ if (!_is_chunked && !_cl_set)
+ {
+ if (String.Compare(_method, "POST", StringComparison.OrdinalIgnoreCase) == 0 ||
+ String.Compare(_method, "PUT", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ _context.Connection.SendError(null, 411);
+ return;
+ }
+ }
+
+ if (String.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ HttpResponseStream output = _context.Connection.GetResponseStream();
+ output.InternalWrite(s_100continue, 0, s_100continue.Length);
+ }
+ }
+
+ internal static string Unquote(String str)
+ {
+ int start = str.IndexOf('\"');
+ int end = str.LastIndexOf('\"');
+ if (start >= 0 && end >= 0)
+ str = str.Substring(start + 1, end - 1);
+ return str.Trim();
+ }
+
+ internal void AddHeader(string header)
+ {
+ int colon = header.IndexOf(':');
+ if (colon == -1 || colon == 0)
+ {
+ _context.ErrorMessage = HttpStatusDescription.Get(400);
+ _context.ErrorStatus = 400;
+ return;
+ }
+
+ string name = header.Substring(0, colon).Trim();
+ string val = header.Substring(colon + 1).Trim();
+ string lower = name.ToLower(CultureInfo.InvariantCulture);
+ _headers.Set(name, val);
+ switch (lower)
+ {
+ case "accept-language":
+ _user_languages = val.Split(','); // yes, only split with a ','
+ break;
+ case "accept":
+ _accept_types = val.Split(','); // yes, only split with a ','
+ break;
+ case "content-length":
+ try
+ {
+ _content_length = long.Parse(val.Trim());
+ if (_content_length < 0)
+ _context.ErrorMessage = "Invalid Content-Length.";
+ _cl_set = true;
+ }
+ catch
+ {
+ _context.ErrorMessage = "Invalid Content-Length.";
+ }
+
+ break;
+ case "referer":
+ try
+ {
+ _referrer = new Uri(val);
+ }
+ catch
+ {
+ _referrer = null;
+ }
+
+ break;
+ case "cookie":
+ if (_cookies == null)
+ _cookies = new CookieCollection();
+
+ string[] cookieStrings = val.Split(new char[] { ',', ';' });
+ Cookie current = null;
+ int version = 0;
+ foreach (string cookieString in cookieStrings)
+ {
+ string str = cookieString.Trim();
+ if (str.Length == 0)
+ continue;
+ if (str.StartsWith("$Version"))
+ {
+ version = Int32.Parse(Unquote(str.Substring(str.IndexOf('=') + 1)));
+ }
+ else if (str.StartsWith("$Path"))
+ {
+ if (current != null)
+ current.Path = str.Substring(str.IndexOf('=') + 1).Trim();
+ }
+ else if (str.StartsWith("$Domain"))
+ {
+ if (current != null)
+ current.Domain = str.Substring(str.IndexOf('=') + 1).Trim();
+ }
+ else if (str.StartsWith("$Port"))
+ {
+ if (current != null)
+ current.Port = str.Substring(str.IndexOf('=') + 1).Trim();
+ }
+ else
+ {
+ if (current != null)
+ {
+ _cookies.Add(current);
+ }
+ current = new Cookie();
+ int idx = str.IndexOf('=');
+ if (idx > 0)
+ {
+ current.Name = str.Substring(0, idx).Trim();
+ current.Value = str.Substring(idx + 1).Trim();
+ }
+ else
+ {
+ current.Name = str.Trim();
+ current.Value = String.Empty;
+ }
+ current.Version = version;
+ }
+ }
+ if (current != null)
+ {
+ _cookies.Add(current);
+ }
+ break;
+ }
+ }
+
+ // returns true is the stream could be reused.
+ internal bool FlushInput()
+ {
+ if (!HasEntityBody)
+ return true;
+
+ int length = 2048;
+ if (_content_length > 0)
+ length = (int)Math.Min(_content_length, (long)length);
+
+ byte[] bytes = new byte[length];
+ while (true)
+ {
+ try
+ {
+ IAsyncResult ares = InputStream.BeginRead(bytes, 0, length, null, null);
+ if (!ares.IsCompleted && !ares.AsyncWaitHandle.WaitOne(1000))
+ return false;
+ if (InputStream.EndRead(ares) <= 0)
+ return true;
+ }
+ catch (ObjectDisposedException)
+ {
+ _input_stream = null;
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ public string[] AcceptTypes
+ {
+ get { return _accept_types; }
+ }
+
+ public int ClientCertificateError
+ {
+ get
+ {
+ HttpConnection cnc = _context.Connection;
+ if (cnc.ClientCertificate == null)
+ throw new InvalidOperationException(SR.net_no_client_certificate);
+ int[] errors = cnc.ClientCertificateErrors;
+ if (errors != null && errors.Length > 0)
+ return errors[0];
+ return 0;
+ }
+ }
+
+ public Encoding ContentEncoding
+ {
+ get
+ {
+ if (_content_encoding == null)
+ _content_encoding = Encoding.Default;
+ return _content_encoding;
+ }
+ }
+
+ public long ContentLength64
+ {
+ get { return _content_length; }
+ }
+
+ public string ContentType
+ {
+ get { return _headers["content-type"]; }
+ }
+
+ public CookieCollection Cookies
+ {
+ get
+ {
+ if (_cookies == null)
+ _cookies = new CookieCollection();
+ return _cookies;
+ }
+ }
+
+ public bool HasEntityBody
+ {
+ get { return (_content_length > 0 || _is_chunked); }
+ }
+
+ public NameValueCollection Headers
+ {
+ get { return _headers; }
+ }
+
+ public string HttpMethod
+ {
+ get { return _method; }
+ }
+
+ public Stream InputStream
+ {
+ get
+ {
+ if (_input_stream == null)
+ {
+ if (_is_chunked || _content_length > 0)
+ _input_stream = _context.Connection.GetRequestStream(_is_chunked, _content_length);
+ else
+ _input_stream = Stream.Null;
+ }
+
+ return _input_stream;
+ }
+ }
+
+ public bool IsAuthenticated
+ {
+ get { return false; }
+ }
+
+ public bool IsLocal
+ {
+ get { return LocalEndPoint.Address.Equals(RemoteEndPoint.Address); }
+ }
+
+ public bool IsSecureConnection
+ {
+ get { return _context.Connection.IsSecure; }
+ }
+
+ public bool KeepAlive
+ {
+ get
+ {
+ if (_ka_set)
+ return _keep_alive;
+
+ _ka_set = true;
+ // 1. Connection header
+ // 2. Protocol (1.1 == keep-alive by default)
+ // 3. Keep-Alive header
+ string cnc = _headers["Connection"];
+ if (!String.IsNullOrEmpty(cnc))
+ {
+ _keep_alive = (0 == String.Compare(cnc, "keep-alive", StringComparison.OrdinalIgnoreCase));
+ }
+ else if (_version == HttpVersion.Version11)
+ {
+ _keep_alive = true;
+ }
+ else
+ {
+ cnc = _headers["keep-alive"];
+ if (!String.IsNullOrEmpty(cnc))
+ _keep_alive = (0 != String.Compare(cnc, "closed", StringComparison.OrdinalIgnoreCase));
+ }
+ return _keep_alive;
+ }
+ }
+
+ public IPEndPoint LocalEndPoint
+ {
+ get { return _context.Connection.LocalEndPoint; }
+ }
+
+ public Version ProtocolVersion
+ {
+ get { return _version; }
+ }
+
+ public NameValueCollection QueryString
+ {
+ get { return _query_string; }
+ }
+
+ public string RawUrl
+ {
+ get { return _raw_url; }
+ }
+
+ public IPEndPoint RemoteEndPoint
+ {
+ get { return _context.Connection.RemoteEndPoint; }
+ }
+
+ public Guid RequestTraceIdentifier
+ {
+ get { return Guid.Empty; }
+ }
+
+ public Uri Url
+ {
+ get { return _url; }
+ }
+
+ public Uri UrlReferrer
+ {
+ get { return _referrer; }
+ }
+
+ public string UserAgent
+ {
+ get { return _headers["user-agent"]; }
+ }
+
+ public string UserHostAddress
+ {
+ get { return LocalEndPoint.ToString(); }
+ }
+
+ public string UserHostName
+ {
+ get { return _headers["host"]; }
+ }
+
+ public string[] UserLanguages
+ {
+ get { return _user_languages; }
+ }
+
+ public IAsyncResult BeginGetClientCertificate(AsyncCallback requestCallback, object state)
+ {
+ if (_gccDelegate == null)
+ _gccDelegate = new GCCDelegate(GetClientCertificate);
+ return _gccDelegate.BeginInvoke(requestCallback, state);
+ }
+
+ public X509Certificate2 EndGetClientCertificate(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ if (_gccDelegate == null)
+ throw new InvalidOperationException();
+
+ return _gccDelegate.EndInvoke(asyncResult);
+ }
+
+ public X509Certificate2 GetClientCertificate()
+ {
+ return _context.Connection.ClientCertificate;
+ }
+
+ public string ServiceName
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public TransportContext TransportContext
+ {
+ get
+ {
+ return new Context();
+ }
+ }
+
+ public bool IsWebSocketRequest
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public Task<X509Certificate2> GetClientCertificateAsync()
+ {
+ return Task<X509Certificate2>.Factory.FromAsync(BeginGetClientCertificate, EndGetClientCertificate, null);
+ }
+ }
+}
+
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerResponse.Managed.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerResponse.Managed.cs
new file mode 100644
index 0000000000..1a3a2ee15d
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerResponse.Managed.cs
@@ -0,0 +1,475 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.HttpListenerResponse
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+//
+// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+namespace System.Net
+{
+ public sealed partial class HttpListenerResponse : IDisposable
+ {
+ private bool _disposed;
+ private Encoding _contentEncoding;
+ private long _contentLength;
+ private bool _clSet;
+ private string _contentType;
+ private bool _keepAlive = true;
+ private HttpResponseStream _outputStream;
+ private Version _version = HttpVersion.Version11;
+ private string _location;
+ private int _statusCode = 200;
+ private string _statusDescription = "OK";
+ private bool _chunked;
+ private HttpListenerContext _context;
+ internal bool _headersSent;
+ internal object _headersLock = new object();
+ private bool _forceCloseChunked;
+
+ internal HttpListenerResponse(HttpListenerContext context)
+ {
+ _context = context;
+ }
+
+ internal bool ForceCloseChunked
+ {
+ get { return _forceCloseChunked; }
+ }
+
+ public Encoding ContentEncoding
+ {
+ get
+ {
+ if (_contentEncoding == null)
+ {
+ _contentEncoding = Encoding.Default;
+ }
+
+ return _contentEncoding;
+ }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (_headersSent)
+ throw new InvalidOperationException(SR.net_cannot_change_after_headers);
+
+ _contentEncoding = value;
+ }
+ }
+
+ public long ContentLength64
+ {
+ get { return _contentLength; }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (_headersSent)
+ throw new InvalidOperationException(SR.net_cannot_change_after_headers);
+
+ if (value < 0)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.net_clsmall);
+
+ _clSet = true;
+ _contentLength = value;
+ }
+ }
+
+ public string ContentType
+ {
+ get { return _contentType; }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (_headersSent)
+ throw new InvalidOperationException(SR.net_cannot_change_after_headers);
+
+ _contentType = value;
+ }
+ }
+
+ public bool KeepAlive
+ {
+ get { return _keepAlive; }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (_headersSent)
+ throw new InvalidOperationException(SR.net_cannot_change_after_headers);
+
+ _keepAlive = value;
+ }
+ }
+
+ public Stream OutputStream
+ {
+ get
+ {
+ if (_outputStream == null)
+ _outputStream = _context.Connection.GetResponseStream();
+ return _outputStream;
+ }
+ }
+
+ public Version ProtocolVersion
+ {
+ get { return _version; }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (_headersSent)
+ throw new InvalidOperationException(SR.net_cannot_change_after_headers);
+
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+
+ if (value.Major != 1 || (value.Minor != 0 && value.Minor != 1))
+ throw new ArgumentException(SR.net_wrongversion, nameof(value));
+
+ _version = value;
+ }
+ }
+
+ public string RedirectLocation
+ {
+ get { return _location; }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (_headersSent)
+ throw new InvalidOperationException(SR.net_cannot_change_after_headers);
+
+ _location = value;
+ }
+ }
+
+ public bool SendChunked
+ {
+ get { return _chunked; }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (_headersSent)
+ throw new InvalidOperationException(SR.net_cannot_change_after_headers);
+
+ _chunked = value;
+ }
+ }
+
+ public int StatusCode
+ {
+ get { return _statusCode; }
+ set
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (_headersSent)
+ throw new InvalidOperationException(SR.net_cannot_change_after_headers);
+
+ if (value < 100 || value > 999)
+ throw new ProtocolViolationException(SR.net_invalidstatus);
+
+ _statusCode = value;
+ }
+ }
+
+ public string StatusDescription
+ {
+ get { return _statusDescription; }
+ set
+ {
+ _statusDescription = value;
+ }
+ }
+
+ private void Dispose()
+ {
+ Close(true);
+ }
+
+ public void Close()
+ {
+ if (_disposed)
+ return;
+
+ Close(false);
+ }
+
+ public void Abort()
+ {
+ if (_disposed)
+ return;
+
+ Close(true);
+ }
+
+ private void Close(bool force)
+ {
+ _disposed = true;
+ _context.Connection.Close(force);
+ }
+
+ public void Close(byte[] responseEntity, bool willBlock)
+ {
+ if (_disposed)
+ return;
+
+ if (responseEntity == null)
+ throw new ArgumentNullException(nameof(responseEntity));
+
+ ContentLength64 = responseEntity.Length;
+ OutputStream.Write(responseEntity, 0, (int)_contentLength);
+ Close(false);
+ }
+
+ public void CopyFrom(HttpListenerResponse templateResponse)
+ {
+ _webHeaders.Clear();
+ _webHeaders.Add(templateResponse._webHeaders);
+ _contentLength = templateResponse._contentLength;
+ _statusCode = templateResponse._statusCode;
+ _statusDescription = templateResponse._statusDescription;
+ _keepAlive = templateResponse._keepAlive;
+ _version = templateResponse._version;
+ }
+
+ public void Redirect(string url)
+ {
+ StatusCode = 302; // Found
+ _location = url;
+ }
+
+ private bool FindCookie(Cookie cookie)
+ {
+ string name = cookie.Name;
+ string domain = cookie.Domain;
+ string path = cookie.Path;
+ foreach (Cookie c in _cookies)
+ {
+ if (name != c.Name)
+ continue;
+ if (domain != c.Domain)
+ continue;
+ if (path == c.Path)
+ return true;
+ }
+
+ return false;
+ }
+
+ internal void SendHeaders(bool closing, MemoryStream ms)
+ {
+ Encoding encoding = _contentEncoding;
+ if (encoding == null)
+ encoding = Encoding.Default;
+
+ if (_contentType != null)
+ {
+ if (_contentEncoding != null && _contentType.IndexOf(HttpHeaderStrings.Charset, StringComparison.Ordinal) == -1)
+ {
+ string enc_name = _contentEncoding.WebName;
+ _webHeaders.Set(HttpKnownHeaderNames.ContentType, _contentType + "; " + HttpHeaderStrings.Charset + enc_name);
+ }
+ else
+ {
+ _webHeaders.Set(HttpKnownHeaderNames.ContentType, _contentType);
+ }
+ }
+
+ if (_webHeaders[HttpKnownHeaderNames.Server] == null)
+ _webHeaders.Set(HttpKnownHeaderNames.Server, HttpHeaderStrings.NetCoreServerName);
+
+ CultureInfo inv = CultureInfo.InvariantCulture;
+ if (_webHeaders[HttpKnownHeaderNames.Date] == null)
+ _webHeaders.Set(HttpKnownHeaderNames.Date, DateTime.UtcNow.ToString("r", inv));
+
+ if (!_chunked)
+ {
+ if (!_clSet && closing)
+ {
+ _clSet = true;
+ _contentLength = 0;
+ }
+
+ if (_clSet)
+ _webHeaders.Set(HttpKnownHeaderNames.ContentLength, _contentLength.ToString(inv));
+ }
+
+ Version v = _context.Request.ProtocolVersion;
+ if (!_clSet && !_chunked && v >= HttpVersion.Version11)
+ _chunked = true;
+
+ /* Apache forces closing the connection for these status codes:
+ * HttpStatusCode.BadRequest 400
+ * HttpStatusCode.RequestTimeout 408
+ * HttpStatusCode.LengthRequired 411
+ * HttpStatusCode.RequestEntityTooLarge 413
+ * HttpStatusCode.RequestUriTooLong 414
+ * HttpStatusCode.InternalServerError 500
+ * HttpStatusCode.ServiceUnavailable 503
+ */
+ bool conn_close = (_statusCode == (int)HttpStatusCode.BadRequest || _statusCode == (int)HttpStatusCode.RequestTimeout
+ || _statusCode == (int)HttpStatusCode.LengthRequired || _statusCode == (int)HttpStatusCode.RequestEntityTooLarge
+ || _statusCode == (int)HttpStatusCode.RequestUriTooLong || _statusCode == (int)HttpStatusCode.InternalServerError
+ || _statusCode == (int)HttpStatusCode.ServiceUnavailable);
+
+ if (conn_close == false)
+ conn_close = !_context.Request.KeepAlive;
+
+ // They sent both KeepAlive: true and Connection: close
+ if (!_keepAlive || conn_close)
+ {
+ _webHeaders.Set(HttpKnownHeaderNames.Connection, HttpHeaderStrings.Close);
+ conn_close = true;
+ }
+
+ if (_chunked)
+ _webHeaders.Set(HttpKnownHeaderNames.TransferEncoding, HttpHeaderStrings.Chunked);
+
+ int reuses = _context.Connection.Reuses;
+ if (reuses >= 100)
+ {
+ _forceCloseChunked = true;
+ if (!conn_close)
+ {
+ _webHeaders.Set(HttpKnownHeaderNames.Connection, HttpHeaderStrings.Close);
+ conn_close = true;
+ }
+ }
+
+ if (!conn_close)
+ {
+ _webHeaders.Set(HttpKnownHeaderNames.KeepAlive, String.Format("timeout=15,max={0}", 100 - reuses));
+ if (_context.Request.ProtocolVersion <= HttpVersion.Version10)
+ _webHeaders.Set(HttpKnownHeaderNames.Connection, HttpHeaderStrings.KeepAlive);
+ }
+
+ if (_location != null)
+ _webHeaders.Set(HttpKnownHeaderNames.Location, _location);
+
+ if (_cookies != null)
+ {
+ foreach (Cookie cookie in _cookies)
+ _webHeaders.Set(HttpKnownHeaderNames.SetCookie, CookieToClientString(cookie));
+ }
+
+ StreamWriter writer = new StreamWriter(ms, encoding, 256);
+ writer.Write("HTTP/{0} {1} {2}\r\n", _version, _statusCode, _statusDescription);
+ string headers_str = FormatHeaders(_webHeaders);
+ writer.Write(headers_str);
+ writer.Flush();
+ int preamble = encoding.GetPreamble().Length;
+ if (_outputStream == null)
+ _outputStream = _context.Connection.GetResponseStream();
+
+ /* Assumes that the ms was at position 0 */
+ ms.Position = preamble;
+ _headersSent = true;
+ }
+
+ private static string FormatHeaders(WebHeaderCollection headers)
+ {
+ var sb = new StringBuilder();
+
+ for (int i = 0; i < headers.Count; i++)
+ {
+ string key = headers.GetKey(i);
+ string[] values = headers.GetValues(i);
+ for (int j = 0; j < values.Length; j++)
+ {
+ sb.Append(key).Append(": ").Append(values[j]).Append("\r\n");
+ }
+ }
+
+ return sb.Append("\r\n").ToString();
+ }
+
+ private static string CookieToClientString(Cookie cookie)
+ {
+ if (cookie.Name.Length == 0)
+ return String.Empty;
+
+ StringBuilder result = new StringBuilder(64);
+
+ if (cookie.Version > 0)
+ result.Append("Version=").Append(cookie.Version).Append(";");
+
+ result.Append(cookie.Name).Append("=").Append(cookie.Value);
+
+ if (cookie.Path != null && cookie.Path.Length != 0)
+ result.Append(";Path=").Append(QuotedString(cookie, cookie.Path));
+
+ if (cookie.Domain != null && cookie.Domain.Length != 0)
+ result.Append(";Domain=").Append(QuotedString(cookie, cookie.Domain));
+
+ if (cookie.Port != null && cookie.Port.Length != 0)
+ result.Append(";Port=").Append(cookie.Port);
+
+ return result.ToString();
+ }
+
+ private static string QuotedString(Cookie cookie, string value)
+ {
+ if (cookie.Version == 0 || IsToken(value))
+ return value;
+ else
+ return "\"" + value.Replace("\"", "\\\"") + "\"";
+ }
+
+ private static string s_tspecials = "()<>@,;:\\\"/[]?={} \t"; // from RFC 2965, 2068
+
+ private static bool IsToken(string value)
+ {
+ int len = value.Length;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value[i];
+ if (c < 0x20 || c >= 0x7f || s_tspecials.IndexOf(c) != -1)
+ return false;
+ }
+ return true;
+ }
+ }
+}
+
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerTimeoutManager.Unix.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerTimeoutManager.Managed.cs
index 14597fb54a..d234432288 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerTimeoutManager.Unix.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerTimeoutManager.Managed.cs
@@ -4,9 +4,10 @@
namespace System.Net
{
- // TODO: #13187
public class HttpListenerTimeoutManager
{
+ internal HttpListenerTimeoutManager(HttpListener listener) { }
+
public TimeSpan EntityBody
{
get
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpRequestStream.Managed.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpRequestStream.Managed.cs
new file mode 100644
index 0000000000..e9edfb7f0b
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpRequestStream.Managed.cs
@@ -0,0 +1,229 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.RequestStream
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+//
+// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.IO;
+using System.Net.Sockets;
+using System.Runtime.InteropServices;
+
+namespace System.Net
+{
+ internal class HttpRequestStream : Stream
+ {
+ private byte[] _buffer;
+ private int _offset;
+ private int _length;
+ private long _remainingBody;
+ private bool _disposed;
+ private Stream _stream;
+
+ internal HttpRequestStream(Stream stream, byte[] buffer, int offset, int length)
+ : this(stream, buffer, offset, length, -1)
+ {
+ }
+
+ internal HttpRequestStream(Stream stream, byte[] buffer, int offset, int length, long contentlength)
+ {
+ _stream = stream;
+ _buffer = buffer;
+ _offset = offset;
+ _length = length;
+ _remainingBody = contentlength;
+ }
+
+ public override bool CanRead => true;
+
+ public override bool CanSeek => false;
+
+ public override bool CanWrite => false;
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(SR.net_noseek); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(SR.net_noseek); }
+ set { throw new NotSupportedException(SR.net_noseek); }
+ }
+
+ public override void Close() => _disposed = true;
+
+ public override void Flush()
+ {
+ }
+
+
+ // Returns 0 if we can keep reading from the base stream,
+ // > 0 if we read something from the buffer.
+ // -1 if we had a content length set and we finished reading that many bytes.
+ private int FillFromBuffer(byte[] buffer, int offset, int count)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException(nameof(buffer));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException(nameof(offset));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count));
+ int len = buffer.Length;
+ if (offset > len)
+ throw new ArgumentException(nameof(offset), SR.offset_out_of_range);
+ if (offset > len - count)
+ throw new ArgumentException(nameof(count), SR.offset_out_of_range);
+
+ if (_remainingBody == 0)
+ return -1;
+
+ if (_length == 0)
+ return 0;
+
+ int size = Math.Min(_length, count);
+ if (_remainingBody > 0)
+ size = (int)Math.Min(size, _remainingBody);
+
+ if (_offset > _buffer.Length - size)
+ {
+ size = Math.Min(size, _buffer.Length - _offset);
+ }
+ if (size == 0)
+ return 0;
+
+ Buffer.BlockCopy(_buffer, _offset, buffer, offset, size);
+ _offset += size;
+ _length -= size;
+ if (_remainingBody > 0)
+ _remainingBody -= size;
+ return size;
+ }
+
+ public override int Read([In, Out] byte[] buffer, int offset, int count)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(typeof(HttpRequestStream).ToString());
+
+ // Call FillFromBuffer to check for buffer boundaries even when remaining_body is 0
+ int nread = FillFromBuffer(buffer, offset, count);
+ if (nread == -1)
+ { // No more bytes available (Content-Length)
+ return 0;
+ }
+ else if (nread > 0)
+ {
+ return nread;
+ }
+
+ nread = _stream.Read(buffer, offset, count);
+ if (nread > 0 && _remainingBody > 0)
+ _remainingBody -= nread;
+ return nread;
+ }
+
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback cback, object state)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(typeof(HttpRequestStream).ToString());
+
+ int nread = FillFromBuffer(buffer, offset, count);
+ if (nread > 0 || nread == -1)
+ {
+ HttpStreamAsyncResult ares = new HttpStreamAsyncResult();
+ ares._buffer = buffer;
+ ares._offset = offset;
+ ares._count = count;
+ ares._callback = cback;
+ ares._state = state;
+ ares._synchRead = Math.Max(0, nread);
+ ares.Complete();
+ return ares;
+ }
+
+ // Avoid reading past the end of the request to allow
+ // for HTTP pipelining
+ if (_remainingBody >= 0 && count > _remainingBody)
+ {
+ count = (int)Math.Min(int.MaxValue, _remainingBody);
+ }
+
+ return _stream.BeginRead(buffer, offset, count, cback, state);
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(typeof(HttpRequestStream).ToString());
+
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ if (asyncResult is HttpStreamAsyncResult)
+ {
+ HttpStreamAsyncResult r = (HttpStreamAsyncResult)asyncResult;
+ if (!asyncResult.IsCompleted)
+ asyncResult.AsyncWaitHandle.WaitOne();
+ return r._synchRead;
+ }
+
+ int nread = _stream.EndRead(asyncResult);
+ if (_remainingBody > 0 && nread > 0)
+ {
+ _remainingBody -= nread;
+ }
+
+ return nread;
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new NotSupportedException(SR.net_noseek);
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException(SR.net_noseek);
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ throw new NotSupportedException(SR.net_readonlystream);
+ }
+
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count,
+ AsyncCallback cback, object state)
+ {
+ throw new NotSupportedException(SR.net_readonlystream);
+ }
+
+ public override void EndWrite(IAsyncResult async_result)
+ {
+ throw new NotSupportedException(SR.net_readonlystream);
+ }
+ }
+}
+
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpResponseStream.Managed.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpResponseStream.Managed.cs
new file mode 100644
index 0000000000..15849208c8
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpResponseStream.Managed.cs
@@ -0,0 +1,275 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.ResponseStream
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+//
+// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.IO;
+using System.Net.Sockets;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace System.Net
+{
+ internal class HttpResponseStream : Stream
+ {
+ private HttpListenerResponse _response;
+ private bool _ignore_errors;
+ private bool _disposed;
+ private bool _trailer_sent;
+ private Stream _stream;
+
+ internal HttpResponseStream(Stream stream, HttpListenerResponse response, bool ignore_errors)
+ {
+ _response = response;
+ _ignore_errors = ignore_errors;
+ _stream = stream;
+ }
+
+ public override bool CanRead => false;
+
+ public override bool CanSeek => false;
+
+ public override bool CanWrite => true;
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(SR.net_noseek); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(SR.net_noseek); }
+ set { throw new NotSupportedException(SR.net_noseek); }
+ }
+
+ public override void Close()
+ {
+ if (_disposed == false)
+ {
+ _disposed = true;
+ byte[] bytes = null;
+ MemoryStream ms = GetHeaders(true);
+ bool chunked = _response.SendChunked;
+ if (_stream.CanWrite)
+ {
+ try
+ {
+ if (ms != null)
+ {
+ long start = ms.Position;
+ if (chunked && !_trailer_sent)
+ {
+ bytes = GetChunkSizeBytes(0, true);
+ ms.Position = ms.Length;
+ ms.Write(bytes, 0, bytes.Length);
+ }
+ InternalWrite(ms.GetBuffer(), (int)start, (int)(ms.Length - start));
+ _trailer_sent = true;
+ }
+ else if (chunked && !_trailer_sent)
+ {
+ bytes = GetChunkSizeBytes(0, true);
+ InternalWrite(bytes, 0, bytes.Length);
+ _trailer_sent = true;
+ }
+ }
+ catch (IOException)
+ {
+ // Ignore error due to connection reset by peer
+ }
+ }
+ _response.Close();
+ }
+ }
+
+ private MemoryStream GetHeaders(bool closing)
+ {
+ // SendHeaders works on shared headers
+ lock (_response._headersLock)
+ {
+ if (_response._headersSent)
+ {
+ return null;
+ }
+
+ MemoryStream ms = new MemoryStream();
+ _response.SendHeaders(closing, ms);
+ return ms;
+ }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ private static byte[] s_crlf = new byte[] { 13, 10 };
+ private static byte[] GetChunkSizeBytes(int size, bool final)
+ {
+ string str = String.Format("{0:x}\r\n{1}", size, final ? "\r\n" : "");
+ return Encoding.ASCII.GetBytes(str);
+ }
+
+ internal void InternalWrite(byte[] buffer, int offset, int count)
+ {
+ if (_ignore_errors)
+ {
+ try
+ {
+ _stream.Write(buffer, offset, count);
+ }
+ catch { }
+ }
+ else
+ {
+ _stream.Write(buffer, offset, count);
+ }
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+ if (count == 0)
+ return;
+
+ byte[] bytes = null;
+ MemoryStream ms = GetHeaders(false);
+ bool chunked = _response.SendChunked;
+ if (ms != null)
+ {
+ long start = ms.Position; // After the possible preamble for the encoding
+ ms.Position = ms.Length;
+ if (chunked)
+ {
+ bytes = GetChunkSizeBytes(count, false);
+ ms.Write(bytes, 0, bytes.Length);
+ }
+
+ int new_count = Math.Min(count, 16384 - (int)ms.Position + (int)start);
+ ms.Write(buffer, offset, new_count);
+ count -= new_count;
+ offset += new_count;
+ InternalWrite(ms.GetBuffer(), (int)start, (int)(ms.Length - start));
+ ms.SetLength(0);
+ ms.Capacity = 0; // 'dispose' the buffer in ms.
+ }
+ else if (chunked)
+ {
+ bytes = GetChunkSizeBytes(count, false);
+ InternalWrite(bytes, 0, bytes.Length);
+ }
+
+ if (count > 0)
+ InternalWrite(buffer, offset, count);
+ if (chunked)
+ InternalWrite(s_crlf, 0, 2);
+ }
+
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count,
+ AsyncCallback cback, object state)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ byte[] bytes = null;
+ MemoryStream ms = GetHeaders(false);
+ bool chunked = _response.SendChunked;
+ if (ms != null)
+ {
+ long start = ms.Position;
+ ms.Position = ms.Length;
+ if (chunked)
+ {
+ bytes = GetChunkSizeBytes(count, false);
+ ms.Write(bytes, 0, bytes.Length);
+ }
+ ms.Write(buffer, offset, count);
+ buffer = ms.GetBuffer();
+ offset = (int)start;
+ count = (int)(ms.Position - start);
+ }
+ else if (chunked)
+ {
+ bytes = GetChunkSizeBytes(count, false);
+ InternalWrite(bytes, 0, bytes.Length);
+ }
+
+ return _stream.BeginWrite(buffer, offset, count, cback, state);
+ }
+
+ public override void EndWrite(IAsyncResult ares)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().ToString());
+
+ if (_ignore_errors)
+ {
+ try
+ {
+ _stream.EndWrite(ares);
+ if (_response.SendChunked)
+ _stream.Write(s_crlf, 0, 2);
+ }
+ catch { }
+ }
+ else
+ {
+ _stream.EndWrite(ares);
+ if (_response.SendChunked)
+ _stream.Write(s_crlf, 0, 2);
+ }
+ }
+
+ public override int Read([In, Out] byte[] buffer, int offset, int count)
+ {
+ throw new NotSupportedException(SR.net_writeonlystream);
+ }
+
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count,
+ AsyncCallback cback, object state)
+ {
+ throw new NotSupportedException(SR.net_writeonlystream);
+ }
+
+ public override int EndRead(IAsyncResult ares)
+ {
+ throw new NotSupportedException(SR.net_writeonlystream);
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new NotSupportedException(SR.net_noseek);
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException(SR.net_noseek);
+ }
+ }
+}
+
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/HttpStreamAsyncResult.cs b/src/System.Net.HttpListener/src/System/Net/Managed/HttpStreamAsyncResult.cs
new file mode 100644
index 0000000000..d9524d1458
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/HttpStreamAsyncResult.cs
@@ -0,0 +1,106 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.HttpStreamAsyncResult
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+//
+// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Threading;
+
+namespace System.Net
+{
+ internal class HttpStreamAsyncResult : IAsyncResult
+ {
+ private object _locker = new object();
+ private ManualResetEvent _handle;
+ private bool _completed;
+
+ internal byte[] _buffer;
+ internal int _offset;
+ internal int _count;
+ internal AsyncCallback _callback;
+ internal object _state;
+ internal int _synchRead;
+ internal Exception _error;
+
+ public void Complete(Exception e)
+ {
+ _error = e;
+ Complete();
+ }
+
+ public void Complete()
+ {
+ lock (_locker)
+ {
+ if (_completed)
+ return;
+
+ _completed = true;
+ if (_handle != null)
+ _handle.Set();
+
+ if (_callback != null)
+ _callback.BeginInvoke(this, null, null);
+ }
+ }
+
+ public object AsyncState
+ {
+ get { return _state; }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get
+ {
+ lock (_locker)
+ {
+ if (_handle == null)
+ _handle = new ManualResetEvent(_completed);
+ }
+
+ return _handle;
+ }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get { return (_synchRead == _count); }
+ }
+
+ public bool IsCompleted
+ {
+ get
+ {
+ lock (_locker)
+ {
+ return _completed;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/ListenerAsyncResult.Managed.cs b/src/System.Net.HttpListener/src/System/Net/Managed/ListenerAsyncResult.Managed.cs
new file mode 100644
index 0000000000..64846303ab
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/ListenerAsyncResult.Managed.cs
@@ -0,0 +1,208 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.ListenerAsyncResult
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// Copyright (c) 2005 Ximian, Inc (http://www.ximian.com)
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Threading;
+
+namespace System.Net
+{
+ internal class ListenerAsyncResult : IAsyncResult
+ {
+ private ManualResetEvent _handle;
+ private bool _synch;
+ private bool _completed;
+ private AsyncCallback _cb;
+ private object _state;
+ private Exception _exception;
+ private HttpListenerContext _context;
+ private object _locker = new object();
+ private ListenerAsyncResult _forward;
+ internal bool _endCalled;
+ internal bool _inGet;
+
+ public ListenerAsyncResult(AsyncCallback cb, object state)
+ {
+ _cb = cb;
+ _state = state;
+ }
+
+ internal void Complete(Exception exc)
+ {
+ if (_forward != null)
+ {
+ _forward.Complete(exc);
+ return;
+ }
+ _exception = exc;
+ if (_inGet && (exc is ObjectDisposedException))
+ _exception = new HttpListenerException((int)HttpStatusCode.InternalServerError, SR.net_listener_close);
+ lock (_locker)
+ {
+ _completed = true;
+ if (_handle != null)
+ _handle.Set();
+
+ if (_cb != null)
+ ThreadPool.UnsafeQueueUserWorkItem(s_invokeCB, this);
+ }
+ }
+
+ private static WaitCallback s_invokeCB = new WaitCallback(InvokeCallback);
+ private static void InvokeCallback(object o)
+ {
+ ListenerAsyncResult ares = (ListenerAsyncResult)o;
+ if (ares._forward != null)
+ {
+ InvokeCallback(ares._forward);
+ return;
+ }
+ try
+ {
+ ares._cb(ares);
+ }
+ catch
+ {
+ }
+ }
+
+ internal void Complete(HttpListenerContext context)
+ {
+ Complete(context, false);
+ }
+
+ internal void Complete(HttpListenerContext context, bool synch)
+ {
+ if (_forward != null)
+ {
+ _forward.Complete(context, synch);
+ return;
+ }
+ _synch = synch;
+ _context = context;
+ lock (_locker)
+ {
+ AuthenticationSchemes schemes = context.Listener.SelectAuthenticationScheme(context);
+ if ((schemes == AuthenticationSchemes.Basic || context.Listener.AuthenticationSchemes == AuthenticationSchemes.Negotiate) && context.Request.Headers["Authorization"] == null)
+ {
+ context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
+ context.Response.Headers["WWW-Authenticate"] = schemes + " realm=\"" + context.Listener.Realm + "\"";
+ context.Response.OutputStream.Close();
+ IAsyncResult ares = context.Listener.BeginGetContext(_cb, _state);
+ _forward = (ListenerAsyncResult)ares;
+ lock (_forward._locker)
+ {
+ if (_handle != null)
+ _forward._handle = _handle;
+ }
+ ListenerAsyncResult next = _forward;
+ for (int i = 0; next._forward != null; i++)
+ {
+ if (i > 20)
+ Complete(new HttpListenerException((int)HttpStatusCode.Unauthorized, SR.net_listener_auth_errors));
+ next = next._forward;
+ }
+ }
+ else
+ {
+ _completed = true;
+ _synch = false;
+
+ if (_handle != null)
+ _handle.Set();
+
+ if (_cb != null)
+ ThreadPool.UnsafeQueueUserWorkItem(s_invokeCB, this);
+ }
+ }
+ }
+
+ internal HttpListenerContext GetContext()
+ {
+ if (_forward != null)
+ return _forward.GetContext();
+ if (_exception != null)
+ throw _exception;
+
+ return _context;
+ }
+
+ public object AsyncState
+ {
+ get
+ {
+ if (_forward != null)
+ return _forward.AsyncState;
+ return _state;
+ }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get
+ {
+ if (_forward != null)
+ return _forward.AsyncWaitHandle;
+
+ lock (_locker)
+ {
+ if (_handle == null)
+ _handle = new ManualResetEvent(_completed);
+ }
+
+ return _handle;
+ }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get
+ {
+ if (_forward != null)
+ return _forward.CompletedSynchronously;
+ return _synch;
+ }
+ }
+
+ public bool IsCompleted
+ {
+ get
+ {
+ if (_forward != null)
+ return _forward.IsCompleted;
+
+ lock (_locker)
+ {
+ return _completed;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/Managed/ListenerPrefix.cs b/src/System.Net.HttpListener/src/System/Net/Managed/ListenerPrefix.cs
new file mode 100644
index 0000000000..6b4dd6dde6
--- /dev/null
+++ b/src/System.Net.HttpListener/src/System/Net/Managed/ListenerPrefix.cs
@@ -0,0 +1,175 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// See the LICENSE file in the project root for more information.
+//
+// System.Net.ListenerPrefix
+//
+// Author:
+// Gonzalo Paniagua Javier (gonzalo@novell.com)
+// Oleg Mihailik (mihailik gmail co_m)
+//
+// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace System.Net
+{
+ internal sealed class ListenerPrefix
+ {
+ private string _original;
+ private string _host;
+ private ushort _port;
+ private string _path;
+ private bool _secure;
+ private IPAddress[] _addresses;
+ internal HttpListener _listener;
+
+ public ListenerPrefix(string prefix)
+ {
+ _original = prefix;
+ Parse(prefix);
+ }
+
+ public override string ToString()
+ {
+ return _original;
+ }
+
+ public IPAddress[] Addresses
+ {
+ get { return _addresses; }
+ set { _addresses = value; }
+ }
+ public bool Secure
+ {
+ get { return _secure; }
+ }
+
+ public string Host
+ {
+ get { return _host; }
+ }
+
+ public int Port
+ {
+ get { return _port; }
+ }
+
+ public string Path
+ {
+ get { return _path; }
+ }
+
+ // Equals and GetHashCode are required to detect duplicates in HttpListenerPrefixCollection.
+ public override bool Equals(object o)
+ {
+ ListenerPrefix other = o as ListenerPrefix;
+ if (other == null)
+ return false;
+
+ return (_original == other._original);
+ }
+
+ public override int GetHashCode()
+ {
+ return _original.GetHashCode();
+ }
+
+ private void Parse(string uri)
+ {
+ ushort default_port = 80;
+ if (uri.StartsWith("https://"))
+ {
+ default_port = 443;
+ _secure = true;
+ }
+
+ int length = uri.Length;
+ int start_host = uri.IndexOf(':') + 3;
+ if (start_host >= length)
+ throw new ArgumentException(SR.net_listener_host);
+
+ int colon = uri.IndexOf(':', start_host, length - start_host);
+ int root;
+ if (colon > 0)
+ {
+ _host = uri.Substring(start_host, colon - start_host);
+ root = uri.IndexOf('/', colon, length - colon);
+ _port = (ushort)int.Parse(uri.Substring(colon + 1, root - colon - 1));
+ _path = uri.Substring(root);
+ }
+ else
+ {
+ root = uri.IndexOf('/', start_host, length - start_host);
+ _host = uri.Substring(start_host, root - start_host);
+ _port = default_port;
+ _path = uri.Substring(root);
+ }
+ if (_path.Length != 1)
+ _path = _path.Substring(0, _path.Length - 1);
+ }
+
+ public static void CheckUri(string uri)
+ {
+ if (uri == null)
+ throw new ArgumentNullException("uriPrefix");
+
+ if (!uri.StartsWith("http://") && !uri.StartsWith("https://"))
+ throw new ArgumentException(SR.net_listener_scheme);
+
+ int length = uri.Length;
+ int start_host = uri.IndexOf(':') + 3;
+ if (start_host >= length)
+ throw new ArgumentException(SR.net_listener_host);
+
+ int colon = uri.IndexOf(':', start_host, length - start_host);
+ if (start_host == colon)
+ throw new ArgumentException(SR.net_listener_host);
+
+ int root;
+ if (colon > 0)
+ {
+ root = uri.IndexOf('/', colon, length - colon);
+ if (root == -1)
+ throw new ArgumentException(SR.net_invalid_path);
+
+ try
+ {
+ int p = int.Parse(uri.Substring(colon + 1, root - colon - 1));
+ if (p <= 0 || p >= 65536)
+ throw new ArgumentException(SR.net_invalid_port);
+ }
+ catch
+ {
+ throw new ArgumentException(SR.net_invalid_port);
+ }
+ }
+ else
+ {
+ root = uri.IndexOf('/', start_host, length - start_host);
+ if (root == -1)
+ throw new ArgumentException(SR.net_invalid_path);
+ }
+
+ if (uri[uri.Length - 1] != '/')
+ throw new ArgumentException(SR.net_listener_slash);
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/src/System/Net/WebSockets/WebSocketHelpers.cs b/src/System.Net.HttpListener/src/System/Net/WebSockets/WebSocketHelpers.cs
index 49543e1780..637c6aea44 100644
--- a/src/System.Net.HttpListener/src/System/Net/WebSockets/WebSocketHelpers.cs
+++ b/src/System.Net.HttpListener/src/System/Net/WebSockets/WebSocketHelpers.cs
@@ -336,7 +336,7 @@ namespace System.Net.WebSockets
HttpKnownHeaderNames.SecWebSocketKey));
}
}
-
+
internal static void ValidateOptions(string subProtocol,
int receiveBufferSize,
int sendBufferSize,
diff --git a/src/System.Net.HttpListener/src/System/Net/AsyncRequestContext.cs b/src/System.Net.HttpListener/src/System/Net/Windows/AsyncRequestContext.cs
index 09851a3b1a..09851a3b1a 100644
--- a/src/System.Net.HttpListener/src/System/Net/AsyncRequestContext.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/AsyncRequestContext.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/BoundaryType.cs b/src/System.Net.HttpListener/src/System/Net/Windows/BoundaryType.cs
index fc81c9a66c..fc81c9a66c 100644
--- a/src/System.Net.HttpListener/src/System/Net/BoundaryType.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/BoundaryType.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/ContextFlags.cs b/src/System.Net.HttpListener/src/System/Net/Windows/ContextFlags.cs
index befb6578bd..befb6578bd 100644
--- a/src/System.Net.HttpListener/src/System/Net/ContextFlags.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/ContextFlags.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/CookieExtensions.cs b/src/System.Net.HttpListener/src/System/Net/Windows/CookieExtensions.cs
index 82eafd6524..82eafd6524 100644
--- a/src/System.Net.HttpListener/src/System/Net/CookieExtensions.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/CookieExtensions.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/EntitySendFormat.cs b/src/System.Net.HttpListener/src/System/Net/Windows/EntitySendFormat.cs
index 416db779e9..416db779e9 100644
--- a/src/System.Net.HttpListener/src/System/Net/EntitySendFormat.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/EntitySendFormat.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListener.Windows.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListener.Windows.cs
index 2b1d5c25e0..5b00d7d488 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListener.Windows.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListener.Windows.cs
@@ -7,6 +7,7 @@ using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
+using System.Net.Security;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Authentication.ExtendedProtection;
@@ -46,52 +47,21 @@ namespace System.Net
// 0.5 seconds per request. Respond with a 400 Bad Request.
private const int UnknownHeaderLimit = 1000;
- private static readonly byte[] s_WwwAuthenticateBytes = new byte[]
+ private static readonly byte[] s_wwwAuthenticateBytes = new byte[]
{
(byte) 'W', (byte) 'W', (byte) 'W', (byte) '-', (byte) 'A', (byte) 'u', (byte) 't', (byte) 'h',
(byte) 'e', (byte) 'n', (byte) 't', (byte) 'i', (byte) 'c', (byte) 'a', (byte) 't', (byte) 'e'
};
- private AuthenticationSchemeSelector _authenticationDelegate;
- private AuthenticationSchemes _authenticationScheme = AuthenticationSchemes.Anonymous;
- private string _realm;
private SafeHandle _requestQueueHandle;
private ThreadPoolBoundHandle _requestQueueBoundHandle;
- private volatile State _state; // _state is set only within lock blocks, but often read outside locks.
- private HttpListenerPrefixCollection _prefixes;
- private bool _ignoreWriteExceptions;
private bool _unsafeConnectionNtlmAuthentication;
- private ExtendedProtectionSelector _extendedProtectionSelectorDelegate;
- private ExtendedProtectionPolicy _extendedProtectionPolicy;
- private ServiceNameStore _defaultServiceNames;
+
private HttpServerSessionHandle _serverSessionHandle;
private ulong _urlGroupId;
- private HttpListenerTimeoutManager _timeoutManager;
- private bool _V2Initialized;
-
- private Dictionary<ulong, DisconnectAsyncResult> _disconnectResults; // ulong -> DisconnectAsyncResult
- private readonly object _internalLock;
-
- internal Hashtable _uriPrefixes = new Hashtable();
-
- public HttpListener()
- {
- if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
- _state = State.Stopped;
- _internalLock = new object();
- _defaultServiceNames = new ServiceNameStore();
-
- _timeoutManager = new HttpListenerTimeoutManager(this);
-
- // default: no CBT checks on any platform (appcompat reasons); applies also to PolicyEnforcement
- // config element
- _extendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never);
-
- if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
- }
-
- internal ICollection PrefixCollection => _uriPrefixes.Keys;
+ private bool _V2Initialized;
+ private Dictionary<ulong, DisconnectAsyncResult> _disconnectResults;
internal SafeHandle RequestQueueHandle
{
@@ -101,104 +71,69 @@ namespace System.Net
}
}
- public AuthenticationSchemeSelector AuthenticationSchemeSelectorDelegate
+ private void ValidateV2Property()
{
- get
- {
- return _authenticationDelegate;
- }
- set
+ // Make sure that calling CheckDisposed and SetupV2Config is an atomic operation. This
+ // avoids race conditions if the listener is aborted/closed after CheckDisposed(), but
+ // before SetupV2Config().
+ lock (_internalLock)
{
CheckDisposed();
- _authenticationDelegate = value;
+ SetupV2Config();
}
}
- public ExtendedProtectionSelector ExtendedProtectionSelectorDelegate
- {
- get
- {
- return _extendedProtectionSelectorDelegate;
- }
- set
- {
- CheckDisposed();
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- _extendedProtectionSelectorDelegate = value;
- }
- }
- public AuthenticationSchemes AuthenticationSchemes
+ public bool UnsafeConnectionNtlmAuthentication
{
get
{
- return _authenticationScheme;
- }
- set
- {
- CheckDisposed();
- _authenticationScheme = value;
+ return _unsafeConnectionNtlmAuthentication;
}
- }
- public ExtendedProtectionPolicy ExtendedProtectionPolicy
- {
- get
- {
- return _extendedProtectionPolicy;
- }
set
{
CheckDisposed();
- if (value == null)
+ if (_unsafeConnectionNtlmAuthentication == value)
{
- throw new ArgumentNullException(nameof(value));
+ return;
}
- if (value.CustomChannelBinding != null)
+ lock ((DisconnectResults as ICollection).SyncRoot)
{
- throw new ArgumentException(SR.net_listener_cannot_set_custom_cbt, nameof(value));
+ if (_unsafeConnectionNtlmAuthentication == value)
+ {
+ return;
+ }
+ _unsafeConnectionNtlmAuthentication = value;
+ if (!value)
+ {
+ foreach (DisconnectAsyncResult result in DisconnectResults.Values)
+ {
+ result.AuthenticatedConnection = null;
+ }
+ }
}
-
- _extendedProtectionPolicy = value;
- }
- }
-
- public ServiceNameCollection DefaultServiceNames
- {
- get
- {
- return _defaultServiceNames.ServiceNames;
}
}
- public string Realm
+ private Dictionary<ulong, DisconnectAsyncResult> DisconnectResults
{
get
{
- return _realm;
- }
- set
- {
- CheckDisposed();
- _realm = value;
+ if (_disconnectResults == null)
+ {
+ lock (_internalLock)
+ {
+ if (_disconnectResults == null)
+ {
+ _disconnectResults = new Dictionary<ulong, DisconnectAsyncResult>();
+ }
+ }
+ }
+ return _disconnectResults;
}
}
- private void ValidateV2Property()
- {
- // Make sure that calling CheckDisposed and SetupV2Config is an atomic operation. This
- // avoids race conditions if the listener is aborted/closed after CheckDisposed(), but
- // before SetupV2Config().
- lock (_internalLock)
- {
- CheckDisposed();
- SetupV2Config();
- }
- }
private void SetUrlGroupProperty(Interop.HttpApi.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize)
{
@@ -258,77 +193,6 @@ namespace System.Net
}
}
- public bool IsListening
- {
- get
- {
- return _state == State.Started;
- }
- }
-
- public bool IgnoreWriteExceptions
- {
- get
- {
- return _ignoreWriteExceptions;
- }
- set
- {
- CheckDisposed();
- _ignoreWriteExceptions = value;
- }
- }
-
- public bool UnsafeConnectionNtlmAuthentication
- {
- get
- {
- return _unsafeConnectionNtlmAuthentication;
- }
-
- set
- {
- CheckDisposed();
- if (_unsafeConnectionNtlmAuthentication == value)
- {
- return;
- }
- lock ((DisconnectResults as ICollection).SyncRoot)
- {
- if (_unsafeConnectionNtlmAuthentication == value)
- {
- return;
- }
- _unsafeConnectionNtlmAuthentication = value;
- if (!value)
- {
- foreach (DisconnectAsyncResult result in DisconnectResults.Values)
- {
- result.AuthenticatedConnection = null;
- }
- }
- }
- }
- }
-
- private Dictionary<ulong, DisconnectAsyncResult> DisconnectResults
- {
- get
- {
- if (_disconnectResults == null)
- {
- lock (_internalLock)
- {
- if (_disconnectResults == null)
- {
- _disconnectResults = new Dictionary<ulong, DisconnectAsyncResult>();
- }
- }
- }
- return _disconnectResults;
- }
- }
-
internal void AddPrefix(string uriPrefix)
{
if (NetEventSource.IsEnabled) NetEventSource.Enter(this, $"uriPrefix:{uriPrefix}");
@@ -628,7 +492,6 @@ namespace System.Net
{
// If an error occured while adding prefixes, free all resources allocated by previous steps.
DetachRequestQueueFromUrlGroup();
- ClearDigestCache();
throw;
}
@@ -751,8 +614,6 @@ namespace System.Net
_state = State.Stopped;
}
-
- ClearDigestCache();
}
catch (Exception exception)
{
@@ -822,7 +683,6 @@ namespace System.Net
CloseRequestQueueHandle();
}
CleanupV2Config();
- ClearDigestCache();
}
catch (Exception exception)
{
@@ -1104,14 +964,6 @@ namespace System.Net
return httpContext;
}
- public Task<HttpListenerContext> GetContextAsync()
- {
- return Task.Factory.FromAsync(
- (callback, state) => ((HttpListener)state).BeginGetContext(callback, state),
- iar => ((HttpListener)iar.AsyncState).EndGetContext(iar),
- this);
- }
-
internal HttpListenerContext HandleAuthentication(RequestContextBase memoryBlob, out bool stoleBlob)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "HandleAuthentication() memoryBlob:0x" + ((IntPtr)memoryBlob.RequestBlob).ToString("x"));
@@ -1248,22 +1100,17 @@ namespace System.Net
if (index < authorizationHeader.Length)
{
if ((authenticationScheme & AuthenticationSchemes.Negotiate) != AuthenticationSchemes.None &&
- string.Compare(authorizationHeader, 0, AuthConstants.Negotiate, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
+ string.Compare(authorizationHeader, 0, AuthenticationTypes.Negotiate, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
{
headerScheme = AuthenticationSchemes.Negotiate;
}
else if ((authenticationScheme & AuthenticationSchemes.Ntlm) != AuthenticationSchemes.None &&
- string.Compare(authorizationHeader, 0, AuthConstants.NTLM, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
+ string.Compare(authorizationHeader, 0, AuthenticationTypes.NTLM, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
{
headerScheme = AuthenticationSchemes.Ntlm;
}
- else if ((authenticationScheme & AuthenticationSchemes.Digest) != AuthenticationSchemes.None &&
- string.Compare(authorizationHeader, 0, AuthConstants.Digest, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
- {
- headerScheme = AuthenticationSchemes.Digest;
- }
else if ((authenticationScheme & AuthenticationSchemes.Basic) != AuthenticationSchemes.None &&
- string.Compare(authorizationHeader, 0, AuthConstants.Basic, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
+ string.Compare(authorizationHeader, 0, AuthenticationTypes.Basic, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
{
headerScheme = AuthenticationSchemes.Basic;
}
@@ -1276,6 +1123,7 @@ namespace System.Net
// httpError holds the error we will return if an Authorization header is present but can't be authenticated
HttpStatusCode httpError = HttpStatusCode.InternalServerError;
+ bool error = false;
// See if we found an acceptable auth header
if (headerScheme == AuthenticationSchemes.None)
@@ -1300,7 +1148,230 @@ namespace System.Net
}
else
{
- throw new NotImplementedException();
+ // Perform Authentication
+ byte[] bytes = null;
+ byte[] decodedOutgoingBlob = null;
+ string outBlob = null;
+
+ // Find the beginning of the blob. Trust that HTTP.SYS parsed out just our header ok.
+ for (index++; index < authorizationHeader.Length; index++)
+ {
+ if (authorizationHeader[index] != ' ' && authorizationHeader[index] != '\t' &&
+ authorizationHeader[index] != '\r' && authorizationHeader[index] != '\n')
+ {
+ break;
+ }
+ }
+ string inBlob = index < authorizationHeader.Length ? authorizationHeader.Substring(index) : "";
+
+ IPrincipal principal = null;
+ SecurityStatusPal statusCodeNew;
+ ChannelBinding binding;
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Performing Authentication headerScheme: {headerScheme}");
+ switch (headerScheme)
+ {
+ case AuthenticationSchemes.Negotiate:
+ case AuthenticationSchemes.Ntlm:
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"context: {oldContext} for connectionId: {connectionId}");
+
+ string package = headerScheme == AuthenticationSchemes.Ntlm ? NegotiationInfoClass.NTLM : NegotiationInfoClass.Negotiate;
+ if (oldContext != null && oldContext.Package == package)
+ {
+ context = oldContext;
+ }
+ else
+ {
+ binding = GetChannelBinding(connectionId, isSecureConnection, extendedProtectionPolicy);
+ ContextFlagsPal contextFlags = GetContextFlags(extendedProtectionPolicy, isSecureConnection);
+ context = new NTAuthentication(true, package, CredentialCache.DefaultNetworkCredentials, null, contextFlags, binding);
+ }
+
+ try
+ {
+ bytes = Convert.FromBase64String(inBlob);
+ }
+ catch (FormatException)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"FormatException from FormBase64String");
+ httpError = HttpStatusCode.BadRequest;
+ error = true;
+ }
+ if (!error)
+ {
+ decodedOutgoingBlob = context.GetOutgoingBlob(bytes, false, out statusCodeNew);
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"GetOutgoingBlob returned IsCompleted: {context.IsCompleted} and statusCodeNew: {statusCodeNew}");
+ error = !context.IsValidContext;
+ if (error)
+ {
+ // SSPI Workaround
+ // If a client sends up a blob on the initial request, Negotiate returns SEC_E_INVALID_HANDLE
+ // when it should return SEC_E_INVALID_TOKEN.
+ if (statusCodeNew.ErrorCode == SecurityStatusPalErrorCode.InvalidHandle && oldContext == null && bytes != null && bytes.Length > 0)
+ {
+ statusCodeNew = new SecurityStatusPal(SecurityStatusPalErrorCode.InvalidToken);
+ }
+
+ httpError = HttpStatusFromSecurityStatus(statusCodeNew.ErrorCode);
+ }
+ }
+
+ if (decodedOutgoingBlob != null)
+ {
+ outBlob = Convert.ToBase64String(decodedOutgoingBlob);
+ }
+
+ if (!error)
+ {
+ if (context.IsCompleted)
+ {
+ SecurityContextTokenHandle userContext = null;
+ try
+ {
+ if (!CheckSpn(context, isSecureConnection, extendedProtectionPolicy))
+ {
+ httpError = HttpStatusCode.Unauthorized;
+ }
+ else
+ {
+ httpContext.Request.ServiceName = context.ClientSpecifiedSpn;
+
+ SafeDeleteContext securityContext = context.GetContext(out statusCodeNew);
+ if (statusCodeNew.ErrorCode != SecurityStatusPalErrorCode.OK)
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this,
+ $"HandleAuthentication GetContextToken failed with statusCodeNew: {statusCodeNew}");
+ }
+
+ httpError = HttpStatusFromSecurityStatus(statusCodeNew.ErrorCode);
+ }
+ else
+ {
+ SSPIWrapper.QuerySecurityContextToken(GlobalSSPI.SSPIAuth, securityContext, out userContext);
+
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this,
+ $"HandleAuthentication creating new WindowsIdentity from user context: {userContext.DangerousGetHandle().ToString("x8")}");
+ }
+
+ WindowsPrincipal windowsPrincipal = new WindowsPrincipal(
+ new WindowsIdentity(userContext.DangerousGetHandle(), context.ProtocolName));
+
+ principal = windowsPrincipal;
+ // if appropriate, cache this credential on this connection
+ if (UnsafeConnectionNtlmAuthentication && context.ProtocolName == NegotiationInfoClass.NTLM)
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this,
+ $"HandleAuthentication inserting principal: {principal} for connectionId: {connectionId}");
+ }
+
+ // We may need to call WaitForDisconnect.
+ if (disconnectResult == null)
+ {
+ RegisterForDisconnectNotification(connectionId, ref disconnectResult);
+ }
+ if (disconnectResult != null)
+ {
+ lock ((DisconnectResults as ICollection).SyncRoot)
+ {
+ if (UnsafeConnectionNtlmAuthentication)
+ {
+ disconnectResult.AuthenticatedConnection = windowsPrincipal;
+ }
+ }
+ }
+ else
+ {
+ // Registration failed - UnsafeConnectionNtlmAuthentication ignored.
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, $"HandleAuthentication RegisterForDisconnectNotification failed.");
+ }
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ if (userContext != null)
+ {
+ userContext.Close();
+ }
+ }
+ }
+ else
+ {
+ // auth incomplete
+ newContext = context;
+
+ challenge = (headerScheme == AuthenticationSchemes.Ntlm ? NegotiationInfoClass.NTLM : NegotiationInfoClass.Negotiate);
+ if (!String.IsNullOrEmpty(outBlob))
+ {
+ challenge += " " + outBlob;
+ }
+ }
+ }
+ break;
+
+ case AuthenticationSchemes.Basic:
+ try
+ {
+ bytes = Convert.FromBase64String(inBlob);
+
+ inBlob = WebHeaderEncoding.GetString(bytes, 0, bytes.Length);
+ index = inBlob.IndexOf(':');
+
+ if (index != -1)
+ {
+ string userName = inBlob.Substring(0, index);
+ string password = inBlob.Substring(index + 1);
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, $"Basic Identity found, userName: {userName}");
+ }
+
+ principal = new GenericPrincipal(new HttpListenerBasicIdentity(userName, password), null);
+ }
+ else
+ {
+ httpError = HttpStatusCode.BadRequest;
+ }
+ }
+ catch (FormatException)
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, $"FromBase64String threw a FormatException.");
+ }
+ }
+ break;
+ }
+
+ if (principal != null)
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, $"Got principal: {principal}, IdentityName: {principal.Identity.Name} for creating request.");
+ }
+
+ httpContext.SetIdentity(principal, outBlob);
+ }
+ else
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, "Handshake has failed.");
+ }
+
+ httpContext.Request.DetachBlob(memoryBlob);
+ httpContext.Close();
+ httpContext = null;
+ }
}
// if we're not giving a request to the application, we need to send an error
@@ -1397,16 +1468,7 @@ namespace System.Net
if (toClose != null)
{
- // Save digest context in digest cache, we may need it later because of
- // subsequest responses to the same req on the same/diff connection
- if ((authenticationScheme & AuthenticationSchemes.Digest) != 0)
- {
- SaveDigestContext(toClose);
- }
- else
- {
- toClose.CloseContext();
- }
+ toClose.CloseContext();
}
}
@@ -1466,17 +1528,7 @@ namespace System.Net
disconnectResult.Session = null;
}
- // Save digest context in digest cache, we may need it later because of
- // subsequest responses to the same req on the same/diff connection
-
- if ((authenticationScheme & AuthenticationSchemes.Digest) != 0)
- {
- SaveDigestContext(oldContext);
- }
- else
- {
- oldContext.CloseContext();
- }
+ oldContext.CloseContext();
}
// Delete any context created but not stored.
@@ -1516,11 +1568,6 @@ namespace System.Net
// but throwing from HttpListener would be a breaking change.
if (challenges != null) // null == Anonymous
{
- if (newContext != null) // Digest challenge, keep it alive for 10s - 5min.
- {
- SaveDigestContext(newContext);
- }
-
// Add the new WWW-Authenticate headers
foreach (string challenge in challenges)
{
@@ -1529,6 +1576,232 @@ namespace System.Net
}
}
+ private ChannelBinding GetChannelBinding(ulong connectionId, bool isSecureConnection, ExtendedProtectionPolicy policy)
+ {
+ if (policy.PolicyEnforcement == PolicyEnforcement.Never)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, SR.net_log_listener_no_cbt_disabled);
+ return null;
+ }
+
+ if (!isSecureConnection)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, SR.net_log_listener_no_cbt_http);
+ return null;
+ }
+
+ if (policy.ProtectionScenario == ProtectionScenario.TrustedProxy)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, SR.net_log_listener_no_cbt_trustedproxy);
+ return null;
+ }
+
+ ChannelBinding result = GetChannelBindingFromTls(connectionId);
+
+ if (NetEventSource.IsEnabled && result != null)
+ NetEventSource.Info(this, "GetChannelBindingFromTls returned null even though OS supposedly supports Extended Protection");
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, SR.net_log_listener_cbt);
+ return result;
+ }
+
+ private bool CheckSpn(NTAuthentication context, bool isSecureConnection, ExtendedProtectionPolicy policy)
+ {
+ // Kerberos does SPN check already in ASC
+ if (context.IsKerberos)
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, SR.net_log_listener_no_spn_kerberos);
+ }
+ return true;
+ }
+
+ // Don't check the SPN if Extended Protection is off or we already checked the CBT
+ if (policy.PolicyEnforcement == PolicyEnforcement.Never)
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, SR.net_log_listener_no_spn_disabled);
+ }
+ return true;
+ }
+
+ if (ScenarioChecksChannelBinding(isSecureConnection, policy.ProtectionScenario))
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, SR.net_log_listener_no_spn_cbt);
+ }
+ return true;
+ }
+
+ string clientSpn = context.ClientSpecifiedSpn;
+
+ // An empty SPN is only allowed in the WhenSupported case
+ if (String.IsNullOrEmpty(clientSpn))
+ {
+ if (policy.PolicyEnforcement == PolicyEnforcement.WhenSupported)
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this,
+ SR.net_log_listener_no_spn_whensupported);
+ }
+ return true;
+ }
+ else
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this,
+ SR.net_log_listener_spn_failed_always);
+ }
+ return false;
+ }
+ }
+ else if (string.Equals(clientSpn, "http/localhost", StringComparison.OrdinalIgnoreCase))
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, SR.net_log_listener_no_spn_loopback);
+ }
+
+ return true;
+ }
+ else
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, SR.net_log_listener_spn, clientSpn);
+ }
+
+ ServiceNameCollection serviceNames = GetServiceNames(policy);
+
+ bool found = serviceNames.Contains(clientSpn);
+
+ if (NetEventSource.IsEnabled)
+ {
+ if (found)
+ {
+ NetEventSource.Info(this, SR.net_log_listener_spn_passed);
+ }
+ else
+ {
+ NetEventSource.Info(this, SR.net_log_listener_spn_failed);
+
+ if (serviceNames.Count == 0)
+ {
+ if (NetEventSource.IsEnabled)
+ {
+ NetEventSource.Info(this, SR.net_log_listener_spn_failed_empty);
+ }
+ }
+ else
+ {
+ NetEventSource.Info(this, SR.net_log_listener_spn_failed_dump);
+
+ foreach (string serviceName in serviceNames)
+ {
+ NetEventSource.Info(this, "\t" + serviceName);
+ }
+ }
+ }
+ }
+
+ return found;
+ }
+ }
+
+ private ServiceNameCollection GetServiceNames(ExtendedProtectionPolicy policy)
+ {
+ ServiceNameCollection serviceNames;
+
+ if (policy.CustomServiceNames == null)
+ {
+ if (_defaultServiceNames.ServiceNames.Count == 0)
+ {
+ throw new InvalidOperationException(SR.net_listener_no_spns);
+ }
+ serviceNames = _defaultServiceNames.ServiceNames;
+ }
+ else
+ {
+ serviceNames = policy.CustomServiceNames;
+ }
+ return serviceNames;
+ }
+
+ private static bool ScenarioChecksChannelBinding(bool isSecureConnection, ProtectionScenario scenario)
+ {
+ return (isSecureConnection && scenario == ProtectionScenario.TransportSelected);
+ }
+
+ private ContextFlagsPal GetContextFlags(ExtendedProtectionPolicy policy, bool isSecureConnection)
+ {
+ ContextFlagsPal result = ContextFlagsPal.Connection;
+ if (policy.PolicyEnforcement != PolicyEnforcement.Never)
+ {
+ if (policy.PolicyEnforcement == PolicyEnforcement.WhenSupported)
+ {
+ result |= ContextFlagsPal.AllowMissingBindings;
+ }
+
+ if (policy.ProtectionScenario == ProtectionScenario.TrustedProxy)
+ {
+ result |= ContextFlagsPal.ProxyBindings;
+ }
+ }
+
+ return result;
+ }
+
+ // This only works for context-destroying errors.
+ private HttpStatusCode HttpStatusFromSecurityStatus(SecurityStatusPalErrorCode statusErrorCode)
+ {
+ if (IsCredentialFailure(statusErrorCode))
+ {
+ return HttpStatusCode.Unauthorized;
+ }
+ if (IsClientFault(statusErrorCode))
+ {
+ return HttpStatusCode.BadRequest;
+ }
+ return HttpStatusCode.InternalServerError;
+ }
+
+ // This only works for context-destroying errors.
+ internal static bool IsCredentialFailure(SecurityStatusPalErrorCode error)
+ {
+ return error == SecurityStatusPalErrorCode.LogonDenied ||
+ error == SecurityStatusPalErrorCode.UnknownCredentials ||
+ error == SecurityStatusPalErrorCode.NoImpersonation ||
+ error == SecurityStatusPalErrorCode.NoAuthenticatingAuthority ||
+ error == SecurityStatusPalErrorCode.UntrustedRoot ||
+ error == SecurityStatusPalErrorCode.CertExpired ||
+ error == SecurityStatusPalErrorCode.SmartcardLogonRequired ||
+ error == SecurityStatusPalErrorCode.BadBinding;
+ }
+
+ // This only works for context-destroying errors.
+ internal static bool IsClientFault(SecurityStatusPalErrorCode error)
+ {
+ return error == SecurityStatusPalErrorCode.InvalidToken ||
+ error == SecurityStatusPalErrorCode.CannotPack ||
+ error == SecurityStatusPalErrorCode.QopNotSupported ||
+ error == SecurityStatusPalErrorCode.NoCredentials ||
+ error == SecurityStatusPalErrorCode.MessageAltered ||
+ error == SecurityStatusPalErrorCode.OutOfSequence ||
+ error == SecurityStatusPalErrorCode.IncompleteMessage ||
+ error == SecurityStatusPalErrorCode.IncompleteCredentials ||
+ error == SecurityStatusPalErrorCode.WrongPrincipal ||
+ error == SecurityStatusPalErrorCode.TimeSkew ||
+ error == SecurityStatusPalErrorCode.IllegalMessage ||
+ error == SecurityStatusPalErrorCode.CertUnknown ||
+ error == SecurityStatusPalErrorCode.AlgorithmMismatch ||
+ error == SecurityStatusPalErrorCode.SecurityQosFailed ||
+ error == SecurityStatusPalErrorCode.UnsupportedPreauth;
+ }
+
private static void AddChallenge(ref ArrayList challenges, string challenge)
{
if (challenge != null)
@@ -1555,18 +1828,12 @@ namespace System.Net
if ((authenticationScheme & AuthenticationSchemes.Negotiate) != 0)
{
- AddChallenge(ref challenges, AuthConstants.Negotiate);
+ AddChallenge(ref challenges, AuthenticationTypes.Negotiate);
}
if ((authenticationScheme & AuthenticationSchemes.Ntlm) != 0)
{
- AddChallenge(ref challenges, AuthConstants.NTLM);
- }
-
- if ((authenticationScheme & AuthenticationSchemes.Digest) != 0)
- {
- if (NetEventSource.IsEnabled) NetEventSource.Info(this, "WDigest");
- throw new NotImplementedException();
+ AddChallenge(ref challenges, AuthenticationTypes.NTLM);
}
if ((authenticationScheme & AuthenticationSchemes.Basic) != 0)
@@ -1656,15 +1923,15 @@ namespace System.Net
{
headersArrayHandle = GCHandle.Alloc(headersArray, GCHandleType.Pinned);
httpResponse.Headers.pUnknownHeaders = (Interop.HttpApi.HTTP_UNKNOWN_HEADER*)Marshal.UnsafeAddrOfPinnedArrayElement(headersArray, 0);
- wwwAuthenticateHandle = GCHandle.Alloc(s_WwwAuthenticateBytes, GCHandleType.Pinned);
- sbyte* wwwAuthenticate = (sbyte*)Marshal.UnsafeAddrOfPinnedArrayElement(s_WwwAuthenticateBytes, 0);
+ wwwAuthenticateHandle = GCHandle.Alloc(s_wwwAuthenticateBytes, GCHandleType.Pinned);
+ sbyte* wwwAuthenticate = (sbyte*)Marshal.UnsafeAddrOfPinnedArrayElement(s_wwwAuthenticateBytes, 0);
for (int i = 0; i < challengeHandles.Length; i++)
{
byte[] byteChallenge = Encoding.Default.GetBytes((string)challenges[i]);
challengeHandles[i] = GCHandle.Alloc(byteChallenge, GCHandleType.Pinned);
headersArray[i].pName = wwwAuthenticate;
- headersArray[i].NameLength = (ushort)s_WwwAuthenticateBytes.Length;
+ headersArray[i].NameLength = (ushort)s_wwwAuthenticateBytes.Length;
headersArray[i].pRawValue = (sbyte*)Marshal.UnsafeAddrOfPinnedArrayElement(byteChallenge, 0);
headersArray[i].RawValueLength = checked((ushort)byteChallenge.Length);
}
@@ -1716,7 +1983,7 @@ namespace System.Net
}
}
- private unsafe static int GetTokenOffsetFromBlob(IntPtr blob)
+ private static unsafe int GetTokenOffsetFromBlob(IntPtr blob)
{
Debug.Assert(blob != IntPtr.Zero);
IntPtr tokenPointer = Marshal.ReadIntPtr((IntPtr)blob, (int)Marshal.OffsetOf(s_channelBindingStatusType, "ChannelToken"));
@@ -1725,7 +1992,7 @@ namespace System.Net
return (int)((long)tokenPointer - (long)blob);
}
- private unsafe static int GetTokenSizeFromBlob(IntPtr blob)
+ private static unsafe int GetTokenSizeFromBlob(IntPtr blob)
{
Debug.Assert(blob != IntPtr.Zero);
return Marshal.ReadInt32(blob, (int)Marshal.OffsetOf(s_channelBindingStatusType, "ChannelTokenSize"));
@@ -1801,155 +2068,6 @@ namespace System.Net
return token;
}
- internal void CheckDisposed()
- {
- if (_state == State.Closed)
- {
- throw new ObjectDisposedException(this.GetType().FullName);
- }
- }
-
- private enum State
- {
- Stopped,
- Started,
- Closed,
- }
-
- private const int DigestLifetimeSeconds = 300;
- private const int MaximumDigests = 1024; // Must be a power of two.
- private const int MinimumDigestLifetimeSeconds = 10;
-
- private struct DigestContext
- {
- internal NTAuthentication context;
- internal int timestamp;
- }
-
- private DigestContext[] _savedDigests;
- private ArrayList _extraSavedDigests;
- private ArrayList _extraSavedDigestsBaking;
- private int _extraSavedDigestsTimestamp;
- private int _newestContext;
- private int _oldestContext;
-
- private void SaveDigestContext(NTAuthentication digestContext)
- {
- if (_savedDigests == null)
- {
- Interlocked.CompareExchange<DigestContext[]>(ref _savedDigests, new DigestContext[MaximumDigests], null);
- }
-
- // We want to actually close the contexts outside the lock.
- NTAuthentication oldContext = null;
- ArrayList digestsToClose = null;
- lock (_savedDigests)
- {
- // If we're stopped, just throw it away.
- if (!IsListening)
- {
- digestContext.CloseContext();
- return;
- }
-
- int now = ((now = Environment.TickCount) == 0 ? 1 : now);
-
- _newestContext = (_newestContext + 1) & (MaximumDigests - 1);
-
- int oldTimestamp = _savedDigests[_newestContext].timestamp;
- oldContext = _savedDigests[_newestContext].context;
- _savedDigests[_newestContext].timestamp = now;
- _savedDigests[_newestContext].context = digestContext;
-
- // May need to move this up.
- if (_oldestContext == _newestContext)
- {
- _oldestContext = (_newestContext + 1) & (MaximumDigests - 1);
- }
-
- // Delete additional contexts older than five minutes.
- while (unchecked(now - _savedDigests[_oldestContext].timestamp) >= DigestLifetimeSeconds && _savedDigests[_oldestContext].context != null)
- {
- if (digestsToClose == null)
- {
- digestsToClose = new ArrayList();
- }
- digestsToClose.Add(_savedDigests[_oldestContext].context);
- _savedDigests[_oldestContext].context = null;
- _oldestContext = (_oldestContext + 1) & (MaximumDigests - 1);
- }
-
- // If the old context is younger than 10 seconds, put it in the backup pile.
- if (oldContext != null && unchecked(now - oldTimestamp) <= MinimumDigestLifetimeSeconds * 1000)
- {
- // Use a two-tier ArrayList system to guarantee each entry lives at least 10 seconds.
- if (_extraSavedDigests == null ||
- unchecked(now - _extraSavedDigestsTimestamp) > MinimumDigestLifetimeSeconds * 1000)
- {
- digestsToClose = _extraSavedDigestsBaking;
- _extraSavedDigestsBaking = _extraSavedDigests;
- _extraSavedDigestsTimestamp = now;
- _extraSavedDigests = new ArrayList();
- }
- _extraSavedDigests.Add(oldContext);
- oldContext = null;
- }
- }
-
- if (oldContext != null)
- {
- oldContext.CloseContext();
- }
- if (digestsToClose != null)
- {
- for (int i = 0; i < digestsToClose.Count; i++)
- {
- ((NTAuthentication)digestsToClose[i]).CloseContext();
- }
- }
- }
-
- private void ClearDigestCache()
- {
- if (_savedDigests == null)
- {
- return;
- }
-
- ArrayList[] toClose = new ArrayList[3];
- lock (_savedDigests)
- {
- toClose[0] = _extraSavedDigestsBaking;
- _extraSavedDigestsBaking = null;
- toClose[1] = _extraSavedDigests;
- _extraSavedDigests = null;
-
- _newestContext = 0;
- _oldestContext = 0;
-
- toClose[2] = new ArrayList();
- for (int i = 0; i < MaximumDigests; i++)
- {
- if (_savedDigests[i].context != null)
- {
- toClose[2].Add(_savedDigests[i].context);
- _savedDigests[i].context = null;
- }
- _savedDigests[i].timestamp = 0;
- }
- }
-
- for (int j = 0; j < toClose.Length; j++)
- {
- if (toClose[j] != null)
- {
- for (int k = 0; k < toClose[j].Count; k++)
- {
- ((NTAuthentication)toClose[j][k]).CloseContext();
- }
- }
- }
- }
private class DisconnectAsyncResult : IAsyncResult
{
@@ -2063,7 +2181,7 @@ namespace System.Net
_httpListener.DisconnectResults.Remove(_connectionId);
if (_session != null)
{
- throw new NotImplementedException();
+ _session.CloseContext();
}
// Clean up the identity. This is for scenarios where identity was not cleaned up before due to
@@ -2071,7 +2189,7 @@ namespace System.Net
IDisposable identity = _authenticatedConnection == null ? null : _authenticatedConnection.Identity as IDisposable;
if ((identity != null) &&
- (_authenticatedConnection.Identity.AuthenticationType == AuthConstants.NTLM) &&
+ (_authenticatedConnection.Identity.AuthenticationType == AuthenticationTypes.NTLM) &&
(_httpListener.UnsafeConnectionNtlmAuthentication))
{
identity.Dispose();
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerContext.Windows.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerContext.Windows.cs
index 3c9cb60e92..0bb116190e 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerContext.Windows.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerContext.Windows.cs
@@ -132,7 +132,7 @@ namespace System.Net
// For unsafe connection ntlm auth we dont dispose this identity as yet since its cached
if ((user != null) &&
- (_user.Identity.AuthenticationType != AuthConstants.NTLM) &&
+ (_user.Identity.AuthenticationType != NegotiationInfoClass.NTLM) &&
(!_listener.UnsafeConnectionNtlmAuthentication))
{
user.Dispose();
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerPrefixCollection.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerPrefixCollection.Windows.cs
index e82f922af7..e82f922af7 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerPrefixCollection.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerPrefixCollection.Windows.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.Windows.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerRequest.Windows.cs
index 7a6205b2f5..391bf7a832 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequest.Windows.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerRequest.Windows.cs
@@ -169,6 +169,16 @@ namespace System.Net
}
}
+ public Guid RequestTraceIdentifier
+ {
+ get
+ {
+ Guid guid = new Guid();
+ *(1 + (ulong*)&guid) = RequestId;
+ return guid;
+ }
+ }
+
public string[] AcceptTypes
{
get
@@ -727,8 +737,8 @@ namespace System.Net
&bytesReceived,
asyncResult.NativeOverlapped);
- if (NetEventSource.IsEnabled) NetEventSource.Info(this,
- "Call to Interop.HttpApi.HttpReceiveClientCertificate returned:" + statusCode + " bytesReceived:" + bytesReceived);
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveClientCertificate returned:" + statusCode + " bytesReceived:" + bytesReceived);
if (statusCode == Interop.HttpApi.ERROR_MORE_DATA)
{
Interop.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult.RequestBlob;
@@ -829,8 +839,8 @@ namespace System.Net
&bytesReceived,
null);
- if (NetEventSource.IsEnabled) NetEventSource.Info(this,
- "Call to Interop.HttpApi.HttpReceiveClientCertificate returned:" + statusCode + " bytesReceived:" + bytesReceived);
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveClientCertificate returned:" + statusCode + " bytesReceived:" + bytesReceived);
if (statusCode == Interop.HttpApi.ERROR_MORE_DATA)
{
size = bytesReceived + pClientCertInfo->CertEncodedSize;
@@ -840,8 +850,8 @@ namespace System.Net
{
if (pClientCertInfo != null)
{
- if (NetEventSource.IsEnabled) NetEventSource.Info(this,
- $"pClientCertInfo:{(IntPtr)pClientCertInfo} pClientCertInfo->CertFlags: {pClientCertInfo->CertFlags} pClientCertInfo->CertEncodedSize: {pClientCertInfo->CertEncodedSize} pClientCertInfo->pCertEncoded: {(IntPtr)pClientCertInfo->pCertEncoded} pClientCertInfo->Token: {(IntPtr)pClientCertInfo->Token} pClientCertInfo->CertDeniedByMapper: {pClientCertInfo->CertDeniedByMapper}");
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Info(this, $"pClientCertInfo:{(IntPtr)pClientCertInfo} pClientCertInfo->CertFlags: {pClientCertInfo->CertFlags} pClientCertInfo->CertEncodedSize: {pClientCertInfo->CertEncodedSize} pClientCertInfo->pCertEncoded: {(IntPtr)pClientCertInfo->pCertEncoded} pClientCertInfo->Token: {(IntPtr)pClientCertInfo->Token} pClientCertInfo->CertDeniedByMapper: {pClientCertInfo->CertDeniedByMapper}");
if (pClientCertInfo->pCertEncoded != null)
{
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequestContext.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerRequestContext.cs
index c4aed0ab2c..c4aed0ab2c 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerRequestContext.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerRequestContext.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.Windows.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerResponse.Windows.cs
index ba54de5bd3..60b74f87b9 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.Windows.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerResponse.Windows.cs
@@ -24,12 +24,11 @@ namespace System.Net
}
private Encoding _contentEncoding;
- private CookieCollection _cookies;
private string _statusDescription;
private bool _keepAlive;
private ResponseState _responseState;
- private WebHeaderCollection _webHeaders;
+
private HttpResponseStream _responseStream;
private long _contentLength;
private BoundaryType _boundaryType;
@@ -41,7 +40,6 @@ namespace System.Net
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this);
_nativeResponse = new Interop.HttpApi.HTTP_RESPONSE();
- _webHeaders = new WebHeaderCollection();
_boundaryType = BoundaryType.None;
_nativeResponse.StatusCode = (ushort)HttpStatusCode.OK;
_nativeResponse.Version.MajorVersion = 1;
@@ -191,22 +189,6 @@ namespace System.Net
}
}
- public CookieCollection Cookies
- {
- get
- {
- if (_cookies == null)
- {
- _cookies = new CookieCollection();
- }
- return _cookies;
- }
- set
- {
- _cookies = value;
- }
- }
-
public void CopyFrom(HttpListenerResponse templateResponse)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"templateResponse {templateResponse}");
@@ -294,34 +276,6 @@ namespace System.Net
}
}
- public WebHeaderCollection Headers
- {
- get
- {
- return _webHeaders;
- }
- set
- {
- _webHeaders = new WebHeaderCollection();
- foreach (string headerName in value.AllKeys)
- {
- _webHeaders.Add(headerName, value[headerName]);
- }
- }
- }
-
- public void AddHeader(string name, string value)
- {
- if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"name={name}, value={value}");
- Headers.Set(name, value);
- }
-
- public void AppendHeader(string name, string value)
- {
- if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"name={name}, value={value}");
- Headers.Add(value);
- }
-
public void Redirect(string url)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"url={url}");
@@ -330,42 +284,6 @@ namespace System.Net
StatusDescription = HttpStatusDescription.Get(StatusCode);
}
- public void AppendCookie(Cookie cookie)
- {
- if (cookie == null)
- {
- throw new ArgumentNullException(nameof(cookie));
- }
- if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"cookie: {cookie}");
- Cookies.Add(cookie);
- }
-
- public void SetCookie(Cookie cookie)
- {
- if (cookie == null)
- {
- throw new ArgumentNullException(nameof(cookie));
- }
- bool added = false;
- try
- {
- Cookies.Add(cookie);
- added = true;
- }
- catch (CookieException)
- {
- Debug.Assert(!added);
- }
-
- if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"cookie: {cookie}");
-
- if (!added)
- {
- // cookie already existed and couldn't be replaced
- throw new ArgumentException(SR.net_cookie_exists, nameof(cookie));
- }
- }
-
public long ContentLength64
{
get
@@ -432,6 +350,20 @@ namespace System.Net
}
}
+ public void Close()
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+ try
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this);
+ ((IDisposable)this).Dispose();
+ }
+ finally
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
+ }
+ }
+
public void Close(byte[] responseEntity, bool willBlock)
{
if (NetEventSource.IsEnabled) NetEventSource.Enter(this, $"responseEntity={responseEntity},willBlock={willBlock}");
@@ -475,7 +407,7 @@ namespace System.Net
}
}
- private void Dispose(bool disposing)
+ private void Dispose()
{
if (_responseState >= ResponseState.Closed)
{
@@ -592,7 +524,7 @@ namespace System.Net
if (NetEventSource.IsEnabled) NetEventSource.Info(this, sb.ToString());
}
_responseState = ResponseState.SentHeaders;
-
+
uint statusCode;
uint bytesSent;
List<GCHandle> pinnedHeaders = SerializeHeaders(ref _nativeResponse.Headers, isWebSocketHandshake);
@@ -684,8 +616,9 @@ namespace System.Net
internal void ComputeCookies()
{
- if (NetEventSource.IsEnabled) NetEventSource.Info(this,
- $"Entering Set-Cookie: {Headers[HttpResponseHeader.SetCookie]}, Set-Cookie2: {Headers[HttpKnownHeaderNames.SetCookie2]}");
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Info(this,
+$"Entering Set-Cookie: {Headers[HttpResponseHeader.SetCookie]}, Set-Cookie2: {Headers[HttpKnownHeaderNames.SetCookie2]}");
if (_cookies != null)
{
// now go through the collection, and concatenate all the cookies in per-variant strings
@@ -726,8 +659,9 @@ namespace System.Net
}
}
}
- if (NetEventSource.IsEnabled) NetEventSource.Info(this,
- $"Exiting Set-Cookie: {Headers[HttpResponseHeader.SetCookie]} Set-Cookie2: {Headers[HttpKnownHeaderNames.SetCookie2]}");
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Info(this,
+$"Exiting Set-Cookie: {Headers[HttpResponseHeader.SetCookie]} Set-Cookie2: {Headers[HttpKnownHeaderNames.SetCookie2]}");
}
internal Interop.HttpApi.HTTP_FLAGS ComputeHeaders()
@@ -736,11 +670,12 @@ namespace System.Net
if (NetEventSource.IsEnabled) NetEventSource.Info(this);
Debug.Assert(!ComputedHeaders, "ComputedHeaders is true.");
_responseState = ResponseState.ComputedHeaders;
-
+
ComputeCoreHeaders();
- if (NetEventSource.IsEnabled) NetEventSource.Info(this,
- $"flags: {flags} _boundaryType: {_boundaryType} _contentLength: {_contentLength} _keepAlive: {_keepAlive}");
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Info(this,
+$"flags: {flags} _boundaryType: {_boundaryType} _contentLength: {_contentLength} _keepAlive: {_keepAlive}");
if (_boundaryType == BoundaryType.None)
{
if (HttpListenerRequest.ProtocolVersion.Minor == 0)
@@ -817,7 +752,7 @@ namespace System.Net
Interop.HttpApi.HTTP_UNKNOWN_HEADER[] unknownHeaders = null;
List<GCHandle> pinnedHeaders;
GCHandle gcHandle;
-
+
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "SerializeHeaders(HTTP_RESPONSE_HEADERS)");
if (Headers.Count == 0)
{
@@ -900,8 +835,9 @@ namespace System.Net
{
lookup = -1;
}
- if (NetEventSource.IsEnabled) NetEventSource.Info(this,
- $"index={index},headers.count={Headers.Count},headerName:{headerName},lookup:{lookup} headerValue:{headerValue}");
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Info(this,
+ $"index={index},headers.count={Headers.Count},headerName:{headerName},lookup:{lookup} headerValue:{headerValue}");
if (lookup == -1)
{
if (unknownHeaders == null)
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpListenerTimeoutManager.Windows.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerTimeoutManager.Windows.cs
index d32068b390..d32068b390 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpListenerTimeoutManager.Windows.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpListenerTimeoutManager.Windows.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpRequestQueueV2Handle.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpRequestQueueV2Handle.cs
index 4b87a516b0..4b87a516b0 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpRequestQueueV2Handle.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpRequestQueueV2Handle.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpRequestStream.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpRequestStream.Windows.cs
index 25207a3d34..25207a3d34 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpRequestStream.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpRequestStream.Windows.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpResponseStream.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpResponseStream.Windows.cs
index 8bf255118e..4859adac8e 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpResponseStream.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpResponseStream.Windows.cs
@@ -391,7 +391,7 @@ namespace System.Net
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "dataWritten:" + dataWritten + " _leftToWrite:" + _leftToWrite + " _closed:" + _closed);
}
- private static readonly byte[] ChunkTerminator = new byte[] { (byte)'0', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' };
+ private static readonly byte[] s_chunkTerminator = new byte[] { (byte)'0', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' };
protected override void Dispose(bool disposing)
{
@@ -427,7 +427,7 @@ namespace System.Net
{
flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
}
- fixed (void* pBuffer = ChunkTerminator)
+ fixed (void* pBuffer = s_chunkTerminator)
{
Interop.HttpApi.HTTP_DATA_CHUNK* pDataChunk = null;
if (_httpContext.Response.BoundaryType == BoundaryType.Chunked)
@@ -435,7 +435,7 @@ namespace System.Net
Interop.HttpApi.HTTP_DATA_CHUNK dataChunk = new Interop.HttpApi.HTTP_DATA_CHUNK();
dataChunk.DataChunkType = Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
dataChunk.pBuffer = (byte*)pBuffer;
- dataChunk.BufferLength = (uint)ChunkTerminator.Length;
+ dataChunk.BufferLength = (uint)s_chunkTerminator.Length;
pDataChunk = &dataChunk;
}
if (!sentHeaders)
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpResponseStreamAsyncResult.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpResponseStreamAsyncResult.cs
index b24681be14..b24681be14 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpResponseStreamAsyncResult.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpResponseStreamAsyncResult.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/HttpServerSessionHandle.cs b/src/System.Net.HttpListener/src/System/Net/Windows/HttpServerSessionHandle.cs
index 99ae13b5fd..99ae13b5fd 100644
--- a/src/System.Net.HttpListener/src/System/Net/HttpServerSessionHandle.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/HttpServerSessionHandle.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/ListenerAsyncResult.cs b/src/System.Net.HttpListener/src/System/Net/Windows/ListenerAsyncResult.Windows.cs
index 74e82a36d4..74e82a36d4 100644
--- a/src/System.Net.HttpListener/src/System/Net/ListenerAsyncResult.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/ListenerAsyncResult.Windows.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/ListenerClientCertAsyncResult.cs b/src/System.Net.HttpListener/src/System/Net/Windows/ListenerClientCertAsyncResult.Windows.cs
index 6a0624750a..da5ef48efc 100644
--- a/src/System.Net.HttpListener/src/System/Net/ListenerClientCertAsyncResult.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/ListenerClientCertAsyncResult.Windows.cs
@@ -10,7 +10,7 @@ using System.Threading;
namespace System.Net
{
- unsafe internal class ListenerClientCertAsyncResult : LazyAsyncResult
+ internal unsafe class ListenerClientCertAsyncResult : LazyAsyncResult
{
private ThreadPoolBoundHandle _boundHandle;
private NativeOverlapped* _pOverlapped;
@@ -115,8 +115,9 @@ namespace System.Net
Interop.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult._memoryBlob;
if (pClientCertInfo != null)
{
- if (NetEventSource.IsEnabled) NetEventSource.Info(null,
- $"pClientCertInfo:{(IntPtr)pClientCertInfo} pClientCertInfo->CertFlags: {pClientCertInfo->CertFlags} pClientCertInfo->CertEncodedSize: {pClientCertInfo->CertEncodedSize} pClientCertInfo->pCertEncoded: {(IntPtr)pClientCertInfo->pCertEncoded} pClientCertInfo->Token: {(IntPtr)pClientCertInfo->Token} pClientCertInfo->CertDeniedByMapper: {pClientCertInfo->CertDeniedByMapper}");
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Info(null,
+ $"pClientCertInfo:{(IntPtr)pClientCertInfo} pClientCertInfo->CertFlags: {pClientCertInfo->CertFlags} pClientCertInfo->CertEncodedSize: {pClientCertInfo->CertEncodedSize} pClientCertInfo->pCertEncoded: {(IntPtr)pClientCertInfo->pCertEncoded} pClientCertInfo->Token: {(IntPtr)pClientCertInfo->Token} pClientCertInfo->CertDeniedByMapper: {pClientCertInfo->CertDeniedByMapper}");
if (pClientCertInfo->pCertEncoded != null)
{
try
@@ -127,8 +128,9 @@ namespace System.Net
}
catch (CryptographicException exception)
{
- if (NetEventSource.IsEnabled) NetEventSource.Info(null,
- $"HttpListenerRequest: {httpListenerRequest} caught CryptographicException: {exception}");
+ if (NetEventSource.IsEnabled)
+ NetEventSource.Info(null,
+ $"HttpListenerRequest: {httpListenerRequest} caught CryptographicException: {exception}");
result = exception;
}
catch (SecurityException exception)
diff --git a/src/System.Net.HttpListener/src/System/Net/ListenerClientCertState.cs b/src/System.Net.HttpListener/src/System/Net/Windows/ListenerClientCertState.cs
index 4e8bff395c..4e8bff395c 100644
--- a/src/System.Net.HttpListener/src/System/Net/ListenerClientCertState.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/ListenerClientCertState.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/RequestContextBase.cs b/src/System.Net.HttpListener/src/System/Net/Windows/RequestContextBase.cs
index 3d1021e525..3d1021e525 100644
--- a/src/System.Net.HttpListener/src/System/Net/RequestContextBase.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/RequestContextBase.cs
diff --git a/src/System.Net.HttpListener/src/System/Net/SyncRequestContext.cs b/src/System.Net.HttpListener/src/System/Net/Windows/SyncRequestContext.cs
index f7ba1e4f1b..f7ba1e4f1b 100644
--- a/src/System.Net.HttpListener/src/System/Net/SyncRequestContext.cs
+++ b/src/System.Net.HttpListener/src/System/Net/Windows/SyncRequestContext.cs
diff --git a/src/System.Net.HttpListener/tests/AuthenticationTests.cs b/src/System.Net.HttpListener/tests/AuthenticationTests.cs
new file mode 100644
index 0000000000..107d36b328
--- /dev/null
+++ b/src/System.Net.HttpListener/tests/AuthenticationTests.cs
@@ -0,0 +1,152 @@
+// 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.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Net.Tests
+{
+ public class AuthenticationTests
+ {
+ private const string Basic = "Basic";
+ private const string TestUser = "testuser";
+ private const string TestPassword = "testpassword";
+
+ [ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
+ [InlineData(AuthenticationSchemes.Basic)]
+ [InlineData(AuthenticationSchemes.Basic | AuthenticationSchemes.None)]
+ [InlineData(AuthenticationSchemes.Basic | AuthenticationSchemes.Anonymous)]
+ public async Task TestBasicAuthentication(AuthenticationSchemes authScheme)
+ {
+ string url = UrlPrefix.CreateLocal();
+ HttpListener listener = new HttpListener();
+
+ try
+ {
+ listener.Prefixes.Add(url);
+ listener.AuthenticationSchemes = authScheme;
+ listener.Start();
+
+ await ValidateValidUser(url, listener);
+ }
+ finally
+ {
+ listener.Stop();
+ listener.Close();
+ }
+ }
+
+ [ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
+ public async Task TestAnonymousAuthentication()
+ {
+ string url = UrlPrefix.CreateLocal();
+ HttpListener listener = new HttpListener();
+
+ try
+ {
+ listener.Prefixes.Add(url);
+ listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
+ listener.Start();
+
+ await ValidateNullUser(url, listener);
+ }
+ finally
+ {
+ listener.Stop();
+ listener.Close();
+ }
+ }
+
+ [ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
+ public async Task TestBasicAuthenticationWithDelegate()
+ {
+ string url = UrlPrefix.CreateLocal();
+ HttpListener listener = new HttpListener();
+ try
+ {
+ listener.Prefixes.Add(url);
+ listener.AuthenticationSchemes = AuthenticationSchemes.None;
+ AuthenticationSchemeSelector selector = new AuthenticationSchemeSelector(SelectAnonymousAndBasicSchemes);
+ listener.AuthenticationSchemeSelectorDelegate += selector;
+ listener.Start();
+
+ await ValidateValidUser(url, listener);
+ }
+ finally
+ {
+ listener.Stop();
+ listener.Close();
+ }
+ }
+
+ [ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
+ public async Task TestAnonymousAuthenticationWithDelegate()
+ {
+ string url = UrlPrefix.CreateLocal();
+ HttpListener listener = new HttpListener();
+ try
+ {
+ listener.Prefixes.Add(url);
+ listener.AuthenticationSchemes = AuthenticationSchemes.None;
+ AuthenticationSchemeSelector selector = new AuthenticationSchemeSelector(SelectAnonymousScheme);
+ listener.AuthenticationSchemeSelectorDelegate += selector;
+ listener.Start();
+
+ await ValidateNullUser(url, listener);
+ }
+ finally
+ {
+ listener.Stop();
+ listener.Close();
+ }
+ }
+
+ private async Task ValidateNullUser(string url, HttpListener listener)
+ {
+ var serverContextTask = listener.GetContextAsync();
+
+ using (HttpClient client = new HttpClient())
+ {
+ client.DefaultRequestHeaders.Authorization = new Http.Headers.AuthenticationHeaderValue(
+ Basic,
+ Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", TestUser, TestPassword))));
+
+ var clientTask = client.GetStringAsync(url);
+ HttpListenerContext listenerContext = await serverContextTask;
+
+ Assert.Null(listenerContext.User);
+ }
+ }
+
+ private async Task ValidateValidUser(string url, HttpListener listener)
+ {
+ var serverContextTask = listener.GetContextAsync();
+ using (HttpClient client = new HttpClient())
+ {
+ client.DefaultRequestHeaders.Authorization = new Http.Headers.AuthenticationHeaderValue(
+ Basic,
+ Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", TestUser, TestPassword))));
+
+ var clientTask = client.GetStringAsync(url);
+ HttpListenerContext listenerContext = await serverContextTask;
+
+ Assert.Equal(TestUser, listenerContext.User.Identity.Name);
+ Assert.True(listenerContext.User.Identity.IsAuthenticated);
+ Assert.Equal(Basic, listenerContext.User.Identity.AuthenticationType);
+ }
+ }
+
+ private AuthenticationSchemes SelectAnonymousAndBasicSchemes(HttpListenerRequest request)
+ {
+ return AuthenticationSchemes.Anonymous | AuthenticationSchemes.Basic;
+ }
+
+ private AuthenticationSchemes SelectAnonymousScheme(HttpListenerRequest request)
+ {
+ return AuthenticationSchemes.Anonymous;
+ }
+ }
+}
diff --git a/src/System.Net.HttpListener/tests/SimpleHttpTest.cs b/src/System.Net.HttpListener/tests/SimpleHttpTest.cs
index 373a671acc..20d85fc4df 100644
--- a/src/System.Net.HttpListener/tests/SimpleHttpTest.cs
+++ b/src/System.Net.HttpListener/tests/SimpleHttpTest.cs
@@ -10,16 +10,15 @@ using Xunit;
// TODO: #13618
namespace System.Net.Tests
{
- [PlatformSpecific(TestPlatforms.Windows)]
public class SimpleHttpTest
{
- [Fact]
+ [ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
public static void Supported_True()
{
Assert.True(HttpListener.IsSupported);
}
- [Fact]
+ [ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
public static async Task SimpleRequest_Succeeds()
{
string url = UrlPrefix.CreateLocal();
diff --git a/src/System.Net.HttpListener/tests/System.Net.HttpListener.Tests.csproj b/src/System.Net.HttpListener/tests/System.Net.HttpListener.Tests.csproj
index 3b26223a1a..ed1ccb05ee 100644
--- a/src/System.Net.HttpListener/tests/System.Net.HttpListener.Tests.csproj
+++ b/src/System.Net.HttpListener/tests/System.Net.HttpListener.Tests.csproj
@@ -11,8 +11,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
<ItemGroup>
+ <Compile Include="AuthenticationTests.cs" />
<Compile Include="SimpleHttpTest.cs" />
<Compile Include="UrlPrefix.cs" />
+ <Compile Include="$(CommonTestPath)\System\PlatformDetection.cs">
+ <Link>Common\tests\System\PlatformDetection.cs</Link>
+ </Compile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Net.Mail/pkg/System.Net.Mail.pkgproj b/src/System.Net.Mail/pkg/System.Net.Mail.pkgproj
index f208793465..4318d41e9e 100644
--- a/src/System.Net.Mail/pkg/System.Net.Mail.pkgproj
+++ b/src/System.Net.Mail/pkg/System.Net.Mail.pkgproj
@@ -4,7 +4,7 @@
<ItemGroup>
<ProjectReference Include="..\ref\System.Net.Mail.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Net.Mail.builds" />
<InboxOnTargetFramework Include="$(AllXamarinFrameworks)" />
diff --git a/src/System.Net.Mail/src/Configurations.props b/src/System.Net.Mail/src/Configurations.props
index 3bb6330d9e..4caac7c12c 100644
--- a/src/System.Net.Mail/src/Configurations.props
+++ b/src/System.Net.Mail/src/Configurations.props
@@ -4,7 +4,7 @@
<BuildConfigurations>
netstandard-Unix;
netstandard-Windows_NT;
- net463-Windows_NT;
+ net461-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>
diff --git a/src/System.Net.Mail/src/System.Net.Mail.csproj b/src/System.Net.Mail/src/System.Net.Mail.csproj
index 70c158bff4..9793d4582d 100644
--- a/src/System.Net.Mail/src/System.Net.Mail.csproj
+++ b/src/System.Net.Mail/src/System.Net.Mail.csproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<ProjectGuid>{53D09AF4-0C13-4197-B8AD-9746F0374E88}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net463'">true</IsPartialFacadeAssembly>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net461'">true</IsPartialFacadeAssembly>
</PropertyGroup>
<!-- Default configurations to help VS understand the options -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Debug|AnyCPU'" />
@@ -13,8 +13,8 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Unix_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Unix_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\Net\Base64Stream.cs" />
<Compile Include="System\Net\Mime\MimePart.cs" />
@@ -147,8 +147,8 @@
<Compile Include="$(CommonPath)\System\Net\NegotiationInfoClass.cs">
<Link>Common\System\Net\NegotiationInfoClass.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Net\NTAuthentication.cs">
- <Link>Common\System\Net\NTAuthentication.cs</Link>
+ <Compile Include="$(CommonPath)\System\Net\NTAuthentication.Common.cs">
+ <Link>Common\System\Net\NTAuthentication.Common.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Net\SecurityStatusPal.cs">
<Link>Common\System\Net\SecurityStatusPal.cs</Link>
@@ -162,7 +162,9 @@
<Compile Include="$(CommonPath)\System\Net\Security\SSPIHandleCache.cs">
<Link>Common\System\Net\Security\SSPIHandleCache.cs</Link>
</Compile>
- <Compile Include="System\Net\Security\NetEventSource.Security.cs" />
+ <Compile Include="$(CommonPath)\System\Net\Security\NetEventSource.Security.cs">
+ <Link>Common\System\Net\Security\NetEventSource.Security.cs</Link>
+ </Compile>
</ItemGroup>
<!-- Unix specific files -->
<ItemGroup Condition="'$(TargetsUnix)'=='true' And '$(TargetGroup)' == 'netstandard'">
@@ -220,7 +222,9 @@
<Compile Include="$(CommonPath)\System\Net\Security\NegotiateStreamPal.Windows.cs">
<Link>Common\System\Net\Security\NegotiateStreamPal.Windows.cs</Link>
</Compile>
- <Compile Include="System\Net\Security\NetEventSource.Security.Windows.cs" />
+ <Compile Include="$(CommonPath)\System\Net\Security\NetEventSource.Security.Windows.cs">
+ <Link>Common\System\Net\Security\NetEventSource.Security.Windows.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\Crypt32\Interop.certificates_types.cs">
<Link>Common\Interop\Windows\Crypt32\Interop.certificates_types.cs</Link>
</Compile>
@@ -285,7 +289,7 @@
<Link>Common\Interop\Windows\sspicli\SSPIWrapper.cs</Link>
</Compile>
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="System" />
</ItemGroup>
<ItemGroup>
diff --git a/src/System.Net.Mail/src/System/Net/Base64Stream.cs b/src/System.Net.Mail/src/System/Net/Base64Stream.cs
index cd3b476c52..5217a7c9a1 100644
--- a/src/System.Net.Mail/src/System/Net/Base64Stream.cs
+++ b/src/System.Net.Mail/src/System/Net/Base64Stream.cs
@@ -499,7 +499,7 @@ namespace System.Net
private sealed class WriteAsyncResult : LazyAsyncResult
{
- private readonly static AsyncCallback s_onWrite = OnWrite;
+ private static readonly AsyncCallback s_onWrite = OnWrite;
private readonly Base64Stream _parent;
private readonly byte[] _buffer;
diff --git a/src/System.Net.Mail/src/System/Net/Mail/SmtpCommands.cs b/src/System.Net.Mail/src/System/Net/Mail/SmtpCommands.cs
index bd143c1e08..7bbadc19f7 100644
--- a/src/System.Net.Mail/src/System/Net/Mail/SmtpCommands.cs
+++ b/src/System.Net.Mail/src/System/Net/Mail/SmtpCommands.cs
@@ -639,25 +639,25 @@ namespace System.Net.Mail
internal static class SmtpCommands
{
- internal readonly static byte[] Auth = Encoding.ASCII.GetBytes("AUTH ");
- internal readonly static byte[] CRLF = Encoding.ASCII.GetBytes("\r\n");
- internal readonly static byte[] Data = Encoding.ASCII.GetBytes("DATA\r\n");
- internal readonly static byte[] DataStop = Encoding.ASCII.GetBytes("\r\n.\r\n");
- internal readonly static byte[] EHello = Encoding.ASCII.GetBytes("EHLO ");
- internal readonly static byte[] Expand = Encoding.ASCII.GetBytes("EXPN ");
- internal readonly static byte[] Hello = Encoding.ASCII.GetBytes("HELO ");
- internal readonly static byte[] Help = Encoding.ASCII.GetBytes("HELP");
- internal readonly static byte[] Mail = Encoding.ASCII.GetBytes("MAIL FROM:");
- internal readonly static byte[] Noop = Encoding.ASCII.GetBytes("NOOP\r\n");
- internal readonly static byte[] Quit = Encoding.ASCII.GetBytes("QUIT\r\n");
- internal readonly static byte[] Recipient = Encoding.ASCII.GetBytes("RCPT TO:");
- internal readonly static byte[] Reset = Encoding.ASCII.GetBytes("RSET\r\n");
- internal readonly static byte[] Send = Encoding.ASCII.GetBytes("SEND FROM:");
- internal readonly static byte[] SendAndMail = Encoding.ASCII.GetBytes("SAML FROM:");
- internal readonly static byte[] SendOrMail = Encoding.ASCII.GetBytes("SOML FROM:");
- internal readonly static byte[] Turn = Encoding.ASCII.GetBytes("TURN\r\n");
- internal readonly static byte[] Verify = Encoding.ASCII.GetBytes("VRFY ");
- internal readonly static byte[] StartTls = Encoding.ASCII.GetBytes("STARTTLS");
+ internal static readonly byte[] Auth = Encoding.ASCII.GetBytes("AUTH ");
+ internal static readonly byte[] CRLF = Encoding.ASCII.GetBytes("\r\n");
+ internal static readonly byte[] Data = Encoding.ASCII.GetBytes("DATA\r\n");
+ internal static readonly byte[] DataStop = Encoding.ASCII.GetBytes("\r\n.\r\n");
+ internal static readonly byte[] EHello = Encoding.ASCII.GetBytes("EHLO ");
+ internal static readonly byte[] Expand = Encoding.ASCII.GetBytes("EXPN ");
+ internal static readonly byte[] Hello = Encoding.ASCII.GetBytes("HELO ");
+ internal static readonly byte[] Help = Encoding.ASCII.GetBytes("HELP");
+ internal static readonly byte[] Mail = Encoding.ASCII.GetBytes("MAIL FROM:");
+ internal static readonly byte[] Noop = Encoding.ASCII.GetBytes("NOOP\r\n");
+ internal static readonly byte[] Quit = Encoding.ASCII.GetBytes("QUIT\r\n");
+ internal static readonly byte[] Recipient = Encoding.ASCII.GetBytes("RCPT TO:");
+ internal static readonly byte[] Reset = Encoding.ASCII.GetBytes("RSET\r\n");
+ internal static readonly byte[] Send = Encoding.ASCII.GetBytes("SEND FROM:");
+ internal static readonly byte[] SendAndMail = Encoding.ASCII.GetBytes("SAML FROM:");
+ internal static readonly byte[] SendOrMail = Encoding.ASCII.GetBytes("SOML FROM:");
+ internal static readonly byte[] Turn = Encoding.ASCII.GetBytes("TURN\r\n");
+ internal static readonly byte[] Verify = Encoding.ASCII.GetBytes("VRFY ");
+ internal static readonly byte[] StartTls = Encoding.ASCII.GetBytes("STARTTLS");
}
diff --git a/src/System.Net.Mail/src/System/Net/Mime/QEncodedStream.cs b/src/System.Net.Mail/src/System/Net/Mime/QEncodedStream.cs
index ca7343910a..1f73dacfda 100644
--- a/src/System.Net.Mail/src/System/Net/Mime/QEncodedStream.cs
+++ b/src/System.Net.Mail/src/System/Net/Mime/QEncodedStream.cs
@@ -322,7 +322,7 @@ namespace System.Net.Mime
private class WriteAsyncResult : LazyAsyncResult
{
- private readonly static AsyncCallback s_onWrite = OnWrite;
+ private static readonly AsyncCallback s_onWrite = OnWrite;
private readonly QEncodedStream _parent;
private readonly byte[] _buffer;
diff --git a/src/System.Net.Mail/src/System/Net/Mime/QuotedPrintableStream.cs b/src/System.Net.Mail/src/System/Net/Mime/QuotedPrintableStream.cs
index 4982a67654..e70646283e 100644
--- a/src/System.Net.Mail/src/System/Net/Mime/QuotedPrintableStream.cs
+++ b/src/System.Net.Mail/src/System/Net/Mime/QuotedPrintableStream.cs
@@ -376,7 +376,7 @@ namespace System.Net.Mime
private readonly byte[] _buffer;
private readonly int _offset;
private readonly int _count;
- private readonly static AsyncCallback s_onWrite = new AsyncCallback(OnWrite);
+ private static readonly AsyncCallback s_onWrite = new AsyncCallback(OnWrite);
private int _written;
internal WriteAsyncResult(QuotedPrintableStream parent, byte[] buffer, int offset, int count, AsyncCallback callback, object state) : base(null, state, callback)
diff --git a/src/System.Net.Mail/src/System/Net/Mime/SmtpDateTime.cs b/src/System.Net.Mail/src/System/Net/Mime/SmtpDateTime.cs
index adf08d9162..17c431f786 100644
--- a/src/System.Net.Mail/src/System/Net/Mime/SmtpDateTime.cs
+++ b/src/System.Net.Mail/src/System/Net/Mime/SmtpDateTime.cs
@@ -58,7 +58,7 @@ namespace System.Net.Mime
// array of all possible date time values
// if a string matches any one of these it will be parsed correctly
- internal readonly static string[] s_validDateTimeFormats = new string[]
+ internal static readonly string[] s_validDateTimeFormats = new string[]
{
DateFormatWithDayOfWeek,
DateFormatWithoutDayOfWeek,
@@ -66,7 +66,7 @@ namespace System.Net.Mime
DateFormatWithoutDayOfWeekAndNoSeconds
};
- internal readonly static char[] s_allowedWhiteSpaceChars = new char[] { ' ', '\t' };
+ internal static readonly char[] s_allowedWhiteSpaceChars = new char[] { ' ', '\t' };
internal static readonly Dictionary<string, TimeSpan> s_timeZoneOffsetLookup = InitializeShortHandLookups();
diff --git a/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxNetworkInterface.cs b/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxNetworkInterface.cs
index c93b49acab..406cfd0624 100644
--- a/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxNetworkInterface.cs
+++ b/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxNetworkInterface.cs
@@ -26,7 +26,7 @@ namespace System.Net.NetworkInformation
_ipProperties = new LinuxIPInterfaceProperties(this);
}
- public unsafe static NetworkInterface[] GetLinuxNetworkInterfaces()
+ public static unsafe NetworkInterface[] GetLinuxNetworkInterfaces()
{
Dictionary<string, LinuxNetworkInterface> interfacesByName = new Dictionary<string, LinuxNetworkInterface>();
List<Exception> exceptions = null;
diff --git a/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Windows.cs b/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Windows.cs
index aa8274b0d9..772b6b0fce 100644
--- a/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Windows.cs
+++ b/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Windows.cs
@@ -50,12 +50,12 @@ namespace System.Net.NetworkInformation
internal static class AvailabilityChangeListener
{
- private readonly static object s_syncObject = new object();
- private readonly static Dictionary<NetworkAvailabilityChangedEventHandler, ExecutionContext> s_availabilityCallerArray =
+ private static readonly object s_syncObject = new object();
+ private static readonly Dictionary<NetworkAvailabilityChangedEventHandler, ExecutionContext> s_availabilityCallerArray =
new Dictionary<NetworkAvailabilityChangedEventHandler, ExecutionContext>();
- private readonly static NetworkAddressChangedEventHandler s_addressChange = ChangedAddress;
+ private static readonly NetworkAddressChangedEventHandler s_addressChange = ChangedAddress;
private static volatile bool s_isAvailable = false;
- private readonly static ContextCallback s_RunHandlerCallback = new ContextCallback(RunHandlerCallback);
+ private static readonly ContextCallback s_RunHandlerCallback = new ContextCallback(RunHandlerCallback);
private static void RunHandlerCallback(object state)
{
@@ -122,11 +122,11 @@ namespace System.Net.NetworkInformation
}
// Helper class for detecting address change events.
- internal unsafe static class AddressChangeListener
+ internal static unsafe class AddressChangeListener
{
- private readonly static Dictionary<NetworkAddressChangedEventHandler, ExecutionContext> s_callerArray =
+ private static readonly Dictionary<NetworkAddressChangedEventHandler, ExecutionContext> s_callerArray =
new Dictionary<NetworkAddressChangedEventHandler, ExecutionContext>();
- private readonly static ContextCallback s_runHandlerCallback = new ContextCallback(RunHandlerCallback);
+ private static readonly ContextCallback s_runHandlerCallback = new ContextCallback(RunHandlerCallback);
private static RegisteredWaitHandle s_registeredWait;
// Need to keep the reference so it isn't GC'd before the native call executes.
diff --git a/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/OsxNetworkInterface.cs b/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/OsxNetworkInterface.cs
index 492cf3dd02..3597744960 100644
--- a/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/OsxNetworkInterface.cs
+++ b/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/OsxNetworkInterface.cs
@@ -24,7 +24,7 @@ namespace System.Net.NetworkInformation
_ipProperties = new OsxIpInterfaceProperties(this, (int)nativeStats.Mtu);
}
- public unsafe static NetworkInterface[] GetOsxNetworkInterfaces()
+ public static unsafe NetworkInterface[] GetOsxNetworkInterfaces()
{
Dictionary<string, OsxNetworkInterface> interfacesByName = new Dictionary<string, OsxNetworkInterface>();
List<Exception> exceptions = null;
diff --git a/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/TeredoHelper.cs b/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/TeredoHelper.cs
index 4150829011..5676adf60b 100644
--- a/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/TeredoHelper.cs
+++ b/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/TeredoHelper.cs
@@ -31,7 +31,7 @@ namespace System.Net.NetworkInformation
{
// Holds a list of all pending calls to NotifyStableUnicastIpAddressTable. Also used as a lock to protect its
// contents.
- private readonly static List<TeredoHelper> s_pendingNotifications = new List<TeredoHelper>();
+ private static readonly List<TeredoHelper> s_pendingNotifications = new List<TeredoHelper>();
private readonly Action<object> _callback;
private readonly object _state;
diff --git a/src/System.Net.Primitives/ref/System.Net.Primitives.cs b/src/System.Net.Primitives/ref/System.Net.Primitives.cs
index 1d5ac78d9e..a48150966f 100644
--- a/src/System.Net.Primitives/ref/System.Net.Primitives.cs
+++ b/src/System.Net.Primitives/ref/System.Net.Primitives.cs
@@ -243,9 +243,15 @@ namespace System.Net
{
public NetworkCredential() { }
public NetworkCredential(string userName, string password) { }
+ [System.CLSCompliant(false)]
+ public NetworkCredential(string userName, System.Security.SecureString password) { }
public NetworkCredential(string userName, string password, string domain) { }
+ [System.CLSCompliant(false)]
+ public NetworkCredential(string userName, System.Security.SecureString password, string domain) { }
public string Domain { get { throw null; } set { } }
public string Password { get { throw null; } set { } }
+ [System.CLSCompliant(false)]
+ public System.Security.SecureString SecurePassword { get { throw null; } set { } }
public string UserName { get { throw null; } set { } }
public System.Net.NetworkCredential GetCredential(string host, int port, string authenticationType) { throw null; }
public System.Net.NetworkCredential GetCredential(System.Uri uri, string authType) { throw null; }
@@ -357,6 +363,7 @@ namespace System.Net.Sockets
Irda = 26,
Iso = 7,
Lat = 14,
+ Max = 29,
NetBios = 17,
NetworkDesigners = 28,
NS = 6,
diff --git a/src/System.Net.Primitives/src/System/Net/Cookie.cs b/src/System.Net.Primitives/src/System/Net/Cookie.cs
index 07ad3dce08..7964a9012a 100644
--- a/src/System.Net.Primitives/src/System/Net/Cookie.cs
+++ b/src/System.Net.Primitives/src/System/Net/Cookie.cs
@@ -1333,7 +1333,7 @@ namespace System.Net
}
// Recognized attributes in order of expected frequency.
- private readonly static RecognizedAttribute[] s_recognizedAttributes = {
+ private static readonly RecognizedAttribute[] s_recognizedAttributes = {
new RecognizedAttribute(Cookie.PathAttributeName, CookieToken.Path),
new RecognizedAttribute(Cookie.MaxAgeAttributeName, CookieToken.MaxAge),
new RecognizedAttribute(Cookie.ExpiresAttributeName, CookieToken.Expires),
@@ -1347,7 +1347,7 @@ namespace System.Net
new RecognizedAttribute(Cookie.HttpOnlyAttributeName, CookieToken.HttpOnly),
};
- private readonly static RecognizedAttribute[] s_recognizedServerAttributes = {
+ private static readonly RecognizedAttribute[] s_recognizedServerAttributes = {
new RecognizedAttribute('$' + Cookie.PathAttributeName, CookieToken.Path),
new RecognizedAttribute('$' + Cookie.VersionAttributeName, CookieToken.Version),
new RecognizedAttribute('$' + Cookie.DomainAttributeName, CookieToken.Domain),
diff --git a/src/System.Net.Primitives/src/System/Net/NetworkCredential.cs b/src/System.Net.Primitives/src/System/Net/NetworkCredential.cs
index 737875ca82..253eb16c58 100644
--- a/src/System.Net.Primitives/src/System/Net/NetworkCredential.cs
+++ b/src/System.Net.Primitives/src/System/Net/NetworkCredential.cs
@@ -21,7 +21,7 @@ namespace System.Net
{
private string _domain;
private string _userName;
- private string _password;
+ private object _password;
public NetworkCredential()
: this(string.Empty, string.Empty, string.Empty)
@@ -42,7 +42,7 @@ namespace System.Net
/// <devdoc>
/// <para>
/// Initializes a new instance of the <see cref='System.Net.NetworkCredential'/>
- /// class with name and password set as specified.
+ /// class with name, password and domain set as specified.
/// </para>
/// </devdoc>
public NetworkCredential(string userName, string password, string domain)
@@ -52,6 +52,20 @@ namespace System.Net
Domain = domain;
}
+ [CLSCompliant(false)]
+ public NetworkCredential(string userName, SecureString password)
+ : this(userName, password, string.Empty)
+ {
+ }
+
+ [CLSCompliant(false)]
+ public NetworkCredential(string userName, SecureString password, string domain)
+ {
+ UserName = userName;
+ SecurePassword = password;
+ Domain = domain;
+ }
+
/// <devdoc>
/// <para>
/// The user name associated with this credential.
@@ -59,14 +73,8 @@ namespace System.Net
/// </devdoc>
public string UserName
{
- get
- {
- return InternalGetUserName();
- }
- set
- {
- _userName = value ?? string.Empty;
- }
+ get { return _userName; }
+ set { _userName = value ?? string.Empty; }
}
/// <devdoc>
@@ -78,52 +86,57 @@ namespace System.Net
{
get
{
- return InternalGetPassword();
+ SecureString sstr = _password as SecureString;
+ if (sstr != null)
+ {
+ return MarshalToString(sstr);
+ }
+ return (string)_password ?? string.Empty;
}
set
{
+ SecureString old = _password as SecureString;
_password = value;
+ old?.Dispose();
}
}
- /// <devdoc>
- /// <para>
- /// The machine name that verifies
- /// the credentials. Usually this is the host machine.
- /// </para>
- /// </devdoc>
- public string Domain
+ [CLSCompliant(false)]
+ public SecureString SecurePassword
{
get
{
- return InternalGetDomain();
- }
+ string str = _password as string;
+ if (str != null)
+ {
+ return MarshalToSecureString(str);
+ }
+ SecureString sstr = _password as SecureString;
+ return sstr != null ? sstr.Copy() : new SecureString();
+ }
set
- {
- _domain = value ?? string.Empty;
+ {
+ SecureString old = _password as SecureString;
+ _password = value?.Copy();
+ old?.Dispose();
}
}
- internal string InternalGetUserName()
- {
- return _userName;
- }
-
- internal string InternalGetPassword()
- {
- return _password;
- }
-
- internal string InternalGetDomain()
+ /// <devdoc>
+ /// <para>
+ /// The machine name that verifies
+ /// the credentials. Usually this is the host machine.
+ /// </para>
+ /// </devdoc>
+ public string Domain
{
- return _domain;
+ get { return _domain; }
+ set { _domain = value ?? string.Empty; }
}
internal string InternalGetDomainUserName()
{
- string domain = InternalGetDomain();
- string userName = InternalGetUserName();
- return domain != "" ? domain + "\\" + userName : userName;
+ return _domain != "" ? _domain + "\\" + _userName : _userName;
}
/// <devdoc>
@@ -142,30 +155,41 @@ namespace System.Net
return this;
}
-#if DEBUG
- // This method is only called as part of an assert
- internal bool IsEqualTo(object compObject)
+ private string MarshalToString(SecureString sstr)
{
- if ((object)compObject == null)
+ if (sstr == null || sstr.Length == 0)
{
- return false;
+ return string.Empty;
}
- if ((object)this == (object)compObject)
+ IntPtr ptr = IntPtr.Zero;
+ string result = string.Empty;
+ try
{
- return true;
+ ptr = Marshal.SecureStringToGlobalAllocUnicode(sstr);
+ result = Marshal.PtrToStringUni(ptr);
}
+ finally
+ {
+ if (ptr != IntPtr.Zero)
+ {
+ Marshal.ZeroFreeGlobalAllocUnicode(ptr);
+ }
+ }
+ return result;
+ }
- NetworkCredential compCred = compObject as NetworkCredential;
- if ((object)compCred == null)
+ private unsafe SecureString MarshalToSecureString(string str)
+ {
+ if (string.IsNullOrEmpty(str))
{
- return false;
+ return new SecureString();
}
- return (InternalGetUserName() == compCred.InternalGetUserName() &&
- InternalGetDomain() == compCred.InternalGetDomain() &&
- string.Equals(_password, compCred._password, StringComparison.Ordinal));
+ fixed (char* ptr = str)
+ {
+ return new SecureString(ptr, str.Length);
+ }
}
-#endif
}
}
diff --git a/src/System.Net.Primitives/tests/FunctionalTests/NetworkCredentialTest.cs b/src/System.Net.Primitives/tests/FunctionalTests/NetworkCredentialTest.cs
index 3e2bfd609d..8c3cb0f9ed 100644
--- a/src/System.Net.Primitives/tests/FunctionalTests/NetworkCredentialTest.cs
+++ b/src/System.Net.Primitives/tests/FunctionalTests/NetworkCredentialTest.cs
@@ -6,7 +6,7 @@ using Xunit;
namespace System.Net.Primitives.Functional.Tests
{
- public static class NetworkCredentialTest
+ public static partial class NetworkCredentialTest
{
[Fact]
public static void Ctor_Empty_Success()
diff --git a/src/System.Net.Primitives/tests/FunctionalTests/NetworkCredentialTest.netstandard1.7.cs b/src/System.Net.Primitives/tests/FunctionalTests/NetworkCredentialTest.netstandard1.7.cs
new file mode 100644
index 0000000000..38a2c29767
--- /dev/null
+++ b/src/System.Net.Primitives/tests/FunctionalTests/NetworkCredentialTest.netstandard1.7.cs
@@ -0,0 +1,131 @@
+// 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.Generic;
+using System.Runtime.InteropServices;
+using System.Security;
+using Xunit;
+
+namespace System.Net.Primitives.Functional.Tests
+{
+ public static partial class NetworkCredentialTest
+ {
+ public static IEnumerable<object[]> SecurePassword_TestData()
+ {
+ yield return new object[] { "password", AsSecureString("password") };
+ yield return new object[] { "SecurePassword", AsSecureString("SecurePassword") };
+ yield return new object[] { "", AsSecureString("") };
+ yield return new object[] { null, AsSecureString(null) };
+ }
+
+ public static IEnumerable<object[]> Password_RoundTestData()
+ {
+ yield return new object[] { "password", "planPassword" };
+ yield return new object[] { "SecurePassword", "justOnePassword" };
+ yield return new object[] { "", "OneMoreTest" };
+ yield return new object[] { null, null };
+ }
+
+ [Fact]
+ public static void Ctor_SecureString_Test()
+ {
+ string expectedUser = "UserName";
+
+ using (SecureString expectedSecurePassword = AsSecureString("password"))
+ {
+ NetworkCredential nc = new NetworkCredential(expectedUser, expectedSecurePassword);
+ Assert.Equal(expectedUser, nc.UserName);
+ Assert.True(expectedSecurePassword.CompareSecureString(nc.SecurePassword));
+ }
+ }
+
+ [Fact]
+ public static void Ctor_SecureStringDomain_Test()
+ {
+ string expectedUser = "UserName";
+ string expectedDomain = "thisDomain";
+
+ using (SecureString expectedSecurePassword = AsSecureString("password"))
+ {
+ NetworkCredential nc = new NetworkCredential(expectedUser, expectedSecurePassword, expectedDomain);
+ Assert.Equal(expectedUser, nc.UserName);
+ Assert.Equal(expectedDomain, nc.Domain);
+ Assert.True(expectedSecurePassword.CompareSecureString(nc.SecurePassword));
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(SecurePassword_TestData))]
+ public static void SecurePasswordSetGet_Test(string password, SecureString expectedPassword)
+ {
+ NetworkCredential nc = new NetworkCredential();
+ using (SecureString securePassword = AsSecureString(password))
+ {
+ nc.SecurePassword = securePassword;
+ Assert.True(expectedPassword.CompareSecureString(nc.SecurePassword));
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(Password_RoundTestData))]
+ public static void SecurePassword_Password_RoundData_Test(string expectedSecurePassword, string expectedPassword)
+ {
+ NetworkCredential nc = new NetworkCredential();
+ using (SecureString securePassword = AsSecureString(expectedSecurePassword))
+ {
+ nc.SecurePassword = securePassword;
+ Assert.Equal(expectedSecurePassword ?? string.Empty, nc.Password);
+
+ nc.Password = expectedPassword;
+ Assert.True(AsSecureString(expectedPassword).CompareSecureString(nc.SecurePassword));
+ }
+ }
+
+ private static bool CompareSecureString(this SecureString s1, SecureString s2)
+ {
+ return s1 != null && s2 != null && AsString(s1) == AsString(s2);
+ }
+
+ private static string AsString(SecureString sstr)
+ {
+ if (sstr.Length == 0)
+ {
+ return string.Empty;
+ }
+
+ IntPtr ptr = IntPtr.Zero;
+ string result = string.Empty;
+ try
+ {
+ ptr = Marshal.SecureStringToGlobalAllocUnicode(sstr);
+ result = Marshal.PtrToStringUni(ptr);
+ }
+ finally
+ {
+ if (ptr != IntPtr.Zero)
+ {
+ Marshal.ZeroFreeGlobalAllocUnicode(ptr);
+ }
+ }
+ return result;
+ }
+
+ private static SecureString AsSecureString(string str)
+ {
+ SecureString secureString = new SecureString();
+
+ if (string.IsNullOrEmpty(str))
+ {
+ return secureString;
+ }
+
+ foreach (char ch in str)
+ {
+ secureString.AppendChar(ch);
+ }
+
+ return secureString;
+ }
+ }
+}
diff --git a/src/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj b/src/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj
index 3ac9219e93..474179e2dc 100644
--- a/src/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj
+++ b/src/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj
@@ -26,13 +26,14 @@
<Compile Include="IPAddressMappingTest.cs" />
<Compile Include="IPEndPointTest.cs" />
<Compile Include="NetworkCredentialTest.cs" />
- <Compile Include="RequestCachePolicyTest.cs" Condition="'$(TargetGroup)' == 'netstandard1.7'" />
<Compile Include="SocketAddressTest.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard1.7'">
<Compile Include="LoggingTest.cs" />
<Compile Include="SerializationTest.cs" />
+ <Compile Include="RequestCachePolicyTest.cs" />
<Compile Include="CookieContainerAddTest.cs" />
+ <Compile Include="NetworkCredentialTest.netstandard1.7.cs" />
<Compile Include="$(CommonTestPath)\System\Diagnostics\Tracing\TestEventListener.cs">
<Link>Common\System\Diagnostics\Tracing\TestEventListener.cs</Link>
</Compile>
diff --git a/src/System.Net.Requests/ref/System.Net.Requests.cs b/src/System.Net.Requests/ref/System.Net.Requests.cs
index 878317796f..f2f20251c2 100644
--- a/src/System.Net.Requests/ref/System.Net.Requests.cs
+++ b/src/System.Net.Requests/ref/System.Net.Requests.cs
@@ -106,7 +106,7 @@ namespace System.Net
public override System.IO.Stream GetRequestStream() { throw null; }
public override System.Net.WebResponse GetResponse() { throw null; }
}
- public class FtpWebResponse : WebResponse
+ public class FtpWebResponse : WebResponse, IDisposable
{
internal FtpWebResponse() { }
public override long ContentLength { get { throw null; } }
@@ -123,9 +123,11 @@ namespace System.Net
public string StatusDescription { get { throw null; } }
public DateTime LastModified { get { throw null; } }
}
- public partial class HttpWebRequest : System.Net.WebRequest
+ public partial class HttpWebRequest : System.Net.WebRequest, System.Runtime.Serialization.ISerializable
{
internal HttpWebRequest() { }
+ [System.ObsoleteAttribute("Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202")]
+ protected HttpWebRequest(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { }
public string Accept { get { throw null; } set { } }
public virtual bool AllowReadStreamBuffering { get { throw null; } set { } }
public override string ContentType { get { throw null; } set { } }
@@ -152,8 +154,7 @@ namespace System.Net
public DateTime Date { get { throw null; } set { } }
public static int DefaultMaximumResponseHeadersLength { get { throw null; } set { } }
public static int DefaultMaximumErrorResponseLength { get { throw null; } set { } }
- public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates {
- get { throw null; } set { } }
+ public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get { throw null; } set { } }
public string Expect { get { throw null; } set { } }
public DateTime IfModifiedSince { get { throw null; } set { } }
public bool KeepAlive { get { throw null; } set { } }
@@ -183,10 +184,24 @@ namespace System.Net
public override string ConnectionGroupName { get { throw null; } set { } }
public System.Net.Security.RemoteCertificateValidationCallback ServerCertificateValidationCallback { get; set; }
public HttpContinueDelegate ContinueDelegate { get { throw null; } set { } }
+ public string Connection { get { throw null; } set { } }
+ public override System.Net.IWebProxy Proxy { get { throw null; } set { } }
+ public static new System.Net.Cache.RequestCachePolicy DefaultCachePolicy { get { throw null; } set { } }
+ public override bool PreAuthenticate { get { throw null; } set { } }
+ public override int Timeout { get { throw null; } set { } }
+ public override long ContentLength { get { throw null; } set { } }
+#pragma warning disable 0809 // Obsolete member overrides non-obsolete member
+ [ObsoleteAttribute("Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202")]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { throw null; }
+ [ObsoleteAttribute("Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202")]
+ protected override void GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { throw null; }
+#pragma warning restore 0809
}
- public partial class HttpWebResponse : System.Net.WebResponse
+ public partial class HttpWebResponse : System.Net.WebResponse, System.Runtime.Serialization.ISerializable
{
public HttpWebResponse() { }
+ [System.ObsoleteAttribute("Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202")]
+ protected HttpWebResponse(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { }
public override long ContentLength { get { throw null; } }
public override string ContentType { get { throw null; } }
public virtual System.Net.CookieCollection Cookies { get { throw null; } set { } }
@@ -205,6 +220,13 @@ namespace System.Net
public string CharacterSet { get { throw null; } }
public string Server { get { throw null; } }
public override void Close() { throw null; }
+ public override bool IsMutuallyAuthenticated { get { throw null; } }
+#pragma warning disable 0809 // Obsolete member overrides non-obsolete member
+ [ObsoleteAttribute("Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202")]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { throw null; }
+ [ObsoleteAttribute("Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202")]
+ protected override void GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { throw null; }
+#pragma warning restore 0809
}
public interface IAuthenticationModule
{
diff --git a/src/System.Net.Requests/src/FxCopBaseline.cs b/src/System.Net.Requests/src/FxCopBaseline.cs
new file mode 100644
index 0000000000..864b3c544d
--- /dev/null
+++ b/src/System.Net.Requests/src/FxCopBaseline.cs
@@ -0,0 +1,12 @@
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Design", "CA2237", Scope = "type", Target = "System.Net.FtpWebRequest")]
+[assembly: SuppressMessage("Microsoft.Design", "CA2237", Scope = "type", Target = "System.Net.FtpWebResponse")]
+
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Net.FileWebRequest.#CheckAndMarkAsyncGetRequestStreamPending()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Net.FileWebRequest.#CheckAndMarkAsyncGetResponsePending()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Net.FileWebRequest.#CreateResponse():System.Net.WebResponse")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Net.FileWebRequest.#UnblockReader()")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Net.CommandStream.#Abort(System.Exception)")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Net.CommandStream.#ContinueCommandPipeline():System.IO.Stream")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Net.FtpWebResponse.#get_Headers():System.Net.WebHeaderCollection")]
diff --git a/src/System.Net.Requests/src/System.Net.Requests.csproj b/src/System.Net.Requests/src/System.Net.Requests.csproj
index 36a43d42db..3900467521 100644
--- a/src/System.Net.Requests/src/System.Net.Requests.csproj
+++ b/src/System.Net.Requests/src/System.Net.Requests.csproj
@@ -17,6 +17,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <ItemGroup>
+ <Compile Include="FxCopBaseline.cs" />
+ </ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\Net\AuthenticationManager.cs" />
<Compile Include="System\Net\Authorization.cs" />
diff --git a/src/System.Net.Requests/src/System/Net/FtpDataStream.cs b/src/System.Net.Requests/src/System/Net/FtpDataStream.cs
index e814a5d426..c3eb704b33 100644
--- a/src/System.Net.Requests/src/System/Net/FtpDataStream.cs
+++ b/src/System.Net.Requests/src/System/Net/FtpDataStream.cs
@@ -56,6 +56,8 @@ namespace System.Net
}
}
+ //TODO: Add this to FxCopBaseline.cs once https://github.com/dotnet/roslyn/issues/15728 is fixed
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity")]
void ICloseEx.CloseEx(CloseExState closeState)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"state = {closeState}");
diff --git a/src/System.Net.Requests/src/System/Net/HttpWebRequest.cs b/src/System.Net.Requests/src/System/Net/HttpWebRequest.cs
index 09649c412c..3181fa95f5 100644
--- a/src/System.Net.Requests/src/System/Net/HttpWebRequest.cs
+++ b/src/System.Net.Requests/src/System/Net/HttpWebRequest.cs
@@ -49,6 +49,7 @@ namespace System.Net
private int _maximumAllowedRedirections = HttpHandlerDefaults.DefaultMaxAutomaticRedirections;
private int _maximumResponseHeaderLen = _defaultMaxResponseHeaderLength;
private ServicePoint _servicePoint;
+ private int _timeout = WebRequest.DefaultTimeoutMilliseconds;
private HttpContinueDelegate _continueDelegate;
private RequestStream _requestStream;
@@ -59,8 +60,9 @@ namespace System.Net
private int _abortCalled = 0;
private CancellationTokenSource _sendRequestCts;
private X509CertificateCollection _clientCertificates;
- private Booleans _Booleans = Booleans.Default;
+ private Booleans _booleans = Booleans.Default;
private bool _pipelined = true;
+ private bool _preAuthenticate;
private DecompressionMethods _automaticDecompression = HttpHandlerDefaults.DefaultAutomaticDecompression;
//these should be safe.
@@ -93,86 +95,17 @@ namespace System.Net
[Obsolete("Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202")]
protected HttpWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext)
{
-#if DEBUG
- using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) {
-#endif
- _webHeaderCollection = (WebHeaderCollection)serializationInfo.GetValue("_HttpRequestHeaders", typeof(WebHeaderCollection));
- Proxy = (IWebProxy)serializationInfo.GetValue("_Proxy", typeof(IWebProxy));
- KeepAlive = serializationInfo.GetBoolean("_KeepAlive");
- Pipelined = serializationInfo.GetBoolean("_Pipelined");
- AllowAutoRedirect = serializationInfo.GetBoolean("_AllowAutoRedirect");
- if (!serializationInfo.GetBoolean("_AllowWriteStreamBuffering"))
- {
- _Booleans &= ~Booleans.AllowWriteStreamBuffering;
- }
- _maximumAllowedRedirections = serializationInfo.GetInt32("_MaximumAllowedRedirections");
- AllowAutoRedirect = serializationInfo.GetInt32("_AutoRedirects") > 0;
- Timeout = serializationInfo.GetInt32("_Timeout");
-
- try
- {
- ReadWriteTimeout = serializationInfo.GetInt32("_ReadWriteTimeout");
- }
- catch
- { // default
- }
- try
- {
- MaximumResponseHeadersLength = serializationInfo.GetInt32("_MaximumResponseHeadersLength");
- }
- catch
- {
- // default
- }
- ContentLength = serializationInfo.GetInt64("_ContentLength");
- MediaType = serializationInfo.GetString("_MediaType");
- _originVerb = serializationInfo.GetString("_OriginVerb");
- ConnectionGroupName = serializationInfo.GetString("_ConnectionGroupName");
- ProtocolVersion = (Version)serializationInfo.GetValue("_Version", typeof(Version));
- _requestUri = (Uri)serializationInfo.GetValue("_OriginUri", typeof(Uri));
-#if DEBUG
- }
-#endif
+ throw new PlatformNotSupportedException();
}
-
void ISerializable.GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
{
-#if DEBUG
- using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) {
-#endif
- GetObjectData(serializationInfo, streamingContext);
-#if DEBUG
- }
-#endif
+ throw new PlatformNotSupportedException();
}
protected override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
{
-#if DEBUG
- using (DebugThreadTracking.SetThreadKind(ThreadKinds.User)) {
-#endif
- serializationInfo.AddValue("_HttpRequestHeaders", _webHeaderCollection, typeof(WebHeaderCollection));
- serializationInfo.AddValue("_Proxy", _proxy, typeof(IWebProxy));
- serializationInfo.AddValue("_KeepAlive", KeepAlive);
- serializationInfo.AddValue("_Pipelined", Pipelined);
- serializationInfo.AddValue("_AllowAutoRedirect", AllowAutoRedirect);
- serializationInfo.AddValue("_AllowWriteStreamBuffering", AllowWriteStreamBuffering);
- serializationInfo.AddValue("_MaximumAllowedRedirections", AllowAutoRedirect);
- serializationInfo.AddValue("_AutoRedirects", AllowAutoRedirect);
- serializationInfo.AddValue("_Timeout", Timeout);
- serializationInfo.AddValue("_ReadWriteTimeout", ReadWriteTimeout);
- serializationInfo.AddValue("_MaximumResponseHeadersLength", _defaultMaxResponseHeaderLength);
- serializationInfo.AddValue("_ContentLength", ContentLength);
- serializationInfo.AddValue("_MediaType", MediaType);
- serializationInfo.AddValue("_OriginVerb", _originVerb);
- serializationInfo.AddValue("_ConnectionGroupName", ConnectionGroupName);
- serializationInfo.AddValue("_Version", ProtocolVersion, typeof(Version));
- serializationInfo.AddValue("_OriginUri", Address, typeof(Uri));
- base.GetObjectData(serializationInfo, streamingContext);
-#if DEBUG
- }
-#endif
+ throw new PlatformNotSupportedException();
}
internal HttpWebRequest(Uri uri)
@@ -272,7 +205,46 @@ namespace System.Net
_continueTimeout = value;
}
}
-
+
+ public override int Timeout
+ {
+ get
+ {
+ return _timeout;
+ }
+ set
+ {
+ if (value < 0 && value != System.Threading.Timeout.Infinite)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), SR.net_io_timeout_use_ge_zero);
+ }
+
+ _timeout = value;
+ }
+ }
+
+ public override long ContentLength
+ {
+ get
+ {
+ long value;
+ long.TryParse(_webHeaderCollection[HttpKnownHeaderNames.ContentLength], out value);
+ return value;
+ }
+ set
+ {
+ if (RequestSubmitted)
+ {
+ throw new InvalidOperationException(SR.net_writestarted);
+ }
+ if (value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), SR.net_io_timeout_use_ge_zero);
+ }
+ SetSpecialHeaders(HttpKnownHeaderNames.ContentLength, value.ToString());
+ }
+ }
+
public Uri Address
{
get
@@ -432,17 +404,17 @@ namespace System.Net
{
get
{
- return (_Booleans & Booleans.UnsafeAuthenticatedConnectionSharing) != 0;
+ return (_booleans & Booleans.UnsafeAuthenticatedConnectionSharing) != 0;
}
set
{
if (value)
{
- _Booleans |= Booleans.UnsafeAuthenticatedConnectionSharing;
+ _booleans |= Booleans.UnsafeAuthenticatedConnectionSharing;
}
else
{
- _Booleans &= ~Booleans.UnsafeAuthenticatedConnectionSharing;
+ _booleans &= ~Booleans.UnsafeAuthenticatedConnectionSharing;
}
}
}
@@ -468,17 +440,17 @@ namespace System.Net
{
get
{
- return (_Booleans & Booleans.AllowWriteStreamBuffering) != 0;
+ return (_booleans & Booleans.AllowWriteStreamBuffering) != 0;
}
set
{
if (value)
{
- _Booleans |= Booleans.AllowWriteStreamBuffering;
+ _booleans |= Booleans.AllowWriteStreamBuffering;
}
else
{
- _Booleans &= ~Booleans.AllowWriteStreamBuffering;
+ _booleans &= ~Booleans.AllowWriteStreamBuffering;
}
}
}
@@ -492,17 +464,17 @@ namespace System.Net
{
get
{
- return (_Booleans & Booleans.AllowAutoRedirect) != 0;
+ return (_booleans & Booleans.AllowAutoRedirect) != 0;
}
set
{
if (value)
{
- _Booleans |= Booleans.AllowAutoRedirect;
+ _booleans |= Booleans.AllowAutoRedirect;
}
else
{
- _Booleans &= ~Booleans.AllowAutoRedirect;
+ _booleans &= ~Booleans.AllowAutoRedirect;
}
}
}
@@ -519,6 +491,18 @@ namespace System.Net
}
}
+ public override bool PreAuthenticate
+ {
+ get
+ {
+ return _preAuthenticate;
+ }
+ set
+ {
+ _preAuthenticate = value;
+ }
+ }
+
public string Connection
{
get
@@ -687,7 +671,7 @@ namespace System.Net
{
get
{
- return (_Booleans & Booleans.SendChunked) != 0;
+ return (_booleans & Booleans.SendChunked) != 0;
}
set
{
@@ -697,11 +681,11 @@ namespace System.Net
}
if (value)
{
- _Booleans |= Booleans.SendChunked;
+ _booleans |= Booleans.SendChunked;
}
else
{
- _Booleans &= ~Booleans.SendChunked;
+ _booleans &= ~Booleans.SendChunked;
}
}
}
@@ -978,17 +962,17 @@ namespace System.Net
{
get
{
- return (_Booleans & Booleans.IsVersionHttp10) != 0;
+ return (_booleans & Booleans.IsVersionHttp10) != 0;
}
set
{
if (value)
{
- _Booleans |= Booleans.IsVersionHttp10;
+ _booleans |= Booleans.IsVersionHttp10;
}
else
{
- _Booleans &= ~Booleans.IsVersionHttp10;
+ _booleans &= ~Booleans.IsVersionHttp10;
}
}
}
@@ -998,7 +982,7 @@ namespace System.Net
try
{
_sendRequestCts = new CancellationTokenSource();
- return SendRequest().Result;
+ return SendRequest().GetAwaiter().GetResult();
}
catch (Exception ex)
{
@@ -1131,12 +1115,16 @@ namespace System.Net
request.Content = new ByteArrayContent(bytes.Array, bytes.Offset, bytes.Count);
}
- // set up the various properties
handler.AutomaticDecompression = AutomaticDecompression;
handler.Credentials = _credentials;
handler.AllowAutoRedirect = AllowAutoRedirect;
handler.MaxAutomaticRedirections = MaximumAutomaticRedirections;
handler.MaxResponseHeadersLength = MaximumResponseHeadersLength;
+ handler.PreAuthenticate = PreAuthenticate;
+ client.Timeout = Timeout == Threading.Timeout.Infinite ?
+ Threading.Timeout.InfiniteTimeSpan :
+ TimeSpan.FromMilliseconds(Timeout);
+
if (_cookieContainer != null)
{
handler.CookieContainer = _cookieContainer;
@@ -1407,7 +1395,7 @@ namespace System.Net
}
}
- private readonly static string[] s_wellKnownContentHeaders = {
+ private static readonly string[] s_wellKnownContentHeaders = {
HttpKnownHeaderNames.ContentDisposition,
HttpKnownHeaderNames.ContentEncoding,
HttpKnownHeaderNames.ContentLanguage,
diff --git a/src/System.Net.Requests/src/System/Net/HttpWebResponse.cs b/src/System.Net.Requests/src/System/Net/HttpWebResponse.cs
index d3bca094ea..1e7be94bcb 100644
--- a/src/System.Net.Requests/src/System/Net/HttpWebResponse.cs
+++ b/src/System.Net.Requests/src/System/Net/HttpWebResponse.cs
@@ -34,31 +34,19 @@ namespace System.Net
[ObsoleteAttribute("Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202")]
protected HttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext)
{
- _webHeaderCollection = (WebHeaderCollection)serializationInfo.GetValue("_HttpResponseHeaders", typeof(WebHeaderCollection));
- _requestUri = (Uri)serializationInfo.GetValue("_Uri", typeof(Uri));
- Version version = (Version)serializationInfo.GetValue("_Version", typeof(Version));
- _isVersionHttp11 = version.Equals(HttpVersion.Version11);
- ContentLength = serializationInfo.GetInt64("_ContentLength");
+ throw new PlatformNotSupportedException();
}
void ISerializable.GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
{
- GetObjectData(serializationInfo, streamingContext);
+ throw new PlatformNotSupportedException();
}
protected override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
{
- serializationInfo.AddValue("_HttpResponseHeaders", _webHeaderCollection, typeof(WebHeaderCollection));
- serializationInfo.AddValue("_Uri", _requestUri, typeof(Uri));
- serializationInfo.AddValue("_Version", ProtocolVersion, typeof(Version));
- serializationInfo.AddValue("_StatusCode", StatusCode);
- serializationInfo.AddValue("_ContentLength", ContentLength);
- serializationInfo.AddValue("_Verb", Method);
- serializationInfo.AddValue("_StatusDescription", StatusDescription);
- base.GetObjectData(serializationInfo, streamingContext);
+ throw new PlatformNotSupportedException();
}
-
internal HttpWebResponse(HttpResponseMessage _message, Uri requestUri, CookieContainer cookieContainer)
{
_httpResponseMessage = _message;
diff --git a/src/System.Net.Requests/src/System/Net/WebException.cs b/src/System.Net.Requests/src/System/Net/WebException.cs
index a8b133863e..5b1e9b0d49 100644
--- a/src/System.Net.Requests/src/System/Net/WebException.cs
+++ b/src/System.Net.Requests/src/System/Net/WebException.cs
@@ -5,6 +5,7 @@
using System.Diagnostics;
using System.Net.Http;
using System.Runtime.Serialization;
+using System.Threading.Tasks;
namespace System.Net
{
@@ -96,6 +97,14 @@ namespace System.Net
GetStatusFromException(exception as HttpRequestException),
null);
}
+ else if (exception is TaskCanceledException)
+ {
+ return new WebException(
+ SR.net_webstatus_Timeout,
+ null,
+ WebExceptionStatus.Timeout,
+ null);
+ }
return exception;
}
diff --git a/src/System.Net.Requests/tests/HttpRequestResponseSerializationTest.cs b/src/System.Net.Requests/tests/HttpRequestResponseSerializationTest.cs
new file mode 100644
index 0000000000..58a19fa9d9
--- /dev/null
+++ b/src/System.Net.Requests/tests/HttpRequestResponseSerializationTest.cs
@@ -0,0 +1,47 @@
+// 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.Serialization.Formatters.Tests;
+using System.Net.Test.Common;
+using Xunit;
+
+namespace System.Net.HttpRequest.Tests
+{
+ using Configuration = System.Net.Test.Common.Configuration;
+
+ public partial class HttpRequestResponseSerializationTest
+ {
+ [ActiveIssue(14068)]
+ [OuterLoop]
+ [Fact]
+ public void SerializeDeserialize_Roundtrips()
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(Configuration.Http.RemoteEchoServer);
+ request.KeepAlive = true;
+ request.CookieContainer = new CookieContainer(10);
+
+ using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
+ using (HttpWebResponse responseClone = BinaryFormatterHelpers.Clone(response))
+ {
+ Assert.NotSame(responseClone, response);
+ Assert.Equal(response.CharacterSet, responseClone.CharacterSet);
+ Assert.Equal(response.ContentEncoding, responseClone.ContentEncoding);
+ Assert.Equal(response.ContentLength, responseClone.ContentLength);
+ Assert.Equal(response.ContentType, responseClone.ContentType);
+ Assert.Equal(response.Cookies.Count, responseClone.Cookies.Count);
+ Assert.Equal(response.Headers.Count, responseClone.Headers.Count);
+ Assert.Equal(response.IsFromCache, responseClone.IsFromCache);
+ Assert.Equal(response.IsMutuallyAuthenticated, responseClone.IsMutuallyAuthenticated);
+ Assert.Equal(response.LastModified, responseClone.LastModified);
+ Assert.Equal(response.Method, responseClone.Method);
+ Assert.Equal(response.ProtocolVersion, responseClone.ProtocolVersion);
+ Assert.Equal(response.ResponseUri, responseClone.ResponseUri);
+ Assert.Equal(response.Server, responseClone.Server);
+ Assert.Equal(response.StatusCode, responseClone.StatusCode);
+ Assert.Equal(response.StatusDescription, responseClone.StatusDescription);
+ Assert.Equal(response.SupportsHeaders, responseClone.SupportsHeaders);
+ }
+ }
+ }
+}
diff --git a/src/System.Net.Requests/tests/HttpWebRequestHeaderTest.cs b/src/System.Net.Requests/tests/HttpWebRequestHeaderTest.cs
index eceab2f26a..bb52e9ca91 100644
--- a/src/System.Net.Requests/tests/HttpWebRequestHeaderTest.cs
+++ b/src/System.Net.Requests/tests/HttpWebRequestHeaderTest.cs
@@ -2,7 +2,9 @@
// 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.Http;
+using System.Net.Sockets;
using System.Net.Test.Common;
using System.Threading.Tasks;
@@ -11,9 +13,11 @@ using Xunit.Abstractions;
namespace System.Net.Tests
{
+ using Configuration = System.Net.Test.Common.Configuration;
+
public class HttpWebRequestHeaderTest
{
- public readonly static object[][] EchoServers = System.Net.Test.Common.Configuration.Http.EchoServers;
+ public static readonly object[][] EchoServers = Configuration.Http.EchoServers;
[OuterLoop]
[Theory, MemberData(nameof(EchoServers))]
@@ -25,12 +29,12 @@ namespace System.Net.Tests
Assert.False(request.HaveResponse);
Assert.NotNull(HttpWebRequest.DefaultCachePolicy);
Assert.Null(request.CookieContainer);
- Assert.Equal(0,HttpWebRequest.DefaultMaximumErrorResponseLength);
- Assert.Equal(65536,HttpWebRequest.DefaultMaximumResponseHeadersLength);
+ Assert.Equal(0, HttpWebRequest.DefaultMaximumErrorResponseLength); // NetFX behavior difference (64 on NetFX).
+ Assert.Equal(65536, HttpWebRequest.DefaultMaximumResponseHeadersLength); // NetFX behavior difference (64 on NetFX).
Assert.Null(request.CookieContainer);
Assert.True(request.AllowWriteStreamBuffering);
Assert.NotNull(request.ClientCertificates);
- Assert.Throws<NotImplementedException>(() => request.ConnectionGroupName);
+ Assert.Throws<NotImplementedException>(() => request.ConnectionGroupName); //NetFX behavior difference.
}
[OuterLoop]
@@ -60,24 +64,20 @@ namespace System.Net.Tests
public void CookieContainer_Count_Add(Uri remoteServer)
{
HttpWebRequest request = WebRequest.CreateHttp(remoteServer);
- {
- DateTime now = DateTime.UtcNow;
- request.CookieContainer = new CookieContainer();
- request.CookieContainer.Add(remoteServer, new Cookie("1", "cookie1"));
- request.CookieContainer.Add(remoteServer, new Cookie("2", "cookie2"));
- Assert.True(request.SupportsCookieContainer);
- Assert.Equal(request.CookieContainer.GetCookies(remoteServer).Count, 2);
- }
+ DateTime now = DateTime.UtcNow;
+ request.CookieContainer = new CookieContainer();
+ request.CookieContainer.Add(remoteServer, new Cookie("1", "cookie1"));
+ request.CookieContainer.Add(remoteServer, new Cookie("2", "cookie2"));
+ Assert.True(request.SupportsCookieContainer);
+ Assert.Equal(request.CookieContainer.GetCookies(remoteServer).Count, 2);
}
[OuterLoop]
[Theory, MemberData(nameof(EchoServers))]
- public void ServicePoint_PNS_Expect(Uri remoteServer)
+ public void HttpWebRequest_ServicePoint_Throws(Uri remoteServer)
{
HttpWebRequest request = WebRequest.CreateHttp(remoteServer);
- {
- Assert.Throws<PlatformNotSupportedException>(() => request.ServicePoint);
- }
+ Assert.Throws<PlatformNotSupportedException>(() => request.ServicePoint); // NetFX Behavior difference.
}
[OuterLoop]
@@ -85,10 +85,8 @@ namespace System.Net.Tests
public void Range_Add_Success(Uri remoteServer)
{
HttpWebRequest request = WebRequest.CreateHttp(remoteServer);
- {
- request.AddRange(1, 5);
- Assert.Equal(request.Headers["Range"], "bytes=1-5");
- }
+ request.AddRange(1, 5);
+ Assert.Equal(request.Headers["Range"], "bytes=1-5");
}
[Theory, MemberData(nameof(EchoServers))]
@@ -97,9 +95,110 @@ namespace System.Net.Tests
System.Net.TransportContext context;
HttpWebRequest httpWebRequest = HttpWebRequest.CreateHttp(remoteServer);
httpWebRequest.Method = "POST";
+
using (httpWebRequest.EndGetRequestStream(httpWebRequest.BeginGetRequestStream(null, null), out context))
{
- Assert.Equal(null, context);
+ Assert.Equal(null, context); // NetFX behavior difference.
+ }
+ }
+
+ [Fact]
+ public void HttpWebRequest_ConnectionTryAddCloseKeepAlive_Fails()
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(Configuration.Http.RemoteEchoServer);
+ Assert.Throws<ArgumentException>(() => { request.Connection = "Close;keep-alive"; });
+ }
+
+ [Fact]
+ public void HttpWebRequest_DefaultCachePolicy_BypassCache()
+ {
+ Assert.Equal(Cache.RequestCacheLevel.BypassCache, HttpWebRequest.DefaultCachePolicy.Level);
+ }
+
+ [OuterLoop]
+ [Theory, MemberData(nameof(EchoServers))]
+ public void HttpWebRequest_ProxySetAfterGetResponse_Fails(Uri remoteServer)
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(remoteServer);
+ using (var response = (HttpWebResponse)request.GetResponse())
+ {
+ Assert.Throws<InvalidOperationException>(() => { request.Proxy = WebRequest.DefaultWebProxy; });
+ }
+ }
+
+ [Fact]
+ public void HttpWebRequest_TimeOutSetGet_Ok()
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(Configuration.Http.RemoteEchoServer);
+ request.Timeout = 100;
+ Assert.Equal(100, request.Timeout);
+
+ request.Timeout = Threading.Timeout.Infinite;
+ Assert.Equal(Threading.Timeout.Infinite, request.Timeout);
+
+ request.Timeout = int.MaxValue;
+ Assert.Equal(int.MaxValue, request.Timeout);
+ }
+
+ [Fact]
+ public void HttpWebRequest_TimeOutDefaultGet_Ok()
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(Configuration.Http.RemoteEchoServer);
+ Assert.Equal(100000, request.Timeout);
+ }
+
+ [Fact]
+ public void HttpWebRequest_TimeOutNegative_Throws()
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(Configuration.Http.RemoteEchoServer);
+ Assert.Throws<ArgumentOutOfRangeException>(() => { request.Timeout = -10; });
+ }
+
+ [Fact]
+ public void HttpWebRequest_Timeout_Throws()
+ {
+ using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
+ {
+ s.Bind(new IPEndPoint(IPAddress.Loopback, 0));
+ s.Listen(0);
+
+ IPEndPoint ep = (IPEndPoint)s.LocalEndPoint;
+ Uri uri = new Uri($"http://{ep.Address}:{ep.Port}");
+
+ HttpWebRequest request = WebRequest.CreateHttp(uri);
+ request.Timeout = 10; // ms.
+
+ var sw = Stopwatch.StartNew();
+ WebException exception = Assert.Throws<WebException>(() =>
+ {
+ var response = (HttpWebResponse)request.GetResponse();
+ });
+
+ sw.Stop();
+
+ Assert.InRange(sw.ElapsedMilliseconds, 1, 10 * 1000); // Allow a very wide range.
+ Assert.Equal(WebExceptionStatus.Timeout, exception.Status);
+ Assert.Equal(null, exception.InnerException);
+ Assert.Equal(null, exception.Response);
+ }
+ }
+
+ [Fact]
+ public void HttpWebRequest_ContentLengthSetGet_Ok()
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(Configuration.Http.RemoteEchoServer);
+ request.ContentLength = 100;
+ Assert.Equal(100, request.ContentLength);
+ }
+
+ [Fact]
+ public void HttpWebRequest_PreAuthenticateGetSet_Ok()
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(Configuration.Http.RemoteEchoServer);
+ request.PreAuthenticate = true;
+ using (var response = (HttpWebResponse)request.GetResponse())
+ {
+ Assert.True(request.PreAuthenticate);
}
}
}
diff --git a/src/System.Net.Requests/tests/HttpWebRequestTest.cs b/src/System.Net.Requests/tests/HttpWebRequestTest.cs
index 5fc2ba5a6c..8ad1e8f7bc 100644
--- a/src/System.Net.Requests/tests/HttpWebRequestTest.cs
+++ b/src/System.Net.Requests/tests/HttpWebRequestTest.cs
@@ -13,7 +13,7 @@ using Xunit.Abstractions;
namespace System.Net.Tests
{
- public class HttpWebRequestTest
+ public partial class HttpWebRequestTest
{
private const string RequestBody = "This is data to POST.";
private readonly byte[] _requestBodyBytes = Encoding.UTF8.GetBytes(RequestBody);
@@ -28,7 +28,7 @@ namespace System.Net.Tests
private int _responseCallbackCallCount = 0;
private readonly ITestOutputHelper _output;
- public readonly static object[][] EchoServers = System.Net.Test.Common.Configuration.Http.EchoServers;
+ public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.Http.EchoServers;
public HttpWebRequestTest(ITestOutputHelper output)
{
diff --git a/src/System.Net.Requests/tests/HttpWebRequestTest.netstandard1.7.cs b/src/System.Net.Requests/tests/HttpWebRequestTest.netstandard1.7.cs
new file mode 100644
index 0000000000..ee5de8e398
--- /dev/null
+++ b/src/System.Net.Requests/tests/HttpWebRequestTest.netstandard1.7.cs
@@ -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.IO;
+using System.Net.Http;
+using System.Runtime.Serialization.Formatters.Binary;
+
+using Xunit;
+using Xunit.Abstractions;
+
+namespace System.Net.Tests
+{
+ public partial class HttpWebRequestTest
+ {
+ [Fact]
+ public void HttpWebRequest_Serialize_Fails()
+ {
+ using (MemoryStream fs = new MemoryStream())
+ {
+ BinaryFormatter formatter = new BinaryFormatter();
+ var hwr = HttpWebRequest.CreateHttp("http://localhost");
+
+ Assert.Throws<PlatformNotSupportedException>(() => formatter.Serialize(fs, hwr));
+ }
+ }
+ }
+}
diff --git a/src/System.Net.Requests/tests/HttpWebResponseHeaderTest.cs b/src/System.Net.Requests/tests/HttpWebResponseHeaderTest.cs
index 2e25a1878f..d8475b61c3 100644
--- a/src/System.Net.Requests/tests/HttpWebResponseHeaderTest.cs
+++ b/src/System.Net.Requests/tests/HttpWebResponseHeaderTest.cs
@@ -2,9 +2,11 @@
// 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.IO;
using System.Net.Http;
using System.Net.Test.Common;
using System.Threading.Tasks;
+using System.Runtime.Serialization.Formatters.Binary;
using Xunit;
using Xunit.Abstractions;
@@ -100,5 +102,28 @@ namespace System.Net.Tests
});
}
+ [Fact]
+ public async Task HttpWebResponse_Serialize_Fails()
+ {
+ await LoopbackServer.CreateServerAsync(async (server, url) =>
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(url);
+ request.Method = HttpMethod.Get.Method;
+ Task<WebResponse> getResponse = request.GetResponseAsync();
+ await LoopbackServer.ReadRequestAndSendResponseAsync(server, "HTTP/1.1 200 OK\r\n");
+
+ using (WebResponse response = await getResponse)
+ {
+ HttpWebResponse httpResponse = (HttpWebResponse)response;
+ using (MemoryStream fs = new MemoryStream())
+ {
+ BinaryFormatter formatter = new BinaryFormatter();
+ HttpWebResponse hwr = (HttpWebResponse)response;
+
+ Assert.Throws<PlatformNotSupportedException>(() => formatter.Serialize(fs, hwr));
+ }
+ }
+ });
+ }
}
}
diff --git a/src/System.Net.Requests/tests/System.Net.Requests.Tests.csproj b/src/System.Net.Requests/tests/System.Net.Requests.Tests.csproj
index 224fc2fc88..6baae18160 100644
--- a/src/System.Net.Requests/tests/System.Net.Requests.Tests.csproj
+++ b/src/System.Net.Requests/tests/System.Net.Requests.Tests.csproj
@@ -48,7 +48,12 @@
<Compile Include="LoggingTest.cs" />
<Compile Include="HttpRequestCachePolicyTest.cs" />
<Compile Include="HttpWebRequestHeaderTest.cs" />
+ <Compile Include="HttpWebRequestTest.netstandard1.7.cs" />
<Compile Include="HttpWebResponseHeaderTest.cs" />
+ <Compile Include="HttpRequestResponseSerializationTest.cs" />
+ <Compile Include="$(CommonTestPath)\System\Runtime\Serialization\Formatters\BinaryFormatterHelpers.cs">
+ <Link>Common\System\Runtime\Serialization\Formatters\BinaryFormatterHelpers.cs</Link>
+ </Compile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Net.Security/ref/System.Net.Security.cs b/src/System.Net.Security/ref/System.Net.Security.cs
index 846fb94150..17891ac318 100644
--- a/src/System.Net.Security/ref/System.Net.Security.cs
+++ b/src/System.Net.Security/ref/System.Net.Security.cs
@@ -75,11 +75,15 @@ namespace System.Net.Security
public virtual IAsyncResult BeginAuthenticateAsServer(System.Net.NetworkCredential credential, System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy policy, System.Net.Security.ProtectionLevel requiredProtectionLevel, System.Security.Principal.TokenImpersonationLevel requiredImpersonationLevel, System.AsyncCallback asyncCallback, object asyncState) { throw null; }
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { throw null; }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { throw null; }
+ protected override void Dispose(bool disposing) { }
public virtual void EndAuthenticateAsClient(System.IAsyncResult asyncResult) { }
public virtual void EndAuthenticateAsServer(System.IAsyncResult asyncResult) { }
public override int EndRead(IAsyncResult asyncResult) { throw null; }
public override void EndWrite(IAsyncResult asyncResult) { }
public override void Flush() { }
+#if netcoreapp11
+ public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
public override int Read(byte[] buffer, int offset, int count) { throw null; }
public override long Seek(long offset, System.IO.SeekOrigin origin) { throw null; }
public override void SetLength(long value) { }
@@ -155,11 +159,15 @@ namespace System.Net.Security
#endif
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { throw null; }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState) { throw null; }
+ protected override void Dispose(bool disposing) { }
public virtual void EndAuthenticateAsClient(IAsyncResult asyncResult) { }
public virtual void EndAuthenticateAsServer(IAsyncResult asyncResult) { }
public override int EndRead(IAsyncResult asyncResult) { throw null; }
public override void EndWrite(IAsyncResult asyncResult) { }
public override void Flush() { }
+#if netcoreapp11
+ public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
public override int Read(byte[] buffer, int offset, int count) { throw null; }
public override long Seek(long offset, System.IO.SeekOrigin origin) { throw null; }
public override void SetLength(long value) { }
diff --git a/src/System.Net.Security/src/System.Net.Security.csproj b/src/System.Net.Security/src/System.Net.Security.csproj
index c009067e4f..a85d8b495e 100644
--- a/src/System.Net.Security/src/System.Net.Security.csproj
+++ b/src/System.Net.Security/src/System.Net.Security.csproj
@@ -116,8 +116,8 @@
<Compile Include="$(CommonPath)\System\Net\NegotiationInfoClass.cs">
<Link>Common\System\Net\NegotiationInfoClass.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Net\NTAuthentication.cs">
- <Link>Common\System\Net\NTAuthentication.cs</Link>
+ <Compile Include="$(CommonPath)\System\Net\NTAuthentication.Common.cs">
+ <Link>Common\System\Net\NTAuthentication.Common.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Net\SecurityStatusPal.cs">
<Link>Common\System\Net\SecurityStatusPal.cs</Link>
diff --git a/src/System.Net.Security/src/System/Net/FixedSizeReader.cs b/src/System.Net.Security/src/System/Net/FixedSizeReader.cs
index c4eb5cb05f..d1ffb829b6 100644
--- a/src/System.Net.Security/src/System/Net/FixedSizeReader.cs
+++ b/src/System.Net.Security/src/System/Net/FixedSizeReader.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.IO;
+using System.Threading.Tasks;
namespace System.Net
{
@@ -70,17 +71,26 @@ namespace System.Net
{
while (true)
{
- IAsyncResult ar = _transport.BeginRead(_request.Buffer, _request.Offset + _totalRead, _request.Count - _totalRead, s_readCallback, this);
- if (!ar.CompletedSynchronously)
+ int bytes;
+
+ Task<int> t = _transport.ReadAsync(_request.Buffer, _request.Offset + _totalRead, _request.Count - _totalRead);
+ if (t.IsCompleted)
+ {
+ bytes = t.GetAwaiter().GetResult();
+ }
+ else
{
+ IAsyncResult ar = TaskToApm.Begin(t, s_readCallback, this);
+ if (!ar.CompletedSynchronously)
+ {
#if DEBUG
- _request._DebugAsyncChain = ar;
+ _request._DebugAsyncChain = ar;
#endif
- break;
+ break;
+ }
+ bytes = TaskToApm.End<int>(ar);
}
- int bytes = _transport.EndRead(ar);
-
if (CheckCompletionBeforeNextRead(bytes))
{
break;
@@ -135,7 +145,7 @@ namespace System.Net
// Async completion.
try
{
- int bytes = reader._transport.EndRead(transportResult);
+ int bytes = TaskToApm.End<int>(transportResult);
if (reader.CheckCompletionBeforeNextRead(bytes))
{
diff --git a/src/System.Net.Security/src/System/Net/NTAuthentication.cs b/src/System.Net.Security/src/System/Net/NTAuthentication.cs
index 30204460fc..95bdaf374f 100644
--- a/src/System.Net.Security/src/System/Net/NTAuthentication.cs
+++ b/src/System.Net.Security/src/System/Net/NTAuthentication.cs
@@ -14,10 +14,7 @@ namespace System.Net
{
internal partial class NTAuthentication
{
- static private ContextCallback s_InitializeCallback = new ContextCallback(InitializeCallback);
- private string _clientSpecifiedSpn;
- private string _protocolName;
- private string _lastProtocolName;
+ private static ContextCallback s_InitializeCallback = new ContextCallback(InitializeCallback);
internal string AssociatedName
{
@@ -82,43 +79,6 @@ namespace System.Net
}
}
- internal string ClientSpecifiedSpn
- {
- get
- {
- if (_clientSpecifiedSpn == null)
- {
- _clientSpecifiedSpn = GetClientSpecifiedSpn();
- }
-
- return _clientSpecifiedSpn;
- }
- }
-
- //
- // True indicates this instance is for Server and will use AcceptSecurityContext SSPI API.
- //
- internal bool IsServer
- {
- get
- {
- return _isServer;
- }
- }
-
- internal bool IsKerberos
- {
- get
- {
- if (_lastProtocolName == null)
- {
- _lastProtocolName = ProtocolName;
- }
-
- return (object)_lastProtocolName == (object)NegotiationInfoClass.Kerberos;
- }
- }
-
internal bool IsNTLM
{
get
@@ -132,30 +92,6 @@ namespace System.Net
}
}
- internal string ProtocolName
- {
- get
- {
- // Note: May return string.Empty if the auth is not done yet or failed.
- if (_protocolName == null)
- {
- string negotiationAuthenticationPackage = null;
-
- if (IsValidContext)
- {
- negotiationAuthenticationPackage = NegotiateStreamPal.QueryContextAuthenticationPackage(_securityContext);
- if (IsCompleted)
- {
- _protocolName = negotiationAuthenticationPackage;
- }
- }
- return negotiationAuthenticationPackage ?? string.Empty;
- }
-
- return _protocolName;
- }
- }
-
private class InitializeCallbackContext
{
internal InitializeCallbackContext(NTAuthentication thisPtr, bool isServer, string package, NetworkCredential credential, string spn, ContextFlagsPal requestedContextFlags, ChannelBinding channelBinding)
@@ -184,28 +120,6 @@ namespace System.Net
context.ThisPtr.Initialize(context.IsServer, context.Package, context.Credential, context.Spn, context.RequestedContextFlags, context.ChannelBinding);
}
- internal SafeDeleteContext GetContext(out SecurityStatusPal status)
- {
- status = new SecurityStatusPal(SecurityStatusPalErrorCode.OK);
- if (!(IsCompleted && IsValidContext))
- {
- NetEventSource.Fail(this, "Should be called only when completed with success, currently is not!");
- }
-
- if (!IsServer)
- {
- NetEventSource.Fail(this, "The method must not be called by the client side!");
- }
-
- if (!IsValidContext)
- {
- status = new SecurityStatusPal(SecurityStatusPalErrorCode.InvalidHandle);
- return null;
- }
-
- return _securityContext;
- }
-
internal int Encrypt(byte[] buffer, int offset, int count, ref byte[] output, uint sequenceNumber)
{
return NegotiateStreamPal.Encrypt(
@@ -223,19 +137,5 @@ namespace System.Net
{
return NegotiateStreamPal.Decrypt(_securityContext, payload, offset, count, IsConfidentialityFlag, IsNTLM, out newOffset, expectedSeqNumber);
}
-
- private string GetClientSpecifiedSpn()
- {
- if (!(IsValidContext && IsCompleted))
- {
- NetEventSource.Fail(this, "Trying to get the client SPN before handshaking is done!");
- }
-
- string spn = NegotiateStreamPal.QueryContextClientSpecifiedSpn(_securityContext);
-
- if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"The client specified SPN is [{spn}]");
-
- return spn;
- }
}
}
diff --git a/src/System.Net.Security/src/System/Net/Security/InternalNegotiateStream.cs b/src/System.Net.Security/src/System/Net/Security/InternalNegotiateStream.cs
index c57008bb9c..b23fc4e27c 100644
--- a/src/System.Net.Security/src/System/Net/Security/InternalNegotiateStream.cs
+++ b/src/System.Net.Security/src/System/Net/Security/InternalNegotiateStream.cs
@@ -5,6 +5,7 @@
using System.Diagnostics;
using System.IO;
using System.Threading;
+using System.Threading.Tasks;
namespace System.Net.Security
{
@@ -167,13 +168,20 @@ namespace System.Net.Security
{
// prepare for the next request
asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, null);
- IAsyncResult ar = InnerStream.BeginWrite(outBuffer, 0, encryptedBytes, s_writeCallback, asyncRequest);
- if (!ar.CompletedSynchronously)
+ Task t = InnerStream.WriteAsync(outBuffer, 0, encryptedBytes);
+ if (t.IsCompleted)
{
- return;
+ t.GetAwaiter().GetResult();
+ }
+ else
+ {
+ IAsyncResult ar = TaskToApm.Begin(t, s_writeCallback, asyncRequest);
+ if (!ar.CompletedSynchronously)
+ {
+ return;
+ }
+ TaskToApm.End(ar);
}
-
- InnerStream.EndWrite(ar);
}
else
{
@@ -384,7 +392,7 @@ namespace System.Net.Security
try
{
NegotiateStream negoStream = (NegotiateStream)asyncRequest.AsyncObject;
- negoStream.InnerStream.EndWrite(transportResult);
+ TaskToApm.End(transportResult);
if (asyncRequest.Count == 0)
{
// This was the last chunk.
diff --git a/src/System.Net.Security/src/System/Net/Security/NegotiateStream.cs b/src/System.Net.Security/src/System/Net/Security/NegotiateStream.cs
index fff772ee9f..e07a61c578 100644
--- a/src/System.Net.Security/src/System/Net/Security/NegotiateStream.cs
+++ b/src/System.Net.Security/src/System/Net/Security/NegotiateStream.cs
@@ -502,6 +502,11 @@ namespace System.Net.Security
#endif
}
+ public override Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return InnerStream.FlushAsync(cancellationToken);
+ }
+
protected override void Dispose(bool disposing)
{
#if DEBUG
@@ -570,7 +575,7 @@ namespace System.Net.Security
if (!_negoState.CanGetSecureStream)
{
- return InnerStream.BeginRead(buffer, offset, count, asyncCallback, asyncState);
+ return TaskToApm.Begin(InnerStream.ReadAsync(buffer, offset, count), asyncCallback, asyncState);
}
BufferAsyncResult bufferResult = new BufferAsyncResult(this, buffer, offset, count, asyncState, asyncCallback);
@@ -592,7 +597,7 @@ namespace System.Net.Security
if (!_negoState.CanGetSecureStream)
{
- return InnerStream.EndRead(asyncResult);
+ return TaskToApm.End<int>(asyncResult);
}
@@ -642,7 +647,7 @@ namespace System.Net.Security
if (!_negoState.CanGetSecureStream)
{
- return InnerStream.BeginWrite(buffer, offset, count, asyncCallback, asyncState);
+ return TaskToApm.Begin(InnerStream.WriteAsync(buffer, offset, count), asyncCallback, asyncState);
}
BufferAsyncResult bufferResult = new BufferAsyncResult(this, buffer, offset, count, asyncState, asyncCallback);
@@ -665,7 +670,7 @@ namespace System.Net.Security
if (!_negoState.CanGetSecureStream)
{
- InnerStream.EndWrite(asyncResult);
+ TaskToApm.End(asyncResult);
return;
}
@@ -701,67 +706,5 @@ namespace System.Net.Security
}
#endif
}
-
- // ReadAsync - provide async read functionality.
- //
- // This method provides async read functionality. All we do is
- // call through to the Begin/EndRead methods.
- //
- // Input:
- //
- // buffer - Buffer to read into.
- // offset - Offset into the buffer where we're to read.
- // size - Number of bytes to read.
- // cancellationToken - Token used to request cancellation of the operation
- //
- // Returns:
- //
- // A Task<int> representing the read.
- public override Task<int> ReadAsync(byte[] buffer, int offset, int size, CancellationToken cancellationToken)
- {
- if (cancellationToken.IsCancellationRequested)
- {
- return Task.FromCanceled<int>(cancellationToken);
- }
-
- return Task.Factory.FromAsync(
- (bufferArg, offsetArg, sizeArg, callback, state) => ((NegotiateStream)state).BeginRead(bufferArg, offsetArg, sizeArg, callback, state),
- iar => ((NegotiateStream)iar.AsyncState).EndRead(iar),
- buffer,
- offset,
- size,
- this);
- }
-
- // WriteAsync - provide async write functionality.
- //
- // This method provides async write functionality. All we do is
- // call through to the Begin/EndWrite methods.
- //
- // Input:
- //
- // buffer - Buffer to write into.
- // offset - Offset into the buffer where we're to write.
- // size - Number of bytes to write.
- // cancellationToken - Token used to request cancellation of the operation
- //
- // Returns:
- //
- // A Task representing the write.
- public override Task WriteAsync(byte[] buffer, int offset, int size, CancellationToken cancellationToken)
- {
- if (cancellationToken.IsCancellationRequested)
- {
- return Task.FromCanceled<int>(cancellationToken);
- }
-
- return Task.Factory.FromAsync(
- (bufferArg, offsetArg, sizeArg, callback, state) => ((NegotiateStream)state).BeginWrite(bufferArg, offsetArg, sizeArg, callback, state),
- iar => ((NegotiateStream)iar.AsyncState).EndWrite(iar),
- buffer,
- offset,
- size,
- this);
- }
}
}
diff --git a/src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Unix.cs b/src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Unix.cs
index 0493a83d89..1232bfc057 100644
--- a/src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Unix.cs
+++ b/src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Unix.cs
@@ -37,17 +37,6 @@ namespace System.Net.Security
{
throw new PlatformNotSupportedException(SR.net_nego_server_not_supported);
}
-
- internal static string QueryContextAuthenticationPackage(SafeDeleteContext securityContext)
- {
- SafeDeleteNegoContext negoContext = (SafeDeleteNegoContext)securityContext;
- return negoContext.IsNtlmUsed ? NegotiationInfoClass.NTLM : NegotiationInfoClass.Kerberos;
- }
-
- internal static string QueryContextClientSpecifiedSpn(SafeDeleteContext securityContext)
- {
- throw new PlatformNotSupportedException(SR.net_nego_server_not_supported);
- }
internal static void ValidateImpersonationLevel(TokenImpersonationLevel impersonationLevel)
{
diff --git a/src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Windows.cs b/src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Windows.cs
index 82e051005c..ef489290b1 100644
--- a/src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Windows.cs
+++ b/src/System.Net.Security/src/System/Net/Security/NegotiateStreamPal.Windows.cs
@@ -80,17 +80,6 @@ namespace System.Net.Security
{
return SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NAMES) as string;
}
-
- internal static string QueryContextAuthenticationPackage(SafeDeleteContext securityContext)
- {
- var negotiationInfoClass = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NEGOTIATION_INFO) as NegotiationInfoClass;
- return negotiationInfoClass?.AuthenticationPackage;
- }
-
- internal static string QueryContextClientSpecifiedSpn(SafeDeleteContext securityContext)
- {
- return SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CLIENT_SPECIFIED_TARGET) as string;
- }
internal static void ValidateImpersonationLevel(TokenImpersonationLevel impersonationLevel)
{
diff --git a/src/System.Net.Security/src/System/Net/Security/SslState.cs b/src/System.Net.Security/src/System/Net/Security/SslState.cs
index 5b13a730f7..cdc7f2f2ba 100644
--- a/src/System.Net.Security/src/System/Net/Security/SslState.cs
+++ b/src/System.Net.Security/src/System/Net/Security/SslState.cs
@@ -11,6 +11,7 @@ using System.Security.Authentication;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
+using System.Threading.Tasks;
namespace System.Net.Security
{
@@ -477,6 +478,11 @@ namespace System.Net.Security
InnerStream.Flush();
}
+ internal Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return InnerStream.FlushAsync(cancellationToken);
+ }
+
//
// This is to not depend on GC&SafeHandle class if the context is not needed anymore.
//
@@ -784,16 +790,23 @@ namespace System.Net.Security
else
{
asyncRequest.AsyncState = message;
- IAsyncResult ar = InnerStream.BeginWrite(message.Payload, 0, message.Size, s_writeCallback, asyncRequest);
- if (!ar.CompletedSynchronously)
+ Task t = InnerStream.WriteAsync(message.Payload, 0, message.Size);
+ if (t.IsCompleted)
{
+ t.GetAwaiter().GetResult();
+ }
+ else
+ {
+ IAsyncResult ar = TaskToApm.Begin(t, s_writeCallback, asyncRequest);
+ if (!ar.CompletedSynchronously)
+ {
#if DEBUG
- asyncRequest._DebugAsyncChain = ar;
+ asyncRequest._DebugAsyncChain = ar;
#endif
- return;
+ return;
+ }
+ TaskToApm.End(ar);
}
-
- InnerStream.EndWrite(ar);
}
}
@@ -990,12 +1003,20 @@ namespace System.Net.Security
else
{
asyncRequest.AsyncState = exception;
- IAsyncResult ar = InnerStream.BeginWrite(message.Payload, 0, message.Size, s_writeCallback, asyncRequest);
- if (!ar.CompletedSynchronously)
+ Task t = InnerStream.WriteAsync(message.Payload, 0, message.Size);
+ if (t.IsCompleted)
{
- return;
+ t.GetAwaiter().GetResult();
+ }
+ else
+ {
+ IAsyncResult ar = TaskToApm.Begin(t, s_writeCallback, asyncRequest);
+ if (!ar.CompletedSynchronously)
+ {
+ return;
+ }
+ TaskToApm.End(ar);
}
- InnerStream.EndWrite(ar);
}
exception.Throw();
@@ -1059,7 +1080,7 @@ namespace System.Net.Security
// Async completion.
try
{
- sslState.InnerStream.EndWrite(transportResult);
+ TaskToApm.End(transportResult);
// Special case for an error notification.
object asyncState = asyncRequest.AsyncState;
@@ -1827,14 +1848,14 @@ namespace System.Net.Security
CheckThrow(authSuccessCheck:true, shutdownCheck:true);
ProtocolToken message = Context.CreateShutdownToken();
- return InnerStream.BeginWrite(message.Payload, 0, message.Payload.Length, asyncCallback, asyncState);
+ return TaskToApm.Begin(InnerStream.WriteAsync(message.Payload, 0, message.Payload.Length), asyncCallback, asyncState);
}
internal void EndShutdown(IAsyncResult result)
{
CheckThrow(authSuccessCheck: true, shutdownCheck:true);
- InnerStream.EndWrite(result);
+ TaskToApm.End(result);
_shutdown = true;
}
}
diff --git a/src/System.Net.Security/src/System/Net/Security/SslStream.cs b/src/System.Net.Security/src/System/Net/Security/SslStream.cs
index 00e24f9490..0f55e769b8 100644
--- a/src/System.Net.Security/src/System/Net/Security/SslStream.cs
+++ b/src/System.Net.Security/src/System/Net/Security/SslStream.cs
@@ -490,6 +490,11 @@ namespace System.Net.Security
_sslState.Flush();
}
+ public override Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return _sslState.FlushAsync(cancellationToken);
+ }
+
protected override void Dispose(bool disposing)
{
try
diff --git a/src/System.Net.Security/src/System/Net/Security/SslStreamInternal.cs b/src/System.Net.Security/src/System/Net/Security/SslStreamInternal.cs
index a0fe031f78..6e459ec398 100644
--- a/src/System.Net.Security/src/System/Net/Security/SslStreamInternal.cs
+++ b/src/System.Net.Security/src/System/Net/Security/SslStreamInternal.cs
@@ -5,6 +5,7 @@
using System.Diagnostics;
using System.IO;
using System.Threading;
+using System.Threading.Tasks;
namespace System.Net.Security
{
@@ -454,14 +455,20 @@ namespace System.Net.Security
{
// Prepare for the next request.
asyncRequest.SetNextRequest(buffer, offset + chunkBytes, count - chunkBytes, s_resumeAsyncWriteCallback);
- IAsyncResult ar = _sslState.InnerStream.BeginWrite(outBuffer, 0, encryptedBytes, s_writeCallback, asyncRequest);
- if (!ar.CompletedSynchronously)
+ Task t = _sslState.InnerStream.WriteAsync(outBuffer, 0, encryptedBytes);
+ if (t.IsCompleted)
{
- return;
+ t.GetAwaiter().GetResult();
+ }
+ else
+ {
+ IAsyncResult ar = TaskToApm.Begin(t, s_writeCallback, asyncRequest);
+ if (!ar.CompletedSynchronously)
+ {
+ return;
+ }
+ TaskToApm.End(ar);
}
-
- _sslState.InnerStream.EndWrite(ar);
-
}
else
{
@@ -767,7 +774,7 @@ namespace System.Net.Security
try
{
- sslStream._sslState.InnerStream.EndWrite(transportResult);
+ TaskToApm.End(transportResult);
sslStream._sslState.FinishWrite();
if (asyncRequest.Count == 0)
diff --git a/src/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs b/src/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs
index 198fd270da..0015de2e03 100644
--- a/src/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs
+++ b/src/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs
@@ -290,7 +290,7 @@ namespace System.Net.Security
return SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(errorCode, attachException:true);
}
- public unsafe static SafeFreeContextBufferChannelBinding QueryContextChannelBinding(SafeDeleteContext securityContext, ChannelBindingKind attribute)
+ public static unsafe SafeFreeContextBufferChannelBinding QueryContextChannelBinding(SafeDeleteContext securityContext, ChannelBindingKind attribute)
{
return SSPIWrapper.QueryContextChannelBinding(GlobalSSPI.SSPISecureChannel, securityContext, (Interop.SspiCli.ContextAttribute)attribute);
}
diff --git a/src/System.Net.Security/src/System/Net/StreamFramer.cs b/src/System.Net.Security/src/System/Net/StreamFramer.cs
index 3aac3ef885..8123c48235 100644
--- a/src/System.Net.Security/src/System/Net/StreamFramer.cs
+++ b/src/System.Net.Security/src/System/Net/StreamFramer.cs
@@ -5,6 +5,7 @@
using System.Diagnostics;
using System.IO;
using System.Globalization;
+using System.Threading.Tasks;
namespace System.Net
{
@@ -136,7 +137,7 @@ namespace System.Net
_readHeaderBuffer, 0,
_readHeaderBuffer.Length);
- IAsyncResult result = _transport.BeginRead(_readHeaderBuffer, 0, _readHeaderBuffer.Length,
+ IAsyncResult result = TaskToApm.Begin(_transport.ReadAsync(_readHeaderBuffer, 0, _readHeaderBuffer.Length),
_readFrameCallback, workerResult);
if (result.CompletedSynchronously)
@@ -199,7 +200,7 @@ namespace System.Net
WorkerAsyncResult workerResult = (WorkerAsyncResult)transportResult.AsyncState;
- int bytesRead = _transport.EndRead(transportResult);
+ int bytesRead = TaskToApm.End<int>(transportResult);
workerResult.Offset += bytesRead;
if (!(workerResult.Offset <= workerResult.End))
@@ -260,7 +261,7 @@ namespace System.Net
workerResult.End = frame.Length;
workerResult.Offset = 0;
- // Transport.BeginRead below will pickup those changes.
+ // Transport.ReadAsync below will pickup those changes.
}
else
{
@@ -271,7 +272,7 @@ namespace System.Net
}
// This means we need more data to complete the data block.
- transportResult = _transport.BeginRead(workerResult.Buffer, workerResult.Offset, workerResult.End - workerResult.Offset,
+ transportResult = TaskToApm.Begin(_transport.ReadAsync(workerResult.Buffer, workerResult.Offset, workerResult.End - workerResult.Offset),
_readFrameCallback, workerResult);
} while (transportResult.CompletedSynchronously);
}
@@ -352,7 +353,7 @@ namespace System.Net
if (message.Length == 0)
{
- return _transport.BeginWrite(_writeHeaderBuffer, 0, _writeHeaderBuffer.Length,
+ return TaskToApm.Begin(_transport.WriteAsync(_writeHeaderBuffer, 0, _writeHeaderBuffer.Length),
asyncCallback, stateObject);
}
@@ -361,7 +362,7 @@ namespace System.Net
message, 0, message.Length);
// Charge the first:
- IAsyncResult result = _transport.BeginWrite(_writeHeaderBuffer, 0, _writeHeaderBuffer.Length,
+ IAsyncResult result = TaskToApm.Begin(_transport.WriteAsync(_writeHeaderBuffer, 0, _writeHeaderBuffer.Length),
_beginWriteCallback, workerResult);
if (result.CompletedSynchronously)
@@ -412,7 +413,7 @@ namespace System.Net
WorkerAsyncResult workerResult = (WorkerAsyncResult)transportResult.AsyncState;
// First, complete the previous portion write.
- _transport.EndWrite(transportResult);
+ TaskToApm.End(transportResult);
// Check on exit criterion.
if (workerResult.Offset == workerResult.End)
@@ -425,7 +426,7 @@ namespace System.Net
workerResult.Offset = workerResult.End;
// Write next portion (frame body) using Async IO.
- transportResult = _transport.BeginWrite(workerResult.Buffer, 0, workerResult.End,
+ transportResult = TaskToApm.Begin(_transport.WriteAsync(workerResult.Buffer, 0, workerResult.End),
_beginWriteCallback, workerResult);
}
while (transportResult.CompletedSynchronously);
@@ -454,7 +455,7 @@ namespace System.Net
}
else
{
- _transport.EndWrite(asyncResult);
+ TaskToApm.End(asyncResult);
}
}
}
diff --git a/src/System.Net.Security/src/System/PinnableBufferCache.cs b/src/System.Net.Security/src/System/PinnableBufferCache.cs
index 92d3af3f66..7e58893350 100644
--- a/src/System.Net.Security/src/System/PinnableBufferCache.cs
+++ b/src/System.Net.Security/src/System/PinnableBufferCache.cs
@@ -561,7 +561,7 @@ namespace System
public void WalkFreeListResult(string cacheName, int freeListCount, int gen0BuffersInFreeList) { if (IsEnabled()) WriteEvent(21, cacheName, freeListCount, gen0BuffersInFreeList); }
- static internal ulong AddressOf(object obj)
+ internal static ulong AddressOf(object obj)
{
var asByteArray = obj as byte[];
if (asByteArray != null)
@@ -573,7 +573,7 @@ namespace System
}
[System.Security.SecuritySafeCritical]
- static internal unsafe long AddressOfByteArray(byte[] array)
+ internal static unsafe long AddressOfByteArray(byte[] array)
{
if (array == null)
{
diff --git a/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs b/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs
index 3477f90c4d..be31a9948b 100644
--- a/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs
+++ b/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamKerberosTest.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net.Test.Common;
+using System.Security;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
@@ -30,17 +31,33 @@ namespace System.Net.Security.Tests
Configuration.Security.ActiveDirectoryUserName,
Configuration.Security.ActiveDirectoryUserPassword,
Configuration.Security.ActiveDirectoryName) };
+
+ yield return new object[] { new NetworkCredential(
+ Configuration.Security.ActiveDirectoryUserName,
+ AsSecureString(Configuration.Security.ActiveDirectoryUserPassword),
+ Configuration.Security.ActiveDirectoryName) };
+
// Anonymous (with domain name).
yield return new object[] { new NetworkCredential(
Configuration.Security.ActiveDirectoryUserName,
- null,
+ (string)null,
+ Configuration.Security.ActiveDirectoryName) };
+
+ yield return new object[] { new NetworkCredential(
+ Configuration.Security.ActiveDirectoryUserName,
+ (SecureString)null,
Configuration.Security.ActiveDirectoryName) };
// Anonymous (without domain).
yield return new object[] { new NetworkCredential(
Configuration.Security.ActiveDirectoryUserName,
- null,
+ (string)null,
+ null) };
+
+ yield return new object[] { new NetworkCredential(
+ Configuration.Security.ActiveDirectoryUserName,
+ (SecureString)null,
null) };
}
}
@@ -49,15 +66,25 @@ namespace System.Net.Security.Tests
{
get
{
- yield return new object[] { new NetworkCredential(null, null, Configuration.Security.ActiveDirectoryName) };
- yield return new object[] { new NetworkCredential(null, null, null) };
+ yield return new object[] { new NetworkCredential(null, (string)null, Configuration.Security.ActiveDirectoryName) };
+ yield return new object[] { new NetworkCredential(null, (SecureString)null, Configuration.Security.ActiveDirectoryName) };
+
+ yield return new object[] { new NetworkCredential(null, (string)null, null) };
+ yield return new object[] { new NetworkCredential(null, (SecureString)null, null) };
+
yield return new object[] { new NetworkCredential(
"baduser",
- null,
+ (string)null,
Configuration.Security.ActiveDirectoryName) };
+
+ yield return new object[] { new NetworkCredential(
+ "baduser",
+ (SecureString)null,
+ Configuration.Security.ActiveDirectoryName) };
+
yield return new object[] { new NetworkCredential(
"baduser",
- "badpassword",
+ AsSecureString("badpassword"),
Configuration.Security.ActiveDirectoryName) };
}
}
@@ -142,5 +169,22 @@ namespace System.Net.Security.Tests
return isLocalHost + isLoopback > 0;
}
+
+ private static SecureString AsSecureString(string str)
+ {
+ SecureString secureString = new SecureString();
+
+ if (string.IsNullOrEmpty(str))
+ {
+ return secureString;
+ }
+
+ foreach (char ch in str)
+ {
+ secureString.AppendChar(ch);
+ }
+
+ return secureString;
+ }
}
}
diff --git a/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamStreamToStreamTest.cs b/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamStreamToStreamTest.cs
index 27b8abda7f..bba718ebc8 100644
--- a/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamStreamToStreamTest.cs
+++ b/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamStreamToStreamTest.cs
@@ -260,6 +260,39 @@ namespace System.Net.Security.Tests
Assert.True(_sampleMsg.SequenceEqual(recvBuf));
}
}
+
+
+ [OuterLoop] // TODO: Issue #11345
+ [Fact]
+ public void NegotiateStream_StreamToStream_Flush_Propagated()
+ {
+ VirtualNetwork network = new VirtualNetwork();
+
+ using (var stream = new VirtualNetworkStream(network, isServer: false))
+ using (var negotiateStream = new NegotiateStream(stream))
+ {
+ Assert.False(stream.HasBeenSyncFlushed);
+ negotiateStream.Flush();
+ Assert.True(stream.HasBeenSyncFlushed);
+ }
+ }
+
+ [OuterLoop] // TODO: Issue #11345
+ [Fact]
+ public void NegotiateStream_StreamToStream_FlushAsync_Propagated()
+ {
+ VirtualNetwork network = new VirtualNetwork();
+
+ using (var stream = new VirtualNetworkStream(network, isServer: false))
+ using (var negotiateStream = new NegotiateStream(stream))
+ {
+ Task task = negotiateStream.FlushAsync();
+
+ Assert.False(task.IsCompleted);
+ stream.CompleteAsyncFlush();
+ Assert.True(task.IsCompleted);
+ }
+ }
}
public sealed class NegotiateStreamStreamToStreamTest_Async : NegotiateStreamStreamToStreamTest
diff --git a/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamTestForUnix.cs b/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamTestForUnix.cs
index 32fd209442..912fe1abc9 100644
--- a/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamTestForUnix.cs
+++ b/src/System.Net.Security/tests/FunctionalTests/NegotiateStreamTestForUnix.cs
@@ -129,7 +129,7 @@ namespace System.Net.Security.Tests
private readonly ITestOutputHelper _output;
private readonly string _emptyTarget = string.Empty;
private readonly string _testTarget = "TestTarget";
- private readonly static string _ntlmPassword = TestConfiguration.NtlmPassword;
+ private static readonly string _ntlmPassword = TestConfiguration.NtlmPassword;
private void AssertClientPropertiesForTarget(NegotiateStream client, string target)
{
diff --git a/src/System.Net.Security/tests/FunctionalTests/NotifyReadVirtualNetworkStream.cs b/src/System.Net.Security/tests/FunctionalTests/NotifyReadVirtualNetworkStream.cs
new file mode 100644
index 0000000000..66a088cbba
--- /dev/null
+++ b/src/System.Net.Security/tests/FunctionalTests/NotifyReadVirtualNetworkStream.cs
@@ -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.
+
+using System.Net.Test.Common;
+
+namespace System.Net.Security.Tests
+{
+ internal class NotifyReadVirtualNetworkStream : VirtualNetworkStream
+ {
+ public delegate void ReadEventHandler(byte[] buffer, int offset, int count);
+ public event ReadEventHandler OnRead;
+
+ public NotifyReadVirtualNetworkStream(VirtualNetwork network, bool isServer)
+ : base(network, isServer)
+ {
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ OnRead?.Invoke(buffer, offset, count);
+ return base.Read(buffer, offset, count);
+ }
+ }
+}
diff --git a/src/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs b/src/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs
index b30d94ae39..48ac3f41c0 100644
--- a/src/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs
+++ b/src/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs
@@ -258,6 +258,107 @@ namespace System.Net.Security.Tests
}
}
+ [OuterLoop] // TODO: Issue #11345
+ [Fact]
+ public async Task SslStream_StreamToStream_WriteAsync_ReadByte_Success()
+ {
+ VirtualNetwork network = new VirtualNetwork();
+
+ using (var clientStream = new VirtualNetworkStream(network, isServer: false))
+ using (var serverStream = new VirtualNetworkStream(network, isServer: true))
+ using (var clientSslStream = new SslStream(clientStream, false, AllowAnyServerCertificate))
+ using (var serverSslStream = new SslStream(serverStream))
+ {
+ bool result = DoHandshake(clientSslStream, serverSslStream);
+ Assert.True(result, "Handshake completed.");
+
+ for (int i = 0; i < 3; i++)
+ {
+ await clientSslStream.WriteAsync(_sampleMsg, 0, _sampleMsg.Length).ConfigureAwait(false);
+ foreach (byte b in _sampleMsg)
+ {
+ Assert.Equal(b, serverSslStream.ReadByte());
+ }
+ }
+ }
+ }
+
+ [OuterLoop] // TODO: Issue #11345
+ [Fact]
+ public async Task SslStream_StreamToStream_WriteAsync_ReadAsync_Pending_Success()
+ {
+ VirtualNetwork network = new VirtualNetwork();
+
+ using (var clientStream = new VirtualNetworkStream(network, isServer: false))
+ using (var serverStream = new NotifyReadVirtualNetworkStream(network, isServer: true))
+ using (var clientSslStream = new SslStream(clientStream, false, AllowAnyServerCertificate))
+ using (var serverSslStream = new SslStream(serverStream))
+ {
+ bool result = DoHandshake(clientSslStream, serverSslStream);
+ Assert.True(result, "Handshake completed.");
+
+ var serverBuffer = new byte[1];
+ var tcs = new TaskCompletionSource<object>();
+ serverStream.OnRead += (buffer, offset, count) =>
+ {
+ tcs.TrySetResult(null);
+ };
+ Task readTask = serverSslStream.ReadAsync(serverBuffer, 0, serverBuffer.Length);
+
+ // Since the sequence of calls that ends in serverStream.Read() is sync, by now
+ // the read task will have acquired the semaphore shared by Stream.BeginReadInternal()
+ // and Stream.BeginWriteInternal().
+ // But to be sure, we wait until we know we're inside Read().
+ await tcs.Task.TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds);
+
+ // Should not hang
+ await serverSslStream.WriteAsync(new byte[] { 1 }, 0, 1)
+ .TimeoutAfter(TestConfiguration.PassingTestTimeoutMilliseconds);
+
+ // Read in client
+ var clientBuffer = new byte[1];
+ await clientSslStream.ReadAsync(clientBuffer, 0, clientBuffer.Length);
+ Assert.Equal(1, clientBuffer[0]);
+
+ // Complete server read task
+ await clientSslStream.WriteAsync(new byte[] { 2 }, 0, 1);
+ await readTask;
+ Assert.Equal(2, serverBuffer[0]);
+ }
+ }
+
+ [OuterLoop] // TODO: Issue #11345
+ [Fact]
+ public void SslStream_StreamToStream_Flush_Propagated()
+ {
+ VirtualNetwork network = new VirtualNetwork();
+
+ using (var stream = new VirtualNetworkStream(network, isServer: false))
+ using (var sslStream = new SslStream(stream, false, AllowAnyServerCertificate))
+ {
+ Assert.False(stream.HasBeenSyncFlushed);
+ sslStream.Flush();
+ Assert.True(stream.HasBeenSyncFlushed);
+ }
+ }
+
+ [OuterLoop] // TODO: Issue #11345
+ [Fact]
+ public void SslStream_StreamToStream_FlushAsync_Propagated()
+ {
+ VirtualNetwork network = new VirtualNetwork();
+
+ using (var stream = new VirtualNetworkStream(network, isServer: false))
+ using (var sslStream = new SslStream(stream, false, AllowAnyServerCertificate))
+ {
+ Task task = sslStream.FlushAsync();
+
+ Assert.False(task.IsCompleted);
+ stream.CompleteAsyncFlush();
+ Assert.True(task.IsCompleted);
+ }
+ }
+
private bool VerifyOutput(byte[] actualBuffer, byte[] expectedBuffer)
{
return expectedBuffer.SequenceEqual(actualBuffer);
diff --git a/src/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj
index bcd60f1787..0faf4cfb2e 100644
--- a/src/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj
+++ b/src/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj
@@ -15,6 +15,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Windows_Debug|AnyCPU' " />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU' " />
<ItemGroup>
+ <Compile Include="NotifyReadVirtualNetworkStream.cs" />
<Compile Include="DummyTcpServer.cs" />
<Compile Include="TestConfiguration.cs" />
<!-- SslStream Tests -->
diff --git a/src/System.Net.Security/tests/UnitTests/Fakes/FakeSslState.cs b/src/System.Net.Security/tests/UnitTests/Fakes/FakeSslState.cs
index 9a72c84bca..34f1310cb6 100644
--- a/src/System.Net.Security/tests/UnitTests/Fakes/FakeSslState.cs
+++ b/src/System.Net.Security/tests/UnitTests/Fakes/FakeSslState.cs
@@ -6,6 +6,8 @@ using System.IO;
using System.Security.Authentication;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Cryptography.X509Certificates;
+using System.Threading;
+using System.Threading.Tasks;
namespace System.Net.Security
{
@@ -155,6 +157,11 @@ namespace System.Net.Security
{
}
+ internal Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+
//
// This is to not depend on GC&SafeHandle class if the context is not needed anymore.
//
@@ -237,6 +244,11 @@ namespace System.Net.Security
throw new NotImplementedException();
}
+ public override Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return Task.FromException(new NotImplementedException());
+ }
+
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
@@ -257,6 +269,11 @@ namespace System.Net.Security
throw new NotImplementedException();
}
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
{
throw new NotImplementedException();
diff --git a/src/System.Net.ServicePoint/pkg/System.Net.ServicePoint.pkgproj b/src/System.Net.ServicePoint/pkg/System.Net.ServicePoint.pkgproj
index fff1c7e234..7f72c06e93 100644
--- a/src/System.Net.ServicePoint/pkg/System.Net.ServicePoint.pkgproj
+++ b/src/System.Net.ServicePoint/pkg/System.Net.ServicePoint.pkgproj
@@ -4,7 +4,7 @@
<ItemGroup>
<ProjectReference Include="..\ref\System.Net.ServicePoint.builds">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Net.ServicePoint.builds" />
</ItemGroup>
diff --git a/src/System.Net.ServicePoint/src/Configurations.props b/src/System.Net.ServicePoint/src/Configurations.props
index 9c336c0be9..53b62c64fe 100644
--- a/src/System.Net.ServicePoint/src/Configurations.props
+++ b/src/System.Net.ServicePoint/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Net.ServicePoint/src/System.Net.ServicePoint.csproj b/src/System.Net.ServicePoint/src/System.Net.ServicePoint.csproj
index 6e489da3b5..c8d8564161 100644
--- a/src/System.Net.ServicePoint/src/System.Net.ServicePoint.csproj
+++ b/src/System.Net.ServicePoint/src/System.Net.ServicePoint.csproj
@@ -4,20 +4,20 @@
<PropertyGroup>
<ProjectGuid>{53D09AF4-0C13-4197-B8AD-9746F0374E88}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net463'">true</IsPartialFacadeAssembly>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net461'">true</IsPartialFacadeAssembly>
</PropertyGroup>
<!-- Default configurations to help VS understand the options -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\Net\BindIPEndPoint.cs" />
<Compile Include="System\Net\ServicePoint.cs" />
<Compile Include="System\Net\ServicePointManager.cs" />
<Compile Include="System\Net\SecurityProtocolType.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="System" />
</ItemGroup>
<ItemGroup>
diff --git a/src/System.Net.Sockets/ref/System.Net.Sockets.cs b/src/System.Net.Sockets/ref/System.Net.Sockets.cs
index 05792e316b..033dc1765b 100644
--- a/src/System.Net.Sockets/ref/System.Net.Sockets.cs
+++ b/src/System.Net.Sockets/ref/System.Net.Sockets.cs
@@ -254,6 +254,8 @@ namespace System.Net.Sockets
public IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state) { throw null; }
public IAsyncResult BeginSend(Collections.Generic.IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state) { throw null; }
public IAsyncResult BeginSend(Collections.Generic.IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state) { throw null; }
+ public IAsyncResult BeginSendFile(string fileName, AsyncCallback callback, object state) { throw null; }
+ public IAsyncResult BeginSendFile(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state) { throw null; }
public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP, AsyncCallback callback, object state) { throw null; }
public void Bind(System.Net.EndPoint localEP) { }
public static void CancelConnectAsync(System.Net.Sockets.SocketAsyncEventArgs e) { }
@@ -272,6 +274,8 @@ namespace System.Net.Sockets
public bool DisconnectAsync(SocketAsyncEventArgs e) { throw null; }
public SocketInformation DuplicateAndClose(int targetProcessId) { throw null; }
public Socket EndAccept(IAsyncResult asyncResult) { throw null; }
+ public Socket EndAccept(out byte[] buffer, IAsyncResult asyncResult) { throw null; }
+ public Socket EndAccept(out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult) { throw null; }
public void EndConnect(IAsyncResult asyncResult) { }
public void EndDisconnect(IAsyncResult asyncResult) { }
public int EndReceive(IAsyncResult asyncResult) { throw null; }
@@ -280,6 +284,7 @@ namespace System.Net.Sockets
public int EndReceiveMessageFrom(IAsyncResult asyncResult, ref SocketFlags socketFlags, ref EndPoint endPoint, out IPPacketInformation ipPacketInformation) { throw null; }
public int EndSend(IAsyncResult asyncResult) { throw null; }
public int EndSend(IAsyncResult asyncResult, out SocketError errorCode) { throw null; }
+ public void EndSendFile(IAsyncResult asyncResult) { }
public int EndSendTo(IAsyncResult asyncResult) { throw null; }
public object GetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName) { throw null; }
public void GetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, byte[] optionValue) { }
@@ -315,6 +320,8 @@ namespace System.Net.Sockets
public int Send(System.Collections.Generic.IList<System.ArraySegment<byte>> buffers, System.Net.Sockets.SocketFlags socketFlags, out System.Net.Sockets.SocketError errorCode) { throw null; }
public bool SendAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; }
public bool SendPacketsAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; }
+ public void SendFile(string fileName) { }
+ public void SendFile(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags) { }
public int SendTo(byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) { throw null; }
public int SendTo(byte[] buffer, int size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) { throw null; }
public int SendTo(byte[] buffer, System.Net.EndPoint remoteEP) { throw null; }
@@ -326,6 +333,7 @@ namespace System.Net.Sockets
public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, int optionValue) { }
public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, object optionValue) { }
public void Shutdown(System.Net.Sockets.SocketShutdown how) { }
+
}
public partial class SocketAsyncEventArgs : System.EventArgs, System.IDisposable
{
@@ -343,6 +351,7 @@ namespace System.Net.Sockets
public System.Net.Sockets.IPPacketInformation ReceiveMessageFromPacketInfo { get { throw null; } }
public System.Net.EndPoint RemoteEndPoint { get { throw null; } set { } }
public System.Net.Sockets.SendPacketsElement[] SendPacketsElements { get { throw null; } set { } }
+ public System.Net.Sockets.TransmitFileOptions SendPacketsFlags { get { throw null; } set { } }
public int SendPacketsSendSize { get { throw null; } set { } }
public System.Net.Sockets.SocketError SocketError { get { throw null; } set { } }
public System.Net.Sockets.SocketFlags SocketFlags { get { throw null; } set { } }
@@ -380,6 +389,7 @@ namespace System.Net.Sockets
Peek = 2,
Truncated = 256,
}
+  [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct SocketInformation
{
public SocketInformationOptions Options { get { throw null; } set { } }
diff --git a/src/System.Net.Sockets/src/Resources/Strings.resx b/src/System.Net.Sockets/src/Resources/Strings.resx
index fb4340e0f0..76d0fc0de6 100644
--- a/src/System.Net.Sockets/src/Resources/Strings.resx
+++ b/src/System.Net.Sockets/src/Resources/Strings.resx
@@ -291,6 +291,9 @@
<data name="net_sockets_disconnect_notsupported" xml:space="preserve">
<value>This platform does not support disconnecting a Socket. Instead, close the Socket and create a new one.</value>
</data>
+ <data name="net_sockets_transmitfileoptions_notsupported" xml:space="preserve">
+ <value>This platform does not support TransmitFileOptions other than TransmitFileOptions.UseDefaultWorkerThread.</value>
+ </data>
<data name="NotSupported_UnreadableStream" xml:space="preserve">
<value>Stream does not support reading.</value>
</data>
diff --git a/src/System.Net.Sockets/src/System.Net.Sockets.csproj b/src/System.Net.Sockets/src/System.Net.Sockets.csproj
index ae033ab897..935e6816ed 100644
--- a/src/System.Net.Sockets/src/System.Net.Sockets.csproj
+++ b/src/System.Net.Sockets/src/System.Net.Sockets.csproj
@@ -160,6 +160,7 @@
<Compile Include="System\Net\Sockets\SocketAsyncEventArgs.Windows.cs" />
<Compile Include="System\Net\Sockets\SocketPal.Windows.cs" />
<Compile Include="System\Net\Sockets\TCPClient.Windows.cs" />
+ <Compile Include="System\Net\Sockets\TransmitFileAsyncResult.Windows.cs" />
<Compile Condition="'$(TargetGroup)' != 'netcore50'" Include="System\Net\Sockets\TCPClient.Windows.netstandard17.cs" />
<Compile Include="$(CommonPath)\System\Net\SafeCloseSocket.Windows.cs">
<Link>Common\System\Net\SafeCloseSocket.Windows.cs</Link>
@@ -219,6 +220,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\Winsock\Interop.shutdown.cs">
<Link>Interop\Windows\Winsock\Interop.shutdown.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\Winsock\Interop.TransmitFile.cs">
+ <Link>Interop\Windows\Winsock\Interop.TransmitFile.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\Winsock\Interop.WinsockBSD.cs">
<Link>Interop\Windows\Winsock\Interop.WinsockBSD.cs</Link>
</Compile>
@@ -369,6 +373,9 @@
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.LingerOption.cs">
<Link>Interop\Unix\System.Native\Interop.LingerOption.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.SendFile.cs">
+ <Link>Interop\Unix\System.Native\Interop.SendFile.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.SetSendTimeout.cs">
<Link>Interop\Unix\System.Native\Interop.SetSendTimeout.cs</Link>
</Compile>
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/AcceptOverlappedAsyncResult.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/AcceptOverlappedAsyncResult.Windows.cs
index 9921fd5de5..e65fe81315 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/AcceptOverlappedAsyncResult.Windows.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/AcceptOverlappedAsyncResult.Windows.cs
@@ -62,7 +62,7 @@ namespace System.Net.Sockets
if (errorCode == SocketError.SocketError)
{
- errorCode = (SocketError)Marshal.GetLastWin32Error();
+ errorCode = SocketPal.GetLastSocketError();
}
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"setsockopt handle:{handle}, AcceptSocket:{_acceptSocket}, returns:{errorCode}");
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Windows.cs
index ad44d26620..9718acccd5 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Windows.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Windows.cs
@@ -21,7 +21,7 @@ namespace System.Net.Sockets
private SafeNativeOverlapped _nativeOverlapped;
// The WinNT Completion Port callback.
- private unsafe static readonly IOCompletionCallback s_ioCallback = new IOCompletionCallback(CompletionPortCallback);
+ private static unsafe readonly IOCompletionCallback s_ioCallback = new IOCompletionCallback(CompletionPortCallback);
internal BaseOverlappedAsyncResult(Socket socket, Object asyncState, AsyncCallback asyncCallback)
: base(socket, asyncState, asyncCallback)
@@ -69,7 +69,7 @@ namespace System.Net.Sockets
}
}
- private unsafe static void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
+ private static unsafe void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
{
#if DEBUG
DebugThreadTracking.SetThreadSource(ThreadKinds.CompletionPort);
@@ -111,7 +111,7 @@ namespace System.Net.Sockets
try
{
// The async IO completed with a failure.
- // Here we need to call WSAGetOverlappedResult() just so Marshal.GetLastWin32Error() will return the correct error.
+ // Here we need to call WSAGetOverlappedResult() just so GetLastSocketError() will return the correct error.
SocketFlags ignore;
bool success = Interop.Winsock.WSAGetOverlappedResult(
socket.SafeHandle,
@@ -121,11 +121,7 @@ namespace System.Net.Sockets
out ignore);
if (!success)
{
- socketError = (SocketError)Marshal.GetLastWin32Error();
- if (socketError == 0)
- {
- NetEventSource.Fail(asyncResult, $"socketError:0 numBytes:{numBytes}");
- }
+ socketError = SocketPal.GetLastSocketError();
}
if (success)
{
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/ConnectOverlappedAsyncResult.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/ConnectOverlappedAsyncResult.Windows.cs
index 38f6909c6c..bd30aca4c0 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/ConnectOverlappedAsyncResult.Windows.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/ConnectOverlappedAsyncResult.Windows.cs
@@ -32,7 +32,7 @@ namespace System.Net.Sockets
0);
if (errorCode == SocketError.SocketError)
{
- errorCode = (SocketError)Marshal.GetLastWin32Error();
+ errorCode = SocketPal.GetLastSocketError();
}
}
catch (ObjectDisposedException)
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/DynamicWinsockMethods.cs b/src/System.Net.Sockets/src/System/Net/Sockets/DynamicWinsockMethods.cs
index afb49b1812..6d18e46aaa 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/DynamicWinsockMethods.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/DynamicWinsockMethods.cs
@@ -324,5 +324,5 @@ namespace System.Net.Sockets
int elementCount,
int sendSize,
SafeNativeOverlapped overlapped,
- int flags);
+ TransmitFileOptions flags);
}
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Unix.cs b/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Unix.cs
index 6af19ad1fc..45f44b9f1f 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Unix.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Unix.cs
@@ -6,7 +6,7 @@ using System.Diagnostics;
namespace System.Net.Sockets
{
- unsafe internal sealed partial class ReceiveMessageOverlappedAsyncResult : BaseOverlappedAsyncResult
+ internal unsafe sealed partial class ReceiveMessageOverlappedAsyncResult : BaseOverlappedAsyncResult
{
private int _socketAddressSize;
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Windows.cs
index 321b07e8d1..eb6fb632d7 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Windows.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.Windows.cs
@@ -12,7 +12,7 @@ using System.Collections.Generic;
namespace System.Net.Sockets
{
- unsafe internal sealed partial class ReceiveMessageOverlappedAsyncResult : BaseOverlappedAsyncResult
+ internal unsafe sealed partial class ReceiveMessageOverlappedAsyncResult : BaseOverlappedAsyncResult
{
private Interop.Winsock.WSAMsg* _message;
private WSABuffer* _wsaBuffer;
@@ -99,7 +99,7 @@ namespace System.Net.Sockets
_message->flags = socketFlags;
}
- unsafe private void InitIPPacketInformation()
+ private unsafe void InitIPPacketInformation()
{
IPAddress address = null;
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.cs b/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.cs
index 11d95ade05..8a5298f96c 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/ReceiveMessageOverlappedAsyncResult.cs
@@ -11,7 +11,7 @@ using System.Collections.Generic;
namespace System.Net.Sockets
{
- unsafe internal sealed partial class ReceiveMessageOverlappedAsyncResult : BaseOverlappedAsyncResult
+ internal unsafe sealed partial class ReceiveMessageOverlappedAsyncResult : BaseOverlappedAsyncResult
{
private Internals.SocketAddress _socketAddressOriginal;
private Internals.SocketAddress _socketAddress;
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Unix.cs b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Unix.cs
index 00d710657c..2f79139854 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Unix.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Unix.cs
@@ -2,6 +2,10 @@
// 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.IO;
+using System.Threading.Tasks;
+
namespace System.Net.Sockets
{
public partial class Socket
@@ -17,5 +21,128 @@ namespace System.Net.Sockets
handle = null;
return null;
}
+
+ private static void CheckTransmitFileOptions(TransmitFileOptions flags)
+ {
+ // Note, UseDefaultWorkerThread is the default and is == 0.
+ // Unfortunately there is no TransmitFileOptions.None.
+ if (flags != TransmitFileOptions.UseDefaultWorkerThread)
+ {
+ throw new PlatformNotSupportedException(SR.net_sockets_transmitfileoptions_notsupported);
+ }
+ }
+
+ private void SendFileInternal(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
+ {
+ CheckTransmitFileOptions(flags);
+
+ // Open the file, if any
+ // Open it before we send the preBuffer so that any exception happens first
+ FileStream fileStream = OpenFile(fileName);
+
+ SocketError errorCode = SocketError.Success;
+ using (fileStream)
+ {
+ // Send the preBuffer, if any
+ // This will throw on error
+ if (preBuffer != null && preBuffer.Length > 0)
+ {
+ Send(preBuffer);
+ }
+
+ // Send the file, if any
+ if (fileStream != null)
+ {
+ // This can throw ObjectDisposedException.
+ errorCode = SocketPal.SendFile(_handle, fileStream);
+ }
+ }
+
+ if (errorCode != SocketError.Success)
+ {
+ SocketException socketException = new SocketException((int)errorCode);
+ UpdateStatusAfterSocketError(socketException);
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, socketException);
+ throw socketException;
+ }
+
+ // Send the postBuffer, if any
+ // This will throw on error
+ if (postBuffer != null && postBuffer.Length > 0)
+ {
+ Send(postBuffer);
+ }
+ }
+
+ private async Task SendFileInternalAsync(FileStream fileStream, byte[] preBuffer, byte[] postBuffer)
+ {
+ SocketError errorCode = SocketError.Success;
+ using (fileStream)
+ {
+ // Send the preBuffer, if any
+ // This will throw on error
+ if (preBuffer != null && preBuffer.Length > 0)
+ {
+ // Using "this." makes the extension method kick in
+ await this.SendAsync(new ArraySegment<byte>(preBuffer), SocketFlags.None).ConfigureAwait(false);
+ }
+
+ // Send the file, if any
+ if (fileStream != null)
+ {
+ var tcs = new TaskCompletionSource<bool>();
+
+ // This can throw ObjectDisposedException.
+ errorCode = SocketPal.SendFileAsync(_handle, fileStream, (bytesTransferred, socketError) =>
+ {
+ if (socketError != SocketError.Success)
+ {
+ // Synchronous exception from SendFileAsync
+ SocketException socketException = new SocketException((int)errorCode);
+ UpdateStatusAfterSocketError(socketException);
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, socketException);
+ tcs.SetException(socketException);
+ }
+
+ tcs.SetResult(true);
+ });
+
+ await tcs.Task.ConfigureAwait(false);
+ }
+ }
+
+ if (errorCode != SocketError.Success)
+ {
+ // Synchronous exception from SendFileAsync
+ SocketException socketException = new SocketException((int)errorCode);
+ UpdateStatusAfterSocketError(socketException);
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, socketException);
+ throw socketException;
+ }
+
+ // Send the postBuffer, if any
+ // This will throw on error
+ if (postBuffer != null && postBuffer.Length > 0)
+ {
+ // Using "this." makes the extension method kick in
+ await this.SendAsync(new ArraySegment<byte>(postBuffer), SocketFlags.None).ConfigureAwait(false);
+ }
+ }
+
+ private IAsyncResult BeginSendFileInternal(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
+ {
+ CheckTransmitFileOptions(flags);
+
+ // Open the file, if any
+ // Open it before we send the preBuffer so that any exception happens first
+ FileStream fileStream = OpenFile(fileName);
+
+ return TaskToApm.Begin(SendFileInternalAsync(fileStream, preBuffer, postBuffer), callback, state);
+ }
+
+ private void EndSendFileInternal(IAsyncResult asyncResult)
+ {
+ TaskToApm.End(asyncResult);
+ }
}
}
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs
index 0e7baa7f79..015c0b8b3a 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs
@@ -2,16 +2,10 @@
// 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 Microsoft.Win32.SafeHandles;
using System.Collections;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Globalization;
using System.IO;
-using System.Net;
using System.Runtime.InteropServices;
-using System.Threading.Tasks;
-using System.Threading;
namespace System.Net.Sockets
{
@@ -117,13 +111,12 @@ namespace System.Net.Sockets
return recvMsg_Blocking(socketHandle, msg, out bytesTransferred, overlapped, completionRoutine);
}
- internal bool TransmitPackets(SafeCloseSocket socketHandle, IntPtr packetArray, int elementCount, int sendSize, SafeNativeOverlapped overlapped)
+ internal bool TransmitPackets(SafeCloseSocket socketHandle, IntPtr packetArray, int elementCount, int sendSize, SafeNativeOverlapped overlapped, TransmitFileOptions flags)
{
EnsureDynamicWinsockMethods();
TransmitPacketsDelegate transmitPackets = _dynamicWinsockMethods.GetDelegate<TransmitPacketsDelegate>(socketHandle);
- // UseDefaultWorkerThread = 0.
- return transmitPackets(socketHandle, packetArray, elementCount, sendSize, overlapped, 0);
+ return transmitPackets(socketHandle, packetArray, elementCount, sendSize, overlapped, flags);
}
internal static IntPtr[] SocketListToFileDescriptorSet(IList socketList)
@@ -211,5 +204,93 @@ namespace System.Net.Sockets
handle = acceptSocket._handle;
return acceptSocket;
}
+
+ private void SendFileInternal(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
+ {
+ // Open the file, if any
+ FileStream fileStream = OpenFile(fileName);
+
+ SocketError errorCode;
+ using (fileStream)
+ {
+ SafeFileHandle fileHandle = fileStream?.SafeFileHandle;
+
+ // This can throw ObjectDisposedException.
+ errorCode = SocketPal.SendFile(_handle, fileHandle, preBuffer, postBuffer, flags);
+ }
+
+ if (errorCode != SocketError.Success)
+ {
+ SocketException socketException = new SocketException((int)errorCode);
+ UpdateStatusAfterSocketError(socketException);
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, socketException);
+ throw socketException;
+ }
+
+ // If the user passed the Disconnect and/or ReuseSocket flags, then TransmitFile disconnected the socket.
+ // Update our state to reflect this.
+ if ((flags & (TransmitFileOptions.Disconnect | TransmitFileOptions.ReuseSocket)) != 0)
+ {
+ SetToDisconnected();
+ _remoteEndPoint = null;
+ }
+ }
+
+ private IAsyncResult BeginSendFileInternal(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
+ {
+ FileStream fileStream = OpenFile(fileName);
+
+ TransmitFileAsyncResult asyncResult = new TransmitFileAsyncResult(this, state, callback);
+ asyncResult.StartPostingAsyncOp(false);
+
+ SocketError errorCode = SocketPal.SendFileAsync(_handle, fileStream, preBuffer, postBuffer, flags, asyncResult);
+
+ // Check for synchronous exception
+ if (errorCode != SocketError.Success)
+ {
+ SocketException socketException = new SocketException((int)errorCode);
+ UpdateStatusAfterSocketError(socketException);
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, socketException);
+ throw socketException;
+ }
+
+ asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
+
+ return asyncResult;
+ }
+
+ private void EndSendFileInternal(IAsyncResult asyncResult)
+ {
+ TransmitFileAsyncResult castedAsyncResult = asyncResult as TransmitFileAsyncResult;
+ if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this)
+ {
+ throw new ArgumentException(SR.net_io_invalidasyncresult, nameof(asyncResult));
+ }
+
+ if (castedAsyncResult.EndCalled)
+ {
+ throw new InvalidOperationException(SR.Format(SR.net_io_invalidendcall, "EndSendFile"));
+ }
+
+ castedAsyncResult.InternalWaitForCompletion();
+ castedAsyncResult.EndCalled = true;
+
+ // If the user passed the Disconnect and/or ReuseSocket flags, then TransmitFile disconnected the socket.
+ // Update our state to reflect this.
+ if (castedAsyncResult.DoDisconnect)
+ {
+ SetToDisconnected();
+ _remoteEndPoint = null;
+ }
+
+ if ((SocketError)castedAsyncResult.ErrorCode != SocketError.Success)
+ {
+ SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
+ UpdateStatusAfterSocketError(socketException);
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, socketException);
+ throw socketException;
+ }
+
+ }
}
}
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
index 166da46144..f3fc7915b6 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
@@ -2,6 +2,7 @@
// 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.Collections.Generic;
using System.Collections;
using System.ComponentModel;
@@ -1294,6 +1295,45 @@ namespace System.Net.Sockets
return bytesTransferred;
}
+ public void SendFile(string fileName)
+ {
+ SendFile(fileName, null, null, TransmitFileOptions.UseDefaultWorkerThread);
+ }
+
+ public void SendFile(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+
+ if (CleanedUp)
+ {
+ throw new ObjectDisposedException(this.GetType().FullName);
+ }
+
+ if (!Connected)
+ {
+ throw new NotSupportedException(SR.net_notconnected);
+ }
+
+ ValidateBlockingMode();
+
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"::SendFile() SRC:{LocalEndPoint} DST:{RemoteEndPoint} fileName:{fileName}");
+
+ SendFileInternal(fileName, preBuffer, postBuffer, flags);
+
+#if TRACE_VERBOSE
+ if (NetEventSource.IsEnabled)
+ {
+ try
+ {
+ NetEventSource.Info(this, $"::SendFile() SRC:{LocalEndPoint} DST:{RemoteEndPoint} UnsafeNclNativeMethods.OSSOCK.TransmitFile returns errorCode:{errorCode}");
+ }
+ catch (ObjectDisposedException) { }
+ }
+#endif
+
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
+ }
+
// Sends data to a specific end point, starting at the indicated location in the buffer.
public int SendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP)
{
@@ -2852,6 +2892,52 @@ namespace System.Net.Sockets
return bytesTransferred;
}
+ public IAsyncResult BeginSendFile(string fileName, AsyncCallback callback, object state)
+ {
+ return BeginSendFile(fileName, null, null, TransmitFileOptions.UseDefaultWorkerThread, callback, state);
+ }
+
+ public IAsyncResult BeginSendFile(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+
+ if (CleanedUp)
+ {
+ throw new ObjectDisposedException(this.GetType().FullName);
+ }
+
+ if (!Connected)
+ {
+ throw new NotSupportedException(SR.net_notconnected);
+ }
+
+ if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"::DoBeginSendFile() SRC:{LocalEndPoint} DST:{RemoteEndPoint} fileName:{fileName}");
+
+ IAsyncResult asyncResult = BeginSendFileInternal(fileName, preBuffer, postBuffer, flags, callback, state);
+
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this, asyncResult);
+ return asyncResult;
+ }
+
+ public void EndSendFile(IAsyncResult asyncResult)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this, asyncResult);
+
+ if (CleanedUp)
+ {
+ throw new ObjectDisposedException(this.GetType().FullName);
+ }
+
+ if (asyncResult == null)
+ {
+ throw new ArgumentNullException(nameof(asyncResult));
+ }
+
+ EndSendFileInternal(asyncResult);
+
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
+ }
+
// Routine Description:
//
// BeginSendTo - Async implementation of SendTo,
@@ -3147,9 +3233,6 @@ namespace System.Net.Sockets
// Throw an appropriate SocketException if the native call fails synchronously.
if (errorCode != SocketError.Success)
{
- // TODO: https://github.com/dotnet/corefx/issues/5426
- // NetEventSource.Fail(this, "GetLastWin32Error() returned zero.");
-
// Update the internal state of this socket according to the error before throwing.
UpdateStatusAfterSocketError(errorCode);
var socketException = new SocketException((int)errorCode);
@@ -3915,7 +3998,7 @@ namespace System.Net.Sockets
return EndAccept(out buffer, out bytesTransferred, asyncResult);
}
- internal Socket EndAccept(out byte[] buffer, IAsyncResult asyncResult)
+ public Socket EndAccept(out byte[] buffer, IAsyncResult asyncResult)
{
int bytesTransferred;
byte[] innerBuffer;
@@ -3926,7 +4009,7 @@ namespace System.Net.Sockets
return socket;
}
- internal Socket EndAccept(out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
+ public Socket EndAccept(out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
{
if (NetEventSource.IsEnabled) NetEventSource.Enter(this, asyncResult);
if (CleanedUp)
@@ -5738,6 +5821,9 @@ namespace System.Net.Sockets
}
}
+ // Helper for SendFile implementations
+ private static FileStream OpenFile(string name) => string.IsNullOrEmpty(name) ? null : File.OpenRead(name);
+
#endregion
[System.Diagnostics.Conditional("TRACE_VERBOSE")]
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs b/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs
index 6621680caa..36a95649dc 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs
@@ -2,6 +2,7 @@
// 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;
using System.Collections.Generic;
using System.Diagnostics;
@@ -302,6 +303,32 @@ namespace System.Net.Sockets
}
}
+ private sealed class SendFileOperation : AsyncOperation
+ {
+ public SafeFileHandle FileHandle;
+ public long Offset;
+ public long Count;
+ public long BytesTransferred;
+
+ protected override void Abort() { }
+
+ public Action<long, SocketError> Callback
+ {
+ private get { return (Action<long, SocketError>)CallbackOrEvent; }
+ set { CallbackOrEvent = value; }
+ }
+
+ protected override void InvokeCallback()
+ {
+ Callback(BytesTransferred, ErrorCode);
+ }
+
+ protected override bool DoTryComplete(SocketAsyncContext context)
+ {
+ return SocketPal.TryCompleteSendFile(context._socket, FileHandle, ref Offset, ref Count, ref BytesTransferred, out ErrorCode);
+ }
+ }
+
private enum QueueState
{
Clear = 0,
@@ -432,7 +459,7 @@ namespace System.Net.Sockets
private SafeCloseSocket _socket;
private OperationQueue<TransferOperation> _receiveQueue;
- private OperationQueue<SendOperation> _sendQueue;
+ private OperationQueue<AsyncOperation> _sendQueue; // Note, can be either SendOperation or SendFileOperation
private OperationQueue<AcceptOrConnectOperation> _acceptOrConnectQueue;
private SocketAsyncEngine.Token _asyncEngineToken;
private Interop.Sys.SocketEvents _registeredEvents;
@@ -1427,6 +1454,114 @@ namespace System.Net.Sockets
}
}
+ public SocketError SendFile(SafeFileHandle fileHandle, long offset, long count, int timeout, out long bytesSent)
+ {
+ Debug.Assert(timeout == -1 || timeout > 0, $"Unexpected timeout: {timeout}");
+
+ ManualResetEventSlim @event = null;
+ try
+ {
+ SendFileOperation operation;
+
+ lock (_sendAcceptConnectLock)
+ {
+ bytesSent = 0;
+ SocketError errorCode;
+
+ if (_sendQueue.IsEmpty &&
+ SocketPal.TryCompleteSendFile(_socket, fileHandle, ref offset, ref count, ref bytesSent, out errorCode))
+ {
+ return errorCode;
+ }
+
+ @event = new ManualResetEventSlim(false, 0);
+
+ operation = new SendFileOperation
+ {
+ Event = @event,
+ FileHandle = fileHandle,
+ Offset = offset,
+ Count = count,
+ BytesTransferred = bytesSent
+ };
+
+ bool isStopped;
+ while (!TryBeginOperation(ref _sendQueue, operation, Interop.Sys.SocketEvents.Write, maintainOrder: true, isStopped: out isStopped))
+ {
+ if (isStopped)
+ {
+ bytesSent = operation.BytesTransferred;
+ return SocketError.Interrupted;
+ }
+
+ if (operation.TryComplete(this))
+ {
+ bytesSent = operation.BytesTransferred;
+ return operation.ErrorCode;
+ }
+ }
+ }
+
+ bool signaled = operation.Wait(timeout);
+ bytesSent = operation.BytesTransferred;
+ return signaled ? operation.ErrorCode : SocketError.TimedOut;
+ }
+ finally
+ {
+ if (@event != null) @event.Dispose();
+ }
+ }
+
+ public SocketError SendFileAsync(SafeFileHandle fileHandle, long offset, long count, Action<long, SocketError> callback)
+ {
+ SetNonBlocking();
+
+ lock (_sendAcceptConnectLock)
+ {
+ long bytesSent = 0;
+ SocketError errorCode;
+
+ if (_sendQueue.IsEmpty &&
+ SocketPal.TryCompleteSendFile(_socket, fileHandle, ref offset, ref count, ref bytesSent, out errorCode))
+ {
+ if (errorCode == SocketError.Success)
+ {
+ ThreadPool.QueueUserWorkItem(args =>
+ {
+ var c = (Action<long, SocketError>)args;
+ c(bytesSent, SocketError.Success);
+ }, callback);
+ }
+ return errorCode;
+ }
+
+ var operation = new SendFileOperation
+ {
+ Callback = callback,
+ FileHandle = fileHandle,
+ Offset = offset,
+ Count = count,
+ BytesTransferred = bytesSent
+ };
+
+ bool isStopped;
+ while (!TryBeginOperation(ref _sendQueue, operation, Interop.Sys.SocketEvents.Write, maintainOrder: true, isStopped: out isStopped))
+ {
+ if (isStopped)
+ {
+ return SocketError.OperationAborted;
+ }
+
+ if (operation.TryComplete(this))
+ {
+ operation.QueueCompletionCallback();
+ break;
+ }
+ }
+ return SocketError.IOPending;
+ }
+ }
+
public unsafe void HandleEvents(Interop.Sys.SocketEvents events)
{
if ((events & Interop.Sys.SocketEvents.Error) != 0)
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs
index 09e249c86c..83c987c54d 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs
@@ -251,7 +251,7 @@ namespace System.Net.Sockets
(int)(DisconnectReuseSocket ? TransmitFileOptions.ReuseSocket : 0),
0))
{
- socketError = (SocketError)Marshal.GetLastWin32Error();
+ socketError = SocketPal.GetLastSocketError();
}
return socketError;
@@ -637,7 +637,8 @@ namespace System.Net.Sockets
_ptrSendPacketsDescriptor,
_sendPacketsDescriptor.Length,
_sendPacketsSendSize,
- _ptrNativeOverlapped);
+ _ptrNativeOverlapped,
+ _sendPacketsFlags);
return result ? SocketError.Success : SocketPal.GetLastSocketError();
}
@@ -881,7 +882,7 @@ namespace System.Net.Sockets
}
// Sets up an Overlapped object with either _buffer or _acceptBuffer pinned.
- unsafe private void SetupOverlappedSingle(bool pinSingleBuffer)
+ private unsafe void SetupOverlappedSingle(bool pinSingleBuffer)
{
// Pin buffer, get native pointers, and fill in WSABuffer descriptor.
if (pinSingleBuffer)
@@ -928,7 +929,7 @@ namespace System.Net.Sockets
}
// Sets up an Overlapped object with multiple buffers pinned.
- unsafe private void SetupOverlappedMultiple()
+ private unsafe void SetupOverlappedMultiple()
{
ArraySegment<byte>[] tempList = new ArraySegment<byte>[_bufferList.Count];
_bufferList.CopyTo(tempList, 0);
@@ -966,7 +967,7 @@ namespace System.Net.Sockets
}
// Sets up an Overlapped object for SendPacketsAsync.
- unsafe private void SetupOverlappedSendPackets()
+ private unsafe void SetupOverlappedSendPackets()
{
int index;
@@ -1243,7 +1244,7 @@ namespace System.Net.Sockets
try
{
// The Async IO completed with a failure.
- // here we need to call WSAGetOverlappedResult() just so Marshal.GetLastWin32Error() will return the correct error.
+ // here we need to call WSAGetOverlappedResult() just so GetLastSocketError() will return the correct error.
bool success = Interop.Winsock.WSAGetOverlappedResult(
_currentSocket.SafeHandle,
_ptrNativeOverlapped,
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs b/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs
index a3adfdb092..4b01cf738b 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs
@@ -54,6 +54,9 @@ namespace System.Net.Sockets
// SendPacketsElements property variables.
internal SendPacketsElement[] _sendPacketsElements;
+ // SendPacketsFlags property variable.
+ internal TransmitFileOptions _sendPacketsFlags;
+
// SocketError property variables.
private SocketError _socketError;
private Exception _connectByNameError;
@@ -117,6 +120,13 @@ namespace System.Net.Sockets
get { return _count; }
}
+ // SendPacketsFlags property.
+ public TransmitFileOptions SendPacketsFlags
+ {
+ get { return _sendPacketsFlags; }
+ set { _sendPacketsFlags = value; }
+ }
+
// NOTE: this property is mutually exclusive with Buffer.
// Setting this property with an existing non-null Buffer will throw.
public IList<ArraySegment<byte>> BufferList
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/SocketInformation.cs b/src/System.Net.Sockets/src/System/Net/Sockets/SocketInformation.cs
index a6431731d6..7a6d24568a 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/SocketInformation.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/SocketInformation.cs
@@ -12,6 +12,7 @@ namespace System.Net.Sockets
#if !netcore50
[Serializable]
#endif
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct SocketInformation
{
private byte[] _protocolInformation;
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs b/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs
index 35de19d488..dc53587964 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs
@@ -2,9 +2,11 @@
// 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.Collections;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
using System.Runtime.InteropServices;
namespace System.Net.Sockets
@@ -16,7 +18,7 @@ namespace System.Net.Sockets
public const int ProtocolInformationSize = 0;
public const bool SupportsMultipleConnectAttempts = false;
- private readonly static bool SupportsDualModeIPv4PacketInfo = GetPlatformSupportsDualModeIPv4PacketInfo();
+ private static readonly bool SupportsDualModeIPv4PacketInfo = GetPlatformSupportsDualModeIPv4PacketInfo();
private static bool GetPlatformSupportsDualModeIPv4PacketInfo()
{
@@ -229,6 +231,21 @@ namespace System.Net.Sockets
return sent;
}
+ private static unsafe long SendFile(SafeCloseSocket socket, SafeFileHandle fileHandle, ref long offset, ref long count, out Interop.Error errno)
+ {
+ long bytesSent;
+ errno = Interop.Sys.SendFile(socket, fileHandle, offset, count, out bytesSent);
+
+ if (errno != Interop.Error.SUCCESS)
+ {
+ return -1;
+ }
+
+ offset += bytesSent;
+ count -= bytesSent;
+ return bytesSent;
+ }
+
private static unsafe int Receive(SafeCloseSocket socket, SocketFlags flags, IList<ArraySegment<byte>> buffers, byte[] socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno)
{
int available;
@@ -620,6 +637,45 @@ namespace System.Net.Sockets
}
}
+ public static bool TryCompleteSendFile(SafeCloseSocket socket, SafeFileHandle handle, ref long offset, ref long count, ref long bytesSent, out SocketError errorCode)
+ {
+ for (;;)
+ {
+ long sent;
+ Interop.Error errno;
+ try
+ {
+ sent = SendFile(socket, handle, ref offset, ref count, out errno);
+ }
+ catch (ObjectDisposedException)
+ {
+ // The socket was closed, or is closing.
+ errorCode = SocketError.OperationAborted;
+ return true;
+ }
+
+ if (sent == -1)
+ {
+ if (errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK)
+ {
+ errorCode = GetSocketErrorForErrorCode(errno);
+ return true;
+ }
+
+ errorCode = SocketError.Success;
+ return false;
+ }
+
+ bytesSent += sent;
+
+ if (sent == 0 || count == 0)
+ {
+ errorCode = SocketError.Success;
+ return true;
+ }
+ }
+ }
+
public static SocketError SetBlocking(SafeCloseSocket handle, bool shouldBlock, out bool willBlock)
{
handle.IsNonBlocking = !shouldBlock;
@@ -735,6 +791,25 @@ namespace System.Net.Sockets
return completed ? errorCode : SocketError.WouldBlock;
}
+ public static SocketError SendFile(SafeCloseSocket handle, FileStream fileStream)
+ {
+ long offset = 0;
+ long length = fileStream.Length;
+
+ SafeFileHandle fileHandle = fileStream.SafeFileHandle;
+
+ long bytesTransferred = 0;
+
+ if (!handle.IsNonBlocking)
+ {
+ return handle.AsyncContext.SendFile(fileHandle, offset, length, handle.SendTimeout, out bytesTransferred);
+ }
+
+ SocketError errorCode;
+ bool completed = TryCompleteSendFile(handle, fileHandle, ref offset, ref length, ref bytesTransferred, out errorCode);
+ return completed ? errorCode : SocketError.WouldBlock;
+ }
+
public static SocketError SendTo(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, byte[] socketAddress, int socketAddressLen, out int bytesTransferred)
{
if (!handle.IsNonBlocking)
@@ -1279,6 +1354,11 @@ namespace System.Net.Sockets
return handle.AsyncContext.SendAsync(buffers, socketFlags, asyncResult.CompletionCallback);
}
+ public static SocketError SendFileAsync(SafeCloseSocket handle, FileStream fileStream, Action<long, SocketError> callback)
+ {
+ return handle.AsyncContext.SendFileAsync(fileStream.SafeFileHandle, 0, (int)fileStream.Length, callback);
+ }
+
public static SocketError SendToAsync(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, Internals.SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
{
asyncResult.SocketAddress = socketAddress;
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs
index 9944ad0bab..c41faa166b 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs
@@ -2,6 +2,7 @@
// 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.Collections.Generic;
using System.Collections;
using System.ComponentModel;
@@ -19,7 +20,7 @@ namespace System.Net.Sockets
{
public const bool SupportsMultipleConnectAttempts = true;
- private readonly static int s_protocolInformationSize = Marshal.SizeOf<Interop.Winsock.WSAPROTOCOL_INFO>();
+ private static readonly int s_protocolInformationSize = Marshal.SizeOf<Interop.Winsock.WSAPROTOCOL_INFO>();
public static int ProtocolInformationSize { get { return s_protocolInformationSize; } }
@@ -40,7 +41,14 @@ namespace System.Net.Sockets
public static SocketError GetLastSocketError()
{
- return (SocketError)Marshal.GetLastWin32Error();
+ int win32Error = Marshal.GetLastWin32Error();
+
+ if (win32Error == 0)
+ {
+ NetEventSource.Fail(null, "GetLastWin32Error() returned zero.");
+ }
+
+ return (SocketError)win32Error;
}
public static SocketError CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, out SafeCloseSocket socket)
@@ -61,7 +69,7 @@ namespace System.Net.Sockets
if (errorCode == SocketError.SocketError)
{
- errorCode = (SocketError)Marshal.GetLastWin32Error();
+ errorCode = GetLastSocketError();
}
willBlock = intBlocking == 0;
@@ -152,7 +160,7 @@ namespace System.Net.Sockets
if ((SocketError)errorCode == SocketError.SocketError)
{
- errorCode = (SocketError)Marshal.GetLastWin32Error();
+ errorCode = GetLastSocketError();
}
return errorCode;
@@ -201,6 +209,15 @@ namespace System.Net.Sockets
return SocketError.Success;
}
+ public static unsafe SocketError SendFile(SafeCloseSocket handle, SafeFileHandle fileHandle, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
+ {
+ fixed (byte* prePinnedBuffer = preBuffer)
+ fixed (byte* postPinnedBuffer = postBuffer)
+ {
+ return TransmitFileHelper(handle, fileHandle, SafeNativeOverlapped.Zero, preBuffer, postBuffer, flags);
+ }
+ }
+
public static unsafe SocketError SendTo(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, byte[] peerAddress, int peerAddressSize, out int bytesTransferred)
{
int bytesSent;
@@ -268,7 +285,7 @@ namespace System.Net.Sockets
if ((SocketError)errorCode == SocketError.SocketError)
{
- errorCode = (SocketError)Marshal.GetLastWin32Error();
+ errorCode = GetLastSocketError();
}
return errorCode;
@@ -331,7 +348,7 @@ namespace System.Net.Sockets
IntPtr.Zero,
IntPtr.Zero) == SocketError.SocketError)
{
- errorCode = (SocketError)Marshal.GetLastWin32Error();
+ errorCode = GetLastSocketError();
}
}
finally
@@ -785,6 +802,51 @@ namespace System.Net.Sockets
return errorCode;
}
+ // This assumes preBuffer/postBuffer are pinned already
+
+ private static unsafe SocketError TransmitFileHelper(
+ SafeHandle socket,
+ SafeHandle fileHandle,
+ SafeHandle overlapped,
+ byte[] preBuffer,
+ byte[] postBuffer,
+ TransmitFileOptions flags)
+ {
+ bool needTransmitFileBuffers = false;
+ Interop.Mswsock.TransmitFileBuffers transmitFileBuffers = default(Interop.Mswsock.TransmitFileBuffers);
+
+ if (preBuffer != null && preBuffer.Length > 0)
+ {
+ needTransmitFileBuffers = true;
+ transmitFileBuffers.Head = Marshal.UnsafeAddrOfPinnedArrayElement(preBuffer, 0);
+ transmitFileBuffers.HeadLength = preBuffer.Length;
+ }
+
+ if (postBuffer != null && postBuffer.Length > 0)
+ {
+ needTransmitFileBuffers = true;
+ transmitFileBuffers.Tail = Marshal.UnsafeAddrOfPinnedArrayElement(postBuffer, 0);
+ transmitFileBuffers.TailLength = postBuffer.Length;
+ }
+
+ bool success = Interop.Mswsock.TransmitFile(socket, fileHandle, 0, 0, overlapped,
+ needTransmitFileBuffers ? &transmitFileBuffers : null, flags);
+
+ return success ? SocketError.Success : GetLastSocketError();
+ }
+
+ public static unsafe SocketError SendFileAsync(SafeCloseSocket handle, FileStream fileStream, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, TransmitFileAsyncResult asyncResult)
+ {
+ asyncResult.SetUnmanagedStructures(fileStream, preBuffer, postBuffer, (flags & (TransmitFileOptions.Disconnect | TransmitFileOptions.ReuseSocket)) != 0);
+
+ SocketError errorCode = TransmitFileHelper(handle, fileStream?.SafeFileHandle, asyncResult.OverlappedHandle, preBuffer, postBuffer, flags);
+
+ // This will release resources if necessary
+ errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
+
+ return errorCode;
+ }
+
public static unsafe SocketError SendToAsync(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, Internals.SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
{
// Set up asyncResult for overlapped WSASendTo.
@@ -963,7 +1025,7 @@ namespace System.Net.Sockets
// This can throw ObjectDisposedException (handle, and retrieving the delegate).
if (!socket.DisconnectExBlocking(handle, IntPtr.Zero, (int)(reuseSocket ? TransmitFileOptions.ReuseSocket : 0), 0))
{
- errorCode = (SocketError)Marshal.GetLastWin32Error();
+ errorCode = GetLastSocketError();
}
return errorCode;
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/TransmitFileAsyncResult.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/TransmitFileAsyncResult.Windows.cs
new file mode 100644
index 0000000000..37eb38e728
--- /dev/null
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/TransmitFileAsyncResult.Windows.cs
@@ -0,0 +1,65 @@
+// 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.IO;
+using System.Runtime.InteropServices;
+
+namespace System.Net.Sockets
+{
+ internal sealed class TransmitFileAsyncResult : BaseOverlappedAsyncResult
+ {
+ private FileStream _fileStream;
+ private bool _doDisconnect;
+
+ internal TransmitFileAsyncResult(Socket socket, Object asyncState, AsyncCallback asyncCallback) :
+ base(socket, asyncState, asyncCallback)
+ {
+ }
+
+ internal void SetUnmanagedStructures(FileStream fileStream, byte[] preBuffer, byte[] postBuffer, bool doDisconnect)
+ {
+ _fileStream = fileStream;
+ _doDisconnect = doDisconnect;
+
+ int buffsNumber = 0;
+
+ if (preBuffer != null && preBuffer.Length > 0)
+ ++buffsNumber;
+
+ if (postBuffer != null && postBuffer.Length > 0)
+ ++buffsNumber;
+
+ object[] objectsToPin = null;
+ if (buffsNumber != 0)
+ {
+ objectsToPin = new object[buffsNumber];
+
+ if (preBuffer != null && preBuffer.Length > 0)
+ {
+ objectsToPin[--buffsNumber] = preBuffer;
+ }
+
+ if (postBuffer != null && postBuffer.Length > 0)
+ {
+ objectsToPin[--buffsNumber] = postBuffer;
+ }
+ }
+
+ base.SetUnmanagedStructures(objectsToPin);
+ }
+
+ protected override void ForceReleaseUnmanagedStructures()
+ {
+ if (_fileStream != null)
+ {
+ _fileStream.Dispose();
+ _fileStream = null;
+ }
+
+ base.ForceReleaseUnmanagedStructures();
+ }
+
+ internal bool DoDisconnect => _doDisconnect;
+ }
+}
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs b/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs
index 165dcc3019..81d8039c07 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs
@@ -42,11 +42,11 @@ namespace System.Net.Sockets.Tests
public void RemoveAt(int index) { }
}
- private readonly static byte[] s_buffer = new byte[1];
- private readonly static IList<ArraySegment<byte>> s_buffers = new List<ArraySegment<byte>> { new ArraySegment<byte>(s_buffer) };
- private readonly static SocketAsyncEventArgs s_eventArgs = new SocketAsyncEventArgs();
- private readonly static Socket s_ipv4Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- private readonly static Socket s_ipv6Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+ private static readonly byte[] s_buffer = new byte[1];
+ private static readonly IList<ArraySegment<byte>> s_buffers = new List<ArraySegment<byte>> { new ArraySegment<byte>(s_buffer) };
+ private static readonly SocketAsyncEventArgs s_eventArgs = new SocketAsyncEventArgs();
+ private static readonly Socket s_ipv4Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ private static readonly Socket s_ipv6Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
private static void TheAsyncCallback(IAsyncResult ar)
{
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs b/src/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs
index c105e016df..1cf3788d68 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/DisposedSocketTests.cs
@@ -11,9 +11,9 @@ namespace System.Net.Sockets.Tests
{
public class DisposedSocket
{
- private readonly static byte[] s_buffer = new byte[1];
- private readonly static IList<ArraySegment<byte>> s_buffers = new List<ArraySegment<byte>> { new ArraySegment<byte>(s_buffer) };
- private readonly static SocketAsyncEventArgs s_eventArgs = new SocketAsyncEventArgs();
+ private static readonly byte[] s_buffer = new byte[1];
+ private static readonly IList<ArraySegment<byte>> s_buffers = new List<ArraySegment<byte>> { new ArraySegment<byte>(s_buffer) };
+ private static readonly SocketAsyncEventArgs s_eventArgs = new SocketAsyncEventArgs();
private static Socket GetDisposedSocket(AddressFamily addressFamily = AddressFamily.InterNetwork)
{
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/SendFile.cs b/src/System.Net.Sockets/tests/FunctionalTests/SendFile.cs
new file mode 100644
index 0000000000..174125b652
--- /dev/null
+++ b/src/System.Net.Sockets/tests/FunctionalTests/SendFile.cs
@@ -0,0 +1,211 @@
+// 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.Generic;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Xunit;
+using Xunit.Abstractions;
+
+namespace System.Net.Sockets.Tests
+{
+ public class SendFile
+ {
+ public static readonly object[][] SendFile_MemberData = new object[][]
+ {
+ new object[] { IPAddress.IPv6Loopback, true },
+ new object[] { IPAddress.IPv6Loopback, false },
+ new object[] { IPAddress.Loopback, true },
+ new object[] { IPAddress.Loopback, false },
+ };
+
+ private string CreateFileToSend(int size, bool sendPreAndPostBuffers, out byte[] preBuffer, out byte[] postBuffer, out Fletcher32 checksum)
+ {
+ // Create file to send
+ var random = new Random();
+ int fileSize = sendPreAndPostBuffers ? size - 512 : size;
+
+ checksum = new Fletcher32();
+
+ preBuffer = null;
+ if (sendPreAndPostBuffers)
+ {
+ preBuffer = new byte[256];
+ random.NextBytes(preBuffer);
+ checksum.Add(preBuffer, 0, preBuffer.Length);
+ }
+
+ byte[] fileBuffer = new byte[fileSize];
+ random.NextBytes(fileBuffer);
+
+ string path = Path.GetTempFileName();
+ File.WriteAllBytes(path, fileBuffer);
+
+ checksum.Add(fileBuffer, 0, fileBuffer.Length);
+
+ postBuffer = null;
+ if (sendPreAndPostBuffers)
+ {
+ postBuffer = new byte[256];
+ random.NextBytes(postBuffer);
+ checksum.Add(postBuffer, 0, postBuffer.Length);
+ }
+
+ return path;
+ }
+
+ [OuterLoop] // TODO: Issue #11345
+ [Theory]
+ [MemberData(nameof(SendFile_MemberData))]
+ private void SendFile_Synchronous(IPAddress listenAt, bool sendPreAndPostBuffers)
+ {
+ const int BytesToSend = 123456;
+ const int ListenBacklog = 1;
+ const int LingerTime = 10;
+ const int TestTimeout = 30000;
+
+ // Create file to send
+ byte[] preBuffer;
+ byte[] postBuffer;
+ Fletcher32 sentChecksum;
+ string filename = CreateFileToSend(BytesToSend, sendPreAndPostBuffers, out preBuffer, out postBuffer, out sentChecksum);
+
+ // Start server
+ var server = new Socket(listenAt.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+ server.BindToAnonymousPort(listenAt);
+
+ server.Listen(ListenBacklog);
+
+ int bytesReceived = 0;
+ var receivedChecksum = new Fletcher32();
+ var serverThread = new Thread(() =>
+ {
+ using (server)
+ {
+ Socket remote = server.Accept();
+ Assert.NotNull(remote);
+
+ using (remote)
+ {
+ var recvBuffer = new byte[256];
+ for (;;)
+ {
+ int received = remote.Receive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None);
+ if (received == 0)
+ {
+ break;
+ }
+
+ bytesReceived += received;
+ receivedChecksum.Add(recvBuffer, 0, received);
+ }
+ }
+ }
+ });
+ serverThread.Start();
+
+ // Run client
+ EndPoint clientEndpoint = server.LocalEndPoint;
+ var client = new Socket(clientEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+ client.Connect(clientEndpoint);
+
+ using (client)
+ {
+ client.SendFile(filename, preBuffer, postBuffer, TransmitFileOptions.UseDefaultWorkerThread);
+
+ client.LingerState = new LingerOption(true, LingerTime);
+ }
+
+ Assert.True(serverThread.Join(TestTimeout), "Completed within allowed time");
+
+ Assert.Equal(BytesToSend, bytesReceived);
+ Assert.Equal(sentChecksum.Sum, receivedChecksum.Sum);
+
+ // Clean up the file we created
+ File.Delete(filename);
+ }
+
+ [OuterLoop] // TODO: Issue #11345
+ [Theory]
+ [MemberData(nameof(SendFile_MemberData))]
+ private void SendFile_APM(IPAddress listenAt, bool sendPreAndPostBuffers)
+ {
+ const int BytesToSend = 123456;
+ const int ListenBacklog = 1;
+ const int LingerTime = 10;
+ const int TestTimeout = 30000;
+
+ // Create file to send
+ byte[] preBuffer;
+ byte[] postBuffer;
+ Fletcher32 sentChecksum;
+ string filename = CreateFileToSend(BytesToSend, sendPreAndPostBuffers, out preBuffer, out postBuffer, out sentChecksum);
+
+ // Start server
+ var server = new Socket(listenAt.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+ server.BindToAnonymousPort(listenAt);
+
+ server.Listen(ListenBacklog);
+
+ var serverFinished = new TaskCompletionSource<bool>();
+ int bytesReceived = 0;
+ var receivedChecksum = new Fletcher32();
+
+ server.AcceptAPM(remote =>
+ {
+ Action<int> recvHandler = null;
+ bool first = true;
+
+ var recvBuffer = new byte[256];
+ recvHandler = received =>
+ {
+ if (!first)
+ {
+ if (received == 0)
+ {
+ remote.Dispose();
+ server.Dispose();
+ serverFinished.SetResult(true);
+ return;
+ }
+
+ bytesReceived += received;
+ receivedChecksum.Add(recvBuffer, 0, received);
+ }
+ else
+ {
+ first = false;
+ }
+
+ remote.ReceiveAPM(recvBuffer, 0, recvBuffer.Length, SocketFlags.None, recvHandler);
+ };
+
+ recvHandler(0);
+ });
+
+ // Run client
+ EndPoint clientEndpoint = server.LocalEndPoint;
+ var client = new Socket(clientEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+
+ client.ConnectAPM(clientEndpoint, () =>
+ {
+ client.SendFileAPM(filename, preBuffer, postBuffer, TransmitFileOptions.UseDefaultWorkerThread, () =>
+ {
+ client.LingerState = new LingerOption(true, LingerTime);
+ client.Dispose();
+ });
+ });
+
+ Assert.True(serverFinished.Task.Wait(TestTimeout), "Completed within allowed time");
+
+ Assert.Equal(BytesToSend, bytesReceived);
+ Assert.Equal(sentChecksum.Sum, receivedChecksum.Sum);
+
+ // Clean up the file we created
+ File.Delete(filename);
+ }
+ }
+}
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs b/src/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs
index 1241e602c0..f2af64f516 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs
@@ -279,6 +279,26 @@ namespace System.Net.Sockets.Tests
#endregion Buffers
+ #region TransmitFileOptions
+ [Theory]
+ [InlineData(SocketImplementationType.APM)]
+ [InlineData(SocketImplementationType.Async)]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void SocketDisconnected_TransmitFileOptionDisconnect(SocketImplementationType type)
+ {
+ SendPackets(type, new SendPacketsElement(new byte[10], 4, 4), TransmitFileOptions.Disconnect, 4);
+ }
+
+ [Theory]
+ [InlineData(SocketImplementationType.APM)]
+ [InlineData(SocketImplementationType.Async)]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void SocketDisconnectedAndReusable_TransmitFileOptionReuseSocket(SocketImplementationType type)
+ {
+ SendPackets(type, new SendPacketsElement(new byte[10], 4, 4), TransmitFileOptions.Disconnect | TransmitFileOptions.ReuseSocket, 4);
+ }
+ #endregion
+
#region Files
[Theory]
@@ -422,9 +442,50 @@ namespace System.Net.Sockets.Tests
GC.WaitForPendingFinalizers();
}
}
- #endregion
+ #endregion
#region Helpers
+ private void SendPackets(SocketImplementationType type, SendPacketsElement element, TransmitFileOptions flags, int bytesExpected)
+ {
+ Assert.True(Capability.IPv6Support());
+
+ EventWaitHandle completed = new ManualResetEvent(false);
+
+ int port;
+ using (SocketTestServer.SocketTestServerFactory(type, _serverAddress, out port))
+ {
+ using (Socket sock = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
+ {
+ sock.Connect(new IPEndPoint(_serverAddress, port));
+ using (SocketAsyncEventArgs args = new SocketAsyncEventArgs())
+ {
+ args.Completed += OnCompleted;
+ args.UserToken = completed;
+ args.SendPacketsElements = new[] { element };
+ args.SendPacketsFlags = flags;
+
+ if (sock.SendPacketsAsync(args))
+ {
+ Assert.True(completed.WaitOne(TestSettings.PassingTestTimeout), "Timed out");
+ }
+ Assert.Equal(SocketError.Success, args.SocketError);
+ Assert.Equal(bytesExpected, args.BytesTransferred);
+ }
+
+ switch (flags)
+ {
+ case TransmitFileOptions.Disconnect:
+ // Sending data again throws with socket shut down error.
+ Assert.Throws<SocketException>(() => { sock.Send(new byte[1] { 01 }); });
+ break;
+ case TransmitFileOptions.ReuseSocket & TransmitFileOptions.Disconnect:
+ // Able to send data again with reuse socket flag set.
+ Assert.Equal(1, sock.Send(new byte[1] { 01 }));
+ break;
+ }
+ }
+ }
+ }
private void SendPackets(SocketImplementationType type, SendPacketsElement element, int bytesExpected)
{
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/SocketAPMExtensions.cs b/src/System.Net.Sockets/tests/FunctionalTests/SocketAPMExtensions.cs
index 9b4676a54b..1de38bcf7a 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/SocketAPMExtensions.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/SocketAPMExtensions.cs
@@ -58,6 +58,16 @@ namespace System.Net.Sockets.Tests
socket.BeginSend(buffers, flags, callback, socket);
}
+ public static void SendFileAPM(this Socket socket, string filename, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, Action handler)
+ {
+ var callback = new AsyncCallback(asyncResult =>
+ {
+ ((Socket)asyncResult.AsyncState).EndSendFile(asyncResult);
+ handler();
+ });
+ socket.BeginSendFile(filename, preBuffer, postBuffer, flags, callback, socket);
+ }
+
public static void SendToAPM(this Socket socket, byte[] buffer, int offset, int count, SocketFlags flags, EndPoint remoteEndpoint, Action<int> handler)
{
var callback = new AsyncCallback(asyncResult => handler(((Socket)asyncResult.AsyncState).EndSendTo(asyncResult)));
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/SocketAsyncEventArgsTest.cs b/src/System.Net.Sockets/tests/FunctionalTests/SocketAsyncEventArgsTest.cs
index cb423377b2..cf10ae491e 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/SocketAsyncEventArgsTest.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/SocketAsyncEventArgsTest.cs
@@ -10,6 +10,14 @@ namespace System.Net.Sockets.Tests
public class SocketAsyncEventArgsTest
{
[Fact]
+ public void TestDefaultConstructor()
+ {
+ SocketAsyncEventArgs args = new SocketAsyncEventArgs();
+ Assert.Equal(0, args.SendPacketsSendSize);
+ Assert.Equal((TransmitFileOptions)0, args.SendPacketsFlags);
+ }
+
+ [Fact]
public async Task ReuseSocketAsyncEventArgs_SameInstance_MultipleSockets()
{
using (var listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj b/src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj
index 9cd60e1d8e..cdebd96900 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj
+++ b/src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj
@@ -28,6 +28,7 @@
<Compile Include="SelectTest.cs" />
<Compile Include="SendPacketsAsync.cs" />
<Compile Include="SendPacketsElementTest.cs" />
+ <Compile Include="SendFile.cs" />
<Compile Include="SendReceive.cs" />
<Compile Include="SelectAndPollTests.cs" />
<Compile Include="TimeoutTest.cs" />
diff --git a/src/System.Net.WebClient/pkg/System.Net.WebClient.pkgproj b/src/System.Net.WebClient/pkg/System.Net.WebClient.pkgproj
index 09a29432ac..c096c97d8c 100644
--- a/src/System.Net.WebClient/pkg/System.Net.WebClient.pkgproj
+++ b/src/System.Net.WebClient/pkg/System.Net.WebClient.pkgproj
@@ -4,7 +4,7 @@
<ItemGroup>
<ProjectReference Include="..\ref\System.Net.WebClient.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Net.WebClient.builds" />
</ItemGroup>
diff --git a/src/System.Net.WebClient/src/Configurations.props b/src/System.Net.WebClient/src/Configurations.props
index 9c336c0be9..53b62c64fe 100644
--- a/src/System.Net.WebClient/src/Configurations.props
+++ b/src/System.Net.WebClient/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Net.WebClient/src/System.Net.WebClient.csproj b/src/System.Net.WebClient/src/System.Net.WebClient.csproj
index be3821dc76..27f0b4520c 100644
--- a/src/System.Net.WebClient/src/System.Net.WebClient.csproj
+++ b/src/System.Net.WebClient/src/System.Net.WebClient.csproj
@@ -4,13 +4,13 @@
<PropertyGroup>
<ProjectGuid>{53D09AF4-0C13-4197-B8AD-9746F0374E88}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net463'">true</IsPartialFacadeAssembly>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net461'">true</IsPartialFacadeAssembly>
</PropertyGroup>
<!-- Default configurations to help VS understand the options -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\Net\WebClient.cs" />
<Compile Include="$(CommonPath)\System\IO\DelegatingStream.cs">
@@ -29,7 +29,7 @@
<Link>Common\System\Net\HttpKnownHeaderNames.cs</Link>
</Compile>
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="System" />
</ItemGroup>
<ItemGroup>
diff --git a/src/System.Net.WebClient/tests/WebClientTest.cs b/src/System.Net.WebClient/tests/WebClientTest.cs
index bedb5f2bc1..68ef83cd81 100644
--- a/src/System.Net.WebClient/tests/WebClientTest.cs
+++ b/src/System.Net.WebClient/tests/WebClientTest.cs
@@ -448,7 +448,7 @@ namespace System.Net.Tests
public abstract class WebClientTestBase
{
- public readonly static object[][] EchoServers = System.Net.Test.Common.Configuration.Http.EchoServers;
+ public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.Http.EchoServers;
const string ExpectedText =
"To be, or not to be, that is the question:" +
"Whether 'tis Nobler in the mind to suffer" +
diff --git a/src/System.Net.WebHeaderCollection/ref/System.Net.WebHeaderCollection.cs b/src/System.Net.WebHeaderCollection/ref/System.Net.WebHeaderCollection.cs
index 2b6fa41d10..b404d8221b 100644
--- a/src/System.Net.WebHeaderCollection/ref/System.Net.WebHeaderCollection.cs
+++ b/src/System.Net.WebHeaderCollection/ref/System.Net.WebHeaderCollection.cs
@@ -113,6 +113,9 @@ namespace System.Net
public override void Clear() { }
public override string Get(int index) { throw null; }
public override string Get(string name) { throw null; }
+ public void Set(HttpRequestHeader header, string value) { }
+ public void Set(HttpResponseHeader header, string value) { }
+ public override void Set(string name, string value) { }
public void Add(HttpRequestHeader header, string value) { }
public void Add(HttpResponseHeader header, string value) { }
public void Add(string header) { }
diff --git a/src/System.Net.WebHeaderCollection/src/System/Net/HttpRequestHeader.cs b/src/System.Net.WebHeaderCollection/src/System/Net/HttpRequestHeader.cs
index 92a64950c7..61adc64699 100644
--- a/src/System.Net.WebHeaderCollection/src/System/Net/HttpRequestHeader.cs
+++ b/src/System.Net.WebHeaderCollection/src/System/Net/HttpRequestHeader.cs
@@ -52,7 +52,7 @@ namespace System.Net
internal static class HttpRequestHeaderExtensions
{
- private readonly static string[] s_names = {
+ private static readonly string[] s_names = {
"Cache-Control",
"Connection",
"Date",
diff --git a/src/System.Net.WebHeaderCollection/src/System/Net/HttpResponseHeader.cs b/src/System.Net.WebHeaderCollection/src/System/Net/HttpResponseHeader.cs
index 824676484d..4081861b6a 100644
--- a/src/System.Net.WebHeaderCollection/src/System/Net/HttpResponseHeader.cs
+++ b/src/System.Net.WebHeaderCollection/src/System/Net/HttpResponseHeader.cs
@@ -41,7 +41,7 @@ namespace System.Net
internal static class HttpResponseHeaderExtensions
{
- private readonly static string[] s_names = {
+ private static readonly string[] s_names = {
"Cache-Control",
"Connection",
"Date",
diff --git a/src/System.Net.WebHeaderCollection/tests/WebHeaderCollectionTest.netstandard17.cs b/src/System.Net.WebHeaderCollection/tests/WebHeaderCollectionTest.netstandard17.cs
index 5b4e9dcc07..6cddc07825 100644
--- a/src/System.Net.WebHeaderCollection/tests/WebHeaderCollectionTest.netstandard17.cs
+++ b/src/System.Net.WebHeaderCollection/tests/WebHeaderCollectionTest.netstandard17.cs
@@ -142,5 +142,37 @@ namespace System.Net.WebHeaderCollectionTests
WebHeaderCollection w = new WebHeaderCollection();
Assert.Throws<ArgumentNullException>(() => w.Remove(null));
}
+
+ [Fact]
+ public void HttpResponseHeader_Set_Success()
+ {
+ WebHeaderCollection w = new WebHeaderCollection();
+ w.Set(HttpResponseHeader.ProxyAuthenticate, "value123");
+
+ Assert.Equal("value123", w[HttpResponseHeader.ProxyAuthenticate]);
+ }
+
+ [Fact]
+ public void HttpRequestHeader_Set_Success()
+ {
+ WebHeaderCollection w = new WebHeaderCollection();
+ w.Set(HttpRequestHeader.Connection, "keep-alive");
+
+ Assert.Equal(1, w.Count);
+ Assert.Equal("keep-alive", w[HttpRequestHeader.Connection]);
+ Assert.Equal("Connection", w.AllKeys[0]);
+ }
+
+ [Fact]
+ public void NameValue_Set_Success()
+ {
+ WebHeaderCollection w = new WebHeaderCollection();
+ w.Set("firstName", "first");
+ Assert.Equal(1, w.Count);
+ Assert.NotEmpty(w);
+ Assert.NotEmpty(w.AllKeys);
+ Assert.Equal(new[] { "firstName" }, w.AllKeys);
+ Assert.Equal("first", w["firstName"]);
+ }
}
}
diff --git a/src/System.Net.WebProxy/pkg/System.Net.WebProxy.pkgproj b/src/System.Net.WebProxy/pkg/System.Net.WebProxy.pkgproj
index eb27d4b8b3..5a16a2f3e6 100644
--- a/src/System.Net.WebProxy/pkg/System.Net.WebProxy.pkgproj
+++ b/src/System.Net.WebProxy/pkg/System.Net.WebProxy.pkgproj
@@ -4,7 +4,7 @@
<ItemGroup>
<ProjectReference Include="..\ref\System.Net.WebProxy.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Net.WebProxy.builds" />
</ItemGroup>
diff --git a/src/System.Net.WebProxy/src/Configurations.props b/src/System.Net.WebProxy/src/Configurations.props
index 9c336c0be9..53b62c64fe 100644
--- a/src/System.Net.WebProxy/src/Configurations.props
+++ b/src/System.Net.WebProxy/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Net.WebProxy/src/System.Net.WebProxy.csproj b/src/System.Net.WebProxy/src/System.Net.WebProxy.csproj
index 4c5132d12a..893cd1a561 100644
--- a/src/System.Net.WebProxy/src/System.Net.WebProxy.csproj
+++ b/src/System.Net.WebProxy/src/System.Net.WebProxy.csproj
@@ -4,18 +4,18 @@
<PropertyGroup>
<ProjectGuid>{53D09AF4-0C13-4197-B8AD-9746F0374E88}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net463'">true</IsPartialFacadeAssembly>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)'=='net461'">true</IsPartialFacadeAssembly>
</PropertyGroup>
<!-- Default configurations to help VS understand the options -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\Net\IWebProxyScript.cs" />
<Compile Include="System\Net\WebProxy.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="System" />
</ItemGroup>
<ItemGroup>
diff --git a/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/ManagedWebSocket.cs b/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/ManagedWebSocket.cs
index e8ca95a19f..416f12dabf 100644
--- a/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/ManagedWebSocket.cs
+++ b/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/ManagedWebSocket.cs
@@ -2,6 +2,7 @@
// 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.Buffers;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
@@ -81,7 +82,9 @@ namespace System.Net.WebSockets
/// <summary>CancellationTokenSource used to abort all current and future operations when anything is canceled or any error occurs.</summary>
private readonly CancellationTokenSource _abortSource = new CancellationTokenSource();
/// <summary>Buffer used for reading data from the network.</summary>
- private readonly byte[] _receiveBuffer;
+ private byte[] _receiveBuffer;
+ /// <summary>Gets whether the receive buffer came from the ArrayPool.</summary>
+ private readonly bool _receiveBufferFromPool;
/// <summary>
/// Tracks the state of the validity of the UTF8 encoding of text payloads. Text may be split across fragments.
/// </summary>
@@ -132,9 +135,10 @@ namespace System.Net.WebSockets
/// </summary>
private int _receivedMaskOffsetOffset = 0;
/// <summary>
- /// Buffer used to store the complete message to be sent to the stream. This is needed
- /// rather than just sending a header and then the user's buffer, as we need to mutate the
- /// buffered data with the mask, and we don't want to change the data in the user's buffer.
+ /// Temporary send buffer. This should be released back to the ArrayPool once it's
+ /// no longer needed for the current send operation. It is stored as an instance
+ /// field to minimize needing to pass it around and to avoid it becoming a field on
+ /// various async state machine objects.
/// </summary>
private byte[] _sendBuffer;
/// <summary>
@@ -195,7 +199,8 @@ namespace System.Net.WebSockets
}
else
{
- _receiveBuffer = new byte[Math.Max(receiveBufferSize, MaxMessageHeaderLength)];
+ _receiveBufferFromPool = true;
+ _receiveBuffer = ArrayPool<byte>.Shared.Rent(Math.Max(receiveBufferSize, MaxMessageHeaderLength));
}
// Set up the abort source so that if it's triggered, we transition the instance appropriately.
@@ -238,6 +243,12 @@ namespace System.Net.WebSockets
_disposed = true;
_keepAliveTimer?.Dispose();
_stream?.Dispose();
+ if (_receiveBufferFromPool)
+ {
+ byte[] old = _receiveBuffer;
+ _receiveBuffer = null;
+ ArrayPool<byte>.Shared.Return(old);
+ }
if (_state < WebSocketState.Aborted)
{
_state = WebSocketState.Closed;
@@ -382,7 +393,7 @@ namespace System.Net.WebSockets
// If we get here, the cancellation token is not cancelable so we don't have to worry about it,
// and we own the semaphore, so we don't need to asynchronously wait for it.
Task writeTask = null;
- bool releaseSemaphore = true;
+ bool releaseSemaphoreAndSendBuffer = true;
try
{
// Write the payload synchronously to the buffer, then write that buffer out to the network.
@@ -399,9 +410,9 @@ namespace System.Net.WebSockets
}
// Up until this point, if an exception occurred (such as when accessing _stream or when
- // calling GetResult), we want to release the semaphore. After this point, the semaphore needs
- // to remain held until writeTask completes.
- releaseSemaphore = false;
+ // calling GetResult), we want to release the semaphore and the send buffer. After this point,
+ // both need to be held until writeTask completes.
+ releaseSemaphoreAndSendBuffer = false;
}
catch (Exception exc)
{
@@ -411,9 +422,10 @@ namespace System.Net.WebSockets
}
finally
{
- if (releaseSemaphore)
+ if (releaseSemaphoreAndSendBuffer)
{
_sendFrameAsyncLock.Release();
+ ReleaseSendBuffer();
}
}
@@ -423,6 +435,7 @@ namespace System.Net.WebSockets
{
var thisRef = (ManagedWebSocket)s;
thisRef._sendFrameAsyncLock.Release();
+ thisRef.ReleaseSendBuffer();
try { t.GetAwaiter().GetResult(); }
catch (Exception exc)
@@ -454,14 +467,15 @@ namespace System.Net.WebSockets
finally
{
_sendFrameAsyncLock.Release();
+ ReleaseSendBuffer();
}
}
/// <summary>Writes a frame into the send buffer, which can then be sent over the network.</summary>
private int WriteFrameToSendBuffer(MessageOpcode opcode, bool endOfMessage, ArraySegment<byte> payloadBuffer)
{
- // Grow our send buffer as needed. We reuse the buffer for all messages, with it protected by the send frame lock.
- EnsureBufferLength(ref _sendBuffer, payloadBuffer.Count + MaxMessageHeaderLength);
+ // Ensure we have a _sendBuffer.
+ AllocateSendBuffer(payloadBuffer.Count + MaxMessageHeaderLength);
// Write the message header data to the buffer.
int headerLength;
@@ -996,37 +1010,44 @@ namespace System.Net.WebSockets
$"Unexpected state {State}.");
// Wait until we've received a close response
- byte[] closeBuffer = new byte[MaxMessageHeaderLength + MaxControlPayloadLength];
- while (!_receivedCloseFrame)
+ byte[] closeBuffer = ArrayPool<byte>.Shared.Rent(MaxMessageHeaderLength + MaxControlPayloadLength);
+ try
{
- Debug.Assert(!Monitor.IsEntered(StateUpdateLock), $"{nameof(StateUpdateLock)} must never be held when acquiring {nameof(ReceiveAsyncLock)}");
- Task<WebSocketReceiveResult> receiveTask;
- lock (ReceiveAsyncLock)
+ while (!_receivedCloseFrame)
{
- // Now that we're holding the ReceiveAsyncLock, double-check that we've not yet received the close frame.
- // It could have been received between our check above and now due to a concurrent receive completing.
- if (_receivedCloseFrame)
+ Debug.Assert(!Monitor.IsEntered(StateUpdateLock), $"{nameof(StateUpdateLock)} must never be held when acquiring {nameof(ReceiveAsyncLock)}");
+ Task<WebSocketReceiveResult> receiveTask;
+ lock (ReceiveAsyncLock)
{
- break;
- }
+ // Now that we're holding the ReceiveAsyncLock, double-check that we've not yet received the close frame.
+ // It could have been received between our check above and now due to a concurrent receive completing.
+ if (_receivedCloseFrame)
+ {
+ break;
+ }
- // We've not yet processed a received close frame, which means we need to wait for a received close to complete.
- // There may already be one in flight, in which case we want to just wait for that one rather than kicking off
- // another (we don't support concurrent receive operations). We need to kick off a new receive if either we've
- // never issued a receive or if the last issued receive completed for reasons other than a close frame. There is
- // a race condition here, e.g. if there's a in-flight receive that completes after we check, but that's fine: worst
- // case is we then await it, find that it's not what we need, and try again.
- receiveTask = _lastReceiveAsync;
- if (receiveTask == null ||
- (receiveTask.Status == TaskStatus.RanToCompletion && receiveTask.Result.MessageType != WebSocketMessageType.Close))
- {
- _lastReceiveAsync = receiveTask = ReceiveAsyncPrivate(new ArraySegment<byte>(closeBuffer), cancellationToken);
+ // We've not yet processed a received close frame, which means we need to wait for a received close to complete.
+ // There may already be one in flight, in which case we want to just wait for that one rather than kicking off
+ // another (we don't support concurrent receive operations). We need to kick off a new receive if either we've
+ // never issued a receive or if the last issued receive completed for reasons other than a close frame. There is
+ // a race condition here, e.g. if there's a in-flight receive that completes after we check, but that's fine: worst
+ // case is we then await it, find that it's not what we need, and try again.
+ receiveTask = _lastReceiveAsync;
+ if (receiveTask == null ||
+ (receiveTask.Status == TaskStatus.RanToCompletion && receiveTask.Result.MessageType != WebSocketMessageType.Close))
+ {
+ _lastReceiveAsync = receiveTask = ReceiveAsyncPrivate(new ArraySegment<byte>(closeBuffer), cancellationToken);
+ }
}
- }
- // Wait for whatever receive task we have. We'll then loop around again to re-check our state.
- Debug.Assert(receiveTask != null);
- await receiveTask.ConfigureAwait(false);
+ // Wait for whatever receive task we have. We'll then loop around again to re-check our state.
+ Debug.Assert(receiveTask != null);
+ await receiveTask.ConfigureAwait(false);
+ }
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(closeBuffer);
}
// We're closed. Close the connection and update the status.
@@ -1048,24 +1069,36 @@ namespace System.Net.WebSockets
{
// Close payload is two bytes containing the close status followed by a UTF8-encoding of the status description, if it exists.
- byte[] buffer;
- if (string.IsNullOrEmpty(closeStatusDescription))
+ byte[] buffer = null;
+ try
{
- buffer = new byte[2];
+ int count = 2;
+ if (string.IsNullOrEmpty(closeStatusDescription))
+ {
+ buffer = ArrayPool<byte>.Shared.Rent(count);
+ }
+ else
+ {
+ count += s_textEncoding.GetByteCount(closeStatusDescription);
+ buffer = ArrayPool<byte>.Shared.Rent(count);
+ int encodedLength = s_textEncoding.GetBytes(closeStatusDescription, 0, closeStatusDescription.Length, buffer, 2);
+ Debug.Assert(count - 2 == encodedLength, $"GetByteCount and GetBytes encoded count didn't match");
+ }
+
+ ushort closeStatusValue = (ushort)closeStatus;
+ buffer[0] = (byte)(closeStatusValue >> 8);
+ buffer[1] = (byte)(closeStatusValue & 0xFF);
+
+ await SendFrameAsync(MessageOpcode.Close, true, new ArraySegment<byte>(buffer, 0, count), cancellationToken).ConfigureAwait(false);
}
- else
+ finally
{
- buffer = new byte[2 + s_textEncoding.GetByteCount(closeStatusDescription)];
- int encodedLength = s_textEncoding.GetBytes(closeStatusDescription, 0, closeStatusDescription.Length, buffer, 2);
- Debug.Assert(buffer.Length - 2 == encodedLength, $"GetByteCount and GetBytes encoded count didn't match");
+ if (buffer != null)
+ {
+ ArrayPool<byte>.Shared.Return(buffer);
+ }
}
- ushort closeStatusValue = (ushort)closeStatus;
- buffer[0] = (byte)(closeStatusValue >> 8);
- buffer[1] = (byte)(closeStatusValue & 0xFF);
-
- await SendFrameAsync(MessageOpcode.Close, true, new ArraySegment<byte>(buffer), cancellationToken).ConfigureAwait(false);
-
lock (StateUpdateLock)
{
_sentCloseFrame = true;
@@ -1124,15 +1157,21 @@ namespace System.Net.WebSockets
}
}
- /// <summary>
- /// Grows the specified buffer if it's not at least the specified minimum length.
- /// Data is not copied if the buffer is grown.
- /// </summary>
- private static void EnsureBufferLength(ref byte[] buffer, int minLength)
+ /// <summary>Gets a send buffer from the pool.</summary>
+ private void AllocateSendBuffer(int minLength)
+ {
+ Debug.Assert(_sendBuffer == null); // would only fail if had some catastrophic error previously that prevented cleaning up
+ _sendBuffer = ArrayPool<byte>.Shared.Rent(minLength);
+ }
+
+ /// <summary>Releases the send buffer to the pool.</summary>
+ private void ReleaseSendBuffer()
{
- if (buffer == null || buffer.Length < minLength)
+ byte[] old = _sendBuffer;
+ if (old != null)
{
- buffer = new byte[minLength];
+ _sendBuffer = null;
+ ArrayPool<byte>.Shared.Return(old);
}
}
diff --git a/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs b/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs
index 3db48caede..a599b8e16f 100644
--- a/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs
+++ b/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs
@@ -73,7 +73,7 @@ namespace System.Net.WebSockets
public async Task ConnectAsyncCore(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
{
- // TODO: Not currently implemented, or explicitly ignored:
+ // TODO #14480 : Not currently implemented, or explicitly ignored:
// - ClientWebSocketOptions.UseDefaultCredentials
// - ClientWebSocketOptions.Credentials
// - ClientWebSocketOptions.Proxy
diff --git a/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinHttpWebSocket.cs b/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinHttpWebSocket.cs
index 4c79360051..ef71840266 100644
--- a/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinHttpWebSocket.cs
+++ b/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinHttpWebSocket.cs
@@ -70,8 +70,8 @@ namespace System.Net.WebSockets
}
#endregion
- readonly static WebSocketState[] s_validConnectStates = { WebSocketState.None };
- readonly static WebSocketState[] s_validConnectingStates = { WebSocketState.Connecting };
+ static readonly WebSocketState[] s_validConnectStates = { WebSocketState.None };
+ static readonly WebSocketState[] s_validConnectingStates = { WebSocketState.Connecting };
public async Task ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
{
@@ -287,7 +287,7 @@ namespace System.Net.WebSockets
}
}
- private readonly static WebSocketState[] s_validSendStates = { WebSocketState.Open, WebSocketState.CloseReceived };
+ private static readonly WebSocketState[] s_validSendStates = { WebSocketState.Open, WebSocketState.CloseReceived };
public override Task SendAsync(
ArraySegment<byte> buffer,
WebSocketMessageType messageType,
@@ -349,8 +349,8 @@ namespace System.Net.WebSockets
}
}
- private readonly static WebSocketState[] s_validReceiveStates = { WebSocketState.Open, WebSocketState.CloseSent };
- private readonly static WebSocketState[] s_validAfterReceiveStates = { WebSocketState.Open, WebSocketState.CloseSent, WebSocketState.CloseReceived };
+ private static readonly WebSocketState[] s_validReceiveStates = { WebSocketState.Open, WebSocketState.CloseSent };
+ private static readonly WebSocketState[] s_validAfterReceiveStates = { WebSocketState.Open, WebSocketState.CloseSent, WebSocketState.CloseReceived };
public override async Task<WebSocketReceiveResult> ReceiveAsync(
ArraySegment<byte> buffer,
CancellationToken cancellationToken)
@@ -523,8 +523,8 @@ namespace System.Net.WebSockets
}
}
- private readonly static WebSocketState[] s_validCloseOutputStates = { WebSocketState.Open, WebSocketState.CloseReceived };
- private readonly static WebSocketState[] s_validCloseOutputStatesAfterUpdate = { WebSocketState.CloseReceived, WebSocketState.CloseSent };
+ private static readonly WebSocketState[] s_validCloseOutputStates = { WebSocketState.Open, WebSocketState.CloseReceived };
+ private static readonly WebSocketState[] s_validCloseOutputStatesAfterUpdate = { WebSocketState.CloseReceived, WebSocketState.CloseSent };
public override Task CloseOutputAsync(
WebSocketCloseStatus closeStatus,
string statusDescription,
diff --git a/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinRTWebSocket.cs b/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinRTWebSocket.cs
index c785cdccc5..67bbba71f1 100644
--- a/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinRTWebSocket.cs
+++ b/src/System.Net.WebSockets.Client/src/System/Net/WebSockets/WinRTWebSocket.cs
@@ -204,7 +204,7 @@ namespace System.Net.WebSockets
}
}
- private readonly static WebSocketState[] s_validCloseOutputStates = { WebSocketState.Open, WebSocketState.CloseReceived, WebSocketState.CloseSent };
+ private static readonly WebSocketState[] s_validCloseOutputStates = { WebSocketState.Open, WebSocketState.CloseReceived, WebSocketState.CloseSent };
public override Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string statusDescription,
CancellationToken cancellationToken)
{
@@ -244,8 +244,8 @@ namespace System.Net.WebSockets
}
}
- private readonly static WebSocketState[] s_validReceiveStates = { WebSocketState.Open, WebSocketState.CloseSent };
- private readonly static WebSocketState[] s_validAfterReceiveStates = { WebSocketState.Open, WebSocketState.CloseSent, WebSocketState.CloseReceived, WebSocketState.Closed };
+ private static readonly WebSocketState[] s_validReceiveStates = { WebSocketState.Open, WebSocketState.CloseSent };
+ private static readonly WebSocketState[] s_validAfterReceiveStates = { WebSocketState.Open, WebSocketState.CloseSent, WebSocketState.CloseReceived, WebSocketState.Closed };
public override async Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer,
CancellationToken cancellationToken)
{
@@ -322,7 +322,7 @@ namespace System.Net.WebSockets
}
}
- private readonly static WebSocketState[] s_validSendStates = { WebSocketState.Open, WebSocketState.CloseReceived };
+ private static readonly WebSocketState[] s_validSendStates = { WebSocketState.Open, WebSocketState.CloseReceived };
public override async Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage,
CancellationToken cancellationToken)
{
diff --git a/src/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs b/src/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs
index 7282e3b3bf..e06bfe3997 100644
--- a/src/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs
+++ b/src/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs
@@ -17,8 +17,8 @@ namespace System.Net.WebSockets.Client.Tests
/// </summary>
public class ClientWebSocketTestBase
{
- public readonly static object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.EchoServers;
- public readonly static object[][] EchoHeadersServers = System.Net.Test.Common.Configuration.WebSockets.EchoHeadersServers;
+ public static readonly object[][] EchoServers = System.Net.Test.Common.Configuration.WebSockets.EchoServers;
+ public static readonly object[][] EchoHeadersServers = System.Net.Test.Common.Configuration.WebSockets.EchoHeadersServers;
public const int TimeOutMilliseconds = 10000;
public const int CloseDescriptionMaxLength = 123;
diff --git a/src/System.Numerics.Vectors/src/System/Numerics/Vector.cs b/src/System.Numerics.Vectors/src/System/Numerics/Vector.cs
index ff31013a00..dd58b4da6b 100644
--- a/src/System.Numerics.Vectors/src/System/Numerics/Vector.cs
+++ b/src/System.Numerics.Vectors/src/System/Numerics/Vector.cs
@@ -2752,11 +2752,11 @@ namespace System.Numerics
}
/// <summary>
- /// Returns a boolean indicating whether any single pair of elements in the given vectors are equal.
+ /// Returns a boolean indicating whether any single pair of elements in the given vectors are not equal.
/// </summary>
/// <param name="left">The first vector to compare.</param>
/// <param name="right">The second vector to compare.</param>
- /// <returns>True if any element pairs are equal; False if no element pairs are equal.</returns>
+ /// <returns>True if left and right are not equal; False otherwise.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Vector<T> left, Vector<T> right)
{
diff --git a/src/System.Numerics.Vectors/src/System/Numerics/Vector.tt b/src/System.Numerics.Vectors/src/System/Numerics/Vector.tt
index 39911eb21f..43552bc3a3 100644
--- a/src/System.Numerics.Vectors/src/System/Numerics/Vector.tt
+++ b/src/System.Numerics.Vectors/src/System/Numerics/Vector.tt
@@ -7,7 +7,6 @@
<#@ import namespace="System.Runtime.InteropServices" #>
<#@ include file="GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #>
-using System.Diagnostics.Contracts;
using System.Globalization;
using System.Numerics.Hashing;
using System.Runtime.CompilerServices;
@@ -1005,11 +1004,11 @@ namespace System.Numerics
}
/// <summary>
- /// Returns a boolean indicating whether any single pair of elements in the given vectors are equal.
+ /// Returns a boolean indicating whether any single pair of elements in the given vectors are not equal.
/// </summary>
/// <param name="left">The first vector to compare.</param>
/// <param name="right">The second vector to compare.</param>
- /// <returns>True if any element pairs are equal; False if no element pairs are equal.</returns>
+ /// <returns>True if left and right are not equal; False otherwise.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Vector<T> left, Vector<T> right)
{
diff --git a/src/System.ObjectModel/pkg/System.ObjectModel.pkgproj b/src/System.ObjectModel/pkg/System.ObjectModel.pkgproj
index 1abf9af883..9e8d34a80f 100644
--- a/src/System.ObjectModel/pkg/System.ObjectModel.pkgproj
+++ b/src/System.ObjectModel/pkg/System.ObjectModel.pkgproj
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
- <ProjectReference Include="..\ref\System.ObjectModel.csproj">
+ <ProjectReference Include="..\ref\System.ObjectModel.builds">
<SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.ObjectModel.builds" />
diff --git a/src/System.ObjectModel/ref/Configurations.props b/src/System.ObjectModel/ref/Configurations.props
new file mode 100644
index 0000000000..ea9ea79f78
--- /dev/null
+++ b/src/System.ObjectModel/ref/Configurations.props
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <BuildConfigurations>
+ netcoreapp;
+ netstandard;
+ </BuildConfigurations>
+ </PropertyGroup>
+</Project>
diff --git a/src/System.ObjectModel/ref/System.ObjectModel.cs b/src/System.ObjectModel/ref/System.ObjectModel.cs
index 4d06807809..63ca8e0d2d 100644
--- a/src/System.ObjectModel/ref/System.ObjectModel.cs
+++ b/src/System.ObjectModel/ref/System.ObjectModel.cs
@@ -19,6 +19,9 @@ namespace System.Collections.ObjectModel
protected void ChangeItemKey(TItem item, TKey newKey) { }
protected override void ClearItems() { }
public bool Contains(TKey key) { throw null; }
+#if netcoreapp11
+ public bool TryGetValue(TKey key, out TItem item) { throw null; }
+#endif
protected abstract TKey GetKeyForItem(TItem item);
protected override void InsertItem(int index, TItem item) { }
public bool Remove(TKey key) { throw null; }
diff --git a/src/System.ObjectModel/ref/System.ObjectModel.csproj b/src/System.ObjectModel/ref/System.ObjectModel.csproj
index 197ffd0afe..f8c8efff1a 100644
--- a/src/System.ObjectModel/ref/System.ObjectModel.csproj
+++ b/src/System.ObjectModel/ref/System.ObjectModel.csproj
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <DefineConstants Condition="'$(TargetGroup)' == 'netcoreapp'">$(DefineConstants);netcoreapp11</DefineConstants>
+ </PropertyGroup>
<ItemGroup>
<Compile Include="System.ObjectModel.cs" />
</ItemGroup>
diff --git a/src/System.ObjectModel/src/System.ObjectModel.csproj b/src/System.ObjectModel/src/System.ObjectModel.csproj
index 4ddcc77f3c..6ea79479e7 100644
--- a/src/System.ObjectModel/src/System.ObjectModel.csproj
+++ b/src/System.ObjectModel/src/System.ObjectModel.csproj
@@ -8,6 +8,11 @@
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net463'">true</IsPartialFacadeAssembly>
<ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net463'">None</ResourcesSourceOutputDirectory>
</PropertyGroup>
+ <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ContractProject Include="..\ref\System.ObjectModel.csproj">
+ <TargetGroup>netstandard1.7</TargetGroup>
+ </ContractProject>
+ </ItemGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard_Release|AnyCPU'" />
diff --git a/src/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs b/src/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs
index 26511baea1..0fb979f1d3 100644
--- a/src/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs
+++ b/src/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs
@@ -73,19 +73,10 @@ namespace System.Collections.ObjectModel
{
get
{
- if (key == null)
- {
- throw new ArgumentNullException(nameof(key));
- }
-
- if (_dict != null)
- {
- return _dict[key];
- }
-
- foreach (TItem item in Items)
+ TItem item;
+ if (TryGetValue(key, out item))
{
- if (_comparer.Equals(GetKeyForItem(item), key)) return item;
+ return item;
}
throw new KeyNotFoundException();
@@ -111,6 +102,32 @@ namespace System.Collections.ObjectModel
return false;
}
+ public bool TryGetValue(TKey key, out TItem item)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ if (_dict != null)
+ {
+ return _dict.TryGetValue(key, out item);
+ }
+
+ foreach (TItem itemInItems in Items)
+ {
+ TKey keyInItems = GetKeyForItem(itemInItems);
+ if (keyInItems != null && _comparer.Equals(key, keyInItems))
+ {
+ item = itemInItems;
+ return true;
+ }
+ }
+
+ item = default(TItem);
+ return false;
+ }
+
private bool ContainsItem(TItem item)
{
TKey key;
diff --git a/src/System.ObjectModel/tests/Configurations.props b/src/System.ObjectModel/tests/Configurations.props
index 512c938bad..11a862f330 100644
--- a/src/System.ObjectModel/tests/Configurations.props
+++ b/src/System.ObjectModel/tests/Configurations.props
@@ -4,6 +4,7 @@
<BuildConfigurations>
netstandard1.3;
netstandard1.7;
+ netcoreapp1.1;
</BuildConfigurations>
</PropertyGroup>
</Project>
diff --git a/src/System.ObjectModel/tests/KeyedCollection/TestMethods.cs b/src/System.ObjectModel/tests/KeyedCollection/TestMethods.cs
index b0db1ab235..d0650b474b 100644
--- a/src/System.ObjectModel/tests/KeyedCollection/TestMethods.cs
+++ b/src/System.ObjectModel/tests/KeyedCollection/TestMethods.cs
@@ -9,7 +9,7 @@ using Xunit;
namespace System.Collections.ObjectModel.Tests
{
- public abstract class KeyedCollectionTests<TKey, TValue>
+ public abstract partial class KeyedCollectionTests<TKey, TValue>
where TValue : IComparable<TValue> where TKey : IEquatable<TKey>
{
private static readonly bool s_keyNullable = default(TKey)
diff --git a/src/System.ObjectModel/tests/KeyedCollection/TestMethods.netcoreapp1.1.cs b/src/System.ObjectModel/tests/KeyedCollection/TestMethods.netcoreapp1.1.cs
new file mode 100644
index 0000000000..a1f62ec9fe
--- /dev/null
+++ b/src/System.ObjectModel/tests/KeyedCollection/TestMethods.netcoreapp1.1.cs
@@ -0,0 +1,65 @@
+// 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.Generic;
+using System.Linq;
+using Tests.Collections;
+using Xunit;
+
+namespace System.Collections.ObjectModel.Tests
+{
+ public abstract partial class KeyedCollectionTests<TKey, TValue>
+ {
+ [Theory]
+ [MemberData(nameof(ContainsKeyData))]
+ public void TryGetValue(
+ int collectionSize,
+ Named<KeyedCollectionGetKeyedValue<TKey, TValue>>
+ generateKeyedItem)
+ {
+ TKey[] keys;
+ IKeyedItem<TKey, TValue>[] items;
+ IKeyedItem<TKey, TValue>[] itemsWithKeys;
+ var collection =
+ new TestKeyedCollectionOfIKeyedItem<TKey, TValue>();
+ collection.AddItems(
+ generateKeyedItem.Value.Bind(
+ GenerateValue,
+ GetKeyForItem),
+ ki => ki.Key,
+ collectionSize,
+ out keys,
+ out items,
+ out itemsWithKeys);
+ IKeyedItem<TKey, TValue> itemNotIn =
+ generateKeyedItem.Value(GenerateValue, GetKeyForItem);
+
+ TKey keyNotIn = itemNotIn.Key;
+ if (keyNotIn == null)
+ {
+ IKeyedItem<TKey, TValue> item;
+ Assert.Throws<ArgumentNullException>(
+ () => collection.TryGetValue(keyNotIn, out item));
+ }
+ else
+ {
+ IKeyedItem<TKey, TValue> item;
+ Assert.False(collection.TryGetValue(keyNotIn, out item));
+ }
+ foreach (TKey k in keys)
+ {
+ IKeyedItem<TKey, TValue> item;
+ TKey key = k;
+ if (key == null)
+ {
+ Assert.Throws<ArgumentNullException>(
+ () => collection.TryGetValue(key, out item));
+ continue;
+ }
+ Assert.True(collection.TryGetValue(key, out item));
+ Assert.Equal(item.Key, key);
+ }
+ }
+ }
+}
diff --git a/src/System.ObjectModel/tests/System.ObjectModel.Tests.csproj b/src/System.ObjectModel/tests/System.ObjectModel.Tests.csproj
index 4995c76998..f5447d6b7f 100644
--- a/src/System.ObjectModel/tests/System.ObjectModel.Tests.csproj
+++ b/src/System.ObjectModel/tests/System.ObjectModel.Tests.csproj
@@ -43,6 +43,7 @@
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)'==''">
+ <Compile Include="KeyedCollection\TestMethods.netcoreapp1.1.cs" />
<Compile Include="KeyedCollection\Serialization.netstandard1.7.cs" />
<Compile Include="ObservableCollection\ObservableCollection_ConstructorAndPropertyTests.netstandard1.7.cs" />
<Compile Include="ObservableCollection\ObservableCollection_Serialization.netstandard1.7.cs" />
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs
index 45a46f3810..35ffb9573d 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs
@@ -376,7 +376,7 @@ namespace System.Runtime.Serialization
/// is therefore marked SRR
/// Safe - does not let caller influence isNonAttributedType calculation; no harm in leaking value
/// </SecurityNote>
- static internal bool IsNonAttributedTypeValidForSerialization(Type type)
+ internal static bool IsNonAttributedTypeValidForSerialization(Type type)
{
if (type.IsArray)
return false;
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs
index 3446f1b591..30c3e91bba 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs
@@ -775,7 +775,7 @@ namespace System.Runtime.Serialization
}
}
- static public bool TryCreateBuiltInDataContract(Type type, out DataContract dataContract)
+ public static bool TryCreateBuiltInDataContract(Type type, out DataContract dataContract)
{
if (type.GetTypeInfo().IsEnum) // Type.GetTypeCode will report Enums as TypeCode.IntXX
{
@@ -856,7 +856,7 @@ namespace System.Runtime.Serialization
return dataContract != null;
}
- static public bool TryCreateBuiltInDataContract(string name, string ns, out DataContract dataContract)
+ public static bool TryCreateBuiltInDataContract(string name, string ns, out DataContract dataContract)
{
dataContract = null;
if (ns == DictionaryGlobals.SchemaNamespace.Value)
@@ -1190,7 +1190,7 @@ namespace System.Runtime.Serialization
}
}
- static internal bool IsTypeSerializable(Type type)
+ internal static bool IsTypeSerializable(Type type)
{
return IsTypeSerializable(type, new HashSet<Type>());
}
@@ -1278,7 +1278,7 @@ namespace System.Runtime.Serialization
return true;
}
- static internal string EncodeLocalName(string localName)
+ internal static string EncodeLocalName(string localName)
{
if (IsAsciiLocalName(localName))
return localName;
@@ -1944,7 +1944,7 @@ namespace System.Runtime.Serialization
return typeName.ToString();
}
- static internal bool IsTypeNullable(Type type)
+ internal static bool IsTypeNullable(Type type)
{
return !type.GetTypeInfo().IsValueType ||
(type.GetTypeInfo().IsGenericType &&
@@ -2087,7 +2087,7 @@ namespace System.Runtime.Serialization
/// since this information is used to determine whether to give the generated code access
/// permissions to private members, any changes to the logic should be reviewed.
/// </SecurityNote>
- static internal bool IsTypeVisible(Type t)
+ internal static bool IsTypeVisible(Type t)
{
if (!t.GetTypeInfo().IsVisible && !IsTypeVisibleInSerializationModule(t))
return false;
@@ -2107,7 +2107,7 @@ namespace System.Runtime.Serialization
/// since this information is used to determine whether to give the generated code access
/// permissions to private members, any changes to the logic should be reviewed.
/// </SecurityNote>
- static internal bool ConstructorRequiresMemberAccess(ConstructorInfo ctor)
+ internal static bool ConstructorRequiresMemberAccess(ConstructorInfo ctor)
{
return ctor != null && !ctor.IsPublic && !IsMemberVisibleInSerializationModule(ctor);
}
@@ -2118,7 +2118,7 @@ namespace System.Runtime.Serialization
/// since this information is used to determine whether to give the generated code access
/// permissions to private members, any changes to the logic should be reviewed.
/// </SecurityNote>
- static internal bool MethodRequiresMemberAccess(MethodInfo method)
+ internal static bool MethodRequiresMemberAccess(MethodInfo method)
{
return method != null && !method.IsPublic && !IsMemberVisibleInSerializationModule(method);
}
@@ -2129,7 +2129,7 @@ namespace System.Runtime.Serialization
/// since this information is used to determine whether to give the generated code access
/// permissions to private members, any changes to the logic should be reviewed.
/// </SecurityNote>
- static internal bool FieldRequiresMemberAccess(FieldInfo field)
+ internal static bool FieldRequiresMemberAccess(FieldInfo field)
{
return field != null && !field.IsPublic && !IsMemberVisibleInSerializationModule(field);
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DictionaryGlobals.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DictionaryGlobals.cs
index 1b5d515197..c6d1ee34a0 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DictionaryGlobals.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DictionaryGlobals.cs
@@ -14,43 +14,43 @@ namespace System.Runtime.Serialization
internal static class DictionaryGlobals
#endif
{
- public readonly static XmlDictionaryString EmptyString;
- public readonly static XmlDictionaryString SchemaInstanceNamespace;
- public readonly static XmlDictionaryString SchemaNamespace;
- public readonly static XmlDictionaryString SerializationNamespace;
- public readonly static XmlDictionaryString XmlnsNamespace;
- public readonly static XmlDictionaryString XsiTypeLocalName;
- public readonly static XmlDictionaryString XsiNilLocalName;
- public readonly static XmlDictionaryString ClrTypeLocalName;
- public readonly static XmlDictionaryString ClrAssemblyLocalName;
- public readonly static XmlDictionaryString ArraySizeLocalName;
- public readonly static XmlDictionaryString IdLocalName;
- public readonly static XmlDictionaryString RefLocalName;
- public readonly static XmlDictionaryString ISerializableFactoryTypeLocalName;
- public readonly static XmlDictionaryString CharLocalName;
- public readonly static XmlDictionaryString BooleanLocalName;
- public readonly static XmlDictionaryString SignedByteLocalName;
- public readonly static XmlDictionaryString UnsignedByteLocalName;
- public readonly static XmlDictionaryString ShortLocalName;
- public readonly static XmlDictionaryString UnsignedShortLocalName;
- public readonly static XmlDictionaryString IntLocalName;
- public readonly static XmlDictionaryString UnsignedIntLocalName;
- public readonly static XmlDictionaryString LongLocalName;
- public readonly static XmlDictionaryString UnsignedLongLocalName;
- public readonly static XmlDictionaryString FloatLocalName;
- public readonly static XmlDictionaryString DoubleLocalName;
- public readonly static XmlDictionaryString DecimalLocalName;
- public readonly static XmlDictionaryString DateTimeLocalName;
- public readonly static XmlDictionaryString StringLocalName;
- public readonly static XmlDictionaryString ByteArrayLocalName;
- public readonly static XmlDictionaryString ObjectLocalName;
- public readonly static XmlDictionaryString TimeSpanLocalName;
- public readonly static XmlDictionaryString GuidLocalName;
- public readonly static XmlDictionaryString UriLocalName;
- public readonly static XmlDictionaryString QNameLocalName;
- public readonly static XmlDictionaryString Space;
+ public static readonly XmlDictionaryString EmptyString;
+ public static readonly XmlDictionaryString SchemaInstanceNamespace;
+ public static readonly XmlDictionaryString SchemaNamespace;
+ public static readonly XmlDictionaryString SerializationNamespace;
+ public static readonly XmlDictionaryString XmlnsNamespace;
+ public static readonly XmlDictionaryString XsiTypeLocalName;
+ public static readonly XmlDictionaryString XsiNilLocalName;
+ public static readonly XmlDictionaryString ClrTypeLocalName;
+ public static readonly XmlDictionaryString ClrAssemblyLocalName;
+ public static readonly XmlDictionaryString ArraySizeLocalName;
+ public static readonly XmlDictionaryString IdLocalName;
+ public static readonly XmlDictionaryString RefLocalName;
+ public static readonly XmlDictionaryString ISerializableFactoryTypeLocalName;
+ public static readonly XmlDictionaryString CharLocalName;
+ public static readonly XmlDictionaryString BooleanLocalName;
+ public static readonly XmlDictionaryString SignedByteLocalName;
+ public static readonly XmlDictionaryString UnsignedByteLocalName;
+ public static readonly XmlDictionaryString ShortLocalName;
+ public static readonly XmlDictionaryString UnsignedShortLocalName;
+ public static readonly XmlDictionaryString IntLocalName;
+ public static readonly XmlDictionaryString UnsignedIntLocalName;
+ public static readonly XmlDictionaryString LongLocalName;
+ public static readonly XmlDictionaryString UnsignedLongLocalName;
+ public static readonly XmlDictionaryString FloatLocalName;
+ public static readonly XmlDictionaryString DoubleLocalName;
+ public static readonly XmlDictionaryString DecimalLocalName;
+ public static readonly XmlDictionaryString DateTimeLocalName;
+ public static readonly XmlDictionaryString StringLocalName;
+ public static readonly XmlDictionaryString ByteArrayLocalName;
+ public static readonly XmlDictionaryString ObjectLocalName;
+ public static readonly XmlDictionaryString TimeSpanLocalName;
+ public static readonly XmlDictionaryString GuidLocalName;
+ public static readonly XmlDictionaryString UriLocalName;
+ public static readonly XmlDictionaryString QNameLocalName;
+ public static readonly XmlDictionaryString Space;
- public readonly static XmlDictionaryString hexBinaryLocalName;
+ public static readonly XmlDictionaryString hexBinaryLocalName;
static DictionaryGlobals()
{
// Update array size when adding new strings or templates
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/EnumDataContract.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/EnumDataContract.cs
index 61e88b99cd..9ce7940e60 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/EnumDataContract.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/EnumDataContract.cs
@@ -101,7 +101,7 @@ namespace System.Runtime.Serialization
Add(typeof(ulong), "unsignedLong");
}
- static internal void Add(Type type, string localName)
+ internal static void Add(Type type, string localName)
{
XmlQualifiedName stableName = CreateQualifiedName(localName, Globals.SchemaNamespace);
s_typeToName.Add(type, stableName);
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs
index 0797e9d7f2..ae8b03b311 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs
@@ -906,7 +906,7 @@ namespace System.Runtime.Serialization
public const bool DefaultIsReference = false;
// The value string.Empty aids comparisons (can do simple length checks
// instead of string comparison method calls in IL.)
- public readonly static string NewObjectId = string.Empty;
+ public static readonly string NewObjectId = string.Empty;
public const string NullObjectId = null;
public const string SimpleSRSInternalsVisiblePattern = @"^[\s]*System\.Runtime\.Serialization[\s]*$";
public const string FullSRSInternalsVisiblePattern = @"^[\s]*System\.Runtime\.Serialization[\s]*,[\s]*PublicKey[\s]*=[\s]*(?i:00240000048000009400000006020000002400005253413100040000010001008d56c76f9e8649383049f383c44be0ec204181822a6c31cf5eb7ef486944d032188ea1d3920763712ccb12d75fb77e9811149e6148e5d32fbaab37611c1878ddc19e20ef135d0cb2cff2bfec3d115810c3d9069638fe4be215dbf795861920e5ab6f7db2e2ceef136ac23d5dd2bf031700aec232f6c6b1c785b4305c123b37ab)[\s]*$";
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ByteArrayHelperWithString.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ByteArrayHelperWithString.cs
index bcf0fd6b1e..01e861b099 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ByteArrayHelperWithString.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ByteArrayHelperWithString.cs
@@ -11,7 +11,7 @@ namespace System.Runtime.Serialization.Json
{
internal class ByteArrayHelperWithString : ArrayHelper<string, byte>
{
- static public readonly ByteArrayHelperWithString Instance = new ByteArrayHelperWithString();
+ public static readonly ByteArrayHelperWithString Instance = new ByteArrayHelperWithString();
internal void WriteArray(XmlWriter writer, byte[] array, int offset, int count)
{
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs
index 51f8081b2b..ee36e95293 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs
@@ -247,7 +247,7 @@ namespace System.Runtime.Serialization.Json
return knownTypesList;
}
- static internal void InvokeOnSerializing(Object value, DataContract contract, XmlObjectSerializerWriteContextComplexJson context)
+ internal static void InvokeOnSerializing(Object value, DataContract contract, XmlObjectSerializerWriteContextComplexJson context)
{
if (contract is ClassDataContract)
{
@@ -285,7 +285,7 @@ namespace System.Runtime.Serialization.Json
}
}
- static internal void InvokeOnSerialized(Object value, DataContract contract, XmlObjectSerializerWriteContextComplexJson context)
+ internal static void InvokeOnSerialized(Object value, DataContract contract, XmlObjectSerializerWriteContextComplexJson context)
{
if (contract is ClassDataContract)
{
@@ -323,7 +323,7 @@ namespace System.Runtime.Serialization.Json
}
}
- static internal void InvokeOnDeserializing(Object value, DataContract contract, XmlObjectSerializerReadContextComplexJson context)
+ internal static void InvokeOnDeserializing(Object value, DataContract contract, XmlObjectSerializerReadContextComplexJson context)
{
if (contract is ClassDataContract)
{
@@ -361,7 +361,7 @@ namespace System.Runtime.Serialization.Json
}
}
- static internal void InvokeOnDeserialized(object value, DataContract contract, XmlObjectSerializerReadContextComplexJson context)
+ internal static void InvokeOnDeserialized(object value, DataContract contract, XmlObjectSerializerReadContextComplexJson context)
{
if (contract is ClassDataContract)
{
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/PrimitiveDataContract.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/PrimitiveDataContract.cs
index 1f691a1aeb..7dc0764e44 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/PrimitiveDataContract.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/PrimitiveDataContract.cs
@@ -26,12 +26,12 @@ namespace System.Runtime.Serialization
_helper = base.Helper as PrimitiveDataContractCriticalHelper;
}
- static internal PrimitiveDataContract GetPrimitiveDataContract(Type type)
+ internal static PrimitiveDataContract GetPrimitiveDataContract(Type type)
{
return DataContract.GetBuiltInDataContract(type) as PrimitiveDataContract;
}
- static internal PrimitiveDataContract GetPrimitiveDataContract(string name, string ns)
+ internal static PrimitiveDataContract GetPrimitiveDataContract(string name, string ns)
{
return DataContract.GetBuiltInDataContract(name, ns) as PrimitiveDataContract;
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionClassWriter.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionClassWriter.cs
index 2694043982..451d34404c 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionClassWriter.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionClassWriter.cs
@@ -21,7 +21,15 @@ namespace System.Runtime.Serialization
{
InvokeOnSerializing(obj, context, classContract);
obj = ResolveAdapterType(obj, classContract);
- ReflectionWriteMembers(xmlWriter, obj, context, classContract, classContract, 0 /*childElementIndex*/, memberNames);
+ if (classContract.IsISerializable)
+ {
+ context.WriteISerializable(xmlWriter, (ISerializable) obj);
+ }
+ else
+ {
+ ReflectionWriteMembers(xmlWriter, obj, context, classContract, classContract, 0 /*childElementIndex*/, memberNames);
+ }
+
InvokeOnSerialized(obj, context, classContract);
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionReader.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionReader.cs
index a18c79d8ba..5ba5edcd01 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionReader.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ReflectionReader.cs
@@ -20,12 +20,12 @@ namespace System.Runtime.Serialization
private delegate object CollectionReadItemDelegate(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, CollectionDataContract collectionContract, Type itemType, string itemName, string itemNs);
private delegate object CollectionSetItemDelegate(object resultCollection, object collectionItem, int itemIndex);
- private readonly static MethodInfo s_getCollectionSetItemDelegateMethod = typeof(ReflectionReader).GetMethod(nameof(GetCollectionSetItemDelegate), BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
- private readonly static MethodInfo s_objectToKeyValuePairGetKey = typeof(ReflectionReader).GetMethod(nameof(ObjectToKeyValuePairGetKey), BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
- private readonly static MethodInfo s_objectToKeyValuePairGetValue = typeof(ReflectionReader).GetMethod(nameof(ObjectToKeyValuePairGetValue), BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
+ private static readonly MethodInfo s_getCollectionSetItemDelegateMethod = typeof(ReflectionReader).GetMethod(nameof(GetCollectionSetItemDelegate), BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
+ private static readonly MethodInfo s_objectToKeyValuePairGetKey = typeof(ReflectionReader).GetMethod(nameof(ObjectToKeyValuePairGetKey), BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
+ private static readonly MethodInfo s_objectToKeyValuePairGetValue = typeof(ReflectionReader).GetMethod(nameof(ObjectToKeyValuePairGetValue), BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
- private readonly static Type[] s_arrayConstructorParameters = new Type[] { Globals.TypeOfInt };
- private readonly static object[] s_arrayConstructorArguments = new object[] { 32 };
+ private static readonly Type[] s_arrayConstructorParameters = new Type[] { Globals.TypeOfInt };
+ private static readonly object[] s_arrayConstructorArguments = new object[] { 32 };
public object ReflectionReadClass(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces, ClassDataContract classContract)
{
@@ -33,7 +33,15 @@ namespace System.Runtime.Serialization
context.AddNewObject(obj);
InvokeOnDeserializing(context, classContract, obj);
- ReflectionReadMembers(xmlReader, context, memberNames, memberNamespaces, classContract, ref obj);
+ if (classContract.IsISerializable)
+ {
+ obj = ReadISerializable(xmlReader, context, classContract);
+ }
+ else
+ {
+ ReflectionReadMembers(xmlReader, context, memberNames, memberNamespaces, classContract, ref obj);
+ }
+
obj = ResolveAdapterObject(obj, classContract);
InvokeDeserializationCallback(obj);
InvokeOnDeserialized(context, classContract, obj);
@@ -279,6 +287,16 @@ namespace System.Runtime.Serialization
return value;
}
+ private static object ReadISerializable(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, ClassDataContract classContract)
+ {
+ object obj;
+ SerializationInfo serializationInfo = context.ReadSerializationInfo(xmlReader, classContract.UnderlyingType);
+ StreamingContext streamingContext = context.GetStreamingContext();
+ ConstructorInfo iSerializableConstructor = classContract.GetISerializableConstructor();
+ obj = iSerializableConstructor.Invoke(new object[] { serializationInfo, streamingContext });
+ return obj;
+ }
+
// This method is a perf optimization for collections. The original method is ReflectionReadValue.
private CollectionReadItemDelegate GetReflectionReadValueDelegate(Type type)
{
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs
index b10c00d9b3..a771363961 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs
@@ -31,16 +31,6 @@ namespace System.Runtime.Serialization
internal sealed class XmlFormatReaderGenerator
#endif
{
- private static readonly Func<Type, object> s_getUninitializedObjectDelegate = (Func<Type, object>)
- typeof(string)
- .GetTypeInfo()
- .Assembly
- .GetType("System.Runtime.Serialization.FormatterServices")
- ?.GetMethod("GetUninitializedObject", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)
- ?.CreateDelegate(typeof(Func<Type, object>));
-
- private static readonly ConcurrentDictionary<Type, bool> s_typeHasDefaultConstructorMap = new ConcurrentDictionary<Type, bool>();
-
private CriticalHelper _helper;
public XmlFormatReaderGenerator()
@@ -937,17 +927,10 @@ namespace System.Runtime.Serialization
#endif
}
- static internal object UnsafeGetUninitializedObject(Type type)
+ internal static object UnsafeGetUninitializedObject(Type type)
{
#if !NET_NATIVE
- if (type.GetTypeInfo().IsValueType)
- {
- return Activator.CreateInstance(type);
- }
-
- const BindingFlags Flags = BindingFlags.Public | BindingFlags.Instance;
- bool hasDefaultConstructor = s_typeHasDefaultConstructorMap.GetOrAdd(type, t => t.GetConstructor(Flags, Array.Empty<Type>()) != null);
- return hasDefaultConstructor ? Activator.CreateInstance(type) : TryGetUninitializedObjectWithFormatterServices(type) ?? Activator.CreateInstance(type);
+ return FormatterServices.GetUninitializedObject(type);
#else
return RuntimeAugments.NewObject(type.TypeHandle);
#endif
@@ -961,14 +944,11 @@ namespace System.Runtime.Serialization
#if USE_REFEMIT
public static object UnsafeGetUninitializedObject(int id)
#else
- static internal object UnsafeGetUninitializedObject(int id)
+ internal static object UnsafeGetUninitializedObject(int id)
#endif
{
var type = DataContract.GetDataContractForInitialization(id).TypeForInitialization;
return UnsafeGetUninitializedObject(type);
}
-
- static internal object TryGetUninitializedObjectWithFormatterServices(Type type) =>
- s_getUninitializedObjectDelegate?.Invoke(type);
}
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializer.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializer.cs
index 47769611f9..e0372f22f0 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializer.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializer.cs
@@ -368,13 +368,13 @@ namespace System.Runtime.Serialization
return XmlObjectSerializer.CreateSerializationException(TryAddLineInfo(reader, SR.Format(SR.EncounteredWithNameNamespace, errorMessage, reader.NodeType, reader.LocalName, reader.NamespaceURI)));
}
- static internal SerializationException CreateSerializationException(string errorMessage)
+ internal static SerializationException CreateSerializationException(string errorMessage)
{
return XmlObjectSerializer.CreateSerializationException(errorMessage, null);
}
[MethodImpl(MethodImplOptions.NoInlining)]
- static internal SerializationException CreateSerializationException(string errorMessage, Exception innerException)
+ internal static SerializationException CreateSerializationException(string errorMessage, Exception innerException)
{
return new SerializationException(errorMessage, innerException);
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XsdDataContractExporter.cs b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XsdDataContractExporter.cs
index befbef5e7f..1129e41d59 100644
--- a/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XsdDataContractExporter.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XsdDataContractExporter.cs
@@ -58,11 +58,7 @@ namespace System.Runtime.Serialization
{
get
{
- //if (dataContractSet == null)
- //{
- // dataContractSet = new DataContractSet((Options == null) ? null : Options.GetSurrogate());
- //}
- return _dataContractSet;
+ throw new PlatformNotSupportedException();
}
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Text/Base64Encoding.cs b/src/System.Private.DataContractSerialization/src/System/Text/Base64Encoding.cs
index fdc11d1921..c01c2a71e1 100644
--- a/src/System.Private.DataContractSerialization/src/System/Text/Base64Encoding.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Text/Base64Encoding.cs
@@ -53,7 +53,7 @@ namespace System.Text
return !(v3 == 64 && v4 != 64);
}
- unsafe public override int GetByteCount(char[] chars, int index, int count)
+ public unsafe override int GetByteCount(char[] chars, int index, int count)
{
if (chars == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(chars)));
@@ -107,7 +107,7 @@ namespace System.Text
}
}
- unsafe public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ public unsafe override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
if (chars == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(chars)));
@@ -186,7 +186,7 @@ namespace System.Text
}
}
- unsafe public virtual int GetBytes(byte[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ public unsafe virtual int GetBytes(byte[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
if (chars == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(chars)));
@@ -274,7 +274,7 @@ namespace System.Text
return GetMaxCharCount(count);
}
- unsafe public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
+ public unsafe override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
{
if (bytes == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bytes)));
@@ -363,7 +363,7 @@ namespace System.Text
return charCount;
}
- unsafe public int GetChars(byte[] bytes, int byteIndex, int byteCount, byte[] chars, int charIndex)
+ public unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, byte[] chars, int charIndex)
{
if (bytes == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bytes)));
diff --git a/src/System.Private.DataContractSerialization/src/System/Text/BinHexEncoding.cs b/src/System.Private.DataContractSerialization/src/System/Text/BinHexEncoding.cs
index 4e43450060..c89012898e 100644
--- a/src/System.Private.DataContractSerialization/src/System/Text/BinHexEncoding.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Text/BinHexEncoding.cs
@@ -45,7 +45,7 @@ namespace System.Text
return GetMaxByteCount(count);
}
- unsafe public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ public unsafe override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
if (chars == null)
throw new ArgumentNullException(nameof(chars));
@@ -115,7 +115,7 @@ namespace System.Text
return GetMaxCharCount(count);
}
- unsafe public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
+ public unsafe override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
{
if (bytes == null)
throw new ArgumentNullException(nameof(bytes));
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/ArrayHelper.cs b/src/System.Private.DataContractSerialization/src/System/Xml/ArrayHelper.cs
index 9482787236..7f836b793e 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/ArrayHelper.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/ArrayHelper.cs
@@ -97,7 +97,7 @@ namespace System.Xml
internal class BooleanArrayHelperWithString : ArrayHelper<string, bool>
{
- static public readonly BooleanArrayHelperWithString Instance = new BooleanArrayHelperWithString();
+ public static readonly BooleanArrayHelperWithString Instance = new BooleanArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, bool[] array, int offset, int count)
{
@@ -112,7 +112,7 @@ namespace System.Xml
internal class BooleanArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, bool>
{
- static public readonly BooleanArrayHelperWithDictionaryString Instance = new BooleanArrayHelperWithDictionaryString();
+ public static readonly BooleanArrayHelperWithDictionaryString Instance = new BooleanArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, bool[] array, int offset, int count)
{
@@ -127,7 +127,7 @@ namespace System.Xml
internal class Int16ArrayHelperWithString : ArrayHelper<string, Int16>
{
- static public readonly Int16ArrayHelperWithString Instance = new Int16ArrayHelperWithString();
+ public static readonly Int16ArrayHelperWithString Instance = new Int16ArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, Int16[] array, int offset, int count)
{
@@ -142,7 +142,7 @@ namespace System.Xml
internal class Int16ArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, Int16>
{
- static public readonly Int16ArrayHelperWithDictionaryString Instance = new Int16ArrayHelperWithDictionaryString();
+ public static readonly Int16ArrayHelperWithDictionaryString Instance = new Int16ArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int16[] array, int offset, int count)
{
@@ -157,7 +157,7 @@ namespace System.Xml
internal class Int32ArrayHelperWithString : ArrayHelper<string, Int32>
{
- static public readonly Int32ArrayHelperWithString Instance = new Int32ArrayHelperWithString();
+ public static readonly Int32ArrayHelperWithString Instance = new Int32ArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, Int32[] array, int offset, int count)
{
@@ -172,7 +172,7 @@ namespace System.Xml
internal class Int32ArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, Int32>
{
- static public readonly Int32ArrayHelperWithDictionaryString Instance = new Int32ArrayHelperWithDictionaryString();
+ public static readonly Int32ArrayHelperWithDictionaryString Instance = new Int32ArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int32[] array, int offset, int count)
{
@@ -187,7 +187,7 @@ namespace System.Xml
internal class Int64ArrayHelperWithString : ArrayHelper<string, Int64>
{
- static public readonly Int64ArrayHelperWithString Instance = new Int64ArrayHelperWithString();
+ public static readonly Int64ArrayHelperWithString Instance = new Int64ArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, Int64[] array, int offset, int count)
{
@@ -202,7 +202,7 @@ namespace System.Xml
internal class Int64ArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, Int64>
{
- static public readonly Int64ArrayHelperWithDictionaryString Instance = new Int64ArrayHelperWithDictionaryString();
+ public static readonly Int64ArrayHelperWithDictionaryString Instance = new Int64ArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int64[] array, int offset, int count)
{
@@ -217,7 +217,7 @@ namespace System.Xml
internal class SingleArrayHelperWithString : ArrayHelper<string, float>
{
- static public readonly SingleArrayHelperWithString Instance = new SingleArrayHelperWithString();
+ public static readonly SingleArrayHelperWithString Instance = new SingleArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, float[] array, int offset, int count)
{
@@ -232,7 +232,7 @@ namespace System.Xml
internal class SingleArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, float>
{
- static public readonly SingleArrayHelperWithDictionaryString Instance = new SingleArrayHelperWithDictionaryString();
+ public static readonly SingleArrayHelperWithDictionaryString Instance = new SingleArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count)
{
@@ -247,7 +247,7 @@ namespace System.Xml
internal class DoubleArrayHelperWithString : ArrayHelper<string, double>
{
- static public readonly DoubleArrayHelperWithString Instance = new DoubleArrayHelperWithString();
+ public static readonly DoubleArrayHelperWithString Instance = new DoubleArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, double[] array, int offset, int count)
{
@@ -262,7 +262,7 @@ namespace System.Xml
internal class DoubleArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, double>
{
- static public readonly DoubleArrayHelperWithDictionaryString Instance = new DoubleArrayHelperWithDictionaryString();
+ public static readonly DoubleArrayHelperWithDictionaryString Instance = new DoubleArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count)
{
@@ -277,7 +277,7 @@ namespace System.Xml
internal class DecimalArrayHelperWithString : ArrayHelper<string, decimal>
{
- static public readonly DecimalArrayHelperWithString Instance = new DecimalArrayHelperWithString();
+ public static readonly DecimalArrayHelperWithString Instance = new DecimalArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, decimal[] array, int offset, int count)
{
@@ -292,7 +292,7 @@ namespace System.Xml
internal class DecimalArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, decimal>
{
- static public readonly DecimalArrayHelperWithDictionaryString Instance = new DecimalArrayHelperWithDictionaryString();
+ public static readonly DecimalArrayHelperWithDictionaryString Instance = new DecimalArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count)
{
@@ -307,7 +307,7 @@ namespace System.Xml
internal class DateTimeArrayHelperWithString : ArrayHelper<string, DateTime>
{
- static public readonly DateTimeArrayHelperWithString Instance = new DateTimeArrayHelperWithString();
+ public static readonly DateTimeArrayHelperWithString Instance = new DateTimeArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, DateTime[] array, int offset, int count)
{
@@ -322,7 +322,7 @@ namespace System.Xml
internal class DateTimeArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, DateTime>
{
- static public readonly DateTimeArrayHelperWithDictionaryString Instance = new DateTimeArrayHelperWithDictionaryString();
+ public static readonly DateTimeArrayHelperWithDictionaryString Instance = new DateTimeArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, DateTime[] array, int offset, int count)
{
@@ -337,7 +337,7 @@ namespace System.Xml
internal class GuidArrayHelperWithString : ArrayHelper<string, Guid>
{
- static public readonly GuidArrayHelperWithString Instance = new GuidArrayHelperWithString();
+ public static readonly GuidArrayHelperWithString Instance = new GuidArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, Guid[] array, int offset, int count)
{
@@ -352,7 +352,7 @@ namespace System.Xml
internal class GuidArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, Guid>
{
- static public readonly GuidArrayHelperWithDictionaryString Instance = new GuidArrayHelperWithDictionaryString();
+ public static readonly GuidArrayHelperWithDictionaryString Instance = new GuidArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Guid[] array, int offset, int count)
{
@@ -367,7 +367,7 @@ namespace System.Xml
internal class TimeSpanArrayHelperWithString : ArrayHelper<string, TimeSpan>
{
- static public readonly TimeSpanArrayHelperWithString Instance = new TimeSpanArrayHelperWithString();
+ public static readonly TimeSpanArrayHelperWithString Instance = new TimeSpanArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, TimeSpan[] array, int offset, int count)
{
@@ -382,7 +382,7 @@ namespace System.Xml
internal class TimeSpanArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, TimeSpan>
{
- static public readonly TimeSpanArrayHelperWithDictionaryString Instance = new TimeSpanArrayHelperWithDictionaryString();
+ public static readonly TimeSpanArrayHelperWithDictionaryString Instance = new TimeSpanArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, TimeSpan[] array, int offset, int count)
{
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/EncodingStreamWrapper.cs b/src/System.Private.DataContractSerialization/src/System/Xml/EncodingStreamWrapper.cs
index 6e71e7b7f0..93054af22e 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/EncodingStreamWrapper.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/EncodingStreamWrapper.cs
@@ -596,7 +596,11 @@ namespace System.Xml
protected override void Dispose(bool disposing)
{
- Flush();
+ if (_stream.CanWrite)
+ {
+ Flush();
+ }
+
_stream.Dispose();
base.Dispose(disposing);
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/PrefixHandle.cs b/src/System.Private.DataContractSerialization/src/System/Xml/PrefixHandle.cs
index 9af09b26d5..70400316ae 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/PrefixHandle.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/PrefixHandle.cs
@@ -206,32 +206,32 @@ namespace System.Xml
{
return Equals2(prefix2.Value);
}
- static public bool operator ==(PrefixHandle prefix1, string prefix2)
+ public static bool operator ==(PrefixHandle prefix1, string prefix2)
{
return prefix1.Equals2(prefix2);
}
- static public bool operator !=(PrefixHandle prefix1, string prefix2)
+ public static bool operator !=(PrefixHandle prefix1, string prefix2)
{
return !prefix1.Equals2(prefix2);
}
- static public bool operator ==(PrefixHandle prefix1, XmlDictionaryString prefix2)
+ public static bool operator ==(PrefixHandle prefix1, XmlDictionaryString prefix2)
{
return prefix1.Equals2(prefix2);
}
- static public bool operator !=(PrefixHandle prefix1, XmlDictionaryString prefix2)
+ public static bool operator !=(PrefixHandle prefix1, XmlDictionaryString prefix2)
{
return !prefix1.Equals2(prefix2);
}
- static public bool operator ==(PrefixHandle prefix1, PrefixHandle prefix2)
+ public static bool operator ==(PrefixHandle prefix1, PrefixHandle prefix2)
{
return prefix1.Equals(prefix2);
}
- static public bool operator !=(PrefixHandle prefix1, PrefixHandle prefix2)
+ public static bool operator !=(PrefixHandle prefix1, PrefixHandle prefix2)
{
return !prefix1.Equals(prefix2);
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/StringHandle.cs b/src/System.Private.DataContractSerialization/src/System/Xml/StringHandle.cs
index 614825083c..8199e30baf 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/StringHandle.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/StringHandle.cs
@@ -240,31 +240,31 @@ namespace System.Xml
return Equals2(other.GetString());
}
- static public bool operator ==(StringHandle s1, XmlDictionaryString xmlString2)
+ public static bool operator ==(StringHandle s1, XmlDictionaryString xmlString2)
{
return s1.Equals2(xmlString2);
}
- static public bool operator !=(StringHandle s1, XmlDictionaryString xmlString2)
+ public static bool operator !=(StringHandle s1, XmlDictionaryString xmlString2)
{
return !s1.Equals2(xmlString2);
}
- static public bool operator ==(StringHandle s1, string s2)
+ public static bool operator ==(StringHandle s1, string s2)
{
return s1.Equals2(s2);
}
- static public bool operator !=(StringHandle s1, string s2)
+ public static bool operator !=(StringHandle s1, string s2)
{
return !s1.Equals2(s2);
}
- static public bool operator ==(StringHandle s1, StringHandle s2)
+ public static bool operator ==(StringHandle s1, StringHandle s2)
{
return s1.Equals(s2);
}
- static public bool operator !=(StringHandle s1, StringHandle s2)
+ public static bool operator !=(StringHandle s1, StringHandle s2)
{
return !s1.Equals(s2);
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs b/src/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs
index 9e9474fc44..0c2a6a8ed7 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs
@@ -63,7 +63,7 @@ namespace System.Xml
{
}
- unsafe public UniqueId(byte[] guid, int offset)
+ public unsafe UniqueId(byte[] guid, int offset)
{
if (guid == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(guid)));
@@ -80,7 +80,7 @@ namespace System.Xml
}
}
- unsafe public UniqueId(string value)
+ public unsafe UniqueId(string value)
{
if (value == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(value));
@@ -93,7 +93,7 @@ namespace System.Xml
_s = value;
}
- unsafe public UniqueId(char[] chars, int offset, int count)
+ public unsafe UniqueId(char[] chars, int offset, int count)
{
if (chars == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(chars)));
@@ -199,7 +199,7 @@ namespace System.Xml
}
}
- unsafe public int ToCharArray(char[] chars, int offset)
+ public unsafe int ToCharArray(char[] chars, int offset)
{
int count = CharArrayLength;
@@ -280,7 +280,7 @@ namespace System.Xml
return true;
}
- unsafe public bool TryGetGuid(byte[] buffer, int offset)
+ public unsafe bool TryGetGuid(byte[] buffer, int offset)
{
if (!IsGuid)
return false;
@@ -305,7 +305,7 @@ namespace System.Xml
return true;
}
- unsafe public override string ToString()
+ public unsafe override string ToString()
{
if (_s == null)
{
@@ -317,7 +317,7 @@ namespace System.Xml
return _s;
}
- static public bool operator ==(UniqueId id1, UniqueId id2)
+ public static bool operator ==(UniqueId id1, UniqueId id2)
{
if (object.ReferenceEquals(id1, id2))
return true;
@@ -334,7 +334,7 @@ namespace System.Xml
return id1.ToString() == id2.ToString();
}
- static public bool operator !=(UniqueId id1, UniqueId id2)
+ public static bool operator !=(UniqueId id1, UniqueId id2)
{
return !(id1 == id2);
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlBaseReader.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlBaseReader.cs
index 17c62d7ea7..54606d92e1 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlBaseReader.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlBaseReader.cs
@@ -2573,7 +2573,7 @@ namespace System.Xml
_lang = string.Empty;
}
- static public Namespace XmlNamespace
+ public static Namespace XmlNamespace
{
get
{
@@ -2597,7 +2597,7 @@ namespace System.Xml
}
}
- static public Namespace EmptyNamespace
+ public static Namespace EmptyNamespace
{
get
{
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryWriter.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryWriter.cs
index 82e3224245..17d6baa8b4 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryWriter.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlBinaryWriter.cs
@@ -603,7 +603,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteText(string value)
+ public unsafe override void WriteText(string value)
{
if (_inAttribute)
{
@@ -625,7 +625,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteText(char[] chars, int offset, int count)
+ public unsafe override void WriteText(char[] chars, int offset, int count)
{
if (_inAttribute)
{
@@ -747,7 +747,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteFloatText(float f)
+ public unsafe override void WriteFloatText(float f)
{
long l;
if (f >= long.MinValue && f <= long.MaxValue && (l = (long)f) == f)
@@ -768,7 +768,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteDoubleText(double d)
+ public unsafe override void WriteDoubleText(double d)
{
float f;
if (d >= float.MinValue && d <= float.MaxValue && (f = (float)d) == d)
@@ -793,7 +793,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteDecimalText(decimal d)
+ public unsafe override void WriteDecimalText(decimal d)
{
int offset;
byte[] buffer = GetTextNodeBuffer(1 + sizeof(decimal), out offset);
@@ -891,7 +891,7 @@ namespace System.Xml
WriteMultiByteInt32(count);
}
- unsafe public void UnsafeWriteArray(XmlBinaryNodeType nodeType, int count, byte* array, byte* arrayMax)
+ public unsafe void UnsafeWriteArray(XmlBinaryNodeType nodeType, int count, byte* array, byte* arrayMax)
{
WriteArrayInfo(nodeType, count);
UnsafeWriteArray(array, (int)(arrayMax - array));
@@ -1220,7 +1220,7 @@ namespace System.Xml
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.SizeExceedsRemainingBufferSpace, array.Length - offset)));
}
- unsafe public override void WriteArray(string prefix, string localName, string namespaceUri, bool[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, string localName, string namespaceUri, bool[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1234,7 +1234,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, bool[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, bool[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1248,7 +1248,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, string localName, string namespaceUri, Int16[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, string localName, string namespaceUri, Int16[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1262,7 +1262,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int16[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int16[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1276,7 +1276,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, string localName, string namespaceUri, Int32[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, string localName, string namespaceUri, Int32[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1290,7 +1290,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int32[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int32[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1304,7 +1304,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, string localName, string namespaceUri, Int64[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, string localName, string namespaceUri, Int64[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1318,7 +1318,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int64[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int64[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1332,7 +1332,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, string localName, string namespaceUri, float[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, string localName, string namespaceUri, float[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1346,7 +1346,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1360,7 +1360,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, string localName, string namespaceUri, double[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, string localName, string namespaceUri, double[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1374,7 +1374,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1388,7 +1388,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, string localName, string namespaceUri, decimal[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, string localName, string namespaceUri, decimal[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
@@ -1402,7 +1402,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count)
+ public unsafe override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count)
{
{
CheckArray(array, offset, count);
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs
index 9e71fda0cc..1891fcf49f 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlBufferReader.cs
@@ -46,7 +46,7 @@ namespace System.Xml
_buffer = buffer;
}
- static public XmlBufferReader Empty
+ public static XmlBufferReader Empty
{
get
{
@@ -389,7 +389,7 @@ namespace System.Xml
return (hi << 32) + lo;
}
- unsafe public float ReadSingle()
+ public unsafe float ReadSingle()
{
int offset;
byte[] buffer = GetBuffer(ValueHandleLength.Single, out offset);
@@ -404,7 +404,7 @@ namespace System.Xml
return value;
}
- unsafe public double ReadDouble()
+ public unsafe double ReadDouble()
{
int offset;
byte[] buffer = GetBuffer(ValueHandleLength.Double, out offset);
@@ -423,7 +423,7 @@ namespace System.Xml
return value;
}
- unsafe public decimal ReadDecimal()
+ public unsafe decimal ReadDecimal()
{
int offset;
byte[] buffer = GetBuffer(ValueHandleLength.Decimal, out offset);
@@ -508,7 +508,7 @@ namespace System.Xml
return value;
}
- unsafe public void UnsafeReadArray(byte* dst, byte* dstMax)
+ public unsafe void UnsafeReadArray(byte* dst, byte* dstMax)
{
UnsafeReadArray(dst, (int)(dstMax - dst));
}
@@ -921,7 +921,7 @@ namespace System.Xml
return true;
}
- unsafe public bool Equals2(int offset1, int length1, string s2)
+ public unsafe bool Equals2(int offset1, int length1, string s2)
{
int byteLength = length1;
int charLength = s2.Length;
@@ -1039,7 +1039,7 @@ namespace System.Xml
return (ulong)GetInt64(offset);
}
- unsafe public float GetSingle(int offset)
+ public unsafe float GetSingle(int offset)
{
byte[] buffer = _buffer;
float value;
@@ -1052,7 +1052,7 @@ namespace System.Xml
return value;
}
- unsafe public double GetDouble(int offset)
+ public unsafe double GetDouble(int offset)
{
byte[] buffer = _buffer;
double value;
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs
index 637372e975..86c925e108 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs
@@ -36,7 +36,7 @@ namespace System.Xml
private static Base64Encoding s_base64Encoding;
- static public Base64Encoding Base64Encoding
+ public static Base64Encoding Base64Encoding
{
get
{
@@ -66,7 +66,7 @@ namespace System.Xml
}
}
- static public bool ToBoolean(string value)
+ public static bool ToBoolean(string value)
{
try
{
@@ -82,7 +82,7 @@ namespace System.Xml
}
}
- static public bool ToBoolean(byte[] buffer, int offset, int count)
+ public static bool ToBoolean(byte[] buffer, int offset, int count)
{
if (count == 1)
{
@@ -95,7 +95,7 @@ namespace System.Xml
return ToBoolean(ToString(buffer, offset, count));
}
- static public int ToInt32(string value)
+ public static int ToInt32(string value)
{
try
{
@@ -115,7 +115,7 @@ namespace System.Xml
}
}
- static public int ToInt32(byte[] buffer, int offset, int count)
+ public static int ToInt32(byte[] buffer, int offset, int count)
{
int value;
if (TryParseInt32(buffer, offset, count, out value))
@@ -123,7 +123,7 @@ namespace System.Xml
return ToInt32(ToString(buffer, offset, count));
}
- static public Int64 ToInt64(string value)
+ public static Int64 ToInt64(string value)
{
try
{
@@ -143,7 +143,7 @@ namespace System.Xml
}
}
- static public Int64 ToInt64(byte[] buffer, int offset, int count)
+ public static Int64 ToInt64(byte[] buffer, int offset, int count)
{
long value;
if (TryParseInt64(buffer, offset, count, out value))
@@ -151,7 +151,7 @@ namespace System.Xml
return ToInt64(ToString(buffer, offset, count));
}
- static public float ToSingle(string value)
+ public static float ToSingle(string value)
{
try
{
@@ -171,7 +171,7 @@ namespace System.Xml
}
}
- static public float ToSingle(byte[] buffer, int offset, int count)
+ public static float ToSingle(byte[] buffer, int offset, int count)
{
float value;
if (TryParseSingle(buffer, offset, count, out value))
@@ -179,7 +179,7 @@ namespace System.Xml
return ToSingle(ToString(buffer, offset, count));
}
- static public double ToDouble(string value)
+ public static double ToDouble(string value)
{
try
{
@@ -199,7 +199,7 @@ namespace System.Xml
}
}
- static public double ToDouble(byte[] buffer, int offset, int count)
+ public static double ToDouble(byte[] buffer, int offset, int count)
{
double value;
if (TryParseDouble(buffer, offset, count, out value))
@@ -207,7 +207,7 @@ namespace System.Xml
return ToDouble(ToString(buffer, offset, count));
}
- static public decimal ToDecimal(string value)
+ public static decimal ToDecimal(string value)
{
try
{
@@ -227,12 +227,12 @@ namespace System.Xml
}
}
- static public decimal ToDecimal(byte[] buffer, int offset, int count)
+ public static decimal ToDecimal(byte[] buffer, int offset, int count)
{
return ToDecimal(ToString(buffer, offset, count));
}
- static public DateTime ToDateTime(Int64 value)
+ public static DateTime ToDateTime(Int64 value)
{
try
{
@@ -244,7 +244,7 @@ namespace System.Xml
}
}
- static public DateTime ToDateTime(string value)
+ public static DateTime ToDateTime(string value)
{
try
{
@@ -260,7 +260,7 @@ namespace System.Xml
}
}
- static public DateTime ToDateTime(byte[] buffer, int offset, int count)
+ public static DateTime ToDateTime(byte[] buffer, int offset, int count)
{
DateTime value;
if (TryParseDateTime(buffer, offset, count, out value))
@@ -268,7 +268,7 @@ namespace System.Xml
return ToDateTime(ToString(buffer, offset, count));
}
- static public UniqueId ToUniqueId(string value)
+ public static UniqueId ToUniqueId(string value)
{
try
{
@@ -284,12 +284,12 @@ namespace System.Xml
}
}
- static public UniqueId ToUniqueId(byte[] buffer, int offset, int count)
+ public static UniqueId ToUniqueId(byte[] buffer, int offset, int count)
{
return ToUniqueId(ToString(buffer, offset, count));
}
- static public TimeSpan ToTimeSpan(string value)
+ public static TimeSpan ToTimeSpan(string value)
{
try
{
@@ -309,12 +309,12 @@ namespace System.Xml
}
}
- static public TimeSpan ToTimeSpan(byte[] buffer, int offset, int count)
+ public static TimeSpan ToTimeSpan(byte[] buffer, int offset, int count)
{
return ToTimeSpan(ToString(buffer, offset, count));
}
- static public Guid ToGuid(string value)
+ public static Guid ToGuid(string value)
{
try
{
@@ -334,12 +334,12 @@ namespace System.Xml
}
}
- static public Guid ToGuid(byte[] buffer, int offset, int count)
+ public static Guid ToGuid(byte[] buffer, int offset, int count)
{
return ToGuid(ToString(buffer, offset, count));
}
- static public UInt64 ToUInt64(string value)
+ public static UInt64 ToUInt64(string value)
{
try
{
@@ -359,12 +359,12 @@ namespace System.Xml
}
}
- static public UInt64 ToUInt64(byte[] buffer, int offset, int count)
+ public static UInt64 ToUInt64(byte[] buffer, int offset, int count)
{
return ToUInt64(ToString(buffer, offset, count));
}
- static public string ToString(byte[] buffer, int offset, int count)
+ public static string ToString(byte[] buffer, int offset, int count)
{
try
{
@@ -376,7 +376,7 @@ namespace System.Xml
}
}
- static public string ToStringUnicode(byte[] buffer, int offset, int count)
+ public static string ToStringUnicode(byte[] buffer, int offset, int count)
{
try
{
@@ -389,7 +389,7 @@ namespace System.Xml
}
- static public byte[] ToBytes(string value)
+ public static byte[] ToBytes(string value)
{
try
{
@@ -401,7 +401,7 @@ namespace System.Xml
}
}
- static public int ToChars(byte[] buffer, int offset, int count, char[] chars, int charOffset)
+ public static int ToChars(byte[] buffer, int offset, int count, char[] chars, int charOffset)
{
try
{
@@ -413,19 +413,19 @@ namespace System.Xml
}
}
- static public string ToString(bool value) { return value ? "true" : "false"; }
- static public string ToString(int value) { return XmlConvert.ToString(value); }
- static public string ToString(Int64 value) { return XmlConvert.ToString(value); }
- static public string ToString(float value) { return XmlConvert.ToString(value); }
- static public string ToString(double value) { return XmlConvert.ToString(value); }
- static public string ToString(decimal value) { return XmlConvert.ToString(value); }
- static public string ToString(TimeSpan value) { return XmlConvert.ToString(value); }
+ public static string ToString(bool value) { return value ? "true" : "false"; }
+ public static string ToString(int value) { return XmlConvert.ToString(value); }
+ public static string ToString(Int64 value) { return XmlConvert.ToString(value); }
+ public static string ToString(float value) { return XmlConvert.ToString(value); }
+ public static string ToString(double value) { return XmlConvert.ToString(value); }
+ public static string ToString(decimal value) { return XmlConvert.ToString(value); }
+ public static string ToString(TimeSpan value) { return XmlConvert.ToString(value); }
- static public string ToString(UniqueId value) { return value.ToString(); }
- static public string ToString(Guid value) { return value.ToString(); }
- static public string ToString(UInt64 value) { return value.ToString(NumberFormatInfo.InvariantInfo); }
+ public static string ToString(UniqueId value) { return value.ToString(); }
+ public static string ToString(Guid value) { return value.ToString(); }
+ public static string ToString(UInt64 value) { return value.ToString(NumberFormatInfo.InvariantInfo); }
- static public string ToString(DateTime value)
+ public static string ToString(DateTime value)
{
byte[] dateChars = new byte[MaxDateTimeChars];
int count = ToChars(value, dateChars, 0);
@@ -460,7 +460,7 @@ namespace System.Xml
return value.ToString();
}
- static public string ToString(object[] objects)
+ public static string ToString(object[] objects)
{
if (objects.Length == 0)
return string.Empty;
@@ -478,7 +478,7 @@ namespace System.Xml
return value;
}
- static public void ToQualifiedName(string qname, out string prefix, out string localName)
+ public static void ToQualifiedName(string qname, out string prefix, out string localName)
{
int index = qname.IndexOf(':');
if (index < 0)
@@ -699,21 +699,21 @@ namespace System.Xml
return true;
}
- static public int ToChars(int value, byte[] chars, int offset)
+ public static int ToChars(int value, byte[] chars, int offset)
{
int count = ToCharsR(value, chars, offset + MaxInt32Chars);
Buffer.BlockCopy(chars, offset + MaxInt32Chars - count, chars, offset, count);
return count;
}
- static public int ToChars(long value, byte[] chars, int offset)
+ public static int ToChars(long value, byte[] chars, int offset)
{
int count = ToCharsR(value, chars, offset + MaxInt64Chars);
Buffer.BlockCopy(chars, offset + MaxInt64Chars - count, chars, offset, count);
return count;
}
- static public int ToCharsR(long value, byte[] chars, int offset)
+ public static int ToCharsR(long value, byte[] chars, int offset)
{
int count = 0;
if (value >= 0)
@@ -788,7 +788,7 @@ namespace System.Xml
}
}
- static public int ToChars(double value, byte[] buffer, int offset)
+ public static int ToChars(double value, byte[] buffer, int offset)
{
if (double.IsInfinity(value))
return ToInfinity(double.IsNegativeInfinity(value), buffer, offset);
@@ -797,7 +797,7 @@ namespace System.Xml
return ToAsciiChars(value.ToString("R", NumberFormatInfo.InvariantInfo), buffer, offset);
}
- static public int ToChars(float value, byte[] buffer, int offset)
+ public static int ToChars(float value, byte[] buffer, int offset)
{
if (float.IsInfinity(value))
return ToInfinity(float.IsNegativeInfinity(value), buffer, offset);
@@ -806,12 +806,12 @@ namespace System.Xml
return ToAsciiChars(value.ToString("R", NumberFormatInfo.InvariantInfo), buffer, offset);
}
- static public int ToChars(decimal value, byte[] buffer, int offset)
+ public static int ToChars(decimal value, byte[] buffer, int offset)
{
return ToAsciiChars(value.ToString(null, NumberFormatInfo.InvariantInfo), buffer, offset);
}
- static public int ToChars(UInt64 value, byte[] buffer, int offset)
+ public static int ToChars(UInt64 value, byte[] buffer, int offset)
{
return ToAsciiChars(value.ToString(null, NumberFormatInfo.InvariantInfo), buffer, offset);
}
@@ -826,7 +826,7 @@ namespace System.Xml
return s.Length;
}
- static public int ToChars(bool value, byte[] buffer, int offset)
+ public static int ToChars(bool value, byte[] buffer, int offset)
{
if (value)
{
@@ -1002,7 +1002,7 @@ namespace System.Xml
// Works left from offset
- static public int ToCharsR(int value, byte[] chars, int offset)
+ public static int ToCharsR(int value, byte[] chars, int offset)
{
int count = 0;
if (value >= 0)
@@ -1071,7 +1071,7 @@ namespace System.Xml
return count;
}
- static public int ToChars(DateTime value, byte[] chars, int offset)
+ public static int ToChars(DateTime value, byte[] chars, int offset)
{
const long TicksPerMillisecond = 10000;
const long TicksPerSecond = TicksPerMillisecond * 1000;
@@ -1119,7 +1119,7 @@ namespace System.Xml
return offset - offsetMin;
}
- static public bool IsWhitespace(string s)
+ public static bool IsWhitespace(string s)
{
for (int i = 0; i < s.Length; i++)
{
@@ -1129,12 +1129,12 @@ namespace System.Xml
return true;
}
- static public bool IsWhitespace(char ch)
+ public static bool IsWhitespace(char ch)
{
return (ch <= ' ' && (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'));
}
- static public string StripWhitespace(string s)
+ public static string StripWhitespace(string s)
{
int count = s.Length;
for (int i = 0; i < s.Length; i++)
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionary.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionary.cs
index b498d22ec3..ae12989565 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionary.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionary.cs
@@ -21,7 +21,7 @@ namespace System.Xml
private XmlDictionaryString[] _strings;
private int _nextId;
- static public IXmlDictionary Empty
+ public static IXmlDictionary Empty
{
get
{
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryReaderQuotas.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryReaderQuotas.cs
index 1ceec44a7e..8a75881e47 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryReaderQuotas.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryReaderQuotas.cs
@@ -55,7 +55,7 @@ namespace System.Xml
MakeReadOnly();
}
- static public XmlDictionaryReaderQuotas Max
+ public static XmlDictionaryReaderQuotas Max
{
get
{
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryString.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryString.cs
index 36a0a6ee42..97e6c988f4 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryString.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlDictionaryString.cs
@@ -35,14 +35,14 @@ namespace System.Xml
_key = key;
}
- static internal string GetString(XmlDictionaryString s)
+ internal static string GetString(XmlDictionaryString s)
{
if (s == null)
return null;
return s.Value;
}
- static public XmlDictionaryString Empty
+ public static XmlDictionaryString Empty
{
get
{
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlExceptionHelper.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlExceptionHelper.cs
index a29b39dd12..ea8e44145d 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlExceptionHelper.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlExceptionHelper.cs
@@ -14,7 +14,7 @@ namespace System.Xml
ThrowXmlException(reader, res, null);
}
- static public void ThrowXmlException(XmlDictionaryReader reader, string res, string arg1)
+ public static void ThrowXmlException(XmlDictionaryReader reader, string res, string arg1)
{
ThrowXmlException(reader, res, arg1, null);
}
@@ -36,7 +36,7 @@ namespace System.Xml
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(s));
}
- static public void ThrowXmlException(XmlDictionaryReader reader, XmlException exception)
+ public static void ThrowXmlException(XmlDictionaryReader reader, XmlException exception)
{
string s = exception.Message;
IXmlLineInfo lineInfo = reader as IXmlLineInfo;
@@ -77,127 +77,127 @@ namespace System.Xml
return SR.Format(SR.XmlFoundNodeType, reader.NodeType);
}
- static public void ThrowStartElementExpected(XmlDictionaryReader reader)
+ public static void ThrowStartElementExpected(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlStartElementExpected, GetWhatWasFound(reader));
}
- static public void ThrowStartElementExpected(XmlDictionaryReader reader, string name)
+ public static void ThrowStartElementExpected(XmlDictionaryReader reader, string name)
{
ThrowXmlException(reader, SR.XmlStartElementNameExpected, name, GetWhatWasFound(reader));
}
- static public void ThrowStartElementExpected(XmlDictionaryReader reader, string localName, string ns)
+ public static void ThrowStartElementExpected(XmlDictionaryReader reader, string localName, string ns)
{
ThrowXmlException(reader, SR.XmlStartElementLocalNameNsExpected, localName, ns, GetWhatWasFound(reader));
}
- static public void ThrowStartElementExpected(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString ns)
+ public static void ThrowStartElementExpected(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString ns)
{
ThrowStartElementExpected(reader, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(ns));
}
- static public void ThrowFullStartElementExpected(XmlDictionaryReader reader)
+ public static void ThrowFullStartElementExpected(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlFullStartElementExpected, GetWhatWasFound(reader));
}
- static public void ThrowFullStartElementExpected(XmlDictionaryReader reader, string name)
+ public static void ThrowFullStartElementExpected(XmlDictionaryReader reader, string name)
{
ThrowXmlException(reader, SR.XmlFullStartElementNameExpected, name, GetWhatWasFound(reader));
}
- static public void ThrowFullStartElementExpected(XmlDictionaryReader reader, string localName, string ns)
+ public static void ThrowFullStartElementExpected(XmlDictionaryReader reader, string localName, string ns)
{
ThrowXmlException(reader, SR.XmlFullStartElementLocalNameNsExpected, localName, ns, GetWhatWasFound(reader));
}
- static public void ThrowFullStartElementExpected(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString ns)
+ public static void ThrowFullStartElementExpected(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString ns)
{
ThrowFullStartElementExpected(reader, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(ns));
}
- static public void ThrowEndElementExpected(XmlDictionaryReader reader, string localName, string ns)
+ public static void ThrowEndElementExpected(XmlDictionaryReader reader, string localName, string ns)
{
ThrowXmlException(reader, SR.XmlEndElementExpected, localName, ns, GetWhatWasFound(reader));
}
- static public void ThrowMaxArrayLengthExceeded(XmlDictionaryReader reader, int maxArrayLength)
+ public static void ThrowMaxArrayLengthExceeded(XmlDictionaryReader reader, int maxArrayLength)
{
ThrowXmlException(reader, SR.XmlMaxArrayLengthExceeded, maxArrayLength.ToString(NumberFormatInfo.CurrentInfo));
}
- static public void ThrowMaxBytesPerReadExceeded(XmlDictionaryReader reader, int maxBytesPerRead)
+ public static void ThrowMaxBytesPerReadExceeded(XmlDictionaryReader reader, int maxBytesPerRead)
{
ThrowXmlException(reader, SR.XmlMaxBytesPerReadExceeded, maxBytesPerRead.ToString(NumberFormatInfo.CurrentInfo));
}
- static public void ThrowMaxNameTableCharCountExceeded(XmlDictionaryReader reader, int maxNameTableCharCount)
+ public static void ThrowMaxNameTableCharCountExceeded(XmlDictionaryReader reader, int maxNameTableCharCount)
{
ThrowXmlException(reader, SR.XmlMaxNameTableCharCountExceeded, maxNameTableCharCount.ToString(NumberFormatInfo.CurrentInfo));
}
- static public void ThrowMaxDepthExceeded(XmlDictionaryReader reader, int maxDepth)
+ public static void ThrowMaxDepthExceeded(XmlDictionaryReader reader, int maxDepth)
{
ThrowXmlException(reader, SR.XmlMaxDepthExceeded, maxDepth.ToString());
}
- static public void ThrowMaxStringContentLengthExceeded(XmlDictionaryReader reader, int maxStringContentLength)
+ public static void ThrowMaxStringContentLengthExceeded(XmlDictionaryReader reader, int maxStringContentLength)
{
ThrowXmlException(reader, SR.XmlMaxStringContentLengthExceeded, maxStringContentLength.ToString(NumberFormatInfo.CurrentInfo));
}
- static public void ThrowBase64DataExpected(XmlDictionaryReader reader)
+ public static void ThrowBase64DataExpected(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlBase64DataExpected, GetWhatWasFound(reader));
}
- static public void ThrowUndefinedPrefix(XmlDictionaryReader reader, string prefix)
+ public static void ThrowUndefinedPrefix(XmlDictionaryReader reader, string prefix)
{
ThrowXmlException(reader, SR.XmlUndefinedPrefix, prefix);
}
- static public void ThrowProcessingInstructionNotSupported(XmlDictionaryReader reader)
+ public static void ThrowProcessingInstructionNotSupported(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlProcessingInstructionNotSupported);
}
- static public void ThrowInvalidXml(XmlDictionaryReader reader, byte b)
+ public static void ThrowInvalidXml(XmlDictionaryReader reader, byte b)
{
ThrowXmlException(reader, SR.XmlInvalidXmlByte, b.ToString("X2", CultureInfo.InvariantCulture));
}
- static public void ThrowUnexpectedEndOfFile(XmlDictionaryReader reader)
+ public static void ThrowUnexpectedEndOfFile(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlUnexpectedEndOfFile, ((XmlBaseReader)reader).GetOpenElements());
}
- static public void ThrowUnexpectedEndElement(XmlDictionaryReader reader)
+ public static void ThrowUnexpectedEndElement(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlUnexpectedEndElement);
}
- static public void ThrowTokenExpected(XmlDictionaryReader reader, string expected, char found)
+ public static void ThrowTokenExpected(XmlDictionaryReader reader, string expected, char found)
{
ThrowXmlException(reader, SR.XmlTokenExpected, expected, found.ToString());
}
- static public void ThrowTokenExpected(XmlDictionaryReader reader, string expected, string found)
+ public static void ThrowTokenExpected(XmlDictionaryReader reader, string expected, string found)
{
ThrowXmlException(reader, SR.XmlTokenExpected, expected, found);
}
- static public void ThrowInvalidCharRef(XmlDictionaryReader reader)
+ public static void ThrowInvalidCharRef(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlInvalidCharRef);
}
- static public void ThrowTagMismatch(XmlDictionaryReader reader, string expectedPrefix, string expectedLocalName, string foundPrefix, string foundLocalName)
+ public static void ThrowTagMismatch(XmlDictionaryReader reader, string expectedPrefix, string expectedLocalName, string foundPrefix, string foundLocalName)
{
ThrowXmlException(reader, SR.XmlTagMismatch, GetName(expectedPrefix, expectedLocalName), GetName(foundPrefix, foundLocalName));
}
- static public void ThrowDuplicateXmlnsAttribute(XmlDictionaryReader reader, string localName, string ns)
+ public static void ThrowDuplicateXmlnsAttribute(XmlDictionaryReader reader, string localName, string ns)
{
string name;
if (localName.Length == 0)
@@ -207,72 +207,72 @@ namespace System.Xml
ThrowXmlException(reader, SR.XmlDuplicateAttribute, name, name, ns);
}
- static public void ThrowDuplicateAttribute(XmlDictionaryReader reader, string prefix1, string prefix2, string localName, string ns)
+ public static void ThrowDuplicateAttribute(XmlDictionaryReader reader, string prefix1, string prefix2, string localName, string ns)
{
ThrowXmlException(reader, SR.XmlDuplicateAttribute, GetName(prefix1, localName), GetName(prefix2, localName), ns);
}
- static public void ThrowInvalidBinaryFormat(XmlDictionaryReader reader)
+ public static void ThrowInvalidBinaryFormat(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlInvalidFormat);
}
- static public void ThrowInvalidRootData(XmlDictionaryReader reader)
+ public static void ThrowInvalidRootData(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlInvalidRootData);
}
- static public void ThrowMultipleRootElements(XmlDictionaryReader reader)
+ public static void ThrowMultipleRootElements(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlMultipleRootElements);
}
- static public void ThrowDeclarationNotFirst(XmlDictionaryReader reader)
+ public static void ThrowDeclarationNotFirst(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlDeclNotFirst);
}
- static public void ThrowConversionOverflow(XmlDictionaryReader reader, string value, string type)
+ public static void ThrowConversionOverflow(XmlDictionaryReader reader, string value, string type)
{
ThrowXmlException(reader, SR.XmlConversionOverflow, value, type);
}
- static public void ThrowXmlDictionaryStringIDOutOfRange(XmlDictionaryReader reader)
+ public static void ThrowXmlDictionaryStringIDOutOfRange(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlDictionaryStringIDRange, XmlDictionaryString.MinKey.ToString(NumberFormatInfo.CurrentInfo), XmlDictionaryString.MaxKey.ToString(NumberFormatInfo.CurrentInfo));
}
- static public void ThrowXmlDictionaryStringIDUndefinedStatic(XmlDictionaryReader reader, int key)
+ public static void ThrowXmlDictionaryStringIDUndefinedStatic(XmlDictionaryReader reader, int key)
{
ThrowXmlException(reader, SR.XmlDictionaryStringIDUndefinedStatic, key.ToString(NumberFormatInfo.CurrentInfo));
}
- static public void ThrowXmlDictionaryStringIDUndefinedSession(XmlDictionaryReader reader, int key)
+ public static void ThrowXmlDictionaryStringIDUndefinedSession(XmlDictionaryReader reader, int key)
{
ThrowXmlException(reader, SR.XmlDictionaryStringIDUndefinedSession, key.ToString(NumberFormatInfo.CurrentInfo));
}
- static public void ThrowEmptyNamespace(XmlDictionaryReader reader)
+ public static void ThrowEmptyNamespace(XmlDictionaryReader reader)
{
ThrowXmlException(reader, SR.XmlEmptyNamespaceRequiresNullPrefix);
}
- static public XmlException CreateConversionException(string type, Exception exception)
+ public static XmlException CreateConversionException(string type, Exception exception)
{
return new XmlException(SR.Format(SR.XmlInvalidConversionWithoutValue, type), exception);
}
- static public XmlException CreateConversionException(string value, string type, Exception exception)
+ public static XmlException CreateConversionException(string value, string type, Exception exception)
{
return new XmlException(SR.Format(SR.XmlInvalidConversion, value, type), exception);
}
- static public XmlException CreateEncodingException(byte[] buffer, int offset, int count, Exception exception)
+ public static XmlException CreateEncodingException(byte[] buffer, int offset, int count, Exception exception)
{
return CreateEncodingException(new System.Text.UTF8Encoding(false, false).GetString(buffer, offset, count), exception);
}
- static public XmlException CreateEncodingException(string value, Exception exception)
+ public static XmlException CreateEncodingException(string value, Exception exception)
{
return new XmlException(SR.Format(SR.XmlInvalidUTF8Bytes, value), exception);
}
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs
index 6d8ea6c2e7..ea071160d5 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlStreamNodeWriter.cs
@@ -243,7 +243,7 @@ namespace System.Xml
}
}
- unsafe protected void UnsafeWriteBytes(byte* bytes, int byteCount)
+ protected unsafe void UnsafeWriteBytes(byte* bytes, int byteCount)
{
FlushBuffer();
byte[] buffer = _buffer;
@@ -262,7 +262,7 @@ namespace System.Xml
}
}
- unsafe protected void WriteUTF8Char(int ch)
+ protected unsafe void WriteUTF8Char(int ch)
{
if (ch < 0x80)
{
@@ -300,7 +300,7 @@ namespace System.Xml
}
}
- unsafe protected void WriteUTF8Chars(string value)
+ protected unsafe void WriteUTF8Chars(string value)
{
int count = value.Length;
if (count > 0)
@@ -312,7 +312,7 @@ namespace System.Xml
}
}
- unsafe protected void UnsafeWriteUTF8Chars(char* chars, int charCount)
+ protected unsafe void UnsafeWriteUTF8Chars(char* chars, int charCount)
{
const int charChunkSize = bufferLength / maxBytesPerChar;
while (charCount > charChunkSize)
@@ -334,7 +334,7 @@ namespace System.Xml
}
}
- unsafe protected void UnsafeWriteUnicodeChars(char* chars, int charCount)
+ protected unsafe void UnsafeWriteUnicodeChars(char* chars, int charCount)
{
const int charChunkSize = bufferLength / 2;
while (charCount > charChunkSize)
@@ -356,7 +356,7 @@ namespace System.Xml
}
}
- unsafe protected int UnsafeGetUnicodeChars(char* chars, int charCount, byte[] buffer, int offset)
+ protected unsafe int UnsafeGetUnicodeChars(char* chars, int charCount, byte[] buffer, int offset)
{
char* charsMax = chars + charCount;
while (chars < charsMax)
@@ -369,7 +369,7 @@ namespace System.Xml
return charCount * 2;
}
- unsafe protected int UnsafeGetUTF8Length(char* chars, int charCount)
+ protected unsafe int UnsafeGetUTF8Length(char* chars, int charCount)
{
char* charsMax = chars + charCount;
while (chars < charsMax)
@@ -391,7 +391,7 @@ namespace System.Xml
return (int)(chars - (charsMax - charCount)) + GetByteCount(chArray);
}
- unsafe protected int UnsafeGetUTF8Chars(char* chars, int charCount, byte[] buffer, int offset)
+ protected unsafe int UnsafeGetUTF8Chars(char* chars, int charCount, byte[] buffer, int offset)
{
if (charCount > 0)
{
diff --git a/src/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs b/src/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs
index b2f20a6360..d5300c0a42 100644
--- a/src/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs
+++ b/src/System.Private.DataContractSerialization/src/System/Xml/XmlUTF8TextWriter.cs
@@ -435,7 +435,7 @@ namespace System.Xml
WriteEscapedText(s.Value);
}
- unsafe public override void WriteEscapedText(string s)
+ public unsafe override void WriteEscapedText(string s)
{
int count = s.Length;
if (count > 0)
@@ -447,7 +447,7 @@ namespace System.Xml
}
}
- unsafe public override void WriteEscapedText(char[] s, int offset, int count)
+ public unsafe override void WriteEscapedText(char[] s, int offset, int count)
{
if (count > 0)
{
@@ -518,7 +518,7 @@ namespace System.Xml
WriteUTF8Chars(chars, offset, count);
}
- unsafe public override void WriteText(char[] chars, int offset, int count)
+ public unsafe override void WriteText(char[] chars, int offset, int count)
{
if (count > 0)
{
diff --git a/src/System.Private.Uri/pkg/unix/System.Private.Uri.pkgproj b/src/System.Private.Uri/pkg/unix/System.Private.Uri.pkgproj
index 51704ef9de..4dd94eacff 100644
--- a/src/System.Private.Uri/pkg/unix/System.Private.Uri.pkgproj
+++ b/src/System.Private.Uri/pkg/unix/System.Private.Uri.pkgproj
@@ -10,7 +10,10 @@
<ProjectReference Include="..\..\src\System.Private.Uri.csproj" >
<OSGroup>Unix</OSGroup>
</ProjectReference>
-
+ <ProjectReference Include="..\..\src\System.Private.Uri.csproj">
+ <TargetGroup>netcoreapp1.2corert</TargetGroup>
+ <OSGroup>Unix</OSGroup>
+ </ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/System.Private.Uri/pkg/win/System.Private.Uri.pkgproj b/src/System.Private.Uri/pkg/win/System.Private.Uri.pkgproj
index 704df3d840..fe9ac10f72 100644
--- a/src/System.Private.Uri/pkg/win/System.Private.Uri.pkgproj
+++ b/src/System.Private.Uri/pkg/win/System.Private.Uri.pkgproj
@@ -13,6 +13,10 @@
<OSGroup>Windows_NT</OSGroup>
<TargetGroup>uap101aot</TargetGroup>
</ProjectReference>
+ <ProjectReference Include="..\..\src\System.Private.Uri.csproj">
+ <OSGroup>Windows_NT</OSGroup>
+ <TargetGroup>netcoreapp1.2corert</TargetGroup>
+ </ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/System.Private.Uri/src/Configurations.props b/src/System.Private.Uri/src/Configurations.props
index 005b55090e..f2122dc3ce 100644
--- a/src/System.Private.Uri/src/Configurations.props
+++ b/src/System.Private.Uri/src/Configurations.props
@@ -5,6 +5,8 @@
uap101aot-Windows_NT;
netstandard1.0-Unix;
netstandard1.0-Windows_NT;
+ netcoreapp1.2corert-Unix;
+ netcoreapp1.2corert-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>
diff --git a/src/System.Private.Uri/src/FxCopBaseline.cs b/src/System.Private.Uri/src/FxCopBaseline.cs
new file mode 100644
index 0000000000..5207ad7c67
--- /dev/null
+++ b/src/System.Private.Uri/src/FxCopBaseline.cs
@@ -0,0 +1,4 @@
+using System.Diagnostics.CodeAnalysis;
+
+// TODO: Remove this once https://github.com/dotnet/corefx/issues/13107 is fixed
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "System.Uri.#CreateUriInfo(System.Uri+Flags)")]
diff --git a/src/System.Private.Uri/src/System.Private.Uri.csproj b/src/System.Private.Uri/src/System.Private.Uri.csproj
index b46d9b3d1b..1839f84157 100644
--- a/src/System.Private.Uri/src/System.Private.Uri.csproj
+++ b/src/System.Private.Uri/src/System.Private.Uri.csproj
@@ -5,10 +5,9 @@
<ProjectGuid>{4AC5343E-6E31-4BA5-A795-0493AE7E9008}</ProjectGuid>
<AssemblyName>System.Private.Uri</AssemblyName>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <DefineConstants>$(DefineConstants);INTERNAL_GLOBALIZATION_EXTENSIONS</DefineConstants>
<!-- Suppress warnings for type conflicts between SafeFileHandle in partial facade and mscorlib -->
<NoWarn>0436</NoWarn>
- <SkipCommonResourcesIncludes Condition="'$(TargetGroup)'=='uap101aot'">true</SkipCommonResourcesIncludes>
+ <SkipCommonResourcesIncludes Condition="'$(TargetGroup)'=='uap101aot' or '$(TargetGroup)' == 'netcoreapp1.2corert'">true</SkipCommonResourcesIncludes>
<DefineConstants Condition="'$(TargetGroup)'=='netstandard1.0'">$(DefineConstants);netstandard10</DefineConstants>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
@@ -19,7 +18,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_uap101aot_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_uap101aot_Release|AnyCPU'" />
<ItemGroup>
- <Compile Include="$(CommonPath)\System\Diagnostics\Debug.cs" Condition="'$(TargetGroup)'!='uap101aot'">
+ <Compile Include="$(CommonPath)\System\Diagnostics\Debug.cs" Condition="'$(TargetGroup)'!='uap101aot' and '$(TargetGroup)' != 'netcoreapp1.2corert'">
<Link>Common\System\Diagnostics\Debug.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\Collections\Generic\ArrayBuilder.cs">
@@ -28,15 +27,9 @@
<Compile Include="$(CommonPath)\System\Collections\Generic\LowLevelDictionary.cs">
<Link>Common\System\Collections\Generic\LowLevelDictionary.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\StringNormalizationExtensions.cs" Condition="'$(TargetGroup)'=='uap101aot'">
- <Link>Common\System\StringNormalizationExtensions.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\Globalization\IdnMapping.cs" Condition="'$(TargetGroup)'=='uap101aot'">
- <Link>Common\System\Globalization\IdnMapping.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\Text\NormalizationForm.cs" Condition="'$(TargetGroup)'=='uap101aot'">
- <Link>Common\System\Text\NormalizationForm.cs</Link>
- </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="FxCopBaseline.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="System\DomainNameHelper.cs" />
@@ -57,34 +50,19 @@
<Compile Include="System\UriScheme.cs" />
<Compile Include="System\UriSyntax.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetsWindows)' == 'true'">
+ <ItemGroup Condition="'$(TargetsWindows)' == 'true' and '$(TargetGroup)'=='netstandard1.0'">
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs">
<Link>Common\Interop\Windows\Interop.Libraries.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.OutputDebugString.cs">
<Link>Common\Interop\Windows\kernel32\Interop.OutputDebugString.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\StringNormalizationExtensions.Windows.cs" Condition="'$(TargetGroup)'=='uap101aot'">
- <Link>Common\System\StringNormalizationExtensions.Windows.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\Globalization\IdnMapping.Windows.cs" Condition="'$(TargetGroup)'=='uap101aot'">
- <Link>Common\System\Globalization\IdnMapping.Windows.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\Diagnostics\Debug.Windows.cs" Condition="'$(TargetGroup)'!='uap101aot'">
+ <Compile Include="$(CommonPath)\System\Diagnostics\Debug.Windows.cs">
<Link>Common\System\Diagnostics\Debug.Windows.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetLastError.cs">
- <Link>Common\Interop\Windows\kernel32\Interop.SetLastError.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.Normalization.cs" Condition="'$(TargetGroup)'=='uap101aot'">
- <Link>Common\Interop\Windows\kernel32\Interop.Normalization.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\normaliz\Interop.Idna.cs" Condition="'$(TargetGroup)'=='uap101aot'">
- <Link>Common\Interop\Windows\normaliz\Interop.Idna.cs</Link>
- </Compile>
</ItemGroup>
- <ItemGroup Condition="'$(TargetsUnix)' == 'true'">
- <Compile Include="$(CommonPath)\System\Diagnostics\Debug.Unix.cs" Condition="'$(TargetGroup)'!='uap101aot'">
+ <ItemGroup Condition="'$(TargetsUnix)' == 'true' and '$(TargetGroup)' == 'netstandard1.0'">
+ <Compile Include="$(CommonPath)\System\Diagnostics\Debug.Unix.cs">
<Link>Common\System\Diagnostics\Debug.Unix.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Unix\Interop.Libraries.cs">
@@ -127,7 +105,7 @@
<Link>Common\Microsoft\Win32\SafeHandles\SafeFileHandleHelper.Unix.cs</Link>
</Compile>
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)'=='uap101aot'">
+ <ItemGroup Condition="'$(TargetGroup)'=='uap101aot' or '$(TargetGroup)' == 'netcoreapp1.2corert'">
<EmbeddedResource Include="Resources\$(AssemblyName).rd.xml" />
<Compile Include="$(CommonPath)\System\SR.Core.cs">
<Link>Common\System\SR.Core.cs</Link>
@@ -135,15 +113,6 @@
<Compile Include="$(CommonPath)\System\Resources\NeutralResourcesLanguageAttribute.cs">
<Link>Common\System\Resources\NeutralResourcesLanguageAttribute.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\Runtime\InteropServices\Marshal.Win32.cs" Condition="'$(TargetsWindows)'=='true'">
- <Link>Common\System\Runtime\InteropServices\Marshal.Win32.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\Runtime\InteropServices\Marshal.Unix.cs" Condition="'$(TargetsUnix)'=='true'">
- <Link>Common\System\Runtime\InteropServices\Marshal.Unix.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetLastError.cs" Condition="'$(TargetsWindows)'=='true'">
- <Link>Common\Interop\Windows\kernel32\Interop.GetLastError.cs</Link>
- </Compile>
</ItemGroup>
<ItemGroup>
<TargetingPackReference Include="System.Private.CoreLib" />
diff --git a/src/System.Private.Uri/src/System/DomainNameHelper.cs b/src/System.Private.Uri/src/System/DomainNameHelper.cs
index 0231c3a9c3..cfc31d61f1 100644
--- a/src/System.Private.Uri/src/System/DomainNameHelper.cs
+++ b/src/System.Private.Uri/src/System/DomainNameHelper.cs
@@ -67,7 +67,7 @@ namespace System
// MUST NOT be used unless all input indexes are verified and trusted.
//
- internal unsafe static bool IsValid(char* name, ushort pos, ref int returnedEnd, ref bool notCanonical, bool notImplicitFile)
+ internal static unsafe bool IsValid(char* name, ushort pos, ref int returnedEnd, ref bool notCanonical, bool notImplicitFile)
{
char* curPos = name + pos;
char* newPos = curPos;
@@ -130,7 +130,7 @@ namespace System
// There are pretty much no restrictions and we effectively return the end of the
// domain name.
//
- internal unsafe static bool IsValidByIri(char* name, ushort pos, ref int returnedEnd, ref bool notCanonical, bool notImplicitFile)
+ internal static unsafe bool IsValidByIri(char* name, ushort pos, ref int returnedEnd, ref bool notCanonical, bool notImplicitFile)
{
char* curPos = name + pos;
char* newPos = curPos;
@@ -217,7 +217,7 @@ namespace System
//
// Will convert a host name into its idn equivalent + tell you if it had a valid idn label
//
- internal unsafe static string IdnEquivalent(char* hostname, int start, int end, ref bool allAscii, ref bool atLeastOneValidIdn)
+ internal static unsafe string IdnEquivalent(char* hostname, int start, int end, ref bool allAscii, ref bool atLeastOneValidIdn)
{
string bidiStrippedHost = null;
string idnEquivalent = IdnEquivalent(hostname, start, end, ref allAscii, ref bidiStrippedHost);
@@ -297,7 +297,7 @@ namespace System
//
// Will convert a host name into its idn equivalent
//
- internal unsafe static string IdnEquivalent(char* hostname, int start, int end, ref bool allAscii, ref string bidiStrippedHost)
+ internal static unsafe string IdnEquivalent(char* hostname, int start, int end, ref bool allAscii, ref string bidiStrippedHost)
{
string idn = null;
if (end <= start)
@@ -343,7 +343,7 @@ namespace System
}
}
- private unsafe static bool IsIdnAce(string input, int index)
+ private static unsafe bool IsIdnAce(string input, int index)
{
if ((input[index] == 'x') &&
(input[index + 1] == 'n') &&
@@ -354,7 +354,7 @@ namespace System
return false;
}
- private unsafe static bool IsIdnAce(char* input, int index)
+ private static unsafe bool IsIdnAce(char* input, int index)
{
if ((input[index] == 'x') &&
(input[index + 1] == 'n') &&
@@ -368,7 +368,7 @@ namespace System
//
// Will convert a host name into its unicode equivalent expanding any existing idn names present
//
- internal unsafe static string UnicodeEquivalent(string idnHost, char* hostname, int start, int end)
+ internal static unsafe string UnicodeEquivalent(string idnHost, char* hostname, int start, int end)
{
IdnMapping map = new IdnMapping();
@@ -388,7 +388,7 @@ namespace System
return UnicodeEquivalent(hostname, start, end, ref dummy, ref dummy);
}
- internal unsafe static string UnicodeEquivalent(char* hostname, int start, int end, ref bool allAscii, ref bool atLeastOneValidIdn)
+ internal static unsafe string UnicodeEquivalent(char* hostname, int start, int end, ref bool allAscii, ref bool atLeastOneValidIdn)
{
IdnMapping map = new IdnMapping();
diff --git a/src/System.Private.Uri/src/System/IPv4AddressHelper.cs b/src/System.Private.Uri/src/System/IPv4AddressHelper.cs
index 3f4410ba6f..3d4cbcd216 100644
--- a/src/System.Private.Uri/src/System/IPv4AddressHelper.cs
+++ b/src/System.Private.Uri/src/System/IPv4AddressHelper.cs
@@ -84,7 +84,7 @@ namespace System
//
//Remark: MUST NOT be used unless all input indexes are verified and trusted.
- internal unsafe static bool IsValid(char* name, int start, ref int end, bool allowIPv6, bool notImplicitFile, bool unknownScheme)
+ internal static unsafe bool IsValid(char* name, int start, ref int end, bool allowIPv6, bool notImplicitFile, bool unknownScheme)
{
// IPv6 can only have canonical IPv4 embedded. Unknown schemes will not attempt parsing of non-canonical IPv4 addresses.
if (allowIPv6 || unknownScheme)
@@ -110,7 +110,7 @@ namespace System
// / "2" %x30-34 DIGIT ; 200-249
// / "25" %x30-35 ; 250-255
//
- internal unsafe static bool IsValidCanonical(char* name, int start, ref int end, bool allowIPv6, bool notImplicitFile)
+ internal static unsafe bool IsValidCanonical(char* name, int start, ref int end, bool allowIPv6, bool notImplicitFile)
{
int dots = 0;
int number = 0;
@@ -180,7 +180,7 @@ namespace System
// Return Invalid (-1) for failures.
// If the address has less than three dots, only the rightmost section is assumed to contain the combined value for
// the missing sections: 0xFF00FFFF == 0xFF.0x00.0xFF.0xFF == 0xFF.0xFFFF
- internal unsafe static long ParseNonCanonical(char* name, int start, ref int end, bool notImplicitFile)
+ internal static unsafe long ParseNonCanonical(char* name, int start, ref int end, bool notImplicitFile)
{
int numberBase = Decimal;
char ch;
@@ -328,7 +328,7 @@ namespace System
//
// Convert this IPv4 address into a sequence of 4 8-bit numbers
//
- unsafe private static bool Parse(string name, byte* numbers, int start, int end)
+ private static unsafe bool Parse(string name, byte* numbers, int start, int end)
{
fixed (char* ipString = name)
{
@@ -351,7 +351,7 @@ namespace System
// of 8-bit numbers and the characters '.'
// Address may terminate with ':' or with the end of the string
//
- unsafe private static bool ParseCanonical(string name, byte* numbers, int start, int end)
+ private static unsafe bool ParseCanonical(string name, byte* numbers, int start, int end)
{
for (int i = 0; i < NumberOfLabels; ++i)
{
diff --git a/src/System.Private.Uri/src/System/IPv6AddressHelper.cs b/src/System.Private.Uri/src/System/IPv6AddressHelper.cs
index 86ecf79f86..991b977e62 100644
--- a/src/System.Private.Uri/src/System/IPv6AddressHelper.cs
+++ b/src/System.Private.Uri/src/System/IPv6AddressHelper.cs
@@ -35,7 +35,7 @@ namespace System
}
}
- internal unsafe static string CreateCanonicalName(ushort* numbers)
+ internal static unsafe string CreateCanonicalName(ushort* numbers)
{
// RFC 5952 Sections 4 & 5 - Compressed, lower case, with possible embedded IPv4 addresses.
@@ -83,7 +83,7 @@ namespace System
// Longest consecutive sequence of zero segments, minimum 2.
// On equal, first sequence wins.
// <-1, -1> for no compression.
- private unsafe static KeyValuePair<int, int> FindCompressionRange(ushort* numbers)
+ private static unsafe KeyValuePair<int, int> FindCompressionRange(ushort* numbers)
{
int longestSequenceLength = 0;
int longestSequenceStart = -1;
@@ -117,7 +117,7 @@ namespace System
// Returns true if the IPv6 address should be formated with an embedded IPv4 address:
// ::192.168.1.1
- private unsafe static bool ShouldHaveIpv4Embedded(ushort* numbers)
+ private static unsafe bool ShouldHaveIpv4Embedded(ushort* numbers)
{
// 0:0 : 0:0 : x:x : x.x.x.x
if (numbers[0] == 0 && numbers[1] == 0 && numbers[2] == 0 && numbers[3] == 0 && numbers[6] != 0)
@@ -175,7 +175,7 @@ namespace System
// Remarks: MUST NOT be used unless all input indexes are verified and trusted.
// start must be next to '[' position, or error is reported
- unsafe private static bool InternalIsValid(char* name, int start, ref int end, bool validateStrictAddress)
+ private static unsafe bool InternalIsValid(char* name, int start, ref int end, bool validateStrictAddress)
{
int sequenceCount = 0;
int sequenceLength = 0;
@@ -346,7 +346,7 @@ namespace System
// Remarks: MUST NOT be used unless all input indexes are verified and trusted.
// start must be next to '[' position, or error is reported
- internal unsafe static bool IsValid(char* name, int start, ref int end)
+ internal static unsafe bool IsValid(char* name, int start, ref int end)
{
return InternalIsValid(name, start, ref end, false);
}
@@ -383,7 +383,7 @@ namespace System
// Remarks: MUST NOT be used unless all input indexes are verified and trusted.
// start must be next to '[' position, or error is reported
- internal unsafe static bool IsValidStrict(char* name, int start, ref int end)
+ internal static unsafe bool IsValidStrict(char* name, int start, ref int end)
{
return InternalIsValid(name, start, ref end, true);
}
@@ -416,7 +416,7 @@ namespace System
// Nothing
//
- unsafe internal static bool Parse(string address, ushort* numbers, int start, ref string scopeId)
+ internal static unsafe bool Parse(string address, ushort* numbers, int start, ref string scopeId)
{
int number = 0;
int index = 0;
diff --git a/src/System.Private.Uri/src/System/UncNameHelper.cs b/src/System.Private.Uri/src/System/UncNameHelper.cs
index b3dfab2802..26cec9d303 100644
--- a/src/System.Private.Uri/src/System/UncNameHelper.cs
+++ b/src/System.Private.Uri/src/System/UncNameHelper.cs
@@ -49,7 +49,7 @@ namespace System
//
// Assumption is the caller will check on the resulting name length
// Remarks: MUST NOT be used unless all input indexes are verified and trusted.
- internal unsafe static bool IsValid(char* name, ushort start, ref int returnedEnd, bool notImplicitFile)
+ internal static unsafe bool IsValid(char* name, ushort start, ref int returnedEnd, bool notImplicitFile)
{
ushort end = (ushort)returnedEnd;
diff --git a/src/System.Private.Uri/src/System/Uri.cs b/src/System.Private.Uri/src/System/Uri.cs
index d9af1f2885..0b49658d66 100644
--- a/src/System.Private.Uri/src/System/Uri.cs
+++ b/src/System.Private.Uri/src/System/Uri.cs
@@ -538,7 +538,7 @@ namespace System
// The assumptions:
// - baseUri is a valid absolute Uri
// - relative part is not null and not empty
- private unsafe static ParsingError GetCombinedString(Uri baseUri, string relativeStr,
+ private static unsafe ParsingError GetCombinedString(Uri baseUri, string relativeStr,
bool dontEscape, ref string result)
{
// NB: This is not RFC2396 compliant although it is inline with w3c.org recommendations
@@ -1944,7 +1944,7 @@ namespace System
return (index >= 0 && uriString[index] == ':');
}
- internal unsafe static string InternalEscapeString(string rawString)
+ internal static unsafe string InternalEscapeString(string rawString)
{
if ((object)rawString == null)
return string.Empty;
@@ -3615,7 +3615,7 @@ namespace System
// returns the start of the next component position
// throws UriFormatException if invalid scheme
//
- unsafe static private ushort ParseSchemeCheckImplicitFile(char* uriString, ushort length,
+ private static unsafe ushort ParseSchemeCheckImplicitFile(char* uriString, ushort length,
ref ParsingError err, ref Flags flags, ref UriParser syntax)
{
ushort idx = 0;
@@ -3730,7 +3730,7 @@ namespace System
//
// Quickly parses well known schemes.
// nChars does not include the last ':'. Assuming there is one at the end of passed buffer
- unsafe static private bool CheckKnownSchemes(long* lptr, ushort nChars, ref UriParser syntax)
+ private static unsafe bool CheckKnownSchemes(long* lptr, ushort nChars, ref UriParser syntax)
{
//NOTE beware of too short input buffers!
@@ -3885,7 +3885,7 @@ namespace System
//
// This will check whether a scheme string follows the rules
//
- unsafe static private ParsingError CheckSchemeSyntax(char* ptr, ushort length, ref UriParser syntax)
+ private static unsafe ParsingError CheckSchemeSyntax(char* ptr, ushort length, ref UriParser syntax)
{
//First character must be an alpha
{
@@ -4830,7 +4830,7 @@ namespace System
}
// works only with ASCII characters, used to partially unescape path before compressing
- private unsafe static void UnescapeOnly(char* pch, int start, ref int end, char ch1, char ch2, char ch3)
+ private static unsafe void UnescapeOnly(char* pch, int start, ref int end, char ch1, char ch2, char ch3)
{
if (end - start < 3)
{
diff --git a/src/System.Private.Uri/src/System/UriHelper.cs b/src/System.Private.Uri/src/System/UriHelper.cs
index ce0039efe8..6a7715c718 100644
--- a/src/System.Private.Uri/src/System/UriHelper.cs
+++ b/src/System.Private.Uri/src/System/UriHelper.cs
@@ -125,7 +125,7 @@ namespace System
private const short c_MaxUnicodeCharsReallocate = 40;
private const short c_MaxUTF_8BytesPerUnicodeChar = 4;
private const short c_EncodedCharsPerByte = 3;
- internal unsafe static char[] EscapeString(string input, int start, int end, char[] dest, ref int destPos,
+ internal static unsafe char[] EscapeString(string input, int start, int end, char[] dest, ref int destPos,
bool isUriString, char force1, char force2, char rsvd)
{
if (end - start >= Uri.c_MaxUriBufferSize)
@@ -229,7 +229,7 @@ namespace System
//
// ensure destination array has enough space and contains all the needed input stuff
//
- private unsafe static char[] EnsureDestinationSize(char* pStr, char[] dest, int currentInputPos,
+ private static unsafe char[] EnsureDestinationSize(char* pStr, char[] dest, int currentInputPos,
short charsToAdd, short minReallocateChars, ref int destPos, int prevInputPos)
{
if ((object)dest == null || dest.Length < destPos + (currentInputPos - prevInputPos) + charsToAdd)
@@ -259,7 +259,7 @@ namespace System
// - It is a RARE case when Unescape actually needs escaping some characters mentioned above.
// For this reason it returns a char[] that is usually the same ref as the input "dest" value.
//
- internal unsafe static char[] UnescapeString(string input, int start, int end, char[] dest,
+ internal static unsafe char[] UnescapeString(string input, int start, int end, char[] dest,
ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax,
bool isQuery)
{
@@ -269,7 +269,7 @@ namespace System
syntax, isQuery);
}
}
- internal unsafe static char[] UnescapeString(char* pStr, int start, int end, char[] dest, ref int destPosition,
+ internal static unsafe char[] UnescapeString(char* pStr, int start, int end, char[] dest, ref int destPosition,
char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery)
{
byte[] bytes = null;
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XCData.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XCData.cs
index 551da96934..e9eee51faa 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XCData.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XCData.cs
@@ -2,6 +2,9 @@
// 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.Threading;
+using System.Threading.Tasks;
+
namespace System.Xml.Linq
{
/// <summary>
@@ -49,6 +52,27 @@ namespace System.Xml.Linq
writer.WriteCData(text);
}
+ /// <summary>
+ /// Write this <see cref="XCData"/> to the given <see cref="XmlWriter"/>.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="XmlWriter"/> to write this <see cref="XCData"/> to.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// The CancellationToken to use to request cancellation of this operation.
+ /// </param>
+ /// <returns>
+ /// A Task that represents the eventual completion of the operation.
+ /// </returns>
+ public override Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ if (writer == null)
+ throw new ArgumentNullException(nameof(writer));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+ return writer.WriteCDataAsync(text);
+ }
+
internal override XNode CloneNode()
{
return new XCData(this);
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XComment.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XComment.cs
index 486d30e1bc..9018092dd4 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XComment.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XComment.cs
@@ -2,6 +2,9 @@
// 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.Threading;
+using System.Threading.Tasks;
+
namespace System.Xml.Linq
{
/// <summary>
@@ -93,6 +96,22 @@ namespace System.Xml.Linq
writer.WriteComment(value);
}
+ /// <summary>
+ /// Write this <see cref="XComment"/> to the passed in <see cref="XmlWriter"/>.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="XmlWriter"/> to write this <see cref="XComment"/> to.
+ /// </param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public override Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ if (writer == null)
+ throw new ArgumentNullException(nameof(writer));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+ return writer.WriteCommentAsync(value);
+ }
+
internal override XNode CloneNode()
{
return new XComment(this);
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XContainer.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XContainer.cs
index ebd9c4a42e..7a3ae67461 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XContainer.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XContainer.cs
@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
using Debug = System.Diagnostics.Debug;
using IEnumerable = System.Collections.IEnumerable;
@@ -853,53 +855,117 @@ namespace System.Xml.Linq
internal void ReadContentFrom(XmlReader r)
{
if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(SR.InvalidOperation_ExpectedInteractive);
- XContainer c = this;
- NamespaceCache eCache = new NamespaceCache();
- NamespaceCache aCache = new NamespaceCache();
+
+ ContentReader cr = new ContentReader(this);
+ while (cr.ReadContentFrom(this, r) && r.Read()) ;
+ }
+
+ internal void ReadContentFrom(XmlReader r, LoadOptions o)
+ {
+ if ((o & (LoadOptions.SetBaseUri | LoadOptions.SetLineInfo)) == 0)
+ {
+ ReadContentFrom(r);
+ return;
+ }
+ if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(SR.InvalidOperation_ExpectedInteractive);
+
+ ContentReader cr = new ContentReader(this, r, o);
+ while (cr.ReadContentFrom(this, r, o) && r.Read()) ;
+ }
+
+ internal async Task ReadContentFromAsync(XmlReader r, CancellationToken cancellationToken)
+ {
+ if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(SR.InvalidOperation_ExpectedInteractive);
+
+ ContentReader cr = new ContentReader(this);
do
{
+ cancellationToken.ThrowIfCancellationRequested();
+ }
+ while (cr.ReadContentFrom(this, r) && await r.ReadAsync().ConfigureAwait(false));
+ }
+
+ internal async Task ReadContentFromAsync(XmlReader r, LoadOptions o, CancellationToken cancellationToken)
+ {
+ if ((o & (LoadOptions.SetBaseUri | LoadOptions.SetLineInfo)) == 0)
+ {
+ await ReadContentFromAsync(r, cancellationToken).ConfigureAwait(false);
+ return;
+ }
+ if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(SR.InvalidOperation_ExpectedInteractive);
+
+ ContentReader cr = new ContentReader(this, r, o);
+ do
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ }
+ while (cr.ReadContentFrom(this, r, o) && await r.ReadAsync().ConfigureAwait(false));
+ }
+
+ private sealed class ContentReader
+ {
+ private readonly NamespaceCache _eCache = new NamespaceCache();
+ private readonly NamespaceCache _aCache = new NamespaceCache();
+ private readonly IXmlLineInfo _lineInfo;
+ private XContainer _currentContainer;
+ private string _baseUri;
+
+ public ContentReader(XContainer rootContainer)
+ {
+ _currentContainer = rootContainer;
+ }
+
+ public ContentReader(XContainer rootContainer, XmlReader r, LoadOptions o)
+ {
+ _currentContainer = rootContainer;
+ _baseUri = (o & LoadOptions.SetBaseUri) != 0 ? r.BaseURI : null;
+ _lineInfo = (o & LoadOptions.SetLineInfo) != 0 ? r as IXmlLineInfo : null;
+ }
+
+ public bool ReadContentFrom(XContainer rootContainer, XmlReader r)
+ {
switch (r.NodeType)
{
case XmlNodeType.Element:
- XElement e = new XElement(eCache.Get(r.NamespaceURI).GetName(r.LocalName));
+ XElement e = new XElement(_eCache.Get(r.NamespaceURI).GetName(r.LocalName));
if (r.MoveToFirstAttribute())
{
do
{
- e.AppendAttributeSkipNotify(new XAttribute(aCache.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value));
+ e.AppendAttributeSkipNotify(new XAttribute(_aCache.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value));
} while (r.MoveToNextAttribute());
r.MoveToElement();
}
- c.AddNodeSkipNotify(e);
+ _currentContainer.AddNodeSkipNotify(e);
if (!r.IsEmptyElement)
{
- c = e;
+ _currentContainer = e;
}
break;
case XmlNodeType.EndElement:
- if (c.content == null)
+ if (_currentContainer.content == null)
{
- c.content = string.Empty;
+ _currentContainer.content = string.Empty;
}
- if (c == this) return;
- c = c.parent;
+ if (_currentContainer == rootContainer) return false;
+ _currentContainer = _currentContainer.parent;
break;
case XmlNodeType.Text:
case XmlNodeType.SignificantWhitespace:
case XmlNodeType.Whitespace:
- c.AddStringSkipNotify(r.Value);
+ _currentContainer.AddStringSkipNotify(r.Value);
break;
case XmlNodeType.CDATA:
- c.AddNodeSkipNotify(new XCData(r.Value));
+ _currentContainer.AddNodeSkipNotify(new XCData(r.Value));
break;
case XmlNodeType.Comment:
- c.AddNodeSkipNotify(new XComment(r.Value));
+ _currentContainer.AddNodeSkipNotify(new XComment(r.Value));
break;
case XmlNodeType.ProcessingInstruction:
- c.AddNodeSkipNotify(new XProcessingInstruction(r.Name, r.Value));
+ _currentContainer.AddNodeSkipNotify(new XProcessingInstruction(r.Name, r.Value));
break;
case XmlNodeType.DocumentType:
- c.AddNodeSkipNotify(new XDocumentType(r.LocalName, r.GetAttribute("PUBLIC"), r.GetAttribute("SYSTEM"), r.Value));
+ _currentContainer.AddNodeSkipNotify(new XDocumentType(r.LocalName, r.GetAttribute("PUBLIC"), r.GetAttribute("SYSTEM"), r.Value));
break;
case XmlNodeType.EntityReference:
if (!r.CanResolveEntity) throw new InvalidOperationException(SR.InvalidOperation_UnresolvedEntityReference);
@@ -910,109 +976,97 @@ namespace System.Xml.Linq
default:
throw new InvalidOperationException(SR.Format(SR.InvalidOperation_UnexpectedNodeType, r.NodeType));
}
- } while (r.Read());
- }
-
- internal void ReadContentFrom(XmlReader r, LoadOptions o)
- {
- if ((o & (LoadOptions.SetBaseUri | LoadOptions.SetLineInfo)) == 0)
- {
- ReadContentFrom(r);
- return;
+ return true;
}
- if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(SR.InvalidOperation_ExpectedInteractive);
- XContainer c = this;
- XNode n = null;
- NamespaceCache eCache = new NamespaceCache();
- NamespaceCache aCache = new NamespaceCache();
- string baseUri = (o & LoadOptions.SetBaseUri) != 0 ? r.BaseURI : null;
- IXmlLineInfo li = (o & LoadOptions.SetLineInfo) != 0 ? r as IXmlLineInfo : null;
- do
+
+ public bool ReadContentFrom(XContainer rootContainer, XmlReader r, LoadOptions o)
{
- string uri = r.BaseURI;
+ XNode newNode = null;
+ string baseUri = r.BaseURI;
+
switch (r.NodeType)
{
case XmlNodeType.Element:
+ {
+ XElement e = new XElement(_eCache.Get(r.NamespaceURI).GetName(r.LocalName));
+ if (_baseUri != null && _baseUri != baseUri)
{
- XElement e = new XElement(eCache.Get(r.NamespaceURI).GetName(r.LocalName));
- if (baseUri != null && baseUri != uri)
- {
- e.SetBaseUri(uri);
- }
- if (li != null && li.HasLineInfo())
- {
- e.SetLineInfo(li.LineNumber, li.LinePosition);
- }
- if (r.MoveToFirstAttribute())
- {
- do
- {
- XAttribute a = new XAttribute(aCache.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value);
- if (li != null && li.HasLineInfo())
- {
- a.SetLineInfo(li.LineNumber, li.LinePosition);
- }
- e.AppendAttributeSkipNotify(a);
- } while (r.MoveToNextAttribute());
- r.MoveToElement();
- }
- c.AddNodeSkipNotify(e);
- if (!r.IsEmptyElement)
+ e.SetBaseUri(baseUri);
+ }
+ if (_lineInfo != null && _lineInfo.HasLineInfo())
+ {
+ e.SetLineInfo(_lineInfo.LineNumber, _lineInfo.LinePosition);
+ }
+ if (r.MoveToFirstAttribute())
+ {
+ do
{
- c = e;
- if (baseUri != null)
+ XAttribute a = new XAttribute(_aCache.Get(r.Prefix.Length == 0 ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value);
+ if (_lineInfo != null && _lineInfo.HasLineInfo())
{
- baseUri = uri;
+ a.SetLineInfo(_lineInfo.LineNumber, _lineInfo.LinePosition);
}
- }
- break;
+ e.AppendAttributeSkipNotify(a);
+ } while (r.MoveToNextAttribute());
+ r.MoveToElement();
}
- case XmlNodeType.EndElement:
+ _currentContainer.AddNodeSkipNotify(e);
+ if (!r.IsEmptyElement)
{
- if (c.content == null)
- {
- c.content = string.Empty;
- }
- // Store the line info of the end element tag.
- // Note that since we've got EndElement the current container must be an XElement
- XElement e = c as XElement;
- Debug.Assert(e != null, "EndElement received but the current container is not an element.");
- if (e != null && li != null && li.HasLineInfo())
- {
- e.SetEndElementLineInfo(li.LineNumber, li.LinePosition);
- }
- if (c == this) return;
- if (baseUri != null && c.HasBaseUri)
+ _currentContainer = e;
+ if (_baseUri != null)
{
- baseUri = c.parent.BaseUri;
+ _baseUri = baseUri;
}
- c = c.parent;
- break;
}
+ break;
+ }
+ case XmlNodeType.EndElement:
+ {
+ if (_currentContainer.content == null)
+ {
+ _currentContainer.content = string.Empty;
+ }
+ // Store the line info of the end element tag.
+ // Note that since we've got EndElement the current container must be an XElement
+ XElement e = _currentContainer as XElement;
+ Debug.Assert(e != null, "EndElement received but the current container is not an element.");
+ if (e != null && _lineInfo != null && _lineInfo.HasLineInfo())
+ {
+ e.SetEndElementLineInfo(_lineInfo.LineNumber, _lineInfo.LinePosition);
+ }
+ if (_currentContainer == rootContainer) return false;
+ if (_baseUri != null && _currentContainer.HasBaseUri)
+ {
+ _baseUri = _currentContainer.parent.BaseUri;
+ }
+ _currentContainer = _currentContainer.parent;
+ break;
+ }
case XmlNodeType.Text:
case XmlNodeType.SignificantWhitespace:
case XmlNodeType.Whitespace:
- if ((baseUri != null && baseUri != uri) ||
- (li != null && li.HasLineInfo()))
+ if ((_baseUri != null && _baseUri != baseUri) ||
+ (_lineInfo != null && _lineInfo.HasLineInfo()))
{
- n = new XText(r.Value);
+ newNode = new XText(r.Value);
}
else
{
- c.AddStringSkipNotify(r.Value);
+ _currentContainer.AddStringSkipNotify(r.Value);
}
break;
case XmlNodeType.CDATA:
- n = new XCData(r.Value);
+ newNode = new XCData(r.Value);
break;
case XmlNodeType.Comment:
- n = new XComment(r.Value);
+ newNode = new XComment(r.Value);
break;
case XmlNodeType.ProcessingInstruction:
- n = new XProcessingInstruction(r.Name, r.Value);
+ newNode = new XProcessingInstruction(r.Name, r.Value);
break;
case XmlNodeType.DocumentType:
- n = new XDocumentType(r.LocalName, r.GetAttribute("PUBLIC"), r.GetAttribute("SYSTEM"), r.Value);
+ newNode = new XDocumentType(r.LocalName, r.GetAttribute("PUBLIC"), r.GetAttribute("SYSTEM"), r.Value);
break;
case XmlNodeType.EntityReference:
if (!r.CanResolveEntity) throw new InvalidOperationException(SR.InvalidOperation_UnresolvedEntityReference);
@@ -1023,20 +1077,25 @@ namespace System.Xml.Linq
default:
throw new InvalidOperationException(SR.Format(SR.InvalidOperation_UnexpectedNodeType, r.NodeType));
}
- if (n != null)
+
+ if (newNode != null)
{
- if (baseUri != null && baseUri != uri)
+ if (_baseUri != null && _baseUri != baseUri)
{
- n.SetBaseUri(uri);
+ newNode.SetBaseUri(baseUri);
}
- if (li != null && li.HasLineInfo())
+
+ if (_lineInfo != null && _lineInfo.HasLineInfo())
{
- n.SetLineInfo(li.LineNumber, li.LinePosition);
+ newNode.SetLineInfo(_lineInfo.LineNumber, _lineInfo.LinePosition);
}
- c.AddNodeSkipNotify(n);
- n = null;
+
+ _currentContainer.AddNodeSkipNotify(newNode);
+ newNode = null;
}
- } while (r.Read());
+
+ return true;
+ }
}
internal void RemoveNode(XNode n)
@@ -1113,6 +1172,41 @@ namespace System.Xml.Linq
}
}
+ internal async Task WriteContentToAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ if (content != null)
+ {
+ string stringContent = content as string;
+
+ if (stringContent != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ Task tWrite;
+
+ if (this is XDocument)
+ {
+ tWrite = writer.WriteWhitespaceAsync(stringContent);
+ }
+ else
+ {
+ tWrite = writer.WriteStringAsync(stringContent);
+ }
+
+ await tWrite.ConfigureAwait(false);
+ }
+ else
+ {
+ XNode n = (XNode)content;
+ do
+ {
+ n = n.next;
+ await n.WriteToAsync(writer, cancellationToken).ConfigureAwait(false);
+ } while (n != content);
+ }
+ }
+ }
+
private static void AddContentToList(List<object> list, object content)
{
IEnumerable e = content is string ? null : content as IEnumerable;
@@ -1129,7 +1223,7 @@ namespace System.Xml.Linq
}
}
- static internal object GetContentSnapshot(object content)
+ internal static object GetContentSnapshot(object content)
{
if (content is string || !(content is IEnumerable)) return content;
List<object> list = new List<object>();
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocument.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocument.cs
index a7f3ccd36f..1957ec2e14 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocument.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocument.cs
@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute;
using Encoding = System.Text.Encoding;
@@ -270,6 +272,42 @@ namespace System.Xml.Linq
/// <summary>
/// Create a new <see cref="XDocument"/> and initialize its underlying XML tree using
+ /// the passed <see cref="Stream"/> parameter. Optionally whitespace handling
+ /// can be preserved.
+ /// </summary>
+ /// <remarks>
+ /// If LoadOptions.PreserveWhitespace is enabled then
+ /// the underlying <see cref="XmlReaderSettings"/> property <see cref="XmlReaderSettings.IgnoreWhitespace"/>
+ /// is set to false.
+ /// </remarks>
+ /// <param name="stream">
+ /// A <see cref="Stream"/> containing the raw XML to read into the newly
+ /// created <see cref="XDocument"/>.
+ /// </param>
+ /// <param name="options">
+ /// A set of <see cref="LoadOptions"/>.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A cancellation token.
+ /// </param>
+ /// <returns>
+ /// A new <see cref="XDocument"/> containing the contents of the passed in
+ /// <see cref="Stream"/>.
+ /// </returns>
+ public static async Task<XDocument> LoadAsync(Stream stream, LoadOptions options, CancellationToken cancellationToken)
+ {
+ XmlReaderSettings rs = GetXmlReaderSettings(options);
+
+ rs.Async = true;
+
+ using (XmlReader r = XmlReader.Create(stream, rs))
+ {
+ return await LoadAsync(r, options, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ /// <summary>
+ /// Create a new <see cref="XDocument"/> and initialize its underlying XML tree using
/// the passed <see cref="TextReader"/> parameter.
/// </summary>
/// <param name="textReader">
@@ -316,6 +354,42 @@ namespace System.Xml.Linq
}
/// <summary>
+ /// Create a new <see cref="XDocument"/> and initialize its underlying XML tree using
+ /// the passed <see cref="TextReader"/> parameter. Optionally whitespace handling
+ /// can be preserved.
+ /// </summary>
+ /// <remarks>
+ /// If LoadOptions.PreserveWhitespace is enabled then
+ /// the <see cref="XmlReaderSettings"/> property <see cref="XmlReaderSettings.IgnoreWhitespace"/>
+ /// is set to false.
+ /// </remarks>
+ /// <param name="textReader">
+ /// A <see cref="TextReader"/> containing the raw XML to read into the newly
+ /// created <see cref="XDocument"/>.
+ /// </param>
+ /// <param name="options">
+ /// A set of <see cref="LoadOptions"/>.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A cancellation token.
+ /// </param>
+ /// <returns>
+ /// A new <see cref="XDocument"/> containing the contents of the passed in
+ /// <see cref="TextReader"/>.
+ /// </returns>
+ public static async Task<XDocument> LoadAsync(TextReader textReader, LoadOptions options, CancellationToken cancellationToken)
+ {
+ XmlReaderSettings rs = GetXmlReaderSettings(options);
+
+ rs.Async = true;
+
+ using (XmlReader r = XmlReader.Create(textReader, rs))
+ {
+ return await LoadAsync(r, options, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ /// <summary>
/// Create a new <see cref="XDocument"/> containing the contents of the
/// passed in <see cref="XmlReader"/>.
/// </summary>
@@ -351,6 +425,62 @@ namespace System.Xml.Linq
{
if (reader == null) throw new ArgumentNullException(nameof(reader));
if (reader.ReadState == ReadState.Initial) reader.Read();
+
+ XDocument d = InitLoad(reader, options);
+ d.ReadContentFrom(reader, options);
+
+ if( !reader.EOF) throw new InvalidOperationException(SR.InvalidOperation_ExpectedEndOfFile);
+ if (d.Root == null) throw new InvalidOperationException(SR.InvalidOperation_MissingRoot);
+ return d;
+ }
+
+ /// <summary>
+ /// Create a new <see cref="XDocument"/> containing the contents of the
+ /// passed in <see cref="XmlReader"/>.
+ /// </summary>
+ /// <param name="reader">
+ /// An <see cref="XmlReader"/> containing the XML to be read into the new
+ /// <see cref="XDocument"/>.
+ /// </param>
+ /// <param name="options">
+ /// A set of <see cref="LoadOptions"/>.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A cancellation token.
+ /// </param>
+ /// <returns>
+ /// A new <see cref="XDocument"/> containing the contents of the passed
+ /// in <see cref="XmlReader"/>.
+ /// </returns>
+ public static Task<XDocument> LoadAsync(XmlReader reader, LoadOptions options, CancellationToken cancellationToken)
+ {
+ if (reader == null)
+ throw new ArgumentNullException(nameof(reader));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<XDocument>(cancellationToken);
+ return LoadAsyncInternal(reader, options, cancellationToken);
+ }
+
+ private static async Task<XDocument> LoadAsyncInternal(XmlReader reader, LoadOptions options, CancellationToken cancellationToken)
+ {
+ if (reader.ReadState == ReadState.Initial)
+ {
+ await reader.ReadAsync().ConfigureAwait(false);
+ }
+
+ XDocument d = InitLoad(reader, options);
+ await d.ReadContentFromAsync(reader, options, cancellationToken).ConfigureAwait(false);
+
+ if (!reader.EOF) throw new InvalidOperationException(SR.InvalidOperation_ExpectedEndOfFile);
+ if (d.Root == null) throw new InvalidOperationException(SR.InvalidOperation_MissingRoot);
+ return d;
+ }
+
+ /// <summary>
+ /// Performs shared initialization between Load and LoadAsync.
+ /// </summary>
+ static XDocument InitLoad(XmlReader reader, LoadOptions options)
+ {
XDocument d = new XDocument();
if ((options & LoadOptions.SetBaseUri) != 0)
{
@@ -372,9 +502,6 @@ namespace System.Xml.Linq
{
d.Declaration = new XDeclaration(reader);
}
- d.ReadContentFrom(reader, options);
- if (!reader.EOF) throw new InvalidOperationException(SR.InvalidOperation_ExpectedEndOfFile);
- if (d.Root == null) throw new InvalidOperationException(SR.InvalidOperation_MissingRoot);
return d;
}
@@ -481,6 +608,40 @@ namespace System.Xml.Linq
}
/// <summary>
+ /// Output this <see cref="XDocument"/> to a <see cref="Stream"/>.
+ /// </summary>
+ /// <param name="stream">
+ /// The <see cref="Stream"/> to output the XML to.
+ /// </param>
+ /// <param name="options">
+ /// If SaveOptions.DisableFormatting is enabled the output is not indented.
+ /// If SaveOptions.OmitDuplicateNamespaces is enabled duplicate namespace declarations will be removed.
+ /// </param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public async Task SaveAsync(Stream stream, SaveOptions options, CancellationToken cancellationToken)
+ {
+ XmlWriterSettings ws = GetXmlWriterSettings(options);
+
+ ws.Async = true;
+
+ if (_declaration != null && !string.IsNullOrEmpty(_declaration.Encoding))
+ {
+ try
+ {
+ ws.Encoding = Encoding.GetEncoding(_declaration.Encoding);
+ }
+ catch (ArgumentException)
+ {
+ }
+ }
+
+ using (XmlWriter w = XmlWriter.Create(stream, ws))
+ {
+ await WriteToAsync(w, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ /// <summary>
/// Output this <see cref="XDocument"/> to the passed in <see cref="TextWriter"/>.
/// </summary>
/// <remarks>
@@ -529,6 +690,29 @@ namespace System.Xml.Linq
WriteTo(writer);
}
+ /// <summary>
+ /// Output this <see cref="XDocument"/> to a <see cref="TextWriter"/>.
+ /// </summary>
+ /// <param name="textWriter">
+ /// The <see cref="TextWriter"/> to output the XML to.
+ /// </param>
+ /// <param name="options">
+ /// If SaveOptions.DisableFormatting is enabled the output is not indented.
+ /// If SaveOptions.OmitDuplicateNamespaces is enabled duplicate namespace declarations will be removed.
+ /// </param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public async Task SaveAsync(TextWriter textWriter, SaveOptions options, CancellationToken cancellationToken)
+ {
+ XmlWriterSettings ws = GetXmlWriterSettings(options);
+
+ ws.Async = true;
+
+ using (XmlWriter w = XmlWriter.Create(textWriter, ws))
+ {
+ await WriteToAsync(w, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
///<overloads>
/// Outputs this <see cref="XDocument"/>'s underlying XML tree. The output can
/// be saved to a file, a <see cref="Stream"/>, a <see cref="TextWriter"/>,
@@ -554,6 +738,20 @@ namespace System.Xml.Linq
}
/// <summary>
+ /// Output this <see cref="XDocument"/> to an <see cref="XmlWriter"/>.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="XmlWriter"/> to output the XML to.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A cancellation token.
+ /// </param>
+ public Task SaveAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ return WriteToAsync(writer, cancellationToken);
+ }
+
+ /// <summary>
/// Output this <see cref="XDocument"/> to a file.
/// </summary>
/// <param name="fileName">
@@ -611,6 +809,46 @@ namespace System.Xml.Linq
writer.WriteEndDocument();
}
+ /// <summary>
+ /// Output this <see cref="XDocument"/>'s underlying XML tree to the
+ /// passed in <see cref="XmlWriter"/>.
+ /// <seealso cref="XDocument.Save(XmlWriter)"/>
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="XmlWriter"/> to output the content of this
+ /// <see cref="XDocument"/>.
+ /// </param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public override Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ if (writer == null)
+ throw new ArgumentNullException(nameof(writer));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+ return WriteToAsyncInternal(writer, cancellationToken);
+ }
+
+ private async Task WriteToAsyncInternal(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ Task tStart;
+ if (_declaration != null && _declaration.Standalone == "yes")
+ {
+ tStart = writer.WriteStartDocumentAsync(true);
+ }
+ else if (_declaration != null && _declaration.Standalone == "no")
+ {
+ tStart = writer.WriteStartDocumentAsync(false);
+ }
+ else
+ {
+ tStart = writer.WriteStartDocumentAsync();
+ }
+ await tStart.ConfigureAwait(false);
+
+ await WriteContentToAsync(writer, cancellationToken).ConfigureAwait(false);
+ await writer.WriteEndDocumentAsync().ConfigureAwait(false);
+ }
+
internal override void AddAttribute(XAttribute a)
{
throw new ArgumentException(SR.Argument_AddAttribute);
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocumentType.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocumentType.cs
index 3f4a031d07..64c2ce977f 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocumentType.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XDocumentType.cs
@@ -2,6 +2,9 @@
// 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.Threading;
+using System.Threading.Tasks;
+
namespace System.Xml.Linq
{
/// <summary>
@@ -143,6 +146,24 @@ namespace System.Xml.Linq
writer.WriteDocType(_name, _publicId, _systemId, _internalSubset);
}
+ /// <summary>
+ /// Write this <see cref="XDocumentType"/> to the passed in <see cref="XmlWriter"/>.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="XmlWriter"/> to write this <see cref="XDocumentType"/> to.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A cancellation token.
+ /// </param>
+ public override Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ if (writer == null)
+ throw new ArgumentNullException(nameof(writer));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+ return writer.WriteDocTypeAsync(_name, _publicId, _systemId, _internalSubset);
+ }
+
internal override XNode CloneNode()
{
return new XDocumentType(this);
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XElement.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XElement.cs
index 61ef13bbeb..c15850ea25 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XElement.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XElement.cs
@@ -6,6 +6,8 @@ using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using System.Xml.Schema;
+using System.Threading;
+using System.Threading.Tasks;
using CultureInfo = System.Globalization.CultureInfo;
using IEnumerable = System.Collections.IEnumerable;
@@ -137,11 +139,29 @@ namespace System.Xml.Linq
{
}
+ private XElement(AsyncConstructionSentry s)
+ {
+ // Dummy ctor used to avoid public default ctor. This is used
+ // by async methods meant to perform the same operations as
+ // the XElement constructors that do synchronous processing;
+ // the async methods instead construct an XElement using this
+ // constructor (which doesn't do any processing) and then themselves
+ // do the async processing. This is because ctors can't be 'async'.
+ }
+ private struct AsyncConstructionSentry { }
+
internal XElement(XmlReader r, LoadOptions o)
{
ReadElementFrom(r, o);
}
+ internal static async Task<XElement> CreateAsync(XmlReader r, CancellationToken cancellationToken)
+ {
+ XElement xe = new XElement(default(AsyncConstructionSentry));
+ await xe.ReadElementFromAsync(r, LoadOptions.None, cancellationToken).ConfigureAwait(false);
+ return xe;
+ }
+
///<overloads>
/// Outputs this <see cref="XElement"/>'s underlying XML tree. The output can
/// be saved to a file, a <see cref="Stream"/>, a <see cref="TextWriter"/>,
@@ -632,6 +652,42 @@ namespace System.Xml.Linq
return Load(r, options);
}
}
+
+ /// <summary>
+ /// Create a new <see cref="XElement"/> and initialize its underlying XML tree using
+ /// the passed <see cref="Stream"/> parameter. Optionally whitespace handling
+ /// can be preserved.
+ /// </summary>
+ /// <remarks>
+ /// If LoadOptions.PreserveWhitespace is enabled then
+ /// the <see cref="XmlReaderSettings"/> property <see cref="XmlReaderSettings.IgnoreWhitespace"/>
+ /// is set to false.
+ /// </remarks>
+ /// <param name="stream">
+ /// A <see cref="Stream"/> containing the raw XML to read into the newly
+ /// created <see cref="XElement"/>.
+ /// </param>
+ /// <param name="options">
+ /// A set of <see cref="LoadOptions"/>.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A cancellation token.</param>
+ /// <returns>
+ /// A new <see cref="XElement"/> containing the contents of the passed in
+ /// <see cref="Stream"/>.
+ /// </returns>
+ public static async Task<XElement> LoadAsync(Stream stream, LoadOptions options, CancellationToken cancellationToken)
+ {
+ XmlReaderSettings rs = GetXmlReaderSettings(options);
+
+ rs.Async = true;
+
+ using (XmlReader r = XmlReader.Create(stream, rs))
+ {
+ return await LoadAsync(r, options, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
/// <summary>
/// Create a new <see cref="XElement"/> and initialize its underlying XML tree using
/// the passed <see cref="TextReader"/> parameter.
@@ -680,6 +736,41 @@ namespace System.Xml.Linq
}
/// <summary>
+ /// Create a new <see cref="XElement"/> and initialize its underlying XML tree using
+ /// the passed <see cref="TextReader"/> parameter. Optionally whitespace handling
+ /// can be preserved.
+ /// </summary>
+ /// <remarks>
+ /// If LoadOptions.PreserveWhitespace is enabled then
+ /// the <see cref="XmlReaderSettings"/> property <see cref="XmlReaderSettings.IgnoreWhitespace"/>
+ /// is set to false.
+ /// </remarks>
+ /// <param name="textReader">
+ /// A <see cref="TextReader"/> containing the raw XML to read into the newly
+ /// created <see cref="XElement"/>.
+ /// </param>
+ /// <param name="options">
+ /// A set of <see cref="LoadOptions"/>.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A cancellation token.</param>
+ /// <returns>
+ /// A new <see cref="XElement"/> containing the contents of the passed in
+ /// <see cref="TextReader"/>.
+ /// </returns>
+ public static async Task<XElement> LoadAsync(TextReader textReader, LoadOptions options, CancellationToken cancellationToken)
+ {
+ XmlReaderSettings rs = GetXmlReaderSettings(options);
+
+ rs.Async = true;
+
+ using (XmlReader r = XmlReader.Create(textReader, rs))
+ {
+ return await LoadAsync(r, options, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ /// <summary>
/// Create a new <see cref="XElement"/> containing the contents of the
/// passed in <see cref="XmlReader"/>.
/// </summary>
@@ -721,6 +812,46 @@ namespace System.Xml.Linq
return e;
}
+ /// <summary>
+ /// Create a new <see cref="XElement"/> containing the contents of the
+ /// passed in <see cref="XmlReader"/>.
+ /// </summary>
+ /// <param name="reader">
+ /// An <see cref="XmlReader"/> containing the XML to be read into the new
+ /// <see cref="XElement"/>.
+ /// </param>
+ /// <param name="options">
+ /// A set of <see cref="LoadOptions"/>.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A cancellation token.</param>
+ /// <returns>
+ /// A new <see cref="XElement"/> containing the contents of the passed
+ /// in <see cref="XmlReader"/>.
+ /// </returns>
+ public static Task<XElement> LoadAsync(XmlReader reader, LoadOptions options, CancellationToken cancellationToken)
+ {
+ if (reader == null)
+ throw new ArgumentNullException(nameof(reader));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<XElement>(cancellationToken);
+ return LoadAsyncInternal(reader, options, cancellationToken);
+ }
+
+ private static async Task<XElement> LoadAsyncInternal(XmlReader reader, LoadOptions options, CancellationToken cancellationToken)
+ {
+ if (await reader.MoveToContentAsync().ConfigureAwait(false) != XmlNodeType.Element) throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ExpectedNodeType, XmlNodeType.Element, reader.NodeType));
+
+ XElement e = new XElement(new AsyncConstructionSentry());
+ await e.ReadElementFromAsync(reader, options, cancellationToken).ConfigureAwait(false);
+
+ cancellationToken.ThrowIfCancellationRequested();
+ await reader.MoveToContentAsync().ConfigureAwait(false);
+
+ if (!reader.EOF) throw new InvalidOperationException(SR.InvalidOperation_ExpectedEndOfFile);
+ return e;
+ }
+
/// <overloads>
/// Parses a string containing XML into an <see cref="XElement"/>. Optionally
/// whitespace can be preserved.
@@ -933,6 +1064,29 @@ namespace System.Xml.Linq
}
/// <summary>
+ /// Output this <see cref="XElement"/> to a <see cref="Stream"/>.
+ /// </summary>
+ /// <param name="stream">
+ /// The <see cref="Stream"/> to output the XML to.
+ /// </param>
+ /// <param name="options">
+ /// If SaveOptions.DisableFormatting is enabled the output is not indented.
+ /// If SaveOptions.OmitDuplicateNamespaces is enabled duplicate namespace declarations will be removed.
+ /// </param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public async Task SaveAsync(Stream stream, SaveOptions options, CancellationToken cancellationToken)
+ {
+ XmlWriterSettings ws = GetXmlWriterSettings(options);
+
+ ws.Async = true;
+
+ using (XmlWriter w = XmlWriter.Create(stream, ws))
+ {
+ await SaveAsync(w, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ /// <summary>
/// Output this <see cref="XElement"/> to the passed in <see cref="TextWriter"/>.
/// </summary>
/// <remarks>
@@ -971,6 +1125,29 @@ namespace System.Xml.Linq
}
/// <summary>
+ /// Output this <see cref="XElement"/> to a <see cref="TextWriter"/>.
+ /// </summary>
+ /// <param name="textWriter">
+ /// The <see cref="TextWriter"/> to output the XML to.
+ /// </param>
+ /// <param name="options">
+ /// If SaveOptions.DisableFormatting is enabled the output is not indented.
+ /// If SaveOptions.OmitDuplicateNamespaces is enabled duplicate namespace declarations will be removed.
+ /// </param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public async Task SaveAsync(TextWriter textWriter, SaveOptions options, CancellationToken cancellationToken)
+ {
+ XmlWriterSettings ws = GetXmlWriterSettings(options);
+
+ ws.Async = true;
+
+ using (XmlWriter w = XmlWriter.Create(textWriter, ws))
+ {
+ await SaveAsync(w, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ /// <summary>
/// Output this <see cref="XElement"/> to an <see cref="XmlWriter"/>.
/// </summary>
/// <param name="writer">
@@ -985,6 +1162,32 @@ namespace System.Xml.Linq
}
/// <summary>
+ /// Output this <see cref="XElement"/> to an <see cref="XmlWriter"/>.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="XmlWriter"/> to output the XML to.
+ /// </param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public Task SaveAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ if (writer == null)
+ throw new ArgumentNullException(nameof(writer));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+ return SaveAsyncInternal(writer, cancellationToken);
+ }
+
+ private async Task SaveAsyncInternal(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ await writer.WriteStartDocumentAsync().ConfigureAwait(false);
+
+ await WriteToAsync(writer, cancellationToken).ConfigureAwait(false);
+
+ cancellationToken.ThrowIfCancellationRequested();
+ await writer.WriteEndDocumentAsync().ConfigureAwait(false);
+ }
+
+ /// <summary>
/// Sets the value of an attribute. The value is assigned to the attribute with the given
/// name. If no attribute with the given name exists, a new attribute is added. If the
/// value is null, the attribute with the given name, if any, is deleted.
@@ -1095,6 +1298,22 @@ namespace System.Xml.Linq
}
/// <summary>
+ /// Write this <see cref="XElement"/> to the passed in <see cref="XmlTextWriter"/>.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="XmlTextWriter"/> to write this <see cref="XElement"/> to.
+ /// </param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public override Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ if (writer == null)
+ throw new ArgumentNullException(nameof(writer));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+ return new ElementWriter(writer).WriteElementAsync(this, cancellationToken);
+ }
+
+ /// <summary>
/// Cast the value of this <see cref="XElement"/> to a <see cref="string"/>.
/// </summary>
/// <remarks>
@@ -1784,7 +2003,39 @@ namespace System.Xml.Linq
private void ReadElementFrom(XmlReader r, LoadOptions o)
{
- if (r.ReadState != ReadState.Interactive) throw new InvalidOperationException(SR.InvalidOperation_ExpectedInteractive);
+ ReadElementFromImpl(r, o);
+
+ if (!r.IsEmptyElement)
+ {
+ r.Read();
+ ReadContentFrom(r, o);
+ }
+
+ r.Read();
+ }
+
+ private async Task ReadElementFromAsync(XmlReader r, LoadOptions o, CancellationToken cancellationTokentoken)
+ {
+ ReadElementFromImpl(r, o);
+
+ if (!r.IsEmptyElement)
+ {
+ cancellationTokentoken.ThrowIfCancellationRequested();
+ await r.ReadAsync().ConfigureAwait(false);
+
+ await ReadContentFromAsync(r, o, cancellationTokentoken).ConfigureAwait(false);
+ }
+
+ cancellationTokentoken.ThrowIfCancellationRequested();
+ await r.ReadAsync().ConfigureAwait(false);
+ }
+
+ /// <summary>
+ /// Shared implementation between ReadElementFrom / ReadElementFromAsync.
+ /// </summary>
+ private void ReadElementFromImpl(XmlReader r, LoadOptions o)
+ {
+ if(r.ReadState != ReadState.Interactive) throw new InvalidOperationException(SR.InvalidOperation_ExpectedInteractive);
name = XNamespace.Get(r.NamespaceURI).GetName(r.LocalName);
if ((o & LoadOptions.SetBaseUri) != 0)
{
@@ -1816,12 +2067,6 @@ namespace System.Xml.Linq
} while (r.MoveToNextAttribute());
r.MoveToElement();
}
- if (!r.IsEmptyElement)
- {
- r.Read();
- ReadContentFrom(r, o);
- }
- r.Read();
}
internal void RemoveAttribute(XAttribute a)
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XLinq.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XLinq.cs
index 95d4cde8c4..5ae8f32a4a 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XLinq.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XLinq.cs
@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
using IEnumerable = System.Collections.IEnumerable;
using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute;
@@ -246,6 +248,51 @@ namespace System.Xml.Linq
}
}
+ public async Task WriteElementAsync(XElement e, CancellationToken cancellationToken)
+ {
+ PushAncestors(e);
+ XElement root = e;
+ XNode n = e;
+ while (true)
+ {
+ e = n as XElement;
+ if (e != null)
+ {
+ await WriteStartElementAsync(e, cancellationToken).ConfigureAwait(false);
+ if (e.content == null)
+ {
+ await WriteEndElementAsync(cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ string s = e.content as string;
+ if (s != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await _writer.WriteStringAsync(s).ConfigureAwait(false);
+ await WriteFullEndElementAsync(cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ n = ((XNode) e.content).next;
+ continue;
+ }
+ }
+ }
+ else
+ {
+ await n.WriteToAsync(_writer, cancellationToken).ConfigureAwait(false);
+ }
+ while (n != root && n == n.parent.content)
+ {
+ n = n.parent;
+ await WriteFullEndElementAsync(cancellationToken).ConfigureAwait(false);
+ }
+ if (n == root) break;
+ n = n.next;
+ }
+ }
+
private string GetPrefixOfNamespace(XNamespace ns, bool allowDefaultNamespace)
{
string namespaceName = ns.NamespaceName;
@@ -300,6 +347,13 @@ namespace System.Xml.Linq
_writer.WriteEndElement();
_resolver.PopScope();
}
+
+ private async Task WriteEndElementAsync(CancellationToken cancellationToken)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await _writer.WriteEndElementAsync().ConfigureAwait(false);
+ _resolver.PopScope();
+ }
private void WriteFullEndElement()
{
@@ -307,6 +361,13 @@ namespace System.Xml.Linq
_resolver.PopScope();
}
+ private async Task WriteFullEndElementAsync(CancellationToken cancellationToken)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await _writer.WriteFullEndElementAsync().ConfigureAwait(false);
+ _resolver.PopScope();
+ }
+
private void WriteStartElement(XElement e)
{
PushElement(e);
@@ -325,6 +386,25 @@ namespace System.Xml.Linq
} while (a != e.lastAttr);
}
}
+
+ async Task WriteStartElementAsync(XElement e, CancellationToken cancellationToken)
+ {
+ PushElement(e);
+ XNamespace ns = e.Name.Namespace;
+ await _writer.WriteStartElementAsync(GetPrefixOfNamespace(ns, true), e.Name.LocalName, ns.NamespaceName).ConfigureAwait(false);
+ XAttribute a = e.lastAttr;
+ if (a != null)
+ {
+ do
+ {
+ a = a.next;
+ ns = a.Name.Namespace;
+ string localName = a.Name.LocalName;
+ string namespaceName = ns.NamespaceName;
+ await _writer.WriteAttributeStringAsync(GetPrefixOfNamespace(ns, false), localName, namespaceName.Length == 0 && localName == "xmlns" ? XNamespace.xmlnsPrefixNamespace : namespaceName, a.Value).ConfigureAwait(false);
+ } while (a != e.lastAttr);
+ }
+ }
}
internal struct NamespaceResolver
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XName.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XName.cs
index b7ff5e1911..1285b10a36 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XName.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XName.cs
@@ -11,6 +11,7 @@ namespace System.Xml.Linq
/// Represents a name of an XML element or attribute. This class cannot be inherited.
/// </summary>
[Serializable]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Serialization", "CA2229", Justification = "Serialized with custom proxy")]
public sealed class XName : IEquatable<XName>, ISerializable
{
private XNamespace _ns;
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XNode.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XNode.cs
index b4740d5cad..110823dc16 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XNode.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XNode.cs
@@ -4,6 +4,8 @@
using System.Collections.Generic;
using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
using CultureInfo = System.Globalization.CultureInfo;
using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute;
@@ -462,6 +464,72 @@ namespace System.Xml.Linq
}
/// <summary>
+ /// Creates an <see cref="XNode"/> from an <see cref="XmlReader"/>.
+ /// The runtime type of the node is determined by the node type
+ /// (<see cref="XObject.NodeType"/>) of the first node encountered
+ /// in the reader.
+ /// </summary>
+ /// <param name="reader">An <see cref="XmlReader"/> positioned at the node to read into this <see cref="XNode"/>.</param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ /// <returns>An <see cref="XNode"/> that contains the nodes read from the reader.</returns>
+ /// <exception cref="InvalidOperationException">
+ /// Thrown if the <see cref="XmlReader"/> is not positioned on a recognized node type.
+ /// </exception>
+ public static Task<XNode> ReadFromAsync(XmlReader reader, CancellationToken cancellationToken)
+ {
+ if (reader == null)
+ throw new ArgumentNullException(nameof(reader));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<XNode>(cancellationToken);
+ return ReadFromAsyncInternal(reader, cancellationToken);
+ }
+
+ private static async Task<XNode> ReadFromAsyncInternal(XmlReader reader, CancellationToken cancellationToken)
+ {
+ if (reader.ReadState != ReadState.Interactive) throw new InvalidOperationException(SR.InvalidOperation_ExpectedInteractive);
+
+ XNode ret;
+
+ switch (reader.NodeType)
+ {
+ case XmlNodeType.Text:
+ case XmlNodeType.SignificantWhitespace:
+ case XmlNodeType.Whitespace:
+ ret = new XText(reader.Value);
+ break;
+ case XmlNodeType.CDATA:
+ ret = new XCData(reader.Value);
+ break;
+ case XmlNodeType.Comment:
+ ret = new XComment(reader.Value);
+ break;
+ case XmlNodeType.DocumentType:
+ var name = reader.Name;
+ var publicId = reader.GetAttribute("PUBLIC");
+ var systemId = reader.GetAttribute("SYSTEM");
+ var internalSubset = reader.Value;
+
+ ret = new XDocumentType(name, publicId, systemId, internalSubset);
+ break;
+ case XmlNodeType.Element:
+ return await XElement.CreateAsync(reader, cancellationToken).ConfigureAwait(false);
+ case XmlNodeType.ProcessingInstruction:
+ var target = reader.Name;
+ var data = reader.Value;
+
+ ret = new XProcessingInstruction(target, data);
+ break;
+ default:
+ throw new InvalidOperationException(SR.Format(SR.InvalidOperation_UnexpectedNodeType, reader.NodeType));
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+ await reader.ReadAsync().ConfigureAwait(false);
+
+ return ret;
+ }
+
+ /// <summary>
/// Removes this XNode from the underlying XML tree.
/// </summary>
/// <exception cref="InvalidOperationException">
@@ -559,6 +627,13 @@ namespace System.Xml.Linq
/// <param name="writer">The <see cref="XmlWriter"/> to write the current node into.</param>
public abstract void WriteTo(XmlWriter writer);
+ /// <summary>
+ /// Write the current node to an <see cref="XmlWriter"/>.
+ /// </summary>
+ /// <param name="writer">The <see cref="XmlWriter"/> to write the current node into.</param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public abstract Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken);
+
internal virtual void AppendText(StringBuilder sb)
{
}
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XProcessingInstruction.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XProcessingInstruction.cs
index 2cb0214a01..2ad625fc61 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XProcessingInstruction.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XProcessingInstruction.cs
@@ -2,6 +2,9 @@
// 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.Threading;
+using System.Threading.Tasks;
+
namespace System.Xml.Linq
{
/// <summary>
@@ -119,6 +122,22 @@ namespace System.Xml.Linq
writer.WriteProcessingInstruction(target, data);
}
+ /// <summary>
+ /// Writes this <see cref="XProcessingInstruction"/> to the passed in <see cref="XmlWriter"/>.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="XmlWriter"/> to write this <see cref="XProcessingInstruction"/> to.
+ /// </param>
+ /// <param name="cancellationToken">A cancellation token.</param>
+ public override Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ if (writer == null)
+ throw new ArgumentNullException(nameof(writer));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+ return writer.WriteProcessingInstructionAsync(target, data);
+ }
+
internal override XNode CloneNode()
{
return new XProcessingInstruction(this);
diff --git a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XText.cs b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XText.cs
index c31a668d34..7ca06139f0 100644
--- a/src/System.Private.Xml.Linq/src/System/Xml/Linq/XText.cs
+++ b/src/System.Private.Xml.Linq/src/System/Xml/Linq/XText.cs
@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
using StringBuilder = System.Text.StringBuilder;
+using System.Threading;
+using System.Threading.Tasks;
namespace System.Xml.Linq
{
@@ -90,6 +92,27 @@ namespace System.Xml.Linq
}
}
+ /// <summary>
+ /// Write this <see cref="XText"/> to the given <see cref="XmlWriter"/>.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="XmlWriter"/> to write this <see cref="XText"/> to.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A cancellation token.
+ /// </param>
+ public override Task WriteToAsync(XmlWriter writer, CancellationToken cancellationToken)
+ {
+ if (writer == null)
+ throw new ArgumentNullException(nameof(writer));
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ return parent is XDocument?
+ writer.WriteWhitespaceAsync(text) :
+ writer.WriteStringAsync(text);
+ }
+
internal override void AppendText(StringBuilder sb)
{
sb.Append(text);
diff --git a/src/System.Private.Xml.Linq/tests/System.Private.Xml.Linq.Tests.builds b/src/System.Private.Xml.Linq/tests/System.Private.Xml.Linq.Tests.builds
index 1f3a1a8981..562f456691 100644
--- a/src/System.Private.Xml.Linq/tests/System.Private.Xml.Linq.Tests.builds
+++ b/src/System.Private.Xml.Linq/tests/System.Private.Xml.Linq.Tests.builds
@@ -2,44 +2,70 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
+ <Project Include="axes\System.Xml.Linq.Axes.Tests.csproj" />
<Project Include="axes\System.Xml.Linq.Axes.Tests.csproj">
- <TestTFMs>netcoreapp1.1;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>net46</TestTFMs>
</Project>
+ <Project Include="events\System.Xml.Linq.Events.Tests.csproj" />
<Project Include="events\System.Xml.Linq.Events.Tests.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="misc\System.Xml.Linq.Misc.Tests.csproj" />
<Project Include="misc\System.Xml.Linq.Misc.Tests.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="Properties\System.Xml.Linq.Properties.Tests.csproj" />
<Project Include="Properties\System.Xml.Linq.Properties.Tests.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="SDMSample\System.Xml.Linq.SDMSample.Tests.csproj" />
<Project Include="SDMSample\System.Xml.Linq.SDMSample.Tests.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="Streaming\System.Xml.Linq.Streaming.Tests.csproj" />
<Project Include="Streaming\System.Xml.Linq.Streaming.Tests.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="TreeManipulation\System.Xml.Linq.TreeManipulation.Tests.csproj" />
<Project Include="TreeManipulation\System.Xml.Linq.TreeManipulation.Tests.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="XDocument.Common\XDocument.Common.csproj" />
<Project Include="XDocument.Common\XDocument.Common.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="XDocument.Test.ModuleCore\XDocument.Test.ModuleCore.csproj" />
<Project Include="XDocument.Test.ModuleCore\XDocument.Test.ModuleCore.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="xNodeBuilder\System.Xml.Linq.xNodeBuilder.Tests.csproj" />
<Project Include="xNodeBuilder\System.Xml.Linq.xNodeBuilder.Tests.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="xNodeReader\System.Xml.Linq.xNodeReader.Tests.csproj" />
<Project Include="xNodeReader\System.Xml.Linq.xNodeReader.Tests.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="XPath\XDocument\System.Xml.XPath.XDocument.Tests.csproj" />
<Project Include="XPath\XDocument\System.Xml.XPath.XDocument.Tests.csproj">
- <TestTFMs>netcoreapp1.1;netcore50;net46</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>netcore50;net46</TestTFMs>
</Project>
+ <Project Include="Schema\System.Xml.Schema.Extensions.Tests.csproj" />
<Project Include="Schema\System.Xml.Schema.Extensions.Tests.csproj">
- <TestTFMs>netcoreapp1.1;net463</TestTFMs>
+ <OSGroup>Windows_NT</OSGroup>
+ <TestTFMs>net463</TestTFMs>
</Project>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
diff --git a/src/System.Private.Xml.Linq/tests/TreeManipulation/LoadFromStream.cs b/src/System.Private.Xml.Linq/tests/TreeManipulation/LoadFromStream.cs
index 528e52864d..a8ea8c5b7c 100644
--- a/src/System.Private.Xml.Linq/tests/TreeManipulation/LoadFromStream.cs
+++ b/src/System.Private.Xml.Linq/tests/TreeManipulation/LoadFromStream.cs
@@ -435,7 +435,7 @@ namespace XLinqTests
return XElement.Load(s, lo);
}
default:
- throw new TestFailedException("TEST FAILED: don't know how to create XDocument");
+ throw new TestFailedException("TEST FAILED: don't know how to create XElement");
}
}
#endregion
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Common/BridgeHelpers.cs b/src/System.Private.Xml.Linq/tests/XDocument.Common/BridgeHelpers.cs
index f01688ee2d..5185156c8e 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Common/BridgeHelpers.cs
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Common/BridgeHelpers.cs
@@ -163,7 +163,7 @@ namespace CoreXml.Test.XLinq
}
}
- public string GetTestFileName()
+ public static string GetTestFileName()
{
return Path.Combine("TestData", "XmlReader", "API", pGenericXml);
}
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Common/CXmlCache.cs b/src/System.Private.Xml.Linq/tests/XDocument.Common/CXmlCache.cs
index e3d75e0315..f7b98a10da 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Common/CXmlCache.cs
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Common/CXmlCache.cs
@@ -688,7 +688,7 @@ public class CXmlCache
protected CXmlNode prDocumentRootNode;
protected CXmlNode prRootNode = null;
internal static NodeFlags _eDefaultFlags = NodeFlags.None;
- static internal BufferWriter _rBufferWriter = new BufferWriter();
+ internal static BufferWriter _rBufferWriter = new BufferWriter();
//
// Constructor
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Common/DNException.cs b/src/System.Private.Xml.Linq/tests/XDocument.Common/DNException.cs
index fa93186c16..5857fc2701 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Common/DNException.cs
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Common/DNException.cs
@@ -12,12 +12,12 @@ namespace CoreXml.Test.XLinq
public DNException(string s) : base(s) { }
- static internal Exception DocumentNavigatorNotOnLastNode()
+ internal static Exception DocumentNavigatorNotOnLastNode()
{
return new DNException("DocumentNavigatorNotOnLastNode");
}
- static internal Exception DocumentNavigatorNotOnFirstNode()
+ internal static Exception DocumentNavigatorNotOnFirstNode()
{
return new DNException("DocumentNavigatorNotOnFirstNode");
}
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Common/HelperExtensionMethods.cs b/src/System.Private.Xml.Linq/tests/XDocument.Common/HelperExtensionMethods.cs
index c74b7eef66..f055d72ef9 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Common/HelperExtensionMethods.cs
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Common/HelperExtensionMethods.cs
@@ -12,8 +12,6 @@ using System.Xml.Linq;
using Microsoft.Test.ModuleCore;
-[assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
-
namespace CoreXml.Test.XLinq
{
public static class Helpers
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Common/XDocument.Common.csproj b/src/System.Private.Xml.Linq/tests/XDocument.Common/XDocument.Common.csproj
index d4c26835b7..639dcc8b18 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Common/XDocument.Common.csproj
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Common/XDocument.Common.csproj
@@ -20,9 +20,6 @@
<Compile Include="InputSpace.cs" />
<Compile Include="ManagedNodeWriter.cs" />
<Compile Include="XLinqTestCase.cs" />
- <Compile Include="$(CommonPath)\System\Diagnostics\CodeAnalysis\ExcludeFromCodeCoverageAttribute.cs">
- <Link>Common\System\Diagnostics\CodeAnalysis\ExcludeFromCodeCoverageAttribute.cs</Link>
- </Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(CommonTestPath)\System\Xml\XmlCoreTest\XmlCoreTest.csproj" />
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/XDocument.Test.ModuleCore.csproj b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/XDocument.Test.ModuleCore.csproj
index a25f718e61..9e64ec7517 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/XDocument.Test.ModuleCore.csproj
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/XDocument.Test.ModuleCore.csproj
@@ -22,9 +22,6 @@
<Compile Include="testspec.cs" />
<Compile Include="testvariation.cs" />
<Compile Include="util.cs" />
- <Compile Include="$(CommonPath)\System\Diagnostics\CodeAnalysis\ExcludeFromCodeCoverageAttribute.cs">
- <Link>Common\System\Diagnostics\CodeAnalysis\ExcludeFromCodeCoverageAttribute.cs</Link>
- </Compile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testlog.cs b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testlog.cs
index 1e9ce31a81..67cca17a29 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testlog.cs
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testlog.cs
@@ -33,7 +33,7 @@ namespace Microsoft.Test.ModuleCore
private static TestLogAssertHandler s_passerthandler = null;
//Accessors
- static public ITestLog Internal
+ public static ITestLog Internal
{
set
{
@@ -45,18 +45,18 @@ namespace Microsoft.Test.ModuleCore
}
}
- static public TraceLevel Level
+ public static TraceLevel Level
{
get { return s_plevel; }
set { s_plevel = value; }
}
- static public TestLogAssertHandler AssertHandler
+ public static TestLogAssertHandler AssertHandler
{
get { return s_passerthandler; }
}
- static internal void Dispose()
+ internal static void Dispose()
{
//Reset the info.
s_pinternal = null;
@@ -64,84 +64,84 @@ namespace Microsoft.Test.ModuleCore
}
//Helpers
- static public string NewLine
+ public static string NewLine
{
get { return "\n"; }
}
- static public bool WillTrace(TraceLevel level)
+ public static bool WillTrace(TraceLevel level)
{
return (s_plevel >= level);
}
- static public void Write(object value)
+ public static void Write(object value)
{
Write(TestLogFlags.Text, StringEx.ToString(value));
}
- static public void WriteLine(object value)
+ public static void WriteLine(object value)
{
WriteLine(TestLogFlags.Text, StringEx.ToString(value));
}
- static public void WriteLine()
+ public static void WriteLine()
{
WriteLine(TestLogFlags.Text, null);
}
- static public void Write(string text)
+ public static void Write(string text)
{
Write(TestLogFlags.Text, text);
}
- static public void Write(string text, params object[] args)
+ public static void Write(string text, params object[] args)
{
//Delegate
Write(TestLogFlags.Text, String.Format(text, args));
}
- static public void WriteLine(string text)
+ public static void WriteLine(string text)
{
WriteLine(TestLogFlags.Text, text);
}
- static public void WriteLine(string text, params object[] args)
+ public static void WriteLine(string text, params object[] args)
{
//Delegate
WriteLine(String.Format(text, args));
}
- static public void Write(char[] value)
+ public static void Write(char[] value)
{
WriteLine(TestLogFlags.Text, new string(value));
}
- static public void WriteLine(char[] value)
+ public static void WriteLine(char[] value)
{
WriteLine(TestLogFlags.Text, new string(value));
}
- static public void WriteXml(string text)
+ public static void WriteXml(string text)
{
Write(TestLogFlags.Xml, text);
}
- static public void WriteRaw(string text)
+ public static void WriteRaw(string text)
{
Write(TestLogFlags.Raw, text);
}
- static public void WriteIgnore(string text)
+ public static void WriteIgnore(string text)
{
Write(TestLogFlags.Ignore, text);
}
- static public void WriteLineIgnore(string text)
+ public static void WriteLineIgnore(string text)
{
WriteLine(TestLogFlags.Ignore, text);
}
- static public void Write(TestLogFlags flags, string text)
+ public static void Write(TestLogFlags flags, string text)
{
if (Internal != null)
Internal.Write(flags, FixupXml(text));
@@ -149,7 +149,7 @@ namespace Microsoft.Test.ModuleCore
Console.Write(text);
}
- static public void WriteLine(TestLogFlags flags, string text)
+ public static void WriteLine(TestLogFlags flags, string text)
{
if (Internal != null)
Internal.WriteLine(flags, FixupXml(text));
@@ -157,46 +157,46 @@ namespace Microsoft.Test.ModuleCore
Console.WriteLine(text);
}
- static public void Trace(String value)
+ public static void Trace(String value)
{
Trace(TraceLevel.Default, value);
}
- static public void TraceLine(String value)
+ public static void TraceLine(String value)
{
TraceLine(TraceLevel.Default, value);
}
- static public void TraceLine()
+ public static void TraceLine()
{
TraceLine(TraceLevel.Default, null);
}
- static public void Trace(TraceLevel level, String value)
+ public static void Trace(TraceLevel level, String value)
{
if (WillTrace(level))
Write(TestLogFlags.Trace | TestLogFlags.Ignore, value);
}
- static public void TraceLine(TraceLevel level, String value)
+ public static void TraceLine(TraceLevel level, String value)
{
if (WillTrace(level))
Write(TestLogFlags.Trace | TestLogFlags.Ignore, value + TestLog.NewLine);
}
- static public void TraceLine(TraceLevel level)
+ public static void TraceLine(TraceLevel level)
{
TraceLine(level, null);
}
- static public bool Compare(bool equal, string message)
+ public static bool Compare(bool equal, string message)
{
if (equal)
return true;
return Compare(false, true, message);
}
- static public bool Compare(object actual, object expected, string message)
+ public static bool Compare(object actual, object expected, string message)
{
if (InternalEquals(actual, expected))
return true;
@@ -208,7 +208,7 @@ namespace Microsoft.Test.ModuleCore
throw new TestFailedException(message, actual, expected, null);
}
- static public bool Compare(object actual, object expected1, object expected2, string message)
+ public static bool Compare(object actual, object expected1, object expected2, string message)
{
if (InternalEquals(actual, expected1) || InternalEquals(actual, expected2))
return true;
@@ -220,7 +220,7 @@ namespace Microsoft.Test.ModuleCore
throw new TestFailedException(message, actual, expected2, null);
}
- static public bool Equals(object actual, object expected, string message)
+ public static bool Equals(object actual, object expected, string message)
{
//Equals is identical to Compare, except that Equals doesn't throw.
//i.e. the test wants to record the failure and continue to do other things
@@ -232,17 +232,17 @@ namespace Microsoft.Test.ModuleCore
return false;
}
- static public bool Warning(bool equal, string message)
+ public static bool Warning(bool equal, string message)
{
return Warning(equal, true, message, null);
}
- static public bool Warning(object actual, object expected, string message)
+ public static bool Warning(object actual, object expected, string message)
{
return Warning(actual, expected, message, null);
}
- static public bool Warning(object actual, object expected, string message, Exception inner)
+ public static bool Warning(object actual, object expected, string message, Exception inner)
{
//See if these are equal
bool equal = InternalEquals(actual, expected);
@@ -261,20 +261,20 @@ namespace Microsoft.Test.ModuleCore
}
}
- static public bool Skip(string message)
+ public static bool Skip(string message)
{
//Delegate
return Skip(true, message);
}
- static public bool Skip(bool skip, string message)
+ public static bool Skip(bool skip, string message)
{
if (skip)
throw new TestSkippedException(message);
return false;
}
- static internal bool InternalEquals(object actual, object expected)
+ internal static bool InternalEquals(object actual, object expected)
{
//Handle null comparison
if (actual == null && expected == null)
@@ -286,7 +286,7 @@ namespace Microsoft.Test.ModuleCore
return expected.Equals(actual);
}
- static public void Error(TestResult result, object actual, object expected, string source, string message, string stack, String filename, int lineno)
+ public static void Error(TestResult result, object actual, object expected, string source, string message, string stack, String filename, int lineno)
{
//Log the error
if (Internal != null)
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testparser.cs b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testparser.cs
index 8a08d1af05..b8b215c7b2 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testparser.cs
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testparser.cs
@@ -42,12 +42,12 @@ namespace Microsoft.Test.ModuleCore
//Methods
- static public Dictionary<string, string> ParseKeywords(string str)
+ public static Dictionary<string, string> ParseKeywords(string str)
{
return ParseKeywords(str, s_DefaultTokens);
}
- static public Dictionary<string, string> ParseKeywords(string str, Tokens tokens)
+ public static Dictionary<string, string> ParseKeywords(string str, Tokens tokens)
{
PARSE state = PARSE.Initial;
int index = 0;
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testproperties.cs b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testproperties.cs
index dbef76f664..7f3c450be6 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testproperties.cs
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/testproperties.cs
@@ -20,7 +20,7 @@ namespace Microsoft.Test.ModuleCore
private static String s_pcommandline;
//Constructor
- static public TestProps Properties
+ public static TestProps Properties
{
get
{
@@ -104,7 +104,7 @@ namespace Microsoft.Test.ModuleCore
return ret;
}
- static internal void Dispose()
+ internal static void Dispose()
{
//Reset the info.
//Since this is a static class, (to make it simplier to access from anywhere in your code)
@@ -116,7 +116,7 @@ namespace Microsoft.Test.ModuleCore
s_pcommandline = null;
}
- static public string InitString
+ public static string InitString
{
get
{
@@ -127,7 +127,7 @@ namespace Microsoft.Test.ModuleCore
}
}
- static public string CommandLine
+ public static string CommandLine
{
get
{
@@ -142,7 +142,7 @@ namespace Microsoft.Test.ModuleCore
}
}
- static public String Filter
+ public static String Filter
{
get
{
@@ -152,7 +152,7 @@ namespace Microsoft.Test.ModuleCore
}
}
- static public String MaxPriority
+ public static String MaxPriority
{
get
{
diff --git a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/util.cs b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/util.cs
index 4d66312861..05b1611831 100644
--- a/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/util.cs
+++ b/src/System.Private.Xml.Linq/tests/XDocument.Test.ModuleCore/util.cs
@@ -5,8 +5,6 @@
using System;
using System.Collections.Generic;
-[assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
-
namespace Microsoft.Test.ModuleCore
{
////////////////////////////////////////////////////////////////
@@ -15,7 +13,7 @@ namespace Microsoft.Test.ModuleCore
////////////////////////////////////////////////////////////////
internal class StringEx
{
- static public string ToString(object value)
+ public static string ToString(object value)
{
if (value == null)
return null;
@@ -23,7 +21,7 @@ namespace Microsoft.Test.ModuleCore
return value.ToString();
}
- static public string Format(object value)
+ public static string Format(object value)
{
if (value == null)
return "(null)";
diff --git a/src/System.Private.Xml.Linq/tests/XPath/XDocument/XDocumentXPathTest.cs b/src/System.Private.Xml.Linq/tests/XPath/XDocument/XDocumentXPathTest.cs
index 41b90a67e7..9fa102fd7c 100644
--- a/src/System.Private.Xml.Linq/tests/XPath/XDocument/XDocumentXPathTest.cs
+++ b/src/System.Private.Xml.Linq/tests/XPath/XDocument/XDocumentXPathTest.cs
@@ -8,7 +8,7 @@ namespace XPathTests.Common
{
public static partial class Utils
{
- private readonly static ICreateNavigator _navigatorCreator = new CreateNavigatorComparer();
- public readonly static string ResourceFilesPath = "System.Xml.XPath.XDocument.Tests.TestData.";
+ private static readonly ICreateNavigator _navigatorCreator = new CreateNavigatorComparer();
+ public static readonly string ResourceFilesPath = "System.Xml.XPath.XDocument.Tests.TestData.";
}
}
diff --git a/src/System.Private.Xml.Linq/tests/misc/LoadSaveAsyncTests.cs b/src/System.Private.Xml.Linq/tests/misc/LoadSaveAsyncTests.cs
new file mode 100644
index 0000000000..0c09af3d86
--- /dev/null
+++ b/src/System.Private.Xml.Linq/tests/misc/LoadSaveAsyncTests.cs
@@ -0,0 +1,206 @@
+// 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.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Xml;
+using System.Xml.Linq;
+using XmlCoreTest.Common;
+using Xunit;
+
+namespace CoreXml.Test.XLinq
+{
+ public class LoadSaveAsyncTests : BridgeHelpers
+ {
+ [Fact]
+ public static void ArgumentValidation()
+ {
+ // Verify that ArgumentNullExceptions are thrown when passing null to LoadAsync and SaveAsync
+ Assert.Throws<ArgumentNullException>(() => { XDocument.LoadAsync((XmlReader)null, LoadOptions.None, CancellationToken.None); });
+ Assert.Throws<ArgumentNullException>(() => { new XDocument().SaveAsync((XmlWriter)null, CancellationToken.None); });
+ Assert.Throws<ArgumentNullException>(() => { XElement.LoadAsync((XmlReader)null, LoadOptions.None, CancellationToken.None); });
+ Assert.Throws<ArgumentNullException>(() => { new XElement("Name").SaveAsync((XmlWriter)null, CancellationToken.None); });
+ }
+
+ [Fact]
+ public static async Task AlreadyCanceled()
+ {
+ // Verify that providing an already canceled cancellation token will result in a canceled task
+
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => XDocument.LoadAsync(Stream.Null, LoadOptions.None, new CancellationToken(true)));
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => XDocument.LoadAsync(StreamReader.Null, LoadOptions.None, new CancellationToken(true)));
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => XDocument.LoadAsync(XmlReader.Create(Stream.Null), LoadOptions.None, new CancellationToken(true)));
+
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => new XDocument().SaveAsync(Stream.Null, SaveOptions.None, new CancellationToken(true)));
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => new XDocument().SaveAsync(StreamWriter.Null, SaveOptions.None, new CancellationToken(true)));
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => new XDocument().SaveAsync(XmlWriter.Create(Stream.Null), new CancellationToken(true)));
+
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => XElement.LoadAsync(Stream.Null, LoadOptions.None, new CancellationToken(true)));
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => XElement.LoadAsync(StreamReader.Null, LoadOptions.None, new CancellationToken(true)));
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => XElement.LoadAsync(XmlReader.Create(Stream.Null), LoadOptions.None, new CancellationToken(true)));
+
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => new XElement("Name").SaveAsync(Stream.Null, SaveOptions.None, new CancellationToken(true)));
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => new XElement("Name").SaveAsync(StreamWriter.Null, SaveOptions.None, new CancellationToken(true)));
+ await Assert.ThrowsAnyAsync<OperationCanceledException>(() => new XElement("Name").SaveAsync(XmlWriter.Create(Stream.Null), new CancellationToken(true)));
+ }
+
+ [Theory]
+ [MemberData("RoundtripOptions_MemberData")]
+ public static async Task RoundtripSyncAsyncMatches_XmlReader(bool document, LoadOptions loadOptions, SaveOptions saveOptions)
+ {
+ // Create reader and writer settings
+ var readerSettings = new XmlReaderSettings();
+ var writerSettings = new XmlWriterSettings();
+ if ((saveOptions & SaveOptions.OmitDuplicateNamespaces) != 0)
+ {
+ writerSettings.NamespaceHandling = NamespaceHandling.OmitDuplicates;
+ }
+ if ((saveOptions & SaveOptions.DisableFormatting) != 0)
+ {
+ writerSettings.Indent = false;
+ writerSettings.NewLineHandling = NewLineHandling.None;
+ }
+
+ // Roundtrip XML using synchronous and XmlReader/Writer
+ MemoryStream syncOutput = new MemoryStream();
+ using (XmlReader syncReader = XmlReader.Create(FilePathUtil.getStream(GetTestFileName()), readerSettings))
+ using (XmlWriter syncWriter = XmlWriter.Create(syncOutput, writerSettings))
+ {
+ if (document)
+ {
+ XDocument syncDoc = XDocument.Load(syncReader, loadOptions);
+ syncDoc.Save(syncWriter);
+ }
+ else
+ {
+ XElement syncElement = XElement.Load(syncReader, loadOptions);
+ syncElement.Save(syncWriter);
+ }
+ }
+
+ // Roundtrip XML using asynchronous and XmlReader/Writer
+ readerSettings.Async = true;
+ writerSettings.Async = true;
+ MemoryStream asyncOutput = new MemoryStream();
+ using (XmlReader asyncReader = XmlReader.Create(FilePathUtil.getStream(GetTestFileName()), readerSettings))
+ using (XmlWriter asyncWriter = XmlWriter.Create(asyncOutput, writerSettings))
+ {
+ if (document)
+ {
+ XDocument asyncDoc = await XDocument.LoadAsync(asyncReader, loadOptions, CancellationToken.None);
+ await asyncDoc.SaveAsync(asyncWriter, CancellationToken.None);
+ }
+ else
+ {
+ XElement asyncElement = await XElement.LoadAsync(asyncReader, loadOptions, CancellationToken.None);
+ await asyncElement.SaveAsync(asyncWriter, CancellationToken.None);
+ }
+ }
+
+ // Compare to make sure the synchronous and asynchronous results are the same
+ Assert.Equal(syncOutput.ToArray(), asyncOutput.ToArray());
+ }
+
+ [Theory]
+ [MemberData("RoundtripOptions_MemberData")]
+ public static async Task RoundtripSyncAsyncMatches_StreamReader(bool document, LoadOptions loadOptions, SaveOptions saveOptions)
+ {
+ // Roundtrip XML using synchronous and StreamReader/Writer
+ MemoryStream syncOutput = new MemoryStream();
+ using (StreamReader syncReader = new StreamReader(FilePathUtil.getStream(GetTestFileName())))
+ using (StreamWriter syncWriter = new StreamWriter(syncOutput))
+ {
+ if (document)
+ {
+ XDocument syncDoc = XDocument.Load(syncReader, loadOptions);
+ syncDoc.Save(syncWriter, saveOptions);
+ }
+ else
+ {
+ XElement syncElement = XElement.Load(syncReader, loadOptions);
+ syncElement.Save(syncWriter, saveOptions);
+ }
+ }
+
+ // Roundtrip XML using asynchronous and StreamReader/Writer
+ MemoryStream asyncOutput = new MemoryStream();
+ using (StreamReader asyncReader = new StreamReader(FilePathUtil.getStream(GetTestFileName())))
+ using (StreamWriter asyncWriter = new StreamWriter(asyncOutput))
+ {
+ if (document)
+ {
+ XDocument asyncDoc = await XDocument.LoadAsync(asyncReader, loadOptions, CancellationToken.None);
+ await asyncDoc.SaveAsync(asyncWriter, saveOptions, CancellationToken.None);
+ }
+ else
+ {
+ XElement asyncElement = await XElement.LoadAsync(asyncReader, loadOptions, CancellationToken.None);
+ await asyncElement.SaveAsync(asyncWriter, saveOptions, CancellationToken.None);
+ }
+ }
+
+ // Compare to make sure the synchronous and asynchronous results are the same
+ Assert.Equal(syncOutput.ToArray(), asyncOutput.ToArray());
+ }
+
+ [Theory]
+ [MemberData("RoundtripOptions_MemberData")]
+ public static async Task RoundtripSyncAsyncMatches_Stream(bool document, LoadOptions loadOptions, SaveOptions saveOptions)
+ {
+ // Roundtrip XML using synchronous and Stream
+ MemoryStream syncOutput = new MemoryStream();
+ using (Stream syncStream = FilePathUtil.getStream(GetTestFileName()))
+ {
+ if (document)
+ {
+ XDocument syncDoc = XDocument.Load(syncStream, loadOptions);
+ syncDoc.Save(syncOutput, saveOptions);
+ }
+ else
+ {
+ XElement syncElement = XElement.Load(syncStream, loadOptions);
+ syncElement.Save(syncOutput, saveOptions);
+ }
+ }
+
+ // Roundtrip XML using asynchronous and Stream
+ MemoryStream asyncOutput = new MemoryStream();
+ using (Stream asyncStream = FilePathUtil.getStream(GetTestFileName()))
+ {
+ if (document)
+ {
+ XDocument asyncDoc = await XDocument.LoadAsync(asyncStream, loadOptions, CancellationToken.None);
+ await asyncDoc.SaveAsync(asyncOutput, saveOptions, CancellationToken.None);
+ }
+ else
+ {
+ XElement asyncElement = await XElement.LoadAsync(asyncStream, loadOptions, CancellationToken.None);
+ await asyncElement.SaveAsync(asyncOutput, saveOptions, CancellationToken.None);
+ }
+ }
+
+ // Compare to make sure the synchronous and asynchronous results are the same
+ Assert.Equal(syncOutput.ToArray(), asyncOutput.ToArray());
+ }
+
+ // Inputs to the Roundtrip* tests:
+ // - Boolean for whether to test XDocument (true) or XElement (false)
+ // - LoadOptions value
+ // - SaveOptions value
+ public static IEnumerable<object[]> RoundtripOptions_MemberData
+ {
+ get
+ {
+ foreach (bool doc in new[] { true, false })
+ foreach (LoadOptions loadOptions in Enum.GetValues(typeof(LoadOptions)))
+ foreach (SaveOptions saveOptions in Enum.GetValues(typeof(SaveOptions)))
+ yield return new object[] { doc, loadOptions, saveOptions };
+ }
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/System.Private.Xml.Linq/tests/misc/System.Xml.Linq.Misc.Tests.csproj b/src/System.Private.Xml.Linq/tests/misc/System.Xml.Linq.Misc.Tests.csproj
index 92b73a6be1..c7a44deef7 100644
--- a/src/System.Private.Xml.Linq/tests/misc/System.Xml.Linq.Misc.Tests.csproj
+++ b/src/System.Private.Xml.Linq/tests/misc/System.Xml.Linq.Misc.Tests.csproj
@@ -17,8 +17,10 @@
<Compile Include="XHashtable.cs" />
<Compile Include="XLinqErrata4.cs" />
<Compile Include="XNameAPI.cs" />
+ <Compile Include="LoadSaveAsyncTests.cs" Condition="'$(TargetGroup)'==''" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="$(CommonTestPath)\System\Xml\ModuleCore\ModuleCore.csproj" />
<ProjectReference Include="$(CommonTestPath)\System\Xml\XmlCoreTest\XmlCoreTest.csproj" />
<ProjectReference Include="$(CommonTestPath)\System\Xml\XmlDiff\XmlDiff.csproj" />
<ProjectReference Include="..\XDocument.Common\XDocument.Common.csproj" />
diff --git a/src/System.Private.Xml/src/System.Private.Xml.csproj b/src/System.Private.Xml/src/System.Private.Xml.csproj
index a10fe6e4d8..1f10442779 100644
--- a/src/System.Private.Xml/src/System.Private.Xml.csproj
+++ b/src/System.Private.Xml/src/System.Private.Xml.csproj
@@ -7,7 +7,7 @@
<RootNamespace>System.Xml</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>$(NoWarn),649</NoWarn>
- <DefineConstants>ASYNC;ASTORIA_LIGHT</DefineConstants><!-- TODO: this should be prepended with $(DefineConstants); - otherwise DEBUG and TRACE are not being passed -->
+ <DefineConstants>$(DefineConstants);ASYNC;ASTORIA_LIGHT</DefineConstants>
<!--<DefineConstants Condition="'$(TargetGroup)' == 'uap101aot'">$(DefineConstants);NET_NATIVE</DefineConstants> TODO: Bring this back when uap101aot support is added -->
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
diff --git a/src/System.Private.Xml/src/System/Xml/BinaryXml/SqlUtils.cs b/src/System.Private.Xml/src/System/Xml/BinaryXml/SqlUtils.cs
index c3ae881d33..23b6c540fa 100644
--- a/src/System.Private.Xml/src/System/Xml/BinaryXml/SqlUtils.cs
+++ b/src/System.Private.Xml/src/System/Xml/BinaryXml/SqlUtils.cs
@@ -626,7 +626,7 @@ namespace System.Xml
{
private const int MaxFractionDigits = 7;
- static internal int[] KatmaiTimeScaleMultiplicator = new int[8] {
+ internal static int[] KatmaiTimeScaleMultiplicator = new int[8] {
10000000,
1000000,
100000,
diff --git a/src/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs b/src/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs
index e2f7fd1adf..4869463152 100644
--- a/src/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs
+++ b/src/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs
@@ -3213,9 +3213,9 @@ namespace System.Xml
if (decl.scope > 0)
{
#if DEBUG
- if ((object)decl.prefix != (object)this.xnt.Get(decl.prefix))
+ if ((object)decl.prefix != (object)this._xnt.Get(decl.prefix))
throw new Exception("Prefix not interned: \'" + decl.prefix + "\'");
- if ((object)decl.uri != (object)this.xnt.Get(decl.uri))
+ if ((object)decl.uri != (object)this._xnt.Get(decl.uri))
throw new Exception("Uri not interned: \'" + decl.uri + "\'");
#endif
xnm.AddNamespace(decl.prefix, decl.uri);
diff --git a/src/System.Private.Xml/src/System/Xml/Core/LocalAppContextSwitches.cs b/src/System.Private.Xml/src/System/Xml/Core/LocalAppContextSwitches.cs
index c5160fd349..cc91c1e720 100644
--- a/src/System.Private.Xml/src/System/Xml/Core/LocalAppContextSwitches.cs
+++ b/src/System.Private.Xml/src/System/Xml/Core/LocalAppContextSwitches.cs
@@ -8,7 +8,7 @@ namespace System
{
internal partial class LocalAppContextSwitches
{
- private const string DontThrowOnInvalidSurrogatePairsName = "DontThrowOnInvalidSurrogatePairs";
+ private const string DontThrowOnInvalidSurrogatePairsName = "Switch.System.Xml.DontThrowOnInvalidSurrogatePairs";
private static int s_dontThrowOnInvalidSurrogatePairs;
public static bool DontThrowOnInvalidSurrogatePairs
@@ -20,7 +20,7 @@ namespace System
}
}
- private const string IgnoreEmptyKeySequencesName = "IgnoreEmptyKeySequencess";
+ private const string IgnoreEmptyKeySequencesName = "Switch.System.Xml.IgnoreEmptyKeySequencess";
private static int s_ignoreEmptyKeySequences;
public static bool IgnoreEmptyKeySequences
@@ -32,7 +32,7 @@ namespace System
}
}
- private const string IgnoreKindInUtcTimeSerializationName = "IgnoreKindInUtcTimeSerialization";
+ private const string IgnoreKindInUtcTimeSerializationName = "Switch.System.Xml.IgnoreKindInUtcTimeSerialization";
private static int s_ignoreKindInUtcTimeSerialization;
public static bool IgnoreKindInUtcTimeSerialization
@@ -44,7 +44,7 @@ namespace System
}
}
- private const string LimitXPathComplexityName = "LimitXPathComplexity";
+ private const string LimitXPathComplexityName = "Switch.System.Xml.LimitXPathComplexity";
private static int s_limitXPathComplexity;
public static bool LimitXPathComplexity
@@ -55,5 +55,17 @@ namespace System
return LocalAppContext.GetCachedSwitchValue(LimitXPathComplexityName, ref s_limitXPathComplexity);
}
}
+
+ private const string AllowDefaultResolverName = "Switch.System.Xml.AllowDefaultResolver";
+ private static int s_allowDefaultResolver;
+
+ public static bool AllowDefaultResolver
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ return LocalAppContext.GetCachedSwitchValue(AllowDefaultResolverName, ref s_allowDefaultResolver);
+ }
+ }
}
} \ No newline at end of file
diff --git a/src/System.Private.Xml/src/System/Xml/Core/XmlReader.cs b/src/System.Private.Xml/src/System/Xml/Core/XmlReader.cs
index 6466fb4892..f70950470a 100644
--- a/src/System.Private.Xml/src/System/Xml/Core/XmlReader.cs
+++ b/src/System.Private.Xml/src/System/Xml/Core/XmlReader.cs
@@ -17,7 +17,7 @@ namespace System.Xml
[DebuggerDisplay("{debuggerDisplayProxy}")]
public abstract partial class XmlReader : IDisposable
{
- static private uint s_isTextualNodeBitmap = 0x6018; // 00 0110 0000 0001 1000
+ private static uint s_isTextualNodeBitmap = 0x6018; // 00 0110 0000 0001 1000
// 0 None,
// 0 Element,
// 0 Attribute,
@@ -37,7 +37,7 @@ namespace System.Xml
// 0 EndEntity,
// 0 XmlDeclaration
- static private uint s_canReadContentAsBitmap = 0x1E1BC; // 01 1110 0001 1011 1100
+ private static uint s_canReadContentAsBitmap = 0x1E1BC; // 01 1110 0001 1011 1100
// 0 None,
// 0 Element,
// 1 Attribute,
@@ -57,7 +57,7 @@ namespace System.Xml
// 1 EndEntity,
// 0 XmlDeclaration
- static private uint s_hasValueBitmap = 0x2659C; // 10 0110 0101 1001 1100
+ private static uint s_hasValueBitmap = 0x2659C; // 10 0110 0101 1001 1100
// 0 None,
// 0 Element,
// 1 Attribute,
@@ -1428,7 +1428,7 @@ namespace System.Xml
}
}
- static internal bool IsTextualNode(XmlNodeType nodeType)
+ internal static bool IsTextualNode(XmlNodeType nodeType)
{
#if DEBUG
// This code verifies IsTextualNodeBitmap mapping of XmlNodeType to a bool specifying
@@ -1455,7 +1455,7 @@ namespace System.Xml
return 0 != (s_isTextualNodeBitmap & (1 << (int)nodeType));
}
- static internal bool CanReadContentAs(XmlNodeType nodeType)
+ internal static bool CanReadContentAs(XmlNodeType nodeType)
{
#if DEBUG
// This code verifies IsTextualNodeBitmap mapping of XmlNodeType to a bool specifying
@@ -1482,7 +1482,7 @@ namespace System.Xml
return 0 != (s_canReadContentAsBitmap & (1 << (int)nodeType));
}
- static internal bool HasValueInternal(XmlNodeType nodeType)
+ internal static bool HasValueInternal(XmlNodeType nodeType)
{
#if DEBUG
// This code verifies HasValueBitmap mapping of XmlNodeType to a bool specifying
@@ -1572,12 +1572,12 @@ namespace System.Xml
return CanReadContentAs(this.NodeType);
}
- static internal Exception CreateReadContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo)
+ internal static Exception CreateReadContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo)
{
return new InvalidOperationException(AddLineInfo(SR.Format(SR.Xml_InvalidReadContentAs, new string[] { methodName, nodeType.ToString() }), lineInfo));
}
- static internal Exception CreateReadElementContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo)
+ internal static Exception CreateReadElementContentAsException(string methodName, XmlNodeType nodeType, IXmlLineInfo lineInfo)
{
return new InvalidOperationException(AddLineInfo(SR.Format(SR.Xml_InvalidReadElementContentAs, new string[] { methodName, nodeType.ToString() }), lineInfo));
}
diff --git a/src/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs b/src/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs
index 5f6b18e087..a45e87c7b8 100644
--- a/src/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs
+++ b/src/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs
@@ -125,7 +125,7 @@ namespace System.Xml
//notice we must keep GetXmlResolver() to avoid dead lock when init System.Config.ConfigurationManager
internal XmlResolver GetXmlResolver_CheckConfig()
{
- if (!IsXmlResolverSet)
+ if (!LocalAppContextSwitches.AllowDefaultResolver && !IsXmlResolverSet)
return null;
else
return _xmlResolver;
@@ -751,7 +751,7 @@ namespace System.Xml
private static bool? s_enableLegacyXmlSettings = null;
- static internal bool EnableLegacyXmlSettings()
+ internal static bool EnableLegacyXmlSettings()
{
if (s_enableLegacyXmlSettings.HasValue)
{
diff --git a/src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs b/src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs
index 39baf89c75..ed6c3f8314 100644
--- a/src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs
+++ b/src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs
@@ -4982,9 +4982,9 @@ namespace System.Xml
if (tmpch3 == quoteChar)
{
#if DEBUG
- if (normalize)
+ if (_normalize)
{
- string val = new string(chars, ps.charPos, pos - ps.charPos);
+ string val = new string(chars, _ps.charPos, pos - _ps.charPos);
Debug.Assert(val == XmlComplianceUtil.CDataNormalize(val), "The attribute value is not CDATA normalized!");
}
#endif
@@ -9645,7 +9645,7 @@ namespace System.Xml
}
[System.Security.SecuritySafeCritical]
- static internal unsafe void AdjustLineInfo(char[] chars, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo)
+ internal static unsafe void AdjustLineInfo(char[] chars, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo)
{
Debug.Assert(startPos >= 0);
Debug.Assert(endPos < chars.Length);
@@ -9658,7 +9658,7 @@ namespace System.Xml
}
[System.Security.SecuritySafeCritical]
- static internal unsafe void AdjustLineInfo(string str, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo)
+ internal static unsafe void AdjustLineInfo(string str, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo)
{
Debug.Assert(startPos >= 0);
Debug.Assert(endPos < str.Length);
@@ -9671,7 +9671,7 @@ namespace System.Xml
}
[System.Security.SecurityCritical]
- static internal unsafe void AdjustLineInfo(char* pChars, int length, bool isNormalized, ref LineInfo lineInfo)
+ internal static unsafe void AdjustLineInfo(char* pChars, int length, bool isNormalized, ref LineInfo lineInfo)
{
int lastNewLinePos = -1;
for (int i = 0; i < length; i++)
diff --git a/src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImplAsync.cs b/src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImplAsync.cs
index d9d0600a42..24d467659d 100644
--- a/src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImplAsync.cs
+++ b/src/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImplAsync.cs
@@ -2570,7 +2570,7 @@ namespace System.Xml
int attrNameLinePos = _ps.LinePos;
#if DEBUG
- int attrNameLineNo = ps.LineNo;
+ int attrNameLineNo = _ps.LineNo;
#endif
// parse attribute name
@@ -2663,7 +2663,7 @@ namespace System.Xml
attr.SetLineInfo(_ps.LineNo, attrNameLinePos);
#if DEBUG
- Debug.Assert( attrNameLineNo == ps.LineNo );
+ Debug.Assert( attrNameLineNo == _ps.LineNo );
#endif
// parse equals and quote char;
@@ -2708,8 +2708,8 @@ namespace System.Xml
{
#if DEBUG
#if !SILVERLIGHT
- if ( normalize ) {
- string val = new string(chars, ps.charPos, pos - ps.charPos );
+ if ( _normalize ) {
+ string val = new string(chars, _ps.charPos, pos - _ps.charPos );
Debug.Assert( val == XmlComplianceUtil.CDataNormalize( val ), "The attribute value is not CDATA normalized!" );
}
#endif
diff --git a/src/System.Private.Xml/src/System/Xml/Core/XmlWellFormedWriter.cs b/src/System.Private.Xml/src/System/Xml/Core/XmlWellFormedWriter.cs
index 154bfe179e..8ee17f211e 100644
--- a/src/System.Private.Xml/src/System/Xml/Core/XmlWellFormedWriter.cs
+++ b/src/System.Private.Xml/src/System/Xml/Core/XmlWellFormedWriter.cs
@@ -1920,7 +1920,7 @@ namespace System.Xml
}
}
- static private XmlException DupAttrException(string prefix, string localName)
+ private static XmlException DupAttrException(string prefix, string localName)
{
StringBuilder sb = new StringBuilder();
if (prefix.Length > 0)
diff --git a/src/System.Private.Xml/src/System/Xml/Dom/XmlDocument.cs b/src/System.Private.Xml/src/System/Xml/Dom/XmlDocument.cs
index 396ce524f7..ff866e734b 100644
--- a/src/System.Private.Xml/src/System/Xml/Dom/XmlDocument.cs
+++ b/src/System.Private.Xml/src/System/Xml/Dom/XmlDocument.cs
@@ -74,10 +74,10 @@ namespace System.Xml
private XmlAttribute _namespaceXml;
- static internal EmptyEnumerator EmptyEnumerator = new EmptyEnumerator();
- static internal IXmlSchemaInfo NotKnownSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.NotKnown);
- static internal IXmlSchemaInfo ValidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Valid);
- static internal IXmlSchemaInfo InvalidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Invalid);
+ internal static EmptyEnumerator EmptyEnumerator = new EmptyEnumerator();
+ internal static IXmlSchemaInfo NotKnownSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.NotKnown);
+ internal static IXmlSchemaInfo ValidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Valid);
+ internal static IXmlSchemaInfo InvalidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Invalid);
// Initializes a new instance of the XmlDocument class.
public XmlDocument() : this(new XmlImplementation())
@@ -692,7 +692,7 @@ namespace System.Xml
return CreateNavigator(this);
}
- internal protected virtual XPathNavigator CreateNavigator(XmlNode node)
+ protected internal virtual XPathNavigator CreateNavigator(XmlNode node)
{
XmlNodeType nodeType = node.NodeType;
XmlNode parent;
diff --git a/src/System.Private.Xml/src/System/Xml/Dom/XmlLoader.cs b/src/System.Private.Xml/src/System/Xml/Dom/XmlLoader.cs
index c36b39736f..9292852f0a 100644
--- a/src/System.Private.Xml/src/System/Xml/Dom/XmlLoader.cs
+++ b/src/System.Private.Xml/src/System/Xml/Dom/XmlLoader.cs
@@ -1001,7 +1001,7 @@ namespace System.Xml
}
}
- static internal Exception UnexpectedNodeType(XmlNodeType nodetype)
+ internal static Exception UnexpectedNodeType(XmlNodeType nodetype)
{
return new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, SR.Xml_UnexpectedNodeType, nodetype.ToString()));
}
diff --git a/src/System.Private.Xml/src/System/Xml/MTNameTable.cs b/src/System.Private.Xml/src/System/Xml/MTNameTable.cs
index 5115b0018b..e161d3f9b4 100644
--- a/src/System.Private.Xml/src/System/Xml/MTNameTable.cs
+++ b/src/System.Private.Xml/src/System/Xml/MTNameTable.cs
@@ -560,7 +560,7 @@ namespace System.Xml {
this.hash = Hash(array, start, len);
}
- static private Int64 Hash(String value) {
+ private static Int64 Hash(String value) {
Int64 hash = 0;
int len = value.Length;
@@ -579,7 +579,7 @@ namespace System.Xml {
return hash;
}
- static private Int64 Hash(char[] key, int start, int len) {
+ private static Int64 Hash(char[] key, int start, int len) {
Int64 hash = 0;
if (len > 0)
diff --git a/src/System.Private.Xml/src/System/Xml/Schema/Asttree.cs b/src/System.Private.Xml/src/System/Xml/Schema/Asttree.cs
index 6fbbc9c444..69960c5f85 100644
--- a/src/System.Private.Xml/src/System/Xml/Schema/Asttree.cs
+++ b/src/System.Private.Xml/src/System/Xml/Schema/Asttree.cs
@@ -514,8 +514,8 @@ namespace System.Xml.Schema
// only for debug
#if DEBUG
public void PrintTree (StreamWriter msw) {
- for (int i = 0; i < fAxisArray.Count; ++i) {
- ForwardAxis axis = (ForwardAxis)fAxisArray[i];
+ for (int i = 0; i < _fAxisArray.Count; ++i) {
+ ForwardAxis axis = (ForwardAxis)_fAxisArray[i];
msw.WriteLine("<Tree IsDss=\"{0}\" IsAttribute=\"{1}\">", axis.IsDss, axis.IsAttribute);
DoubleLinkAxis printaxis = axis.TopNode;
while ( printaxis != null ) {
diff --git a/src/System.Private.Xml/src/System/Xml/Schema/BitSet.cs b/src/System.Private.Xml/src/System/Xml/Schema/BitSet.cs
index 7e8044f44c..7b82d77eb0 100644
--- a/src/System.Private.Xml/src/System/Xml/Schema/BitSet.cs
+++ b/src/System.Private.Xml/src/System/Xml/Schema/BitSet.cs
@@ -257,7 +257,7 @@ namespace System.Xml.Schema
#if DEBUG
public void Dump(StringBuilder bb) {
- for (int i = 0; i < count; i ++) {
+ for (int i = 0; i < _count; i ++) {
bb.Append( Get(i) ? "1" : "0");
}
}
diff --git a/src/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs b/src/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs
index 0c35380b77..cdcef56236 100644
--- a/src/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs
+++ b/src/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs
@@ -649,72 +649,72 @@ namespace System.Xml.Schema
}
// XSD types
- static private readonly DatatypeImplementation s_anySimpleType = new Datatype_anySimpleType();
- static private readonly DatatypeImplementation s_anyURI = new Datatype_anyURI();
- static private readonly DatatypeImplementation s_base64Binary = new Datatype_base64Binary();
- static private readonly DatatypeImplementation s_boolean = new Datatype_boolean();
- static private readonly DatatypeImplementation s_byte = new Datatype_byte();
- static private readonly DatatypeImplementation s_char = new Datatype_char(); // XDR
- static private readonly DatatypeImplementation s_date = new Datatype_date();
- static private readonly DatatypeImplementation s_dateTime = new Datatype_dateTime();
- static private readonly DatatypeImplementation s_dateTimeNoTz = new Datatype_dateTimeNoTimeZone(); // XDR
- static private readonly DatatypeImplementation s_dateTimeTz = new Datatype_dateTimeTimeZone(); // XDR
- static private readonly DatatypeImplementation s_day = new Datatype_day();
- static private readonly DatatypeImplementation s_decimal = new Datatype_decimal();
- static private readonly DatatypeImplementation s_double = new Datatype_double();
- static private readonly DatatypeImplementation s_doubleXdr = new Datatype_doubleXdr(); // XDR
- static private readonly DatatypeImplementation s_duration = new Datatype_duration();
- static private readonly DatatypeImplementation s_ENTITY = new Datatype_ENTITY();
- static private readonly DatatypeImplementation s_ENTITIES = (DatatypeImplementation)s_ENTITY.DeriveByList(1, null);
- static private readonly DatatypeImplementation s_ENUMERATION = new Datatype_ENUMERATION(); // XDR
- static private readonly DatatypeImplementation s_fixed = new Datatype_fixed();
- static private readonly DatatypeImplementation s_float = new Datatype_float();
- static private readonly DatatypeImplementation s_floatXdr = new Datatype_floatXdr(); // XDR
- static private readonly DatatypeImplementation s_hexBinary = new Datatype_hexBinary();
- static private readonly DatatypeImplementation s_ID = new Datatype_ID();
- static private readonly DatatypeImplementation s_IDREF = new Datatype_IDREF();
- static private readonly DatatypeImplementation s_IDREFS = (DatatypeImplementation)s_IDREF.DeriveByList(1, null);
- static private readonly DatatypeImplementation s_int = new Datatype_int();
- static private readonly DatatypeImplementation s_integer = new Datatype_integer();
- static private readonly DatatypeImplementation s_language = new Datatype_language();
- static private readonly DatatypeImplementation s_long = new Datatype_long();
- static private readonly DatatypeImplementation s_month = new Datatype_month();
- static private readonly DatatypeImplementation s_monthDay = new Datatype_monthDay();
- static private readonly DatatypeImplementation s_name = new Datatype_Name();
- static private readonly DatatypeImplementation s_NCName = new Datatype_NCName();
- static private readonly DatatypeImplementation s_negativeInteger = new Datatype_negativeInteger();
- static private readonly DatatypeImplementation s_NMTOKEN = new Datatype_NMTOKEN();
- static private readonly DatatypeImplementation s_NMTOKENS = (DatatypeImplementation)s_NMTOKEN.DeriveByList(1, null);
- static private readonly DatatypeImplementation s_nonNegativeInteger = new Datatype_nonNegativeInteger();
- static private readonly DatatypeImplementation s_nonPositiveInteger = new Datatype_nonPositiveInteger();
- static private readonly DatatypeImplementation s_normalizedString = new Datatype_normalizedString();
- static private readonly DatatypeImplementation s_NOTATION = new Datatype_NOTATION();
- static private readonly DatatypeImplementation s_positiveInteger = new Datatype_positiveInteger();
- static private readonly DatatypeImplementation s_QName = new Datatype_QName();
- static private readonly DatatypeImplementation s_QNameXdr = new Datatype_QNameXdr(); //XDR
- static private readonly DatatypeImplementation s_short = new Datatype_short();
- static private readonly DatatypeImplementation s_string = new Datatype_string();
- static private readonly DatatypeImplementation s_time = new Datatype_time();
- static private readonly DatatypeImplementation s_timeNoTz = new Datatype_timeNoTimeZone(); // XDR
- static private readonly DatatypeImplementation s_timeTz = new Datatype_timeTimeZone(); // XDR
- static private readonly DatatypeImplementation s_token = new Datatype_token();
- static private readonly DatatypeImplementation s_unsignedByte = new Datatype_unsignedByte();
- static private readonly DatatypeImplementation s_unsignedInt = new Datatype_unsignedInt();
- static private readonly DatatypeImplementation s_unsignedLong = new Datatype_unsignedLong();
- static private readonly DatatypeImplementation s_unsignedShort = new Datatype_unsignedShort();
- static private readonly DatatypeImplementation s_uuid = new Datatype_uuid(); // XDR
- static private readonly DatatypeImplementation s_year = new Datatype_year();
- static private readonly DatatypeImplementation s_yearMonth = new Datatype_yearMonth();
+ private static readonly DatatypeImplementation s_anySimpleType = new Datatype_anySimpleType();
+ private static readonly DatatypeImplementation s_anyURI = new Datatype_anyURI();
+ private static readonly DatatypeImplementation s_base64Binary = new Datatype_base64Binary();
+ private static readonly DatatypeImplementation s_boolean = new Datatype_boolean();
+ private static readonly DatatypeImplementation s_byte = new Datatype_byte();
+ private static readonly DatatypeImplementation s_char = new Datatype_char(); // XDR
+ private static readonly DatatypeImplementation s_date = new Datatype_date();
+ private static readonly DatatypeImplementation s_dateTime = new Datatype_dateTime();
+ private static readonly DatatypeImplementation s_dateTimeNoTz = new Datatype_dateTimeNoTimeZone(); // XDR
+ private static readonly DatatypeImplementation s_dateTimeTz = new Datatype_dateTimeTimeZone(); // XDR
+ private static readonly DatatypeImplementation s_day = new Datatype_day();
+ private static readonly DatatypeImplementation s_decimal = new Datatype_decimal();
+ private static readonly DatatypeImplementation s_double = new Datatype_double();
+ private static readonly DatatypeImplementation s_doubleXdr = new Datatype_doubleXdr(); // XDR
+ private static readonly DatatypeImplementation s_duration = new Datatype_duration();
+ private static readonly DatatypeImplementation s_ENTITY = new Datatype_ENTITY();
+ private static readonly DatatypeImplementation s_ENTITIES = (DatatypeImplementation)s_ENTITY.DeriveByList(1, null);
+ private static readonly DatatypeImplementation s_ENUMERATION = new Datatype_ENUMERATION(); // XDR
+ private static readonly DatatypeImplementation s_fixed = new Datatype_fixed();
+ private static readonly DatatypeImplementation s_float = new Datatype_float();
+ private static readonly DatatypeImplementation s_floatXdr = new Datatype_floatXdr(); // XDR
+ private static readonly DatatypeImplementation s_hexBinary = new Datatype_hexBinary();
+ private static readonly DatatypeImplementation s_ID = new Datatype_ID();
+ private static readonly DatatypeImplementation s_IDREF = new Datatype_IDREF();
+ private static readonly DatatypeImplementation s_IDREFS = (DatatypeImplementation)s_IDREF.DeriveByList(1, null);
+ private static readonly DatatypeImplementation s_int = new Datatype_int();
+ private static readonly DatatypeImplementation s_integer = new Datatype_integer();
+ private static readonly DatatypeImplementation s_language = new Datatype_language();
+ private static readonly DatatypeImplementation s_long = new Datatype_long();
+ private static readonly DatatypeImplementation s_month = new Datatype_month();
+ private static readonly DatatypeImplementation s_monthDay = new Datatype_monthDay();
+ private static readonly DatatypeImplementation s_name = new Datatype_Name();
+ private static readonly DatatypeImplementation s_NCName = new Datatype_NCName();
+ private static readonly DatatypeImplementation s_negativeInteger = new Datatype_negativeInteger();
+ private static readonly DatatypeImplementation s_NMTOKEN = new Datatype_NMTOKEN();
+ private static readonly DatatypeImplementation s_NMTOKENS = (DatatypeImplementation)s_NMTOKEN.DeriveByList(1, null);
+ private static readonly DatatypeImplementation s_nonNegativeInteger = new Datatype_nonNegativeInteger();
+ private static readonly DatatypeImplementation s_nonPositiveInteger = new Datatype_nonPositiveInteger();
+ private static readonly DatatypeImplementation s_normalizedString = new Datatype_normalizedString();
+ private static readonly DatatypeImplementation s_NOTATION = new Datatype_NOTATION();
+ private static readonly DatatypeImplementation s_positiveInteger = new Datatype_positiveInteger();
+ private static readonly DatatypeImplementation s_QName = new Datatype_QName();
+ private static readonly DatatypeImplementation s_QNameXdr = new Datatype_QNameXdr(); //XDR
+ private static readonly DatatypeImplementation s_short = new Datatype_short();
+ private static readonly DatatypeImplementation s_string = new Datatype_string();
+ private static readonly DatatypeImplementation s_time = new Datatype_time();
+ private static readonly DatatypeImplementation s_timeNoTz = new Datatype_timeNoTimeZone(); // XDR
+ private static readonly DatatypeImplementation s_timeTz = new Datatype_timeTimeZone(); // XDR
+ private static readonly DatatypeImplementation s_token = new Datatype_token();
+ private static readonly DatatypeImplementation s_unsignedByte = new Datatype_unsignedByte();
+ private static readonly DatatypeImplementation s_unsignedInt = new Datatype_unsignedInt();
+ private static readonly DatatypeImplementation s_unsignedLong = new Datatype_unsignedLong();
+ private static readonly DatatypeImplementation s_unsignedShort = new Datatype_unsignedShort();
+ private static readonly DatatypeImplementation s_uuid = new Datatype_uuid(); // XDR
+ private static readonly DatatypeImplementation s_year = new Datatype_year();
+ private static readonly DatatypeImplementation s_yearMonth = new Datatype_yearMonth();
//V1 compat types
- static internal readonly DatatypeImplementation c_normalizedStringV1Compat = new Datatype_normalizedStringV1Compat();
- static internal readonly DatatypeImplementation c_tokenV1Compat = new Datatype_tokenV1Compat();
+ internal static readonly DatatypeImplementation c_normalizedStringV1Compat = new Datatype_normalizedStringV1Compat();
+ internal static readonly DatatypeImplementation c_tokenV1Compat = new Datatype_tokenV1Compat();
// XQuery types
- static private readonly DatatypeImplementation s_anyAtomicType = new Datatype_anyAtomicType();
- static private readonly DatatypeImplementation s_dayTimeDuration = new Datatype_dayTimeDuration();
- static private readonly DatatypeImplementation s_untypedAtomicType = new Datatype_untypedAtomicType();
- static private readonly DatatypeImplementation s_yearMonthDuration = new Datatype_yearMonthDuration();
+ private static readonly DatatypeImplementation s_anyAtomicType = new Datatype_anyAtomicType();
+ private static readonly DatatypeImplementation s_dayTimeDuration = new Datatype_dayTimeDuration();
+ private static readonly DatatypeImplementation s_untypedAtomicType = new Datatype_untypedAtomicType();
+ private static readonly DatatypeImplementation s_yearMonthDuration = new Datatype_yearMonthDuration();
private class SchemaDatatypeMap : IComparable
diff --git a/src/System.Private.Xml/src/System/Xml/Schema/DtdParser.cs b/src/System.Private.Xml/src/System/Xml/Schema/DtdParser.cs
index d1c40d85b5..618edb4fb8 100644
--- a/src/System.Private.Xml/src/System/Xml/Schema/DtdParser.cs
+++ b/src/System.Private.Xml/src/System/Xml/Schema/DtdParser.cs
@@ -546,8 +546,8 @@ namespace System.Xml
ParseSubset();
#if DEBUG
- Debug.Assert( readerAdapter.EntityStackLength == 0 ||
- ( freeFloatingDtd && readerAdapter.EntityStackLength == 1 ) );
+ Debug.Assert( _readerAdapter.EntityStackLength == 0 ||
+ ( _freeFloatingDtd && _readerAdapter.EntityStackLength == 1 ) );
#endif
}
@@ -630,8 +630,8 @@ namespace System.Xml
}
#if DEBUG
// check entity nesting
- Debug.Assert( readerAdapter.EntityStackLength == 0 ||
- ( freeFloatingDtd && readerAdapter.EntityStackLength == 1 ) );
+ Debug.Assert( _readerAdapter.EntityStackLength == 0 ||
+ ( _freeFloatingDtd && _readerAdapter.EntityStackLength == 1 ) );
#endif
}
else
diff --git a/src/System.Private.Xml/src/System/Xml/Schema/DtdParserAsync.cs b/src/System.Private.Xml/src/System/Xml/Schema/DtdParserAsync.cs
index a44fc7203e..1e4748ee33 100644
--- a/src/System.Private.Xml/src/System/Xml/Schema/DtdParserAsync.cs
+++ b/src/System.Private.Xml/src/System/Xml/Schema/DtdParserAsync.cs
@@ -164,8 +164,8 @@ namespace System.Xml
await ParseSubsetAsync().ConfigureAwait(false);
#if DEBUG
- Debug.Assert( readerAdapter.EntityStackLength == 0 ||
- ( freeFloatingDtd && readerAdapter.EntityStackLength == 1 ) );
+ Debug.Assert( _readerAdapter.EntityStackLength == 0 ||
+ ( _freeFloatingDtd && _readerAdapter.EntityStackLength == 1 ) );
#endif
}
@@ -248,8 +248,8 @@ namespace System.Xml
}
#if DEBUG
// check entity nesting
- Debug.Assert( readerAdapter.EntityStackLength == 0 ||
- ( freeFloatingDtd && readerAdapter.EntityStackLength == 1 ) );
+ Debug.Assert( _readerAdapter.EntityStackLength == 0 ||
+ ( _freeFloatingDtd && _readerAdapter.EntityStackLength == 1 ) );
#endif
}
else
diff --git a/src/System.Private.Xml/src/System/Xml/Serialization/CodeGenerator.cs b/src/System.Private.Xml/src/System/Xml/Serialization/CodeGenerator.cs
index cf0d8f497c..c16e8eec9c 100644
--- a/src/System.Private.Xml/src/System/Xml/Serialization/CodeGenerator.cs
+++ b/src/System.Private.Xml/src/System/Xml/Serialization/CodeGenerator.cs
@@ -1282,7 +1282,7 @@ namespace System.Xml.Serialization
return ifState;
}
- static internal AssemblyBuilder CreateAssemblyBuilder(string name)
+ internal static AssemblyBuilder CreateAssemblyBuilder(string name)
{
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = name;
@@ -1290,11 +1290,11 @@ namespace System.Xml.Serialization
return AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
}
- static internal ModuleBuilder CreateModuleBuilder(AssemblyBuilder assemblyBuilder, string name)
+ internal static ModuleBuilder CreateModuleBuilder(AssemblyBuilder assemblyBuilder, string name)
{
return assemblyBuilder.DefineDynamicModule(name);
}
- static internal TypeBuilder CreateTypeBuilder(ModuleBuilder moduleBuilder, string name, TypeAttributes attributes, Type parent, Type[] interfaces)
+ internal static TypeBuilder CreateTypeBuilder(ModuleBuilder moduleBuilder, string name, TypeAttributes attributes, Type parent, Type[] interfaces)
{
// parent is nullable if no base class
return moduleBuilder.DefineType(TempAssembly.GeneratedAssemblyNamespace + "." + name,
diff --git a/src/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationWriter.cs b/src/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationWriter.cs
index 56f5e1fde5..1073070777 100644
--- a/src/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationWriter.cs
+++ b/src/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationWriter.cs
@@ -387,7 +387,7 @@ namespace System.Xml.Serialization
throw new PlatformNotSupportedException();
}
- WriteStructMethod(mapping, name, ns, o, mapping.TypeDesc.IsNullable, needType: false, parentMapping: parentMapping);
+ WriteStructMethod(mapping, name, ns, o, element.IsNullable, needType: false, parentMapping: parentMapping);
}
else if (element.Mapping is SpecialMapping)
{
@@ -477,7 +477,7 @@ namespace System.Xml.Serialization
{
if (mapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(mapping.TypeDesc.Type))
{
- throw new PlatformNotSupportedException(typeof(XmlSchemaObject).ToString());
+ EscapeName = false;
}
XmlSerializerNamespaces xmlnsSource = null;
@@ -711,83 +711,82 @@ namespace System.Xml.Serialization
}
}
- var a = memberValue as IEnumerable;
-
- // #10593: Add More Tests for Serialization Code
- Debug.Assert(a != null);
-
- var e = a.GetEnumerator();
- bool shouldAppendWhitespace = false;
- if (e != null)
+ if (memberValue != null)
{
- while (e.MoveNext())
+ var a = (IEnumerable) memberValue;
+ IEnumerator e = a.GetEnumerator();
+ bool shouldAppendWhitespace = false;
+ if (e != null)
{
- object ai = e.Current;
-
- if (attribute.IsList)
+ while (e.MoveNext())
{
- string stringValue;
- if (attribute.Mapping is EnumMapping)
- {
- stringValue = WriteEnumMethod((EnumMapping)attribute.Mapping, ai);
- }
- else
+ object ai = e.Current;
+
+ if (attribute.IsList)
{
- if (!WritePrimitiveValue(arrayElementTypeDesc, ai, true, out stringValue))
+ string stringValue;
+ if (attribute.Mapping is EnumMapping)
{
- // #10593: Add More Tests for Serialization Code
- Debug.Assert(ai is byte[]);
+ stringValue = WriteEnumMethod((EnumMapping)attribute.Mapping, ai);
}
- }
-
- // check to see if we can write values of the attribute sequentially
- if (canOptimizeWriteListSequence)
- {
- if (shouldAppendWhitespace)
+ else
{
- Writer.WriteString(" ");
+ if (!WritePrimitiveValue(arrayElementTypeDesc, ai, true, out stringValue))
+ {
+ // #10593: Add More Tests for Serialization Code
+ Debug.Assert(ai is byte[]);
+ }
}
- if (ai is byte[])
+ // check to see if we can write values of the attribute sequentially
+ if (canOptimizeWriteListSequence)
{
- WriteValue((byte[])ai);
+ if (shouldAppendWhitespace)
+ {
+ Writer.WriteString(" ");
+ }
+
+ if (ai is byte[])
+ {
+ WriteValue((byte[])ai);
+ }
+ else
+ {
+ WriteValue(stringValue);
+ }
}
else
{
- WriteValue(stringValue);
+ if (shouldAppendWhitespace)
+ {
+ sb.Append(" ");
+ }
+
+ sb.Append(stringValue);
}
}
else
{
- if (shouldAppendWhitespace)
- {
- sb.Append(" ");
- }
-
- sb.Append(stringValue);
+ WriteAttribute(ai, attribute, parent);
}
- }
- else
- {
- WriteAttribute(ai, attribute, parent);
- }
- shouldAppendWhitespace = true;
- }
-
- if (attribute.IsList)
- {
- // check to see if we can write values of the attribute sequentially
- if (canOptimizeWriteListSequence)
- {
- Writer.WriteEndAttribute();
+ shouldAppendWhitespace = true;
}
- else
+
+ if (attribute.IsList)
{
- if (sb.Length != 0)
+ // check to see if we can write values of the attribute sequentially
+ if (canOptimizeWriteListSequence)
+ {
+ Writer.WriteEndAttribute();
+ }
+ else
{
- string ns = attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : String.Empty;
- WriteAttribute(attribute.Name, ns, sb.ToString());
+ if (sb.Length != 0)
+ {
+ string ns = attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : String.Empty;
+ WriteAttribute(attribute.Name, ns, sb.ToString());
+ }
}
}
}
diff --git a/src/System.Private.Xml/src/System/Xml/Serialization/Types.cs b/src/System.Private.Xml/src/System/Xml/Serialization/Types.cs
index 85f3164425..8a61b46409 100644
--- a/src/System.Private.Xml/src/System/Xml/Serialization/Types.cs
+++ b/src/System.Private.Xml/src/System/Xml/Serialization/Types.cs
@@ -1366,7 +1366,7 @@ namespace System.Xml.Serialization
return GetDefaultIndexer(type, memberInfo).PropertyType;
}
- static internal XmlQualifiedName ParseWsdlArrayType(string type, out string dims, XmlSchemaObject parent)
+ internal static XmlQualifiedName ParseWsdlArrayType(string type, out string dims, XmlSchemaObject parent)
{
string ns;
string name;
diff --git a/src/System.Private.Xml/src/System/Xml/Serialization/XmlSchemaExporter.cs b/src/System.Private.Xml/src/System/Xml/Serialization/XmlSchemaExporter.cs
index 68048dec54..69cba3f4c8 100644
--- a/src/System.Private.Xml/src/System/Xml/Serialization/XmlSchemaExporter.cs
+++ b/src/System.Private.Xml/src/System/Xml/Serialization/XmlSchemaExporter.cs
@@ -900,7 +900,7 @@ namespace System.Xml.Serialization
}
}
- static internal string ExportDefaultValue(TypeMapping mapping, object value)
+ internal static string ExportDefaultValue(TypeMapping mapping, object value)
{
if (!(mapping is PrimitiveMapping))
// should throw, but it will be a breaking change;
diff --git a/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationILGen.cs b/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationILGen.cs
index 51268d7a85..c4c49ac945 100644
--- a/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationILGen.cs
+++ b/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationILGen.cs
@@ -67,7 +67,7 @@ namespace System.Xml.Serialization
internal TypeAttributes TypeAttributes { get { return _typeAttributes; } }
private static Dictionary<string, Regex> s_regexs = new Dictionary<string, Regex>();
- static internal Regex NewRegex(string pattern)
+ internal static Regex NewRegex(string pattern)
{
Regex regex;
lock (s_regexs)
diff --git a/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs b/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs
index 9ed7900a1c..1b4e999e01 100644
--- a/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs
+++ b/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs
@@ -617,7 +617,7 @@ namespace System.Xml.Serialization
{
#if DEBUG
// use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
- if (!objectsInUse.ContainsKey(o)) throw new InvalidOperationException(SR.Format(SR.XmlInternalErrorDetails, "missing stack object of type " + o.GetType().FullName));
+ if (!_objectsInUse.ContainsKey(o)) throw new InvalidOperationException(SR.Format(SR.XmlInternalErrorDetails, "missing stack object of type " + o.GetType().FullName));
#endif
_objectsInUse.Remove(o);
diff --git a/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs b/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs
index 274eec581d..e6d0596914 100644
--- a/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs
+++ b/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs
@@ -113,16 +113,16 @@ namespace System.Xml.Serialization
/// </devdoc>
public class XmlSerializer
{
- private enum SerializationMode
+ public enum SerializationMode
{
CodeGenOnly,
ReflectionOnly,
ReflectionAsBackup
}
- private SerializationMode Mode { get; set; } = SerializationMode.ReflectionAsBackup;
+ public static SerializationMode Mode { get; set; } = SerializationMode.ReflectionAsBackup;
- private bool ReflectionMethodEnabled
+ private static bool ReflectionMethodEnabled
{
get
{
diff --git a/src/System.Private.Xml/src/System/Xml/XPath/Internal/CacheChildrenQuery.cs b/src/System.Private.Xml/src/System/Xml/XPath/Internal/CacheChildrenQuery.cs
index 9ec24808b9..391b4478d2 100644
--- a/src/System.Private.Xml/src/System/Xml/XPath/Internal/CacheChildrenQuery.cs
+++ b/src/System.Private.Xml/src/System/Xml/XPath/Internal/CacheChildrenQuery.cs
@@ -2,6 +2,7 @@
// 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.Xml;
using System.Xml.XPath;
using StackInt = MS.Internal.Xml.XPath.ClonableStack<int>;
@@ -99,7 +100,7 @@ namespace MS.Internal.Xml.XPath
Debug.Assert(order == XmlNodeOrder.Before, "Algorith error. Nodes expected to be DocOrderDistinct");
}
}
- lastNode = currentNode.Clone();
+ _lastNode = currentNode.Clone();
#endif
if (matches(currentNode))
{
diff --git a/src/System.Private.Xml/src/System/Xml/XPath/Internal/Operator.cs b/src/System.Private.Xml/src/System/Xml/XPath/Internal/Operator.cs
index b388aac19e..3ea10fc17e 100644
--- a/src/System.Private.Xml/src/System/Xml/XPath/Internal/Operator.cs
+++ b/src/System.Private.Xml/src/System/Xml/XPath/Internal/Operator.cs
@@ -45,7 +45,7 @@ namespace MS.Internal.Xml.XPath
/*GE */ Op.LE,
};
- static public Operator.Op InvertOperator(Operator.Op op)
+ public static Operator.Op InvertOperator(Operator.Op op)
{
Debug.Assert(Op.EQ <= op && op <= Op.GE);
return s_invertOp[(int)op];
diff --git a/src/System.Private.Xml/src/System/Xml/XPath/XPathNavigatorReader.cs b/src/System.Private.Xml/src/System/Xml/XPath/XPathNavigatorReader.cs
index b0d2d94a1e..936cfa06e6 100644
--- a/src/System.Private.Xml/src/System/Xml/XPath/XPathNavigatorReader.cs
+++ b/src/System.Private.Xml/src/System/Xml/XPath/XPathNavigatorReader.cs
@@ -75,7 +75,7 @@ namespace System.Xml.XPath
}
}
- static public XPathNavigatorReader Create(XPathNavigator navToRead)
+ public static XPathNavigatorReader Create(XPathNavigator navToRead)
{
XPathNavigator nav = navToRead.Clone();
IXmlLineInfo xli = nav as IXmlLineInfo;
diff --git a/src/System.Private.Xml/src/System/Xml/XmlCharType.cs b/src/System.Private.Xml/src/System/Xml/XmlCharType.cs
index 5e77c397ad..e02c40c1db 100644
--- a/src/System.Private.Xml/src/System/Xml/XmlCharType.cs
+++ b/src/System.Private.Xml/src/System/Xml/XmlCharType.cs
@@ -9,7 +9,7 @@ using System.Runtime.CompilerServices;
namespace System.Xml
{
- unsafe internal struct XmlCharType
+ internal unsafe struct XmlCharType
{
// Surrogate constants
internal const int SurHighStart = 0xd800; // 1101 10xx
@@ -1242,7 +1242,7 @@ namespace System.Xml
return -1;
}
- static internal bool IsOnlyDigits(string str, int startPos, int len)
+ internal static bool IsOnlyDigits(string str, int startPos, int len)
{
Debug.Assert(str != null);
Debug.Assert(startPos + len <= str.Length);
@@ -1258,7 +1258,7 @@ namespace System.Xml
return true;
}
- static internal bool IsOnlyDigits(char[] chars, int startPos, int len)
+ internal static bool IsOnlyDigits(char[] chars, int startPos, int len)
{
Debug.Assert(chars != null);
Debug.Assert(startPos + len <= chars.Length);
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/IlGen/GenerateHelper.cs b/src/System.Private.Xml/src/System/Xml/Xsl/IlGen/GenerateHelper.cs
index c2ef742661..b28ccbbc36 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/IlGen/GenerateHelper.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/IlGen/GenerateHelper.cs
@@ -661,10 +661,6 @@ namespace System.Xml.Xsl.IlGen
LocalBuilder locBldr = _ilgen.DeclareLocal(type);
#if DEBUG
if (XmlILTrace.IsEnabled) {
- // Set name for internal MS debugging. This is not the user-defined name--that will be set later
- if (this.isDebug)
- locBldr.SetLocalSymInfo(name + this.numLocals.ToString(CultureInfo.InvariantCulture));
-
this.symbols.Add(locBldr, name + this.numLocals.ToString(CultureInfo.InvariantCulture));
this.numLocals++;
}
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/IlGen/XmlILModule.cs b/src/System.Private.Xml/src/System/Xml/Xsl/IlGen/XmlILModule.cs
index 55cb56bfff..710d35b90d 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/IlGen/XmlILModule.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/IlGen/XmlILModule.cs
@@ -111,12 +111,6 @@ namespace System.Xml.Xsl.IlGen
// 3. Never allow assembly to Assert permissions
asmName = CreateAssemblyName();
-#if DEBUG
- if (XmlILTrace.IsEnabled) {
- this.modFile = "System.Xml.Xsl.CompiledQuery";
- }
-#endif
-
asmBldr = AssemblyBuilder.DefineDynamicAssembly(
asmName, AssemblyBuilderAccess.Run);
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/QIL/QilValidationVisitor.cs b/src/System.Private.Xml/src/System/Xml/Xsl/QIL/QilValidationVisitor.cs
index 0cf18b2b14..5fb1f51886 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/QIL/QilValidationVisitor.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/QIL/QilValidationVisitor.cs
@@ -64,7 +64,7 @@ namespace System.Xml.Xsl.Qil
SetError(parent, "Type information missing");
}
else {
- XmlQueryType type = this.typeCheck.Check(parent);
+ XmlQueryType type = this._typeCheck.Check(parent);
// BUGBUG: Hack to account for Xslt compiler type fixups
if (!type.IsSubtypeOf(parent.XmlType))
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/Runtime/WhitespaceRuleReader.cs b/src/System.Private.Xml/src/System/Xml/Xsl/Runtime/WhitespaceRuleReader.cs
index 534a57d650..b7c942679b 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/Runtime/WhitespaceRuleReader.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/Runtime/WhitespaceRuleReader.cs
@@ -21,7 +21,7 @@ namespace System.Xml.Xsl.Runtime
private string _val;
private XmlCharType _xmlCharType = XmlCharType.Instance;
- static public XmlReader CreateReader(XmlReader baseReader, WhitespaceRuleLookup wsRules)
+ public static XmlReader CreateReader(XmlReader baseReader, WhitespaceRuleLookup wsRules)
{
if (wsRules == null)
{
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/Runtime/XsltLibrary.cs b/src/System.Private.Xml/src/System/Xml/Xsl/Runtime/XsltLibrary.cs
index 516e1f5ea2..7f790d2a7d 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/Runtime/XsltLibrary.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/Runtime/XsltLibrary.cs
@@ -234,6 +234,59 @@ namespace System.Xml.Xsl.Runtime
}
internal const int InvariantCultureLcid = 0x007f;
+
+ public int LangToLcid(string lang, bool forwardCompatibility)
+ {
+ return LangToLcidInternal(lang, forwardCompatibility, null);
+ }
+
+ internal static int LangToLcidInternal(string lang, bool forwardCompatibility, IErrorHelper errorHelper)
+ {
+ int lcid = InvariantCultureLcid;
+
+ if (lang != null)
+ {
+ // The value of the 'lang' attribute must be a non-empty nmtoken
+ if (lang.Length == 0)
+ {
+ if (!forwardCompatibility)
+ {
+ if (errorHelper != null)
+ {
+ errorHelper.ReportError(SR.Xslt_InvalidAttrValue, "lang", lang);
+ }
+ else
+ {
+ throw new XslTransformException(SR.Xslt_InvalidAttrValue, "lang", lang);
+ }
+ }
+ }
+ else
+ {
+ // Check if lang is a supported culture name
+ try
+ {
+ lcid = new CultureInfo(lang).LCID;
+ }
+ catch (ArgumentException)
+ {
+ if (!forwardCompatibility)
+ {
+ if (errorHelper != null)
+ {
+ errorHelper.ReportError(SR.Xslt_InvalidLanguage, lang);
+ }
+ else
+ {
+ throw new XslTransformException(SR.Xslt_InvalidLanguage, lang);
+ }
+ }
+ }
+ }
+ }
+ return lcid;
+ }
+
internal const string InvariantCultureName = "";
internal static string LangToNameInternal(string lang, bool forwardCompatibility, IErrorHelper errorHelper)
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs b/src/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs
index 9364a7c4ab..e09196da00 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs
@@ -2351,7 +2351,7 @@ namespace System.Xml.Xsl
InitFromDouble(dbl);
#if DEBUG
- if (0 != mantissaSize)
+ if (0 != _mantissaSize)
{
Debug.Assert(dbl == (double)this);
@@ -2370,12 +2370,12 @@ namespace System.Xml.Xsl
#if DEBUG
private bool Equals(FloatingDecimal other) {
- if (_exponent != other._exponent || sign != other._sign || _mantissaSize != other._mantissaSize)
+ if (_exponent != other._exponent || _sign != other._sign || _mantissaSize != other._mantissaSize)
{
return false;
}
- for (int idx = 0; idx < mantissaSize; idx++) {
- if (mantissa[idx] != other.mantissa[idx]) {
+ for (int idx = 0; idx < _mantissaSize; idx++) {
+ if (_mantissa[idx] != other._mantissa[idx]) {
return false;
}
}
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/XmlIlGenerator.cs b/src/System.Private.Xml/src/System/Xml/Xsl/XmlIlGenerator.cs
index 2d58ccb125..9be2177ad4 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/XmlIlGenerator.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/XmlIlGenerator.cs
@@ -88,10 +88,10 @@ namespace System.Xml.Xsl
#if DEBUG
// Trace Qil before optimization
- XmlILTrace.WriteQil(this.qil, "qilbefore.xml");
+ XmlILTrace.WriteQil(this._qil, "qilbefore.xml");
// Trace optimizations
- XmlILTrace.TraceOptimizations(this.qil, "qilopt.xml");
+ XmlILTrace.TraceOptimizations(this._qil, "qilopt.xml");
#endif
// Optimize and annotate the Qil graph
@@ -103,7 +103,7 @@ namespace System.Xml.Xsl
#if DEBUG
// Trace Qil after optimization
- XmlILTrace.WriteQil(this.qil, "qilafter.xml");
+ XmlILTrace.WriteQil(this._qil, "qilafter.xml");
#endif
// Create module in which methods will be generated
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs
index a365c59470..9fd82a7370 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs
@@ -70,12 +70,6 @@ namespace System.Xml.Xsl.Xslt
{
Debug.Assert(CompilerErrorColl == null, "Compiler cannot be reused");
-#if DEBUG
- if (XmlILTrace.IsEnabled) {
- tempFiles.KeepFiles = true;
- }
-#endif
-
Settings = settings;
IsDebug = settings.IncludeDebugInformation | debug;
ScriptAssemblyPath = scriptAssemblyPath;
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/MatcherBuilder.cs b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/MatcherBuilder.cs
index 23040e5cb6..6c2b082e8f 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/MatcherBuilder.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/MatcherBuilder.cs
@@ -88,7 +88,7 @@ namespace System.Xml.Xsl.Xslt
internal class TemplateMatch
{
- public readonly static TemplateMatchComparer Comparer = new TemplateMatchComparer();
+ public static readonly TemplateMatchComparer Comparer = new TemplateMatchComparer();
private Template _template;
private double _priority;
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XPathPatternParser.cs b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XPathPatternParser.cs
index 51c67351e2..267466fe0c 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XPathPatternParser.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XPathPatternParser.cs
@@ -41,8 +41,8 @@ namespace System.Xml.Xsl.Xslt
{
result = ptrnBuilder.EndBuild(result);
#if DEBUG
- this.ptrnBuilder = null;
- this.scanner = null;
+ this._ptrnBuilder = null;
+ this._scanner = null;
#endif
}
return result;
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XslAstAnalyzer.cs b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XslAstAnalyzer.cs
index 4cc394ec94..8d81555b22 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XslAstAnalyzer.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XslAstAnalyzer.cs
@@ -306,7 +306,7 @@ namespace System.Xml.Xsl.Xslt
#if DEBUG
if (DiagnosticsSwitches.XslTypeInference.TraceVerbose) {
Debug.WriteLine(string.Empty);
- foreach (ProtoTemplate tmpl in compiler.AllTemplates) {
+ foreach (ProtoTemplate tmpl in _compiler.AllTemplates) {
Debug.WriteLine(tmpl.TraceName + " = " + (tmpl.Flags & XslFlags.FocusFilter));
}
@@ -320,7 +320,7 @@ namespace System.Xml.Xsl.Xslt
if (DiagnosticsSwitches.XslTypeInference.TraceInfo) {
int current = 0, position = 0, last = 0;
- foreach (ProtoTemplate tmpl in compiler.AllTemplates) {
+ foreach (ProtoTemplate tmpl in _compiler.AllTemplates) {
if ((tmpl.Flags & XslFlags.Current) != 0) {
current++;
}
@@ -355,7 +355,7 @@ namespace System.Xml.Xsl.Xslt
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture,
"Total => templates/attribute-sets: {0}, variables/parameters: {1}.",
- compiler.AllTemplates.Count, totalVarPars
+ _compiler.AllTemplates.Count, totalVarPars
));
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture,
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltInput.cs b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltInput.cs
index f3a13d4b02..7d0ca49ca3 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltInput.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltInput.cs
@@ -710,7 +710,7 @@ namespace System.Xml.Xsl.Xslt
// to there's numbers in actual stylesheet as they ordered in 'records' array
private int[] _xsltAttributeNumber = new int[21];
- static private XsltAttribute[] s_noAttributes = new XsltAttribute[] { };
+ private static XsltAttribute[] s_noAttributes = new XsltAttribute[] { };
public ContextInfo GetAttributes()
{
return GetAttributes(s_noAttributes);
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/HtmlProps.cs b/src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/HtmlProps.cs
index 398c45e1cd..0cea3ccffa 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/HtmlProps.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/HtmlProps.cs
@@ -21,7 +21,7 @@ namespace System.Xml.Xsl.XsltOld
private bool _head;
private bool _nameParent;
- static public HtmlElementProps Create(bool empty, bool abrParent, bool uriParent, bool noEntities, bool blockWS, bool head, bool nameParent)
+ public static HtmlElementProps Create(bool empty, bool abrParent, bool uriParent, bool noEntities, bool blockWS, bool head, bool nameParent)
{
HtmlElementProps props = new HtmlElementProps();
props._empty = empty;
@@ -42,10 +42,10 @@ namespace System.Xml.Xsl.XsltOld
public bool NameParent { get { return _nameParent; } }
- static private Hashtable s_table = CreatePropsTable();
- // static private HtmlElementProps s_otherElements = Create(false, false, false, false, false, false, false);
+ private static Hashtable s_table = CreatePropsTable();
+ // private static HtmlElementProps s_otherElements = Create(false, false, false, false, false, false, false);
- static public HtmlElementProps GetProps(string name)
+ public static HtmlElementProps GetProps(string name)
{
HtmlElementProps result = (HtmlElementProps)s_table[name];
return result;
@@ -141,7 +141,7 @@ namespace System.Xml.Xsl.XsltOld
private bool _uri;
private bool _name;
- static public HtmlAttributeProps Create(bool abr, bool uri, bool name)
+ public static HtmlAttributeProps Create(bool abr, bool uri, bool name)
{
HtmlAttributeProps props = new HtmlAttributeProps();
props._abr = abr;
@@ -153,10 +153,10 @@ namespace System.Xml.Xsl.XsltOld
public bool Uri { get { return _uri; } }
public bool Name { get { return _name; } }
- static private Hashtable s_table = CreatePropsTable();
- // static private HtmlElementProps s_otherAttributes = Create(false, false, false);
+ private static Hashtable s_table = CreatePropsTable();
+ // private static HtmlElementProps s_otherAttributes = Create(false, false, false);
- static public HtmlAttributeProps GetProps(string name)
+ public static HtmlAttributeProps GetProps(string name)
{
HtmlAttributeProps result = (HtmlAttributeProps)s_table[name];
return result;
diff --git a/src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/StringOutput.cs b/src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/StringOutput.cs
index f60e12f390..7adeb8748f 100644
--- a/src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/StringOutput.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xsl/XsltOld/StringOutput.cs
@@ -32,7 +32,7 @@ namespace System.Xml.Xsl.XsltOld
_builder.Append(outputChar);
#if DEBUG
- this.result = this.builder.ToString();
+ this._result = this._builder.ToString();
#endif
}
@@ -41,7 +41,7 @@ namespace System.Xml.Xsl.XsltOld
_builder.Append(outputText);
#if DEBUG
- this.result = this.builder.ToString();
+ this._result = this._builder.ToString();
#endif
}
diff --git a/src/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs b/src/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs
index 110416fabe..260f62882b 100644
--- a/src/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs
@@ -105,7 +105,7 @@ namespace System.Xml.Xsl
public void Load(XmlReader stylesheet)
{
Reset();
- LoadInternal(stylesheet, XsltSettings.Default, XmlNullResolver.Singleton);
+ LoadInternal(stylesheet, XsltSettings.Default, CreateDefaultResolver());
}
// SxS: This method does not take any resource name and does not expose any resources to the caller.
@@ -121,7 +121,7 @@ namespace System.Xml.Xsl
public void Load(IXPathNavigable stylesheet)
{
Reset();
- LoadInternal(stylesheet, XsltSettings.Default, XmlNullResolver.Singleton);
+ LoadInternal(stylesheet, XsltSettings.Default, CreateDefaultResolver());
}
// SxS: This method does not take any resource name and does not expose any resources to the caller.
@@ -139,7 +139,7 @@ namespace System.Xml.Xsl
{
throw new ArgumentNullException(nameof(stylesheetUri));
}
- LoadInternal(stylesheetUri, XsltSettings.Default, XmlNullResolver.Singleton);
+ LoadInternal(stylesheetUri, XsltSettings.Default, CreateDefaultResolver());
}
public void Load(string stylesheetUri, XsltSettings settings, XmlResolver stylesheetResolver)
@@ -273,13 +273,13 @@ namespace System.Xml.Xsl
public void Transform(IXPathNavigable input, XmlWriter results)
{
CheckArguments(input, results);
- Transform(input, (XsltArgumentList)null, results, XmlNullResolver.Singleton);
+ Transform(input, (XsltArgumentList)null, results, CreateDefaultResolver());
}
public void Transform(IXPathNavigable input, XsltArgumentList arguments, XmlWriter results)
{
CheckArguments(input, results);
- Transform(input, arguments, results, XmlNullResolver.Singleton);
+ Transform(input, arguments, results, CreateDefaultResolver());
}
public void Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results)
@@ -287,7 +287,7 @@ namespace System.Xml.Xsl
CheckArguments(input, results);
using (XmlWriter writer = XmlWriter.Create(results, OutputSettings))
{
- Transform(input, arguments, writer, XmlNullResolver.Singleton);
+ Transform(input, arguments, writer, CreateDefaultResolver());
writer.Close();
}
}
@@ -297,7 +297,7 @@ namespace System.Xml.Xsl
CheckArguments(input, results);
using (XmlWriter writer = XmlWriter.Create(results, OutputSettings))
{
- Transform(input, arguments, writer, XmlNullResolver.Singleton);
+ Transform(input, arguments, writer, CreateDefaultResolver());
writer.Close();
}
}
@@ -309,13 +309,13 @@ namespace System.Xml.Xsl
public void Transform(XmlReader input, XmlWriter results)
{
CheckArguments(input, results);
- Transform(input, (XsltArgumentList)null, results, XmlNullResolver.Singleton);
+ Transform(input, (XsltArgumentList)null, results, CreateDefaultResolver());
}
public void Transform(XmlReader input, XsltArgumentList arguments, XmlWriter results)
{
CheckArguments(input, results);
- Transform(input, arguments, results, XmlNullResolver.Singleton);
+ Transform(input, arguments, results, CreateDefaultResolver());
}
public void Transform(XmlReader input, XsltArgumentList arguments, TextWriter results)
@@ -323,7 +323,7 @@ namespace System.Xml.Xsl
CheckArguments(input, results);
using (XmlWriter writer = XmlWriter.Create(results, OutputSettings))
{
- Transform(input, arguments, writer, XmlNullResolver.Singleton);
+ Transform(input, arguments, writer, CreateDefaultResolver());
writer.Close();
}
}
@@ -333,7 +333,7 @@ namespace System.Xml.Xsl
CheckArguments(input, results);
using (XmlWriter writer = XmlWriter.Create(results, OutputSettings))
{
- Transform(input, arguments, writer, XmlNullResolver.Singleton);
+ Transform(input, arguments, writer, CreateDefaultResolver());
writer.Close();
}
}
@@ -351,7 +351,7 @@ namespace System.Xml.Xsl
CheckArguments(inputUri, results);
using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
{
- Transform(reader, (XsltArgumentList)null, results, XmlNullResolver.Singleton);
+ Transform(reader, (XsltArgumentList)null, results, CreateDefaultResolver());
}
}
@@ -361,7 +361,7 @@ namespace System.Xml.Xsl
CheckArguments(inputUri, results);
using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
{
- Transform(reader, arguments, results, XmlNullResolver.Singleton);
+ Transform(reader, arguments, results, CreateDefaultResolver());
}
}
@@ -372,7 +372,7 @@ namespace System.Xml.Xsl
using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
using (XmlWriter writer = XmlWriter.Create(results, OutputSettings))
{
- Transform(reader, arguments, writer, XmlNullResolver.Singleton);
+ Transform(reader, arguments, writer, CreateDefaultResolver());
writer.Close();
}
}
@@ -384,7 +384,7 @@ namespace System.Xml.Xsl
using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
using (XmlWriter writer = XmlWriter.Create(results, OutputSettings))
{
- Transform(reader, arguments, writer, XmlNullResolver.Singleton);
+ Transform(reader, arguments, writer, CreateDefaultResolver());
writer.Close();
}
}
@@ -402,7 +402,7 @@ namespace System.Xml.Xsl
using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
using (XmlWriter writer = XmlWriter.Create(resultsFile, OutputSettings))
{
- Transform(reader, (XsltArgumentList)null, writer, XmlNullResolver.Singleton);
+ Transform(reader, (XsltArgumentList)null, writer, CreateDefaultResolver());
writer.Close();
}
}
@@ -459,6 +459,18 @@ namespace System.Xml.Xsl
}
}
+ private static XmlResolver CreateDefaultResolver()
+ {
+ if (LocalAppContextSwitches.AllowDefaultResolver)
+ {
+ return new XmlUrlResolver();
+ }
+ else
+ {
+ return XmlNullResolver.Singleton;
+ }
+ }
+
//------------------------------------------------
// Test suites entry points
//------------------------------------------------
diff --git a/src/System.Private.Xml/src/System/Xml/Xslt/XslTransform.cs b/src/System.Private.Xml/src/System/Xml/Xslt/XslTransform.cs
index 0dcf0f4c1f..996755c163 100644
--- a/src/System.Private.Xml/src/System/Xml/Xslt/XslTransform.cs
+++ b/src/System.Private.Xml/src/System/Xml/Xslt/XslTransform.cs
@@ -27,7 +27,9 @@ namespace System.Xml.Xsl
if (_isDocumentResolverSet)
return _documentResolver;
else
- return XmlNullResolver.Singleton;
+ {
+ return CreateDefaultResolver();
+ }
}
}
@@ -54,7 +56,7 @@ namespace System.Xml.Xsl
public void Load(XmlReader stylesheet)
{
- Load(stylesheet, XmlNullResolver.Singleton);
+ Load(stylesheet, CreateDefaultResolver());
}
public void Load(XmlReader stylesheet, XmlResolver resolver)
{
@@ -67,7 +69,7 @@ namespace System.Xml.Xsl
public void Load(IXPathNavigable stylesheet)
{
- Load(stylesheet, XmlNullResolver.Singleton);
+ Load(stylesheet, CreateDefaultResolver());
}
public void Load(IXPathNavigable stylesheet, XmlResolver resolver)
{
@@ -84,7 +86,7 @@ namespace System.Xml.Xsl
{
throw new ArgumentNullException(nameof(stylesheet));
}
- Load(stylesheet, XmlNullResolver.Singleton);
+ Load(stylesheet, CreateDefaultResolver());
}
public void Load(XPathNavigator stylesheet, XmlResolver resolver)
@@ -99,7 +101,7 @@ namespace System.Xml.Xsl
public void Load(string url)
{
XmlTextReaderImpl tr = new XmlTextReaderImpl(url);
- Compile(Compiler.LoadDocument(tr).CreateNavigator(), XmlNullResolver.Singleton);
+ Compile(Compiler.LoadDocument(tr).CreateNavigator(), CreateDefaultResolver());
}
public void Load(string url, XmlResolver resolver)
@@ -302,6 +304,18 @@ namespace System.Xml.Xsl
}
}
+ private static XmlResolver CreateDefaultResolver()
+ {
+ if (LocalAppContextSwitches.AllowDefaultResolver)
+ {
+ return new XmlUrlResolver();
+ }
+ else
+ {
+ return XmlNullResolver.Singleton;
+ }
+ }
+
private class DebuggerAddapter : IXsltDebugger
{
private object _unknownDebugger;
diff --git a/src/System.Private.Xml/tests/Readers/CustomReader/CReaderTestModule.cs b/src/System.Private.Xml/tests/Readers/CustomReader/CReaderTestModule.cs
index 99eb11a617..c07d683d5a 100644
--- a/src/System.Private.Xml/tests/Readers/CustomReader/CReaderTestModule.cs
+++ b/src/System.Private.Xml/tests/Readers/CustomReader/CReaderTestModule.cs
@@ -34,7 +34,7 @@ namespace System.Xml.Tests
[Fact]
[OuterLoop]
- static public void RunTests()
+ public static void RunTests()
{
RunTest(() => new TCReadReader() { Attribute = new TestCase() { Name = "Read", Desc = "CustomInheritedReader" } });
}
diff --git a/src/System.Private.Xml/tests/Readers/NameTable/CNameTableTestModule.cs b/src/System.Private.Xml/tests/Readers/NameTable/CNameTableTestModule.cs
index 33454fcd2b..0bb31888a7 100644
--- a/src/System.Private.Xml/tests/Readers/NameTable/CNameTableTestModule.cs
+++ b/src/System.Private.Xml/tests/Readers/NameTable/CNameTableTestModule.cs
@@ -34,21 +34,21 @@ namespace System.Xml.Tests
[Fact]
[OuterLoop]
- static public void TCUserNameTable()
+ public static void TCUserNameTable()
{
RunTest(() => new TCUserNameTable() { Attribute = new TestCase() { Name = "XmlNameTable user scenario inheritance", Desc = "XmlNameTable inheritance" } });
}
[Fact]
[OuterLoop]
- static public void NameTableVerifyWGetChar()
+ public static void NameTableVerifyWGetChar()
{
RunTest(() => new TCRecordNameTableGet() { Attribute = new TestCase() { Name = "NameTable(Get) VerifyWGetChar", Desc = "VerifyWGetChar" } });
}
[Fact]
[OuterLoop]
- static public void NameTableVerifyWAddChar()
+ public static void NameTableVerifyWAddChar()
{
RunTest(() => new TCRecordNameTableGet() { Attribute = new TestCase() { Name = "NameTable(Get) VerifyWAddChar", Desc = "VerifyWAddChar" } });
RunTest(() => new TCRecordNameTableGet() { Attribute = new TestCase() { Name = "NameTable(Get) VerifyWAddString", Desc = "VerifyWAddString" } });
@@ -61,42 +61,42 @@ namespace System.Xml.Tests
[Fact]
[OuterLoop]
- static public void NameTableVerifyWAddString()
+ public static void NameTableVerifyWAddString()
{
RunTest(() => new TCRecordNameTableGet() { Attribute = new TestCase() { Name = "NameTable(Get) VerifyWAddString", Desc = "VerifyWAddString" } });
}
[Fact]
[OuterLoop]
- static public void NameTableVerifyWGetString()
+ public static void NameTableVerifyWGetString()
{
RunTest(() => new TCRecordNameTableGet() { Attribute = new TestCase() { Name = "NameTable(Get) VerifyWGetString", Desc = "VerifyWGetString" } });
}
[Fact]
[OuterLoop]
- static public void TCRecordNameTableAddVerifyWAddChar()
+ public static void TCRecordNameTableAddVerifyWAddChar()
{
RunTest(() => new TCRecordNameTableAdd() { Attribute = new TestCase() { Name = "NameTable(Add) VerifyWAddChar", Desc = "VerifyWAddChar" } });
}
[Fact]
[OuterLoop]
- static public void TCRecordNameTableAddVerifyWGetChar()
+ public static void TCRecordNameTableAddVerifyWGetChar()
{
RunTest(() => new TCRecordNameTableAdd() { Attribute = new TestCase() { Name = "NameTable(Add) VerifyWGetChar", Desc = "VerifyWGetChar" } });
}
[Fact]
[OuterLoop]
- static public void TCRecordNameTableAddVerifyWAddString()
+ public static void TCRecordNameTableAddVerifyWAddString()
{
RunTest(() => new TCRecordNameTableAdd() { Attribute = new TestCase() { Name = "NameTable(Add) VerifyWAddString", Desc = "VerifyWAddString" } });
}
[Fact]
[OuterLoop]
- static public void TCRecordNameTableAddVerifyWGetString()
+ public static void TCRecordNameTableAddVerifyWGetString()
{
RunTest(() => new TCRecordNameTableAdd() { Attribute = new TestCase() { Name = "NameTable(Add) VerifyWGetString", Desc = "VerifyWGetString" } });
}
diff --git a/src/System.Private.Xml/tests/Readers/NameTable/TestFiles.cs b/src/System.Private.Xml/tests/Readers/NameTable/TestFiles.cs
index 91fa320f30..8e84024f07 100644
--- a/src/System.Private.Xml/tests/Readers/NameTable/TestFiles.cs
+++ b/src/System.Private.Xml/tests/Readers/NameTable/TestFiles.cs
@@ -146,11 +146,11 @@ namespace System.Xml.Tests
tw.WriteLine("<ATTRIBUTE2 a1='a1value' />");
tw.WriteLine("<ATTRIBUTE3 a1='a1value' a2='a2value' a3='a3value' />");
tw.WriteLine("<ATTRIBUTE4 a1='' />");
- tw.WriteLine("<ATTRIBUTE5 CRLF='x\r\nx' CR='x\rx' LF='x\nx' MS='x x' TAB='x\tx' />");
- tw.WriteLine("<ENDOFLINE1>x\r\nx</ENDOFLINE1>");
- tw.WriteLine("<ENDOFLINE2>x\rx</ENDOFLINE2>");
+ tw.WriteLine(string.Format("<ATTRIBUTE5 CRLF='x{0}x' CR='x{0}x' LF='x\nx' MS='x x' TAB='x\tx' />", Environment.NewLine));
+ tw.WriteLine(string.Format("<ENDOFLINE1>x{0}x</ENDOFLINE1>", Environment.NewLine));
+ tw.WriteLine(string.Format("<ENDOFLINE2>x{0}x</ENDOFLINE2>", Environment.NewLine));
tw.WriteLine("<ENDOFLINE3>x\nx</ENDOFLINE3>");
- tw.WriteLine("<WHITESPACE1>\r\n<ELEM />\r\n</WHITESPACE1>");
+ tw.WriteLine(string.Format("<WHITESPACE1>{0}<ELEM />{0}</WHITESPACE1>", Environment.NewLine));
tw.WriteLine("<WHITESPACE2> <ELEM /> </WHITESPACE2>");
tw.WriteLine("<WHITESPACE3>\t<ELEM />\t</WHITESPACE3>");
tw.WriteLine("<SKIP1 /><AFTERSKIP1 />");
@@ -259,7 +259,7 @@ namespace System.Xml.Tests
tw.WriteLine("<EMPTY4 val=\"abc\"></EMPTY4>");
tw.WriteLine("<COMPLEX>Text<!-- comment --><![CDATA[cdata]]></COMPLEX>");
tw.WriteLine("<DUMMY />");
- tw.WriteLine("<MULTISPACES att=' \r\n \t \r\r\n n1 \r\n \t \r\r\n n2 \r\n \t \r\r\n ' />");
+ tw.WriteLine(string.Format("<MULTISPACES att=' {0} \t {0}{0} n1 {0} \t {0}{0} n2 {0} \t {0}{0} ' />", Environment.NewLine));
tw.WriteLine("<CAT>AB<![CDATA[CD]]> </CAT>");
tw.WriteLine("<CATMIXED>AB<![CDATA[CD]]> </CATMIXED>");
diff --git a/src/System.Private.Xml/tests/Readers/ReaderSettings/CReaderTestModule.cs b/src/System.Private.Xml/tests/Readers/ReaderSettings/CReaderTestModule.cs
index f78794dd82..a8712e8905 100644
--- a/src/System.Private.Xml/tests/Readers/ReaderSettings/CReaderTestModule.cs
+++ b/src/System.Private.Xml/tests/Readers/ReaderSettings/CReaderTestModule.cs
@@ -30,175 +30,175 @@ namespace System.Xml.Tests
[Fact]
[OuterLoop]
- static public void TCConformanceSettings()
+ public static void TCConformanceSettings()
{
RunTest(() => new TCConformanceSettings() { Attribute = new TestCase() { Name = "Conformance Settings", Desc = "Conformance Settings" } });
}
[Fact]
[OuterLoop]
- static public void TCCreateOverloads()
+ public static void TCCreateOverloads()
{
RunTest(() => new TCCreateOverloads() { Attribute = new TestCase() { Name = "Create Overloads", Desc = "Create Overloads" } });
}
[Fact]
[OuterLoop]
- static public void TCFilterSettings()
+ public static void TCFilterSettings()
{
RunTest(() => new TCFilterSettings() { Attribute = new TestCase() { Name = "Filter Settings", Desc = "Filter Settings" } });
}
[Fact]
[OuterLoop]
- static public void TCLineInfo()
+ public static void TCLineInfo()
{
RunTest(() => new TCLineInfo() { Attribute = new TestCase() { Name = "LineInfo", Desc = "LineInfo" } });
}
[Fact]
[OuterLoop]
- static public void TCMaxSettings()
+ public static void TCMaxSettings()
{
RunTest(() => new TCMaxSettings() { Attribute = new TestCase() { Name = "MaxCharacters Settings", Desc = "MaxCharacters Settings" } });
}
[Fact]
[OuterLoop]
- static public void TCReaderSettingsGenericTestsCharCheckingReader()
+ public static void TCReaderSettingsGenericTestsCharCheckingReader()
{
RunTest(() => new TCReaderSettings() { Attribute = new TestCase() { Name = "ReaderSettings Generic Tests.CharCheckingReader", Param = "CharCheckingReader" } });
}
[Fact]
[OuterLoop]
- static public void TCReaderSettingsGenericTestsSubtreeReader()
+ public static void TCReaderSettingsGenericTestsSubtreeReader()
{
RunTest(() => new TCReaderSettings() { Attribute = new TestCase() { Name = "ReaderSettings Generic Tests.SubtreeReader", Param = "SubtreeReader" } });
}
[Fact]
[OuterLoop]
- static public void TCReaderSettingsGenericTestsCoreReader()
+ public static void TCReaderSettingsGenericTestsCoreReader()
{
RunTest(() => new TCReaderSettings() { Attribute = new TestCase() { Name = "ReaderSettings Generic Tests.CoreReader", Param = "CoreReader" } });
}
[Fact]
[OuterLoop]
- static public void TCReaderSettingsGenericTestsWrappedReader()
+ public static void TCReaderSettingsGenericTestsWrappedReader()
{
RunTest(() => new TCReaderSettings() { Attribute = new TestCase() { Name = "ReaderSettings Generic Tests.WrappedReader", Param = "WrappedReader" } });
}
[Fact]
[OuterLoop]
- static public void TCCloseInputWrappedReader()
+ public static void TCCloseInputWrappedReader()
{
RunTest(() => new TCCloseInput() { Attribute = new TestCase() { Name = "CloseInput.WrappedReader", Param = "WrappedReader" } });
}
[Fact]
[OuterLoop]
- static public void TCCloseInputCharCheckingReader()
+ public static void TCCloseInputCharCheckingReader()
{
RunTest(() => new TCCloseInput() { Attribute = new TestCase() { Name = "CloseInput.CharCheckingReader", Param = "CharCheckingReader" } });
}
[Fact]
[OuterLoop]
- static public void TCCloseInputCoreReader()
+ public static void TCCloseInputCoreReader()
{
RunTest(() => new TCCloseInput() { Attribute = new TestCase() { Name = "CloseInput.CoreReader", Param = "CoreReader" } });
}
[Fact]
[OuterLoop]
- static public void TCCloseInputSubtreeReader()
+ public static void TCCloseInputSubtreeReader()
{
RunTest(() => new TCCloseInput() { Attribute = new TestCase() { Name = "CloseInput.SubtreeReader", Param = "SubtreeReader" } });
}
[Fact]
[OuterLoop]
- static public void TCRSGenericCharCheckingReader()
+ public static void TCRSGenericCharCheckingReader()
{
RunTest(() => new TCRSGeneric() { Attribute = new TestCase() { Name = "ReaderSettings Generic Tests.CharCheckingReader", Param = "CharCheckingReader" } });
}
[Fact]
[OuterLoop]
- static public void TCRSGenericCoreReader()
+ public static void TCRSGenericCoreReader()
{
RunTest(() => new TCRSGeneric() { Attribute = new TestCase() { Name = "ReaderSettings Generic Tests.CoreReader", Param = "CoreReader" } });
}
[Fact]
[OuterLoop]
- static public void TCRSGenericWrappedReader()
+ public static void TCRSGenericWrappedReader()
{
RunTest(() => new TCRSGeneric() { Attribute = new TestCase() { Name = "ReaderSettings Generic Tests.WrappedReader", Param = "WrappedReader" } });
}
[Fact]
[OuterLoop]
- static public void TCRSGenericSubtreeReader()
+ public static void TCRSGenericSubtreeReader()
{
RunTest(() => new TCRSGeneric() { Attribute = new TestCase() { Name = "ReaderSettings Generic Tests.SubtreeReader", Param = "SubtreeReader" } });
}
[Fact]
[OuterLoop]
- static public void TCDtdProcessingCoreReaderCharCheckingReader()
+ public static void TCDtdProcessingCoreReaderCharCheckingReader()
{
RunTest(() => new TCDtdProcessingCoreReader() { Attribute = new TestCase() { Name = "TCDtdProcessingCoreReader.CharCheckingReader", Param = "CharCheckingReader" } });
}
[Fact]
[OuterLoop]
- static public void TCDtdProcessingCoreReaderCoreReader()
+ public static void TCDtdProcessingCoreReaderCoreReader()
{
RunTest(() => new TCDtdProcessingCoreReader() { Attribute = new TestCase() { Name = "TCDtdProcessingCoreReader.CoreReader", Param = "CoreReader" } });
}
[Fact]
[OuterLoop]
- static public void TCDtdProcessingCoreReaderWrappedReader()
+ public static void TCDtdProcessingCoreReaderWrappedReader()
{
RunTest(() => new TCDtdProcessingCoreReader() { Attribute = new TestCase() { Name = "TCDtdProcessingCoreReader.WrappedReader", Param = "WrappedReader" } });
}
[Fact]
[OuterLoop]
- static public void TCDtdProcessingCoreReaderSubtreeReader()
+ public static void TCDtdProcessingCoreReaderSubtreeReader()
{
RunTest(() => new TCDtdProcessingCoreReader() { Attribute = new TestCase() { Name = "TCDtdProcessingCoreReader.SubtreeReader", Param = "SubtreeReader" } });
}
[Fact]
[OuterLoop]
- static public void TCOneByteStreamCharCheckingReader()
+ public static void TCOneByteStreamCharCheckingReader()
{
RunTest(() => new TCOneByteStream() { Attribute = new TestCase() { Name = "Read xml as one byte stream.CharCheckingReader", Param = "CharCheckingReader" } });
}
[Fact]
[OuterLoop]
- static public void TCOneByteStreamSubtreeReader()
+ public static void TCOneByteStreamSubtreeReader()
{
RunTest(() => new TCOneByteStream() { Attribute = new TestCase() { Name = "Read xml as one byte stream.SubtreeReader", Param = "SubtreeReader" } });
}
[Fact]
[OuterLoop]
- static public void TCOneByteStreamCoreReader()
+ public static void TCOneByteStreamCoreReader()
{
RunTest(() => new TCOneByteStream() { Attribute = new TestCase() { Name = "Read xml as one byte stream.CoreReader", Param = "CoreReader" } });
}
[Fact]
[OuterLoop]
- static public void TCOneByteStreamWrappedReader()
+ public static void TCOneByteStreamWrappedReader()
{
RunTest(() => new TCOneByteStream() { Attribute = new TestCase() { Name = "Read xml as one byte stream.WrappedReader", Param = "WrappedReader" } });
}
diff --git a/src/System.Private.Xml/tests/Readers/ReaderSettings/MaxSettings.cs b/src/System.Private.Xml/tests/Readers/ReaderSettings/MaxSettings.cs
index a952bc5bab..f3813be69c 100644
--- a/src/System.Private.Xml/tests/Readers/ReaderSettings/MaxSettings.cs
+++ b/src/System.Private.Xml/tests/Readers/ReaderSettings/MaxSettings.cs
@@ -341,7 +341,7 @@ namespace System.Xml.Tests
//[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = bigVal, MaxDoc = bigVal", Params = new object[] { "" })]
//[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = bigVal, MaxDoc = bigVal", Params = new object[] { "<?xml version='1.0'?><!DOCTYPE test [ <!ELEMENT test ANY> <!ELEMENT a ANY> <!ELEMENT b ANY> <!ELEMENT c ANY> <!ENTITY a '<a>&amp;</a>'>]><test>&a;<test>" })]
//[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = bigVal, MaxDoc = bigVal", Params = new object[] { "<q = 'a'/>" })]
- //[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = bigVal, MaxDoc = bigVal", Params = new object[] { "<!-- http://www.w3.org is bound to n1 and n2 -->\r\n<x xmlns:n1=\"http://www.w3.org\"\r\n xmlns:n2=\"http://www.w3.org\" >\r\n <bad n1:a=\"1\" n2:a=\"2\" /></x>" })]
+ //[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = bigVal, MaxDoc = bigVal", Params = new object[] { string.Format("<!-- http://www.w3.org is bound to n1 and n2 -->{0}<x xmlns:n1=\"http://www.w3.org\"{0} xmlns:n2=\"http://www.w3.org\" >{0} <bad n1:a=\"1\" n2:a=\"2\" /></x>", Environment.NewLine) })]
//[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = bigVal, MaxDoc = bigVal", Params = new object[] { "<root><!--comment \uD812><!--comment \uD812>-->--></root>" })]
public int v260()
{
@@ -371,7 +371,7 @@ namespace System.Xml.Tests
//[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = 1, MaxDoc = val", Params = new object[] { "<?xml version='1.0'?><!DOCTYPE test [ <!ELEMENT test ANY> <!ELEMENT a ANY> <!ELEMENT b ANY> <!ELEMENT c ANY> <!ENTITY a '<a>&a;</a>'>]><test>&a;</test>", 25 })]
//[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = 1, MaxDoc = val", Params = new object[] { "<?xml version='1.0'?><!DOCTYPE test [ <!ELEMENT test ANY> <!ELEMENT a ANY> <!ELEMENT b ANY> <!ELEMENT c ANY> <!ENTITY a '<a>&amp;</a>'>]><test>&a;<test>", 26 })]
//[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = 1, MaxDoc = val", Params = new object[] { "<q = 'a'/>", 5 })]
- //[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = 1, MaxDoc = val", Params = new object[] { "<!-- http://www.w3.org is bound to n1 and n2 -->\r\n<x xmlns:n1=\"http://www.w3.org\"\r\n xmlns:n2=\"http://www.w3.org\" >\r\n <bad n1:a=\"1\" n2:a=\"2\" /></x>", 35 })]
+ //[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = 1, MaxDoc = val", Params = new object[] { string.Format("<!-- http://www.w3.org is bound to n1 and n2 -->{0}<x xmlns:n1=\"http://www.w3.org\"{0} xmlns:n2=\"http://www.w3.org\" >{0} <bad n1:a=\"1\" n2:a=\"2\" /></x>", Environment.NewLine), 35 })]
//[Variation(Pri = 2, Desc = "nwf xml: MaxEnt = 1, MaxDoc = val", Params = new object[] { "<root><!--comment \uD812><!--comment \uD812>-->--></root>", 18 })]
public int v270()
{
diff --git a/src/System.Private.Xml/tests/Readers/ReaderSettings/TCMaxSettings.cs b/src/System.Private.Xml/tests/Readers/ReaderSettings/TCMaxSettings.cs
index 7bf0c5117e..5491a9b14b 100644
--- a/src/System.Private.Xml/tests/Readers/ReaderSettings/TCMaxSettings.cs
+++ b/src/System.Private.Xml/tests/Readers/ReaderSettings/TCMaxSettings.cs
@@ -157,7 +157,7 @@ namespace System.Xml.Tests
{
this.AddChild(new CVariation(v260) { Attribute = new Variation("nwf xml: MaxEnt = bigVal, MaxDoc = bigVal") { Params = new object[] { "" }, Pri = 2 } });
this.AddChild(new CVariation(v260) { Attribute = new Variation("nwf xml: MaxEnt = bigVal, MaxDoc = bigVal") { Params = new object[] { "<root><!--comment \ufffd\ufffd><!--comment \ufffd\ufffd>-->--></root>" }, Pri = 2 } });
- this.AddChild(new CVariation(v260) { Attribute = new Variation("nwf xml: MaxEnt = bigVal, MaxDoc = bigVal") { Params = new object[] { "<!-- http://www.w3.org is bound to n1 and n2 -->\r\n<x xmlns:n1=\"http://www.w3.org\"\r\n xmlns:n2=\"http://www.w3.org\" >\r\n <bad n1:a=\"1\" n2:a=\"2\" /></x>" }, Pri = 2 } });
+ this.AddChild(new CVariation(v260) { Attribute = new Variation("nwf xml: MaxEnt = bigVal, MaxDoc = bigVal") { Params = new object[] { string.Format("<!-- http://www.w3.org is bound to n1 and n2 -->{0}<x xmlns:n1=\"http://www.w3.org\"{0} xmlns:n2=\"http://www.w3.org\" >{0} <bad n1:a=\"1\" n2:a=\"2\" /></x>", Environment.NewLine) }, Pri = 2 } });
this.AddChild(new CVariation(v260) { Attribute = new Variation("nwf xml: MaxEnt = bigVal, MaxDoc = bigVal") { Params = new object[] { "<!DOCTYPE ROOT [<!ENTITY a '&a;'>]><ROOT att='&a;'/>" }, Pri = 2 } });
this.AddChild(new CVariation(v260) { Attribute = new Variation("nwf xml: MaxEnt = bigVal, MaxDoc = bigVal") { Params = new object[] { "<?xml version='1.0'?><!DOCTYPE test [ <!ELEMENT test ANY> <!ELEMENT a ANY> <!ELEMENT b ANY> <!ELEMENT c ANY> <!ENTITY a '<a>&a;</a>'>]><test>&a;</test>" }, Pri = 2 } });
this.AddChild(new CVariation(v260) { Attribute = new Variation("nwf xml: MaxEnt = bigVal, MaxDoc = bigVal") { Params = new object[] { "<?xml version='1.0'?><!DOCTYPE test [ <!ELEMENT test ANY> <!ELEMENT a ANY> <!ELEMENT b ANY> <!ELEMENT c ANY> <!ENTITY a '<a>&amp;</a>'>]><test>&a;<test>" }, Pri = 2 } });
@@ -172,7 +172,7 @@ namespace System.Xml.Tests
this.AddChild(new CVariation(v270) { Attribute = new Variation("nwf xml: MaxEnt = 1, MaxDoc = val") { Params = new object[] { "<?xml version='1.0'?><!DOCTYPE test [ <!ELEMENT test ANY> <!ELEMENT a ANY> <!ELEMENT b ANY> <!ELEMENT c ANY> <!ENTITY a '<a>&a;</a>'>]><test>&a;</test>", 25 }, Pri = 2 } });
this.AddChild(new CVariation(v270) { Attribute = new Variation("nwf xml: MaxEnt = 1, MaxDoc = val") { Params = new object[] { "<?xml version='1.0'?><!DOCTYPE test [ <!ELEMENT test ANY> <!ELEMENT a ANY> <!ELEMENT b ANY> <!ELEMENT c ANY> <!ENTITY a '<a>&amp;</a>'>]><test>&a;<test>", 26 }, Pri = 2 } });
this.AddChild(new CVariation(v270) { Attribute = new Variation("nwf xml: MaxEnt = 1, MaxDoc = val") { Params = new object[] { "<root><!--comment \ufffd\ufffd><!--comment \ufffd\ufffd>-->--></root>", 18 }, Pri = 2 } });
- this.AddChild(new CVariation(v270) { Attribute = new Variation("nwf xml: MaxEnt = 1, MaxDoc = val") { Params = new object[] { "<!-- http://www.w3.org is bound to n1 and n2 -->\r\n<x xmlns:n1=\"http://www.w3.org\"\r\n xmlns:n2=\"http://www.w3.org\" >\r\n <bad n1:a=\"1\" n2:a=\"2\" /></x>", 35 }, Pri = 2 } });
+ this.AddChild(new CVariation(v270) { Attribute = new Variation("nwf xml: MaxEnt = 1, MaxDoc = val") { Params = new object[] { string.Format("<!-- http://www.w3.org is bound to n1 and n2 -->{0}<x xmlns:n1=\"http://www.w3.org\"{0} xmlns:n2=\"http://www.w3.org\" >{0} <bad n1:a=\"1\" n2:a=\"2\" /></x>", Environment.NewLine), 35 }, Pri = 2 } });
}
}
}
diff --git a/src/System.Private.Xml/tests/System.Private.Xml.Tests.builds b/src/System.Private.Xml/tests/System.Private.Xml.Tests.builds
index 59c966ac5a..06b5cf7ebe 100644
--- a/src/System.Private.Xml/tests/System.Private.Xml.Tests.builds
+++ b/src/System.Private.Xml/tests/System.Private.Xml.Tests.builds
@@ -80,6 +80,7 @@
<Project Include="XmlSchema\XmlSchemaSet\System.Xml.XmlSchemaSet.Tests.csproj" />
<Project Include="XmlSchema\XmlSchemaValidatorApi\System.Xml.XmlSchema.XmlSchemaValidatorApi.Tests.csproj" />
<Project Include="XmlSerializer\System.Xml.XmlSerializer.Tests.csproj" />
+ <Project Include="XmlSerializer\ReflectionOnly\System.Xml.XmlSerializer.ReflectionOnly.Tests.csproj" />
<Project Include="XmlWriter\System.Xml.RW.XmlWriter.Tests.csproj" />
<Project Include="XmlWriter\System.Xml.RW.XmlWriter.Tests.csproj">
<TargetGroup>netstandard1.3</TargetGroup>
diff --git a/src/System.Private.Xml/tests/Writers/RwFactory/CFactoryModule.cs b/src/System.Private.Xml/tests/Writers/RwFactory/CFactoryModule.cs
index 5a39d7daf6..bca2f5dd09 100644
--- a/src/System.Private.Xml/tests/Writers/RwFactory/CFactoryModule.cs
+++ b/src/System.Private.Xml/tests/Writers/RwFactory/CFactoryModule.cs
@@ -11,7 +11,7 @@ namespace System.Xml.Tests
{
[Fact]
[OuterLoop]
- static public void RunTests()
+ public static void RunTests()
{
CModInfo.CommandLine = "";
var module = new CFactoryModule();
@@ -22,7 +22,7 @@ namespace System.Xml.Tests
[Fact]
[OuterLoop]
- static public void RunTestsAsync()
+ public static void RunTestsAsync()
{
CModInfo.CommandLine = "/async";
var module = new CFactoryModule();
diff --git a/src/System.Private.Xml/tests/Writers/XmlWriterApi/CommonTests.cs b/src/System.Private.Xml/tests/Writers/XmlWriterApi/CommonTests.cs
index f1450cdf06..5af60d75fa 100644
--- a/src/System.Private.Xml/tests/Writers/XmlWriterApi/CommonTests.cs
+++ b/src/System.Private.Xml/tests/Writers/XmlWriterApi/CommonTests.cs
@@ -7108,6 +7108,7 @@ namespace System.Xml.Tests
Type dest = typeMapper[destStr];
bool isValid = (bool)CurVariation.Params[3];
object expVal = (object)CurVariation.Params[4];
+ CultureInfo origCulture = null;
if (expVal == null && destStr.Contains("DateTime"))
expVal = value[destStr];
@@ -7129,6 +7130,8 @@ namespace System.Xml.Tests
}
try
{
+ origCulture = CultureInfo.CurrentCulture;
+ CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; // So that the number format doesn't depend on the current culture
VerifyValue(dest, expVal, param);
}
catch (XmlException)
@@ -7156,6 +7159,10 @@ namespace System.Xml.Tests
if (!isValid) return TEST_PASS;
CError.Compare(false, "ArgumentException");
}
+ finally
+ {
+ CultureInfo.CurrentCulture = origCulture;
+ }
return (isValid) ? TEST_PASS : TEST_FAIL;
}
diff --git a/src/System.Private.Xml/tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs b/src/System.Private.Xml/tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs
index 7a64dbaf7e..a838849fa3 100644
--- a/src/System.Private.Xml/tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs
+++ b/src/System.Private.Xml/tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs
@@ -100,7 +100,7 @@ namespace System.Xml.Tests
{
output = output.Replace("\r\n", "\n");
output = output.Replace("\r", "\n");
- output = output.Replace("\n", "\r\n");
+ output = output.Replace("\n", nl);
}
else
{
@@ -417,7 +417,7 @@ namespace System.Xml.Tests
wSettings.Indent = true;
XmlWriter w = CreateMemWriter(wSettings);
- CError.Compare(w.Settings.NewLineChars, "\r\n", "Incorect default value for XmlWriter.Settings.NewLineChars");
+ CError.Compare(w.Settings.NewLineChars, nl, "Incorect default value for XmlWriter.Settings.NewLineChars");
CError.Compare(w.Settings.IndentChars, " ", "Incorect default value for XmlWriter.Settings.IndentChars");
w.WriteStartElement("root");
@@ -427,7 +427,7 @@ namespace System.Xml.Tests
w.WriteEndElement();
w.Dispose();
- VerifyOutput("<root>\r\n <foo>\r\n <bar />\r\n </foo>\r\n</root>");
+ VerifyOutput(string.Format("<root>{0} <foo>{0} <bar />{0} </foo>{0}</root>", nl));
return TEST_PASS;
}
diff --git a/src/System.Private.Xml/tests/Writers/XmlWriterApi/TCFullEndElement.cs b/src/System.Private.Xml/tests/Writers/XmlWriterApi/TCFullEndElement.cs
index 338cf6478d..54a180c6eb 100644
--- a/src/System.Private.Xml/tests/Writers/XmlWriterApi/TCFullEndElement.cs
+++ b/src/System.Private.Xml/tests/Writers/XmlWriterApi/TCFullEndElement.cs
@@ -640,8 +640,8 @@ namespace System.Xml.Tests
// for function CData_13
{
this.AddChild(new CVariation(CData_13) { Attribute = new Variation("WriteCData with 0x0A with NewLineHandling.Entitize") { Params = new object[] { 10, NewLineHandling.Entitize, "<r><![CDATA[\n]]></r>" }, id = 18, Pri = 1 } });
- this.AddChild(new CVariation(CData_13) { Attribute = new Variation("WriteCData with 0x0D with NewLineHandling.Replace") { Params = new object[] { 13, NewLineHandling.Replace, "<r><![CDATA[\r\n]]></r>" }, id = 13, Pri = 1 } });
- this.AddChild(new CVariation(CData_13) { Attribute = new Variation("WriteCData with 0x0A with NewLineHandling.Replace") { Params = new object[] { 10, NewLineHandling.Replace, "<r><![CDATA[\r\n]]></r>" }, id = 16, Pri = 1 } });
+ this.AddChild(new CVariation(CData_13) { Attribute = new Variation("WriteCData with 0x0D with NewLineHandling.Replace") { Params = new object[] { 13, NewLineHandling.Replace, string.Format("<r><![CDATA[{0}]]></r>", Environment.NewLine) }, id = 13, Pri = 1 } });
+ this.AddChild(new CVariation(CData_13) { Attribute = new Variation("WriteCData with 0x0A with NewLineHandling.Replace") { Params = new object[] { 10, NewLineHandling.Replace, string.Format("<r><![CDATA[{0}]]></r>", Environment.NewLine) }, id = 16, Pri = 1 } });
this.AddChild(new CVariation(CData_13) { Attribute = new Variation("WriteCData with 0x0A with NewLineHandling.None") { Params = new object[] { 10, NewLineHandling.None, "<r><![CDATA[\n]]></r>" }, id = 17, Pri = 1 } });
this.AddChild(new CVariation(CData_13) { Attribute = new Variation("WriteCData with 0x0D with NewLineHandling.Entitize") { Params = new object[] { 13, NewLineHandling.Entitize, "<r><![CDATA[\r]]></r>" }, id = 15, Pri = 1 } });
this.AddChild(new CVariation(CData_13) { Attribute = new Variation("WriteCData with 0x0D with NewLineHandling.None") { Params = new object[] { 13, NewLineHandling.None, "<r><![CDATA[\r]]></r>" }, id = 14, Pri = 1 } });
diff --git a/src/System.Private.Xml/tests/Writers/XmlWriterApi/TCXmlWriterTestModule.cs b/src/System.Private.Xml/tests/Writers/XmlWriterApi/TCXmlWriterTestModule.cs
index 3d3299e76a..128b0a0154 100644
--- a/src/System.Private.Xml/tests/Writers/XmlWriterApi/TCXmlWriterTestModule.cs
+++ b/src/System.Private.Xml/tests/Writers/XmlWriterApi/TCXmlWriterTestModule.cs
@@ -34,205 +34,203 @@ namespace System.Xml.Tests
[Fact]
[OuterLoop]
- static public void TCErrorState()
+ public static void TCErrorState()
{
RunTest(() => new TCErrorState() { Attribute = new TestCase() { Name = "Invalid State Combinations" } });
}
[Fact]
[OuterLoop]
- static public void TCAutoComplete()
+ public static void TCAutoComplete()
{
RunTest(() => new TCAutoComplete() { Attribute = new TestCase() { Name = "Auto-completion of tokens" } });
}
[Fact]
[OuterLoop]
- static public void TCDocument()
+ public static void TCDocument()
{
RunTest(() => new TCDocument() { Attribute = new TestCase() { Name = "WriteStart/EndDocument" } });
}
[Fact]
[OuterLoop]
- static public void TCDocType()
+ public static void TCDocType()
{
RunTest(() => new TCDocType() { Attribute = new TestCase() { Name = "WriteDocType" } });
}
[Fact]
[OuterLoop]
- static public void TCElement()
+ public static void TCElement()
{
RunTest(() => new TCElement() { Attribute = new TestCase() { Name = "WriteStart/EndElement" } });
}
[Fact]
[OuterLoop]
- static public void TCAttribute()
+ public static void TCAttribute()
{
RunTest(() => new TCAttribute() { Attribute = new TestCase() { Name = "WriteStart/EndAttribute" } });
}
[Fact]
[OuterLoop]
- static public void TCWriteAttributes()
+ public static void TCWriteAttributes()
{
RunTest(() => new TCWriteAttributes() { Attribute = new TestCase() { Name = "WriteAttributes(CoreReader)", Param = "COREREADER" } });
}
[Fact]
[OuterLoop]
- static public void TCWriteNode_XmlReader()
+ public static void TCWriteNode_XmlReader()
{
RunTest(() => new TCWriteNode_XmlReader() { Attribute = new TestCase() { Name = "WriteNode(CoreReader)", Param = "COREREADER" } });
}
[Fact]
[OuterLoop]
- static public void TCWriteNode_With_ReadValueChunk()
+ public static void TCWriteNode_With_ReadValueChunk()
{
RunTest(() => new TCWriteNode_With_ReadValueChunk() { Attribute = new TestCase() { Name = "WriteNode with streaming API ReadValueChunk - COREREADER", Param = "COREREADER" } });
}
[Fact]
[OuterLoop]
- [ActiveIssue(1491)]
- static public void TCFullEndElement()
+ public static void TCFullEndElement()
{
RunTest(() => new TCFullEndElement() { Attribute = new TestCase() { Name = "WriteFullEndElement" } });
}
[Fact]
[OuterLoop]
- [ActiveIssue(6331)]
- static public void TCEOFHandling()
+ public static void TCEOFHandling()
{
RunTest(() => new TCEOFHandling() { Attribute = new TestCase() { Name = "XmlWriterSettings: NewLineHandling" } });
}
[Fact]
[OuterLoop]
- static public void TCErrorConditionWriter()
+ public static void TCErrorConditionWriter()
{
RunTest(() => new TCErrorConditionWriter() { Attribute = new TestCase() { Name = "ErrorCondition" } });
}
[Fact]
[OuterLoop]
- static public void TCNamespaceHandling()
+ public static void TCNamespaceHandling()
{
RunTest(() => new TCNamespaceHandling() { Attribute = new TestCase() { Name = "XmlWriterSettings: NamespaceHandling" } });
}
[Fact]
[OuterLoop]
- static public void TCDefaultWriterSettings()
+ public static void TCDefaultWriterSettings()
{
RunTest(() => new TCDefaultWriterSettings() { Attribute = new TestCase() { Name = "XmlWriterSettings: Default Values" } });
}
[Fact]
[OuterLoop]
- static public void TCWriterSettingsMisc()
+ public static void TCWriterSettingsMisc()
{
RunTest(() => new TCWriterSettingsMisc() { Attribute = new TestCase() { Name = "XmlWriterSettings: Reset/Clone" } });
}
[Fact]
[OuterLoop]
- static public void TCOmitXmlDecl()
+ public static void TCOmitXmlDecl()
{
RunTest(() => new TCOmitXmlDecl() { Attribute = new TestCase() { Name = "XmlWriterSettings: OmitXmlDeclaration" } });
}
[Fact]
[OuterLoop]
- static public void TCCheckChars()
+ public static void TCCheckChars()
{
RunTest(() => new TCCheckChars() { Attribute = new TestCase() { Name = "XmlWriterSettings: CheckCharacters" } });
}
[Fact]
[OuterLoop]
- static public void TCNewLineHandling()
+ public static void TCNewLineHandling()
{
RunTest(() => new TCNewLineHandling() { Attribute = new TestCase() { Name = "XmlWriterSettings: NewLineHandling" } });
}
[Fact]
[OuterLoop]
- static public void TCNewLineChars()
+ public static void TCNewLineChars()
{
RunTest(() => new TCNewLineChars() { Attribute = new TestCase() { Name = "XmlWriterSettings: NewLineChars" } });
}
[Fact]
[OuterLoop]
- static public void TCIndent()
+ public static void TCIndent()
{
RunTest(() => new TCIndent() { Attribute = new TestCase() { Name = "XmlWriterSettings: Indent" } });
}
[Fact]
[OuterLoop]
- static public void TCIndentChars()
+ public static void TCIndentChars()
{
RunTest(() => new TCIndentChars() { Attribute = new TestCase() { Name = "XmlWriterSettings: IndentChars" } });
}
[Fact]
[OuterLoop]
- static public void TCNewLineOnAttributes()
+ public static void TCNewLineOnAttributes()
{
RunTest(() => new TCNewLineOnAttributes() { Attribute = new TestCase() { Name = "XmlWriterSettings: NewLineOnAttributes" } });
}
[Fact]
[OuterLoop]
- static public void TCStandAlone()
+ public static void TCStandAlone()
{
RunTest(() => new TCStandAlone() { Attribute = new TestCase() { Name = "Standalone" } });
}
[Fact]
[OuterLoop]
- static public void TCCloseOutput()
+ public static void TCCloseOutput()
{
RunTest(() => new TCCloseOutput() { Attribute = new TestCase() { Name = "XmlWriterSettings: CloseOutput" } });
}
[Fact]
[OuterLoop]
- static public void TCFragmentCL()
+ public static void TCFragmentCL()
{
RunTest(() => new TCFragmentCL() { Attribute = new TestCase() { Name = "CL = Fragment Tests" } });
}
[Fact]
[OuterLoop]
- static public void TCAutoCL()
+ public static void TCAutoCL()
{
RunTest(() => new TCAutoCL() { Attribute = new TestCase() { Name = "CL = Auto Tests" } });
}
[Fact]
[OuterLoop]
- static public void TCFlushClose()
+ public static void TCFlushClose()
{
RunTest(() => new TCFlushClose() { Attribute = new TestCase() { Name = "Close()/Flush()" } });
}
[Fact]
[OuterLoop]
- static public void TCWriterWithMemoryStream()
+ public static void TCWriterWithMemoryStream()
{
RunTest(() => new TCWriterWithMemoryStream() { Attribute = new TestCase() { Name = "XmlWriter with MemoryStream" } });
}
[Fact]
[OuterLoop]
- static public void TCWriteEndDocumentOnCloseTest()
+ public static void TCWriteEndDocumentOnCloseTest()
{
RunTest(() => new TCWriteEndDocumentOnCloseTest() { Attribute = new TestCase() { Name = "XmlWriterSettings: WriteEndDocumentOnClose" } });
}
diff --git a/src/System.Private.Xml/tests/XPath/XPathDocument/XmlReaderXPathTest.cs b/src/System.Private.Xml/tests/XPath/XPathDocument/XmlReaderXPathTest.cs
index 880009d293..5ad8e5257c 100644
--- a/src/System.Private.Xml/tests/XPath/XPathDocument/XmlReaderXPathTest.cs
+++ b/src/System.Private.Xml/tests/XPath/XPathDocument/XmlReaderXPathTest.cs
@@ -8,7 +8,7 @@ namespace XPathTests.Common
{
public static partial class Utils
{
- private readonly static ICreateNavigator _navigatorCreator = new CreateNavigatorFromXmlReader();
- public readonly static string ResourceFilesPath = "System.Xml.XPath.Tests.TestData.";
+ private static readonly ICreateNavigator _navigatorCreator = new CreateNavigatorFromXmlReader();
+ public static readonly string ResourceFilesPath = "System.Xml.XPath.Tests.TestData.";
}
}
diff --git a/src/System.Private.Xml/tests/XPath/XmlDocument/XmlDocumentXPathTest.cs b/src/System.Private.Xml/tests/XPath/XmlDocument/XmlDocumentXPathTest.cs
index 856f880790..5528cfbc57 100644
--- a/src/System.Private.Xml/tests/XPath/XmlDocument/XmlDocumentXPathTest.cs
+++ b/src/System.Private.Xml/tests/XPath/XmlDocument/XmlDocumentXPathTest.cs
@@ -8,7 +8,7 @@ namespace XPathTests.Common
{
public static partial class Utils
{
- private readonly static ICreateNavigator _navigatorCreator = new CreateNavigatorFromXmlDocument();
- public readonly static string ResourceFilesPath = "System.Xml.XPath.XmlDocument.Tests.TestData.";
+ private static readonly ICreateNavigator _navigatorCreator = new CreateNavigatorFromXmlDocument();
+ public static readonly string ResourceFilesPath = "System.Xml.XPath.XmlDocument.Tests.TestData.";
}
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/TestFiles/TestData/xmlresolver_v4.xsd b/src/System.Private.Xml/tests/XmlSchema/TestFiles/TestData/xmlresolver_v4.xsd
new file mode 100644
index 0000000000..6a0bb85743
--- /dev/null
+++ b/src/System.Private.Xml/tests/XmlSchema/TestFiles/TestData/xmlresolver_v4.xsd
@@ -0,0 +1,22 @@
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="foo" xmlns="foo">
+
+ <xsd:import schemaLocation="include_v1_b.xsd"/>
+
+ <xsd:complexType name="ct-A">
+ <xsd:sequence minOccurs="1">
+ <xsd:element name="a1" type="xsd:int" />
+ <xsd:element name="a2" type="xsd:boolean" />
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="e1" type="ct-A" />
+
+ <xsd:element name="root">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:any namespace="##any" processContents="strict"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/XmlSchema/TestFiles/TestData/xmlresolver_v5.xsd b/src/System.Private.Xml/tests/XmlSchema/TestFiles/TestData/xmlresolver_v5.xsd
new file mode 100644
index 0000000000..7d2073f9e5
--- /dev/null
+++ b/src/System.Private.Xml/tests/XmlSchema/TestFiles/TestData/xmlresolver_v5.xsd
@@ -0,0 +1,3 @@
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <xsd:import namespace="foo" schemaLocation="xmlresolver_v4.xsd"/>
+</xsd:schema> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/CError.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/CError.cs
index bc9b8e7082..8b4df2d1be 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/CError.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/CError.cs
@@ -13,19 +13,19 @@ namespace System.Xml.Tests
{
public static class CError
{
- static public bool Compare(bool equal, string message)
+ public static bool Compare(bool equal, string message)
{
Assert.True(equal, message);
return true;
}
- static public bool Compare(object actual, object expected, string message)
+ public static bool Compare(object actual, object expected, string message)
{
Assert.Equal(expected, actual);
return true;
}
- static public bool Compare(object actual, object expected1, object expected2, string message)
+ public static bool Compare(object actual, object expected1, object expected2, string message)
{
Assert.Equal(expected1, actual);
Assert.Equal(expected2, actual);
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet.cs
index 8e2b148718..535722bb6e 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet.cs
@@ -8,6 +8,11 @@ namespace System.Xml.Tests
{
public class TestData
{
+ static TestData()
+ {
+ AppContext.SetSwitch("TestSwitch.LocalAppContext.DisableCaching", true);
+ }
+
internal static string _Root = Path.Combine("TestFiles", "TestData");
internal static string StandardPath = Path.Combine("TestFiles", "StandardTests");
internal static string _FileXSD1 = Path.Combine(_Root, "schema1.xsd");
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Reader.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Reader.cs
index ba1a433c6d..f40cd2c248 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Reader.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Reader.cs
@@ -2,9 +2,7 @@
// 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.IO;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Schema.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Schema.cs
index 5fd721fe7f..5269343039 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Schema.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_Schema.cs
@@ -2,11 +2,8 @@
// 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.Collections.Generic;
using System.IO;
-using System.Net;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_SchemaSet.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_SchemaSet.cs
index 3c8a16ab2d..a69c1ab3f8 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_SchemaSet.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_SchemaSet.cs
@@ -2,7 +2,6 @@
// 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.IO;
using System.Xml.Schema;
using Xunit;
@@ -212,7 +211,6 @@ namespace System.Xml.Tests
schemaSet1.Add(schema1);
schemaSet1.Add(schema2); // added two schemas
- //schemaSet1.Compile ();
XmlSchemaElement elem = new XmlSchemaElement();
schema1.Items.Add(elem); // make the first schema dirty
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_URL.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_URL.cs
index d945eaaab2..a68abb57b4 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_URL.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Add_URL.cs
@@ -3,11 +3,7 @@
// See the LICENSE file in the project root for more information.
using Xunit;
-using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Net;
-using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_AllowXmlAttributes.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_AllowXmlAttributes.cs
index 6f6b96a35b..cbe994de71 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_AllowXmlAttributes.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_AllowXmlAttributes.cs
@@ -5,7 +5,6 @@
using Xunit;
using Xunit.Abstractions;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Compile.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Compile.cs
index dac2f1e660..1f03419d69 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Compile.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Compile.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Constructors.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Constructors.cs
index c27f4e4e93..9ca4f8ec4f 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Constructors.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Constructors.cs
@@ -4,8 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_ns.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_ns.cs
index 4d2bc3a06f..174f876518 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_ns.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_ns.cs
@@ -4,7 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_schema.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_schema.cs
index b2f9e3fcd4..56eb8cb8c2 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_schema.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Contains_schema.cs
@@ -4,7 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_CopyTo.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_CopyTo.cs
index 367d63bd18..2e66417dc6 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_CopyTo.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_CopyTo.cs
@@ -4,7 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.Collections;
using System.Xml.Schema;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_EnableUpaCheck.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_EnableUpaCheck.cs
index 7e0ab445b2..3a25722959 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_EnableUpaCheck.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_EnableUpaCheck.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalAttributes.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalAttributes.cs
index f57eaa5010..0b1b38577d 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalAttributes.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalAttributes.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalElements.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalElements.cs
index d3f172ce11..30c1baac94 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalElements.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalElements.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalTypes.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalTypes.cs
index ef5f93b07a..ff88bc46cc 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalTypes.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_GlobalTypes.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Imports.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Imports.cs
index 7a064fae22..8e39e341cd 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Imports.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Imports.cs
@@ -5,7 +5,6 @@
using Xunit;
using Xunit.Abstractions;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
@@ -41,8 +40,8 @@ namespace System.Xml.Tests
sc.Compile();
CError.Compare(sc.IsCompiled, true, "IsCompiled");
CError.Compare(sc.Count, param2, "Count");
- // check that schema is present in parent.Includes and its NS correct.
+ // check that schema is present in parent.Includes and its NS correct.
foreach (XmlSchemaImport imp in parent.Includes)
if (imp.SchemaLocation.Equals(param1.ToString()) && imp.Schema.TargetNamespace == (string)param3)
return;
@@ -104,6 +103,7 @@ namespace System.Xml.Tests
CError.Compare(sc.IsCompiled, true, "Add2IsCompiled");
CError.Compare(sc.Count, 2, "Add2Count");
CError.Compare(orig.SourceUri.Contains("import_v4_b.xsd"), true, "Compare the schema object");
+
// check that schema is present in parent.Includes and its NS correct.
foreach (XmlSchemaImport imp in parent.Includes)
if (imp.SchemaLocation.Equals("import_v4_b.xsd") && imp.Schema.TargetNamespace == null)
@@ -197,6 +197,7 @@ namespace System.Xml.Tests
if (imp.SchemaLocation.Equals("import_v9_b.xsd") && imp.Schema.TargetNamespace.Equals("ns-b"))
found = true;
if (!found) Assert.True(false);
+
// check that schema C in sch_b.Includes and its NS correct.
foreach (XmlSchemaImport imp in sch_B.Includes)
if (imp.SchemaLocation.Equals("import_v9_c.xsd") && imp.Schema.TargetNamespace.Equals("ns-c"))
@@ -1526,6 +1527,7 @@ namespace System.Xml.Tests
if (imp.SchemaLocation.Equals("import_v9_b.xsd") && imp.Schema.TargetNamespace.Equals("ns-b"))
found = true;
if (!found) Assert.True(false);
+
// check that schema C in sch_b.Includes and its NS correct.
foreach (XmlSchemaImport imp in sch_B.Includes)
if (imp.SchemaLocation.Equals("import_v9_c.xsd") && imp.Schema.TargetNamespace.Equals("ns-c"))
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Includes.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Includes.cs
index c5775bd1cd..e81dd8c38d 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Includes.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Includes.cs
@@ -4,7 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
using System.Xml.Schema;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Misc.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Misc.cs
index 82cba77fa2..f79b8153ee 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Misc.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Misc.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
@@ -1028,7 +1026,7 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "615444 XmlSchema.Write ((XmlWriter)null) throws InvalidOperationException instead of ArgumenNullException")]
- [Fact(Skip = "TODO: Fix NotImplementedException")]
+ [Fact]
public void v125()
{
XmlSchema xs = new XmlSchema();
@@ -1072,15 +1070,15 @@ namespace System.Xml.Tests
return;
}
- [Fact(Skip = "TODO: Fix NotImplementedException")]
+ [Fact]
public void GetBuiltinSimpleTypeWorksAsEcpected()
{
Initialize();
- string xml = "<?xml version=\"1.0\" encoding=\"utf-16\"?>" + "\r\n" +
- "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">" + "\r\n" +
- " <xs:simpleType>" + "\r\n" +
- " <xs:restriction base=\"xs:anySimpleType\" />" + "\r\n" +
- " </xs:simpleType>" + "\r\n" +
+ string xml = "<?xml version=\"1.0\" encoding=\"utf-16\"?>" + Environment.NewLine +
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">" + Environment.NewLine +
+ " <xs:simpleType>" + Environment.NewLine +
+ " <xs:restriction base=\"xs:anySimpleType\" />" + Environment.NewLine +
+ " </xs:simpleType>" + Environment.NewLine +
"</xs:schema>";
XmlSchema schema = new XmlSchema();
XmlSchemaSimpleType stringType = XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.String);
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ProhibitDTD.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ProhibitDTD.cs
index e663a73b01..47b2d96c45 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ProhibitDTD.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ProhibitDTD.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
@@ -184,7 +182,7 @@ namespace System.Xml.Tests
}
catch (XmlException)
{
- Assert.True(false); //exepect a validation warning for unresolvable schema location
+ Assert.True(false); //expect a validation warning for unresolvable schema location
}
CError.Compare(warningCount, 1, "Warning Count mismatch");
return;
@@ -206,7 +204,7 @@ namespace System.Xml.Tests
}
catch (XmlException)
{
- Assert.True(false); //exepect a validation warning for unresolvable schema location
+ Assert.True(false); //expect a validation warning for unresolvable schema location
}
CError.Compare(warningCount, 1, "Warning Count mismatch");
return;
@@ -232,7 +230,7 @@ namespace System.Xml.Tests
}
catch (XmlException)
{
- Assert.True(false); //exepect a validation warning for unresolvable schema location
+ Assert.True(false); //expect a validation warning for unresolvable schema location
}
CError.Compare(warningCount, (int)param1, "Warning Count mismatch");
CError.Compare(errorCount, 0, "Error Count mismatch");
@@ -258,7 +256,7 @@ namespace System.Xml.Tests
xss.Add(schema);
- // exepect a validation warning for unresolvable schema location
+ // expect a validation warning for unresolvable schema location
CError.Compare(warningCount, 0, "Warning Count mismatch");
CError.Compare(errorCount, 0, "Error Count mismatch");
return;
@@ -303,7 +301,7 @@ namespace System.Xml.Tests
}
catch (XmlException)
{
- Assert.True(false); //exepect a validation warning for unresolvable schema location
+ Assert.True(false); //expect a validation warning for unresolvable schema location
}
CError.Compare(warningCount, 0, "Warning Count mismatch");
@@ -405,7 +403,7 @@ namespace System.Xml.Tests
}
catch (XmlException)
{
- Assert.True(false); //exepect a validation warning for unresolvable schema location
+ Assert.True(false); //expect a validation warning for unresolvable schema location
}
_output.WriteLine("Count: " + xss.Count);
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Remove.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Remove.cs
index 7137bf1645..d031a24a88 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Remove.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Remove.cs
@@ -4,7 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
using System.Collections;
using System.Xml.Schema;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_RemoveRecursive.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_RemoveRecursive.cs
index 0d09f3130d..b4a2244ab5 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_RemoveRecursive.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_RemoveRecursive.cs
@@ -4,7 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
using System.Collections;
using System.Xml.Schema;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Reprocess.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Reprocess.cs
index 76a83b8993..b2f113a28e 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Reprocess.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_Reprocess.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ValidationEventHandler.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ValidationEventHandler.cs
index ae92af6b5f..20a349538b 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ValidationEventHandler.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_ValidationEventHandler.cs
@@ -5,7 +5,6 @@
using Xunit;
using Xunit.Abstractions;
using System.Collections;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlNameTable.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlNameTable.cs
index 8365e0cf8a..cfdda83410 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlNameTable.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlNameTable.cs
@@ -4,7 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlResolver.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlResolver.cs
index fc6e231b98..3e55d13d32 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlResolver.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaSet/TC_SchemaSet_XmlResolver.cs
@@ -5,7 +5,6 @@
using Xunit;
using Xunit.Abstractions;
using System.IO;
-using System.Net;
using System.Xml.Schema;
namespace System.Xml.Tests
@@ -94,56 +93,51 @@ namespace System.Xml.Tests
return;
}
- // TODO: Fix
- ////[Variation(Desc = "v4 - schema(Internet)->schema(Local)", Priority = 1)]
- //[InlineData()]
- //public int v4()
- //{
- // Initialize();
- // XmlSchemaSet sc = new XmlSchemaSet();
- // sc.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
- // sc.Add(null, FilePathUtil.GetHttpTestDataPath() + @"/XmlSchemaCollection/xmlresolver_v4.xsd");
- // CError.Compare(sc.Count, 2, "SchemaSet count");
- // CError.Compare(bWarningCallback, false, "Warning thrown");
- // return;
- //}
- //todo: add these tests for local
- ////[Variation(Desc = "v5 - schema(Intranet)->schema(Internet)->schema(Intranet)", Priority = 1)]
- //[InlineData()]
- //public int v5()
- //{
- // Initialize();
- // XmlSchemaSet sc = new XmlSchemaSet();
- // sc.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
- // sc.Add(null, TestData._Root + "xmlresolver_v5.xsd");
- // CError.Compare(sc.Count, 3, "SchemaSet count");
- // CError.Compare(bWarningCallback, false, "Warning not thrown");
- // return;
- //}
- ////[Variation(Desc = "v6 - schema(Intranet)->schema(Internet)->schema(Internet)", Priority = 1)]
- //[InlineData()]
- //public int v6()
- //{
- // Initialize();
- // XmlSchemaSet sc = new XmlSchemaSet();
- // sc.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
- // sc.Add(null, TestData._Root + "xmlresolver_v6_a.xsd");
- // CError.Compare(sc.Count, 3, "SchemaSet count");
- // CError.Compare(bWarningCallback, false, "Warning not thrown");
- // return;
- //}
- ////[Variation(Desc = "v7 - schema(Local)->schema(Internet)[->schema(Internet)][schema(Local)]", Priority = 1)]
- //[InlineData()]
- //public int v7()
- //{
- // Initialize();
- // XmlSchemaSet sc = new XmlSchemaSet();
- // sc.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
- // sc.Add(null, TestData._Root + "xmlresolver_v7_a.xsd");
- // CError.Compare(sc.Count, 3, "SchemaSet count");
- // CError.Compare(bWarningCallback, false, "Warning not thrown");
- // return;
- //}
+ //[Variation(Desc = "v4 - schema(Local)->schema(Local)", Priority = 1)]
+ [Fact]
+ public void v4()
+ {
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ Initialize();
+ XmlSchemaSet sc = new XmlSchemaSet();
+ sc.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
+ sc.Add(null, Path.Combine(TestData._Root, "xmlresolver_v4.xsd"));
+ CError.Compare(sc.Count, 2, "SchemaSet count");
+ CError.Compare(bWarningCallback, false, "Warning thrown");
+ return;
+ }
+
+ //[Variation(Desc = "v5 - schema(Local)->schema(Local)->schema(Local)", Priority = 1)]
+ [Fact]
+ public void v5()
+ {
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ Initialize();
+ XmlSchemaSet sc = new XmlSchemaSet();
+ sc.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
+ sc.Add(null, Path.Combine(TestData._Root, "xmlresolver_v5.xsd"));
+ CError.Compare(sc.Count, 3, "SchemaSet count");
+ CError.Compare(bWarningCallback, false, "Warning not thrown");
+ return;
+ }
+
+ //[Variation(Desc = "v6 - schema(Local)->schema(Local), but resolving external URI is not allowed", Priority = 1)]
+ [Fact]
+ public void v6()
+ {
+ // Make sure the switch has its default value
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", false);
+
+ Initialize();
+ XmlSchemaSet sc = new XmlSchemaSet();
+ sc.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
+ sc.Add(null, Path.Combine(TestData._Root, "xmlresolver_v4.xsd"));
+ CError.Compare(sc.Count, 1, "SchemaSet count");
+ CError.Compare(bWarningCallback, false, "Warning thrown");
+ return;
+ }
}
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CXmlTestResolver.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CXmlTestResolver.cs
index 1134d74657..de545b2f89 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CXmlTestResolver.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CXmlTestResolver.cs
@@ -2,11 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// ICredentials
-using System;
-using System.Net;
-using System.Xml;
-
namespace System.Xml.Tests
{
// CalledResolveUri Event Args
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Constructor_AddSchema.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Constructor_AddSchema.cs
index d3cb4eeeb3..eb2c7c01b2 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Constructor_AddSchema.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Constructor_AddSchema.cs
@@ -2,9 +2,7 @@
// 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.IO;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
@@ -122,7 +120,7 @@ namespace System.Xml.Tests
XmlSchemaInfo info = new XmlSchemaInfo();
XmlSchemaSet sch = new XmlSchemaSet();
- //sch.Add("", TestData + "Basic.xsd");
+
sch.Add("", XmlReader.Create(new StringReader("<?xml version=\"1.0\" ?>\n" +
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n" +
" <xs:element name=\"root\" type=\"xs:int\" />\n" +
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CustomImplementations.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CustomImplementations.cs
index 9302a67be2..e61ea67dcf 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CustomImplementations.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CustomImplementations.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
-using System.Xml;
using System.Xml.Schema;
namespace System.Xml.Tests
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ExceptionVerifier.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ExceptionVerifier.cs
new file mode 100644
index 0000000000..7de6f2d488
--- /dev/null
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ExceptionVerifier.cs
@@ -0,0 +1,399 @@
+// 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.Linq;
+using Xunit.Abstractions;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Resources;
+using System.Text.RegularExpressions;
+
+namespace System.Xml.Tests
+{
+ public class LineInfo
+ {
+ public int LineNumber { get; private set; }
+
+ public int LinePosition { get; private set; }
+
+ public string FilePath { get; private set; }
+
+ public LineInfo(int lineNum, int linePos)
+ {
+ LineNumber = lineNum;
+ LinePosition = linePos;
+ FilePath = String.Empty;
+ }
+
+ public LineInfo(int lineNum, int linePos, string filePath)
+ {
+ LineNumber = lineNum;
+ LinePosition = linePos;
+ FilePath = filePath;
+ }
+ }
+
+ [Flags]
+ public enum ExceptionVerificationFlags
+ {
+ None = 0,
+ IgnoreMultipleDots = 1,
+ IgnoreLineInfo = 2,
+ }
+
+ public class ExceptionVerifier
+ {
+ private readonly Assembly _asm;
+ private Assembly _locAsm;
+ private readonly Hashtable _resources;
+
+ private string _actualMessage;
+ private string _expectedMessage;
+ private Exception _ex;
+
+ private ExceptionVerificationFlags _verificationFlags = ExceptionVerificationFlags.None;
+
+ private ITestOutputHelper _output;
+
+ public bool IgnoreMultipleDots
+ {
+ get
+ {
+ return (_verificationFlags & ExceptionVerificationFlags.IgnoreMultipleDots) != 0;
+ }
+ set
+ {
+ if (value)
+ _verificationFlags = _verificationFlags | ExceptionVerificationFlags.IgnoreMultipleDots;
+ else
+ _verificationFlags = _verificationFlags & (~ExceptionVerificationFlags.IgnoreMultipleDots);
+ }
+ }
+
+ public bool IgnoreLineInfo
+ {
+ get
+ {
+ return (_verificationFlags & ExceptionVerificationFlags.IgnoreLineInfo) != 0;
+ }
+ set
+ {
+ if (value)
+ _verificationFlags = _verificationFlags | ExceptionVerificationFlags.IgnoreLineInfo;
+ else
+ _verificationFlags = _verificationFlags & (~ExceptionVerificationFlags.IgnoreLineInfo);
+ }
+ }
+
+ private const string ESCAPE_ANY = "~%anything%~";
+ private const string ESCAPE_NUMBER = "~%number%~";
+
+ public ExceptionVerifier(string assemblyName, ExceptionVerificationFlags flags, ITestOutputHelper output)
+ {
+ _output = output;
+
+ if (assemblyName == null)
+ throw new VerifyException("Assembly name cannot be null");
+
+ _verificationFlags = flags;
+
+ try
+ {
+ switch (assemblyName.ToUpper())
+ {
+ case "SYSTEM.XML":
+ {
+ var dom = new XmlDocument();
+ _asm = dom.GetType().GetTypeInfo().Assembly;
+ }
+ break;
+ default:
+ _asm = Assembly.LoadFrom(Path.Combine(GetRuntimeInstallDir(), assemblyName + ".dll"));
+ break;
+ }
+
+ if (_asm == null)
+ throw new VerifyException("Can not load assembly " + assemblyName);
+
+ // let's determine if this is a loc run, if it is then we need to load satellite assembly
+ _locAsm = null;
+ if (!CultureInfo.CurrentCulture.Equals(new CultureInfo("en-US")) && !CultureInfo.CurrentCulture.Equals(new CultureInfo("en")))
+ {
+ try
+ {
+ // load satellite assembly
+ _locAsm = _asm.GetSatelliteAssembly(new CultureInfo(CultureInfo.CurrentCulture.Parent.IetfLanguageTag));
+ }
+ catch (FileNotFoundException e1)
+ {
+ _output.WriteLine(e1.ToString());
+ }
+ catch (FileLoadException e2)
+ {
+ _output.WriteLine(e2.ToString());
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _output.WriteLine("Exception: " + e.Message);
+ _output.WriteLine("Stack: " + e.StackTrace);
+ throw new VerifyException("Error while loading assembly");
+ }
+
+ string[] resArray;
+ Stream resStream = null;
+ var bFound = false;
+
+ // Check that assembly manifest has resources
+ if (null != _locAsm)
+ resArray = _locAsm.GetManifestResourceNames();
+ else
+ resArray = _asm.GetManifestResourceNames();
+
+ foreach (var s in resArray)
+ {
+ if (s.EndsWith(".resources"))
+ {
+ resStream = null != _locAsm ? _locAsm.GetManifestResourceStream(s) : _asm.GetManifestResourceStream(s);
+ bFound = true;
+ if (bFound && resStream != null)
+ {
+ // Populate hashtable from resources
+ var resReader = new ResourceReader(resStream);
+ if (_resources == null)
+ {
+ _resources = new Hashtable();
+ }
+ var ide = resReader.GetEnumerator();
+ while (ide.MoveNext())
+ {
+ if (!_resources.ContainsKey(ide.Key.ToString()))
+ _resources.Add(ide.Key.ToString(), ide.Value.ToString());
+ }
+ resReader.Dispose();
+ }
+ //break;
+ }
+ }
+
+ if (!bFound || resStream == null)
+ throw new VerifyException("GetManifestResourceStream() failed");
+ }
+
+ private static string GetRuntimeInstallDir()
+ {
+ // Get mscorlib path
+ var s = typeof(object).GetTypeInfo().Module.FullyQualifiedName;
+ // Remove mscorlib.dll from the path
+ return Directory.GetParent(s).ToString();
+ }
+
+ public ExceptionVerifier(string assemblyName, ITestOutputHelper output)
+ : this(assemblyName, ExceptionVerificationFlags.None, output)
+ { }
+
+ private void ExceptionInfoOutput()
+ {
+ // Use reflection to obtain "res" property value
+ var exceptionType = _ex.GetType();
+ var fInfo = exceptionType.GetField("res", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase) ??
+ exceptionType.GetTypeInfo().BaseType.GetField("res", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase);
+
+ if (fInfo == null)
+ throw new VerifyException("Cannot obtain Resource ID from Exception.");
+
+ _output.WriteLine(
+ "\n===== Original Exception Message =====\n" + _ex.Message +
+ "\n===== Resource Id =====\n" + fInfo.GetValue(_ex) +
+ "\n===== HelpLink =====\n" + _ex.HelpLink +
+ "\n===== Source =====\n" + _ex.Source /*+
+ "\n===== TargetSite =====\n" + ex.TargetSite + "\n"*/);
+
+ _output.WriteLine(
+ "\n===== InnerException =====\n" + _ex.InnerException +
+ "\n===== StackTrace =====\n" + _ex.StackTrace);
+ }
+
+ public string[] ReturnAllMatchingResIds(string message)
+ {
+ var ide = _resources.GetEnumerator();
+ var list = new ArrayList();
+
+ _output.WriteLine("===== All mached ResIDs =====");
+ while (ide.MoveNext())
+ {
+ var resMessage = ide.Value.ToString();
+
+ resMessage = ESCAPE_ANY + Regex.Replace(resMessage, @"\{\d*\}", ESCAPE_ANY) + ESCAPE_ANY;
+ resMessage = MakeEscapes(resMessage).Replace(ESCAPE_ANY, ".*");
+ if (Regex.Match(message, resMessage, RegexOptions.Singleline).ToString() == message)
+ {
+ list.Add(ide.Key);
+ _output.WriteLine(" [" + ide.Key.ToString() + "] = \"" + ide.Value.ToString() + "\"");
+ }
+ }
+
+ return (string[])list.ToArray(typeof(string[]));
+ }
+
+ // Common helper methods used by different overloads of IsExceptionOk()
+ private static void CheckNull(Exception e)
+ {
+ if (e == null)
+ {
+ throw new VerifyException("NULL exception passed to IsExceptionOk()");
+ }
+ }
+
+ private void CompareMessages()
+ {
+ if (IgnoreMultipleDots && _expectedMessage.EndsWith("."))
+ _expectedMessage = _expectedMessage.TrimEnd(new char[] { '.' }) + ".";
+ _expectedMessage = Regex.Escape(_expectedMessage);
+ _expectedMessage = _expectedMessage.Replace(ESCAPE_ANY, ".*");
+ _expectedMessage = _expectedMessage.Replace(ESCAPE_NUMBER, @"\d*");
+
+ // ignore case
+ _expectedMessage = _expectedMessage.ToLowerInvariant();
+ _actualMessage = _actualMessage.ToLowerInvariant();
+ if (Regex.Match(_actualMessage, _expectedMessage, RegexOptions.Singleline).ToString() != _actualMessage)
+ {
+ // Unescape before printing the expected message string
+ _expectedMessage = Regex.Unescape(_expectedMessage);
+ _output.WriteLine("Mismatch in error message");
+ _output.WriteLine("===== Expected Message =====\n" + _expectedMessage);
+ _output.WriteLine("===== Expected Message Length =====\n" + _expectedMessage.Length);
+ _output.WriteLine("===== Actual Message =====\n" + _actualMessage);
+ _output.WriteLine("===== Actual Message Length =====\n" + _actualMessage.Length);
+ throw new VerifyException("Mismatch in error message");
+ }
+ }
+
+ public void IsExceptionOk(Exception e, string expectedResId)
+ {
+ CheckNull(e);
+ _ex = e;
+ if (expectedResId == null)
+ {
+ // Pint actual exception info and quit
+ // This can be used to dump exception properties, verify them and then plug them into our expected results
+ ExceptionInfoOutput();
+ throw new VerifyException("Did not pass resource ID to verify");
+ }
+
+ IsExceptionOk(e, new object[] { expectedResId });
+ }
+
+ public void IsExceptionOk(Exception e, string expectedResId, string[] paramValues)
+ {
+ var list = new ArrayList { expectedResId };
+
+ foreach (var param in paramValues)
+ list.Add(param);
+
+ IsExceptionOk(e, list.ToArray());
+ }
+
+ public void IsExceptionOk(Exception e, string expectedResId, string[] paramValues, LineInfo lineInfo)
+ {
+ var list = new ArrayList { expectedResId, lineInfo };
+
+ foreach (var param in paramValues)
+ list.Add(param);
+
+ IsExceptionOk(e, list.ToArray());
+ }
+
+ public void IsExceptionOk(Exception e, object[] IdsAndParams)
+ {
+ CheckNull(e);
+ _ex = e;
+
+ _actualMessage = e.Message;
+ _expectedMessage = ConstructExpectedMessage(IdsAndParams);
+
+ CompareMessages();
+ }
+
+ private static string MakeEscapes(string str)
+ {
+ return new[] { "\\", "$", "{", "[", "(", "|", ")", "*", "+", "?" }.Aggregate(str, (current, esc) => current.Replace(esc, "\\" + esc));
+ }
+
+ public string ConstructExpectedMessage(object[] IdsAndParams)
+ {
+ var lineInfoMessage = "";
+ var paramList = new ArrayList();
+ var paramsStartPosition = 1;
+
+ // Verify that input list contains at least one element - ResId
+ if (IdsAndParams.Length == 0 || !(IdsAndParams[0] is string))
+ throw new VerifyException("ResID at IDsAndParams[0] missing!");
+ string expectedResId = (IdsAndParams[0] as string);
+
+ // Verify that resource id exists in resources
+ if (!_resources.ContainsKey(expectedResId))
+ {
+ ExceptionInfoOutput();
+ throw new VerifyException("Resources in [" + _asm.GetName().Name + "] does not contain string resource: " + expectedResId);
+ }
+
+ // If LineInfo exist, construct LineInfo message
+ if (IdsAndParams.Length > 1 && (IdsAndParams[1] is LineInfo))
+ {
+ if (!IgnoreLineInfo)
+ {
+ var lineInfo = (IdsAndParams[1] as LineInfo);
+
+ // Xml_ErrorPosition = "Line {0}, position {1}."
+ lineInfoMessage = String.IsNullOrEmpty(lineInfo.FilePath) ? _resources["Xml_ErrorPosition"].ToString() : _resources["Xml_ErrorFilePosition"].ToString();
+
+ var lineNumber = lineInfo.LineNumber.ToString();
+ var linePosition = lineInfo.LinePosition.ToString();
+ lineInfoMessage = String.IsNullOrEmpty(lineInfo.FilePath) ? String.Format(lineInfoMessage, lineNumber, linePosition) : String.Format(lineInfoMessage, lineInfo.FilePath, lineNumber, linePosition);
+ }
+ else
+ lineInfoMessage = ESCAPE_ANY;
+
+ lineInfoMessage = " " + lineInfoMessage;
+ paramsStartPosition = 2;
+ }
+
+ string message = _resources[expectedResId].ToString();
+ for (var i = paramsStartPosition; i < IdsAndParams.Length; i++)
+ {
+ if (IdsAndParams[i] is object[])
+ paramList.Add(ConstructExpectedMessage(IdsAndParams[i] as object[]));
+ else
+ {
+ if (IdsAndParams[i] == null)
+ paramList.Add(ESCAPE_ANY);
+ else
+ paramList.Add(IdsAndParams[i] as string);
+ }
+ }
+
+ try
+ {
+ message = string.Format(message, paramList.ToArray());
+ }
+ catch (FormatException)
+ {
+ throw new VerifyException("Mismatch in number of parameters!");
+ }
+
+ return message + lineInfoMessage;
+ }
+ }
+
+ public class VerifyException : Exception
+ {
+ public VerifyException(string msg)
+ : base(msg)
+ { }
+ }
+} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedAttributes.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedAttributes.cs
index 4543403701..8c3acdfbc2 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedAttributes.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedAttributes.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedParticles.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedParticles.cs
index b97c3c5ea4..5fe8e6bd6a 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedParticles.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/GetExpectedParticles.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.IO;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Initialize_EndValidation.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Initialize_EndValidation.cs
index ef16fd4a38..79b5b9d76a 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Initialize_EndValidation.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/Initialize_EndValidation.cs
@@ -2,9 +2,7 @@
// 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.IO;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
@@ -16,9 +14,12 @@ namespace System.Xml.Tests
public class TCInitialize : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCInitialize(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Fact]
@@ -230,9 +231,23 @@ namespace System.Xml.Tests
break;
}
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, (string)null);
+ switch (typeToValidate)
+ {
+ case "other":
+ _exVerifier.IsExceptionOk(e, "Sch_SchemaElementNameMismatch", new string[] { "PartialElement2", "PartialElement" });
+ break;
+ case "type":
+ _exVerifier.IsExceptionOk(e, "Sch_SchemaElementNameMismatch", new string[] { "foo", "PartialElement" });
+ break;
+ case "attribute":
+ _exVerifier.IsExceptionOk(e, "Sch_ValidateAttributeInvalidCall");
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
return;
}
@@ -285,10 +300,6 @@ namespace System.Xml.Tests
val.ValidateElement("foo", "", info, "PartialType2", null, null, null);
break;
- case "element":
- val.ValidateElement("PartialElement", "", info);
- break;
-
case "attribute":
val.ValidateAttribute("PartialAttribute", "", StringGetter("123"), info);
break;
@@ -298,10 +309,20 @@ namespace System.Xml.Tests
break;
}
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, (string)null);
-
+ switch (typeToValidate)
+ {
+ case "other":
+ _exVerifier.IsExceptionOk(e, "Sch_XsiTypeBlockedEx", new string[] { "PartialType2", "foo" });
+ break;
+ case "attribute":
+ _exVerifier.IsExceptionOk(e, "Sch_ValidateAttributeInvalidCall");
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
return;
}
@@ -391,10 +412,23 @@ namespace System.Xml.Tests
break;
}
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, (string)null);
-
+ switch (typeToValidate)
+ {
+ case "other":
+ _exVerifier.IsExceptionOk(e, "Sch_SchemaAttributeNameMismatch", new string[] { "PartialAttribute2", "PartialAttribute" });
+ break;
+ case "element":
+ _exVerifier.IsExceptionOk(e, "Sch_ValidateElementInvalidCall");
+ break;
+ case "type":
+ _exVerifier.IsExceptionOk(e, "Sch_ValidateElementInvalidCall");
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
return;
}
@@ -459,7 +493,7 @@ namespace System.Xml.Tests
if (typeToValidate == "text")
val.ValidateText(StringGetter("foo"));
else
- val.ValidateWhitespace(StringGetter("\r\n\t "));
+ val.ValidateWhitespace(StringGetter(Environment.NewLine + "\t "));
return;
}
@@ -470,9 +504,12 @@ namespace System.Xml.Tests
public class TCEndValidation : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCEndValidation(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Fact]
@@ -559,9 +596,9 @@ namespace System.Xml.Tests
val.EndValidation();
Assert.True(false);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_UndeclaredId", new string[] { "a3" });
+ _exVerifier.IsExceptionOk(e, "Sch_UndeclaredId", new string[] { "a3" });
return;
}
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/PropertiesTests.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/PropertiesTests.cs
index 8e3a4138ed..250e7d2bff 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/PropertiesTests.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/PropertiesTests.cs
@@ -2,10 +2,8 @@
// 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.Collections;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
@@ -17,9 +15,12 @@ namespace System.Xml.Tests
public class TCXmlResolver : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCXmlResolver(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
//BUG #304124
@@ -181,9 +182,9 @@ namespace System.Xml.Tests
val.ValidateElement("bar", "", null, "t:type1", null, "uri:tempuri " + Path.Combine(TestData, XSDFILE_TARGET_NAMESPACE), null);
Assert.True(false);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_XsiTypeNotFound", new string[] { "uri:tempuri:type1" });
+ _exVerifier.IsExceptionOk(e, "Sch_XsiTypeNotFound", new string[] { "uri:tempuri:type1" });
return;
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/System.Xml.XmlSchema.XmlSchemaValidatorApi.Tests.csproj b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/System.Xml.XmlSchema.XmlSchemaValidatorApi.Tests.csproj
index 01edca2817..1bcd7714fe 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/System.Xml.XmlSchema.XmlSchemaValidatorApi.Tests.csproj
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/System.Xml.XmlSchema.XmlSchemaValidatorApi.Tests.csproj
@@ -12,6 +12,7 @@
<ItemGroup>
<Compile Include="Constructor_AddSchema.cs" />
<Compile Include="CustomImplementations.cs" />
+ <Compile Include="ExceptionVerifier.cs" />
<Compile Include="GetExpectedAttributes.cs" />
<Compile Include="GetExpectedParticles.cs" />
<Compile Include="Initialize_EndValidation.cs" />
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute.cs
index c003373a25..a05bc159cb 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute.cs
@@ -2,10 +2,8 @@
// 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.Collections;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
@@ -17,9 +15,12 @@ namespace System.Xml.Tests
public class TCValidateAttribute : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCValidateAttribute(ITestOutputHelper output) : base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Theory]
@@ -188,9 +189,9 @@ namespace System.Xml.Tests
{
val.ValidateAttribute("RequiredAttribute", "", StringGetter("foo"), info);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_DuplicateAttribute", new string[] { "RequiredAttribute" });
+ _exVerifier.IsExceptionOk(e, "Sch_DuplicateAttribute", new string[] { "RequiredAttribute" });
return;
}
@@ -368,9 +369,12 @@ namespace System.Xml.Tests
public class TCValidateEndOfAttributes : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCValidateEndOfAttributes(ITestOutputHelper output) : base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Fact]
@@ -445,9 +449,9 @@ namespace System.Xml.Tests
{
val.ValidateEndOfAttributes(null);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_MissRequiredAttribute", new string[] { "RequiredAttribute" });
+ _exVerifier.IsExceptionOk(e, "Sch_MissRequiredAttribute", new string[] { "RequiredAttribute" });
return;
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute_String.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute_String.cs
index 308c69fb11..aa342d5eb6 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute_String.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateAttribute_String.cs
@@ -2,10 +2,8 @@
// 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.Collections;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
@@ -17,9 +15,12 @@ namespace System.Xml.Tests
public class TCValidateAttribute_String : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCValidateAttribute_String(ITestOutputHelper output) : base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Theory]
@@ -188,9 +189,9 @@ namespace System.Xml.Tests
{
val.ValidateAttribute("RequiredAttribute", "", "foo", info);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_DuplicateAttribute", new string[] { "RequiredAttribute" });
+ _exVerifier.IsExceptionOk(e, "Sch_DuplicateAttribute", new string[] { "RequiredAttribute" });
return;
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateElement.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateElement.cs
index 1e28b1a2a7..fb47e7b2af 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateElement.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateElement.cs
@@ -2,10 +2,8 @@
// 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.Collections;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
@@ -17,9 +15,12 @@ namespace System.Xml.Tests
public class TCValidateElement : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCValidateElement(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Theory]
@@ -87,9 +88,9 @@ namespace System.Xml.Tests
else
val.ValidateElement("$$##", "", null, null, null, null, null);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_UndeclaredElement", new string[] { "$$##" });
+ _exVerifier.IsExceptionOk(e, "Sch_UndeclaredElement", new string[] { "$$##" });
return;
}
@@ -198,7 +199,7 @@ namespace System.Xml.Tests
else
{
Assert.True(holder.IsCalledA);
- //XmlExceptionVerifier.IsExceptionOk(holder.lastException);
+ _exVerifier.IsExceptionOk(holder.lastException, "Sch_XsiTypeNotFound", new string[] { "uri:tempuri:type1" });
}
return;
@@ -233,7 +234,7 @@ namespace System.Xml.Tests
else
{
Assert.True(holder.IsCalledA);
- //XmlExceptionVerifier.IsExceptionOk(holder.lastException);
+ _exVerifier.IsExceptionOk(holder.lastException, "Sch_XsiTypeNotFound", new string[] { "type1" });
}
return;
@@ -257,11 +258,11 @@ namespace System.Xml.Tests
{
val.ValidateEndElement(info);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, new object[] { "Sch_IncompleteContentExpecting",
- // new object[] { "Sch_ElementName", "NillableElement" },
- // new object[] { "Sch_ElementName", "foo" } });
+ _exVerifier.IsExceptionOk(e, new object[] { "Sch_IncompleteContentExpecting",
+ new object[] { "Sch_ElementName", "NillableElement" },
+ new object[] { "Sch_ElementName", "foo" } });
return;
}
@@ -322,9 +323,9 @@ namespace System.Xml.Tests
{
val.ValidateElement("foo", "uri:tempuri", null, "type1", null, null, null);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_XsiTypeNotFound", new string[] { "type1" });
+ _exVerifier.IsExceptionOk(e, "Sch_XsiTypeNotFound", new string[] { "type1" });
return;
}
Assert.True(false);
@@ -356,7 +357,7 @@ namespace System.Xml.Tests
Assert.True(holder.IsCalledA);
Assert.Equal(holder.lastSeverity, XmlSeverityType.Warning);
- //XmlExceptionVerifier.IsExceptionOk(holder.lastException, "Sch_CannotLoadSchema", new string[] { "uri:tempuri", null });
+ _exVerifier.IsExceptionOk(holder.lastException, "Sch_CannotLoadSchema", new string[] { "uri:tempuri", null });
return;
}
@@ -384,7 +385,7 @@ namespace System.Xml.Tests
Assert.True(holder.IsCalledA);
Assert.Equal(holder.lastSeverity, XmlSeverityType.Warning);
- //XmlExceptionVerifier.IsExceptionOk(holder.lastException, "Sch_CannotLoadSchema", new string[] { "", null });
+ _exVerifier.IsExceptionOk(holder.lastException, "Sch_CannotLoadSchema", new string[] { "", null });
return;
}
@@ -405,7 +406,7 @@ namespace System.Xml.Tests
Assert.True(holder.IsCalledA);
Assert.Equal(holder.lastSeverity, XmlSeverityType.Warning);
- //XmlExceptionVerifier.IsExceptionOk(holder.lastException, "Sch_NoElementSchemaFound", new string[] { "undefined" });
+ _exVerifier.IsExceptionOk(holder.lastException, "Sch_NoElementSchemaFound", new string[] { "undefined" });
return;
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateMisc.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateMisc.cs
index c319a5435e..f1d15548d1 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateMisc.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateMisc.cs
@@ -2,10 +2,8 @@
// 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.IO;
using System.Text.RegularExpressions;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_EndElement.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_EndElement.cs
index 02db6dea69..dd81c604d0 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_EndElement.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_EndElement.cs
@@ -2,7 +2,6 @@
// 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.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
@@ -14,9 +13,12 @@ namespace System.Xml.Tests
public class TCValidateText : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCValidateText(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Fact]
@@ -133,11 +135,11 @@ namespace System.Xml.Tests
{
val.ValidateText(StringGetter("some text"));
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, new object[] { "Sch_InvalidTextInElementExpecting",
- // new object[] { "Sch_ElementName", "ElementOnlyElement" },
- // new object[] { "Sch_ElementName", "child" } });
+ _exVerifier.IsExceptionOk(e, new object[] { "Sch_InvalidTextInElementExpecting",
+ new object[] { "Sch_ElementName", "ElementOnlyElement" },
+ new object[] { "Sch_ElementName", "child" } });
return;
}
@@ -158,9 +160,9 @@ namespace System.Xml.Tests
{
val.ValidateText(StringGetter("some text"));
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_InvalidTextInEmpty");
+ _exVerifier.IsExceptionOk(e, "Sch_InvalidTextInEmpty");
return;
}
@@ -173,9 +175,12 @@ namespace System.Xml.Tests
public class TCValidateWhitespace : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCValidateWhitespace(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Fact]
@@ -205,7 +210,7 @@ namespace System.Xml.Tests
val.ValidationEventHandler += new ValidationEventHandler(holder.CallbackA);
val.Initialize();
- val.ValidateWhitespace(StringGetter(" \t\r\n"));
+ val.ValidateWhitespace(StringGetter(" \t" + Environment.NewLine));
val.EndValidation();
Assert.True(!holder.IsCalledA);
@@ -226,13 +231,13 @@ namespace System.Xml.Tests
val.ValidateElement("ElementOnlyElement", "", info);
val.ValidateEndOfAttributes(null);
- val.ValidateWhitespace(StringGetter(" \t\r\n"));
+ val.ValidateWhitespace(StringGetter(" \t"+ Environment.NewLine));
val.ValidateElement("child", "", info);
val.ValidateEndOfAttributes(null);
val.ValidateEndElement(info);
- val.ValidateWhitespace(StringGetter(" \t\r\n"));
+ val.ValidateWhitespace(StringGetter(" \t" + Environment.NewLine));
val.ValidateEndElement(info);
val.EndValidation();
@@ -256,11 +261,11 @@ namespace System.Xml.Tests
try
{
- val.ValidateWhitespace(StringGetter(" \r\n\t"));
+ val.ValidateWhitespace(StringGetter(" " + Environment.NewLine + "\t"));
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_InvalidWhitespaceInEmpty");
+ _exVerifier.IsExceptionOk(e, "Sch_InvalidWhitespaceInEmpty");
return;
}
@@ -282,7 +287,7 @@ namespace System.Xml.Tests
}
catch (Exception) // Replace with concrete exception type
{
- // Verify exception
+ // Verify exception ????
Assert.True(false);
}
@@ -295,9 +300,12 @@ namespace System.Xml.Tests
public class TCValidateEndElement : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCValidateEndElement(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Fact]
@@ -474,9 +482,9 @@ namespace System.Xml.Tests
{
val.ValidateEndElement(info, "23");
}
- catch (InvalidOperationException)
+ catch (InvalidOperationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_InvalidEndElementCall");
+ _exVerifier.IsExceptionOk(e, "Sch_InvalidEndElementCall");
return;
}
@@ -606,9 +614,9 @@ namespace System.Xml.Tests
val.ValidateEndElement(info);
Assert.True(false);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_DuplicateKey", new string[] { "1", "numberKey" });
+ _exVerifier.IsExceptionOk(e, "Sch_DuplicateKey", new string[] { "1", "numberKey" });
return;
}
}
@@ -624,9 +632,9 @@ namespace System.Xml.Tests
val.ValidateEndElement(info);
Assert.True(false);
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_UnresolvedKeyref", new string[] { "3", "numberKey" });
+ _exVerifier.IsExceptionOk(e, "Sch_UnresolvedKeyref", new string[] { "3", "numberKey" });
return;
}
}
@@ -711,9 +719,9 @@ namespace System.Xml.Tests
{
val.ValidateEndElement(info, "23");
}
- catch (InvalidOperationException)
+ catch (InvalidOperationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, (string)null);
+ _exVerifier.IsExceptionOk(e, "Sch_InvalidEndElementCallTyped");
return;
}
@@ -726,9 +734,12 @@ namespace System.Xml.Tests
public class TCSkipToEndElement : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCSkipToEndElement(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Fact]
@@ -838,9 +849,9 @@ namespace System.Xml.Tests
{
val.SkipToEndElement(info);
}
- catch (InvalidOperationException)
+ catch (InvalidOperationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_InvalidEndElementMultiple", new string[] { "SkipToEndElement" });
+ _exVerifier.IsExceptionOk(e, "Sch_InvalidEndElementMultiple", new string[] { "SkipToEndElement" });
return;
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_String.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_String.cs
index 52b589c944..ddc3ca1de2 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_String.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateText_String.cs
@@ -2,7 +2,6 @@
// 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.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
@@ -14,9 +13,12 @@ namespace System.Xml.Tests
public class TCValidateText_String : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
+
public TCValidateText_String(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Fact]
@@ -135,11 +137,11 @@ namespace System.Xml.Tests
{
val.ValidateText("some text");
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, new object[] { "Sch_InvalidTextInElementExpecting",
- // new object[] { "Sch_ElementName", "ElementOnlyElement" },
- // new object[] { "Sch_ElementName", "child" } });
+ _exVerifier.IsExceptionOk(e, new object[] { "Sch_InvalidTextInElementExpecting",
+ new object[] { "Sch_ElementName", "ElementOnlyElement" },
+ new object[] { "Sch_ElementName", "child" } });
return;
}
@@ -160,9 +162,9 @@ namespace System.Xml.Tests
{
val.ValidateText("some text");
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_InvalidTextInEmpty");
+ _exVerifier.IsExceptionOk(e, "Sch_InvalidTextInEmpty");
return;
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateWhitespace_String.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateWhitespace_String.cs
index c5c26eb789..4c715b2b11 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateWhitespace_String.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidateWhitespace_String.cs
@@ -14,9 +14,11 @@ namespace System.Xml.Tests
public class TCValidateWhitespace_String : CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
+ private ExceptionVerifier _exVerifier;
public TCValidateWhitespace_String(ITestOutputHelper output): base(output)
{
_output = output;
+ _exVerifier = new ExceptionVerifier("System.Xml", _output);
}
[Fact]
@@ -46,7 +48,7 @@ namespace System.Xml.Tests
val.ValidationEventHandler += new ValidationEventHandler(holder.CallbackA);
val.Initialize();
- val.ValidateWhitespace(" \t\r\n");
+ val.ValidateWhitespace(" \t" + Environment.NewLine);
val.EndValidation();
Assert.True(!holder.IsCalledA);
@@ -67,13 +69,13 @@ namespace System.Xml.Tests
val.ValidateElement("ElementOnlyElement", "", info);
val.ValidateEndOfAttributes(null);
- val.ValidateWhitespace(" \t\r\n");
+ val.ValidateWhitespace(" \t" + Environment.NewLine);
val.ValidateElement("child", "", info);
val.ValidateEndOfAttributes(null);
val.ValidateEndElement(info);
- val.ValidateWhitespace(" \t\r\n");
+ val.ValidateWhitespace(" \t" + Environment.NewLine);
val.ValidateEndElement(info);
val.EndValidation();
@@ -97,11 +99,11 @@ namespace System.Xml.Tests
try
{
- val.ValidateWhitespace(" \r\n\t");
+ val.ValidateWhitespace(" " + Environment.NewLine + "\t");
}
- catch (XmlSchemaValidationException)
+ catch (XmlSchemaValidationException e)
{
- //XmlExceptionVerifier.IsExceptionOk(e, "Sch_InvalidWhitespaceInEmpty");
+ _exVerifier.IsExceptionOk(e, "Sch_InvalidWhitespaceInEmpty");
return;
}
diff --git a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidatorModule.cs b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidatorModule.cs
index 278bdb66e4..8eaf9118f9 100644
--- a/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidatorModule.cs
+++ b/src/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/ValidatorModule.cs
@@ -2,16 +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;
using System.IO;
-using System.Xml;
using System.Xml.Schema;
using Xunit;
using Xunit.Abstractions;
namespace System.Xml.Tests
{
- public class CXmlSchemaValidatorTestCase //: CTestCase
+ public class CXmlSchemaValidatorTestCase
{
private ITestOutputHelper _output;
public CXmlSchemaValidatorTestCase(ITestOutputHelper output)
diff --git a/src/System.Private.Xml/tests/XmlSerializer/ReflectionOnly/System.Xml.XmlSerializer.ReflectionOnly.Tests.csproj b/src/System.Private.Xml/tests/XmlSerializer/ReflectionOnly/System.Xml.XmlSerializer.ReflectionOnly.Tests.csproj
new file mode 100644
index 0000000000..1db27992b8
--- /dev/null
+++ b/src/System.Private.Xml/tests/XmlSerializer/ReflectionOnly/System.Xml.XmlSerializer.ReflectionOnly.Tests.csproj
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <DefineConstants>$(DefineConstants);ReflectionOnly</DefineConstants>
+ <RootNamespace>System.Xml.XmlSerializer.ReflectionOnly.Tests</RootNamespace>
+ <AssemblyName>System.Xml.XmlSerializer.ReflectionOnly.Tests</AssemblyName>
+ <ProjectGuid>{4050F1D1-1DD2-4B48-A17B-E3F955518C4B}</ProjectGuid>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(TestSourceFolder)..\..\..\System.Runtime.Serialization.Xml\tests\Utils.cs" />
+ <Compile Include="$(TestSourceFolder)..\..\..\System.Runtime.Serialization.Xml\tests\SerializationTypes.cs" />
+ <Compile Include="$(TestSourceFolder)..\..\..\System.Runtime.Serialization.Xml\tests\Performance\PerformanceTestsCommon.cs" />
+ <Compile Include="$(TestSourceFolder)XmlSerializerTests.cs" />
+ <Compile Include="$(TestSourceFolder)Performance\XsPerformanceTest.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(TargetGroup)' != 'netcore50' AND '$(TargetGroup)' != 'netcore50aot'">
+ <Compile Include="$(TestSourceFolder)XmlSerializerTests.Internal.cs" Condition="'$(UseContractReferences)' == ''" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), System.Xml.XmlSerializer.Tests.settings.targets))\System.Xml.XmlSerializer.Tests.settings.targets" />
+</Project>
diff --git a/src/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.csproj b/src/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.csproj
index 03d22653a7..9be9bae051 100644
--- a/src/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.csproj
+++ b/src/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.csproj
@@ -7,14 +7,14 @@
<DefineConstants Condition="'$(TargetGroup)' == 'netcore50' OR '$(TargetGroup)' == 'netcore50aot'">$(DefineConstants);NET_NATIVE</DefineConstants>
</PropertyGroup>
<ItemGroup>
- <Compile Include="..\..\..\System.Runtime.Serialization.Xml\tests\Utils.cs" />
- <Compile Include="..\..\..\System.Runtime.Serialization.Xml\tests\SerializationTypes.cs" />
- <Compile Include="..\..\..\System.Runtime.Serialization.Xml\tests\Performance\PerformanceTestsCommon.cs" />
- <Compile Include="XmlSerializerTests.cs" />
- <Compile Include="Performance\XsPerformanceTest.cs" />
+ <Compile Include="$(TestSourceFolder)..\..\..\System.Runtime.Serialization.Xml\tests\Utils.cs" />
+ <Compile Include="$(TestSourceFolder)..\..\..\System.Runtime.Serialization.Xml\tests\SerializationTypes.cs" />
+ <Compile Include="$(TestSourceFolder)..\..\..\System.Runtime.Serialization.Xml\tests\Performance\PerformanceTestsCommon.cs" />
+ <Compile Include="$(TestSourceFolder)XmlSerializerTests.cs" />
+ <Compile Include="$(TestSourceFolder)Performance\XsPerformanceTest.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' != 'netcore50' AND '$(TargetGroup)' != 'netcore50aot'">
- <Compile Include="XmlSerializerTests.Internal.cs" Condition="'$(UseContractReferences)' == ''" />
+ <Compile Include="$(TestSourceFolder)XmlSerializerTests.Internal.cs" Condition="'$(UseContractReferences)' == ''" />
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), System.Xml.XmlSerializer.Tests.settings.targets))\System.Xml.XmlSerializer.Tests.settings.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.settings.targets b/src/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.settings.targets
new file mode 100644
index 0000000000..a4c547ebfb
--- /dev/null
+++ b/src/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.settings.targets
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <DefineConstants Condition="'$(TargetGroup)' == 'netcore50' OR '$(TargetGroup)' == 'netcore50aot'">$(DefineConstants);NET_NATIVE</DefineConstants>
+ <NugetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.7</NugetTargetMoniker>
+ <NugetTargetMoniker>.NETStandard,Version=v1.7</NugetTargetMoniker>
+ <TestSourceFolder>$(MSBuildThisFileDirectory)\</TestSourceFolder>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(UseContractReferences)' == 'true'">
+ <ProjectJson>Performance/project.json</ProjectJson>
+ <ProjectLockJson>Performance/project.lock.json</ProjectLockJson>
+ </PropertyGroup>
+ <ItemGroup>
+ <ProjectReference Include="$(TestSourceFolder)..\..\..\System.Private.Xml\pkg\System.Private.Xml.pkgproj" />
+ <ProjectReference Include="$(TestSourceFolder)..\..\..\System.Xml.XmlSerializer\pkg\System.Xml.XmlSerializer.pkgproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs b/src/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs
index 39e77fbb9c..16c40fcbb3 100644
--- a/src/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs
+++ b/src/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs
@@ -20,6 +20,17 @@ using Xunit;
public static partial class XmlSerializerTests
{
+#if ReflectionOnly
+ private static readonly string SerializationModeSetterName = "set_Mode";
+
+ static XmlSerializerTests()
+ {
+ var method = typeof(XmlSerializer).GetMethod(SerializationModeSetterName);
+ Assert.True(method != null, $"No method named {SerializationModeSetterName}");
+ method.Invoke(null, new object[] { 1 });
+ }
+
+#endif
[Fact]
public static void Xml_BoolAsRoot()
{
@@ -2354,6 +2365,9 @@ string.Format(@"<?xml version=""1.0"" encoding=""utf-8""?>
Assert.Equal(originalmapping.XsdTypeNamespace, newmapping.XsdTypeNamespace);
}
+#if ReflectionOnly
+ [ActiveIssue(11919)]
+#endif
[Fact]
public static void XmlSerializerFactoryTest()
{
@@ -2367,6 +2381,9 @@ string.Format(@"<?xml version=""1.0"" encoding=""utf-8""?>
Assert.Equal(dog1.Breed, dog2.Breed);
}
+#if ReflectionOnly
+ [ActiveIssue(14259)]
+#endif
[Fact]
public static void XmlUnknownElementAndEventHandlerTest()
{
@@ -2397,6 +2414,9 @@ string.Format(@"<?xml version=""1.0"" encoding=""utf-8""?>
Assert.True(b);
}
+#if ReflectionOnly
+ [ActiveIssue(14259)]
+#endif
[Fact]
public static void XmlUnknownNodeAndEventHandlerTest()
{
@@ -2589,6 +2609,9 @@ string.Format(@"<?xml version=""1.0"" encoding=""utf-8""?>
cds.AddReserved(typeof(Employee).Name);
cds.Add("test", new TestData());
cds.AddUnique("test2", new TestData());
+ Assert.Equal("camelText", CodeIdentifier.MakeCamel("Camel Text"));
+ Assert.Equal("PascalText", CodeIdentifier.MakePascal("Pascal Text"));
+ Assert.Equal("ValidText", CodeIdentifier.MakeValid("Valid Text!"));
}
[Fact]
@@ -2618,6 +2641,12 @@ string.Format(@"<?xml version=""1.0"" encoding=""utf-8""?>
Assert.Equal(1, mapping.Count);
}
+ [Fact]
+ public static void XmlSerializationGeneratedCodeTest()
+ {
+ var cg = new MycodeGenerator();
+ Assert.NotNull(cg);
+ }
private static Stream GenerateStreamFromString(string s)
{
var stream = new MemoryStream();
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/398968repro.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/398968repro.xsl
new file mode 100644
index 0000000000..6276032f19
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/398968repro.xsl
@@ -0,0 +1,9 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output omit-xml-declaration="yes"/>
+
+<xsl:template match="/">
+ <xsl:copy-of select="document('Stra%C3%9Fe.xml')"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/QFE505_multith_customer_repro_with_or_expr.xml b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/QFE505_multith_customer_repro_with_or_expr.xml
new file mode 100644
index 0000000000..a68862d508
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/QFE505_multith_customer_repro_with_or_expr.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="iso-8859-1"?><eventpage lang="en" type="category"><sporttabs selected="12"><sporttab ID="0" desc="Home" /><sporttab ID="2" desc="Bonus Ball" /><sporttab ID="3" desc="Boxing" /><sporttab ID="4" desc="Cricket" /><sporttab ID="6" desc="Golf" /><sporttab ID="10" desc="Rugby" /><sporttab ID="12" desc="Soccer" /><sporttab ID="13" desc="Tennis" /><sporttab ID="14" desc="US Sports" /></sporttabs><selectedcategory ID="7576" typeID="3" sporttypeID="1" title="" desc="Midweek Champions League" narrative="" iconname="Default.gif" treeiconname="zfoot.jpg"><categorypath><category ID="107" desc="SOCCER MATCHES" /><category ID="7576" desc="Midweek Champions League" /></categorypath><categorygroupmarkets selected="34"><markettype ID="3" styleID="4" desc="90 Mins" /><markettype ID="34" styleID="1" desc="Half Time - Full Time" /><markettype ID="36" styleID="3" desc="Time of 1st Goal" /><markettype ID="38" styleID="3" desc="Which Team Will Score 1st" /></categorygroupmarkets><events><event ID="86376" date="2001-11-29T00:00:00" desc="US Footie" sporttypeID="0" compID="0" compname="Unknown"><market ID="133302" typeID="105488" styleID="1" desc="NCAA - Regular Season Wins" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="86378" date="2001-11-29T00:00:00" desc="More US Footie" sporttypeID="0" compID="0" compname="Unknown"><market ID="133303" typeID="106278" styleID="1" desc="Outright Betting - Without Tiger Woods" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="85702" date="2002-12-01T00:00:00" desc="Celtic v Rosenborg" sporttypeID="1" compID="2" compname="Champions League"><market ID="132187" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132188" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="656192" desc="Celtic - Celtic" oddsnum="6" oddsden="5" /><outcome ID="656193" desc="Celtic - Draw" oddsnum="16" oddsden="1" /><outcome ID="656194" desc="Celtic - Rosenborg" oddsnum="33" oddsden="1" /><outcome ID="656195" desc="Draw - Celtic" oddsnum="67" oddsden="20" /><outcome ID="656196" desc="Draw - Draw" oddsnum="5" oddsden="1" /><outcome ID="656197" desc="Draw - Rosenborg " oddsnum="12" oddsden="1" /><outcome ID="656198" desc="Rosenborg - Celtic" oddsnum="28" oddsden="1" /><outcome ID="656199" desc="Rosenborg - Draw" oddsnum="16" oddsden="1" /><outcome ID="656200" desc="Rosenborg - Rosenborg " oddsnum="11" oddsden="1" /></market><market ID="132189" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132190" typeID="39" styleID="3" desc="Who Will Be Winning At Half Time" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132191" typeID="38" styleID="3" desc="Which Team Will Score 1st" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132192" typeID="36" styleID="3" desc="Time of 1st Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132193" typeID="35" styleID="1" desc="Total Goals In The Game" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132194" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132195" typeID="106273" styleID="1" desc="Outright Betting - With M.Schumacher" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="85707" date="2002-12-01T00:00:00" desc="Porto v Juventus" sporttypeID="1" compID="2" compname="Champions League"><market ID="132196" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132197" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="656220" desc="Porto - Porto " oddsnum="9" oddsden="2" /><outcome ID="656221" desc="Porto - Draw" oddsnum="12" oddsden="1" /><outcome ID="656222" desc="Porto - Juventus" oddsnum="25" oddsden="1" /><outcome ID="656223" desc="Draw - Porto " oddsnum="11" oddsden="2" /><outcome ID="656224" desc="Draw - Draw" oddsnum="4" oddsden="1" /><outcome ID="656225" desc="Draw - Juventus" oddsnum="9" oddsden="2" /><outcome ID="656226" desc="Juventus - Porto" oddsnum="28" oddsden="1" /><outcome ID="656227" desc="Juventus - Draw" oddsnum="12" oddsden="1" /><outcome ID="656228" desc="Juventus - Juventus " oddsnum="11" oddsden="4" /></market><market ID="132198" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132199" typeID="39" styleID="3" desc="Who Will Be Winning At Half Time" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132200" typeID="38" styleID="3" desc="Which Team Will Score 1st" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132201" typeID="36" styleID="3" desc="Time of 1st Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132202" typeID="35" styleID="1" desc="Total Goals In The Game" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132203" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132204" typeID="100451" styleID="1" desc="1st Goalscorer" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="85708" date="2002-12-01T00:00:00" desc="Leverkusen v Fenerbahce" sporttypeID="1" compID="2" compname="Champions League"><market ID="132205" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132206" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="656248" desc="Leverkusen - Leverkusen " oddsnum="9" oddsden="10" /><outcome ID="656249" desc="Leverkusen - Draw" oddsnum="16" oddsden="1" /><outcome ID="656250" desc="Leverkusen - Fenerbahce" oddsnum="40" oddsden="1" /><outcome ID="656251" desc="Draw - Leverkusen " oddsnum="67" oddsden="20" /><outcome ID="656252" desc="Draw - Draw" oddsnum="11" oddsden="2" /><outcome ID="656253" desc="Draw - Fenerbahce" oddsnum="16" oddsden="1" /><outcome ID="656254" desc="Fenerbahce - Leverkusen" oddsnum="28" oddsden="1" /><outcome ID="656255" desc="Fenerbahce - Draw" oddsnum="18" oddsden="1" /><outcome ID="656256" desc="Fenerbahce - Fenerbahce " oddsnum="14" oddsden="1" /></market><market ID="132207" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132208" typeID="39" styleID="3" desc="Who Will Be Winning At Half Time" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132209" typeID="38" styleID="3" desc="Which Team Will Score 1st" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132210" typeID="36" styleID="3" desc="Time of 1st Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132211" typeID="35" styleID="1" desc="Total Goals In The Game" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132212" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132213" typeID="100451" styleID="1" desc="1st Goalscorer" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="85710" date="2002-12-01T00:00:00" desc="Barcelona v Lyon" sporttypeID="1" compID="2" compname="Champions League"><market ID="132214" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132215" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="656276" desc="Barcelona - Barcelona" oddsnum="1" oddsden="1" /><outcome ID="656277" desc="Barcelona - Draw" oddsnum="16" oddsden="1" /><outcome ID="656278" desc="Barcelona - Lyon" oddsnum="33" oddsden="1" /><outcome ID="656279" desc="Draw - Barcelona" oddsnum="67" oddsden="20" /><outcome ID="656280" desc="Draw - Draw" oddsnum="11" oddsden="2" /><outcome ID="656281" desc="Draw - Lyon" oddsnum="14" oddsden="1" /><outcome ID="656282" desc="Lyon - Barcelona" oddsnum="28" oddsden="1" /><outcome ID="656283" desc="Lyon - Draw" oddsnum="18" oddsden="1" /><outcome ID="656284" desc="Lyon - Lyon" oddsnum="12" oddsden="1" /></market><market ID="132216" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132217" typeID="39" styleID="3" desc="Who Will Be Winning At Half Time" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132218" typeID="38" styleID="3" desc="Which Team Will Score 1st" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132219" typeID="36" styleID="3" desc="Time of 1st Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132220" typeID="35" styleID="1" desc="Total Goals In The Game" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132221" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132222" typeID="100451" styleID="1" desc="1st Goalscorer" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="85711" date="2002-12-01T00:00:00" desc="Lille v La Coruna" sporttypeID="1" compID="2" compname="Champions League"><market ID="132223" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132224" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="656304" desc="Lille - Lille " oddsnum="7" oddsden="2" /><outcome ID="656305" desc="Lille - Draw" oddsnum="12" oddsden="1" /><outcome ID="656306" desc="Lille - La Coruna" oddsnum="25" oddsden="1" /><outcome ID="656307" desc="Draw - Lille " oddsnum="9" oddsden="2" /><outcome ID="656308" desc="Draw - Draw" oddsnum="4" oddsden="1" /><outcome ID="656309" desc="Draw - La Coruna" oddsnum="9" oddsden="2" /><outcome ID="656310" desc="La Coruna - Lille " oddsnum="25" oddsden="1" /><outcome ID="656311" desc="La Coruna - Draw" oddsnum="12" oddsden="1" /><outcome ID="656312" desc="La Coruna - La Coruna" oddsnum="7" oddsden="2" /></market><market ID="132225" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132226" typeID="39" styleID="3" desc="Who Will Be Winning At Half Time" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132227" typeID="38" styleID="3" desc="Which Team Will Score 1st" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132228" typeID="36" styleID="3" desc="Time of 1st Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132229" typeID="35" styleID="1" desc="Total Goals In The Game" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132230" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132231" typeID="100451" styleID="1" desc="1st Goalscorer" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="85712" date="2002-12-01T00:00:00" desc="Olympiakos v Man Utd" sporttypeID="1" compID="2" compname="Champions League"><market ID="132232" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132233" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="656332" desc="Olympiakos - Olympiakos" oddsnum="9" oddsden="2" /><outcome ID="656333" desc="Olympiakos - Draw" oddsnum="12" oddsden="1" /><outcome ID="656334" desc="Olympiakos - Man Utd" oddsnum="25" oddsden="1" /><outcome ID="656335" desc="Draw - Olympiakos" oddsnum="11" oddsden="2" /><outcome ID="656336" desc="Draw - Draw" oddsnum="4" oddsden="1" /><outcome ID="656337" desc="Draw - Man Utd" oddsnum="4" oddsden="1" /><outcome ID="656338" desc="Man Utd - Olympiakos" oddsnum="28" oddsden="1" /><outcome ID="656339" desc="Man Utd - Draw" oddsnum="12" oddsden="1" /><outcome ID="656340" desc="Man Utd - Man Utd" oddsnum="13" oddsden="5" /></market><market ID="132234" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132235" typeID="39" styleID="3" desc="Who Will Be Winning At Half Time" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132236" typeID="38" styleID="3" desc="Which Team Will Score 1st" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132237" typeID="36" styleID="3" desc="Time of 1st Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132238" typeID="35" styleID="1" desc="Total Goals In The Game" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132239" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132240" typeID="100451" styleID="1" desc="1st Goalscorer" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="85714" date="2002-12-01T00:00:00" desc="Sparta Prague v Spartak Moskow" sporttypeID="1" compID="3" compname="UEFA Cup"><market ID="132241" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132242" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="656360" desc="Sp Prague - Sp Prague" oddsnum="12" oddsden="5" /><outcome ID="656361" desc="Sp Prague - Draw" oddsnum="14" oddsden="1" /><outcome ID="656362" desc="Sp Prague - Sp Moscow" oddsnum="28" oddsden="1" /><outcome ID="656363" desc="Draw - Sp Prague" oddsnum="7" oddsden="2" /><outcome ID="656364" desc="Draw - Draw" oddsnum="9" oddsden="2" /><outcome ID="656365" desc="Draw - Sp Moscow" oddsnum="13" oddsden="2" /><outcome ID="656366" desc="Sp Moscow - Sp Prague" oddsnum="25" oddsden="1" /><outcome ID="656367" desc="Sp Moscow - Draw" oddsnum="16" oddsden="1" /><outcome ID="656368" desc="Sp Moscow - Sp Moscow" oddsnum="5" oddsden="1" /></market><market ID="132243" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132244" typeID="39" styleID="3" desc="Who Will Be Winning At Half Time" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132245" typeID="38" styleID="3" desc="Which Team Will Score 1st" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132246" typeID="36" styleID="3" desc="Time of 1st Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132247" typeID="35" styleID="1" desc="Total Goals In The Game" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132248" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132249" typeID="100451" styleID="1" desc="1st Goalscorer" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="85715" date="2002-12-01T00:00:00" desc="Feyenoord v Bayern Munich" sporttypeID="1" compID="3" compname="UEFA Cup"><market ID="132250" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132251" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="656388" desc="Feyenoord - Feyenoord" oddsnum="7" oddsden="2" /><outcome ID="656389" desc="Feyenoord - Draw" oddsnum="11" oddsden="1" /><outcome ID="656390" desc="Feyenoord - Bayern Munich" oddsnum="25" oddsden="1" /><outcome ID="656391" desc="Draw - Feyenoord" oddsnum="5" oddsden="1" /><outcome ID="656392" desc="Draw - Draw" oddsnum="4" oddsden="1" /><outcome ID="656393" desc="Draw - Bayern Munich" oddsnum="4" oddsden="1" /><outcome ID="656394" desc="Bayern Munich - Feyenoord" oddsnum="28" oddsden="1" /><outcome ID="656395" desc="Bayern Munich - Draw" oddsnum="14" oddsden="1" /><outcome ID="656396" desc="Bayern Munich - Bayern Munich" oddsnum="13" oddsden="5" /></market><market ID="132252" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132253" typeID="39" styleID="3" desc="Who Will Be Winning At Half Time" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132254" typeID="38" styleID="3" desc="Which Team Will Score 1st" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132255" typeID="36" styleID="3" desc="Time of 1st Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132256" typeID="35" styleID="1" desc="Total Goals In The Game" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132257" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="132258" typeID="100451" styleID="1" desc="1st Goalscorer" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="86368" date="2002-12-01T00:00:00" desc="Copy of Feyenoord v Bayern Munich" sporttypeID="1" compID="2" compname="Champions League"><market ID="133274" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133275" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="660113" desc="Feyenoord - Feyenoord" oddsnum="7" oddsden="2" /><outcome ID="660114" desc="Feyenoord - Draw" oddsnum="12" oddsden="1" /><outcome ID="660115" desc="Feyenoord - Bayern Munich" oddsnum="25" oddsden="1" /><outcome ID="660116" desc="Draw - Feyenoord" oddsnum="5" oddsden="1" /><outcome ID="660117" desc="Draw - Draw" oddsnum="4" oddsden="1" /><outcome ID="660118" desc="Draw - Bayern Munich" oddsnum="4" oddsden="1" /><outcome ID="660119" desc="Bayern Munich - Feyenoord" oddsnum="28" oddsden="1" /><outcome ID="660120" desc="Bayern Munich - Draw" oddsnum="14" oddsden="1" /><outcome ID="660121" desc="Bayern Munich - Bayern Munich" oddsnum="13" oddsden="5" /></market><market ID="133276" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133277" typeID="39" styleID="3" desc="Who Will Be Winning At Half Time" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133278" typeID="38" styleID="3" desc="Which Team Will Score 1st" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133279" typeID="36" styleID="3" desc="Time of 1st Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133280" typeID="35" styleID="1" desc="Total Goals In The Game" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133281" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133282" typeID="100451" styleID="1" desc="1st Goalscorer" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="86355" date="2002-12-01T00:00:00" desc="Copy of Rushen v Colby" sporttypeID="1" compID="0" compname="Unknown"><market ID="133179" typeID="100442" styleID="1" desc="1st Corner in the Second Half" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133435" typeID="3" styleID="4" desc="90 Mins" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133434" typeID="33" styleID="1" desc="Correct Score" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133456" typeID="110713" styleID="2" desc="lewis new post edit" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133180" typeID="106360" styleID="4" desc="Outright Winner" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133433" typeID="37" styleID="3" desc="Which Half Will Have The Most Goals" places="2" placingnum="1" placingden="6"><outcome /></market><market ID="133457" typeID="34" styleID="1" desc="Half Time - Full Time" places="1" placingnum="1" placingden="1"><outcome ID="660620" desc="OUtcome 1" oddsnum="4" oddsden="1" /><outcome ID="660621" desc="Outcome2" oddsnum="8" oddsden="1" /></market><market ID="133181" typeID="110146" styleID="1" desc="Which Team To Score The 3rd Goal?" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133423" typeID="108372" styleID="1" desc="To Score the First Goal" places="1" placingnum="1" placingden="1"><outcome /></market><market ID="133182" typeID="109719" styleID="2" desc="Udinese / Fiorentina / Brescia" places="1" placingnum="1" placingden="1"><outcome /></market></event><event ID="86370" date="2001-11-30T15:00:00" desc="Colby v Rushen" sporttypeID="0" compID="0" compname="Unknown"><market ID="133293" typeID="110146" styleID="1" desc="Which Team To Score The 3rd Goal?" places="2" placingnum="1" placingden="2"><outcome /></market><market ID="133294" typeID="106360" styleID="4" desc="Outright Winner" places="4" placingnum="1" placingden="5"><outcome /></market></event></events></selectedcategory><brokenrules /></eventpage> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/QFE505_multith_customer_repro_with_or_expr.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/QFE505_multith_customer_repro_with_or_expr.xsl
new file mode 100644
index 0000000000..7cdcfdffe8
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/QFE505_multith_customer_repro_with_or_expr.xsl
@@ -0,0 +1,516 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:import href="layout.xsl" />
+ <xsl:import href="coupons.xsl" />
+
+ <xsl:template name="metadata">
+ <title>Categories</title>
+ </xsl:template>
+
+ <xsl:template name="extraheader">
+ <script type="text/javascript" language="javascript" src="../jscript/dates.js">
+ </script>
+ </xsl:template>
+
+
+ <xsl:template match="eventpage">
+ <div class="temp">
+ category.xsl
+ </div>
+ <xsl:apply-templates select="selectedcategory" />
+ </xsl:template>
+
+ <xsl:template match="selectedcategory">
+ <h1><xsl:value-of select="@desc" /></h1>
+ <xsl:apply-templates select="categorypath" />
+ <xsl:apply-templates select="categorygroupmarkets" />
+
+ <xsl:if test="/eventpage/selectedcategory[@typeID !=1 and @typeID !=2]">
+ <xsl:call-template name="timezonemessage" />
+ </xsl:if>
+
+ <xsl:apply-templates select="categories" />
+ <xsl:apply-templates select="events" />
+
+ <xsl:if test="@typeID &gt; 2 and @typeID &lt; 6">
+ <xsl:call-template name="oddstypes">
+ <xsl:with-param name="params" select="concat('catid=',@ID)" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="timezonemessage">
+ <div class="timezone">
+ GMT
+ (
+ <script language="javascript" type="text/javascript">displaytimezone()</script>
+ )
+ </div>
+ </xsl:template>
+
+
+ <xsl:template match="market" mode="eachway">
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates select="." mode="eachway_format">
+ <xsl:with-param name="caption">Each way</xsl:with-param>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ BREADCRUMB TRAIL
+ =================================================================== -->
+ <xsl:template match="categorypath">
+ <div class="breadcrumb">
+ <xsl:apply-templates select="/eventpage/sporttabs/sporttab[@ID=parent::sporttabs/@selected]" />
+ <xsl:apply-templates select="category" />
+ </div>
+ </xsl:template>
+
+
+ <xsl:template match="categorypath/category">
+ <a href="CategoryPage.aspx?tab={/eventpage/sporttabs/@selected}&amp;catid={@ID}">
+ <xsl:value-of select="@desc" /><xsl:text />
+ </a>
+ <xsl:text> / </xsl:text>
+ </xsl:template>
+
+
+ <xsl:template match="categorypath/category[@ID=/eventpage/selectedcategory/@ID]">
+ <xsl:value-of select="@desc" />
+ </xsl:template>
+
+
+ <xsl:template match="sporttab">
+ <a href="CategoryPage.aspx?tab={@ID}">
+ <xsl:value-of select="@desc" /><xsl:text />
+ </a>
+ <xsl:text> / </xsl:text>
+ </xsl:template>
+
+
+
+ <!-- ==================================================================
+ MARKET SELECTOR AT TOP OF PAGE
+ USED BY CATEGORY 3
+ =================================================================== -->
+ <xsl:template match="categorygroupmarkets">
+ <xsl:if test="parent::selectedcategory/@typeID=3 and markettype[position()=2]">
+ <div class="markettypes">
+ <xsl:apply-templates select="markettype" />
+ </div>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="markettype">
+ <span>
+ <a href="CategoryPage.aspx?tab={/eventpage/sporttabs/@selected}&amp;catid={/eventpage/selectedcategory/@ID}&amp;mkttypeid={@ID}">
+ <xsl:value-of select="@desc" />
+ </a>
+ </span>
+ </xsl:template>
+
+ <xsl:template match="markettype[@ID=parent::categorygroupmarkets/@selected]">
+ <span>
+ <xsl:value-of select="@desc" />
+ </span>
+ </xsl:template>
+
+
+
+ <!-- ==================================================================
+ CATEGORY 1
+ SUB-CATEGORIES LIST
+ =================================================================== -->
+ <xsl:template match="categories">
+ <xsl:apply-templates />
+ </xsl:template>
+
+ <xsl:template match="categories/category">
+ <h2>
+ <a href="CategoryPage.aspx?tab={/eventpage/sporttabs/@selected}&amp;catid={@ID}">
+ <xsl:value-of select="@desc" />
+ </a>
+ </h2>
+ <xsl:apply-templates select="@narrative[.!='']" />
+ </xsl:template>
+
+ <xsl:template match="@narrative">
+ <div>
+ <xsl:value-of select="." />
+ </div>
+ </xsl:template>
+
+
+
+
+ <!-- ==================================================================
+ CATEGORY 2
+ LIST OF EVENTS IN CATEGORY
+ =================================================================== -->
+ <xsl:template match="selectedcategory[@typeID=2]/events" priority="2">
+ <ul>
+ <xsl:apply-templates mode="category2" />
+ </ul>
+ </xsl:template>
+
+ <xsl:template match="event" mode="category2">
+ <li>
+ <a href="CategoryPage.aspx?tab={/eventpage/sporttabs/@selected}&amp;evntid={@ID}">
+ <xsl:value-of select="@desc" />
+ </a>
+ </li>
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ MAIN CATEGORY TEMPLATE REDIRECTION
+ =================================================================== -->
+
+ <!-- determine whether to branch off to list by markets or list by events -->
+ <xsl:template match="selectedcategory/events">
+ <xsl:variable name="typeID" select="parent::selectedcategory/@typeID" />
+
+ <xsl:choose>
+ <xsl:when test="$typeID = 3 or $typeID = 5">
+ <xsl:apply-templates select="parent::selectedcategory/categorygroupmarkets/markettype" mode="direct" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="event" mode="direct" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- list markets grouped by event - determine which style to use -->
+ <xsl:template match="event" mode="direct">
+ <xsl:variable name="styleid" select="market[position()=1]/@styleID" />
+ <xsl:choose>
+ <xsl:when test="$styleid = 1">
+ <xsl:apply-templates select="." mode="event1" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="." mode="eventdefault">
+ <xsl:with-param name="styleID" select="$styleid" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- list events grouped by market - determine which style to use -->
+ <xsl:template match="markettype" mode="direct">
+ <xsl:variable name="morebets">
+ <xsl:if test="@ID = parent::categorygroupmarkets/@selected and /eventpage/selectedcategory/@typeID = 3">
+ <xsl:text>1</xsl:text>
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:variable name="styleid" select="parent::categorygroupmarkets/parent::selectedcategory/events/event/market[@typeID=current()/@ID]/@styleID" />
+
+ <xsl:choose>
+ <xsl:when test="$styleid = 2 or $styleid = 3">
+ <xsl:apply-templates select="." mode="market2and3">
+ <xsl:with-param name="morebets" select="$morebets" />
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="$styleid = 4">
+ <xsl:apply-templates select="." mode="market4">
+ <xsl:with-param name="morebets" select="$morebets" />
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="$styleid = 5">
+ <xsl:apply-templates select="." mode="market5">
+ <xsl:with-param name="morebets" select="$morebets" />
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="$styleid = 6 or $styleid = 7">
+ <xsl:apply-templates select="." mode="market6and7">
+ <xsl:with-param name="morebets" select="$morebets" />
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="." mode="market1">
+ <xsl:with-param name="morebets" select="$morebets" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ DUMP - CATEGORY 7
+ =================================================================== -->
+ <xsl:template match="selectedcategory[@typeID=7]/events">
+ <p>
+ Category is no longer available.
+ </p>
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ ASIAN HANDICAPS
+ =================================================================== -->
+ <xsl:template match="selectedcategory[@typeID=6]/events">
+ <p>
+ Asian Note 1
+ </p>
+ <p>
+ Asian Note 2
+ </p>
+
+ <xsl:apply-templates select="event" mode="asianhandicap" />
+ </xsl:template>
+
+ <xsl:template match="event" mode="asianhandicap">
+ <table class="coupon">
+ <tr class="title">
+ <th colspan="3">
+ <xsl:value-of select="@desc" />
+ </th>
+ </tr>
+ <tr class="col">
+ <th>
+ <xsl:apply-templates select="@date" mode="date" />
+ </th>
+ <th>
+ Asian Handicaps
+ </th>
+ <th>
+ Asian Odds
+ </th>
+ </tr>
+ <xsl:apply-templates select="market" mode="asianhandicap" />
+ </table>
+ </xsl:template>
+
+
+ <xsl:template match="market" mode="asianhandicap">
+ <xsl:apply-templates select="outcome" mode="asianhandicap" />
+
+ <xsl:apply-templates select="." mode="asiannarrative">
+ <xsl:with-param name="firstteam" select="outcome[@asianhandicapfactor='-1' or (@asianhandicapfactor='0' and position()=1)]" />
+ <xsl:with-param name="secondteam" select="outcome[@asianhandicapfactor='1' or (@asianhandicapfactor='0' and position()=2)]" />
+ <xsl:with-param name="swap"><xsl:if test="outcome[position()=1]/@asianhandicapfactor='1'">1</xsl:if></xsl:with-param>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <xsl:template match="outcome" mode="asianhandicap">
+ <tr>
+ <xsl:call-template name="cssrowclass" />
+ <td>
+ <xsl:value-of select="@desc" />
+ </td>
+ <td>
+ <xsl:if test="@asianhandicapfactor='-1'">
+ <xsl:text>-</xsl:text>
+ </xsl:if>
+ <xsl:apply-templates select="parent::market/@asiangoal1" /><xsl:text />
+ <xsl:apply-templates select="parent::market/@asiangoal2" /><xsl:text />
+ </td>
+ <td>
+ <xsl:apply-templates select="." mode="odds" />
+ </td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template match="@asiangoal2">
+ <xsl:text>/</xsl:text><xsl:value-of select="." /><xsl:text />
+ </xsl:template>
+
+ <xsl:template match="@asiandeductpercent">
+ <xsl:text>(</xsl:text><xsl:value-of select="." /><xsl:text>%)</xsl:text>
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ ASIAN HANDICAP NARRATIVES
+ =================================================================== -->
+ <xsl:template match="market[@asiangoal1='2.5' and not(@asiangoal2)]" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ Multi-lingual
+ </xsl:template>
+
+ <xsl:template match="market[@asiangoal1='2' and @asiangoal2='2.5']" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="market[@asiangoal1='2' and not(@asiangoal2)]" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="market[@asiangoal1='1.5' and @asiangoal2='2']" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="market[@asiangoal1='1.5' and not(@asiangoal2)]" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="market[@asiangoal1='1' and @asiangoal2='1.5']" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="market[@asiangoal1='1' and not(@asiangoal2)]" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="market[@asiangoal1='0.5' and @asiangoal2='1']" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="market[@asiangoal1='0.5' and not(@asiangoal2)]" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="market[@asiangoal1='0' and @asiangoal2='0.5']" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+
+ <xsl:template match="market[@asiangoal1='0' and not(@asiangoal2)]" mode="asiannarrative">
+ <xsl:param name="firstteam" />
+ <xsl:param name="secondteam" />
+ <xsl:param name="swap" />
+
+ <xsl:call-template name="displayasiandesc">
+ <xsl:with-param name="firstdesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="seconddesc">
+ Multi-lingual
+ </xsl:with-param>
+ <xsl:with-param name="swap" select="$swap" />
+ </xsl:call-template>
+ </xsl:template>
+
+
+ <!-- display an asian handicap description -->
+ <xsl:template name="displayasiandesc">
+ <xsl:param name="firstdesc" />
+ <xsl:param name="seconddesc" />
+ <xsl:param name="swap" />
+
+ <tr>
+ <td colspan="3">
+ <xsl:choose>
+ <xsl:when test="$swap='1'">
+ <xsl:copy-of select="$seconddesc" />
+ <p>
+ <xsl:copy-of select="$firstdesc" />
+ </p>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="$firstdesc" />
+ <p>
+ <xsl:copy-of select="$seconddesc" />
+ </p>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </tr>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/Straße.xml b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/Straße.xml
new file mode 100644
index 0000000000..74d9a6d378
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/Straße.xml
@@ -0,0 +1 @@
+<foo></foo>
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings11.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings11.xsl
new file mode 100644
index 0000000000..7d939717af
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings11.xsl
@@ -0,0 +1,7 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="html" />
+
+<xsl:template match="/">
+<xsl:value-of select="document('http://IDontExist/IDontExist.xml', //book)"/>
+</xsl:template>
+</xsl:stylesheet> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings14-inc.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings14-inc.xsl
new file mode 100644
index 0000000000..0b8e95d06f
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings14-inc.xsl
@@ -0,0 +1,7 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:template match="/">
+ <xsl:value-of select="document('http://IDontExist/IDontExist.xml')"/>
+</xsl:template>
+
+</xsl:stylesheet> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings14.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings14.xsl
new file mode 100644
index 0000000000..fb97ffd16b
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings14.xsl
@@ -0,0 +1,4 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:include href="XsltSettings14-inc.xsl"/>
+
+</xsl:stylesheet> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings15.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings15.xsl
new file mode 100644
index 0000000000..1bded055cb
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings15.xsl
@@ -0,0 +1,11 @@
+<!DOCTYPE xsl:stylesheet [
+<!ENTITY doc "document('http://webxtest/testcases/books.xml')">
+]>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="html" />
+
+<xsl:template match="/">
+<xsl:value-of select="&doc;"/>
+</xsl:template>
+
+</xsl:stylesheet> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings9.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings9.xsl
new file mode 100644
index 0000000000..92acf0d1f6
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/XsltSettings9.xsl
@@ -0,0 +1,8 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="html" />
+
+<xsl:template match="/">
+<xsl:value-of select="document('http://IDontExist/IDontExist.xml')//book[1]/title"/>
+</xsl:template>
+</xsl:stylesheet>
+
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/baseline/DefaultResolver.txt b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/baseline/DefaultResolver.txt
new file mode 100644
index 0000000000..45ec8947cd
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/baseline/DefaultResolver.txt
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><result><elem>1</elem><elem>2</elem><elem>3</elem></result> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/coupons.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/coupons.xsl
new file mode 100644
index 0000000000..344bedbe5e
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/coupons.xsl
@@ -0,0 +1,538 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:template match="outcome" mode="oddsTD">
+ <td class="odd">
+ <xsl:apply-templates select="." mode="oddslink" />
+ </td>
+ </xsl:template>
+
+ <xsl:template match="outcome" mode="td">
+ <td>
+ <xsl:value-of select="@desc" />
+ </td>
+ </xsl:template>
+
+ <xsl:template match="outcome" mode="outhead">
+ <td class="outhead">
+ <xsl:value-of select="@desc" />
+ </td>
+ </xsl:template>
+
+ <xsl:template match="*|@*" mode="date">
+ <script language="javascript" type="text/javascript">
+ <![CDATA[displaydate(']]><xsl:value-of select="."/><![CDATA[');]]>
+ </script>
+ </xsl:template>
+
+
+
+ <!-- ==================================================================
+ COUPON - GROUP BY EVENTS
+ STYLE 1
+ =================================================================== -->
+
+ <xsl:template match="event" mode="event1">
+ <xsl:param name="markets" select="market" />
+
+ <div class="temp">
+ group by event style 1
+ </div>
+
+ <table class="coupon">
+ <tr class="title">
+ <th colspan="4">
+ <xsl:value-of select="@desc" /> (event desc - probably not needed)
+ </th>
+ </tr>
+ <xsl:apply-templates select="$markets" mode="event1" />
+ </table>
+ </xsl:template>
+
+
+ <xsl:template match="market" mode="event1">
+ <tr class="subtitle">
+ <th colspan="4">
+ <xsl:value-of select="@desc" />
+ <xsl:apply-templates select="." mode="eachway" />
+ </th>
+ </tr>
+ <xsl:apply-templates select="outcome" mode="event1" />
+ </xsl:template>
+
+
+ <xsl:template match="outcome" mode="event1">
+ <tr>
+ <xsl:choose>
+ <xsl:when test="position() mod 4 = 1">
+ <xsl:attribute name="class">one</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="class">two</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:apply-templates select="." mode="twocells" />
+ <xsl:apply-templates select="following-sibling::outcome[position()=1]" mode="twocells" />
+ </tr>
+ </xsl:template>
+
+ <xsl:template match="outcome[position() mod 2 = 0]" mode="event1">
+ </xsl:template>
+
+ <xsl:template match="outcome" mode="twocells">
+ <xsl:apply-templates select="." mode="td" />
+ <xsl:apply-templates select="." mode="oddsTD" />
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ COUPON - GROUP BY EVENTS
+ DEFAULT STYLE - USED BY 2, 3, 4, 7
+ =================================================================== -->
+
+ <xsl:template match="event" mode="eventdefault">
+ <xsl:param name="markets" select="market" />
+ <xsl:param name="styleID" select="1" />
+
+ <div class="temp">
+ group by event default style (id=<xsl:value-of select="$styleID" />)
+ </div>
+
+ <table class="coupon">
+ <tr class="title">
+ <th>
+ <xsl:attribute name="colspan">
+ <xsl:choose>
+ <xsl:when test="$styleID=3 or $styleID=4">
+ <xsl:text>4</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>3</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+
+ <xsl:value-of select="@compname" />
+ <xsl:text> - </xsl:text>
+ <xsl:value-of select="@desc" />
+ <xsl:text> - </xsl:text>
+ <xsl:apply-templates select="@eventdate" mode="date" />
+ </th>
+ </tr>
+ <xsl:apply-templates select="$markets" mode="eventdefault" />
+ </table>
+ </xsl:template>
+
+
+ <xsl:template match="market" mode="eventdefault">
+ <tr>
+ <xsl:call-template name="cssrowclass" />
+ <td rowspan="2">
+ <xsl:value-of select="@desc" />
+ </td>
+ <xsl:apply-templates select="outcome" mode="outhead" />
+ </tr>
+ <tr>
+ <xsl:call-template name="cssrowclass" />
+ <xsl:apply-templates select="outcome" mode="oddsTD" />
+ </tr>
+ </xsl:template>
+
+
+
+
+
+ <!-- ==================================================================
+ COUPON - GROUP BY MARKETS
+ STYLE 1
+ =================================================================== -->
+
+ <xsl:template match="markettype" mode="market1">
+ <div class="temp">
+ market style 1
+ </div>
+
+ <xsl:if test="@ID = parent::categorygroupmarkets/@selected or parent::categorygroupmarkets/parent::selectedcategory/@typeID != 3">
+ <table class="coupon">
+ <xsl:apply-templates select="parent::categorygroupmarkets /parent::selectedcategory/events/event/market[@typeID=current()/@ID]" mode="market1" />
+ </table>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template match="market" mode="market1">
+ <tr class="title">
+ <th colspan="4">
+ <xsl:value-of select="parent::event/@desc" />
+ </th>
+ </tr>
+ <!-- redirect to the event1 mode -->
+ <xsl:apply-templates select="." mode="event1" />
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ COUPON - GROUP BY MARKETS
+ STYLES 2 AND 3
+ =================================================================== -->
+
+ <xsl:template match="markettype" mode="market2and3">
+ <xsl:param name="morebets" />
+
+ <div class="temp">
+ group by market - style 2 and 3
+ </div>
+
+ <xsl:if test="@ID = parent::categorygroupmarkets/@selected or parent::categorygroupmarkets/parent::selectedcategory/@typeID != 3">
+ <table class="coupon">
+ <xsl:apply-templates select="parent::categorygroupmarkets/parent::selectedcategory/events/event/market[@typeID=current()/@ID]" mode="market2and3">
+ <xsl:with-param name="morebets" select="$morebets" />
+ </xsl:apply-templates>
+ </table>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template match="market" mode="market2and3">
+ <xsl:param name="morebets" />
+
+ <!-- title if needed -->
+ <xsl:if test="position() = 1 or parent::event/@compID != current()/preceding-sibling::market[position()=1]/parent::event/@compID">
+ <tr class="title">
+ <th>
+ <xsl:attribute name="colspan">
+ <xsl:choose>
+ <xsl:when test="@styleID=2">
+ <xsl:text>3</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>4</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:value-of select="parent::event/@compname" />
+ <xsl:text> - </xsl:text>
+ <xsl:value-of select="@desc" />
+ </th>
+ </tr>
+ </xsl:if>
+
+ <!-- events -->
+ <tr>
+ <xsl:call-template name="cssrowclass" />
+ <td rowspan="2">
+ <div class="evname">
+ <xsl:value-of select="parent::event/@desc" />
+ </div>
+ <div class="evdate">
+ <xsl:apply-templates select="parent::event/@date" mode="date" />
+ </div>
+ </td>
+ <xsl:apply-templates select="outcome" mode="outhead" />
+
+ <xsl:if test="$morebets = 1 and parent::event/market[position()=2]">
+ <td rowspan="2" class="morebets">
+ <a href="CategoryPage.aspx?tab={/eventpage/sporttabs/@selected}&amp;evntid={parent::event/@ID}">
+ more bets
+ </a>
+ </td>
+ </xsl:if>
+ </tr>
+ <tr>
+ <xsl:call-template name="cssrowclass" />
+ <xsl:apply-templates select="outcome" mode="oddsTD" />
+ </tr>
+ </xsl:template>
+
+
+
+ <!-- ==================================================================
+ COUPON - GROUP BY MARKETS
+ 1x2 : STYLE 4
+ =================================================================== -->
+
+ <xsl:template match="markettype" mode="market4">
+ <xsl:param name="morebets" />
+
+ <div class="temp">
+ group by market - style 4 (1x2)
+ </div>
+
+ <xsl:if test="@ID = parent::categorygroupmarkets/@selected or parent::categorygroupmarkets/parent::selectedcategory/@typeID != 3">
+
+ <table class="coupon">
+ <xsl:apply-templates select="parent::categorygroupmarkets /parent::selectedcategory/events/event[market/@typeID=current()/@ID]" mode="market4">
+ <xsl:with-param name="morebets" select="$morebets" />
+ <xsl:with-param name="typeID" select="@ID" />
+ </xsl:apply-templates>
+ </table>
+ </xsl:if>
+ </xsl:template>
+
+
+
+ <xsl:template match="event" mode="market4">
+ <xsl:param name="morebets" />
+ <xsl:param name="typeID" />
+
+ <!-- title if needed -->
+ <xsl:if test="position() = 1 or @compID != preceding-sibling::event[position()=1]/@compID">
+ <tr class="title">
+ <th colspan="4">
+ <xsl:value-of select="@compname" />
+ <xsl:text> - </xsl:text>
+ <xsl:value-of select="market[@typeID = $typeID and position() = 1]/@desc" />
+ </th>
+ </tr>
+ <tr class="col">
+ <th>
+ &#160;
+ </th>
+ <th>
+ 1
+ </th>
+ <th>
+ x
+ </th>
+ <th>
+ 2
+ </th>
+ </tr>
+ </xsl:if>
+ <xsl:apply-templates select="market[@typeID = $typeID]" mode="market4">
+ <xsl:with-param name="morebets" select="$morebets" />
+ <xsl:with-param name="pos" select="position()" />
+ </xsl:apply-templates>
+
+ </xsl:template>
+
+
+ <xsl:template match="market" mode="market4">
+ <xsl:param name="morebets" />
+ <xsl:param name="pos" />
+
+ <xsl:variable name="class">
+ <xsl:choose>
+ <xsl:when test="$pos mod 2 = 1">
+ <xsl:text>one</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>two</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- events -->
+ <tr class="{$class}">
+
+ <td rowspan="2">
+ <div class="evname">
+ <xsl:value-of select="parent::event/@desc" />
+ </div>
+ <div class="evdate">
+ <xsl:apply-templates select="parent::event/@date" mode="date" />
+ </div>
+ </td>
+ <xsl:apply-templates select="outcome" mode="outhead" />
+
+ <xsl:if test="$morebets = 1 and parent::event/market[position()=2]">
+ <td rowspan="2" class="morebets">
+ <a href="CategoryPage.aspx?tab={/eventpage/sporttabs/@selected}&amp;evntid={parent::event/@ID}">
+ more bets
+ </a>
+ </td>
+ </xsl:if>
+ </tr>
+ <tr class="{$class}">
+ <xsl:apply-templates select="outcome" mode="oddsTD" />
+ </tr>
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ COUPON - GROUP BY MARKETS
+ US SPORTS TOTALS : STYLE 5
+ =================================================================== -->
+
+ <xsl:template match="markettype" mode="market5">
+ <xsl:param name="morebets" />
+
+ <div class="temp">
+ group by market - style 5 (US Sports totals)
+ </div>
+
+ <xsl:if test="@ID = parent::categorygroupmarkets/@selected or parent::categorygroupmarkets/parent::selectedcategory/@typeID != 3">
+ <table class="coupon">
+ <xsl:apply-templates select="parent::categorygroupmarkets/parent::selectedcategory/events/event/market[@typeID=current()/@ID]" mode="market5">
+ <xsl:with-param name="morebets" select="$morebets" />
+ </xsl:apply-templates>
+ </table>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template match="market" mode="market5">
+ <xsl:param name="morebets" />
+
+ <!-- title if needed -->
+ <xsl:if test="position() = 1 or parent::event/@compID != current()/preceding-sibling::market[position()=1]/parent::event/@compID">
+ <tr class="title">
+ <th colspan="5">
+ <xsl:value-of select="parent::event/@compname" />
+ <xsl:text> - </xsl:text>
+ <xsl:value-of select="@desc" />
+ </th>
+ </tr>
+ <tr class="col">
+ <th>
+ Odds
+ </th>
+ <th colspan="3">
+ &#160;
+ </th>
+ <th>
+ Odds
+ </th>
+ </tr>
+ </xsl:if>
+
+ <!-- events -->
+ <tr>
+ <xsl:call-template name="cssrowclass" />
+
+ <xsl:apply-templates select="outcome[position()=1]" mode="oddsTD" />
+ <xsl:apply-templates select="outcome[position()=1]" mode="td" />
+
+ <td>
+ <div class="evname">
+ <xsl:value-of select="parent::event/@desc" />
+ </div>
+ <div class="evdate">
+ <xsl:apply-templates select="parent::event/@date" mode="date" />
+ </div>
+ </td>
+
+ <xsl:apply-templates select="outcome[position()=2]" mode="td" />
+ <xsl:apply-templates select="outcome[position()=2]" mode="oddsTD" />
+
+ <xsl:if test="$morebets = 1 and parent::event/market[position()=2]">
+ <td class="morebets">
+ <a href="CategoryPage.aspx?tab={/eventpage/sporttabs/@selected}&amp;evntid={parent::event/@ID}">
+ more bets
+ </a>
+ </td>
+ </xsl:if>
+ </tr>
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ COUPON - GROUP BY MARKETS
+ US SPORTS HANDICAP - STYLE 6
+ WIN 2 WAY - STYLE 7
+ =================================================================== -->
+
+ <xsl:template match="markettype" mode="market6and7">
+ <xsl:param name="morebets" />
+
+ <div class="temp">
+ Group by Markets - Style 6 (US Sport Handicap) and Style 7 (Win 2 Way)
+ </div>
+
+ <xsl:if test="@ID = parent::categorygroupmarkets/@selected or parent::categorygroupmarkets/parent::selectedcategory/@typeID != 3">
+ <table class="coupon">
+ <xsl:apply-templates select="parent::categorygroupmarkets /parent::selectedcategory/events/event/market[@typeID=current()/@ID]" mode="market6and7">
+ <xsl:with-param name="morebets" select="$morebets" />
+ </xsl:apply-templates>
+ </table>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template match="market" mode="market6and7">
+ <xsl:param name="morebets" />
+
+ <!-- title if needed -->
+ <xsl:if test="position() = 1 or parent::event/@compID != current()/preceding-sibling::market[position()=1]/parent::event/@compID">
+ <tr class="title">
+ <th>
+ <xsl:attribute name="colspan">
+ <xsl:choose>
+ <xsl:when test="@styleID=6">
+ <xsl:text>5</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>4</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:value-of select="parent::event/@compname" />
+ <xsl:text> - </xsl:text>
+ <xsl:value-of select="@desc" />
+ </th>
+ </tr>
+ <tr class="col">
+ <th>
+ Odds
+ </th>
+ <xsl:choose>
+ <!-- us sport -->
+ <xsl:when test="@styleID = 6">
+ <th>
+ &#160;
+ </th>
+ <th>
+ @
+ </th>
+ <th>
+ &#160;
+ </th>
+ </xsl:when>
+
+ <!-- win 2 way -->
+ <xsl:otherwise>
+ <th colspan="2">
+ &#160;
+ </th>
+ </xsl:otherwise>
+ </xsl:choose>
+ <th>
+ Odds
+ </th>
+ </tr>
+ </xsl:if>
+
+ <!-- events -->
+ <tr>
+ <xsl:call-template name="cssrowclass" />
+
+ <xsl:apply-templates select="outcome[position()=1]" mode="oddsTD" />
+ <td>
+ <div class="evname">
+ <xsl:value-of select="outcome[position()=1]/@desc" />
+ </div>
+ <div class="evdate">
+ <xsl:apply-templates select="parent::event/@date" mode="date" />
+ </div>
+ </td>
+
+ <xsl:if test="@styleID=6">
+ <td>
+ &#160;
+ </td>
+ </xsl:if>
+
+ <xsl:apply-templates select="outcome[position()=2]" mode="td" />
+ <xsl:apply-templates select="outcome[position()=2]" mode="oddsTD" />
+
+ <xsl:if test="$morebets = 1 and parent::event/market[position()=2]">
+ <td class="morebets">
+ <a href="CategoryPage.aspx?tab={/eventpage/sporttabs/@selected}&amp;evntid={parent::event/@ID}">
+ more bets
+ </a>
+ </td>
+ </xsl:if>
+ </tr>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/layout.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/layout.xsl
new file mode 100644
index 0000000000..5c03156f33
--- /dev/null
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/layout.xsl
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes" />
+
+ <xsl:param name="langcode" select="'en'" />
+ <xsl:param name="oddstype" select="2" />
+
+ <xsl:template match="/">
+ <html lang="{$langcode}">
+ <head>
+ <xsl:call-template name="metadata" />
+ <xsl:call-template name="contenttype" />
+ <xsl:call-template name="css" />
+ <xsl:call-template name="extraheader" />
+ </head>
+ <body>
+ <xsl:apply-templates select="/eventpage/sporttabs" mode="tab" />
+ <xsl:apply-templates />
+
+ <div class="temp">
+ Current category type ID = <xsl:value-of select="/eventpage/selectedcategory/@typeID" />
+ </div>
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template name="css">
+ <link href="css/style.css" rel="stylesheet" type="text/css" />
+ </xsl:template>
+
+ <xsl:template name="extraheader">
+ </xsl:template>
+
+ <xsl:template name="metadata">
+ <title>betinternet.com</title>
+ </xsl:template>
+
+ <xsl:template name="contenttype">
+ <xsl:choose>
+ <xsl:when test="$langcode='zh'">
+ <meta http-equiv="Content-Type" content="text/html; charset=big5" />
+ </xsl:when>
+ <xsl:when test="$langcode='th'">
+ <meta http-equiv="Content-Type" content="text/html; charset=tis-620" />
+ </xsl:when>
+ <xsl:when test="$langcode='ja'">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ </xsl:when>
+ <xsl:otherwise>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+
+ <!-- ==================================================================
+ ODDS FORMATTING
+ =================================================================== -->
+ <xsl:template match="*" mode="oddslink">
+ <xsl:param name="num" select="number(@oddsnum)" />
+ <xsl:param name="den" select="number(@oddsden)" />
+
+ <a target="betslip" href="fr_slip.asp?action=add&amp;outcome={@ID}">
+ <xsl:apply-templates select="." mode="odds">
+ <xsl:with-param name="num" select="$num" />
+ <xsl:with-param name="den" select="$den" />
+ </xsl:apply-templates>
+ </a>
+ </xsl:template>
+
+ <xsl:template match="*" mode="odds">
+ <xsl:param name="num" select="number(@oddsnum)" />
+ <xsl:param name="den" select="number(@oddsden)" />
+
+ <xsl:choose>
+
+ <!-- uk odds -->
+ <xsl:when test="$oddstype=1">
+ <xsl:value-of select="concat($num, '/', $den)" />
+ </xsl:when>
+
+ <!-- us odds -->
+ <xsl:when test="$oddstype=3">
+ <xsl:variable name="factor">
+ <xsl:choose>
+ <xsl:when test="$num &gt;= $den">
+ <xsl:value-of select="$num div $den" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="(-1 * ($den div $num))" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="format-number(number($factor), '#,##0.000')" />
+ </xsl:when>
+
+ <!-- european odds -->
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$num = 0 or $den = 0">
+ No Odds
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="format-number(($num div $den) + 1, '#,##0.000')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="cssrowclass">
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 0">
+ <xsl:attribute name="class">one</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="class">two</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- ==================================================================
+ EACH WAY
+ =================================================================== -->
+ <xsl:template match="market" mode="eachway_format">
+ <xsl:param name="caption" />
+
+ <market ID="97933" typeID="106258" styleID="1" desc="Outright Betting" places="4" placingnum="1" placingden="6" />
+
+ <xsl:value-of select="$caption" />
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates select="." mode="odds">
+ <xsl:with-param name="den" select="@placingden" />
+ <xsl:with-param name="num" select="@placingnum" />
+ </xsl:apply-templates>
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="eachwayplace">
+ <xsl:with-param name="currentplace" select="1" />
+ <xsl:with-param name="maxplaces" select="@places" />
+ </xsl:call-template>
+
+ <xsl:value-of select="eachway/eachwayplaces"/>
+ </xsl:template>
+
+
+ <xsl:template name="eachwayplace">
+ <xsl:param name="currentplace" select="1" />
+ <xsl:param name="maxplaces" select="1" />
+
+ <xsl:value-of select="$currentplace" />
+
+ <xsl:if test="$currentplace &lt; $maxplaces">
+ <xsl:text>,</xsl:text>
+ <xsl:call-template name="eachwayplace">
+ <xsl:with-param name="currentplace" select="$currentplace + 1" />
+ <xsl:with-param name="maxplaces" select="$maxplaces" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template match="sporttabs" mode="tab">
+ <div class="sports">
+ <xsl:apply-templates mode="tab" />
+ </div>
+ </xsl:template>
+
+ <xsl:template match="sporttab" mode="tab">
+ <a href="CategoryPage.aspx?tab={@ID}" target="main">
+ <xsl:if test="@ID=parent::sporttabs/@selected">
+ <xsl:attribute name="class">selectedtab</xsl:attribute>
+ </xsl:if>
+ <xsl:value-of select="@desc" />
+ </a>
+ <xsl:text> </xsl:text>
+ </xsl:template>
+
+
+ <!--
+ odds type selector
+ - pass in URL of current page including a ? or ampersand
+ -->
+ <xsl:template name="oddstypes">
+ <xsl:param name="params" />
+ <xsl:variable name="url">
+ <xsl:text>CategoryPage.aspx?tab=</xsl:text>
+ <xsl:value-of select="/eventpage/sporttabs/@selected" />
+ <xsl:text>&amp;</xsl:text>
+ <xsl:value-of select="$params" />
+ <xsl:text>&amp;oddstypeid=</xsl:text>
+ </xsl:variable>
+
+ <div class="oddtype">
+ <xsl:choose>
+ <xsl:when test="$oddstype = 1">
+ <span>Fractional</span>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="{$url}1">Fractional</a>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text> | </xsl:text>
+ <xsl:choose>
+ <xsl:when test="$oddstype = 2">
+ <span>Decimal</span>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="{$url}2">Decimal</a>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text> | </xsl:text>
+ <xsl:choose>
+ <xsl:when test="$oddstype = 3">
+ <span>U.S.</span>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="{$url}3">U.S.</a>
+ </xsl:otherwise>
+ </xsl:choose>
+ </div>
+ </xsl:template>
+
+
+</xsl:stylesheet>
diff --git a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/xmlResolver_document_function_absolute_uri.xsl b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/xmlResolver_document_function_absolute_uri.xsl
index b38664f1f8..855b041e9e 100644
--- a/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/xmlResolver_document_function_absolute_uri.xsl
+++ b/src/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/xmlResolver_document_function_absolute_uri.xsl
@@ -4,7 +4,7 @@
<result>
- <xsl:for-each select="document('c:\\temp\\xmlResolver_document_function.xml')//elem">
+ <xsl:for-each select="document('ABSOLUTE_URI')//elem">
<xsl:value-of select="."/>
</xsl:for-each>
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/Errata4.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/Errata4.cs
index d73e583128..801828a959 100644
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/Errata4.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/Errata4.cs
@@ -4,11 +4,9 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
-using System.Xml;
using System.Xml.Xsl;
using XmlCoreTest.Common;
using OLEDB.Test.ModuleCore;
@@ -122,7 +120,6 @@ namespace System.Xml.Tests
#endregion private const string createElementsXsltInline = ...
- [ActiveIssue(9877)]
//[Variation(Priority = 1, Desc = "Crate elment/attribute :: Invalid start name char", Params = new object[] { false, CharType.NameStartChar })]
[InlineData(false, CharType.NameStartChar)]
//[Variation(Priority = 1, Desc = "Crate elment/attribute :: Invalid name char", Params = new object[] { false, CharType.NameChar })]
@@ -145,6 +142,7 @@ namespace System.Xml.Tests
//[Variation(Priority = 0, Desc = "Crate elment/attribute :: Valid name CharType.NameStartSurrogateLowChar", Params = new object[] { true, CharType.NameStartSurrogateLowChar })]
//[Variation(Priority = 0, Desc = "Crate elment/attribute :: Valid name CharType.NameSurrogateHighChar", Params = new object[] { true, CharType.NameSurrogateHighChar })]
//[Variation(Priority = 0, Desc = "Crate elment/attribute :: Valid name CharType.NameSurrogateLowChar", Params = new object[] { true, CharType.NameSurrogateLowChar })]
+ [OuterLoop]
[Theory]
public void CreateElementsAndAttributesUsingXsltAndXPath(object param0, object param1)
{
@@ -155,7 +153,7 @@ namespace System.Xml.Tests
string charsToChooseFrom = isValidChar ? UnicodeCharHelper.GetValidCharacters(charType) : UnicodeCharHelper.GetInvalidCharacters(charType);
Assert.True(charsToChooseFrom.Length > 0);
- foreach (bool enableDebug in new bool[] { /*true,*/ false }) //ActiveIssue(10023)
+ foreach (bool enableDebug in new bool[] { /*true,*/ false }) // XSLT debugging not supported in Core
{
XslCompiledTransform transf = new XslCompiledTransform(enableDebug);
using (XmlReader r = XmlReader.Create(new StringReader(createElementsXsltAndXpath))) transf.Load(r);
@@ -185,7 +183,6 @@ namespace System.Xml.Tests
return;
}
- [ActiveIssue(9877)]
//[Variation(Priority = 1, Desc = "Crate elment/attribute (Inline) :: Invalid start name char", Params = new object[] { false, CharType.NameStartChar })]
[InlineData(false, CharType.NameStartChar)]
//[Variation(Priority = 1, Desc = "Crate elment/attribute (Inline) :: Invalid name char", Params = new object[] { false, CharType.NameChar })]
@@ -208,6 +205,7 @@ namespace System.Xml.Tests
//[Variation(Priority = 0, Desc = "Crate elment/attribute (Inline) :: Valid name CharType.NameStartSurrogateLowChar", Params = new object[] { true, CharType.NameStartSurrogateLowChar })]
//[Variation(Priority = 0, Desc = "Crate elment/attribute (Inline) :: Valid name CharType.NameSurrogateHighChar", Params = new object[] { true, CharType.NameSurrogateHighChar })]
//[Variation(Priority = 0, Desc = "Crate elment/attribute (Inline) :: Valid name CharType.NameSurrogateLowChar", Params = new object[] { true, CharType.NameSurrogateLowChar })]
+ [OuterLoop]
[Theory]
public void CreateElementsAndAttributesUsingXsltInline(object param0, object param1)
{
@@ -219,7 +217,7 @@ namespace System.Xml.Tests
string charsToChooseFrom = isValidChar ? UnicodeCharHelper.GetValidCharacters(charType) : UnicodeCharHelper.GetInvalidCharacters(charType);
Assert.True(charsToChooseFrom.Length > 0);
- foreach (bool enableDebug in new bool[] { /*true,*/ false }) //ActiveIssue(10023)
+ foreach (bool enableDebug in new bool[] { /*true,*/ false }) // XSLT debugging not supported in Core
{
foreach (string name in FuzzNames(!isValidChar, charType, numOfRepeat))
{
@@ -268,7 +266,6 @@ namespace System.Xml.Tests
}
}
- [ActiveIssue(9877)]
//[Variation(Priority = 1, Desc = "Invalid start name char", Params = new object[] { false, CharType.NameStartChar })]
[InlineData(false, CharType.NameStartChar)]
//[Variation(Priority = 1, Desc = "Invalid name char", Params = new object[] { false, CharType.NameChar })]
@@ -380,7 +377,7 @@ namespace System.Xml.Tests
}
}
- public /*override*/ new int Init(object objParam)
+ public new int Init(object objParam)
{
return 1;
}
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/OutputSettings.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/OutputSettings.cs
index 72b332f6de..710eb6ba2c 100644
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/OutputSettings.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/OutputSettings.cs
@@ -4,10 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System.Globalization;
using System.IO;
-using System.Xml;
-using System.Xml.XmlDiff;
using System.Xml.Xsl;
using System.Text;
@@ -183,7 +180,7 @@ namespace System.Xml.Tests
//[Variation(id = 18, Desc = "Verify Encoding set to windows-1252 explicitly, expected windows-1252", Pri = 1, Params = new object[] { "books.xml", "Encoding4.xsl", "windows-1252", "Encoding must be windows-1252" })]
[InlineData("books.xml", "Encoding4.xsl", "windows-1252", "Encoding must be windows-1252")]
[Theory]
- public void OS6_ActiveIssue9877(object param0, object param1, object param2, object param3)
+ public void OS6_Windows1252Encoding(object param0, object param1, object param2, object param3)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
OS6(param0, param1, param2, param3);
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/Program.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/Program.cs
deleted file mode 100644
index bdf4e94387..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/Program.cs
+++ /dev/null
@@ -1,17 +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 ModuleCore;
-
-namespace XmlTests
-{
- internal class Program
- {
- public static int Main()
- {
- string args = @"DocType:[DOCTYPE] trace:false Host:[Host]";
- return 100 + TestRunner.Execute(args);
- }
- }
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/TempFiles.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/TempFiles.cs
index c1e3ffddd2..c50d590ba3 100644
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/TempFiles.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/TempFiles.cs
@@ -4,444 +4,162 @@
using Xunit;
using Xunit.Abstractions;
-using System;
-using System.CodeDom.Compiler;
using System.IO;
-using System.Xml;
using System.Xml.Xsl;
namespace System.Xml.Tests
{
- // TODO: BinCompat - this is testing API which is currently not available - re-enable if it is back
- // //[TestCase(Name = "TemporaryFiles", Desc = "This testcase tests the Temporary Files property on XslCompiledTransform")]
- // public class TempFiles : XsltApiTestCaseBase2
- // {
- // private XslCompiledTransform _xsl = null;
- // private string _xmlFile = string.Empty;
- // private string _xslFile = string.Empty;
-
- // private ITestOutputHelper _output;
- // public TempFiles(ITestOutputHelper output) : base(output)
- // {
- // _output = output;
- // }
-
- // private void Init(string xmlFile, string xslFile, bool enableDebug)
- // {
- // if (enableDebug)
- // _xsl = new XslCompiledTransform(true);
- // else
- // _xsl = new XslCompiledTransform(false);
-
- // _xmlFile = FullFilePath(xmlFile);
- // _xslFile = FullFilePath(xslFile);
-
- // return;
- // }
-
- // private StringWriter Transform()
- // {
- // StringWriter sw = new StringWriter();
- // _xsl.Transform(_xmlFile, null, sw);
- // return sw;
- // }
-
- // private void VerifyResult(object actual, object expected, string message)
- // {
- // _output.WriteLine("Expected : {0}", expected);
- // _output.WriteLine("Actual : {0}", actual);
-
- // Assert.Equal(actual, expected);
- // }
-
- // private void VerifyResult(bool expression, string message)
- // {
- // Assert.True(expression);
- // }
-
- // //[Variation(id = 1, Desc = "Default value of TemporaryFiles before load, expected null", Pri = 0)]
- // [InlineData()]
- // [Theory]
- // public void TempFiles1()
- // {
- // XslCompiledTransform xslt = new XslCompiledTransform();
- // VerifyResult(xslt.TemporaryFiles, null, "Default value of TemporaryFiles must be null");
- // }
-
- // //[Variation(id = 2, Desc = "TemporaryFiles after load in Retail Mode with no script block, expected count = 0", Pri = 0, Params = new object[] { "books.xml", "NoScripts.xsl", false })]
- // [InlineData("books.xml", "NoScripts.xsl", false, 2)]
- // //[Variation(id = 3, Desc = "TemporaryFiles after load in Debug Mode with no script block, expected count = 0", Pri = 0, Params = new object[] { "books.xml", "NoScripts.xsl", true })]
- // [InlineData("books.xml", "NoScripts.xsl", true, 3)]
- // [Theory]
- // public void TempFiles2(object param0, object param1, object param2, object id)
- // {
- // if (_isInProc && (int)id == 3)
- // return; //TEST_SKIPPED;
-
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
- // _xsl.Load(_xslFile);
-
- // VerifyResult(_xsl.TemporaryFiles.Count, 0, "There should be no temp files generated, when there are no script block");
- // }
-
- // //[Variation(id = 4, Desc = "TemporaryFiles after load in Retail Mode with script block and EnableScript", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", false })]
- // [ActiveIssue(9873)]
- // [InlineData("books.xml", "TempFiles.xsl", false)]
- // [Theory]
- // public void TempFiles3(object param0, object param1, object param2)
- // {
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
-
- // if (_isInProc)
- // return; //TEST_SKIPPED;
-
- // _xsl.Load(_xslFile, new XsltSettings(false, true), new XmlUrlResolver());
-
- // //In retail mode temporary files are not generated if a script block exist
- // VerifyResult(_xsl.TemporaryFiles.Count, 0, "TemporaryFiles generated in retail mode");
- // }
-
- // //[Variation(id = 5, Desc = "TemporaryFiles after load in Debug Mode with script block and EnableScript", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", true })]
- // [ActiveIssue(9873)]
- // [InlineData("books.xml", "TempFiles.xsl", true)]
- // [Theory]
- // public void TempFiles3AndHalf(object param0, object param1, object param2)
- // {
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
-
- // if (_isInProc)
- // return; //TEST_SKIPPED;
-
- // _xsl.Load(_xslFile, new XsltSettings(false, true), new XmlUrlResolver());
-
- // //In debug mode temporary files are generated if a script block exist
- // //An extra .pdb info is generated if debugging is enabled
- // VerifyResult(_xsl.TemporaryFiles.Count > 0, "TemporaryFiles must be generated when there is a script block");
- // }
-
- // //[Variation(id = 6, Desc = "TemporaryFiles after load in retail mode with script block and default settings", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", false })]
- // [InlineData("books.xml", "TempFiles.xsl", false, 6)]
- // //[Variation(id = 7, Desc = "TemporaryFiles after load in debug mode with script block and default settings", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", true })]
- // [InlineData("books.xml", "TempFiles.xsl", true, 7)]
- // [Theory]
- // public void TempFiles4(object param0, object param1, object param2, object id)
- // {
- // if (_isInProc && (int)id == 7)
- // return; //TEST_SKIPPED;
-
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
- // _xsl.Load(_xslFile, XsltSettings.Default, new XmlUrlResolver());
-
- // VerifyResult(_xsl.TemporaryFiles.Count, 0, "TemporaryFiles must not be generated, when XsltSettings is None");
- // }
-
- // //[Variation(id = 8, Desc = "TemporaryFiles after load in retail mode with script block and EnableDocumentFunction", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", false })]
- // [InlineData("books.xml", "TempFiles.xsl", false, 8)]
- // //[Variation(id = 9, Desc = "TemporaryFiles after load in debug mode with script block and EnableDocumentFunction", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", true })]
- // [InlineData("books.xml", "TempFiles.xsl", true, 9)]
- // [Theory]
- // public void TempFiles5(object param0, object param1, object param2, object id)
- // {
- // if (_isInProc && (int)id == 9)
- // return; //TEST_SKIPPED;
-
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
- // _xsl.Load(_xslFile, new XsltSettings(true, false), new XmlUrlResolver());
-
- // VerifyResult(_xsl.TemporaryFiles.Count, 0, "TemporaryFiles must not be generated, when XsltSettings is EnableDocumentFunction alone");
- // }
-
- // //[Variation(id = 10, Desc = "Verify the existence of TemporaryFiles after load in debug mode with script block", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", true })]
- // [ActiveIssue(9873)]
- // [InlineData("books.xml", "TempFiles.xsl", true)]
- // [Theory]
- // public void TempFiles6(object param0, object param1, object param2)
- // {
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
-
- // if (_isInProc)
- // return; //TEST_SKIPPED;
-
- // _xsl.Load(_xslFile, new XsltSettings(false, true), new XmlUrlResolver());
-
- // foreach (string filename in _xsl.TemporaryFiles)
- // {
- // _output.WriteLine(filename);
- // Assert.True(File.Exists(filename)); //Temporary file
- // }
- // return;
- // }
-
- // //[Variation(id = 11, Desc = "Verify if the user can delete the TemporaryFiles after load in debug mode with script block", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", true })]
- // [ActiveIssue(9873)]
- // [InlineData("books.xml", "TempFiles.xsl", true)]
- // [Theory]
- // public void TempFiles7(object param0, object param1, object param2)
- // {
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
-
- // if (_isInProc)
- // return; //Test_SKIPPED;
-
- // _xsl.Load(_xslFile, new XsltSettings(false, true), new XmlUrlResolver());
-
- // TempFileCollection tempFiles = _xsl.TemporaryFiles;
-
- // int fileCount = tempFiles.Count;
- // tempFiles.Delete();
- // fileCount = tempFiles.Count;
-
- // VerifyResult(fileCount, 0, "Temp files could not be deleted");
- // }
-
- // //[Variation(id = 12, Desc = "Verify if the user can rename the TemporaryFiles after load in debug mode with script block", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", true })]
- // [ActiveIssue(9873)]
- // [InlineData("books.xml", "TempFiles.xsl", true)]
- // [Theory]
- // public void TempFiles8(object param0, object param1, object param2)
- // {
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
-
- // if (_isInProc)
- // return; //Test_SKIPPED;
-
- // _xsl.Load(_xslFile, new XsltSettings(false, true), new XmlUrlResolver());
-
- // TempFileCollection tempFiles = _xsl.TemporaryFiles;
-
- // string newfilename = string.Empty;
- // foreach (string filename in tempFiles)
- // {
- // string tempdir = filename.Substring(0, filename.LastIndexOf("\\") + 1);
- // newfilename = tempdir + "new" + filename.Substring(filename.LastIndexOf("\\") + 1);
- // File.Move(filename, newfilename);
- // }
-
- // return;
- // }
-
- // //[Variation(id = 13, Desc = "Verify if the necessary files are generated after load in debug mode with script block", Pri = 1, Params = new object[] { "books.xml", "TempFiles.xsl", true })]
- // [ActiveIssue(9873)]
- // [InlineData("books.xml", "TempFiles.xsl", true)]
- // [Theory]
- // public void TempFiles9(object param0, object param1, object param2)
- // {
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
-
- // if (_isInProc)
- // return; //Test_SKIPPED;
-
- // _xsl.Load(_xslFile, new XsltSettings(false, true), new XmlUrlResolver());
-
- // TempFileCollection tempFiles = _xsl.TemporaryFiles;
- // string filelist = string.Empty;
-
- // foreach (string filename in tempFiles)
- // {
- // filelist += filename.Substring(filename.LastIndexOf("\\") + 1) + ";";
- // }
-
- // _output.WriteLine("Verifying the existence of .dll, .pdb, .err, .out, .cmdline, .cs and .tmp");
- // Assert.True(filelist.IndexOf(".dll") > 0); //Script DLL tempfile is not generated
- // Assert.True(filelist.IndexOf(".pdb") > 0); //Debug info tempfile is not generated
- // Assert.True(filelist.IndexOf(".err") > 0); //Error tempfile is not generated
- // Assert.True(filelist.IndexOf(".out") > 0); //Output tempfile is not generated
- // Assert.True(filelist.IndexOf(".cmdline") > 0); //Command Line tempfile is not generated
- // Assert.True(filelist.IndexOf(".cs") > 0); //CSharp tempfile is not generated
- // Assert.True(filelist.IndexOf(".tmp") > 0); //Tempfile is not generated
-
- // return;
- // }
-
- // //[Variation(id = 14, Desc = "TemporaryFiles after unsuccessful load of an invalid stylesheet in debug mode with script block", Pri = 2, Params = new object[] { "books.xml", "Invalid.xsl", true })]
- // [InlineData("books.xml", "Invalid.xsl", true)]
- // [Theory]
- // public void TempFiles10(object param0, object param1, object param2)
- // {
- // TempFileCollection tempFiles = null;
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
-
- // try
- // {
- // _xsl.Load(_xslFile, new XsltSettings(false, true), new XmlUrlResolver());
- // }
- // catch (XsltException e)
- // {
- // _output.WriteLine(e.ToString());
- // tempFiles = _xsl.TemporaryFiles;
- // }
-
- // VerifyResult(tempFiles, null, "Temporary files must not be generated");
- // }
-
- // //[Variation(id = 15, Desc = "TemporaryFiles after unsuccessful load of a valid stylesheet in debug mode with a missing function in the script block", Pri = 2, Params = new object[] { "books.xml", "InvalidFn.xsl", true })]
- // [ActiveIssue(9873)]
- // [InlineData("books.xml", "InvalidFn.xsl", true)]
- // [Theory]
- // public void TempFiles11(object param0, object param1, object param2)
- // {
- // TempFileCollection tempFiles = null;
- // Init(param0.ToString(), param1.ToString(), (bool)param2);
-
- // if (_isInProc)
- // return; //Test_SKIPPED;
-
- // try
- // {
- // _xsl.Load(_xslFile, new XsltSettings(false, true), new XmlUrlResolver());
- // }
- // catch (XsltException e)
- // {
- // _output.WriteLine(e.ToString());
- // tempFiles = _xsl.TemporaryFiles;
- // }
-
- // VerifyResult(tempFiles != null, "Temporary files should have been generated even when Load() is unsuccessful");
- // }
-
- // //[Variation(Desc = "Load File from a drive c:", Pri = 2)]
- // [InlineData()]
- // [Theory]
- // public void TempFiles12()
- // {
- // if (_isInProc)
- // return; //Test_SKIPPED;
-
- // string childFile = Path.Combine(Directory.GetCurrentDirectory(), "child.xsl");
-
- // string parentString = "<?xml version=\"1.0\"?>"
- // + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">"
- // + "<xsl:import href=\"" + childFile + "\"/>"
- // + "<xsl:output method=\"xml\" omit-xml-declaration=\"yes\" indent=\"yes\"/>"
- // + "<xsl:template match=\"book[@style='autobiography']\">"
- // + "<SPAN style=\"color=blue\">From B<xsl:value-of select=\"name()\"/> : <xsl:value-of select=\"title\"/>"
- // + "</SPAN><br/>"
- // + "<xsl:apply-templates />"
- // + "</xsl:template>"
- // + "<xsl:template match=\"text()\" >"
- // + "</xsl:template>"
- // + "</xsl:stylesheet>";
-
- // string childString = "<?xml version=\"1.0\"?>"
- // + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">"
- // + "<xsl:output method=\"xml\" omit-xml-declaration=\"yes\" indent=\"yes\"/>"
- // + "<xsl:template match=\"book[@style='autobiography']\">"
- // + "<SPAN style=\"color=blue\">From B<xsl:value-of select=\"name()\"/> : <xsl:value-of select=\"title\"/>"
- // + "</SPAN><br/>"
- // + "<xsl:apply-templates />"
- // + "</xsl:template>"
- // + "<xsl:template match=\"text()\" >"
- // + "</xsl:template>"
- // + "</xsl:stylesheet>";
-
- // try
- // {
- // // create a xsl file in current directory on some drive, this is included in XSL above
- // StreamWriter file = new StreamWriter(new FileStream(childFile, FileMode.Create, FileAccess.Write));
- // file.WriteLine(childString);
- // file.Dispose();
- // StreamWriter parentFile = new StreamWriter(new FileStream("parent.xsl", FileMode.Create, FileAccess.Write));
- // parentFile.WriteLine(parentString);
- // parentFile.Dispose();
- // }
- // catch (Exception e)
- // {
- // _output.WriteLine(e.ToString());
- // Assert.True(false);
- // }
-
- // try
- // {
- // // initialize XslCompiledTransform instance
- // _xsl = new XslCompiledTransform();
- //
- // // Now let's load the parent xsl file
- // _xsl.Load("parent.xsl", new XsltSettings(false, true), new XmlUrlResolver());
- // }
- // catch (XsltException e)
- // {
- // _output.WriteLine(e.ToString());
- // Assert.True(false);
- // }
- // return;
- // }
-
- // //[Variation(Desc = "Bug 469775 - XSLT V2 : Exception thrown if xsl:preserve-space/xsl:strip-space is used and input document contains entities", Pri = 2)]
- // [InlineData()]
- // [Theory]
- // public void TempFiles13()
- // {
- // try
- // {
- // XslCompiledTransform xslt = new XslCompiledTransform();
- // xslt.Load(FullFilePath("bug469775.xsl"));
- // Stream res = new MemoryStream();
- // xslt.Transform(new XmlTextReader(FullFilePath("bug469775.xml")), (XsltArgumentList)null, res);
- // _output.WriteLine(res.ToString());
- // }
- // catch (System.Xml.XmlException)
- // {
- // Assert.True(false);
- // }
- // return;
- // }
-
- // //[Variation(Desc = "Bug 469770 - XslCompiledTransform failed to load embedded stylesheets when prefixes are defined outside of xsl:stylesheet element", Pri = 2)]
- // [InlineData()]
- // [Theory]
- // public void TempFiles14()
- // {
- // try
- // {
- // string xsl = "<root xmlns:ns=\"testing\">"
- // + "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
- // + "<xsl:template match=\"/\">"
- // + "<xsl:value-of select=\"ns:test\" />"
- // + "</xsl:template>"
- // + "</xsl:stylesheet>"
- // + "</root>";
-
- // XmlReader r = XmlReader.Create(new StringReader(xsl));
- // while (r.NodeType != XmlNodeType.Element || r.LocalName != "stylesheet")
- // {
- // if (!r.Read())
- // {
- // _output.WriteLine("There is no 'stylesheet' element in the file");
- // Assert.True(false);
- // }
- // }
-
- // XslCompiledTransform t = new XslCompiledTransform();
- // t.Load(r);
- // }
- // catch (XsltException exception)
- // {
- // _output.WriteLine("The following exception should not have been thrown");
- // _output.WriteLine(exception.ToString());
- // Assert.True(false);
- // }
-
- // return;
- // }
-
- // //[Variation(Desc = "Bug 482971 - XslCompiledTransform cannot output numeric character reference after long output", Pri = 2)]
- // [InlineData()]
- // [Theory]
- // public void TempFiles15()
- // {
- // try
- // {
- // XslCompiledTransform xslt = new XslCompiledTransform();
- // xslt.Load(FullFilePath("bug482971.xsl"));
- // xslt.Transform(FullFilePath("bug482971.xml"), "out.txt");
- // }
- // catch (Exception exception)
- // {
- // _output.WriteLine("No exception should not have been thrown");
- // _output.WriteLine(exception.ToString());
- // Assert.True(false);
- // }
- // return;
- // }
- // }
+ //[TestCase(Name = "TemporaryFiles", Desc = "This testcase tests the Temporary Files property on XslCompiledTransform")]
+ public class TempFiles : XsltApiTestCaseBase2
+ {
+ private XslCompiledTransform _xsl = null;
+
+ private ITestOutputHelper _output;
+ public TempFiles(ITestOutputHelper output) : base(output)
+ {
+ _output = output;
+ }
+
+ //[Variation(Desc = "Load File from a drive c:", Pri = 2)]
+ [InlineData()]
+ [Theory]
+ public void TempFiles1()
+ {
+ string childFile = Path.Combine(Directory.GetCurrentDirectory(), "child.xsl");
+
+ string parentString = "<?xml version=\"1.0\"?>"
+ + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">"
+ + "<xsl:import href=\"" + childFile + "\"/>"
+ + "<xsl:output method=\"xml\" omit-xml-declaration=\"yes\" indent=\"yes\"/>"
+ + "<xsl:template match=\"book[@style='autobiography']\">"
+ + "<SPAN style=\"color=blue\">From B<xsl:value-of select=\"name()\"/> : <xsl:value-of select=\"title\"/>"
+ + "</SPAN><br/>"
+ + "<xsl:apply-templates />"
+ + "</xsl:template>"
+ + "<xsl:template match=\"text()\" >"
+ + "</xsl:template>"
+ + "</xsl:stylesheet>";
+
+ string childString = "<?xml version=\"1.0\"?>"
+ + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">"
+ + "<xsl:output method=\"xml\" omit-xml-declaration=\"yes\" indent=\"yes\"/>"
+ + "<xsl:template match=\"book[@style='autobiography']\">"
+ + "<SPAN style=\"color=blue\">From B<xsl:value-of select=\"name()\"/> : <xsl:value-of select=\"title\"/>"
+ + "</SPAN><br/>"
+ + "<xsl:apply-templates />"
+ + "</xsl:template>"
+ + "<xsl:template match=\"text()\" >"
+ + "</xsl:template>"
+ + "</xsl:stylesheet>";
+
+ try
+ {
+ // create a xsl file in current directory on some drive, this is included in XSL above
+ StreamWriter file = new StreamWriter(new FileStream(childFile, FileMode.Create, FileAccess.Write));
+ file.WriteLine(childString);
+ file.Dispose();
+ StreamWriter parentFile = new StreamWriter(new FileStream("parent.xsl", FileMode.Create, FileAccess.Write));
+ parentFile.WriteLine(parentString);
+ parentFile.Dispose();
+ }
+ catch (Exception e)
+ {
+ _output.WriteLine(e.ToString());
+ Assert.True(false);
+ }
+
+ try
+ {
+ // initialize XslCompiledTransform instance
+ _xsl = new XslCompiledTransform();
+
+ // Now let's load the parent xsl file
+ _xsl.Load("parent.xsl", new XsltSettings(false, true), new XmlUrlResolver());
+ }
+ catch (XsltException e)
+ {
+ _output.WriteLine(e.ToString());
+ Assert.True(false);
+ }
+ return;
+ }
+
+ //[Variation(Desc = "Bug 469775 - XSLT V2 : Exception thrown if xsl:preserve-space/xsl:strip-space is used and input document contains entities", Pri = 2)]
+ [InlineData()]
+ [Theory]
+ public void TempFiles2()
+ {
+ try
+ {
+ XslCompiledTransform xslt = new XslCompiledTransform();
+ xslt.Load(FullFilePath("bug469775.xsl"));
+ Stream res = new MemoryStream();
+ xslt.Transform(new XmlTextReader(FullFilePath("bug469775.xml")), (XsltArgumentList)null, res);
+ _output.WriteLine(res.ToString());
+ }
+ catch (System.Xml.XmlException)
+ {
+ Assert.True(false);
+ }
+ return;
+ }
+
+ //[Variation(Desc = "Bug 469770 - XslCompiledTransform failed to load embedded stylesheets when prefixes are defined outside of xsl:stylesheet element", Pri = 2)]
+ [InlineData()]
+ [Theory]
+ public void TempFiles3()
+ {
+ try
+ {
+ string xsl = "<root xmlns:ns=\"testing\">"
+ + "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
+ + "<xsl:template match=\"/\">"
+ + "<xsl:value-of select=\"ns:test\" />"
+ + "</xsl:template>"
+ + "</xsl:stylesheet>"
+ + "</root>";
+
+ XmlReader r = XmlReader.Create(new StringReader(xsl));
+ while (r.NodeType != XmlNodeType.Element || r.LocalName != "stylesheet")
+ {
+ if (!r.Read())
+ {
+ _output.WriteLine("There is no 'stylesheet' element in the file");
+ Assert.True(false);
+ }
+ }
+
+ XslCompiledTransform t = new XslCompiledTransform();
+ t.Load(r);
+ }
+ catch (XsltException exception)
+ {
+ _output.WriteLine("The following exception should not have been thrown");
+ _output.WriteLine(exception.ToString());
+ Assert.True(false);
+ }
+
+ return;
+ }
+
+ //[Variation(Desc = "Bug 482971 - XslCompiledTransform cannot output numeric character reference after long output", Pri = 2)]
+ [InlineData()]
+ [Theory]
+ public void TempFiles4()
+ {
+ try
+ {
+ XslCompiledTransform xslt = new XslCompiledTransform();
+ xslt.Load(FullFilePath("bug482971.xsl"));
+ xslt.Transform(FullFilePath("bug482971.xml"), "out.txt");
+ }
+ catch (Exception exception)
+ {
+ _output.WriteLine("No exception should not have been thrown");
+ _output.WriteLine(exception.ToString());
+ Assert.True(false);
+ }
+ return;
+ }
+ }
} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs
index aa3b8d985f..201d4a7d97 100644
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs
@@ -4,29 +4,21 @@
using Xunit;
using Xunit.Abstractions;
-using System;
-using System.CodeDom.Compiler;
using System.Collections;
using System.Diagnostics;
using System.IO;
-using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Loader;
-using System.Security;
using System.Text;
-using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using XmlCoreTest.Common;
-using System.Collections.Generic;
namespace System.Xml.Tests
{
public class ReflectionTestCaseBase : XsltApiTestCaseBase2
{
- //protected static readonly MethodInfo methCompileToType = GetStaticMethod(typeof(XslCompiledTransform), "CompileToType");
-
private ITestOutputHelper _output;
public ReflectionTestCaseBase(ITestOutputHelper output) : base(output)
{
@@ -47,19 +39,6 @@ namespace System.Xml.Tests
return methInfo;
}
- /*protected static CompilerErrorCollection WCompileToType(
- XmlReader stylesheet,
- XsltSettings settings,
- XmlResolver stylesheetResolver,
- bool debug,
- TypeBuilder typeBuilder,
- string scriptAssemblyPath)
- {
- return XslCompiledTransform.CompileToType(stylesheet, settings, stylesheetResolver, debug, typeBuilder, scriptAssemblyPath);
- //return (CompilerErrorCollection)methCompileToType.Invoke(null,
- // new object[] { stylesheet, settings, stylesheetResolver, debug, typeBuilder, scriptAssemblyPath });
- }*/
-
protected String scriptTestPath = null;
protected String ScriptTestPath
@@ -80,21 +59,6 @@ namespace System.Xml.Tests
}
}
- //protected TypeBuilder ATypeBuilder
- //{
- // get
- // {
- // AppDomain cd = System.Threading.Thread.GetDomain();
- // AssemblyName an = new AssemblyName();
- // an.Name = "HelloClass";
-
- // AssemblyBuilder ab = cd.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
- // ModuleBuilder mb = ab.DefineDynamicModule("HelloModule", "HelloModule.dll", true);
- // TypeBuilder tb = mb.DefineType("Hello", TypeAttributes.Class | TypeAttributes.Public);
- // return tb;
- // }
- //}
-
protected MethodInfo AMethodInfo
{
get
@@ -112,299 +76,7 @@ namespace System.Xml.Tests
protected void WLoad(XslCompiledTransform instance, MethodInfo meth, Byte[] bytes, Type[] types)
{
instance.Load(meth, bytes, types);
- /*
- Type[] paramTypes = new Type[3] { typeof(MethodInfo), typeof(Byte[]), typeof(Type[]) };
-
- MethodInfo m = typeof(XslCompiledTransform).GetMethod("Load",
- BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
- null,
- paramTypes,
- null);
-
- m.Invoke(instance, new Object[] { meth, bytes, types });
- */
- }
-
- protected void TestWLoad(XslCompiledTransform xslt, String asmPath, String type)
- {
- Assembly asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(asmPath);
- Type t = asm.GetType(type);
-
- MethodInfo meth = GetStaticMethod(t, "Execute");
- Byte[] staticData = (Byte[])t.GetTypeInfo().GetField("staticData", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(t);
- Type[] ebTypes = (Type[])t.GetTypeInfo().GetField("ebTypes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(t);
-
- WLoad(xslt, meth, staticData, ebTypes);
- }
- }
-
- //[TestCase(Name = "CompileToType tests", Desc = "This testcase tests XslCompiledTransform private CompileToType method via Reflection. Same method is also exercised by xsltc.exe")]
- public class CCompileToTypeTest : ReflectionTestCaseBase
- {
- private ITestOutputHelper _output;
- public CCompileToTypeTest(ITestOutputHelper output) : base(output)
- {
- _output = output;
}
-
- //BinCompat TODO: Add this test back
- ////[Variation("CompileToType(XmlReader = null)", Pri = 1)]
- //[InlineData()]
- //[Theory]
- //public void Var1()
- //{
- // try
- // {
- // WCompileToType((XmlReader)null, XsltSettings.Default, null, false, ATypeBuilder, String.Empty);
- // }
- // catch (Exception e)
- // {
- // _output.WriteLine(e.ToString());
-
- // if (e is ArgumentNullException || e.InnerException is ArgumentNullException)
- // return;
-
- // _output.WriteLine("Did not throw ArgumentNullException");
- // }
- // Assert.True(false);
- //}
-
- //BinCompat TODO: Add this test back - it might possibly need to be removed - to be investigated
- //[Variation("CompileToType(TypeBuilder= null)", Pri = 1)]
- [InlineData()]
- [Theory]
- public void Var2()
- {
- /*try
- {
- WCompileToType(XmlReader.Create(FullFilePath("identity.xsl")), XsltSettings.Default, null, false, null, String.Empty);
- }
- catch (Exception e)
- {
- _output.WriteLine(e.ToString());
-
- if (e is ArgumentNullException || e.InnerException is ArgumentNullException)
- return;
-
- _output.WriteLine("Did not throw ArgumentNullException");
- }
- Assert.True(false);*/
- }
-
- //BinCompat TODO: Add this test back
- ////[Variation("CompileToType(AsmPath= No Extension file name)", Pri = 1)]
- //[InlineData()]
- //[Theory]
- //public void Var3()
- //{
- // AppDomain cd = System.Threading.Thread.GetDomain();
- // AssemblyName an = new AssemblyName();
- // an.Name = "HelloClass";
-
- // AssemblyBuilder ab = cd.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
- // ModuleBuilder mb = ab.DefineDynamicModule("HelloModule", "HelloModule.dll", true);
- // TypeBuilder tb = mb.DefineType("Hello", TypeAttributes.Class | TypeAttributes.Public);
-
- // try
- // {
- // String xslPath = ScriptTestPath + "Scripting28.xsl";
- // CompilerErrorCollection errors;
- // using (XmlReader reader = XmlReader.Create(xslPath))
- // {
- // errors = WCompileToType(reader, XsltSettings.TrustedXslt, null, false, tb, "ScName");
- // }
-
- // // Print errors and warnings
- // bool hasError = false;
- // foreach (CompilerError error in errors)
- // {
- // _output.WriteLine(error.ToString());
- // hasError = true;
- // }
-
- // if (hasError) Assert.True(false);
- // }
- // catch (Exception e)
- // {
- // _output.WriteLine(e.ToString());
- // Assert.True(false);
- // }
-
- // return;
- //}
-
- //BinCompat TODO: Add this test back
- ////[Variation("CompileToType(Valid case with scripts)", Pri = 1)]
- //[InlineData()]
- //[Theory]
- //public void Var4()
- //{
- // AppDomain cd = System.Threading.Thread.GetDomain();
- // AssemblyName an = new AssemblyName();
- // an.Name = "HelloClass4";
-
- // AssemblyBuilder ab = cd.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
- // ModuleBuilder mb = ab.DefineDynamicModule("HelloModule4", "HelloModule4.dll", true);
- // TypeBuilder tb = mb.DefineType("Hello4", TypeAttributes.Class | TypeAttributes.Public);
-
- // try
- // {
- // String xslPath = ScriptTestPath + "Scripting28.xsl";
- // CompilerErrorCollection errors;
- // using (XmlReader reader = XmlReader.Create(xslPath))
- // {
- // errors = WCompileToType(reader, XsltSettings.TrustedXslt, null, false, tb, "SomeAsm4.dll");
- // }
-
- // // Print errors and warnings
- // bool hasError = false;
- // foreach (CompilerError error in errors)
- // {
- // _output.WriteLine(error.ToString());
- // hasError = true;
- // }
-
- // if (hasError) Assert.True(false);
- // }
- // catch (Exception e)
- // {
- // _output.WriteLine(e.ToString());
- // Assert.True(false);
- // }
-
- // return;
- //}
-
- // Q> In CompileToType when scriptAssemblyPath is null, should we really throw ArgumentNullExc
- // if the stylesheet does not have any scripts (but the settings are enabled)?
- //
- // Anton> Sergey and I think it\92s acceptable behavior. Implementing the other way will require extra
- // code churn in 3 files, which we tried to avoid.
-
- //BinCompat TODO: Add this test back
- ////[Variation("CompileToType(ScriptPath = null, sytlesheet with no scripts)", Pri = 1)]
- //[InlineData()]
- //[Theory]
- //public void Var5()
- //{
- // AppDomain cd = System.Threading.Thread.GetDomain();
- // AssemblyName an = new AssemblyName();
- // an.Name = "HelloClass5";
-
- // AssemblyBuilder ab = cd.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
- // ModuleBuilder mb = ab.DefineDynamicModule("HelloModule5", "HelloModule5.dll", true);
- // TypeBuilder tb = mb.DefineType("Hello5", TypeAttributes.Class | TypeAttributes.Public);
-
- // try
- // {
- // String xslPath = FullFilePath("identity.xsl");
- // CompilerErrorCollection errors;
- // using (XmlReader reader = XmlReader.Create(xslPath))
- // {
- // errors = WCompileToType(reader, XsltSettings.TrustedXslt, null, false, tb, null);
- // }
-
- // // Print errors and warnings
- // bool hasError = false;
- // foreach (CompilerError error in errors)
- // {
- // _output.WriteLine(error.ToString());
- // hasError = true;
- // }
-
- // if (hasError) Assert.True(false);
- // }
- // catch (ArgumentNullException e)
- // {
- // _output.WriteLine(e.ToString());
- // return;
- // }
-
- // Assert.True(false);
- //}
-
- //BinCompat TODO: Add this test back
- //[Variation("CompileToType(ScriptPath = null, stylesheet with scripts)", Pri = 1)]
- //[InlineData()]
- //[Theory]
- //public void Var6()
- //{
- // AppDomain cd = System.Threading.Thread.GetDomain();
- // AssemblyName an = new AssemblyName();
- // an.Name = "HelloClass6";
-
- // AssemblyBuilder ab = cd.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
- // ModuleBuilder mb = ab.DefineDynamicModule("HelloModule6", "HelloModule6.dll", true);
- // TypeBuilder tb = mb.DefineType("Hello6", TypeAttributes.Class | TypeAttributes.Public);
-
- // try
- // {
- // String xslPath = ScriptTestPath + "Scripting28.xsl";
- // CompilerErrorCollection errors;
- // using (XmlReader reader = XmlReader.Create(xslPath))
- // {
- // errors = WCompileToType(reader, XsltSettings.TrustedXslt, null, false, tb, null);
- // }
-
- // // Print errors and warnings
- // bool hasError = false;
- // foreach (CompilerError error in errors)
- // {
- // _output.WriteLine(error.ToString());
- // hasError = true;
- // }
-
- // if (hasError) Assert.True(false);
- // }
- // catch (Exception e)
- // {
- // _output.WriteLine(e.ToString());
- // return;
- // }
-
- // Assert.True(false);
- //}
-
- //BinCompat TODO: Add this test back
- // //[Variation("CompileToType(ScriptPath = null, XsltSettings = null)", Pri = 1)]
- // [InlineData()]
- // [Theory]
- // public void Var7()
- // {
- // AppDomain cd = System.Threading.Thread.GetDomain();
- // AssemblyName an = new AssemblyName();
- // an.Name = "HelloClass7";
-
- // AssemblyBuilder ab = cd.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
- // ModuleBuilder mb = ab.DefineDynamicModule("HelloModule7", "HelloModule7.dll", true);
- // TypeBuilder tb = mb.DefineType("Hello7", TypeAttributes.Class | TypeAttributes.Public);
-
- // try
- // {
- // CompilerErrorCollection errors;
- // using (XmlReader reader = XmlReader.Create(FullFilePath("identity.xsl")))
- // {
- // errors = WCompileToType(reader, null, null, false, tb, null);
- // }
-
- // // Print errors and warnings
- // bool hasError = false;
- // foreach (CompilerError error in errors)
- // {
- // _output.WriteLine(error.ToString());
- // hasError = true;
- // }
-
- // if (!hasError) return;
- // }
- // catch (Exception e)
- // {
- // _output.WriteLine(e.ToString());
- // Assert.True(false);
- // }
-
- // Assert.True(false);
- // }
}
//[TestCase(Name = "Load(MethodInfo, ByteArray, TypeArray) tests", Desc = "This testcase tests private Load method via Reflection. This method is used by sharepoint")]
@@ -459,167 +131,6 @@ namespace System.Xml.Tests
}
Assert.True(false);
}
-
- //[Variation("Valid Load after error case Load(MethodInfo, ByteArray, TypeArray)", Pri = 1)]
- [ActiveIssue(9988)]
- [InlineData()]
- [Theory]
- public void Var3()
- {
- // BinCompat TODO: rewrite this test so that it does not load xsl from dll
- Assert.True(false);
-
- //XslCompiledTransform xslt = new XslCompiledTransform();
- //try
- //{
- // //error case
- // WLoad(xslt, AMethodInfo, new Byte[5], null);
- //}
- //catch (Exception e)
- //{
- // /*
- // * Anton> If staticData array is malformed, you end up with weird exceptions.
- // * We didn\92t expect this method to be public and didn\92t implement any range/sanity
- // * checks in deserialization code path, besides CLR implicit range checks for array indices.
- // * You have found one such place, but there are dozens of them. Fixing all of them will cause
- // * code churn in many files and another round of [code review/test sign-off/approval] process.
- // * Right now it works according to the \93Garbage In, Garbage Out\94 principle.
- // *
- // */
- // _output.WriteLine(e.ToString());
- //}
-
- //String asmPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\bftBaseLine.dll");
- //String type = "bftBaseLine";
- //String xml = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\sft1.xml");
- //TestWLoad(xslt, Path.GetFullPath(asmPath), type);
- //xslt.Transform(xml, "errout.txt");
- //return;
- }
-
- //[Variation("Multiple Loads Load(MethodInfo, ByteArray, TypeArray)", Pri = 1)]
- [ActiveIssue(9988)]
- [InlineData()]
- [Theory]
- public void Var7()
- {
- // BinCompat TODO: rewrite this test so that it does not load xsl from dll
- Assert.True(false);
-
- /*XslCompiledTransform xslt = new XslCompiledTransform();
-
- String asmPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\bftBaseLine.dll");
- String type = "bftBaseLine";
- String xml = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\sft1.xml");
-
- Assembly asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath(asmPath));
- Type t = asm.GetType(type);
-
- MethodInfo meth = GetStaticMethod(t, "Execute");
- Byte[] staticData = (Byte[])t.GetTypeInfo().GetField("staticData", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(t);
- Type[] ebTypes = (Type[])t.GetTypeInfo().GetField("ebTypes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(t);
-
- asmPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\Scripting28.dll");
- type = "Scripting28";
-
- asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath(asmPath));
- t = asm.GetType(type);
-
- MethodInfo meth2 = GetStaticMethod(t, "Execute");
- Byte[] staticData2 = (Byte[])t.GetTypeInfo().GetField("staticData", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(t);
- Type[] ebTypes2 = (Type[])t.GetTypeInfo().GetField("ebTypes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(t);
-
- for (int i = 0; i < 100; i++)
- {
- WLoad(xslt, meth, staticData, ebTypes);
- WLoad(xslt, meth2, staticData2, ebTypes2);
- xslt.Transform(xml, "out.txt");
- xslt.Transform(xml, "out1.txt");
- }
-
- return;*/
- }
-
- //[Variation("Load(MethodInfo, ByteArray, TypeArray) simple assembly", Pri = 1)]
- [ActiveIssue(9988)]
- [InlineData()]
- [Theory]
- public void Var4()
- {
- // BinCompat TODO: rewrite this test so that it does not load xsl from dll
- Assert.True(false);
-
- /*XslCompiledTransform xslt = new XslCompiledTransform();
- String asmPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\bftBaseLine.dll");
- String type = "bftBaseLine";
- String xml = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\sft1.xml");
-
- try
- {
- TestWLoad(xslt, Path.GetFullPath(asmPath), type);
- xslt.Transform(xml, "out.txt");
- return;
- }
- catch (Exception e)
- {
- _output.WriteLine(e.ToString());
- }
- Assert.True(false);*/
- }
-
- //[Variation("Load(MethodInfo, ByteArray, TypeArray) assembly with scripts", Pri = 1)]
- [ActiveIssue(9988)]
- [InlineData()]
- [Theory]
- public void Var5()
- {
- // BinCompat TODO: rewrite this test so that it does not load xsl from dll
- Assert.True(false);
-
- /*XslCompiledTransform xslt = new XslCompiledTransform();
- String asmPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\Scripting28.dll");
- String type = "Scripting28";
- String xml = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\sft1.xml");
-
- try
- {
- TestWLoad(xslt, Path.GetFullPath(asmPath), type);
- xslt.Transform(xml, "out.txt");
- return;
- }
- catch (Exception e)
- {
- _output.WriteLine(e.ToString());
- }
- Assert.True(false);*/
- }
-
- //[Variation("Load(MethodInfo, ByteArray, TypeArray) old xsltc assembly", Pri = 1)]
- [ActiveIssue(9988)]
- [InlineData()]
- [Theory]
- public void Var6()
- {
- // BinCompat TODO: rewrite this test so that it does not load xsl from dll
- Assert.True(false);
-
- /*XslCompiledTransform xslt = new XslCompiledTransform();
- String asmPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\CTT1.dll");
- String type = "CCT1";
- String xml = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\sft1.xml");
-
- try
- {
- TestWLoad(xslt, Path.GetFullPath(asmPath), type);
- xslt.Transform(xml, "out.txt");
- return;
- }
- catch (Exception e)
- {
- _output.WriteLine(e.ToString());
- }
- Assert.True(false);*/
- }
}
//[TestCase(Name = "Null argument tests", Desc = "This testcase passes NULL arguments to all XslCompiledTransform methods")]
@@ -988,15 +499,16 @@ namespace System.Xml.Tests
{
_output = output;
}
-
//[Variation(id = 1, Desc = "Set XmlResolver property to null, load style sheet with import/include, should not affect transform")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void XmlResolver1()
+ public void XmlResolver1(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL("XmlResolver_Main.xsl", null);
+ LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType, null);
Assert.True(false);
}
catch (XsltException e1)
@@ -1007,24 +519,26 @@ namespace System.Xml.Tests
catch (ArgumentNullException e2)
{
_output.WriteLine(e2.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
}
//[Variation(id = 2, Desc = "Set XmlResolver property to null, load style sheet with document function, should not resolve during load")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void XmlResolver2()
+ public void XmlResolver2(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL("XmlResolver_Main.xsl", null);
+ LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType, null);
_output.WriteLine("No exception was thrown");
Assert.True(false);
}
@@ -1036,27 +550,36 @@ namespace System.Xml.Tests
catch (ArgumentNullException e2)
{
_output.WriteLine(e2.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
}
//[Variation(id = 3, Desc = "Default XmlResolver, load style sheet with document function, should resolve during transform", Pri = 1, Param = "DefaultResolver.txt")]
- [ActiveIssue(9876)]
- [InlineData("DefaultResolver.txt")]
+ [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void XmlResolver3(object param)
+ public void XmlResolver3(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
string Baseline = Path.Combine("baseline", (string)param);
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", xslInputType, readerType) == 1)
{
- if (Transform("fruits.xml") == 1)
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1070,50 +593,51 @@ namespace System.Xml.Tests
Assert.True(false);
}
- /*
- //[Variation("Set to NULL many times in a loop, then to proper cred.")]
- [InlineData()]
- [Theory]
- public void XmlResolver6()
- {
- // Skip this test for Load(URI)
- // Reason: When style sheet URI = Intranet zone, XmlSecureResolver does not resolve document function
-
- if(LoadXSL("xmlResolver_cred.xsl") == TEST_PASS)
- {
- for(int i=0; i<100; i++)
- xslt.XmlResolver = null;
-
- for(int i=0; i<100; i++)
- xslt.XmlResolver = GetDefaultCredResolver();
-
- if ((Transform("fruits.xml") == TEST_PASS) && (CheckResult(377.8217373898) == TEST_PASS))
- return;
- else
- {
- _output.WriteLine("Failed to use XmlResolver property to resolve document function");
- Assert.True(false);
- }
- }
- else
- {
- _output.WriteLine("Failed to load style sheet!");
- Assert.True(false);
- }
- }
- */
-
//[Variation(id = 7, Desc = "document() has absolute URI", Pri = 0)]
- [ActiveIssue(9876)]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void XmlResolver7()
+ public void XmlResolver7(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>123</result>";
+
+ // copy file on the local machine
+ try
+ {
+ string tempPath = Path.GetTempPath();
+ string testFile = Path.Combine(tempPath, "xmlResolver_document_function.xml");
+ if (File.Exists(testFile))
+ {
+ File.SetAttributes(testFile, FileAttributes.Normal);
+ File.Delete(testFile);
+ }
+ string xmlFile = FullFilePath("xmlResolver_document_function.xml");
+ File.Copy(xmlFile, testFile, true);
+ }
+ catch (Exception e)
+ {
+ _output.WriteLine(e.ToString());
+ _output.WriteLine("Could not copy file to local. Some other issues prevented this test from running");
+ return; //TEST_SKIPPED;
+ }
+
// copy file on the local machine (this is now done with createAPItestfiles.js, see Oasys scenario.)
- if (LoadXSL("xmlResolver_document_function_absolute_uri.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function_absolute_uri.xsl", xslInputType, readerType) == 1)
{
- if ((Transform("fruits.xml") == 1) && (CheckResult(377.8217373898) == 1))
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
else
{
_output.WriteLine("Failed to resolve document function with absolute URI.");
@@ -1153,17 +677,18 @@ namespace System.Xml.Tests
}
//[Variation(id = 1, Desc = "Call Load with null value")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric1()
+ public void LoadGeneric1(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL(null);
+ LoadXSL(null, xslInputType, readerType);
}
catch (System.ArgumentException)
{
- // System.Xml.XmlUrlResolver.ResolveUri(Uri baseUri, String relativeUri) throws System.ArgumentException here for null
return;
}
_output.WriteLine("Exception not generated for null parameter name");
@@ -1171,21 +696,29 @@ namespace System.Xml.Tests
}
//[Variation(id = 2, Desc = "Load with valid, then invalid, then valid again")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void LoadGeneric2()
+ public void LoadGeneric2(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
try
{
- LoadXSL("IDontExist.xsl");
+ LoadXSL("IDontExist.xsl", xslInputType, readerType);
}
catch (System.IO.FileNotFoundException)
{
try
{
- Transform("fruits.xml");
+ Transform((string) "fruits.xml", (OutputType) outputType, navType);
}
catch (System.InvalidOperationException e)
{
@@ -1203,18 +736,26 @@ namespace System.Xml.Tests
}
//[Variation(id = 3, Desc = "Load an invalid, then a valid and transform", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
- [Theory]
- public void LoadGeneric3(object param)
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric3(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
try
{
- LoadXSL("IDontExist.xsl");
+ LoadXSL("IDontExist.xsl", xslInputType, readerType);
}
catch (System.IO.FileNotFoundException)
{
- if ((LoadXSL("showParam.xsl") == 1) && (Transform("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1225,31 +766,39 @@ namespace System.Xml.Tests
}
//[Variation(id = 4, Desc = "Call several overloaded functions", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
- [Theory]
- public void LoadGeneric4(object param)
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric4(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
- if (MyXslInputType() != XslInputType.Reader)
- LoadXSL("showParamLongName.xsl", XslInputType.Reader, new XmlUrlResolver());
- if (MyXslInputType() != XslInputType.URI)
- LoadXSL("showParamLongName.xsl", XslInputType.URI, new XmlUrlResolver());
- if (MyXslInputType() != XslInputType.Navigator)
- LoadXSL("showParamLongName.xsl", XslInputType.Navigator, new XmlUrlResolver());
-
- if ((LoadXSL("showParam.xsl") == 0) || (Transform("fruits.xml") == 0))
+ if (xslInputType != XslInputType.Reader)
+ LoadXSL("showParamLongName.xsl", XslInputType.Reader, readerType, new XmlUrlResolver());
+ if (xslInputType != XslInputType.URI)
+ LoadXSL("showParamLongName.xsl", XslInputType.URI, readerType, new XmlUrlResolver());
+ if (xslInputType != XslInputType.Navigator)
+ LoadXSL("showParamLongName.xsl", XslInputType.Navigator, readerType, new XmlUrlResolver());
+
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 0) || (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 0))
Assert.True(false);
VerifyResult(Baseline, _strOutFile);
- if (MyXslInputType() != XslInputType.Navigator)
- LoadXSL("showParamLongName.xsl", XslInputType.Navigator, new XmlUrlResolver());
- if (MyXslInputType() != XslInputType.URI)
- LoadXSL("showParamLongName.xsl", XslInputType.URI, new XmlUrlResolver());
- if (MyXslInputType() != XslInputType.Reader)
- LoadXSL("showParamLongName.xsl", XslInputType.Reader, new XmlUrlResolver());
+ if (xslInputType != XslInputType.Navigator)
+ LoadXSL("showParamLongName.xsl", XslInputType.Navigator, readerType, new XmlUrlResolver());
+ if (xslInputType != XslInputType.URI)
+ LoadXSL("showParamLongName.xsl", XslInputType.URI, readerType, new XmlUrlResolver());
+ if (xslInputType != XslInputType.Reader)
+ LoadXSL("showParamLongName.xsl", XslInputType.Reader, readerType, new XmlUrlResolver());
- if ((LoadXSL("showParam.xsl") == 1) && (Transform("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1259,20 +808,28 @@ namespace System.Xml.Tests
}
//[Variation(id = 5, Desc = "Call same overloaded Load() many times then transform", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
- [Theory]
- public void LoadGeneric5(object param)
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric5(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
for (int i = 0; i < 100; i++)
{
- if (LoadXSL("showParam.xsl") != 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) != 1)
{
_output.WriteLine("Failed to load stylesheet showParam.xsl on the {0} attempt", i);
Assert.True(false);
}
}
- if ((LoadXSL("showParam.xsl") == 1) && (Transform("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1282,13 +839,15 @@ namespace System.Xml.Tests
}
//[Variation(id = 6, Desc = "Call load with non-existing stylesheet")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric6()
+ public void LoadGeneric6(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL("IDontExist.xsl");
+ LoadXSL("IDontExist.xsl", xslInputType, readerType);
}
catch (System.IO.FileNotFoundException)
{
@@ -1299,19 +858,29 @@ namespace System.Xml.Tests
}
//[Variation(id = 7, Desc = "Verify that style sheet is closed properly after Load - Shared Read Access")]
- [InlineData()]
- [Theory]
- public void LoadGeneric7()
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric7(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
FileStream s2;
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
// check immediately after load and after transform
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType) == 1)
{
s2 = new FileStream(FullFilePath("XmlResolver_Main.xsl"), FileMode.Open, FileAccess.Read, FileShare.Read);
s2.Dispose();
- if ((Transform("fruits.xml") == 1) && (CheckResult(428.8541842246) == 1))
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
+ VerifyResult(expected);
s2 = new FileStream(FullFilePath("XmlResolver_Main.xsl"), FileMode.Open, FileAccess.Read, FileShare.Read);
s2.Dispose();
return;
@@ -1320,46 +889,30 @@ namespace System.Xml.Tests
Assert.True(false);
}
- /*
- //[Variation(id =8, Desc ="Verify that style sheet is closed properly after Load - ReadWrite Access")]
- [InlineData()]
- [Theory]
- public void LoadGeneric8()
- {
- FileStream s2;
-
- // check immediately after load and after transform
-
- if(LoadXSL("XmlResolver_Main.xsl") == TEST_PASS)
- {
- s2 = new FileStream(FullFilePath("XmlResolver_Main.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
- if((Transform("fruits.xml") == TEST_PASS) && (CheckResult(428.8541842246)== TEST_PASS))
- {
- s2 = new FileStream(FullFilePath("XmlResolver_Main.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
- return;
- }
- }
- _output.WriteLine("Appeared to not close style sheet file properly after loading.");
- Assert.True(false);
- }
- */
-
//[Variation(id = 9, Desc = "Verify that included files are closed properly after Load - Read Access")]
- [InlineData()]
- [Theory]
- public void LoadGeneric9()
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric9(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
FileStream s2;
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
// check immediately after load and after transform
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType) == 1)
{
s2 = new FileStream(FullFilePath("XmlResolver_Sub.xsl"), FileMode.Open, FileAccess.Read);
s2.Dispose();
- if ((Transform("fruits.xml") == 1) && (CheckResult(428.8541842246) == 1))
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
+ VerifyResult(expected);
s2 = new FileStream(FullFilePath("XmlResolver_Include.xsl"), FileMode.Open, FileAccess.Read, FileShare.Read);
s2.Dispose();
return;
@@ -1369,64 +922,54 @@ namespace System.Xml.Tests
Assert.True(false);
}
- /*
- //[Variation(id =10, Desc ="Verify that included files are closed properly after Load - ReadWrite Access")]
- [InlineData()]
- [Theory]
- public void LoadGeneric10()
- {
- FileStream s2;
-
- // check immediately after load and after transform
- if(LoadXSL("XmlResolver_Main.xsl") == TEST_PASS)
- {
- s2 = new FileStream(FullFilePath("XmlResolver_sub.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
- if((Transform("fruits.xml") == TEST_PASS) && (CheckResult(428.8541842246)== TEST_PASS))
- {
- s2 = new FileStream(FullFilePath("XmlResolver_Include.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
- return;
- }
- }
- _output.WriteLine("Appeared to not close file properly after loading.");
- Assert.True(false);
- }
- */
-
//[Variation(id = 11, Desc = "Load stylesheet with entity reference: Bug #68450 ")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void LoadGeneric11()
- {
- if (MyDocType().ToString() == "DataDocument")
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric11(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
+ {
+ if (navType.ToString() == "DataDocument")
// Skip the test for DataDocument
return;
else
{
- if (LoadXSL("books_entity_ref.xsl", XslInputType.Reader, new XmlUrlResolver()) != 1)
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><Book>
+ Name
+ </Book>";
+
+ if (LoadXSL("books_entity_ref.xsl", XslInputType.Reader, readerType, new XmlUrlResolver()) != 1)
{
_output.WriteLine("Failed to load stylesheet books_entity_ref.xsl");
Assert.True(false);
}
- if ((LoadXSL("books_entity_ref.xsl") == 1) && (Transform("books_entity_ref.xml") == 1)
- && (CheckResult(371.4148215954) == 1))
+ if ((LoadXSL("books_entity_ref.xsl", xslInputType, readerType) == 1) && (Transform((string) "books_entity_ref.xml", (OutputType) outputType, navType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
}
//[Variation(id = 12, Desc = "Load with invalid stylesheet and verify that file is closed properly")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric12()
+ public void LoadGeneric12(XslInputType xslInputType, ReaderType readerType)
{
Stream strmTemp;
try
{
- int i = LoadXSL("xslt_error.xsl");
+ int i = LoadXSL("xslt_error.xsl", xslInputType, readerType);
}
catch (XsltException)
{
@@ -1473,13 +1016,15 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null source value and null resolver")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric1()
+ public void LoadGeneric1(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver(null, null);
+ LoadXSL_Resolver(null, xslInputType, readerType, null);
}
catch (System.ArgumentNullException e)
{
@@ -1491,13 +1036,15 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null source value and valid resolver")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric2()
+ public void LoadGeneric2(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver(null, new XmlUrlResolver());
+ LoadXSL_Resolver(null, xslInputType, readerType, new XmlUrlResolver());
}
catch (System.ArgumentNullException e)
{
@@ -1509,39 +1056,49 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null XmlResolver, style sheet does not have include/import, URI should throw ArgumentNullException and the rest shouldn't error", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
- [Theory]
- public void LoadGeneric3(object param)
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric3(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
try
{
- LoadXSL_Resolver("showParam.xsl", null);
- Transform("fruits.xml");
+ LoadXSL_Resolver("showParam.xsl", xslInputType, readerType, null);
+ Transform((string) "fruits.xml", (OutputType) outputType, navType);
VerifyResult(Baseline, _strOutFile);
return;
}
catch (ArgumentNullException e)
{
_output.WriteLine(e.ToString());
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
}
//[Variation("Call Load with null XmlResolver and stylesheet has import/include, URI should throw ArgumentNullException, rest throw XsltException")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric4()
+ public void LoadGeneric4(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver("XmlResolver_Main.xsl", null);
+ LoadXSL_Resolver("XmlResolver_Main.xsl", xslInputType, readerType, null);
_output.WriteLine("No exception was thrown when a null resolver is passed");
Assert.True(false);
}
@@ -1553,26 +1110,28 @@ namespace System.Xml.Tests
catch (ArgumentNullException e2)
{
_output.WriteLine(e2.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
}
//[Variation("Call Load with null custom resolver and style sheet has import/include, should throw Exception")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric5()
+ public void LoadGeneric5(XslInputType xslInputType, ReaderType readerType)
{
CustomNullResolver myResolver = new CustomNullResolver(_output);
try
{
- LoadXSL_Resolver("XmlResolver_Main.xsl", myResolver);
+ LoadXSL_Resolver("XmlResolver_Main.xsl", xslInputType, readerType, myResolver);
_output.WriteLine("No exception is thrown");
Assert.True(false);
}
@@ -1584,76 +1143,94 @@ namespace System.Xml.Tests
catch (ArgumentNullException e2)
{
_output.WriteLine(e2.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
catch (XmlException e3)
{
_output.WriteLine(e3.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("XmlException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("XmlException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
}
//[Variation("Call Load with null custom resolver and style sheet has no import/include, should error for URI only", Param = "ShowParam.txt")]
- [InlineData("showParam.txt")]
- [Theory]
- public void LoadGeneric6(object param)
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric6(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
CustomNullResolver myResolver = new CustomNullResolver(_output);
try
{
- LoadXSL_Resolver("showParam.xsl", myResolver);
- Transform("fruits.xml");
+ LoadXSL_Resolver("showParam.xsl", xslInputType, readerType, myResolver);
+ Transform((string) "fruits.xml", (OutputType) outputType, navType);
VerifyResult(Baseline, _strOutFile);
return;
}
catch (ArgumentNullException e)
{
_output.WriteLine(e.ToString());
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
catch (XsltException e3)
{
_output.WriteLine(e3.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("XmlException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("XmlException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
}
//[Variation("Style sheet has import/include, call Load first with custom null resolver and then default resolver, should not fail", Param = "XmlResolverTestMain.txt")]
- [InlineData("XmlResolverTestMain.txt")]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void LoadGeneric7(object param)
+ public void LoadGeneric7(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
+
string Baseline = Path.Combine("baseline", (string)param);
CustomNullResolver myResolver = new CustomNullResolver(_output);
try
{
- LoadXSL_Resolver("XmlResolver_Main.xsl", myResolver);
+ LoadXSL_Resolver("XmlResolver_Main.xsl", xslInputType, readerType, myResolver);
}
//For input types != URI
catch (System.Xml.Xsl.XsltException e1)
@@ -1669,10 +1246,13 @@ namespace System.Xml.Tests
CheckExpectedError(e1, "System.Xml", "Xslt_CannotLoadStylesheet", new string[] { new Uri(Uri.UriSchemeFile + Uri.SchemeDelimiter + Path.GetFullPath(FullFilePath("XmlResolver_Main.xsl"))).ToString(), "null" });
}
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType) == 1)
{
- if ((Transform("fruits.xml") == 1) && (CheckResult(428.8541842246) == 1))
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -1695,9 +1275,9 @@ namespace System.Xml.Tests
CheckExpectedError(e2, "System.Xml", "Xslt_CannotLoadStylesheet", new string[] { new Uri(Uri.UriSchemeFile + Uri.SchemeDelimiter + Path.GetFullPath(FullFilePath("XmlResolver_Main.xsl"))).ToString(), "null" });
}
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType) == 1)
{
- if (Transform("fruits.xml") == 1)
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1714,11 +1294,11 @@ namespace System.Xml.Tests
catch (XmlException e3)
{
_output.WriteLine(e3.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("XmlException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("XmlException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
@@ -1727,18 +1307,26 @@ namespace System.Xml.Tests
}
//[Variation("Style sheet has import/include, call Load first with default resolver and then with custom null resolver, should fail", Param = "XmlResolverTestMain.txt")]
- [InlineData("XmlResolverTestMain.txt")]
- [Theory]
- public void LoadGeneric8(object param)
+ [InlineData("XmlResolverTestMain.txt", XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader)]
+ [Theory]
+ public void LoadGeneric8(object param, XslInputType xslInputType, ReaderType readerType)
{
string Baseline = Path.Combine("baseline", (string)param);
CustomNullResolver myResolver = new CustomNullResolver(_output);
- if ((LoadXSL("XmlResolver_Main.xsl") == 1))
+ if ((LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType) == 1))
{
try
{
- LoadXSL_Resolver("XmlResolver_Main.xsl", myResolver);
+ LoadXSL_Resolver("XmlResolver_Main.xsl", xslInputType, readerType, myResolver);
}
catch (System.Xml.Xsl.XsltException e1)
{
@@ -1759,22 +1347,22 @@ namespace System.Xml.Tests
catch (ArgumentNullException e2)
{
_output.WriteLine(e2.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
catch (XmlException e3)
{
_output.WriteLine(e3.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("XmlException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("XmlException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
@@ -1786,15 +1374,27 @@ namespace System.Xml.Tests
}
//[Variation("Load with resolver with credentials, then load XSL that does not need cred.")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void LoadGeneric9()
+ public void LoadGeneric9(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
- if ((LoadXSL_Resolver("XmlResolver_Main.xsl", GetDefaultCredResolver()) == 1))
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
+
+ if ((LoadXSL_Resolver("XmlResolver_Main.xsl", xslInputType, readerType, GetDefaultCredResolver()) == 1))
{
- if ((LoadXSL("XmlResolver_Main.xsl") == 1) && (Transform("fruits.xml") == 1)
- && (CheckResult(428.8541842246) == 1))
+ if ((LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType) == 1) && (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
}
else
{
@@ -1804,35 +1404,16 @@ namespace System.Xml.Tests
Assert.True(false);
}
- /* This test doesn't make sense coz loading a stylesheet with null resolver will throw ArgumentNullException
- //[Variation("Call Load() many times with null resolver then perform a transform")]
- [InlineData()]
- [Theory]
- public void LoadGeneric10()
- {
- for(int i=0; i < 100; i++)
- {
- if(LoadXSL_Resolver("showParam.xsl", null) != TEST_PASS)
- {
- _output.WriteLine("Failed to load stylesheet showParam.xsl on the {0} attempt", i);
- Assert.True(false);
- }
- }
- if((LoadXSL_Resolver("showParam.xsl", null) == TEST_PASS) && (Transform("fruits.xml") == TEST_PASS)
- && (VerifyResult(Baseline, _strOutFile)== TEST_PASS))
- return;
- Assert.True(false);
- }
- */
-
//[Variation("Call Load with null Resolver, file does not exist")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric11()
+ public void LoadGeneric11(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver("IDontExist.xsl", null);
+ LoadXSL_Resolver("IDontExist.xsl", xslInputType, readerType, null);
_output.WriteLine("No exception was thrown");
Assert.True(false);
}
@@ -1844,52 +1425,15 @@ namespace System.Xml.Tests
catch (ArgumentNullException e2)
{
_output.WriteLine(e2.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
}
-
- /* This test doesn't make sense anymore coz passing null resolver throws ArgumentNullException
- * right on the first Load on showParam.xsl
- *
- //[Variation("Load non existing stylesheet with null resolver and try to transform")]
- [InlineData()]
- [Theory]
- public void LoadGeneric12()
- {
- if(LoadXSL_Resolver("showParam.xsl", null) == TEST_PASS)
- {
- try
- {
- LoadXSL_Resolver("IDontExist.xsl", null);
- }
- catch(System.IO.FileNotFoundException)
- {
- //no stylesheet loaded, should throw error
- try
- {
- Transform("fruits.xml");
- }
- catch(System.InvalidOperationException e2)
- {
- return CheckExpectedError(e2, "system.xml", "Xslt_NoStylesheetLoaded", new string[] { "IDontExist.xsl" });
- }
- }
- _output.WriteLine("Exception not generated for non-existent file parameter name");
- }
- else
- {
- _output.WriteLine("Errors loading initial file");
- Assert.True(false);
- }
- Assert.True(false);
- }
- */
}
/***********************************************************/
@@ -1909,15 +1453,17 @@ namespace System.Xml.Tests
}
//[Variation("Basic check for usage of credentials on resolver, load XSL that needs cred. with correct resolver", Param = "XmlResolverTestMain.txt")]
- [InlineData("XmlResolverTestMain.txt")]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("XmlResolverTestMain.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void LoadUrlResolver1(object param)
+ public void LoadUrlResolver1(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
// XsltResolverTestMain.xsl is placed in IIS virtual directory
// which requires integrated Windows NT authentication
string Baseline = Path.Combine("baseline", (string)param);
- if ((LoadXSL_Resolver(Path.Combine("XmlResolver", "XmlResolverTestMain.xsl"), GetDefaultCredResolver()) == 1) &&
- (Transform("fruits.xml") == 1))
+ if ((LoadXSL_Resolver(Path.Combine("XmlResolver", "XmlResolverTestMain.xsl"), xslInputType, readerType, GetDefaultCredResolver()) == 1) &&
+ (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1927,13 +1473,13 @@ namespace System.Xml.Tests
}
//[Variation("Load XSL that needs cred. with null resolver, should fail", Param = "XmlResolverTestMain.txt")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrlResolver2()
+ public void LoadUrlResolver2(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver(Path.Combine("XmlResolver", "XmlResolverTestMain.xsl"), null);
+ LoadXSL_Resolver(Path.Combine("XmlResolver", "XmlResolverTestMain.xsl"), xslInputType, readerType, null);
}
catch (XsltException e)
{
@@ -1945,13 +1491,13 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null source value")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrlResolver3()
+ public void LoadUrlResolver3(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver(null, new XmlUrlResolver());
+ LoadXSL_Resolver(null, xslInputType, readerType, new XmlUrlResolver());
}
catch (ArgumentNullException e)
{
@@ -1963,92 +1509,6 @@ namespace System.Xml.Tests
}
}
- /****************************************************************************************/
- /* XslCompiledTransform.Load(Reader/Navigator,XmlResolver,Evidence) - Integrity */
- /****************************************************************************************/
-
- //[TestCase(Name = "XslCompiledTransform.Load(,XmlResolver,Evidence) : Reader, Reader", Desc = "READER,READER")]
- //[TestCase(Name = "XslCompiledTransform.Load(,XmlResolver,Evidence) : Reader, Stream", Desc = "READER,STREAM")]
- //[TestCase(Name = "XslCompiledTransform.Load(,XmlResolver,Evidence) : Reader, Writer", Desc = "READER,WRITER")]
- //[TestCase(Name = "XslCompiledTransform.Load(,XmlResolver,Evidence) : Reader, TextWriter", Desc = "READER,TEXTWRITER")]
- //[TestCase(Name = "XslCompiledTransform.Load(,XmlResolver,Evidence) : Navigator, Reader", Desc = "NAVIGATOR,READER")]
- //[TestCase(Name = "XslCompiledTransform.Load(,XmlResolver,Evidence) : Navigator, Stream", Desc = "NAVIGATOR,STREAM")]
- //[TestCase(Name = "XslCompiledTransform.Load(,XmlResolver,Evidence) : Navigator, Writer", Desc = "NAVIGATOR,WRITER")]
- //[TestCase(Name = "XslCompiledTransform.Load(,XmlResolver,Evidence) : Navigator, TextWriter", Desc = "NAVIGATOR,TEXTWRITER")]
- public class CLoadReaderResolverEvidenceTest : XsltApiTestCaseBase2
- {
- private ITestOutputHelper _output;
- public CLoadReaderResolverEvidenceTest(ITestOutputHelper output) : base(output)
- {
- _output = output;
- }
-
- // TODO: BinCompat - add this test back if Evidence is back
- //[Variation("Call Load with null source value, null evidence")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void LoadGeneric1()
- {
- /*
- try
- {
- LoadXSL_Resolver_Evidence(null, new XmlUrlResolver(), null);
- }
- catch (ArgumentNullException e)
- {
- _output.WriteLine(e.ToString());
- return;
- }
- _output.WriteLine("Passing null stylesheet parameter should have thrown ArgumentNullException");
- Assert.True(false);*/
- }
-
- //[Variation("Call Load with style sheet that has script, pass null evidence, should throw security exception")]
- [InlineData()]
- [Theory]
- public void LoadGeneric2()
- {
- /*
- try
- {
- LoadXSL_Resolver_Evidence("scripting_unsafe_object.xsl", new XmlUrlResolver(), null);
- }
- catch(System.Security.Policy.PolicyException e)
- {
- _output.WriteLine(e.ToString());
- return;
- }
- _output.WriteLine("Did not throw a security exception for null evidence!");
- Assert.True(false);
- */
- return; //TEST_SKIPPED;
- }
-
- //BinCompat TODO: Add this test back
- ////[Variation("Call Load with style sheet that has script, pass correct evidence")]
- //[InlineData()]
- //[Theory]
- //public void LoadGeneric3()
- //{
- // if (_isInProc)
- // return; //TEST_SKIPPED;
-
- // Evidence evidence = new Evidence();
- // evidence.AddHost(new Zone(SecurityZone.MyComputer));
- // try
- // {
- // LoadXSL_Resolver_Evidence("scripting_unsafe_object.xsl", new XmlUrlResolver(), evidence);
- // }
- // catch (System.Security.Policy.PolicyException)
- // {
- // _output.WriteLine("Should not throw a security exception for correct evidence!");
- // Assert.True(false);
- // }
- // return;
- //}
- }
-
/***********************************************************/
/* XslCompiledTransform.Load(Url) */
/***********************************************************/
@@ -2063,20 +1523,20 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with an invalid uri")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl1()
+ public void LoadUrl1(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL("IDontExist.xsl", XslInputType.URI, new XmlUrlResolver());
+ LoadXSL("IDontExist.xsl", XslInputType.URI, readerType, new XmlUrlResolver());
_output.WriteLine("No exception was thrown");
Assert.True(false);
}
catch (FileNotFoundException e1)
{
_output.WriteLine(e1.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
@@ -2087,28 +1547,27 @@ namespace System.Xml.Tests
catch (ArgumentNullException e2)
{
_output.WriteLine(e2.Message);
- if (MyXslInputType() == XslInputType.URI)
+ if (xslInputType == XslInputType.URI)
return;
else
{
- _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + MyXslInputType() + "'");
+ _output.WriteLine("ArgumentNullException is not supposed to be thrown for the input type '" + xslInputType + "'");
Assert.True(false);
}
}
}
//[Variation("Load file with empty string")]
- [InlineData()]
+ [InlineData(ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl2()
+ public void LoadUrl2(ReaderType readerType)
{
try
{
- LoadXSL(szEmpty, XslInputType.URI, new XmlUrlResolver());
+ LoadXSL(szEmpty, XslInputType.URI, readerType, new XmlUrlResolver());
}
catch (System.ArgumentException)
{
- // System.Xml.XmlUrlResolver.ResolveUri(Uri baseUri, String relativeUri) throws ArgumentException
return;
}
_output.WriteLine("Exception not generated for an empty string filename");
@@ -2116,13 +1575,13 @@ namespace System.Xml.Tests
}
//[Variation("Load with \".\"")]
- [InlineData()]
+ [InlineData(ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl3()
+ public void LoadUrl3(ReaderType readerType)
{
try
{
- LoadXSL(".", XslInputType.URI, new XmlUrlResolver());
+ LoadXSL(".", XslInputType.URI, readerType, new XmlUrlResolver());
}
catch (System.UnauthorizedAccessException)
{
@@ -2133,13 +1592,13 @@ namespace System.Xml.Tests
}
//[Variation("Load with \"..\"")]
- [InlineData()]
+ [InlineData(ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl()
+ public void LoadUrl(ReaderType readerType)
{
try
{
- LoadXSL("..", XslInputType.URI, new XmlUrlResolver());
+ LoadXSL("..", XslInputType.URI, readerType, new XmlUrlResolver());
}
catch (System.UnauthorizedAccessException)
{
@@ -2151,60 +1610,21 @@ namespace System.Xml.Tests
//[Variation("Load with \"\\\\\"")]
[PlatformSpecific(TestPlatforms.Windows)] //Not an invalid path on Unix
- [InlineData()]
+ [InlineData(ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl5()
+ public void LoadUrl5(ReaderType readerType)
{
try
{
- LoadXSL("\\\\", XslInputType.URI, new XmlUrlResolver());
+ LoadXSL("\\\\", XslInputType.URI, readerType, new XmlUrlResolver());
}
catch (System.ArgumentException)
{
- // System.Xml.XmlUrlResolver.ResolveUri(Uri baseUri, String relativeUri) throws ArgumentException
return;
}
_output.WriteLine("Exception not generated for non-existent file parameter name");
Assert.True(false);
}
-
- /*
-
- //[Variation("Call Load with style sheet that has script, pass Url which does not have correct evidence, should fail")]
- [InlineData()]
- [Theory]
- public void LoadUrl6()
- {
- try
- {
- LoadXSL_Resolver(FullHttpPath("XmlResolver/scripting_unsafe_object.xsl"), GetDefaultCredResolver());
- }
- catch(System.Security.Policy.PolicyException)
- {
- return;
- }
- _output.WriteLine("Should throw a security exception for incorrect evidence!");
- Assert.True(false);
- }
-
- //[Variation("Call Load with style sheet that has script, pass Url which has correct evidence, should pass")]
- [InlineData()]
- [Theory]
- public void LoadUrl7()
- {
- try
- {
- LoadXSL("scripting_unsafe_object.xsl");
- }
- catch(System.Security.Policy.PolicyException)
- {
- _output.WriteLine("Should not throw a security exception for correct evidence!");
- Assert.True(false);
- }
- return;
- }
-
- */
}
/***********************************************************/
@@ -2221,9 +1641,9 @@ namespace System.Xml.Tests
}
//[Variation("Basic Verification Test", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void LoadNavigator1(object param)
+ public void LoadNavigator1(object param, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
xslt = new XslCompiledTransform();
@@ -2237,7 +1657,7 @@ namespace System.Xml.Tests
xrLoad.Dispose();
xslt.Load(xdTemp);
- if (Transform("fruits.xml") == 1)
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2246,9 +1666,9 @@ namespace System.Xml.Tests
}
//[Variation("Create Navigator and navigate away from root", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void LoadNavigator2(object param)
+ public void LoadNavigator2(object param, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
xslt = new XslCompiledTransform();
@@ -2260,7 +1680,7 @@ namespace System.Xml.Tests
xP.MoveToNext();
xslt.Load(xP);
- if (Transform("fruits.xml") == 1)
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2269,20 +1689,19 @@ namespace System.Xml.Tests
}
//[Variation("Basic check for usage of credentials on resolver, load XSL that needs cred. with correct resolver", Param = "XmlResolverTestMain.txt")]
- [InlineData("XmlResolverTestMain.txt")]
+ [InlineData("XmlResolverTestMain.txt", OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void LoadNavigator3(object param)
+ public void LoadNavigator3(object param, OutputType outputType, NavType navType)
{
xslt = new XslCompiledTransform();
string Baseline = Path.Combine("baseline", (string)param);
XmlReader xrLoad = XmlReader.Create(FullFilePath(Path.Combine("XmlResolver", "XmlResolverTestMain.xsl")));
- //xrLoad.XmlResolver = GetDefaultCredResolver();
XPathDocument xdTemp = new XPathDocument(xrLoad, XmlSpace.Preserve);
XPathNavigator xP = ((IXPathNavigable)xdTemp).CreateNavigator();
xslt.Load(xP, XsltSettings.TrustedXslt, GetDefaultCredResolver());
- if (Transform("fruits.xml") == 1)
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2291,29 +1710,29 @@ namespace System.Xml.Tests
}
//[Variation("Regression case for bug 80768")]
- [ActiveIssue(9873)]
[InlineData()]
[Theory]
public void LoadNavigator4()
{
- if (_isInProc)
- return; //TEST_SKIPPED;
+ var e = Assert.ThrowsAny<XsltException>(() =>
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><out>You are safe</out>";
- xslt = new XslCompiledTransform();
- XmlReader xrLoad = XmlReader.Create(FullFilePath("Bug80768.xsl"));
- XPathDocument xd = new XPathDocument(xrLoad, XmlSpace.Preserve);
+ xslt = new XslCompiledTransform();
+ XmlReader xrLoad = XmlReader.Create(FullFilePath("Bug80768.xsl"));
+ XPathDocument xd = new XPathDocument(xrLoad, XmlSpace.Preserve);
- xslt.Load(xd, XsltSettings.TrustedXslt, new XmlUrlResolver());
+ xslt.Load(xd, XsltSettings.TrustedXslt, new XmlUrlResolver());
- FileStream fs = new FileStream(_strOutFile, FileMode.Create, FileAccess.ReadWrite);
- XPathNavigator xn = new MyNavigator(FullFilePath("foo.xml"));
- xslt.Transform(xn, null, fs);
- fs.Dispose();
+ FileStream fs = new FileStream(_strOutFile, FileMode.Create, FileAccess.ReadWrite);
+ XPathNavigator xn = new MyNavigator(FullFilePath("foo.xml"));
+ xslt.Transform(xn, null, fs);
+ fs.Dispose();
- if (CheckResult(383.0855503831) == 1)
- return;
- else
- Assert.True(false);
+ VerifyResult(expected);
+ });
+
+ Assert.Equal("Compiling JScript/CSharp scripts is not supported", e.InnerException.Message);
}
}
@@ -2331,9 +1750,9 @@ namespace System.Xml.Tests
}
//[Variation("Basic Verification Test", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void LoadXmlReader1(object param)
+ public void LoadXmlReader1(object param, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
Boolean fTEST_FAIL = false;
@@ -2360,7 +1779,7 @@ namespace System.Xml.Tests
}
if (fTEST_FAIL)
Assert.True(false);
- if (Transform("fruits.xml") == 1)
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2522,18 +1941,18 @@ namespace System.Xml.Tests
}
//[Variation("Basic check for usage of credentials on resolver, load XSL that needs cred. with correct resolver", Param = "XmlResolverTestMain.txt")]
- [InlineData("XmlResolverTestMain.txt")]
+ [InlineData("XmlResolverTestMain.txt", OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void LoadXmlReader7(object param)
+ public void LoadXmlReader7(object param, OutputType outputType, NavType navType)
{
xslt = new XslCompiledTransform();
string Baseline = Path.Combine("baseline", (string)param);
XmlReader xrLoad = XmlReader.Create(FullFilePath(Path.Combine("XmlResolver", "XmlResolverTestMain.xsl")));
- //xrLoad.XmlResolver = GetDefaultCredResolver();
+
xslt.Load(xrLoad, XsltSettings.TrustedXslt, GetDefaultCredResolver());
xrLoad.Dispose();
- if (Transform("fruits.xml") == 1)
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2546,7 +1965,7 @@ namespace System.Xml.Tests
[Theory]
public void Bug380138()
{
- string xsl = @"<?xml version='1.0' encoding='utf-8'?>
+ string xsl = @"<?xml version=""1.0"" encoding=""utf-8""?>
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:ms='urn:schemas-microsoft-com:xslt' exclude-result-prefixes='ms'>
<xsl:template match='asf'><xsl:value-of select=""ms:namespace-uri('ms:b')""/></xsl:template>
@@ -2726,12 +2145,20 @@ namespace System.Xml.Tests
}
//[Variation("Basic Verification Test", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
- [Theory]
- public void TransformGeneric1(object param)
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric1(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2741,14 +2168,22 @@ namespace System.Xml.Tests
}
//[Variation("Load and Transform multiple times", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
- [Theory]
- public void TransformGeneric2(object param)
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric2(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
for (int i = 0; i < 5; i++)
{
- if ((LoadXSL("showParam.xsl") != 1) || (Transform("fruits.xml") != 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) != 1) || (Transform((string) "fruits.xml", (OutputType) outputType, navType) != 1))
Assert.True(false);
VerifyResult(Baseline, _strOutFile);
@@ -2757,16 +2192,24 @@ namespace System.Xml.Tests
}
//[Variation("Load once, Transform many times", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
- [Theory]
- public void TransformGeneric3(object param)
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric3(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
for (int i = 0; i < 100; i++)
{
- if (Transform("fruits.xml") != 1)
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) != 1)
{
_output.WriteLine("Test failed to transform after {0} iterations", i);
Assert.True(false);
@@ -2779,14 +2222,16 @@ namespace System.Xml.Tests
}
//[Variation("Call Transform without loading")]
- [InlineData()]
+ [InlineData(OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void TransformGeneric4()
+ public void TransformGeneric4(OutputType outputType, NavType navType)
{
xslt = new XslCompiledTransform();
try
{
- Transform("fruits.xml");
+ Transform((string) "fruits.xml", (OutputType) outputType, navType);
}
catch (System.InvalidOperationException e)
{
@@ -2798,13 +2243,21 @@ namespace System.Xml.Tests
}
//[Variation("Closing XSL and XML files used in transform, Read access")]
- [InlineData()]
- [Theory]
- public void TransformGeneric5()
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric5(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
FileStream s2;
- if ((LoadXSL("showParam.xsl") == 1) && (Transform("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1))
{
s2 = new FileStream(FullFilePath("showParam.xsl"), FileMode.Open, FileAccess.Read);
s2.Dispose();
@@ -2818,41 +2271,23 @@ namespace System.Xml.Tests
Assert.True(false);
}
- /*
- //[Variation("Closing XSL and XML files used in transform, ReadWrite access")]
- [InlineData()]
- [Theory]
- public void TransformGeneric6()
- {
- FileStream s2;
-
- if((LoadXSL("showParam.xsl") == TEST_PASS) && (Transform("fruits.xml") == TEST_PASS))
- {
- s2 = new FileStream(FullFilePath("showParam.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
-
- s2 = new FileStream(FullFilePath("fruits.xml"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
-
- return;
- }
- _output.WriteLine("Encountered errors performing transform and could not verify if files were closed");
- Assert.True(false);
- }
- */
-
//[Variation("Bug20003707 - InvalidProgramException for 2.0 stylesheets in forwards-compatible mode")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void TransformGeneric7()
+ public void TransformGeneric7(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
- if (_isInProc)
- return; //TEST_SKIPPED;
-
try
{
- LoadXSL("ForwardComp.xsl");
- Transform("data.xml");
+ LoadXSL("ForwardComp.xsl", xslInputType, readerType);
+ Transform((string) "data.xml", (OutputType) outputType, navType);
}
catch (XsltException e)
{
@@ -2875,17 +2310,22 @@ namespace System.Xml.Tests
}
//[Variation("Bug378293 - Incorrect error message when an attribute is added to a root node")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void TransformGeneric9()
+ public void TransformGeneric9(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
- if (_isInProc)
- return; //TEST_SKIPPED;
-
try
{
- LoadXSL("RootNodeAtt.xsl");
- Transform("data.xml");
+ LoadXSL("RootNodeAtt.xsl", xslInputType, readerType);
+ Transform((string) "data.xml", (OutputType) outputType, navType);
}
catch (XsltException e)
{
@@ -2910,17 +2350,22 @@ namespace System.Xml.Tests
}
//[Variation("Bug369463 - Invalid XPath exception in forward compatibility mode should render lineNumber linePosition")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void TransformGeneric11()
+ public void TransformGeneric11(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
- if (_isInProc)
- return; //TEST_SKIPPED;
-
try
{
- LoadXSL("Bug369463.xsl");
- Transform("data.xml");
+ LoadXSL("Bug369463.xsl", xslInputType, readerType);
+ Transform((string) "data.xml", (OutputType) outputType, navType);
}
catch (XsltException e)
{
@@ -2957,16 +2402,29 @@ namespace System.Xml.Tests
}
//[Variation("Pass null XmlResolver, load style sheet with import/include, should not affect transform")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void XmlResolver1()
+ public void XmlResolver1(XslInputType xslInputType , ReaderType readerType, OutputType outputType, NavType navType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
+
try
{
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType) == 1)
{
- if ((TransformResolver("fruits.xml", null) == 1) && (CheckResult(428.8541842246) == 1))
+ if (TransformResolver("fruits.xml", outputType, navType, null) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -2980,18 +2438,27 @@ namespace System.Xml.Tests
}
//[Variation("Pass null XmlResolver, load style sheet with document function, should not resolve during transform", Param = "xmlResolver_document_function.txt")]
- [ActiveIssue(9876)]
- [InlineData("xmlResolver_document_function.txt")]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void XmlResolver2(object param)
+ public void XmlResolver2(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
string Baseline = Path.Combine("baseline", (string)param);
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", xslInputType, readerType) == 1)
{
- if (TransformResolver("fruits.xml", null) == 1)
+ if (TransformResolver("fruits.xml", outputType, navType, null) == 1)
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3006,17 +2473,26 @@ namespace System.Xml.Tests
}
//[Variation("Default XmlResolver, load style sheet with document function, should resolve during transform", Param = "DefaultResolver.txt")]
- [ActiveIssue(9876)]
- [InlineData("DefaultResolver.txt")]
+ [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("DefaultResolver.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void XmlResolver3(object param)
+ public void XmlResolver3(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
string Baseline = Path.Combine("baseline", (string)param);
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", xslInputType, readerType) == 1)
{
- if (Transform("fruits.xml") == 1)
+ if (Transform((string) "fruits.xml", (OutputType) outputType, navType) == 1)
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3031,16 +2507,27 @@ namespace System.Xml.Tests
}
//[Variation("document() has absolute URI")]
- [ActiveIssue(9876)]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void XmlResolver5()
+ public void XmlResolver5(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>123</result>";
+
// copy file on the local machine
try
{
- string curDir = Directory.GetCurrentDirectory();
- string testFile = Path.Combine(curDir, "xmlResolver_document_function.xml");
+ string tempPath = Path.GetTempPath();
+ string testFile = Path.Combine(tempPath, "xmlResolver_document_function.xml");
if (File.Exists(testFile))
{
File.SetAttributes(testFile, FileAttributes.Normal);
@@ -3056,10 +2543,13 @@ namespace System.Xml.Tests
return; //TEST_SKIPPED;
}
- if (LoadXSL("xmlResolver_document_function_absolute_uri.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function_absolute_uri.xsl", xslInputType, readerType) == 1)
{
- if ((TransformResolver("fruits.xml", new XmlUrlResolver()) == 1) && (CheckResult(377.8217373898) == 1))
+ if (TransformResolver("fruits.xml", outputType, navType, new XmlUrlResolver()) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
else
{
_output.WriteLine("Failed to resolve document function with absolute URI.");
@@ -3074,13 +2564,21 @@ namespace System.Xml.Tests
}
//[Variation("Pass null resolver but stylesheet doesn't have any include/imports")]
- [InlineData()]
- [Theory]
- public void XmlResolver7()
- {
- LoadXSL("Bug382198.xsl");
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [Theory]
+ public void XmlResolver7(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
+ {
+ LoadXSL("Bug382198.xsl", xslInputType, readerType);
// Pass null
- TransformResolver("fruits.xml", null);
+ TransformResolver("fruits.xml", outputType, navType, null);
return;
}
}
@@ -3101,14 +2599,16 @@ namespace System.Xml.Tests
}
//[Variation("Basic Verification Test", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr1(object param)
+ public void TransformStrStr1(object param, XslInputType xslInputType, ReaderType readerType)
{
string Baseline = Path.Combine("baseline", (string)param);
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
xslt.Transform(szFullFilename, _strOutFile);
VerifyResult(Baseline, _strOutFile);
@@ -3118,11 +2618,13 @@ namespace System.Xml.Tests
}
//[Variation("Input is null")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr2()
+ public void TransformStrStr2(XslInputType xslInputType, ReaderType readerType)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
try
{
@@ -3136,13 +2638,15 @@ namespace System.Xml.Tests
}
//[Variation("Output file is null")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr3()
+ public void TransformStrStr3(XslInputType xslInputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
try
{
@@ -3158,11 +2662,13 @@ namespace System.Xml.Tests
}
//[Variation("Input is nonexisting file")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr4()
+ public void TransformStrStr4(XslInputType xslInputType, ReaderType readerType)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
try
{
@@ -3179,13 +2685,15 @@ namespace System.Xml.Tests
//[Variation("Output file is invalid")]
[PlatformSpecific(TestPlatforms.Windows)] //Output file name is valid on Unix
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr5()
+ public void TransformStrStr5(XslInputType xslInputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
try
{
@@ -3201,11 +2709,13 @@ namespace System.Xml.Tests
}
//[Variation("Input is empty string")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr6()
+ public void TransformStrStr6(XslInputType xslInputType, ReaderType readerType)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
try
{
@@ -3221,13 +2731,15 @@ namespace System.Xml.Tests
}
//[Variation("Output file is empty string")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr7()
+ public void TransformStrStr7(XslInputType xslInputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
try
{
@@ -3243,16 +2755,18 @@ namespace System.Xml.Tests
}
//[Variation("Call Transform many times", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr8(object param)
+ public void TransformStrStr8(object param, XslInputType xslInputType, ReaderType readerType)
{
string Baseline = Path.Combine("baseline", (string)param);
String szFullFilename = FullFilePath("fruits.xml");
for (int i = 0; i < 50; i++)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
xslt.Transform(szFullFilename, _strOutFile);
VerifyResult(Baseline, _strOutFile);
@@ -3283,11 +2797,13 @@ namespace System.Xml.Tests
}
//[Variation("Output to unreachable destination")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr10()
+ public void TransformStrStr10(XslInputType xslInputType, ReaderType readerType)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
try
{
@@ -3304,12 +2820,14 @@ namespace System.Xml.Tests
}
//[Variation("Input filename is \'.\', \'..\', and \'\\\\\'")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr11()
+ public void TransformStrStr11(XslInputType xslInputType, ReaderType readerType)
{
int iCount = 0;
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
SetExpectedError("Xml_ResolveUrl");
try
@@ -3348,13 +2866,15 @@ namespace System.Xml.Tests
}
//[Variation("Output filename is \'.\' and \'..\'")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr12()
+ public void TransformStrStr12(XslInputType xslInputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
int iCount = 0;
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
try
{
@@ -3383,13 +2903,15 @@ namespace System.Xml.Tests
//[Variation("Output filename is \'\\\\\'")]
[PlatformSpecific(TestPlatforms.Windows)]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr12_win()
+ public void TransformStrStr12_win(XslInputType xslInputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
Assert.Throws<System.ArgumentException>(() => xslt.Transform(szFullFilename, "\\\\"));
return;
@@ -3400,14 +2922,16 @@ namespace System.Xml.Tests
}
//[Variation("Closing files after transform")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr13()
+ public void TransformStrStr13(XslInputType xslInputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
Stream strmTemp;
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", xslInputType, readerType) == 1)
{
xslt.Transform(szFullFilename, _strOutFile);
StreamReader fs = null;
@@ -3430,29 +2954,6 @@ namespace System.Xml.Tests
}
Assert.True(false);
}
-
- /*
- //[Variation("Transform(test.xml, test.xml)")]
- [InlineData()]
- [Theory]
- public void TransformStrStr14()
- {
- String szFullFilename = FullFilePath("Bug75295.xml");
-
- // Copy this file to current directory
- File.Delete("out.xml");
- File.Copy(szFullFilename, "out.xml");
-
- if(LoadXSL("Bug75295.xsl") == TEST_PASS)
- {
- xslt.Transform("out.xml", "out.xml");
-
- if (CheckResult(270.5223692973) == TEST_PASS)
- return;
- }
- Assert.True(false);
- }
- */
}
/***********************************************************/
@@ -3471,73 +2972,75 @@ namespace System.Xml.Tests
}
//[Variation("Pass null XmlResolver to Transform, load style sheet with import/include, should not affect transform")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStrResolver1()
+ public void TransformStrStrResolver1(XslInputType xslInputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
- try
- {
- if (LoadXSL("XmlResolver_Main.xsl", new XmlUrlResolver()) == 1)
- {
- XmlTextReader xr = new XmlTextReader(szFullFilename);
- XmlTextWriter xw = new XmlTextWriter("out.xml", Encoding.Unicode);
- xslt.Transform(xr, null, xw, null);
- xr.Dispose();
- xw.Dispose();
- if (CheckResult(403.7784431795) == 1)
- return;
- else
- Assert.True(false);
- }
- }
- catch (Exception e)
+ string expected = @"<result>
+ <fruit>Apple</fruit>
+ <fruit>orange</fruit>
+</result>";
+
+ if (LoadXSL("XmlResolver_Main.xsl", xslInputType, readerType, new XmlUrlResolver()) == 1)
{
- _output.WriteLine(e.ToString());
- Assert.True(false);
+ XmlTextReader xr = new XmlTextReader(szFullFilename);
+ XmlTextWriter xw = new XmlTextWriter("out.xml", Encoding.Unicode);
+ xslt.Transform(xr, null, xw, null);
+ xr.Dispose();
+ xw.Dispose();
+ VerifyResult(expected);
+ return;
}
Assert.True(false);
}
//[Variation("Pass null XmlResolver, load style sheet with document function, should not resolve during transform")]
- [ActiveIssue(9876)]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStrResolver2()
+ public void TransformStrStrResolver2(XslInputType xslInputType, ReaderType readerType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><elem>1</elem><elem>2</elem><elem>3</elem></result>";
+
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", xslInputType, readerType) == 1)
{
xslt.Transform(szFullFilename, "out.xml");
- if (CheckResult(422.3877210723) == 1)
- return;
+ VerifyResult(expected);
}
else
{
_output.WriteLine("Problem loading stylesheet!");
Assert.True(false);
}
- Assert.True(false);
}
//[Variation("Pass XmlUrlResolver, load style sheet with document function, should resolve during transform", Param = "xmlResolver_document_function.txt")]
- [ActiveIssue(9876)]
- [InlineData("xmlResolver_document_function.txt")]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData("xmlResolver_document_function.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStrResolver3(object param)
+ public void TransformStrStrResolver3(object param, XslInputType xslInputType, ReaderType readerType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
String szFullFilename = FullFilePath("fruits.xml");
string Baseline = Path.Combine("baseline", (string)param);
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", xslInputType, readerType) == 1)
{
xslt.Transform(szFullFilename, "out.xml");
VerifyResult(Baseline, _strOutFile);
@@ -3579,7 +3082,6 @@ namespace System.Xml.Tests
}
}
- [ActiveIssue(9876)]
//[Variation("Import/Include, CustomXmlResolver", Pri = 0, Params = new object[] { "XmlResolver_Main.xsl", "fruits.xml", "xmlResolver_main.txt", "CustomXmlResolver", true })]
[InlineData("XmlResolver_Main.xsl", "fruits.xml", "xmlResolver_main.txt", "CustomXmlResolver", true, "IXPathNavigable")]
[InlineData("XmlResolver_Main.xsl", "fruits.xml", "xmlResolver_main.txt", "CustomXmlResolver", true, "XmlReader")]
@@ -3587,8 +3089,10 @@ namespace System.Xml.Tests
[InlineData("XmlResolver_Main.xsl", "fruits.xml", "xmlResolver_main.txt", "NullResolver", false, "IXPathNavigable")]
[InlineData("XmlResolver_Main.xsl", "fruits.xml", "xmlResolver_main.txt", "NullResolver", false, "XmlReader")]
[Theory]
- public void ValidCases_ActiveIssue9876(object param0, object param1, object param2, object param3, object param4, object param5)
+ public void ValidCases_ExternalURI(object param0, object param1, object param2, object param3, object param4, object param5)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
ValidCases(param0, param1, param2, param3, param4, param5);
}
@@ -3765,58 +3269,82 @@ namespace System.Xml.Tests
}
//[Variation("Local parameter gets overwritten with global param value", Pri = 1)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void var1()
+ public void var1(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><out>
+param1 (correct answer is 'local-param1-arg'): local-param1-arg
+param2 (correct answer is 'local-param2-arg'): local-param2-arg
+</out>";
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("param1", string.Empty, "global-param1-arg");
- if ((LoadXSL("paramScope.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) && (CheckResult(473.4644857331) == 1))
+ if ((LoadXSL("paramScope.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Local parameter gets overwritten with global variable value", Pri = 1)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void var2()
+ public void var2(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><out>
+param1 (correct answer is 'local-param1-arg'): local-param1-arg
+param2 (correct answer is 'local-param2-arg'): local-param2-arg
+</out>";
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("param1", string.Empty, "global-param1-arg");
- if ((LoadXSL("varScope.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) && (CheckResult(473.4644857331) == 1))
+ if ((LoadXSL("varScope.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Subclassed XPathNodeIterator returned from an extension object or XsltFunction is not accepted by XPath", Pri = 1)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void var3()
+ public void var3(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><distinct-countries>France, Spain, Austria, Germany</distinct-countries>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject("http://foo.com", new MyXsltExtension());
- if ((LoadXSL("Bug111075.xsl") == 1) && (Transform_ArgList("Bug111075.xml") == 1) && (CheckResult(441.288076277) == 1))
+ if ((LoadXSL("Bug111075.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("Bug111075.xml", outputType, navType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Iterator using for-each over a variable is not reset correctly while using msxsl:node-set()", Pri = 1)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void var4()
+ public void var4(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
- if ((LoadXSL("Bug109644.xsl") == 1) && (Transform("foo.xml") == 1) && (CheckResult(417.2501860011) == 1))
- return;
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?>
+ Node Count: {3}
+
+
+ Correct Output: (1)(2)(3)
+ Incorrect Output: [1][2][3]";
+
+ if ((LoadXSL("Bug109644.xsl", xslInputType, readerType) == 1) && (Transform((string) "foo.xml", (OutputType) outputType, navType) == 1))
+ {
+ Assert.Equal(expected, File.ReadAllText("out.xml"), ignoreLineEndingDifferences:true);
+ }
else
Assert.True(false);
}
@@ -3831,97 +3359,37 @@ namespace System.Xml.Tests
_output = output;
}
- //BinCompat TODO: Add this test back
- ////[Variation("Bug398968 - Globalization is broken for document() function")]
- //[InlineData()]
- //[Theory]
- //public void RegressionTest1()
- //{
- // // <SQL BU Defect Tracking 410060>
- // if (_isInProc)
- // return; //TEST_SKIPPED;
- // // </SQL BU Defect Tracking 410060>
-
- // string testFile = "Stra\u00DFe.xml";
-
- // // Create the file.
- // using (FileStream fs = File.Open(testFile, FileMode.Open))
- // {
- // Byte[] info = new UTF8Encoding(true).GetBytes("<PASSED/>");
- // fs.Write(info, 0, info.Length);
- // }
-
- // LoadXSL("398968repro.xsl");
- // Transform("data.xml");
- // return;
- //}
-
- //BinCompat TODO: Add this test back
- ////[Variation("Bug410158 - Debug flag on XslCompiledTransform contaminates XsltSettings")]
- //[InlineData()]
- //[Theory]
- //public void RegressionTest2()
- //{
- // // <SQL BU Defect Tracking 410060>
- // // This test uses Reflection, which doenst work inproc
- // if (_isInProc)
- // return; //TEST_SKIPPED;
- // // </SQL BU Defect Tracking 410060>
-
- // string stylesheet = "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'/>";
- // XsltSettings settings = new XsltSettings();
- // XmlResolver resolver = new XmlUrlResolver();
-
- // int debuggableCnt1 = 0;
- // foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
- // {
- // string asmName = asm.GetName().Name;
- // if (asmName.StartsWith("System.Xml.Xsl.CompiledQuery.", StringComparison.Ordinal))
- // {
- // IEnumerable<Attribute> debuggableAttrs = asm.GetCustomAttributes(typeof(DebuggableAttribute));
- // if (debuggableAttrs.Count() > 0 && ((DebuggableAttribute)debuggableAttrs.First()).IsJITTrackingEnabled)
- // {
- // debuggableCnt1++;
- // }
- // }
- // }
- // _output.WriteLine("Number of debuggable XSLT stylesheets loaded (before load): " + debuggableCnt1);
-
- // XslCompiledTransform xct1 = new XslCompiledTransform(true);
- // xct1.Load(XmlReader.Create(new StringReader(stylesheet)), settings, resolver);
-
- // XslCompiledTransform xct2 = new XslCompiledTransform(false);
- // xct2.Load(XmlReader.Create(new StringReader(stylesheet)), settings, resolver);
-
- // int debuggableCnt2 = 0;
- // foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
- // {
- // string asmName = asm.GetName().Name;
- // if (asmName.StartsWith("System.Xml.Xsl.CompiledQuery.", StringComparison.Ordinal))
- // {
- // IEnumerable<Attribute> debuggableAttrs = asm.GetCustomAttributes(typeof(DebuggableAttribute));
- // if (debuggableAttrs.Count() > 0 && ((DebuggableAttribute)debuggableAttrs.First()).IsJITTrackingEnabled)
- // {
- // debuggableCnt2++;
- // }
- // }
- // }
- // _output.WriteLine("Number of debuggable XSLT stylesheets loaded (after load): " + debuggableCnt2);
-
- // if (debuggableCnt2 - debuggableCnt1 == 1)
- // return;
- // else
- // Assert.True(false);
- //}
+ //[Variation("Bug398968 - Globalization is broken for document() function")]
+ [PlatformSpecific(TestPlatforms.Windows)] //[ActiveIssue(14750)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [Theory]
+ public void RegressionTest1(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
+ {
+ // <SQL BU Defect Tracking 410060>
+ // </SQL BU Defect Tracking 410060>
+
+ string testFile = Path.Combine("TestFiles", FilePathUtil.GetTestDataPath(), "XsltApiV2", "Stra\u00DFe.xml");
+
+ // Create the file.
+ using (FileStream fs = File.Open(testFile, FileMode.Open))
+ {
+ Byte[] info = new UTF8Encoding(true).GetBytes("<PASSED />");
+ fs.Write(info, 0, info.Length);
+ }
+
+ LoadXSL("398968repro.xsl", xslInputType, readerType);
+ Transform((string) "data.xml", (OutputType) outputType, navType);
+ return;
+ }
//[Variation("Bug412703 - Off-by-one errors for XSLT loading error column")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)]
[Theory]
- public void RegressionTest3()
+ public void RegressionTest3(XslInputType xslInputType, ReaderType readerType)
{
try
{
- LoadXSL("bug370868.xsl");
+ LoadXSL("bug370868.xsl", xslInputType, readerType);
}
catch (System.Xml.Xsl.XsltException e)
{
@@ -3956,16 +3424,6 @@ namespace System.Xml.Tests
return;
}
- // TODO: DENY is deprecated
- ////[Variation("Bug429365 & SRZ070601000889 - XslCompiledTransform.Transform() fails on x64 when caller does not have UnmanagedCode privilege")]
- //[InlineData()]
- //public int RegressionTest6()
- //{
- // // Should not throw
- // ExecuteTransform();
- // return;
- //}
-
//[Variation("Bug469781 - Replace shouldn't relax original type 'assertion failure'")]
[InlineData()]
[Theory]
@@ -4029,20 +3487,6 @@ namespace System.Xml.Tests
Assert.True(false);
}
-
- //[SecurityPermission(SecurityAction.Deny, UnmanagedCode = true)]
- //private void ExecuteTransform()
- //{
- // XslCompiledTransform xslCompiledTransform = new XslCompiledTransform();
- // xslCompiledTransform.Load(FullFilePath("xslt_sortnames.xsl"));
-
- // MemoryStream ms = new MemoryStream();
- // StreamReader stmRead = new StreamReader(ms, true);
- // xslCompiledTransform.Transform(FullFilePath("xslt_names.xml"), null, ms);
- // ms.Seek(0, new SeekOrigin());
- // string foo = stmRead.ReadToEnd();
- // _output.WriteLine(foo);
- //}
}
internal class MyArrayIterator : XPathNodeIterator
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslTransformMultith.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslTransformMultith.cs
index 10475cd9d6..a15b046c08 100644
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslTransformMultith.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslTransformMultith.cs
@@ -4,11 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Reflection;
-using System.Runtime.Loader;
-using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using XmlCoreTest.Common;
@@ -30,7 +26,7 @@ namespace System.Xml.Tests
Init(null);
}
- public /*override*/ new void Init(object objParam)
+ public new void Init(object objParam)
{
xsltSameInstance = new XslCompiledTransform();
_strPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltApiV2\");
@@ -38,112 +34,11 @@ namespace System.Xml.Tests
}
}
- //[TestCase(Name = "Same instance testing: Transform() - Type & MethodInfo")]
- public class SameTypeCompiledTransform : XsltApiTestCaseBase2
- {
- protected string _strPath; // Path of the data files
- protected int counter;
-
- private Assembly _asm;
- private Type _type;
- private MethodInfo _meth;
- private Byte[] _staticData;
- private Type[] _ebTypes;
-
- private ITestOutputHelper _output;
- public SameTypeCompiledTransform(ITestOutputHelper output) : base(output)
- {
- _output = output;
- Init(null);
- }
-
- public /*override*/ new void Init(object objParam)
- {
- _strPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltApiV2\");
- counter = 0;
- InitTestData();
- return;
- }
-
- private void InitTestData()
- {
- string filePath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\Scripting28.dll");
- _asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath(filePath));
- _type = _asm.GetType("Scripting28");
- _meth = ReflectionTestCaseBase.GetStaticMethod(_type, "Execute");
- _staticData = (Byte[])_type.GetTypeInfo().GetField("staticData", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(_type);
- _ebTypes = (Type[])_type.GetTypeInfo().GetField("ebTypes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(_type);
- }
-
- public int LoadAndTransformWithType(Object args)
- {
- XslCompiledTransform xslt = new XslCompiledTransform();
- xslt.Load(_type);
- string filePath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\Scripting28.xsl");
- xslt.Transform(filePath, String.Format("out{0}.txt", System.Threading.Interlocked.Increment(ref counter)));
- return 1;
- }
-
- public int LoadAndTransformWithMethodInfo(Object args)
- {
- XslCompiledTransform xslt = new XslCompiledTransform();
- xslt.Load(_meth, _staticData, _ebTypes);
- string filePath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\precompiled\Scripting28.xsl");
- xslt.Transform(filePath, String.Format("out{0}.txt", System.Threading.Interlocked.Increment(ref counter)));
- return 1;
- }
-
- ////////////////////////////////////////////////////////////////
- // Same type testing:
- // Multiple Transform() over same XslCompiledTransform object
- ////////////////////////////////////////////////////////////////
- //[Variation("Multiple Loads on Type and Transform")]
- [ActiveIssue(9873)]
- [InlineData()]
- [Theory]
- public void proc1()
- {
- CThreads rThreads = new CThreads(_output);
-
- for (int i = 0; i < 1000; i++)
- {
- rThreads.Add(new ThreadFunc(LoadAndTransformWithType), i.ToString());
- }
-
- //Wait until they are complete
- rThreads.Start();
- rThreads.Wait();
-
- return;
- }
-
- //[Variation("Multiple Loads with Common MethodInfo, ebTypes and static data and Transform")]
- [ActiveIssue(9873)]
- [InlineData()]
- [Theory]
- public void proc2()
- {
- CThreads rThreads = new CThreads(_output);
-
- for (int i = 0; i < 1000; i++)
- {
- rThreads.Add(new ThreadFunc(LoadAndTransformWithMethodInfo), i.ToString());
- }
-
- //Wait until they are complete
- rThreads.Start();
- rThreads.Wait();
-
- return;
- }
- }
-
//[TestCase(Name = "Same instance testing: Transform() - READER")]
public class SameInstanceXslTransformReader : SameInstanceXslTransformTestCase
{
private XPathDocument _xd; // Loads XML file
private XmlReader _xrData; // Loads XML File
- //private XmlReader xr; // Reader output of transform is not supported in XSLT V2
private ITestOutputHelper _output;
public SameInstanceXslTransformReader(ITestOutputHelper output) : base(output)
@@ -203,9 +98,11 @@ namespace System.Xml.Tests
//[Variation("Multiple Transform(): Reader - QFE 505 Repro")]
[InlineData()]
- [Theory(Skip = "Resolving of External URIs is no longer allowed")]
+ [Theory]
public void proc2()
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
Load("QFE505_multith_customer_repro_with_or_expr.xsl", "QFE505_multith_customer_repro_with_or_expr.xml");
CThreads rThreads = new CThreads(_output);
@@ -500,9 +397,11 @@ namespace System.Xml.Tests
//[Variation("Multiple Transform(): TextWriter - QFE 505 Repro")]
[InlineData()]
- [Theory(Skip = "Resolving of External URIs is no longer allowed")]
+ [Theory]
public void proc2()
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
Load("QFE505_multith_customer_repro_with_or_expr.xsl", "QFE505_multith_customer_repro_with_or_expr.xml");
CThreads rThreads = new CThreads(_output);
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltApiV2.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltApiV2.cs
index caf9ccf5f8..c65f3cfd66 100644
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltApiV2.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltApiV2.cs
@@ -4,18 +4,12 @@
using Xunit;
using Xunit.Abstractions;
-using System;
-using System.Globalization;
using System.IO;
-using System.Net;
-using System.Reflection;
using System.Text;
-using System.Xml;
using System.Xml.XmlDiff;
using System.Xml.XPath;
using System.Xml.Xsl;
using XmlCoreTest.Common;
-using OLEDB.Test.ModuleCore;
namespace System.Xml.Tests
{
@@ -40,41 +34,10 @@ namespace System.Xml.Tests
}
////////////////////////////////////////////////////////////////
- // Module declaration for LTM usage
- //
- ////////////////////////////////////////////////////////////////
- //[TestModule(Name = "XsltApiV2", Desc = "XslCompiledTransform API Tests", Pri = 1)]
- public class XslCompiledTransformModule : CTestModule
- {
- public override int Init(object objParam)
- {
- int ret = base.Init(objParam);
-
- // These steps use to be part of javascript files and these were copied and executed as test setup step.
- // I belive this to be a much better way of accomplishing the same task.
- // Logic from CreateApiTestFiles.js
- string sourceFile = Path.Combine(FilePathUtil.GetTestDataPath(), "XsltApiV2", "xmlResolver_document_function.xml");
- string targetFile = @"c:\temp\xmlResolver_document_function.xml";
- if (!Directory.Exists(@"c:\temp"))
- Directory.CreateDirectory(@"c:\temp");
- if (!File.Exists(targetFile))
- File.Copy(sourceFile, targetFile, true);
-
- // Logic from CreateStrasse.js
- using (XmlWriter writer = XmlWriter.Create("Stra\u00DFe.xml"))
- {
- writer.WriteComment(" ");
- }
-
- return ret;
- }
- }
-
- ////////////////////////////////////////////////////////////////
// Base class for test cases
//
////////////////////////////////////////////////////////////////
- public class XsltApiTestCaseBase2 //: CTestCase
+ public class XsltApiTestCaseBase2
{
// Generic data for all derived test cases
public String szXslNS = "http://www.w3.org/1999/XSL/Transform";
@@ -91,12 +54,7 @@ namespace System.Xml.Tests
private string _strPath; // Path of the data files
private string _httpPath; // Http Path of the data files
- private XslInputType _nInputXsl; // reader, url, or navigator
- private XmlInputType _nInputXml = XmlInputType.Reader; // reader, url, or navigator
private bool _fTrace; // Should we write out the results of the transform?
- private OutputType _nOutput; // Type of XSL Transform to do
- private NavType _navType; // Data document type
- private ReaderType _readerType; // Reader type
// Other global variables
protected string _strOutFile = "out.xml"; // File to create when using write transforms
@@ -106,39 +64,26 @@ namespace System.Xml.Tests
protected XsltArgumentList m_xsltArg; // For XsltArgumentList tests
public object retObj;
- protected bool _isInProc; // Is the current test run in proc or /Host None?
protected string _standardTests;
private ITestOutputHelper _output;
public XsltApiTestCaseBase2(ITestOutputHelper output)
{
+ AppContext.SetSwitch("TestSwitch.LocalAppContext.DisableCaching", true);
_output = output;
this.Init(null);
}
- public XslInputType MyXslInputType()
- {
- return _nInputXsl;
- }
-
- public XmlInputType MyXmlInputType()
- {
- return _nInputXml;
- }
-
- public OutputType MyOutputType()
+ static XsltApiTestCaseBase2()
{
- return _nOutput;
- }
-
- public NavType MyDocType()
- {
- return _navType;
- }
-
- public ReaderType MyReaderType()
- {
- return _readerType;
+ // Replace absolute URI in xmlResolver_document_function.xml based on the environment
+ string targetFile = Path.Combine(Path.GetTempPath(), "xmlResolver_document_function.xml");
+ string xslFile = Path.Combine("TestFiles", FilePathUtil.GetTestDataPath(), "XsltApiV2", "xmlResolver_document_function_absolute_uri.xsl");
+ XmlDocument doc = new XmlDocument();
+ doc.Load(xslFile);
+ string xslString = doc.OuterXml.Replace("ABSOLUTE_URI", targetFile);
+ doc.LoadXml(xslString);
+ doc.Save(xslFile);
}
public OutputType GetOutputType(String s)
@@ -157,7 +102,6 @@ namespace System.Xml.Tests
public XmlUrlResolver GetDefaultCredResolver()
{
XmlUrlResolver myDefaultCredResolver = new XmlUrlResolver();
- //myDefaultCredResolver.Credentials = CredentialCache.DefaultCredentials;
return myDefaultCredResolver;
}
@@ -215,21 +159,10 @@ namespace System.Xml.Tests
}
}
- public String InitStringValue(String str)
- {
- return String.Empty;
- }
-
public void Init(object objParam)
{
- // Get input and transform type from attribute
- _nInputXsl = GetXslInputType(String.Empty);
- _nOutput = GetOutputType(String.Empty);
-
// Get parameter info from runtime variables passed to LTM
_fTrace = false;
- _navType = GetDocType(InitStringValue("doctype"));
- _readerType = GetReaderType(InitStringValue("readertype"));
//This is a temporary fix to restore the baselines. Refer to Test bug #
_strPath = Path.Combine("TestFiles", FilePathUtil.GetTestDataPath(), "XsltApiV2");
@@ -326,17 +259,12 @@ namespace System.Xml.Tests
// --------------------------------------------------------------------------------------------------------------
// LoadXSL
// -------------------------------------------------------------------------------------------------------------
- public int LoadXSL(String _strXslFile)
- {
- return LoadXSL(_strXslFile, _nInputXsl, new XmlUrlResolver());
- }
-
- public int LoadXSL(String _strXslFile, XmlResolver xr)
+ public int LoadXSL(string _strXslFile, XslInputType xslInputType, ReaderType readerType)
{
- return LoadXSL(_strXslFile, _nInputXsl, xr);
+ return LoadXSL(_strXslFile, xslInputType, readerType, new XmlUrlResolver());
}
- public int LoadXSL(String _strXslFile, XslInputType xslInputType, XmlResolver xr)
+ public int LoadXSL(string _strXslFile, XslInputType xslInputType, ReaderType readerType, XmlResolver xr)
{
_strXslFile = FullFilePath(_strXslFile);
xslt = new XslCompiledTransform();
@@ -345,12 +273,13 @@ namespace System.Xml.Tests
switch (xslInputType)
{
case XslInputType.URI:
- /* _output.WriteLine("Loading style sheet as URI {0}", _strXslFile);
- xslt.Load(_strXslFile, XsltSettings.TrustedXslt, xr);
- break;
- */
+ _output.WriteLine("Loading style sheet as URI {0}", _strXslFile);
+ xrs = new XmlReaderSettings() { DtdProcessing = DtdProcessing.Parse};
+ xslt.Load(XmlReader.Create(_strXslFile, xrs), XsltSettings.TrustedXslt, xr);
+ break;
+
case XslInputType.Reader:
- switch (_readerType)
+ switch (readerType)
{
case ReaderType.XmlTextReader:
XmlTextReader trTemp = new XmlTextReader(_strXslFile);
@@ -424,12 +353,12 @@ namespace System.Xml.Tests
// --------------------------------------------------------------------------------------------------------------
// LoadXSL_Resolver
// -------------------------------------------------------------------------------------------------------------
- public int LoadXSL_Resolver(String _strXslFile, XmlResolver xr)
+ public int LoadXSL_Resolver(string _strXslFile, XslInputType xslInputType, ReaderType readerType, XmlResolver xr)
{
_strXslFile = FullFilePath(_strXslFile);
xslt = new XslCompiledTransform();
XmlReaderSettings xrs = null;
- switch (_nInputXsl)
+ switch (xslInputType)
{
case XslInputType.URI:
_output.WriteLine("Loading style sheet as URI " + _strXslFile);
@@ -437,7 +366,7 @@ namespace System.Xml.Tests
break;
case XslInputType.Reader:
- switch (_readerType)
+ switch (readerType)
{
case ReaderType.XmlTextReader:
XmlTextReader trTemp = new XmlTextReader(_strXslFile);
@@ -506,102 +435,11 @@ namespace System.Xml.Tests
return 1;
}
- // --------------------------------------------------------------------------------------------------------------
- // LoadXSL_Resolver_Evidence
- // -------------------------------------------------------------------------------------------------------------
- /*public int LoadXSL_Resolver_Evidence(String _strXslFile, XmlResolver xr, Evidence e)
- {
- _strXslFile = FullFilePath(_strXslFile);
- xslt = new XslCompiledTransform();
-
- switch (_nInputXsl)
- {
- case XslInputType.Reader:
- switch (_readerType)
- {
- case ReaderType.XmlTextReader:
- XmlReader trTemp = XmlReader.Create(_strXslFile);
- try
- {
- _output.WriteLine("Loading style sheet as XmlTextReader " + _strXslFile);
- //xslt.Load(trTemp, xr, e); //Evidence is not supported on V2 XSLT Load
- xslt.Load(trTemp, XsltSettings.TrustedXslt, xr);
- }
- catch (Exception ex)
- {
- throw (ex);
- }
- finally
- {
- if (trTemp != null)
- trTemp.Dispose();
- }
- break;
-
- case ReaderType.XmlNodeReader:
- XmlDocument docTemp = new XmlDocument();
- docTemp.Load(_strXslFile);
- XmlNodeReader nrTemp = new XmlNodeReader(docTemp);
- try
- {
- _output.WriteLine("Loading style sheet as XmlNodeReader " + _strXslFile);
- //xslt.Load(nrTemp, xr, e); Evidence is not supported in V2 XSLT Load
- xslt.Load(nrTemp, XsltSettings.TrustedXslt, xr);
- }
- catch (Exception ex)
- {
- throw (ex);
- }
- finally
- {
- if (nrTemp != null)
- nrTemp.Dispose();
- }
- break;
-
- case ReaderType.XmlValidatingReader:
- default:
- XmlReaderSettings xrs = new XmlReaderSettings();
-#pragma warning disable 0618
- xrs.ProhibitDtd = false;
-#pragma warning restore 0618
- XmlReader vrTemp = null;
- try
- {
- vrTemp = XmlReader.Create(_strXslFile, xrs);
- _output.WriteLine("Loading style sheet as XmlValidatingReader " + _strXslFile);
- //xslt.Load(vrTemp, xr, e); Evidence is not supported in V2 XSLT Load
- xslt.Load(vrTemp, XsltSettings.TrustedXslt, xr);
- }
- catch (Exception ex)
- {
- throw (ex);
- }
- finally
- {
- if (vrTemp != null)
- vrTemp.Dispose();
- }
- break;
- }
- break;
-
- case XslInputType.Navigator:
- XmlReader xrLoad = XmlReader.Create(_strXslFile);
- XPathDocument xdTemp = new XPathDocument(xrLoad, XmlSpace.Preserve);
- xrLoad.Dispose();
- _output.WriteLine("Loading style sheet as Navigator " + _strXslFile);
- xslt.Load(xdTemp.CreateNavigator(), XsltSettings.TrustedXslt, xr);
- break;
- }
- return 1;
- }*/
-
//VerifyResult
public void VerifyResult(string expectedValue)
{
XmlDiff.XmlDiff xmldiff = new XmlDiff.XmlDiff();
- xmldiff.Option = XmlDiffOption.InfosetComparison | XmlDiffOption.IgnoreEmptyElement;
+ xmldiff.Option = XmlDiffOption.InfosetComparison | XmlDiffOption.IgnoreEmptyElement | XmlDiffOption.NormalizeNewline;
StreamReader sr = new StreamReader(new FileStream("out.xml", FileMode.Open, FileAccess.Read));
string actualValue = sr.ReadToEnd();
@@ -615,28 +453,25 @@ namespace System.Xml.Tests
XmlTextReader tr1 = new XmlTextReader("out.xml");
XmlTextReader tr2 = new XmlTextReader(new StringReader(expectedValue));
- bool bResult = xmldiff.Compare(tr1, tr2);
+ bool result = xmldiff.Compare(tr1, tr2);
//Close the readers
tr1.Dispose();
tr2.Dispose();
- if (bResult)
- return;
- else
- Assert.True(false);
+ Assert.True(result);
}
//VerifyResult which compares 2 arguments using XmlDiff.
public void VerifyResult(string baseline, string outputFile)
{
- bool bResult = false;
+ bool result = false;
FileStream fsExpected;
baseline = FullFilePath(baseline);
XmlDiff.XmlDiff diff = new XmlDiff.XmlDiff();
- diff.Option = XmlDiffOption.IgnoreEmptyElement | XmlDiffOption.IgnoreAttributeOrder | XmlDiffOption.InfosetComparison | XmlDiffOption.IgnoreWhitespace;
+ diff.Option = XmlDiffOption.IgnoreEmptyElement | XmlDiffOption.IgnoreAttributeOrder | XmlDiffOption.InfosetComparison | XmlDiffOption.IgnoreWhitespace | XmlDiffOption.NormalizeNewline;
XmlParserContext context = new XmlParserContext(new NameTable(), null, "", XmlSpace.None);
fsExpected = new FileStream(baseline, FileMode.Open, FileAccess.Read, FileShare.Read);
@@ -645,7 +480,7 @@ namespace System.Xml.Tests
_output.WriteLine("Verifying o/p with baseline result {0}...", baseline);
try
{
- bResult = diff.Compare(new XmlTextReader(fsActual, XmlNodeType.Element, context), new XmlTextReader(fsExpected, XmlNodeType.Element, context));
+ result = diff.Compare(new XmlTextReader(fsActual, XmlNodeType.Element, context), new XmlTextReader(fsExpected, XmlNodeType.Element, context));
}
catch (Exception e)
{
@@ -657,7 +492,7 @@ namespace System.Xml.Tests
fsExpected.Dispose();
fsActual.Dispose();
}
- if (!bResult)
+ if (!result)
{
// Write out the actual and expected o/p
_output.WriteLine("Expected o/p: ");
@@ -680,36 +515,30 @@ namespace System.Xml.Tests
}
}
- if (bResult)
- return;
- else
- {
- _output.WriteLine("**** Baseline mis-matched ****");
- Assert.True(false);
- }
+ Assert.True(result, "**** Baseline mis-matched ****");
}
// --------------------------------------------------------------------------------------------------------------
// Transform
// -------------------------------------------------------------------------------------------------------------
- public int Transform(String szXmlFile)
+ public int Transform(string szXmlFile, OutputType outputType, NavType navType)
{
// Default value of errorCase is false
- return (Transform(szXmlFile, false));
+ return (Transform(szXmlFile, outputType, navType, false));
}
- public int Transform(String szXmlFile, bool errorCase)
+ public int Transform(String szXmlFile, OutputType outputType, NavType navType, bool errorCase)
{
szXmlFile = FullFilePath(szXmlFile);
_output.WriteLine("Loading XML " + szXmlFile);
- IXPathNavigable xd = LoadXML(szXmlFile, _navType);
+ IXPathNavigable xd = LoadXML(szXmlFile, navType);
_output.WriteLine("Executing transform");
xrXSLT = null;
Stream strmTemp = null;
- switch (_nOutput)
+ switch (outputType)
{
case OutputType.Stream:
try
@@ -762,23 +591,23 @@ namespace System.Xml.Tests
// Transform_ArgList
// -------------------------------------------------------------------------------------------------------------
- public int Transform_ArgList(String szXmlFile)
+ public int Transform_ArgList(string szXmlFile, OutputType outputType, NavType navType)
{
// Default value of errorCase is false
- return (Transform_ArgList(szXmlFile, false));
+ return (Transform_ArgList(szXmlFile, outputType, navType, false));
}
- public int Transform_ArgList(String szXmlFile, bool errorCase)
+ public int Transform_ArgList(string szXmlFile, OutputType outputType, NavType navType, bool errorCase)
{
szXmlFile = FullFilePath(szXmlFile);
_output.WriteLine("Loading XML " + szXmlFile);
- IXPathNavigable xd = LoadXML(szXmlFile, _navType);
+ IXPathNavigable xd = LoadXML(szXmlFile, navType);
_output.WriteLine("Executing transform");
xrXSLT = null;
Stream strmTemp = null;
- switch (_nOutput)
+ switch (outputType)
{
case OutputType.Stream:
try
@@ -831,24 +660,24 @@ namespace System.Xml.Tests
// TransformResolver
// -------------------------------------------------------------------------------------------------------------
- public int TransformResolver(String szXmlFile, XmlResolver xr)
+ public int TransformResolver(string szXmlFile, OutputType outputType, NavType navType, XmlResolver xr)
{
// Default value of errorCase is false
- return (TransformResolver(szXmlFile, xr, false));
+ return (TransformResolver(szXmlFile, outputType, navType, xr, false));
}
- public int TransformResolver(String szXmlFile, XmlResolver xr, bool errorCase)
+ public int TransformResolver(string szXmlFile, OutputType outputType, NavType navType, XmlResolver xr, bool errorCase)
{
szXmlFile = FullFilePath(szXmlFile);
_output.WriteLine("Loading XML " + szXmlFile);
- IXPathNavigable xd = LoadXML(szXmlFile, _navType);
+ IXPathNavigable xd = LoadXML(szXmlFile, navType);
_output.WriteLine("Executing transform");
xrXSLT = null;
Stream strmTemp = null;
- switch (_nOutput)
+ switch (outputType)
{
case OutputType.Stream:
try
@@ -898,12 +727,12 @@ namespace System.Xml.Tests
// --------------------------------------------------------------------------------------------------------------
// CheckResult
// -------------------------------------------------------------------------------------------------------------
- public int CheckResult(double szExpResult)
+ public int CheckResult(double szExpResult, OutputType outputType)
{
double checksumActual;
CXsltChecksum check = new CXsltChecksum(_fTrace, _output);
- if (_nOutput == OutputType.URI)
+ if (outputType == OutputType.URI)
checksumActual = check.Calc(xrXSLT);
else
checksumActual = check.Calc(_strOutFile);
@@ -918,41 +747,6 @@ namespace System.Xml.Tests
return 1;
}
-
- public int CheckResult(string expResult)
- {
- double actChecksum, expChecksum;
- CXsltChecksum check = new CXsltChecksum(_fTrace, _output);
-
- // Let's make sure we use the same checksum calculating function for
- // actual and expected so we know we are comparing apples to apples.
- if (_nOutput == OutputType.URI)
- {
- expChecksum = check.Calc(XmlReader.Create(new StringReader(expResult)));
- actChecksum = check.Calc(xrXSLT);
- }
- else
- {
- using (StreamWriter sw = new StreamWriter(new FileStream(Path.Combine(Directory.GetCurrentDirectory(), "expectdchecksum.xml"), FileMode.Create, FileAccess.Write)))
- {
- sw.Write(expResult);
- }
- expChecksum = check.Calc("expectdchecksum.xml");
- actChecksum = check.Calc(_strOutFile);
- }
-
- if (expChecksum != actChecksum || _fTrace)
- {
- _output.WriteLine("Act Xml: {0}", check.Xml);
- _output.WriteLine("Exp Xml: {0}", expResult);
- _output.WriteLine("Actual checksum: {0}, Expected: {1}", actChecksum, expChecksum);
- }
-
- if (expChecksum != actChecksum)
- return 0;
-
- return 1;
- }
}
internal class CExceptionHandler
@@ -981,7 +775,7 @@ namespace System.Xml.Tests
public bool VerifyException(Exception ex)
{
Type _type = ex.GetType();
- res = String.Empty;//(string)_type.InvokeMember("res", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance, null, ex, null);
+ res = String.Empty;
msg = (string)_nav.Evaluate("string(/exceptions/exception [@res = '" + res + "']/@message)");
try
{
@@ -997,7 +791,6 @@ namespace System.Xml.Tests
public bool VerifyException(Exception ex, string res, string[] strParams)
{
- //msg = (string)nav.Evaluate("string(/exceptions/exception [@res = '"+res+"']/@message)");
try
{
_exVer.IsExceptionOk(ex, res, strParams);
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentList.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentList.cs
index 0b04a10513..6199e57de6 100644
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentList.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentList.cs
@@ -4,16 +4,11 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.Collections.Generic;
using System.Dynamic;
-using System.Globalization;
using System.IO;
-using System.Security;
-using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
-using XmlCoreTest.Common;
namespace System.Xml.Tests
{
@@ -635,9 +630,9 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "Basic Verification Test", Pri = 1)]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void GetExtObject1()
+ public void GetExtObject1(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
@@ -653,9 +648,11 @@ namespace System.Xml.Tests
}
string expXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><result xmlns:myObj=\"urn:my-object\"><func1>1.Test1</func1><func2>2.Test2</func2><func3>3.Test3</func3></result>";
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(expXml) == 1))
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
+ {
+ VerifyResult(expXml);
return;
+ }
else
Assert.True(false);
}
@@ -680,9 +677,9 @@ namespace System.Xml.Tests
}
//[Variation("Namespace URI is empty string", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void GetExtObject3(object param)
+ public void GetExtObject3(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -697,7 +694,7 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -707,9 +704,9 @@ namespace System.Xml.Tests
}
//[Variation("Namespace URI non-existent")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void GetExtObject4()
+ public void GetExtObject4(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
m_xsltArg = new XsltArgumentList();
@@ -722,8 +719,8 @@ namespace System.Xml.Tests
}
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml");
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", outputType, navType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -734,9 +731,9 @@ namespace System.Xml.Tests
}
//[Variation("Very long namespace System.Xml.Tests")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void GetExtObject5()
+ public void GetExtObject5(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
m_xsltArg = new XsltArgumentList();
MyObject obj = new MyObject(5, _output);
@@ -751,9 +748,11 @@ namespace System.Xml.Tests
}
string expXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><result xmlns:myObj=\"http://www.microsoft.com/this/is/a/very/long/namespace/uri/to/do/the/api/testing/for/xslt/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/\"><func1>1.Test1</func1><func2>2.Test2</func2><func3>3.Test3</func3></result>";
- if ((LoadXSL("myObjectLongNS.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(expXml) == 1))
+ if ((LoadXSL("myObjectLongNS.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
+ {
+ VerifyResult(expXml);
return;
+ }
else
Assert.True(false);
}
@@ -834,9 +833,9 @@ namespace System.Xml.Tests
}
//[Variation("Case sensitivity")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void GetExtObject8()
+ public void GetExtObject8(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(8, _output);
m_xsltArg = new XsltArgumentList();
@@ -872,17 +871,19 @@ namespace System.Xml.Tests
}
string expXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><result xmlns:myObj=\"urn:my-object\"><func1>1.Test1</func1><func2>2.Test2</func2><func3>3.Test3</func3></result>";
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(expXml) == 1))
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
+ {
+ VerifyResult(expXml);
return;
+ }
else
Assert.True(false);
}
//[Variation("Whitespace")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void GetExtObject9()
+ public void GetExtObject9(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
int i = 1;
m_xsltArg = new XsltArgumentList();
@@ -903,8 +904,8 @@ namespace System.Xml.Tests
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml");
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", outputType, navType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -915,9 +916,9 @@ namespace System.Xml.Tests
}
//[Variation("Call after object has been removed")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void GetExtObject10()
+ public void GetExtObject10(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(10, _output);
m_xsltArg = new XsltArgumentList();
@@ -934,8 +935,8 @@ namespace System.Xml.Tests
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml");
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", outputType, navType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -946,9 +947,9 @@ namespace System.Xml.Tests
}
//[Variation("Call multiple times")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void GetExtObject11()
+ public void GetExtObject11(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(11, _output);
m_xsltArg = new XsltArgumentList();
@@ -965,9 +966,11 @@ namespace System.Xml.Tests
}
}
string expXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><result xmlns:myObj=\"urn:my-object\"><func1>1.Test1</func1><func2>2.Test2</func2><func3>3.Test3</func3></result>";
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(expXml) == 1))
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
+ {
+ VerifyResult(expXml);
return;
+ }
else
Assert.True(false);
}
@@ -1014,9 +1017,17 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "Basic Verification Test", Pri = 1, Param = "showParam1.txt")]
- [InlineData("showParam1.txt")]
+ [InlineData("showParam1.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam1.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam1.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam1.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam1.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam1.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam1.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam1.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam1.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam1(object param)
+ public void AddParam1(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -1027,7 +1038,7 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test1")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1075,9 +1086,17 @@ namespace System.Xml.Tests
}
//[Variation("Very Long Param Name", Param = "LongParam.txt")]
- [InlineData("LongParam.txt")]
+ [InlineData("LongParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("LongParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("LongParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("LongParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("LongParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("LongParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("LongParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("LongParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("LongParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam4(object param)
+ public void AddParam4(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -1088,7 +1107,7 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test1")
Assert.True(false);
- if ((LoadXSL("showParamLongName.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParamLongName.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1136,9 +1155,17 @@ namespace System.Xml.Tests
}
//[Variation("Namespace URI is empty string", Param = "showParam7.txt")]
- [InlineData("showParam7.txt")]
+ [InlineData("showParam7.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam7.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam7.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam7.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam7.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam7.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam7.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam7.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam7.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam7(object param)
+ public void AddParam7(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -1150,7 +1177,7 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test7")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1160,9 +1187,17 @@ namespace System.Xml.Tests
}
//[Variation("Very long namespace System.Xml.Tests", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam8(object param)
+ public void AddParam8(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -1173,7 +1208,7 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test8")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1214,9 +1249,17 @@ namespace System.Xml.Tests
}
//[Variation("Object with same name, different namespace System.Xml.Tests", Param = "AddParam12.txt")]
- [InlineData("AddParam12.txt")]
+ [InlineData("AddParam12.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam12.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam12.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam12.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam12.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam12.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam12.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam12.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam12.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam12(object param)
+ public void AddParam12(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
@@ -1241,7 +1284,7 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test1")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1251,9 +1294,17 @@ namespace System.Xml.Tests
}
//[Variation("Object with same namespace System.Xml.Tests, different name", Param = "AddParam13.txt")]
- [InlineData("AddParam13.txt")]
+ [InlineData("AddParam13.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam13.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam13.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam13.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam13.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam13.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam13.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam13.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam13.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam13(object param)
+ public void AddParam13(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -1277,7 +1328,7 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test1")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1287,9 +1338,17 @@ namespace System.Xml.Tests
}
//[Variation("Case Sensitivity", Param = "AddParam14.txt")]
- [InlineData("AddParam14.txt")]
+ [InlineData("AddParam14.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam14.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam14.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam14.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam14.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam14.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam14.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam14.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam14.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam14(object param)
+ public void AddParam14(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -1318,7 +1377,7 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test3")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1347,9 +1406,17 @@ namespace System.Xml.Tests
}
//[Variation("Add/remove object many times", Param = "AddParam16.txt")]
- [InlineData("AddParam16.txt")]
+ [InlineData("AddParam16.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam16.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam16.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam16.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam16.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam16.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam16.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam16.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam16.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam16(object param)
+ public void AddParam16(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -1388,7 +1455,7 @@ namespace System.Xml.Tests
retObj = m_xsltArg.GetParam("myArg2", szEmpty);
if (retObj.ToString() != "Test2")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1398,9 +1465,17 @@ namespace System.Xml.Tests
}
//[Variation("Whitespace in URI and param", Param = "AddParam17.txt")]
- [InlineData("AddParam17.txt")]
+ [InlineData("AddParam17.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam17.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam17.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam17.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam17.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam17.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam17.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam17.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam17.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam17(object param)
+ public void AddParam17(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
int i = 1;
@@ -1443,7 +1518,7 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1453,9 +1528,17 @@ namespace System.Xml.Tests
}
//[Variation("Adding many objects", Param = "AddParam18.txt")]
- [InlineData("AddParam18.txt")]
+ [InlineData("AddParam18.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam18.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam18.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam18.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam18.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam18.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam18.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam18.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam18.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam18(object param)
+ public void AddParam18(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -1469,7 +1552,7 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1479,9 +1562,17 @@ namespace System.Xml.Tests
}
//[Variation("Add same object many times", Param = "AddParam19.txt")]
- [InlineData("AddParam19.txt")]
+ [InlineData("AddParam19.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam19.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam19.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam19.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam19.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam19.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam19.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam19.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam19.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam19(object param)
+ public void AddParam19(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -1503,7 +1594,7 @@ namespace System.Xml.Tests
retObj = m_xsltArg.GetParam("myArg2", szEmpty);
if (retObj.ToString() != ("Test2"))
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1513,9 +1604,17 @@ namespace System.Xml.Tests
}
//[Variation("Using Different XSLT namespace", Param = "AddParam20.txt")]
- [InlineData("AddParam20.txt")]
+ [InlineData("AddParam20.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam20.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam20.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam20.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam20.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam20.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParam20.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParam20.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParam20.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam20(object param)
+ public void AddParam20(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
@@ -1545,7 +1644,7 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test4")
Assert.True(false);
- if ((LoadXSL("showParamNS.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParamNS.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1567,24 +1666,39 @@ namespace System.Xml.Tests
}
//[Variation("Parameters should not be cached")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject32()
+ public void AddExtObject32(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
- if (LoadXSL("test_Param.xsl") == 1)
+ string expected1 = @"<?xml version=""1.0"" encoding=""utf-8""?><out>Param: first</out>";
+ string expected2 = @"<?xml version=""1.0"" encoding=""utf-8""?><out>Param: second</out>";
+
+ if (LoadXSL("test_Param.xsl", xslInputType, readerType) == 1)
{
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myParam1", szEmpty, "first");
// Transform once
- if ((Transform_ArgList("foo.xml") == 1) && (CheckResult(383.6292620645) == 1))
+ if (Transform_ArgList("foo.xml", outputType, navType) == 1)
{
+ VerifyResult(expected1);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myParam1", szEmpty, "second");
// Transform again to make sure that parameter from first transform are not cached
- if ((Transform_ArgList("foo.xml") == 1) && (CheckResult(384.9801823644) == 1))
+ if (Transform_ArgList("foo.xml", outputType, navType) == 1)
+ {
+ VerifyResult(expected2);
return;
+ }
}
}
Assert.True(false);
@@ -1618,75 +1732,299 @@ namespace System.Xml.Tests
//global param is xsl:param local param is xsl:param
//[Variation(id = 1, Pri = 2, Desc = "No param sent, global param used, local param exists with a default value", Params = new object[] { "AddParameterA1.xsl", "default local" })]
- [InlineData("AddParameterA1.xsl", "default local")]
+ [InlineData("AddParameterA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 2, Pri = 2, Desc = "No param sent, global param used, local param exists with no default value", Params = new object[] { "AddParameterA2.xsl", "" })]
- [InlineData("AddParameterA2.xsl", "")]
+ [InlineData("AddParameterA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 3, Pri = 2, Desc = "No param sent, global param used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterA3.xsl", "default global" })]
- [InlineData("AddParameterA3.xsl", "default global")]
+ [InlineData("AddParameterA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 4, Pri = 2, Desc = "No param sent, global param used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterA4.xsl", "with-param" })]
- [InlineData("AddParameterA4.xsl", "with-param")]
+ [InlineData("AddParameterA4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 5, Pri = 2, Desc = "No param sent, global param used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterA5.xsl", "" })]
- [InlineData("AddParameterA5.xsl", "")]
+ [InlineData("AddParameterA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 6, Pri = 2, Desc = "No param sent, global param used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterA6.xsl", "default global" })]
- [InlineData("AddParameterA6.xsl", "default global")]
+ [InlineData("AddParameterA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 7, Pri = 2, Desc = "No param sent, global param used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterA7.xsl", "default global" })]
- [InlineData("AddParameterA7.xsl", "default global")]
+ [InlineData("AddParameterA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//global param is xsl:variable local param is xsl:param
//[Variation(id = 8, Pri = 2, Desc = "No param sent, global variable used, local param exists with a default value", Params = new object[] { "AddParameterDA1.xsl", "default local" })]
- [InlineData("AddParameterDA1.xsl", "default local")]
+ [InlineData("AddParameterDA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 9, Pri = 2, Desc = "No param sent, global variable used, local param exists with no default value", Params = new object[] { "AddParameterDA2.xsl", "" })]
- [InlineData("AddParameterDA2.xsl", "")]
+ [InlineData("AddParameterDA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 10, Pri = 2, Desc = "No param sent, global variable used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterDA3.xsl", "default global" })]
- [InlineData("AddParameterDA3.xsl", "default global")]
+ [InlineData("AddParameterDA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 11, Pri = 2, Desc = "No param sent, global variable used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterDA4.xsl", "with-param" })]
- [InlineData("AddParameterDA4.xsl", "with-param")]
+ [InlineData("AddParameterDA4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 12, Pri = 2, Desc = "No param sent, global variable used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterDA5.xsl", "" })]
- [InlineData("AddParameterDA5.xsl", "")]
+ [InlineData("AddParameterDA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 13, Pri = 2, Desc = "No param sent, global variable used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterDA6.xsl", "default global" })]
- [InlineData("AddParameterDA6.xsl", "default global")]
+ [InlineData("AddParameterDA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 14, Pri = 2, Desc = "No param sent, global variable used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterDA7.xsl", "default global" })]
- [InlineData("AddParameterDA7.xsl", "default global")]
+ [InlineData("AddParameterDA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//global param is xsl:param local param is xsl:variable
//[Variation(id = 15, Pri = 2, Desc = "No param sent, global param used, local variable exists with a default value", Params = new object[] { "AddParameterEA1.xsl", "default local" })]
- [InlineData("AddParameterEA1.xsl", "default local")]
+ [InlineData("AddParameterEA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 16, Pri = 2, Desc = "No param sent, global param used, local variable exists with no default value", Params = new object[] { "AddParameterEA2.xsl", "" })]
- [InlineData("AddParameterEA2.xsl", "")]
+ [InlineData("AddParameterEA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 17, Pri = 2, Desc = "No param sent, global param used, local variable doesn't exist but reference to param exists", Params = new object[] { "AddParameterEA3.xsl", "default global" })]
- [InlineData("AddParameterEA3.xsl", "default global")]
+ [InlineData("AddParameterEA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 18, Pri = 2, Desc = "No param sent, global param used, local variable exists with a default value and with-param sends a value", Params = new object[] { "AddParameterEA4.xsl", "default local" })]
- [InlineData("AddParameterEA4.xsl", "default local")]
+ [InlineData("AddParameterEA4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 19, Pri = 2, Desc = "No param sent, global param used, local variable exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterEA5.xsl", "" })]
- [InlineData("AddParameterEA5.xsl", "")]
+ [InlineData("AddParameterEA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 20, Pri = 2, Desc = "No param sent, global param used, local variable doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterEA6.xsl", "default global" })]
- [InlineData("AddParameterEA6.xsl", "default global")]
+ [InlineData("AddParameterEA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 21, Pri = 2, Desc = "No param sent, global param used, local variable doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterEA7.xsl", "default global" })]
- [InlineData("AddParameterEA7.xsl", "default global")]
+ [InlineData("AddParameterEA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//global param is xsl:variable local param is xsl:variable
//[Variation(id = 22, Pri = 2, Desc = "No param sent, global variable used, local variable exists with a default value", Params = new object[] { "AddParameterFA1.xsl", "default local" })]
- [InlineData("AddParameterFA1.xsl", "default local")]
+ [InlineData("AddParameterFA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 23, Pri = 2, Desc = "No param sent, global variable used, local variable exists with no default value", Params = new object[] { "AddParameterFA2.xsl", "" })]
- [InlineData("AddParameterFA2.xsl", "")]
+ [InlineData("AddParameterFA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 24, Pri = 2, Desc = "No param sent, global variable used, local variable doesn't exist but reference to param exists", Params = new object[] { "AddParameterFA3.xsl", "default global" })]
- [InlineData("AddParameterFA3.xsl", "default global")]
+ [InlineData("AddParameterFA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 25, Pri = 2, Desc = "No param sent, global variable used, local variable exists with a default value and with-param sends a value", Params = new object[] { "AddParameterFA4.xsl", "default local" })]
- [InlineData("AddParameterFA4.xsl", "default local")]
+ [InlineData("AddParameterFA4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 26, Pri = 2, Desc = "No param sent, global variable used, local variable exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterFA5.xsl", "" })]
- [InlineData("AddParameterFA5.xsl", "")]
+ [InlineData("AddParameterFA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 27, Pri = 2, Desc = "No param sent, global variable used, local variable doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterFA6.xsl", "default global" })]
- [InlineData("AddParameterFA6.xsl", "default global")]
+ [InlineData("AddParameterFA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 28, Pri = 2, Desc = "No param sent, global variable used, local variable doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterFA7.xsl", "default global" })]
- [InlineData("AddParameterFA7.xsl", "default global")]
+ [InlineData("AddParameterFA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam1(object param0, object param1)
+ public void AddParam1(object param0, object param1, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
m_xsltArg = new XsltArgumentList();
string xslFile = param0.ToString();
string expected = "<result>" + param1.ToString() + "</result>";
- if ((LoadXSL(xslFile) == 1) && (Transform_ArgList("AddParameter.xml") == 1))
+ if ((LoadXSL(xslFile, xslInputType, readerType) == 1) && (Transform_ArgList("AddParameter.xml", outputType, navType) == 1))
{
VerifyResult(expected);
return;
@@ -1699,69 +2037,293 @@ namespace System.Xml.Tests
//global param is xsl:param local param is xsl:param
//[Variation(id = 29, Pri = 2, Desc = "Param sent, global param used, local param exists with a default value", Params = new object[] { "AddParameterB1.xsl", "default local" })]
- [InlineData("AddParameterB1.xsl", "default local")]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 30, Pri = 2, Desc = "Param sent, global param used, local param exists with no default value", Params = new object[] { "AddParameterB2.xsl", "" })]
- [InlineData("AddParameterB2.xsl", "")]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 31, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterB3.xsl", "outside param" })]
- [InlineData("AddParameterB3.xsl", "outside param")]
+ [InlineData("AddParameterB3.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 32, Pri = 2, Desc = "Param sent, global param used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterB4.xsl", "with-param" })]
- [InlineData("AddParameterB4.xsl", "with-param")]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 33, Pri = 2, Desc = "Param sent, global param used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterB5.xsl", "" })]
- [InlineData("AddParameterB5.xsl", "")]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 34, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterB6.xsl", "outside param" })]
- [InlineData("AddParameterB6.xsl", "outside param")]
+ [InlineData("AddParameterB6.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 35, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterB7.xsl", "outside param" })]
- [InlineData("AddParameterB7.xsl", "outside param")]
+ [InlineData("AddParameterB7.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//global param is xsl:variable local param is xsl:param
//[Variation(id = 36, Pri = 2, Desc = "Param sent, global variable used, local param exists with a default value", Params = new object[] { "AddParameterDB1.xsl", "default local" })]
- [InlineData("AddParameterDB1.xsl", "default local")]
+ [InlineData("AddParameterDB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 37, Pri = 2, Desc = "Param sent, global variable used, local param exists with no default value", Params = new object[] { "AddParameterDB2.xsl", "" })]
- [InlineData("AddParameterDB2.xsl", "")]
+ [InlineData("AddParameterDB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 38, Pri = 2, Desc = "Param sent, global variable used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterDB3.xsl", "default global" })]
- [InlineData("AddParameterDB3.xsl", "default global")]
+ [InlineData("AddParameterDB3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 39, Pri = 2, Desc = "Param sent, global variable used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterDB4.xsl", "with-param" })]
- [InlineData("AddParameterDB4.xsl", "with-param")]
+ [InlineData("AddParameterDB4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 40, Pri = 2, Desc = "Param sent, global variable used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterDB5.xsl", "" })]
- [InlineData("AddParameterDB5.xsl", "")]
+ [InlineData("AddParameterDB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 41, Pri = 2, Desc = "Param sent, global variable used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterDB6.xsl", "default global" })]
- [InlineData("AddParameterDB6.xsl", "default global")]
+ [InlineData("AddParameterDB6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 42, Pri = 2, Desc = "Param sent, global variable used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterDB7.xsl", "default global" })]
- [InlineData("AddParameterDB7.xsl", "default global")]
+ [InlineData("AddParameterDB7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//global param is xsl:param local param is xsl:variable
//[Variation(id = 43, Pri = 2, Desc = "Param sent, global param used, local variable exists with a default value", Params = new object[] { "AddParameterEB1.xsl", "default local" })]
- [InlineData("AddParameterEB1.xsl", "default local")]
+ [InlineData("AddParameterEB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 44, Pri = 2, Desc = "Param sent, global param used, local variable exists with no default value", Params = new object[] { "AddParameterEB2.xsl", "" })]
- [InlineData("AddParameterEB2.xsl", "")]
+ [InlineData("AddParameterEB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 45, Pri = 2, Desc = "Param sent, global param used, local variable doesn't exist but reference to param exists", Params = new object[] { "AddParameterEB3.xsl", "outside param" })]
- [InlineData("AddParameterEB3.xsl", "outside param")]
+ [InlineData("AddParameterEB3.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 46, Pri = 2, Desc = "Param sent, global param used, local variable exists with a default value and with-param sends a value", Params = new object[] { "AddParameterEB4.xsl", "default local" })]
- [InlineData("AddParameterEB4.xsl", "default local")]
+ [InlineData("AddParameterEB4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 47, Pri = 2, Desc = "Param sent, global param used, local variable exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterEB5.xsl", "" })]
- [InlineData("AddParameterEB5.xsl", "")]
+ [InlineData("AddParameterEB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 48, Pri = 2, Desc = "Param sent, global param used, local variable doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterEB6.xsl", "outside param" })]
- [InlineData("AddParameterEB6.xsl", "outside param")]
+ [InlineData("AddParameterEB6.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 49, Pri = 2, Desc = "Param sent, global param used, local variable doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterEB7.xsl", "outside param" })]
- [InlineData("AddParameterEB7.xsl", "outside param")]
+ [InlineData("AddParameterEB7.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//global param is xsl:variable local param is xsl:variable
//[Variation(id = 50, Pri = 2, Desc = "Param sent, global variable used, local variable exists with a default value", Params = new object[] { "AddParameterFB1.xsl", "default local" })]
- [InlineData("AddParameterFB1.xsl", "default local")]
+ [InlineData("AddParameterFB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 51, Pri = 2, Desc = "Param sent, global variable used, local variable exists with no default value", Params = new object[] { "AddParameterFB2.xsl", "" })]
- [InlineData("AddParameterFB2.xsl", "")]
+ [InlineData("AddParameterFB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 52, Pri = 2, Desc = "Param sent, global variable used, local variable doesn't exist but reference to param exists", Params = new object[] { "AddParameterFB3.xsl", "default global" })]
- [InlineData("AddParameterFB3.xsl", "default global")]
+ [InlineData("AddParameterFB3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 53, Pri = 2, Desc = "Param sent, global variable used, local variable exists with a default value and with-param sends a value", Params = new object[] { "AddParameterFB4.xsl", "default local" })]
- [InlineData("AddParameterFB4.xsl", "default local")]
+ [InlineData("AddParameterFB4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 54, Pri = 2, Desc = "Param sent, global variable used, local variable exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterFB5.xsl", "" })]
- [InlineData("AddParameterFB5.xsl", "")]
+ [InlineData("AddParameterFB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 55, Pri = 2, Desc = "Param sent, global variable used, local variable doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterFB6.xsl", "default global" })]
- [InlineData("AddParameterFB6.xsl", "default global")]
+ [InlineData("AddParameterFB6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 56, Pri = 2, Desc = "Param sent, global variable used, local variable doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterFB7.xsl", "default global" })]
- [InlineData("AddParameterFB7.xsl", "default global")]
+ [InlineData("AddParameterFB7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam2(object param0, object param1)
+ public void AddParam2(object param0, object param1, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string xslFile = param0.ToString();
string expected = "<result>" + param1.ToString() + "</result>";
@@ -1769,7 +2331,7 @@ namespace System.Xml.Tests
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("param1", "", "outside param");
- if ((LoadXSL(xslFile) == 1) && (Transform_ArgList("AddParameter.xml") == 1))
+ if ((LoadXSL(xslFile, xslInputType, readerType) == 1) && (Transform_ArgList("AddParameter.xml", outputType, navType) == 1))
{
VerifyResult(expected);
return;
@@ -1781,21 +2343,77 @@ namespace System.Xml.Tests
//All the below variations, empty param is sent from client code
//global param is xsl:param local param is xsl:param
//[Variation(id = 57, Pri = 2, Desc = "Param sent, global param used, local param exists with a default value", Params = new object[] { "AddParameterB1.xsl", "default local" })]
- [InlineData("AddParameterB1.xsl", "default local")]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 58, Pri = 2, Desc = "Param sent, global param used, local param exists with no default value", Params = new object[] { "AddParameterB2.xsl", "" })]
- [InlineData("AddParameterB2.xsl", "")]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 59, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterB3.xsl", "" })]
- [InlineData("AddParameterB3.xsl", "")]
+ [InlineData("AddParameterB3.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 60, Pri = 2, Desc = "Param sent, global param used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterB4.xsl", "with-param" })]
- [InlineData("AddParameterB4.xsl", "with-param")]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 61, Pri = 2, Desc = "Param sent, global param used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterB5.xsl", "" })]
- [InlineData("AddParameterB5.xsl", "")]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 62, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterB6.xsl", "" })]
- [InlineData("AddParameterB6.xsl", "")]
+ [InlineData("AddParameterB6.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 63, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterB7.xsl", "" })]
- [InlineData("AddParameterB7.xsl", "")]
+ [InlineData("AddParameterB7.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddParam3(object param0, object param1)
+ public void AddParam3(object param0, object param1, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string xslFile = param0.ToString();
string expected = "<result>" + param1.ToString() + "</result>";
@@ -1803,7 +2421,7 @@ namespace System.Xml.Tests
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("param1", "", "");
- if ((LoadXSL(xslFile) == 1) && (Transform_ArgList("AddParameter.xml") == 1))
+ if ((LoadXSL(xslFile, xslInputType, readerType) == 1) && (Transform_ArgList("AddParameter.xml", outputType, navType) == 1))
{
VerifyResult(expected);
return;
@@ -1831,8 +2449,6 @@ namespace System.Xml.Tests
//[TestCase(Name = "XsltArgumentList - AddExtensionObject : Navigator, TextWriter", Desc = "NAVIGATOR,TEXTWRITER")]
public class CArgAddExtObj : XsltApiTestCaseBase2
{
- ///private PermissionSet nonePermSet = new PermissionSet(PermissionState.None);
-
private ITestOutputHelper _output;
public CArgAddExtObj(ITestOutputHelper output) : base(output)
{
@@ -1840,17 +2456,25 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "Basic Verification Test", Pri = 1, Param = "myObjectDef.txt")]
- [InlineData("myObjectDef.txt")]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject1(object param)
+ public void AddExtObject1(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
string Baseline = Path.Combine("baseline", (string)param);
- ///nonePermSet.PermitOnly();
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1869,12 +2493,10 @@ namespace System.Xml.Tests
try
{
- ///nonePermSet.PermitOnly(); ;
m_xsltArg.AddExtensionObject(null, obj);
}
catch (System.ArgumentNullException)
{
- ///CodeAccessPermission.RevertPermitOnly();
return;
}
_output.WriteLine("System.ArgumentNullException not generated for null namespace System.Xml.Tests");
@@ -1889,25 +2511,31 @@ namespace System.Xml.Tests
MyObject obj = new MyObject(3, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
m_xsltArg.AddExtensionObject(szEmpty, obj);
- ///CodeAccessPermission.RevertPermitOnly();
+
return;
}
//[Variation("Very long namespace System.Xml.Tests", Param = "myObjectLongNs.txt")]
- [InlineData("myObjectLongNS.txt")]
+ [InlineData("myObjectLongNS.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectLongNS.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectLongNS.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectLongNS.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectLongNS.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectLongNS.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectLongNS.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectLongNS.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectLongNS.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject4(object param)
+ public void AddExtObject4(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
m_xsltArg = new XsltArgumentList();
MyObject obj = new MyObject(4, _output);
string Baseline = Path.Combine("baseline", (string)param);
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szLongNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("myObjectLongNS.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("myObjectLongNS.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1923,9 +2551,8 @@ namespace System.Xml.Tests
{
MyObject obj = new MyObject(5, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szInvalid, obj);
- ///CodeAccessPermission.RevertPermitOnly();
return;
}
@@ -1937,7 +2564,7 @@ namespace System.Xml.Tests
MyObject obj1 = new MyObject(1, _output);
MyObject obj2 = new MyObject(2, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj1);
try
{
@@ -1945,7 +2572,6 @@ namespace System.Xml.Tests
}
catch (System.ArgumentException)
{
- ///CodeAccessPermission.RevertPermitOnly();
return;
}
_output.WriteLine("Did not launch exception 'System.ArgumentException' for an item already added");
@@ -1953,14 +2579,22 @@ namespace System.Xml.Tests
}
//[Variation("Case sensitivity", Param = "myObjectDef.txt")]
- [InlineData("myObjectDef.txt")]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject8(object param)
+ public void AddExtObject8(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
string Baseline = Path.Combine("baseline", (string)param);
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject("urn:my-object", obj);
retObj = m_xsltArg.GetExtensionObject("urn:my-object");
@@ -1972,8 +2606,8 @@ namespace System.Xml.Tests
m_xsltArg.AddExtensionObject("URN:MY-OBJECT", obj);
m_xsltArg.AddExtensionObject("urn:My-Object", obj);
m_xsltArg.AddExtensionObject("urn-my:object", obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -1992,12 +2626,10 @@ namespace System.Xml.Tests
try
{
- ///nonePermSet.PermitOnly(); ;
m_xsltArg.AddExtensionObject(szDefaultNS, null);
}
catch (System.ArgumentNullException)
{
- ///CodeAccessPermission.RevertPermitOnly();
return;
}
_output.WriteLine("Did not launch exception 'System.ArgumentNullException' for adding a null-valued item");
@@ -2005,32 +2637,55 @@ namespace System.Xml.Tests
}
//[Variation("Unitialized and NULL return values from the methods in the extension object")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject10()
+ public void AddExtObject10(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+
+ Test1
+ Test2: 0</result>";
+
MyObject obj = new MyObject(10, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("MyObject_Null.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(424.8906559839) == 1 || CheckResult(425.0247531107) == 1 /* for writer */))
+
+ if ((LoadXSL("MyObject_Null.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Add many objects", Param = "myObjectDef.txt")]
- [InlineData("myObjectDef.txt")]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject11(object param)
+ public void AddExtObject11(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
MyObject obj1 = new MyObject(100, _output);
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj1);
for (int i = 1; i < 500; i++)
@@ -2039,8 +2694,7 @@ namespace System.Xml.Tests
m_xsltArg.AddExtensionObject(szDefaultNS + i, obj);
}
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2050,26 +2704,32 @@ namespace System.Xml.Tests
}
//[Variation("Whitespace")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject12()
+ public void AddExtObject12(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
int i = 1;
m_xsltArg = new XsltArgumentList();
-
- ///nonePermSet.PermitOnly(); ;
+
foreach (String str in szWhiteSpace)
{
MyObject obj = new MyObject(i, _output);
m_xsltArg.AddExtensionObject(szDefaultNS + str, obj);
i++;
}
- ///CodeAccessPermission.RevertPermitOnly();
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2086,7 +2746,7 @@ namespace System.Xml.Tests
{
MyObject obj = new MyObject(13, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
try
{
@@ -2094,7 +2754,6 @@ namespace System.Xml.Tests
}
catch (System.ArgumentException)
{
- ///CodeAccessPermission.RevertPermitOnly();
return;
}
_output.WriteLine("Did not exception for adding an extension object that already exists");
@@ -2102,22 +2761,30 @@ namespace System.Xml.Tests
}
//[Variation("Add and Remove multiple times", Param = "myObjectDef.txt")]
- [InlineData("myObjectDef.txt")]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject14(object param)
+ public void AddExtObject14(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
MyObject obj = new MyObject(14, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
for (int i = 0; i < 400; i++)
{
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
m_xsltArg.RemoveExtensionObject(szDefaultNS);
}
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2127,19 +2794,27 @@ namespace System.Xml.Tests
}
//[Variation("Namespace URI non-existent")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject15()
+ public void AddExtObject15(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(15, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szSimple, obj);
- ///CodeAccessPermission.RevertPermitOnly();
+
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2150,33 +2825,41 @@ namespace System.Xml.Tests
}
//[Variation("Accessing Private and protected Items")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject16()
+ public void AddExtObject16(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
+
try
{
- LoadXSL("MyObject_PrivateAccess.xsl");
- Transform_ArgList("fruits.xml", true);
+ LoadXSL("MyObject_PrivateAccess.xsl", xslInputType, readerType);
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
try
{
- LoadXSL("MyObject_ProtectedAccess.xsl");
- Transform_ArgList("fruits.xml", true);
+ LoadXSL("MyObject_ProtectedAccess.xsl", xslInputType, readerType);
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
try
{
- LoadXSL("MyObject_DefaultAccess.xsl");
- Transform_ArgList("fruits.xml", true);
+ LoadXSL("MyObject_DefaultAccess.xsl", xslInputType, readerType);
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2188,34 +2871,56 @@ namespace System.Xml.Tests
}
//[Variation("Writing To Output")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject17()
+ public void AddExtObject17(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ Here:End
+ </result>";
+
MyObject obj = new MyObject(17, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("MyObject_ConsoleWrite.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(421.8660259804) == 1 || CheckResult(421.8527116762) == 1 /* for writer */))
+
+ if ((LoadXSL("MyObject_ConsoleWrite.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Recursive Functions", Param = "myObject_Recursion.txt")]
- [InlineData("MyObject_Recursion.txt")]
+ [InlineData("MyObject_Recursion.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_Recursion.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_Recursion.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_Recursion.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_Recursion.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_Recursion.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_Recursion.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_Recursion.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_Recursion.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject18(object param)
+ public void AddExtObject18(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(18, _output);
m_xsltArg = new XsltArgumentList();
string Baseline = Path.Combine("baseline", (string)param);
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("MyObject_Recursion.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("MyObject_Recursion.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2225,17 +2930,25 @@ namespace System.Xml.Tests
}
//[Variation("Function-exists tests", Param = "MyObject_FnExists.txt")]
- [InlineData("MyObject_FnExists.txt")]
+ [InlineData("MyObject_FnExists.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_FnExists.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_FnExists.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_FnExists.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_FnExists.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_FnExists.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_FnExists.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_FnExists.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_FnExists.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject20(object param)
+ public void AddExtObject20(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
MyObject obj = new MyObject(20, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("MyObject_FnExists.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("MyObject_FnExists.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2245,17 +2958,25 @@ namespace System.Xml.Tests
}
//[Variation("Argument Tests", Param = "MyObject_Arguments.txt")]
- [InlineData("MyObject_Arguments.txt")]
+ [InlineData("MyObject_Arguments.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_Arguments.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_Arguments.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_Arguments.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_Arguments.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_Arguments.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_Arguments.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_Arguments.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_Arguments.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject21(object param)
+ public void AddExtObject21(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("MyObject_Arguments.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("MyObject_Arguments.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2273,7 +2994,7 @@ namespace System.Xml.Tests
double d = 1;
int i = 1;
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject("urn:myspace", d);
try
{
@@ -2281,7 +3002,6 @@ namespace System.Xml.Tests
}
catch (System.ArgumentException)
{
- ///CodeAccessPermission.RevertPermitOnly();
return;
}
_output.WriteLine("Exception not thrown for URI namespace System.Xml.Tests in use");
@@ -2289,21 +3009,29 @@ namespace System.Xml.Tests
}
//[Variation("Case Sensitivity")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject25()
+ public void AddExtObject25(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(25, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if (LoadXSL("MyObject_CaseSensitive.xsl") == 1)
+
+ if (LoadXSL("MyObject_CaseSensitive.xsl", xslInputType, readerType) == 1)
{
try
{
- Transform_ArgList("fruits.xml");
- CheckResult(419.3031944636);
+ Transform_ArgList("fruits.xml", outputType, navType);
+ CheckResult(419.3031944636, outputType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2315,20 +3043,28 @@ namespace System.Xml.Tests
}
//[Variation("Object namespace System.Xml.Tests found")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject26()
+ public void AddExtObject26(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(26, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("MyObject_NotFoundNS.xsl") == 1))
+
+ if ((LoadXSL("MyObject_NotFoundNS.xsl", xslInputType, readerType) == 1))
{
try
{
- Transform_ArgList("fruits.xml", true);
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2340,17 +3076,25 @@ namespace System.Xml.Tests
}
//[Variation("Maintaining State", Param = "MyObject_KeepingState.txt")]
- [InlineData("MyObject_KeepingState.txt")]
+ [InlineData("MyObject_KeepingState.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_KeepingState.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_KeepingState.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_KeepingState.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_KeepingState.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_KeepingState.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_KeepingState.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_KeepingState.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_KeepingState.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject27(object param)
+ public void AddExtObject27(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(27, _output);
m_xsltArg = new XsltArgumentList();
string Baseline = Path.Combine("baseline", (string)param);
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("MyObject_KeepingState.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("MyObject_KeepingState.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2360,20 +3104,27 @@ namespace System.Xml.Tests
}
//[Variation("Deliberately Messing Up the Stylesheet", Param = "MyObject_KillerStrings.txt")]
- [ActiveIssue(9877)]
- [InlineData("MyObject_KillerStrings.txt")]
+ [InlineData("MyObject_KillerStrings.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_KillerStrings.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_KillerStrings.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_KillerStrings.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_KillerStrings.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_KillerStrings.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("MyObject_KillerStrings.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("MyObject_KillerStrings.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("MyObject_KillerStrings.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject28(object param)
+ public void AddExtObject28(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(28, _output);
m_xsltArg = new XsltArgumentList();
string Baseline = Path.Combine("baseline", (string)param);
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("MyObject_KillerStrings.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("MyObject_KillerStrings.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
- if (MyOutputType() == OutputType.Writer)
+ if (outputType == OutputType.Writer)
/* writer output is slighlty different which causes a mismatch so we won't compare */
return;
VerifyResult(Baseline, _strOutFile);
@@ -2384,20 +3135,28 @@ namespace System.Xml.Tests
}
//[Variation("Function not found in Object")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject29()
+ public void AddExtObject29(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(29, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("MyObject_NotFound.xsl") == 1))
+
+ if ((LoadXSL("MyObject_NotFound.xsl", xslInputType, readerType) == 1))
{
try
{
- Transform_ArgList("fruits.xml", true);
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2415,30 +3174,37 @@ namespace System.Xml.Tests
{
MyObject obj = new MyObject(31, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szXslNS, obj);
retObj = m_xsltArg.GetExtensionObject(szXslNS);
- ///CodeAccessPermission.RevertPermitOnly();
Assert.Equal(retObj, obj);
}
//[Variation("Extension objects should not be cached during Transform()", Param = "Bug78587")]
- [InlineData("Bug78587")]
+ [InlineData("Bug78587", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("Bug78587", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("Bug78587", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("Bug78587", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("Bug78587", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("Bug78587", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("Bug78587", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("Bug78587", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("Bug78587", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject32(object param)
+ public void AddExtObject32(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline1 = Path.Combine("baseline", (string)param) + "a.txt";
string Baseline2 = Path.Combine("baseline", (string)param) + "b.txt";
- if (LoadXSL("Bug78587.xsl") == 1)
+ if (LoadXSL("Bug78587.xsl", xslInputType, readerType) == 1)
{
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject("id", new Id("first"));
m_xsltArg.AddExtensionObject("capitalizer", new Capitalizer());
// Transform once
- if (Transform_ArgList("Bug78587.xml") == 1)
+ if (Transform_ArgList("Bug78587.xml", outputType, navType) == 1)
{
VerifyResult(Baseline1, _strOutFile);
m_xsltArg = new XsltArgumentList();
@@ -2446,7 +3212,7 @@ namespace System.Xml.Tests
m_xsltArg.AddExtensionObject("capitalizer", new Capitalizer());
// Transform again to make sure that extension objects from first transform are not cached
- if (Transform_ArgList("Bug78587.xml") == 1)
+ if (Transform_ArgList("Bug78587.xml", outputType, navType) == 1)
{
VerifyResult(Baseline2, _strOutFile);
return;
@@ -2456,39 +3222,98 @@ namespace System.Xml.Tests
Assert.True(false);
}
- //[Variation(id = 36, Desc = "Calling extension object from select in xsl:sort", Params = new object[] { "sort.xsl", "sort.txt" })]
- [InlineData("sort.xsl", "sort.txt")]
- [Theory]
- public void AddExtObject33_ActiveIssue9997(object param0, object param1)
- {
- AddExtObject33(param0, param1);
- }
-
//[Variation(id = 33, Desc = "Calling extension object from select in xsl:apply-templates", Params = new object[] { "apply-templates.xsl", "apply-templates.txt" })]
- [InlineData("apply-templates.xsl", "apply-templates.txt")]
+ [InlineData("apply-templates.xsl", "apply-templates.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("apply-templates.xsl", "apply-templates.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("apply-templates.xsl", "apply-templates.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("apply-templates.xsl", "apply-templates.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("apply-templates.xsl", "apply-templates.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("apply-templates.xsl", "apply-templates.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("apply-templates.xsl", "apply-templates.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("apply-templates.xsl", "apply-templates.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("apply-templates.xsl", "apply-templates.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 34, Desc = "Calling extension object from select in xsl:for-each", Params = new object[] { "for-each.xsl", "for-each.txt" })]
- [InlineData("for-each.xsl", "for-each.txt")]
+ [InlineData("for-each.xsl", "for-each.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("for-each.xsl", "for-each.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("for-each.xsl", "for-each.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("for-each.xsl", "for-each.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("for-each.xsl", "for-each.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("for-each.xsl", "for-each.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("for-each.xsl", "for-each.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("for-each.xsl", "for-each.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("for-each.xsl", "for-each.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 35, Desc = "Calling extension object from select in xsl:copy-of", Params = new object[] { "copy-of.xsl", "copy-of.txt" })]
- [InlineData("copy-of.xsl", "copy-of.txt")]
+ [InlineData("copy-of.xsl", "copy-of.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("copy-of.xsl", "copy-of.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("copy-of.xsl", "copy-of.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("copy-of.xsl", "copy-of.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("copy-of.xsl", "copy-of.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("copy-of.xsl", "copy-of.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("copy-of.xsl", "copy-of.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("copy-of.xsl", "copy-of.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("copy-of.xsl", "copy-of.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 37, Desc = "Calling extension object from select in xsl:variable", Params = new object[] { "variable.xsl", "variable.txt" })]
- [InlineData("variable.xsl", "variable.txt")]
+ [InlineData("variable.xsl", "variable.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable.xsl", "variable.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable.xsl", "variable.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("variable.xsl", "variable.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable.xsl", "variable.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable.xsl", "variable.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("variable.xsl", "variable.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable.xsl", "variable.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable.xsl", "variable.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 38, Desc = "Calling extension object from select in xsl:param", Params = new object[] { "param.xsl", "param.txt" })]
- [InlineData("param.xsl", "param.txt")]
+ [InlineData("param.xsl", "param.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param.xsl", "param.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param.xsl", "param.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("param.xsl", "param.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param.xsl", "param.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param.xsl", "param.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("param.xsl", "param.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param.xsl", "param.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param.xsl", "param.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 39, Desc = "Calling extension object from select in xsl:with-param", Params = new object[] { "with-param.xsl", "with-param.txt" })]
- [InlineData("with-param.xsl", "with-param.txt")]
+ [InlineData("with-param.xsl", "with-param.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("with-param.xsl", "with-param.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("with-param.xsl", "with-param.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("with-param.xsl", "with-param.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("with-param.xsl", "with-param.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("with-param.xsl", "with-param.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("with-param.xsl", "with-param.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("with-param.xsl", "with-param.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("with-param.xsl", "with-param.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 40, Desc = "Calling extension object from select in xsl:value-of", Params = new object[] { "value-of.xsl", "value-of.txt" })]
- [InlineData("value-of.xsl", "value-of.txt")]
+ [InlineData("value-of.xsl", "value-of.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("value-of.xsl", "value-of.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("value-of.xsl", "value-of.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("value-of.xsl", "value-of.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("value-of.xsl", "value-of.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("value-of.xsl", "value-of.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("value-of.xsl", "value-of.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("value-of.xsl", "value-of.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("value-of.xsl", "value-of.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ //[Variation(id = 36, Desc = "Calling extension object from select in xsl:sort", Params = new object[] { "sort.xsl", "sort.txt" })]
+ [InlineData("sort.xsl", "sort.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("sort.xsl", "sort.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("sort.xsl", "sort.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("sort.xsl", "sort.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("sort.xsl", "sort.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("sort.xsl", "sort.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("sort.xsl", "sort.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("sort.xsl", "sort.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("sort.xsl", "sort.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+
[Theory]
- public void AddExtObject33(object param0, object param1)
+ public void AddExtObject33(object param0, object param1, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
ExObj obj = new ExObj(0, _output);
m_xsltArg = new XsltArgumentList();
string xslFile = param0.ToString();
string Baseline = Path.Combine("baseline", param1.ToString());
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject("urn-myobject", obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL(xslFile) == 1) && (Transform_ArgList("ExtData.xml") == 1))
+
+ if ((LoadXSL(xslFile, xslInputType, readerType) == 1) && (Transform_ArgList("ExtData.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2498,19 +3323,67 @@ namespace System.Xml.Tests
}
//[Variation(id = 41, Desc = "Calling extension function from select in xsl:variable and variable is used for incrementing an integer", Params = new object[] { "variable2.xsl", "variable2.txt" })]
- [InlineData("variable2.xsl", "variable2.txt")]
+ [InlineData("variable2.xsl", "variable2.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable2.xsl", "variable2.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable2.xsl", "variable2.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("variable2.xsl", "variable2.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable2.xsl", "variable2.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable2.xsl", "variable2.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("variable2.xsl", "variable2.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable2.xsl", "variable2.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable2.xsl", "variable2.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 42, Desc = "Calling extension function from select in xsl:variable but variable is never used", Params = new object[] { "variable3.xsl", "variable3.txt" })]
- [InlineData("variable3.xsl", "variable3.txt")]
+ [InlineData("variable3.xsl", "variable3.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable3.xsl", "variable3.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable3.xsl", "variable3.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("variable3.xsl", "variable3.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable3.xsl", "variable3.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable3.xsl", "variable3.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("variable3.xsl", "variable3.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable3.xsl", "variable3.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable3.xsl", "variable3.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 43, Desc = "Calling extension function from select in global xsl:variable but variable is never used", Params = new object[] { "variable4.xsl", "variable4.txt" })]
- [InlineData("variable4.xsl", "variable4.txt")]
+ [InlineData("variable4.xsl", "variable4.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable4.xsl", "variable4.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable4.xsl", "variable4.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("variable4.xsl", "variable4.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable4.xsl", "variable4.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable4.xsl", "variable4.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("variable4.xsl", "variable4.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("variable4.xsl", "variable4.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("variable4.xsl", "variable4.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 44, Desc = "Calling extension function from select in xsl:param and parameter is used for incrementing an integer", Params = new object[] { "param2.xsl", "param2.txt" })]
- [InlineData("param2.xsl", "param2.txt")]
+ [InlineData("param2.xsl", "param2.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param2.xsl", "param2.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param2.xsl", "param2.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("param2.xsl", "param2.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param2.xsl", "param2.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param2.xsl", "param2.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("param2.xsl", "param2.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param2.xsl", "param2.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param2.xsl", "param2.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 45, Desc = "Calling extension function from select in xsl:param but parameter is never used", Params = new object[] { "param3.xsl", "param3.txt" })]
- [InlineData("param3.xsl", "param3.txt")]
+ [InlineData("param3.xsl", "param3.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param3.xsl", "param3.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param3.xsl", "param3.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("param3.xsl", "param3.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param3.xsl", "param3.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param3.xsl", "param3.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("param3.xsl", "param3.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param3.xsl", "param3.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param3.xsl", "param3.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
//[Variation(id = 46, Desc = "Calling extension function from select in global xsl:param but parameter is never used", Params = new object[] { "param4.xsl", "param4.txt" })]
- [InlineData("param4.xsl", "param4.txt")]
+ [InlineData("param4.xsl", "param4.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param4.xsl", "param4.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param4.xsl", "param4.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("param4.xsl", "param4.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param4.xsl", "param4.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param4.xsl", "param4.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("param4.xsl", "param4.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("param4.xsl", "param4.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("param4.xsl", "param4.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void AddExtObject41(object param0, object param1)
+ public void AddExtObject41(object param0, object param1, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
/*
* In these variations, the XSLT calls the extension function Increment from XSLT.
@@ -2521,10 +3394,10 @@ namespace System.Xml.Tests
m_xsltArg = new XsltArgumentList();
string xslFile = param0.ToString();
string Baseline = "baseline" + Path.DirectorySeparatorChar + param1.ToString();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject("urn-myobject", obj);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL(xslFile) == 1) && (Transform_ArgList("ExtData.xml") == 1))
+
+ if ((LoadXSL(xslFile, xslInputType, readerType) == 1) && (Transform_ArgList("ExtData.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2580,9 +3453,12 @@ namespace System.Xml.Tests
}
//[Variation(id = 1, Desc = "Basic Verification Test", Pri = 1, Param = "RemoveParam1.txt")]
- [InlineData("RemoveParam1.txt")]
+ [InlineData("RemoveParam1.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("RemoveParam1.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("RemoveParam1.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("RemoveParam1.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam1(object param)
+ public void RemoveParam1(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
m_xsltArg = new XsltArgumentList();
@@ -2605,7 +3481,7 @@ namespace System.Xml.Tests
}
_baseline = Path.Combine("baseline", (string)param);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(_baseline, "out.xml");
return;
@@ -2630,15 +3506,18 @@ namespace System.Xml.Tests
}
//[Variation("Param name is empty string", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam3(object param)
+ public void RemoveParam3(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
m_xsltArg.RemoveParam(szEmpty, szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2648,15 +3527,18 @@ namespace System.Xml.Tests
}
//[Variation("Param name is non-existent", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam4(object param)
+ public void RemoveParam4(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
m_xsltArg.RemoveParam(szSimple, szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2666,15 +3548,18 @@ namespace System.Xml.Tests
}
//[Variation("Invalid Param name", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam5(object param)
+ public void RemoveParam5(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
m_xsltArg.RemoveParam(szInvalid, szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2684,9 +3569,12 @@ namespace System.Xml.Tests
}
//[Variation("Very long param name", Param = "showParamLongName.txt")]
- [InlineData("showParamLongName.txt")]
+ [InlineData("showParamLongName.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParamLongName.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParamLongName.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParamLongName.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam6(object param)
+ public void RemoveParam6(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -2694,7 +3582,7 @@ namespace System.Xml.Tests
m_xsltArg.AddParam(szLongString, szEmpty, "Test1");
m_xsltArg.RemoveParam(szLongString, szEmpty);
- if ((LoadXSL("showParamLongName.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParamLongName.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2720,9 +3608,12 @@ namespace System.Xml.Tests
}
//[Variation("Namespace URI is empty string", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam8(object param)
+ public void RemoveParam8(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -2730,7 +3621,7 @@ namespace System.Xml.Tests
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
m_xsltArg.RemoveParam("myArg1", szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2740,9 +3631,12 @@ namespace System.Xml.Tests
}
//[Variation("Namespace URI is non-existent", Param = "RemoveParam9.txt")]
- [InlineData("RemoveParam9.txt")]
+ [InlineData("RemoveParam9.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("RemoveParam9.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("RemoveParam9.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("RemoveParam9.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam9(object param)
+ public void RemoveParam9(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -2750,7 +3644,7 @@ namespace System.Xml.Tests
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
m_xsltArg.RemoveParam("myArg1", "http://www.xsltTest.com");
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2760,9 +3654,12 @@ namespace System.Xml.Tests
}
//[Variation("Very long namespace System.Xml.Tests", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam10(object param)
+ public void RemoveParam10(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -2770,7 +3667,7 @@ namespace System.Xml.Tests
m_xsltArg.AddParam("myArg1", szLongString, "Test1");
m_xsltArg.RemoveParam("myArg1", szLongString);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2780,9 +3677,12 @@ namespace System.Xml.Tests
}
//[Variation("Different Data Types", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam11(object param)
+ public void RemoveParam11(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
@@ -2975,7 +3875,7 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -2985,9 +3885,12 @@ namespace System.Xml.Tests
}
//[Variation("Case Sensitivity", Param = "RemoveParam12.txt")]
- [InlineData("RemoveParam12.txt")]
+ [InlineData("RemoveParam12.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("RemoveParam12.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("RemoveParam12.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("RemoveParam12.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam12(object param)
+ public void RemoveParam12(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -2998,7 +3901,7 @@ namespace System.Xml.Tests
m_xsltArg.RemoveParam("myArg1 ", szEmpty);
// perform a transform for kicks and ensure all is ok.
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3008,9 +3911,12 @@ namespace System.Xml.Tests
}
//[Variation("Whitespace", Param = "RemoveParam13.txt")]
- [InlineData("RemoveParam13.txt")]
+ [InlineData("RemoveParam13.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("RemoveParam13.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("RemoveParam13.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("RemoveParam13.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam13(object param)
+ public void RemoveParam13(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
int i = 1;
@@ -3044,7 +3950,7 @@ namespace System.Xml.Tests
}
// perform a transform for kicks and ensure all is ok.
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3054,9 +3960,12 @@ namespace System.Xml.Tests
}
//[Variation("Call Multiple Times", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
[Theory]
- public void RemoveParam14(object param)
+ public void RemoveParam14(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -3066,7 +3975,7 @@ namespace System.Xml.Tests
for (int i = 0; i < 500; i++)
m_xsltArg.RemoveParam("myArg1", szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3097,8 +4006,6 @@ namespace System.Xml.Tests
//[TestCase(Name = "XsltArgumentList - RemoveExtensionObject : Navigator, Stream", Desc = "NAVIGATOR,STREAM")]
public class CArgRemoveExtObj : XsltApiTestCaseBase2
{
- ///private PermissionSet nonePermSet = new PermissionSet(PermissionState.None);
-
private ITestOutputHelper _output;
public CArgRemoveExtObj(ITestOutputHelper output) : base(output)
{
@@ -3106,21 +4013,23 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "Basic Verification Test", Pri = 1)]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void RemoveExtObj1()
+ public void RemoveExtObj1(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
m_xsltArg.RemoveExtensionObject(szDefaultNS);
- ///CodeAccessPermission.RevertPermitOnly();
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -3151,19 +4060,22 @@ namespace System.Xml.Tests
}
//[Variation("Call Multiple Times", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void RemoveExtObj3(object param)
+ public void RemoveExtObj3(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
MyObject obj = new MyObject(10, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
for (int i = 0; i < 500; i++)
m_xsltArg.RemoveExtensionObject(szDefaultNS);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3173,18 +4085,21 @@ namespace System.Xml.Tests
}
//[Variation("Namespace URI is non-existent", Param = "MyObjectDef.txt")]
- [InlineData("myObjectDef.txt")]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void RemoveExtObj4(object param)
+ public void RemoveExtObj4(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
MyObject obj = new MyObject(4, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
m_xsltArg.RemoveExtensionObject(szSimple);
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3194,20 +4109,23 @@ namespace System.Xml.Tests
}
//[Variation("Very long namespace System.Xml.Tests")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void RemoveExtObj5()
+ public void RemoveExtObj5(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
m_xsltArg = new XsltArgumentList();
MyObject obj = new MyObject(5, _output);
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject("urn:" + szLongNS, obj);
m_xsltArg.RemoveExtensionObject("urn:" + szLongNS);
- ///CodeAccessPermission.RevertPermitOnly();
+
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -3218,14 +4136,17 @@ namespace System.Xml.Tests
}
//[Variation("Different Data Types", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void RemoveExtObj6(object param)
+ public void RemoveExtObj6(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
MyObject obj = new MyObject(6, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject("urn:my-object", obj);
m_xsltArg.RemoveExtensionObject("urn:my-object");
@@ -3243,8 +4164,8 @@ namespace System.Xml.Tests
m_xsltArg.AddExtensionObject("urn:my-object", false);
m_xsltArg.RemoveExtensionObject("urn:my-object");
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3254,22 +4175,25 @@ namespace System.Xml.Tests
}
//[Variation("Case Sensitivity", Param = "MyObjectDef.txt")]
- [InlineData("myObjectDef.txt")]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("myObjectDef.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void RemoveExtObj7(object param)
+ public void RemoveExtObj7(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(7, _output);
m_xsltArg = new XsltArgumentList();
string Baseline = Path.Combine("baseline", (string)param);
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.AddExtensionObject("urn:my-object", obj);
m_xsltArg.RemoveExtensionObject("URN:MY-OBJECT");
m_xsltArg.RemoveExtensionObject("urn:My-Object");
m_xsltArg.RemoveExtensionObject("urn-my:object");
m_xsltArg.RemoveExtensionObject("urn:my-object ");
- ///CodeAccessPermission.RevertPermitOnly();
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3279,13 +4203,16 @@ namespace System.Xml.Tests
}
//[Variation("Whitespace")]
- [InlineData()]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void RemoveExtObj8()
+ public void RemoveExtObj8(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
int i = 1;
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
foreach (String str in szWhiteSpace)
{
MyObject obj = new MyObject(i, _output);
@@ -3300,12 +4227,11 @@ namespace System.Xml.Tests
}
i++;
}
- ///CodeAccessPermission.RevertPermitOnly();
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", outputType, navType, true);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -3316,18 +4242,21 @@ namespace System.Xml.Tests
}
//[Variation("Using default XSLT namespace", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Reader, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
+ [InlineData("showParam.txt", XslInputType.Navigator, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void RemoveExtObj9(object param)
+ public void RemoveExtObj9(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
MyObject obj = new MyObject(10, _output);
m_xsltArg = new XsltArgumentList();
- ///nonePermSet.PermitOnly(); ;
+
m_xsltArg.RemoveExtensionObject(szDefaultNS);
- ///CodeAccessPermission.RevertPermitOnly();
+
// ensure we can still do a transform
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3351,9 +4280,9 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "Basic Verification Test", Pri = 1, Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void Clear1(object param)
+ public void Clear1(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -3368,7 +4297,7 @@ namespace System.Xml.Tests
if (retObj != null)
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3378,15 +4307,15 @@ namespace System.Xml.Tests
}
//[Variation("Clear with nothing loaded", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void Clear2(object param)
+ public void Clear2(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
m_xsltArg.Clear();
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3396,9 +4325,9 @@ namespace System.Xml.Tests
}
//[Variation("Clear Params", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void Clear3(object param)
+ public void Clear3(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -3413,7 +4342,7 @@ namespace System.Xml.Tests
if (retObj != null)
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3423,9 +4352,9 @@ namespace System.Xml.Tests
}
//[Variation("Clear Extension Objects")]
- [InlineData()]
+ [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void Clear4()
+ public void Clear4(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
MyObject obj = new MyObject(26, _output);
m_xsltArg = new XsltArgumentList();
@@ -3439,11 +4368,11 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("myObjectDef.xsl") == 1))
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
{
try
{
- Transform_ArgList("fruits.xml");
+ Transform_ArgList("fruits.xml", outputType, navType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -3455,9 +4384,9 @@ namespace System.Xml.Tests
}
//[Variation("Clear Many Objects", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void Clear5(object param)
+ public void Clear5(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -3488,11 +4417,9 @@ namespace System.Xml.Tests
}
}
- // _output.WriteLine(retObj.GetType());
-
m_xsltArg.Clear();
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3502,9 +4429,9 @@ namespace System.Xml.Tests
}
//[Variation("Clear Multiple Times", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void Clear6(object param)
+ public void Clear6(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -3520,7 +4447,7 @@ namespace System.Xml.Tests
if (retObj != null)
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3530,9 +4457,9 @@ namespace System.Xml.Tests
}
//[Variation("Loading one object, but clearing another", Param = "ClearParam7.txt")]
- [InlineData("ClearParam7.txt")]
+ [InlineData("ClearParam7.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void Clear7(object param)
+ public void Clear7(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -3545,7 +4472,7 @@ namespace System.Xml.Tests
m_2.Clear();
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) == 1) && (Transform_ArgList("fruits.xml", outputType, navType) == 1))
{
VerifyResult(Baseline, _strOutFile);
return;
@@ -3555,9 +4482,9 @@ namespace System.Xml.Tests
}
//[Variation("Clear after objects have been \"Removed\"", Param = "showParam.txt")]
- [InlineData("showParam.txt")]
+ [InlineData("showParam.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)]
[Theory]
- public void Clear8(object param)
+ public void Clear8(object param, XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType)
{
string Baseline = Path.Combine("baseline", (string)param);
m_xsltArg = new XsltArgumentList();
@@ -3569,7 +4496,7 @@ namespace System.Xml.Tests
retObj = m_xsltArg.RemoveParam("myArg1", szEmpty);
m_xsltArg.Clear();
- if ((LoadXSL("showParam.xsl") != 1) || (Transform_ArgList("fruits.xml") != 1))
+ if ((LoadXSL("showParam.xsl", xslInputType, readerType) != 1) || (Transform_ArgList("fruits.xml", outputType, navType) != 1))
Assert.True(false);
VerifyResult(Baseline, _strOutFile);
@@ -3580,11 +4507,11 @@ namespace System.Xml.Tests
m_xsltArg.RemoveExtensionObject(szDefaultNS);
m_xsltArg.Clear();
- if ((LoadXSL("myObjectDef.xsl") == 1))
+ if ((LoadXSL("myObjectDef.xsl", xslInputType, readerType) == 1))
{
try
{
- Transform_ArgList("fruits.xml");
+ Transform_ArgList("fruits.xml", outputType, navType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -3730,62 +4657,63 @@ namespace System.Xml.Tests
}
//[Variation(id = 1, Desc = "Call Current without MoveNext")]
- [ActiveIssue(9873)]
[InlineData()]
[Theory]
public void NodeIter1()
{
- if (_isInProc)
- return; //TEST_SKIPPED;
-
- XslCompiledTransform xslt = new XslCompiledTransform();
+ var e = Assert.ThrowsAny<XsltException>(() =>
+ {
+ XslCompiledTransform xslt = new XslCompiledTransform();
- XsltArgumentList xslArg = new XsltArgumentList();
- XmlUrlResolver ur = new XmlUrlResolver();
- Uri uriSource = ur.ResolveUri(null, FullFilePath("sample.xsd"));
- xslArg.AddParam("sourceUri", String.Empty, uriSource.ToString());
+ XsltArgumentList xslArg = new XsltArgumentList();
+ XmlUrlResolver ur = new XmlUrlResolver();
+ Uri uriSource = ur.ResolveUri(null, FullFilePath("sample.xsd"));
+ xslArg.AddParam("sourceUri", String.Empty, uriSource.ToString());
- xslt.Load(FullFilePath("xsd2cs1.xsl"), new XsltSettings(true, true), new XmlUrlResolver());
+ xslt.Load(FullFilePath("xsd2cs1.xsl"), new XsltSettings(true, true), new XmlUrlResolver());
+ XPathDocument doc = new XPathDocument(FullFilePath("sample.xsd"));
+ StringWriter sw = new StringWriter();
+ try
+ {
+ xslt.Transform(doc, xslArg, sw);
+ sw.Dispose();
+ _output.WriteLine("No exception is thrown when .Current is called before .MoveNext on XPathNodeIterator");
+ Assert.True(false);
+ }
+ catch (System.InvalidOperationException ex)
+ {
+ _output.WriteLine(ex.ToString());
+ return;
+ }
+ });
- XPathDocument doc = new XPathDocument(FullFilePath("sample.xsd"));
- StringWriter sw = new StringWriter();
- try
- {
- xslt.Transform(doc, xslArg, sw);
- sw.Dispose();
- _output.WriteLine("No exception is thrown when .Current is called before .MoveNext on XPathNodeIterator");
- Assert.True(false);
- }
- catch (System.InvalidOperationException ex)
- {
- _output.WriteLine(ex.ToString());
- return;
- }
+ Assert.Equal("Compiling JScript/CSharp scripts is not supported", e.InnerException.Message);
}
//[Variation(id = 2, Desc = "Call Current after MoveNext")]
- [ActiveIssue(9873)]
[InlineData()]
[Theory]
public void NodeIter2()
{
- if (_isInProc)
- return; //TEST_SKIPPED;
+ var e = Assert.ThrowsAny<XsltException>(() =>
+ {
+ XslCompiledTransform xslt = new XslCompiledTransform();
- XslCompiledTransform xslt = new XslCompiledTransform();
+ XsltArgumentList xslArg = new XsltArgumentList();
+ XmlUrlResolver ur = new XmlUrlResolver();
+ Uri uriSource = ur.ResolveUri(null, FullFilePath("sample.xsd"));
+ xslArg.AddParam("sourceUri", String.Empty, uriSource.ToString());
- XsltArgumentList xslArg = new XsltArgumentList();
- XmlUrlResolver ur = new XmlUrlResolver();
- Uri uriSource = ur.ResolveUri(null, FullFilePath("sample.xsd"));
- xslArg.AddParam("sourceUri", String.Empty, uriSource.ToString());
+ xslt.Load(FullFilePath("xsd2cs2.xsl"), new XsltSettings(true, true), new XmlUrlResolver());
- xslt.Load(FullFilePath("xsd2cs2.xsl"), new XsltSettings(true, true), new XmlUrlResolver());
+ XPathDocument doc = new XPathDocument(FullFilePath("sample.xsd"));
+ StringWriter sw = new StringWriter();
+ xslt.Transform(doc, xslArg, sw);
+ sw.Dispose();
+ return;
+ });
- XPathDocument doc = new XPathDocument(FullFilePath("sample.xsd"));
- StringWriter sw = new StringWriter();
- xslt.Transform(doc, xslArg, sw);
- sw.Dispose();
- return;
+ Assert.Equal("Compiling JScript/CSharp scripts is not supported", e.InnerException.Message);
}
}
}
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentListMultith.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentListMultith.cs
index 71a86e03bb..1df71c169d 100644
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentListMultith.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltArgumentListMultith.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using XmlCoreTest.Common;
@@ -28,7 +26,7 @@ namespace System.Xml.Tests
Init(null);
}
- public /*override*/ new void Init(object objParam)
+ public new void Init(object objParam)
{
// Get parameter info
_strPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltApiV2\");
diff --git a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs
index 6e5c003ce7..69265ea40a 100644
--- a/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs
@@ -5,7 +5,6 @@
using Xunit;
using Xunit.Abstractions;
using System.IO;
-using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
@@ -25,16 +24,8 @@ namespace System.Xml.Tests
private string _xmlFile = string.Empty;
private string _xslFile = string.Empty;
- private bool _debug = false;
-
private void Init(string xmlFile, string xslFile)
{
- //if (Param.ToString() == "Debug")
- //{
- // xsl = new XslCompiledTransform(true);
- // _debug = true;
- //}
- //else
_xsl = new XslCompiledTransform();
_xmlFile = FullFilePath(xmlFile);
@@ -56,7 +47,6 @@ namespace System.Xml.Tests
Assert.Equal(actual, expected);
}
- [ActiveIssue(9873)]
//[Variation(id = 1, Desc = "Test the script block with EnableScript, should work", Pri = 0, Params = new object[] { "XsltSettings.xml", "XsltSettings1.xsl", false, true })]
[InlineData(1, "XsltSettings.xml", "XsltSettings1.xsl", false, true)]
//[Variation(id = 4, Desc = "Test the script block with TrustedXslt, should work", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings1.xsl", true, true })]
@@ -66,9 +56,10 @@ namespace System.Xml.Tests
//[Variation(id = 11, Desc = "Test the combination of script and document function with EnableScript, only script should work", Pri = 2, Params = new object[] { "XsltSettings.xml", "XsltSettings3.xsl", false, true })]
[InlineData(11, "XsltSettings.xml", "XsltSettings3.xsl", false, true)]
[Theory]
- public void XsltSettings1__1ActiveIssue9873(object param0, object param1, object param2, object param3, object param4)
+ public void XsltSettings1_1_ContainsScript(object param0, object param1, object param2, object param3, object param4)
{
- XsltSettings1_1(param0, param1, param2, param3, param4);
+ var e = Assert.ThrowsAny<XsltException>(() => XsltSettings1_1(param0, param1, param2, param3, param4));
+ Assert.Equal("Compiling JScript/CSharp scripts is not supported", e.InnerException.Message);
}
//[Variation(id = 15, Desc = "Test 1 with Default settings, should fail", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings1.xsl", false, true, false, false })]
@@ -79,28 +70,32 @@ namespace System.Xml.Tests
[InlineData(19, "XsltSettings.xml", "XsltSettings3.xsl", true, true, false, false)]
//[Variation(id = 20, Desc = "Test 10 with TrustedXslt override, should work", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings3.xsl", false, false, true, true })]
[InlineData(20, "XsltSettings.xml", "XsltSettings3.xsl", false, false, true, true)]
- public void XsltSettings1_2_ActiveIssue9873(object param0, object param1, object param2, object param3, object param4, object param5, object param6)
+ [Theory]
+ public void XsltSettings1_2_ContainsScript(object param0, object param1, object param2, object param3, object param4, object param5, object param6)
{
- XsltSettings1_2(param0, param1, param2, param3, param4, param5, param6);
+ var e = Assert.ThrowsAny<XsltException>(() => XsltSettings1_2(param0, param1, param2, param3, param4, param5, param6));
+ Assert.Equal("Compiling JScript/CSharp scripts is not supported", e.InnerException.Message);
}
- [ActiveIssue(9876)]
//[Variation(id = 5, Desc = "Test the document function with EnableDocumentFunction, should work", Pri = 0, Params = new object[] { "XsltSettings.xml", "XsltSettings2.xsl", true, false })]
[InlineData(5, "XsltSettings.xml", "XsltSettings2.xsl", true, false)]
//[Variation(id = 8, Desc = "Test the document function with TrustedXslt, should work", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings2.xsl", true, true })]
[InlineData(8, "XsltSettings.xml", "XsltSettings2.xsl", true, true)]
[Theory]
- public void XsltSettings1_1_ActiveIssue9876(object param0, object param1, object param2, object param3, object param4)
+ public void XsltSettings1_1_ExternalURI(object param0, object param1, object param2, object param3, object param4)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
XsltSettings1_1(param0, param1, param2, param3, param4);
}
- [ActiveIssue(9876)]
//[Variation(id = 18, Desc = "Test 6 with EnableDocumentFunction override, should work", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings2.xsl", false, false, true, false })]
[InlineData(18, "XsltSettings.xml", "XsltSettings2.xsl", false, false, true, false)]
[Theory]
- public void XsltSettings1_2_ActiveIssue9876(object param0, object param1, object param2, object param3, object param4, object param5, object param6)
+ public void XsltSettings1_2_ExternalURI(object param0, object param1, object param2, object param3, object param4, object param5, object param6)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
XsltSettings1_2(param0, param1, param2, param3, param4, param5, param6);
}
@@ -135,24 +130,6 @@ namespace System.Xml.Tests
// In Proc Skip
// XsltSettings - Debug (1-20)
// XsltSettings - Retail (1,4,9,11,15,16,19,20)
- if (_isInProc)
- {
- if (_debug)
- return; //TEST_SKIPPED;
- else
- {
- switch ((int)param0)
- {
- case 1:
- case 4:
- case 9:
- case 11:
- return; //TEST_SKIPPED;
- // default:
- //just continue;
- }
- }
- }
XsltSettings xs = new XsltSettings((bool)param3, (bool)param4);
_xsl.Load(_xslFile, xs, new XmlUrlResolver());
@@ -223,28 +200,6 @@ namespace System.Xml.Tests
{
Init(param1.ToString(), param2.ToString());
- // In Proc Skip
- // XsltSettings - Debug (1-20)
- // XsltSettings - Retail (1,4,9,11,15,16,19,20)
- if (_isInProc)
- {
- if (_debug)
- return; //TEST_SKIPPED;
- else
- {
- switch ((int)param0)
- {
- case 15:
- case 16:
- case 19:
- case 20:
- return; //TEST_SKIPPED;
- // default:
- //just continue;
- }
- }
- }
-
XsltSettings xs = new XsltSettings((bool)param3, (bool)param4);
_xsl.Load(_xslFile, xs, new XmlUrlResolver());
@@ -306,10 +261,6 @@ namespace System.Xml.Tests
{
Init(param0.ToString(), param1.ToString());
- if (_isInProc)
- if (_debug)
- return; //TEST_SKIPPED;
-
XsltSettings xs = new XsltSettings((bool)param2, (bool)param3);
XPathDocument doc = new XPathDocument(_xslFile);
_xsl.Load(doc, xs, new XmlUrlResolver());
@@ -328,43 +279,31 @@ namespace System.Xml.Tests
}
//[Variation(id = 25, Desc = "Disable DocumentFunction and Malicious stylesheet has document(url) opening a URL to an external system", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings9.xsl", false, false })]
- //[InlineData("XsltSettings.xml", "XsltSettings9.xsl", false, false)]
+ [InlineData("XsltSettings.xml", "XsltSettings9.xsl", false, false)]
//[Variation(id = 26, Desc = "Disable DocumentFunction and Malicious stylesheet has document(nodeset) opens union of all URLs referenced", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings10.xsl", false, false })]
[InlineData("XsltSettings.xml", "XsltSettings10.xsl", false, false)]
//[Variation(id = 27, Desc = "Disable DocumentFunction and Malicious stylesheet has document(url, nodeset) nodeset is a base URL to 1st arg", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings11.xsl", false, false })]
- //[InlineData("XsltSettings.xml", "XsltSettings11.xsl", false, false)]
+ [InlineData("XsltSettings.xml", "XsltSettings11.xsl", false, false)]
//[Variation(id = 28, Desc = "Disable DocumentFunction and Malicious stylesheet has document(nodeset, nodeset) 2nd arg is a base URL to 1st arg", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings12.xsl", false, false })]
[InlineData("XsltSettings.xml", "XsltSettings12.xsl", false, false)]
//[Variation(id = 29, Desc = "Disable DocumentFunction and Malicious stylesheet has document(''), no threat but just to verify if its considered", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings13.xsl", false, false })]
[InlineData("XsltSettings.xml", "XsltSettings13.xsl", false, false)]
//[Variation(id = 30, Desc = "Disable DocumentFunction and Stylesheet includes another stylesheet with document() function", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings14.xsl", false, false })]
- //[InlineData("XsltSettings.xml", "XsltSettings14.xsl", false, false)]
+ [InlineData("XsltSettings.xml", "XsltSettings14.xsl", false, false)]
//[Variation(id = 31, Desc = "Disable DocumentFunction and Stylesheet has an entity reference to doc(), ENTITY s document('foo.xml')", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings15.xsl", false, false })]
- //[InlineData("XsltSettings.xml", "XsltSettings15.xsl", false, false)]
+ [InlineData("XsltSettings.xml", "XsltSettings15.xsl", false, false)]
[Theory]
public void XsltSettings3(object param0, object param1, object param2, object param3)
{
Init(param0.ToString(), param1.ToString());
- if (_isInProc)
- if (_debug)
- return; //TEST_SKIPPED;
-
XsltSettings xs = new XsltSettings((bool)param2, (bool)param3);
XPathDocument doc = new XPathDocument(_xslFile);
_xsl.Load(doc, xs, new XmlUrlResolver());
- try
- {
- StringWriter sw = Transform();
- _output.WriteLine("Execution of the document function was allowed even when XsltSettings.EnableDocumentFunction is false");
- Assert.True(false);
- }
- catch (XsltException ex)
- {
- _output.WriteLine(ex.ToString());
- return;
- }
+ StringWriter sw;
+ var e = Assert.ThrowsAny<XsltException>(() => sw = Transform());
+ Assert.Contains("Execution of the 'document()' function was prohibited. Use the XsltSettings.EnableDocumentFunction property to enable it.", e.Message);
}
}
} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CThreads.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CThreads.cs
index ac8c2bcec9..5b4fdcb2f7 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CThreads.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CThreads.cs
@@ -2,7 +2,6 @@
// 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.Collections.Generic;
using Xunit;
using Xunit.Abstractions;
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXmlCache.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXmlCache.cs
index ef551cd67b..8027ec4840 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXmlCache.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXmlCache.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Xunit;
using Xunit.Abstractions;
using System;
using System.IO;
@@ -167,10 +166,6 @@ abstract public class CXmlBase
return rChild;
}
-
- //
- // Private Methods and Properties
- //
}
public class CXmlAttribute : CXmlBase
@@ -327,13 +322,6 @@ public class CXmlNode : CXmlBase
string DocTypePublic = null;
string DocTypeSystem = null;
- /*
- // Display of Indent information
- if (this.LocalName == string.Empty)
- _output.WriteLine("Node={0}, Indent={1}, Mixed={2}",this.NodeType, this.Flags & NodeFlags.Indent, this.Flags & NodeFlags.MixedContent);
- else
- _output.WriteLine("Node={0}, Indent={1}, Mixed={2}",this.LocalName, this.Flags & NodeFlags.Indent, this.Flags & NodeFlags.MixedContent);
- */
switch (this.NodeType)
{
case XmlNodeType.CDATA:
@@ -718,7 +706,7 @@ public class CXmlCache
protected CXmlNode _rDocumentRootNode;
protected CXmlNode _rRootNode = null;
internal static NodeFlags _eDefaultFlags = NodeFlags.None;
- static internal BufferWriter _rBufferWriter = new BufferWriter();
+ internal static BufferWriter _rBufferWriter = new BufferWriter();
private ITestOutputHelper _output;
public CXmlCache(ITestOutputHelper output)
@@ -746,7 +734,6 @@ public class CXmlCache
_eWhitespaceMode = ((XmlTextReader)rXmlReader).WhitespaceHandling;
_fNamespaces = ((XmlTextReader)rXmlReader).Namespaces;
_eValidationMode = ValidationType.None;
- // _eEntityMode = ((XmlValidatingReader)rXmlReader).EntityHandling;
}
#pragma warning disable 0618
if (rXmlReader is XmlValidatingReader)
@@ -1112,10 +1099,8 @@ public class CXmlCache
case XmlNodeType.EntityReference:
if (_eValidationMode == ValidationType.DTD)
{
- // _rXmlReader.EntityHandling = EntityHandling.ExpandEntities;
_rXmlReader.ResolveEntity();
Process(rNewNode);
- // _rXmlReader.EntityHandling = _eEntityMode;
}
break;
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTArgumentList.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTArgumentList.cs
index dc8cbe7243..5ac22f717b 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTArgumentList.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTArgumentList.cs
@@ -4,13 +4,11 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.Collections.Generic;
-//using System.Dynamic;
using System.IO;
-using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
+using System.Dynamic;
namespace System.Xml.Tests
{
@@ -73,7 +71,7 @@ namespace System.Xml.Tests
//[Variation(Desc = "Tuple.XsltArgumentList.AddParam/AddExtensionObject", Param = 1)]
[InlineData(1)]
//[Variation(Desc = "DynamicObject.XsltArgumentList.AddParam/AddExtensionObject", Param = 2)]
- //[InlineData(2)]
+ [InlineData(2)]
//[Variation(Desc = "Guid.XsltArgumentList.AddParam/AddExtensionObject", Param = 3)]
[InlineData(3)]
//[Variation(Desc = "Dictionary.XsltArgumentList.AddParam/AddExtensionObject", Param = 4)]
@@ -87,7 +85,7 @@ namespace System.Xml.Tests
switch (param)
{
case 1: t = Tuple.Create(1, "Melitta", 7.5); break;
- //case 2: t = new TestDynamicObject(); break;
+ case 2: t = new TestDynamicObject(); break;
case 3: t = new Guid(); break;
case 4: t = new Dictionary<string, object>(); break;
}
@@ -111,13 +109,13 @@ namespace System.Xml.Tests
return;
}
- //public class TestDynamicObject : DynamicObject
- //{
- // public dynamic GetDynamicObject()
- // {
- // return new Dictionary<string, object>();
- // }
- //}
+ public class TestDynamicObject : DynamicObject
+ {
+ public dynamic GetDynamicObject()
+ {
+ return new Dictionary<string, object>();
+ }
+ }
//[Variation("Param name is null")]
[InlineData()]
@@ -277,29 +275,6 @@ namespace System.Xml.Tests
return;
}
- /*
- * This test is no more valid.
- * MDAC Bug # 88407 fix now allows ANY characters in URI
- //[Variation("Invalid Namespace URI")]
- [InlineData()]
- [Theory]
- public void GetParam11()
- {
- m_xsltArg = new XsltArgumentList();
-
- try
- {
- m_xsltArg.AddParam("myArg1", szInvalid, "Test11");
- }
- catch (System.UriFormatException)
- {
- return;
- }
- _output.WriteLine("Did not throw System.UriFormatException for invalid namespace System.Xml.Tests");
- Assert.True(false);
- }
- */
-
//[Variation("Different Data Types")]
[InlineData()]
[Theory]
@@ -613,361 +588,6 @@ namespace System.Xml.Tests
}
/***********************************************************/
- /* XsltArgumentList.GetExtensionObject */
- /***********************************************************/
-
- // TODO: Fix security issue
- ////[TestCase(Name="XsltArgumentList - GetExtensionObject", Desc="XsltArgumentList.GetExtensionObject")]
-
- //public class CArgGetExtObj : XsltApiTestCaseBase
- //{
- // //[Variation(Desc="Basic Verification Test",Pri=0)]
- // [InlineData()]
- // public int GetExtObject1()
- // {
- // MyObject obj = new MyObject(1);
- // m_xsltArg = new XsltArgumentList();
-
- // m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- // retObj = m_xsltArg.GetExtensionObject(szDefaultNS);
-
- // _output.WriteLine("Retrieved value: {0}", ((MyObject)retObj).MyValue());
- // if(((MyObject)retObj).MyValue() != obj.MyValue())
- // {
- // _output.WriteLine("Set and retrieved value appear to be different");
- // Assert.True(false);
- // }
-
- // if((LoadXSL("myObjectDef.xsl") == TEST_PASS) && (Transform_ArgList("fruits.xml") == TEST_PASS) &&
- // (CheckResult(430.402026847)== TEST_PASS))
- // return;
- // else
- // Assert.True(false);
- // }
-
- // //[Variation("Namespace URI = null")]
- // [InlineData()]
- // public int GetExtObject2()
- // {
- // m_xsltArg = new XsltArgumentList();
-
- // try
- // {
- // m_xsltArg.GetExtensionObject(null);
- // }
- // catch(System.ArgumentNullException)
- // {
- // return;
- // }
- // _output.WriteLine("ArgumentNullException not thrown for null namespace System.Xml.Tests");
- // return;
- // }
-
- // //[Variation("Namespace URI is empty string")]
- // [InlineData()]
- // public int GetExtObject3()
- // {
- // m_xsltArg = new XsltArgumentList();
-
- // try
- // {
- // retObj = m_xsltArg.GetExtensionObject(szEmpty);
- // }
- // catch(Exception e)
- // {
- // _output.WriteLine(e.ToString());
- // Assert.True(false);
- // }
-
- // if((LoadXSL("showParam.xsl") == TEST_PASS) && (Transform_ArgList("fruits.xml") == TEST_PASS) &&
- // (CheckResult(466.5112789241)== TEST_PASS))
- // return;
- // else
- // Assert.True(false);
- // }
-
- // //[Variation("Namespace URI non-existent")]
- // [InlineData()]
- // public int GetExtObject4()
- // {
- // m_xsltArg = new XsltArgumentList();
-
- // retObj = m_xsltArg.GetExtensionObject(szDefaultNS);
-
- // if(retObj != null)
- // {
- // _output.WriteLine("Did not return a NULL value for a non-existent URI");
- // Assert.True(false);
- // }
- // try
- // {
- // if((LoadXSL("myObjectDef.xsl") == TEST_PASS))
- // Transform_ArgList("fruits.xml");
- // }
- // catch(System.Xml.Xsl.XsltException)
- // {
- // return;
- // }
- // _output.WriteLine("Did not throw exception for an invalid transform");
- // Assert.True(false);
- // }
-
- // //[Variation("Very long namespace System.Xml.Tests")]
- // [InlineData()]
- // public int GetExtObject5()
- // {
- // m_xsltArg = new XsltArgumentList();
- // MyObject obj = new MyObject(5);
-
- // m_xsltArg.AddExtensionObject(szLongNS, obj);
- // retObj = m_xsltArg.GetExtensionObject(szLongNS);
-
- // if(((MyObject)retObj).MyValue() != obj.MyValue())
- // {
- // _output.WriteLine("Set and retrieved value appear to be different");
- // Assert.True(false);
- // }
-
- // if((LoadXSL("MyObjectLongNS.xsl") == TEST_PASS) && (Transform_ArgList("fruits.xml") == TEST_PASS) &&
- // (CheckResult(522.0563223871)== TEST_PASS))
- // return;
- // else
- // Assert.True(false);
- // }
-
- // /*
- // * This test is no more valid.
- // * MDAC Bug # 88407 fix now allows ANY characters in URI
- // //[Variation("Invalid namespace System.Xml.Tests")]
- // [InlineData()]
- // public int GetExtObject6()
- // {
- // m_xsltArg = new XsltArgumentList();
- // MyObject obj = new MyObject(6);
-
- // try
- // {
- // m_xsltArg.AddExtensionObject(szInvalid, obj);
- // }
- // catch (System.UriFormatException)
- // {
- // return;
- // }
- // _output.WriteLine("Did not throw System.UriFormatException for invalid namespace System.Xml.Tests");
- // Assert.True(false);
- // }
- // */
-
- // //[Variation("Different Data Types")]
- // [InlineData()]
- // public int GetExtObject7()
- // {
- // m_xsltArg = new XsltArgumentList();
- // String obj = "0.00";
-
- // // string
- // m_xsltArg.AddExtensionObject("myArg1", obj);
- // retObj = m_xsltArg.GetExtensionObject("myArg1");
- // _output.WriteLine("Added Value:{0}\nRetrieved Value: {1}", "0.00", retObj);
- // if( retObj.ToString() != "0.00")
- // {
- // _output.WriteLine("Failed to add/get a value for {0} of type {1}", "0.00", "string");
- // _output.WriteLine("Retrieved: {0} ", retObj);
- // Assert.True(false);
- // }
-
- // int i = 8;
-
- // m_xsltArg.AddExtensionObject("myArg2", i);
- // retObj = m_xsltArg.GetExtensionObject("myArg2");
- // _output.WriteLine("Added Value:{0}\nRetrieved Value:{1}", i, retObj);
- // if(!i.Equals(retObj))
- // {
- // _output.WriteLine("Failed to add/get a value for {0} with conversion from int to double", i);
- // _output.WriteLine("Retrieved: {0}", retObj.ToString());
- // Assert.True(false);
- // }
-
- // //must also be same instance!!!
- // if(i != (int)retObj)
- // Assert.True(false);
-
- // Boolean bF = (1==0);
-
- // m_xsltArg.AddExtensionObject("myArg3", bF);
- // retObj = m_xsltArg.GetExtensionObject("myArg3");
- // _output.WriteLine("Added Value:{0}\nRetrieved Value: {1}", bF.ToString(), retObj);
- // if( !bF.Equals(retObj))
- // {
- // _output.WriteLine("Failed to add/get a value for {0} of type {1}", bF.ToString(), "boolean");
- // _output.WriteLine("Retrieved: {0} ", retObj);
- // Assert.True(false);
- // }
-
- // Boolean bT = (1==1);
-
- // m_xsltArg.AddExtensionObject("myArg4", bT);
- // retObj = m_xsltArg.GetExtensionObject("myArg4");
- // _output.WriteLine("Added Value:{0}\nRetrieved Value: {1}", bT.ToString(), retObj);
- // if( !bT.Equals(retObj))
- // {
- // _output.WriteLine("Failed to add/get a value for {0} of type {1}", bT.ToString(), "boolean");
- // _output.WriteLine("Retrieved: {0} ", retObj);
- // Assert.True(false);
- // }
- // return;
- // }
-
- // //[Variation("Case sensitivity")]
- // [InlineData()]
- // public int GetExtObject8()
- // {
- // MyObject obj = new MyObject(8);
- // m_xsltArg = new XsltArgumentList();
-
- // m_xsltArg.AddExtensionObject("urn:my-object", obj);
-
- // retObj = m_xsltArg.GetExtensionObject("urn:my-object");
- // if(((MyObject)retObj).MyValue() != obj.MyValue())
- // {
- // _output.WriteLine("Set and retrieved value appear to be different");
- // Assert.True(false);
- // }
-
- // retObj = m_xsltArg.GetExtensionObject("URN:MY-OBJECT");
- // if(retObj != null)
- // {
- // _output.WriteLine("Set and retrieved value appear to be different for URN:MY-OBJECT");
- // Assert.True(false);
- // }
-
- // retObj = m_xsltArg.GetExtensionObject("urn:My-Object");
- // if(retObj != null)
- // {
- // _output.WriteLine("Set and retrieved value appear to be different for urn:My-Object");
- // Assert.True(false);
- // }
-
- // retObj = m_xsltArg.GetExtensionObject("urn-my:object");
- // if(retObj != null)
- // {
- // _output.WriteLine("Set and retrieved value appear to be different for urn-my:object");
- // Assert.True(false);
- // }
-
- // if((LoadXSL("myObjectDef.xsl") == TEST_PASS) && (Transform_ArgList("fruits.xml") == TEST_PASS) &&
- // (CheckResult(430.402026847)== TEST_PASS))
- // return;
- // else
- // Assert.True(false);
- // }
-
- // //[Variation("Whitespace")]
- // [InlineData()]
- // public int GetExtObject9()
- // {
- // int i=1;
- // m_xsltArg = new XsltArgumentList();
-
- // foreach(String str in szWhiteSpace)
- // {
- // MyObject obj = new MyObject(i);
-
- // m_xsltArg.AddExtensionObject(szDefaultNS + str, obj);
- // retObj = m_xsltArg.GetExtensionObject(szDefaultNS + str);
- // if(((MyObject)retObj).MyValue() != i)
- // {
- // _output.WriteLine("Error processing {0} test for whitespace arg", i);
- // Assert.True(false);
- // }
- // i++;
- // }
-
- // try
- // {
- // if((LoadXSL("myObjectDef.xsl") == TEST_PASS))
- // Transform_ArgList("fruits.xml");
- // }
- // catch(System.Xml.Xsl.XsltException)
- // {
- // return;
- // }
- // _output.WriteLine("Did not throw expected exception: System.Xml.Xsl.XsltException");
- // Assert.True(false);
- // }
-
- // //[Variation("Call after object has been removed")]
- // [InlineData()]
- // public int GetExtObject10()
- // {
- // MyObject obj = new MyObject(10);
- // m_xsltArg = new XsltArgumentList();
-
- // m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- // m_xsltArg.RemoveExtensionObject(szDefaultNS);
- // retObj = m_xsltArg.GetExtensionObject(szDefaultNS);
-
- // if(retObj != null)
- // {
- // _output.WriteLine("Did not retrieve a NULL value for a non-existent object returned");
- // Assert.True(false);
- // }
-
- // try
- // {
- // if((LoadXSL("myObjectDef.xsl") == TEST_PASS))
- // Transform_ArgList("fruits.xml");
- // }
- // catch(System.Xml.Xsl.XsltException)
- // {
- // return;
- // }
- // _output.WriteLine("Did not throw expected exception: System.Xml.Xsl.XsltException");
- // Assert.True(false);
- // }
-
- // //[Variation("Call multiple times")]
- // [InlineData()]
- // public int GetExtObject11()
- // {
- // MyObject obj = new MyObject(11);
- // m_xsltArg = new XsltArgumentList();
-
- // m_xsltArg.AddExtensionObject(szDefaultNS, obj);
-
- // for(int i=0; i < 500; i++)
- // {
- // retObj = m_xsltArg.GetExtensionObject(szDefaultNS);
- // if(((MyObject)retObj).MyValue() != obj.MyValue())
- // {
- // _output.WriteLine("Set and retrieved value appear to be different after {i} tries", i);
- // Assert.True(false);
- // }
- // }
- // if((LoadXSL("myObjectDef.xsl") == TEST_PASS) && (Transform_ArgList("fruits.xml") == TEST_PASS) &&
- // (CheckResult(430.402026847)== TEST_PASS))
- // return;
- // else
- // Assert.True(false);
- // }
-
- // //[Variation("Using XSL Namespace")]
- // [InlineData()]
- // public int GetExtObject12()
- // {
- // m_xsltArg = new XsltArgumentList();
-
- // retObj = m_xsltArg.GetExtensionObject(szDefaultNS);
- // if(retObj != null)
- // {
- // _output.WriteLine("Did not retrieve null value when using namespace {0}", szXslNS);
- // Assert.True(false);
- // }
- // return;
- // }
- //}
-
- /***********************************************************/
/* XsltArgumentList.AddParam */
/***********************************************************/
@@ -992,11 +612,29 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "Basic Verification Test", Pri = 0)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam1()
+ public void AddParam1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -1005,9 +643,11 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test1")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(457.6003003605) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -1051,11 +691,24 @@ namespace System.Xml.Tests
}
//[Variation("Very Long Param Name")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam4()
+ public void AddParam4(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam(szLongString, szEmpty, "Test1");
@@ -1064,9 +717,11 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test1")
Assert.True(false);
- if ((LoadXSL("showParamLongName.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(383.8692240713) == 1))
+ if ((LoadXSL("showParamLongName.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -1110,11 +765,29 @@ namespace System.Xml.Tests
}
//[Variation("Namespace URI is empty string")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam7()
+ public void AddParam7(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test7
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test7");
@@ -1124,19 +797,39 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test7")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(457.7055635184) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Very long namespace System.Xml.Tests")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam8()
+ public void AddParam8(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szLongNS, "Test8");
@@ -1145,50 +838,49 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test8")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
- return;
- else
- Assert.True(false);
- }
-
- /*
- * This test is no more valid.
- * MDAC Bug # 88407 fix now allows ANY characters in URI
- //[Variation("Invalid Namespace URI")]
- [InlineData()]
- [Theory]
- public void AddParam9()
- {
- m_xsltArg = new XsltArgumentList();
-
- try
- {
- m_xsltArg.AddParam("myArg1", szInvalid, "Test1");
- }
- catch (System.UriFormatException)
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
{
+ VerifyResult(expected);
return;
}
- _output.WriteLine("Did not throw System.UriFormatException for invalid namespace System.Xml.Tests");
- Assert.True(false);
+ else
+ Assert.True(false);
}
- */
//[Variation("Objects as different Data Types")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam10()
+ public void AddParam10(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.My Custom Object has a value of 10
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
MyObject m = new MyObject(10, _output);
m_xsltArg.AddParam("myArg1", szEmpty, m);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(473.4007803959) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -1214,11 +906,29 @@ namespace System.Xml.Tests
}
//[Variation("Object with same name, different namespace System.Xml.Tests")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam12()
+ public void AddParam12(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -1240,19 +950,39 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test1")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(457.6003003605) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Object with same namespace System.Xml.Tests, different name")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam13()
+ public void AddParam13(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1
+ 2.Test2
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -1274,19 +1004,39 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test1")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(449.000354515) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Case Sensitivity")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam14()
+ public void AddParam14(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1
+ 2.Test2
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -1313,9 +1063,11 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test3")
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(449.000354515) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -1340,11 +1092,29 @@ namespace System.Xml.Tests
}
//[Variation("Add/remove object many times")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam16()
+ public void AddParam16(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.Test1
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
String obj = "Test";
@@ -1381,19 +1151,43 @@ namespace System.Xml.Tests
retObj = m_xsltArg.GetParam("myArg2", szEmpty);
if (retObj.ToString() != ("Test1"))
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(458.7752486264) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Whitespace in URI and param")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam17()
+ public void AddParam17(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test
+ 2.Test
+
+ 3.Test
+ 4.Test
+
+ 5.Test
+
+
+ 6.No Value Specified</result>";
+
int i = 1;
int errCount = 0;
m_xsltArg = new XsltArgumentList();
@@ -1434,19 +1228,39 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(420.7138852814) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Adding many objects")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam18()
+ public void AddParam18(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1
+ 2.Test2
+ 3.Test3
+ 4.Test4
+ 5.Test5
+ 6.Test6</result>";
+
m_xsltArg = new XsltArgumentList();
String obj = "Test";
@@ -1458,19 +1272,39 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(413.6341271694) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Add same object many times")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam19()
+ public void AddParam19(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.Test1
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
String obj = "Test";
@@ -1490,19 +1324,39 @@ namespace System.Xml.Tests
retObj = m_xsltArg.GetParam("myArg2", szEmpty);
if (retObj.ToString() != ("Test1"))
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(458.7752486264) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Using Different XSLT namespace")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam20()
+ public void AddParam20(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj1=""urn:http://www.w3.org/1999/XSL/Transform"" xmlns:myObj2=""urn:tmp"" xmlns:myObj3=""urn:my-object"" xmlns:myObj4=""urn:MY-OBJECT"">
+ 1.Test1
+ 2.Test2
+ 3.Test3
+ 4.Test4
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", "urn:" + szXslNS, "Test1");
@@ -1529,9 +1383,11 @@ namespace System.Xml.Tests
if (retObj.ToString() != "Test4")
Assert.True(false);
- if ((LoadXSL("showParamNS.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(509.315418596) == 1))
+ if ((LoadXSL("showParamNS.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -1547,24 +1403,43 @@ namespace System.Xml.Tests
}
//[Variation("Parameters should not be cached")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject32()
+ public void AddExtObject32(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
- if (LoadXSL("test_Param.xsl") == 1)
+ string expected1 = @"<?xml version=""1.0"" encoding=""utf-8""?><out>Param: first</out>";
+ string expected2 = @"<?xml version=""1.0"" encoding=""utf-8""?><out>Param: second</out>";
+
+ if (LoadXSL("test_Param.xsl", inputType, readerType) == 1)
{
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myParam1", szEmpty, "first");
// Transform once
- if ((Transform_ArgList("foo.xml") == 1) && (CheckResult(383.6292620645) == 1))
+ if (Transform_ArgList("foo.xml", transformType, docType) == 1)
{
+ VerifyResult(expected1);
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myParam1", szEmpty, "second");
// Transform again to make sure that parameter from first transform are not cached
- if ((Transform_ArgList("foo.xml") == 1) && (CheckResult(384.9801823644) == 1))
+ if (Transform_ArgList("foo.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected2);
return;
+ }
}
}
Assert.True(false);
@@ -1598,75 +1473,299 @@ namespace System.Xml.Tests
//global param is xsl:param local param is xsl:param
//[Variation(id = 1, Pri = 2, Desc = "No param sent, global param used, local param exists with a default value", Params = new object[] { "AddParameterA1.xsl", "default local" })]
- [InlineData("AddParameterA1.xsl", "default local")]
+ [InlineData("AddParameterA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 2, Pri = 2, Desc = "No param sent, global param used, local param exists with no default value", Params = new object[] { "AddParameterA2.xsl", "" })]
- [InlineData("AddParameterA2.xsl", "")]
+ [InlineData("AddParameterA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 3, Pri = 2, Desc = "No param sent, global param used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterA3.xsl", "default global" })]
- [InlineData("AddParameterA3.xsl", "default global")]
+ [InlineData("AddParameterA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 4, Pri = 2, Desc = "No param sent, global param used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterA4.xsl", "with-param" })]
- [InlineData("AddParameterA4.xsl", "with-param")]
+ [InlineData("AddParameterA4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 5, Pri = 2, Desc = "No param sent, global param used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterA5.xsl", "" })]
- [InlineData("AddParameterA5.xsl", "")]
+ [InlineData("AddParameterA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 6, Pri = 2, Desc = "No param sent, global param used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterA6.xsl", "default global" })]
- [InlineData("AddParameterA6.xsl", "default global")]
+ [InlineData("AddParameterA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 7, Pri = 2, Desc = "No param sent, global param used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterA7.xsl", "default global" })]
- [InlineData("AddParameterA7.xsl", "default global")]
+ [InlineData("AddParameterA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//global param is xsl:variable local param is xsl:param
//[Variation(id = 8, Pri = 2, Desc = "No param sent, global variable used, local param exists with a default value", Params = new object[] { "AddParameterDA1.xsl", "default local" })]
- [InlineData("AddParameterDA1.xsl", "default local")]
+ [InlineData("AddParameterDA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 9, Pri = 2, Desc = "No param sent, global variable used, local param exists with no default value", Params = new object[] { "AddParameterDA2.xsl", "" })]
- [InlineData("AddParameterDA2.xsl", "")]
+ [InlineData("AddParameterDA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 10, Pri = 2, Desc = "No param sent, global variable used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterDA3.xsl", "default global" })]
- [InlineData("AddParameterDA3.xsl", "default global")]
+ [InlineData("AddParameterDA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 11, Pri = 2, Desc = "No param sent, global variable used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterDA4.xsl", "with-param" })]
- [InlineData("AddParameterDA4.xsl", "with-param")]
+ [InlineData("AddParameterDA4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 12, Pri = 2, Desc = "No param sent, global variable used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterDA5.xsl", "" })]
- [InlineData("AddParameterDA5.xsl", "")]
+ [InlineData("AddParameterDA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 13, Pri = 2, Desc = "No param sent, global variable used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterDA6.xsl", "default global" })]
- [InlineData("AddParameterDA6.xsl", "default global")]
+ [InlineData("AddParameterDA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 14, Pri = 2, Desc = "No param sent, global variable used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterDA7.xsl", "default global" })]
- [InlineData("AddParameterDA7.xsl", "default global")]
+ [InlineData("AddParameterDA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//global param is xsl:param local param is xsl:variable
//[Variation(id = 15, Pri = 2, Desc = "No param sent, global param used, local variable exists with a default value", Params = new object[] { "AddParameterEA1.xsl", "default local" })]
- [InlineData("AddParameterEA1.xsl", "default local")]
+ [InlineData("AddParameterEA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 16, Pri = 2, Desc = "No param sent, global param used, local variable exists with no default value", Params = new object[] { "AddParameterEA2.xsl", "" })]
- [InlineData("AddParameterEA2.xsl", "")]
+ [InlineData("AddParameterEA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 17, Pri = 2, Desc = "No param sent, global param used, local variable doesn't exist but reference to param exists", Params = new object[] { "AddParameterEA3.xsl", "default global" })]
- [InlineData("AddParameterEA3.xsl", "default global")]
+ [InlineData("AddParameterEA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 18, Pri = 2, Desc = "No param sent, global param used, local variable exists with a default value and with-param sends a value", Params = new object[] { "AddParameterEA4.xsl", "default local" })]
- [InlineData("AddParameterEA4.xsl", "default local")]
+ [InlineData("AddParameterEA4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 19, Pri = 2, Desc = "No param sent, global param used, local variable exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterEA5.xsl", "" })]
- [InlineData("AddParameterEA5.xsl", "")]
+ [InlineData("AddParameterEA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 20, Pri = 2, Desc = "No param sent, global param used, local variable doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterEA6.xsl", "default global" })]
- [InlineData("AddParameterEA6.xsl", "default global")]
+ [InlineData("AddParameterEA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 21, Pri = 2, Desc = "No param sent, global param used, local variable doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterEA7.xsl", "default global" })]
- [InlineData("AddParameterEA7.xsl", "default global")]
+ [InlineData("AddParameterEA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//global param is xsl:variable local param is xsl:variable
//[Variation(id = 22, Pri = 2, Desc = "No param sent, global variable used, local variable exists with a default value", Params = new object[] { "AddParameterFA1.xsl", "default local" })]
- [InlineData("AddParameterFA1.xsl", "default local")]
+ [InlineData("AddParameterFA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 23, Pri = 2, Desc = "No param sent, global variable used, local variable exists with no default value", Params = new object[] { "AddParameterFA2.xsl", "" })]
- [InlineData("AddParameterFA2.xsl", "")]
+ [InlineData("AddParameterFA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 24, Pri = 2, Desc = "No param sent, global variable used, local variable doesn't exist but reference to param exists", Params = new object[] { "AddParameterFA3.xsl", "default global" })]
- [InlineData("AddParameterFA3.xsl", "default global")]
+ [InlineData("AddParameterFA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 25, Pri = 2, Desc = "No param sent, global variable used, local variable exists with a default value and with-param sends a value", Params = new object[] { "AddParameterFA4.xsl", "default local" })]
- [InlineData("AddParameterFA4.xsl", "default local")]
+ [InlineData("AddParameterFA4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 26, Pri = 2, Desc = "No param sent, global variable used, local variable exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterFA5.xsl", "" })]
- [InlineData("AddParameterFA5.xsl", "")]
+ [InlineData("AddParameterFA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 27, Pri = 2, Desc = "No param sent, global variable used, local variable doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterFA6.xsl", "default global" })]
- [InlineData("AddParameterFA6.xsl", "default global")]
+ [InlineData("AddParameterFA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 28, Pri = 2, Desc = "No param sent, global variable used, local variable doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterFA7.xsl", "default global" })]
- [InlineData("AddParameterFA7.xsl", "default global")]
+ [InlineData("AddParameterFA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFA7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam1(object param0, object param1)
+ public void AddParam1(object param0, object param1, InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
m_xsltArg = new XsltArgumentList();
string xslFile = param0.ToString();
string expected = "<result>" + param1.ToString() + "</result>";
- if ((LoadXSL(xslFile) == 1) && (Transform_ArgList("AddParameter.xml") == 1))
+ if ((LoadXSL(xslFile, inputType, readerType) == 1) && (Transform_ArgList("AddParameter.xml", transformType, docType) == 1))
VerifyResult(expected);
else
Assert.True(false);
@@ -1676,69 +1775,293 @@ namespace System.Xml.Tests
//global param is xsl:param local param is xsl:param
//[Variation(id = 29, Pri = 2, Desc = "Param sent, global param used, local param exists with a default value", Params = new object[] { "AddParameterB1.xsl", "default local" })]
- [InlineData("AddParameterB1.xsl", "default local")]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 30, Pri = 2, Desc = "Param sent, global param used, local param exists with no default value", Params = new object[] { "AddParameterB2.xsl", "" })]
- [InlineData("AddParameterB2.xsl", "")]
+ [InlineData("AddParameterB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 31, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterB3.xsl", "outside param" })]
- [InlineData("AddParameterB3.xsl", "outside param")]
+ [InlineData("AddParameterB3.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 32, Pri = 2, Desc = "Param sent, global param used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterB4.xsl", "with-param" })]
- [InlineData("AddParameterB4.xsl", "with-param")]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 33, Pri = 2, Desc = "Param sent, global param used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterB5.xsl", "" })]
- [InlineData("AddParameterB5.xsl", "")]
+ [InlineData("AddParameterB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 34, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterB6.xsl", "outside param" })]
- [InlineData("AddParameterB6.xsl", "outside param")]
+ [InlineData("AddParameterB6.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 35, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterB7.xsl", "outside param" })]
- [InlineData("AddParameterB7.xsl", "outside param")]
+ [InlineData("AddParameterB7.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//global param is xsl:variable local param is xsl:param
//[Variation(id = 36, Pri = 2, Desc = "Param sent, global variable used, local param exists with a default value", Params = new object[] { "AddParameterDB1.xsl", "default local" })]
- [InlineData("AddParameterDB1.xsl", "default local")]
+ [InlineData("AddParameterDB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 37, Pri = 2, Desc = "Param sent, global variable used, local param exists with no default value", Params = new object[] { "AddParameterDB2.xsl", "" })]
- [InlineData("AddParameterDB2.xsl", "")]
+ [InlineData("AddParameterDB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 38, Pri = 2, Desc = "Param sent, global variable used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterDB3.xsl", "default global" })]
- [InlineData("AddParameterDB3.xsl", "default global")]
+ [InlineData("AddParameterDB3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 39, Pri = 2, Desc = "Param sent, global variable used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterDB4.xsl", "with-param" })]
- [InlineData("AddParameterDB4.xsl", "with-param")]
+ [InlineData("AddParameterDB4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 40, Pri = 2, Desc = "Param sent, global variable used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterDB5.xsl", "" })]
- [InlineData("AddParameterDB5.xsl", "")]
+ [InlineData("AddParameterDB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 41, Pri = 2, Desc = "Param sent, global variable used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterDB6.xsl", "default global" })]
- [InlineData("AddParameterDB6.xsl", "default global")]
+ [InlineData("AddParameterDB6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 42, Pri = 2, Desc = "Param sent, global variable used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterDB7.xsl", "default global" })]
- [InlineData("AddParameterDB7.xsl", "default global")]
+ [InlineData("AddParameterDB7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterDB7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//global param is xsl:param local param is xsl:variable
//[Variation(id = 43, Pri = 2, Desc = "Param sent, global param used, local variable exists with a default value", Params = new object[] { "AddParameterEB1.xsl", "default local" })]
- [InlineData("AddParameterEB1.xsl", "default local")]
+ [InlineData("AddParameterEB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 44, Pri = 2, Desc = "Param sent, global param used, local variable exists with no default value", Params = new object[] { "AddParameterEB2.xsl", "" })]
- [InlineData("AddParameterEB2.xsl", "")]
+ [InlineData("AddParameterEB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 45, Pri = 2, Desc = "Param sent, global param used, local variable doesn't exist but reference to param exists", Params = new object[] { "AddParameterEB3.xsl", "outside param" })]
- [InlineData("AddParameterEB3.xsl", "outside param")]
+ [InlineData("AddParameterEB3.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB3.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 46, Pri = 2, Desc = "Param sent, global param used, local variable exists with a default value and with-param sends a value", Params = new object[] { "AddParameterEB4.xsl", "default local" })]
- [InlineData("AddParameterEB4.xsl", "default local")]
+ [InlineData("AddParameterEB4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 47, Pri = 2, Desc = "Param sent, global param used, local variable exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterEB5.xsl", "" })]
- [InlineData("AddParameterEB5.xsl", "")]
+ [InlineData("AddParameterEB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 48, Pri = 2, Desc = "Param sent, global param used, local variable doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterEB6.xsl", "outside param" })]
- [InlineData("AddParameterEB6.xsl", "outside param")]
+ [InlineData("AddParameterEB6.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB6.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 49, Pri = 2, Desc = "Param sent, global param used, local variable doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterEB7.xsl", "outside param" })]
- [InlineData("AddParameterEB7.xsl", "outside param")]
+ [InlineData("AddParameterEB7.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterEB7.xsl", "outside param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//global param is xsl:variable local param is xsl:variable
//[Variation(id = 50, Pri = 2, Desc = "Param sent, global variable used, local variable exists with a default value", Params = new object[] { "AddParameterFB1.xsl", "default local" })]
- [InlineData("AddParameterFB1.xsl", "default local")]
+ [InlineData("AddParameterFB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 51, Pri = 2, Desc = "Param sent, global variable used, local variable exists with no default value", Params = new object[] { "AddParameterFB2.xsl", "" })]
- [InlineData("AddParameterFB2.xsl", "")]
+ [InlineData("AddParameterFB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 52, Pri = 2, Desc = "Param sent, global variable used, local variable doesn't exist but reference to param exists", Params = new object[] { "AddParameterFB3.xsl", "default global" })]
- [InlineData("AddParameterFB3.xsl", "default global")]
+ [InlineData("AddParameterFB3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB3.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 53, Pri = 2, Desc = "Param sent, global variable used, local variable exists with a default value and with-param sends a value", Params = new object[] { "AddParameterFB4.xsl", "default local" })]
- [InlineData("AddParameterFB4.xsl", "default local")]
+ [InlineData("AddParameterFB4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB4.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 54, Pri = 2, Desc = "Param sent, global variable used, local variable exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterFB5.xsl", "" })]
- [InlineData("AddParameterFB5.xsl", "")]
+ [InlineData("AddParameterFB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 55, Pri = 2, Desc = "Param sent, global variable used, local variable doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterFB6.xsl", "default global" })]
- [InlineData("AddParameterFB6.xsl", "default global")]
+ [InlineData("AddParameterFB6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB6.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 56, Pri = 2, Desc = "Param sent, global variable used, local variable doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterFB7.xsl", "default global" })]
- [InlineData("AddParameterFB7.xsl", "default global")]
+ [InlineData("AddParameterFB7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterFB7.xsl", "default global", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam2(object param0, object param1)
+ public void AddParam2(object param0, object param1, InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
string xslFile = param0.ToString();
string expected = "<result>" + param1.ToString() + "</result>";
@@ -1746,7 +2069,7 @@ namespace System.Xml.Tests
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("param1", "", "outside param");
- if ((LoadXSL(xslFile) == 1) && (Transform_ArgList("AddParameter.xml") == 1))
+ if ((LoadXSL(xslFile, inputType, readerType) == 1) && (Transform_ArgList("AddParameter.xml", transformType, docType) == 1))
VerifyResult(expected);
else
Assert.True(false);
@@ -1755,21 +2078,77 @@ namespace System.Xml.Tests
//All the below variations, empty param is sent from client code
//global param is xsl:param local param is xsl:param
//[Variation(id = 57, Pri = 2, Desc = "Param sent, global param used, local param exists with a default value", Params = new object[] { "AddParameterB1.xsl", "default local" })]
- [InlineData("AddParameterB1.xsl", "default local")]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB1.xsl", "default local", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 58, Pri = 2, Desc = "Param sent, global param used, local param exists with no default value", Params = new object[] { "AddParameterB2.xsl", "" })]
- [InlineData("AddParameterB2.xsl", "")]
+ [InlineData("AddParameterB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB2.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 59, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist but reference to param exists", Params = new object[] { "AddParameterB3.xsl", "" })]
- [InlineData("AddParameterB3.xsl", "")]
+ [InlineData("AddParameterB3.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB3.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 60, Pri = 2, Desc = "Param sent, global param used, local param exists with a default value and with-param sends a value", Params = new object[] { "AddParameterB4.xsl", "with-param" })]
- [InlineData("AddParameterB4.xsl", "with-param")]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB4.xsl", "with-param", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 61, Pri = 2, Desc = "Param sent, global param used, local param exists with no default value and with-param doesn't send a value", Params = new object[] { "AddParameterB5.xsl", "" })]
- [InlineData("AddParameterB5.xsl", "")]
+ [InlineData("AddParameterB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB5.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 62, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist, reference to param, with-param sends a value", Params = new object[] { "AddParameterB6.xsl", "" })]
- [InlineData("AddParameterB6.xsl", "")]
+ [InlineData("AddParameterB6.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB6.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
//[Variation(id = 63, Pri = 2, Desc = "Param sent, global param used, local param doesn't exist, reference to param, with-param sends no value", Params = new object[] { "AddParameterB7.xsl", "" })]
- [InlineData("AddParameterB7.xsl", "")]
+ [InlineData("AddParameterB7.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData("AddParameterB7.xsl", "", InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddParam3(object param0, object param1)
+ public void AddParam3(object param0, object param1, InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
string xslFile = param0.ToString();
string expected = "<result>" + param1.ToString() + "</result>";
@@ -1777,7 +2156,7 @@ namespace System.Xml.Tests
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("param1", "", "");
- if ((LoadXSL(xslFile) == 1) && (Transform_ArgList("AddParameter.xml") == 1))
+ if ((LoadXSL(xslFile, inputType, readerType) == 1) && (Transform_ArgList("AddParameter.xml", transformType, docType) == 1))
VerifyResult(expected);
else
Assert.True(false);
@@ -1810,18 +2189,35 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "Basic Verification Test", Pri = 0)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject1()
+ public void AddExtObject1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ 1.Test1
+ 2.Test2
+ 3.Test3</result>";
+
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(430.402026847) == 1))
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -1859,29 +2255,65 @@ namespace System.Xml.Tests
}
//[Variation("Very long namespace System.Xml.Tests")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject4()
+ public void AddExtObject4(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""http://www.miocrosoft.com/this/is/a/very/long/namespace/uri/to/do/the/api/testing/for/xslt/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/0123456789/"">
+ 1.Test1
+ 2.Test2
+ 3.Test3</result>";
+
m_xsltArg = new XsltArgumentList();
MyObject obj = new MyObject(4, _output);
m_xsltArg.AddExtensionObject(szLongNS, obj);
- if ((LoadXSL("MyObjectLongNS.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(522.0563223871) == 1))
+ if ((LoadXSL("myObjectLongNS.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Different Data Types")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject6()
+ public void AddExtObject6(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+
+ String Argument: System.String
+ Int32 Argument: System.Int32
+ Boolean Argument: System.Boolean
+ Boolean Argument: System.Boolean
+ Double Argument: System.Double
+ String Argument: System.String</result>";
+
m_xsltArg = new XsltArgumentList();
String obj = "0.00";
@@ -1952,9 +2384,11 @@ namespace System.Xml.Tests
retObj = m_xsltArg.GetExtensionObject("myArg6");
_output.WriteLine("Added Value:{0}\nRetrieved Value: {1}", bT.ToString(), retObj);
- if ((LoadXSL("MyObject_DataTypes.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(499.4069850096) == 1))
+ if ((LoadXSL("MyObject_DataTypes.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -1982,11 +2416,26 @@ namespace System.Xml.Tests
}
//[Variation("Case sensitivity")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject8()
+ public void AddExtObject8(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ 1.Test1
+ 2.Test2
+ 3.Test3</result>";
+
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
@@ -2002,9 +2451,11 @@ namespace System.Xml.Tests
m_xsltArg.AddExtensionObject("urn:My-Object", obj);
m_xsltArg.AddExtensionObject("urn-my:object", obj);
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(430.402026847) == 1))
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -2030,28 +2481,60 @@ namespace System.Xml.Tests
}
//[Variation("Unitialized and NULL return values from the methods in the extension object")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject10()
+ public void AddExtObject10(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+
+ Test1
+ Test2: 0</result>";
+
MyObject obj = new MyObject(10, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_Null.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(424.8906559839) == 1))
+ if ((LoadXSL("MyObject_Null.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Add many objects")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject11()
+ public void AddExtObject11(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ 1.Test1
+ 2.Test2
+ 3.Test3</result>";
+
m_xsltArg = new XsltArgumentList();
MyObject obj1 = new MyObject(100, _output);
@@ -2062,17 +2545,30 @@ namespace System.Xml.Tests
MyObject obj = new MyObject(i, _output);
m_xsltArg.AddExtensionObject(szDefaultNS + i, obj);
}
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(430.402026847) == 1))
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Whitespace")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject12()
+ public void AddExtObject12(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
int i = 1;
m_xsltArg = new XsltArgumentList();
@@ -2085,8 +2581,8 @@ namespace System.Xml.Tests
}
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2118,11 +2614,26 @@ namespace System.Xml.Tests
}
//[Variation("Add and Remove multiple times")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject14()
+ public void AddExtObject14(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ 1.Test1
+ 2.Test2
+ 3.Test3</result>";
+
MyObject obj = new MyObject(14, _output);
m_xsltArg = new XsltArgumentList();
@@ -2133,17 +2644,30 @@ namespace System.Xml.Tests
}
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(430.402026847) == 1))
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Namespace URI non-existent")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject15()
+ public void AddExtObject15(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
MyObject obj = new MyObject(15, _output);
m_xsltArg = new XsltArgumentList();
@@ -2151,8 +2675,8 @@ namespace System.Xml.Tests
m_xsltArg.AddExtensionObject(szSimple, obj);
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2163,9 +2687,20 @@ namespace System.Xml.Tests
}
//[Variation("Accessing Private and protected Items")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject16()
+ public void AddExtObject16(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
@@ -2173,22 +2708,22 @@ namespace System.Xml.Tests
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
try
{
- LoadXSL("MyObject_PrivateAccess.xsl");
- Transform_ArgList("fruits.xml", true);
+ LoadXSL("MyObject_PrivateAccess.xsl", inputType, readerType);
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
try
{
- LoadXSL("MyObject_ProtectedAccess.xsl");
- Transform_ArgList("fruits.xml", true);
+ LoadXSL("MyObject_ProtectedAccess.xsl", inputType, readerType);
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
try
{
- LoadXSL("MyObject_DefaultAccess.xsl");
- Transform_ArgList("fruits.xml", true);
+ LoadXSL("MyObject_DefaultAccess.xsl", inputType, readerType);
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2200,103 +2735,215 @@ namespace System.Xml.Tests
}
//[Variation("Writing To Output")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject17()
+ public void AddExtObject17(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ Here:End
+ </result>";
+
MyObject obj = new MyObject(17, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_ConsoleWrite.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(421.8660259804) == 1))
+ if ((LoadXSL("MyObject_ConsoleWrite.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Recursive Functions")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject18()
+ public void AddExtObject18(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ Recursive Function Returning the factorial of five:120</result>";
+
MyObject obj = new MyObject(18, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_Recursion.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(459.4210605285) == 1))
+ if ((LoadXSL("MyObject_Recursion.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Overloaded Functions")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject19()
+ public void AddExtObject19(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ Overloaded Double: Int Overlaod
+ Overloaded Int: Int Overlaod
+ Overloaded String: String Overlaod</result>";
+
MyObject obj = new MyObject(19, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_Overloads.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(481.1053900491) == 1))
+ if ((LoadXSL("MyObject_Overloads.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Function-exists tests")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject20()
+ public void AddExtObject20(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ DoNothing Function Test Pass
+ Construtor Function
+ Return Int Function Test Pass
+ Return String Function Test Pass
+ ReturnInt Function Test Pass
+ Taking in args Test Pass
+ Public Function Test Pass
+ Protected Function
+ Private Function
+ Default Function</result>";
+
MyObject obj = new MyObject(20, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_FnExists.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(534.2681508201) == 1))
+ if ((LoadXSL("MyObject_FnExists.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Argument Tests")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject21()
+ public void AddExtObject21(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+
+ String Argument: Received a string with value: Hello
+ Double Argument: Received a double with value 3.14
+ Boolean Argument: Statement is True
+ Boolean True Argument: Statement is False</result>";
+
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_Arguments.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(513.296131727) == 1))
+ if ((LoadXSL("MyObject_Arguments.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Methods returning void and valid types")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject22()
+ public void AddExtObject22(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ Get A String:Hello world
+ Get A Double:22.41276
+ Get A True Boolean:true
+ Get A False Boolean:false
+ Get An Int:10
+ Get Other with ToString() Support:My Custom Object has a value of 22
+ Call function with no return type:</result>";
+
MyObject obj = new MyObject(22, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_ReturnValidTypes.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(514.0958814743) == 1))
+ if ((LoadXSL("MyObject_ReturnValidTypes.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -2325,20 +2972,31 @@ namespace System.Xml.Tests
}
//[Variation("Case Sensitivity")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject25()
+ public void AddExtObject25(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
MyObject obj = new MyObject(25, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if (LoadXSL("MyObject_CaseSensitive.xsl") == 1)
+ if (LoadXSL("MyObject_CaseSensitive.xsl", inputType, readerType) == 1)
{
try
{
- Transform_ArgList("fruits.xml");
- CheckResult(419.3031944636);
+ Transform_ArgList("fruits.xml", transformType, docType);
+ CheckResult(419.3031944636, transformType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2350,19 +3008,30 @@ namespace System.Xml.Tests
}
//[Variation("Object namespace System.Xml.Tests found")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject26()
+ public void AddExtObject26(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
MyObject obj = new MyObject(26, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_NotFoundNS.xsl") == 1))
+ if ((LoadXSL("MyObject_NotFoundNS.xsl", inputType, readerType) == 1))
{
try
{
- Transform_ArgList("fruits.xml", true);
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2374,53 +3043,107 @@ namespace System.Xml.Tests
}
//[Variation("Maintaining State")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject27()
+ public void AddExtObject27(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ A:27
+ B:23
+ C:23
+ D:23
+ E:37
+ F:Hello
+ G:Hello World
+ E:-13</result>";
+
MyObject obj = new MyObject(27, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_KeepingState.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(439.7536748395) == 1))
+ if ((LoadXSL("MyObject_KeepingState.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Deliberately Messing Up the Stylesheet")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject28()
+ public void AddExtObject28(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+
+ Aiming with Gun: &gt;"" $tmp &gt;;'
+&amp;
+ Aiming with Missile: &lt;xsl:variable name=""tmp""/&gt;
+ Aiming with Nuclear: &lt;/xsl:stylesheet&gt;
+ Wow...survived all killer ammo.
+ </result>";
+
MyObject obj = new MyObject(28, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_KillerStrings.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(495.5795381156) == 1 || CheckResult(503.3730396353) == 1)) //multiple baseline
+ if ((LoadXSL("MyObject_KillerStrings.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Function not found in Object")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject29()
+ public void AddExtObject29(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
MyObject obj = new MyObject(29, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
- if ((LoadXSL("MyObject_NotFound.xsl") == 1))
+ if ((LoadXSL("MyObject_NotFound.xsl", inputType, readerType) == 1))
{
try
{
- Transform_ArgList("fruits.xml", true);
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -2444,27 +3167,50 @@ namespace System.Xml.Tests
}
//[Variation("Extension objects should not be cached during Transform()")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void AddExtObject32()
+ public void AddExtObject32(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
- if (LoadXSL("Bug78587.xsl") == 1)
+ string expected1 = @"<?xml version=""1.0"" encoding=""utf-8""?><out xmlns:id=""id"" xmlns:cap=""capitalizer"">
+ ID: first
+ Capitalized ID: FIRST</out>";
+
+ string expected2 = @"<?xml version=""1.0"" encoding=""utf-8""?><out xmlns:id=""id"" xmlns:cap=""capitalizer"">
+ ID: second
+ Capitalized ID: SECOND</out>";
+
+ if (LoadXSL("Bug78587.xsl", inputType, readerType) == 1)
{
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject("id", new Id("first"));
m_xsltArg.AddExtensionObject("capitalizer", new Capitalizer());
// Transform once
- if ((Transform_ArgList("Bug78587.xml") == 1) && (CheckResult(438.9506396879) == 1))
+ if (Transform_ArgList("Bug78587.xml", transformType, docType) == 1)
{
+ VerifyResult(expected1);
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject("id", new Id("second"));
m_xsltArg.AddExtensionObject("capitalizer", new Capitalizer());
// Transform again to make sure that extension objects from first transform are not cached
- if ((Transform_ArgList("Bug78587.xml") == 1) && (CheckResult(440.0296788876) == 1))
+ if (Transform_ArgList("Bug78587.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected2);
return;
+ }
}
}
Assert.True(false);
@@ -2489,11 +3235,21 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "Basic Verification Test", Pri = 0)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam1()
+ public void RemoveParam1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test2");
@@ -2514,9 +3270,11 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(457.6003003605) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -2537,67 +3295,110 @@ namespace System.Xml.Tests
}
//[Variation("Param name is empty string")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam3()
+ public void RemoveParam3(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.RemoveParam(szEmpty, szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Param name is non-existent")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam4()
+ public void RemoveParam4(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.RemoveParam(szSimple, szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Invalid Param name")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam5()
+ public void RemoveParam5(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.RemoveParam(szInvalid, szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Very long param name")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam6()
+ public void RemoveParam6(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam(szLongString, szEmpty, "Test1");
m_xsltArg.RemoveParam(szLongString, szEmpty);
- if ((LoadXSL("showParamLongName.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(400.2204182193) == 1))
+ if ((LoadXSL("showParamLongName.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -2619,65 +3420,111 @@ namespace System.Xml.Tests
}
//[Variation("Namespace URI is empty string")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam8()
+ public void RemoveParam8(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
m_xsltArg.RemoveParam("myArg1", szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Namespace URI is non-existent")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam9()
+ public void RemoveParam9(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
m_xsltArg.RemoveParam("myArg1", "http://www.xsltTest.com");
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(457.6003003605) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Very long namespace System.Xml.Tests")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam10()
+ public void RemoveParam10(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szLongString, "Test1");
m_xsltArg.RemoveParam("myArg1", szLongString);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Different Data Types")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam11()
+ public void RemoveParam11(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
double d1 = double.PositiveInfinity;
double d2 = double.NegativeInfinity;
double d3 = double.NaN;
@@ -2867,19 +3714,31 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Case Sensitivity")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam12()
+ public void RemoveParam12(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -2888,19 +3747,31 @@ namespace System.Xml.Tests
m_xsltArg.RemoveParam("myArg1 ", szEmpty);
// perform a transform for kicks and ensure all is ok.
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(457.6003003605) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Whitespace")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam13()
+ public void RemoveParam13(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test
+ 2.Test
+ 3.Test
+ 4.Test
+ 5.Test
+ 6.No Value Specified</result>";
+
int i = 1;
m_xsltArg = new XsltArgumentList();
@@ -2932,19 +3803,31 @@ namespace System.Xml.Tests
}
// perform a transform for kicks and ensure all is ok.
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(421.3863242307) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Call Multiple Times")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void RemoveParam14()
+ public void RemoveParam14(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -2952,9 +3835,11 @@ namespace System.Xml.Tests
for (int i = 0; i < 500; i++)
m_xsltArg.RemoveParam("myArg1", szEmpty);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -2989,9 +3874,12 @@ namespace System.Xml.Tests
}
//[Variation(Desc = "Basic Verification Test", Pri = 0)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void RemoveExtObj1()
+ public void RemoveExtObj1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
MyObject obj = new MyObject(1, _output);
m_xsltArg = new XsltArgumentList();
@@ -3001,8 +3889,8 @@ namespace System.Xml.Tests
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -3033,11 +3921,21 @@ namespace System.Xml.Tests
}
//[Variation("Call Multiple Times")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void RemoveExtObj3()
+ public void RemoveExtObj3(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
MyObject obj = new MyObject(10, _output);
m_xsltArg = new XsltArgumentList();
@@ -3046,36 +3944,50 @@ namespace System.Xml.Tests
for (int i = 0; i < 500; i++)
m_xsltArg.RemoveExtensionObject(szDefaultNS);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Namespace URI is non-existent")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void RemoveExtObj4()
+ public void RemoveExtObj4(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ 1.Test1
+ 2.Test2
+ 3.Test3</result>";
+
MyObject obj = new MyObject(4, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject(szDefaultNS, obj);
m_xsltArg.RemoveExtensionObject(szSimple);
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(430.402026847) == 1))
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Very long namespace System.Xml.Tests")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void RemoveExtObj5()
+ public void RemoveExtObj5(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
m_xsltArg = new XsltArgumentList();
MyObject obj = new MyObject(5, _output);
@@ -3085,8 +3997,8 @@ namespace System.Xml.Tests
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -3097,11 +4009,21 @@ namespace System.Xml.Tests
}
//[Variation("Different Data Types")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void RemoveExtObj6()
+ public void RemoveExtObj6(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
MyObject obj = new MyObject(6, _output);
m_xsltArg = new XsltArgumentList();
@@ -3123,19 +4045,28 @@ namespace System.Xml.Tests
m_xsltArg.AddExtensionObject("urn:my-object", false);
m_xsltArg.RemoveExtensionObject("urn:my-object");
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Case Sensitivity")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void RemoveExtObj7()
+ public void RemoveExtObj7(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result xmlns:myObj=""urn:my-object"">
+ 1.Test1
+ 2.Test2
+ 3.Test3</result>";
+
MyObject obj = new MyObject(7, _output);
m_xsltArg = new XsltArgumentList();
@@ -3146,17 +4077,22 @@ namespace System.Xml.Tests
m_xsltArg.RemoveExtensionObject("urn-my:object");
m_xsltArg.RemoveExtensionObject("urn:my-object ");
- if ((LoadXSL("myObjectDef.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(430.402026847) == 1))
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Whitespace")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void RemoveExtObj8()
+ public void RemoveExtObj8(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
int i = 1;
m_xsltArg = new XsltArgumentList();
@@ -3178,8 +4114,8 @@ namespace System.Xml.Tests
try
{
- if ((LoadXSL("myObjectDef.xsl") == 1))
- Transform_ArgList("fruits.xml", true);
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1))
+ Transform_ArgList("fruits.xml", true, transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -3190,20 +4126,32 @@ namespace System.Xml.Tests
}
//[Variation("Using default XSLT namespace - Bug305503")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void RemoveExtObj9()
+ public void RemoveExtObj9(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
MyObject obj = new MyObject(10, _output);
m_xsltArg = new XsltArgumentList();
m_xsltArg.RemoveExtensionObject(szDefaultNS);
// ensure we can still do a transform
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -3222,12 +4170,19 @@ namespace System.Xml.Tests
_output = output;
}
- //[Variation(Desc = "Basic Verification Test", Pri = 0)]
- [ActiveIssue(9877)]
- [InlineData()]
+ //[Variation(Desc = "Basic Verification Test", Pri = 0)][InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void Clear1()
+ public void Clear1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -3240,35 +4195,53 @@ namespace System.Xml.Tests
if (retObj != null)
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Clear with nothing loaded")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void Clear2()
+ public void Clear2(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.Clear();
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Clear Params")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void Clear3()
+ public void Clear3(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -3281,17 +4254,19 @@ namespace System.Xml.Tests
if (retObj != null)
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Clear Extension Objects")]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void Clear4()
+ public void Clear4(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
MyObject obj = new MyObject(26, _output);
m_xsltArg = new XsltArgumentList();
@@ -3305,11 +4280,11 @@ namespace System.Xml.Tests
Assert.True(false);
}
- if ((LoadXSL("myObjectDef.xsl") == 1))
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1))
{
try
{
- Transform_ArgList("fruits.xml");
+ Transform_ArgList("fruits.xml", transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -3321,11 +4296,18 @@ namespace System.Xml.Tests
}
//[Variation("Clear Many Objects")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void Clear5()
+ public void Clear5(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
String obj = "Test";
@@ -3354,23 +4336,30 @@ namespace System.Xml.Tests
}
}
- // _output.WriteLine(retObj.GetType());
-
m_xsltArg.Clear();
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Clear Multiple Times")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void Clear6()
+ public void Clear6(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -3384,19 +4373,28 @@ namespace System.Xml.Tests
if (retObj != null)
Assert.True(false);
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Loading one object, but clearing another")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void Clear7()
+ public void Clear7(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.Test1
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
XsltArgumentList m_2 = new XsltArgumentList();
@@ -3407,19 +4405,28 @@ namespace System.Xml.Tests
m_2.Clear();
- if ((LoadXSL("showParam.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) &&
- (CheckResult(457.6003003605) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Clear after objects have been \"Removed\"")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void Clear8()
+ public void Clear8(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("myArg1", szEmpty, "Test1");
@@ -3429,9 +4436,10 @@ namespace System.Xml.Tests
retObj = m_xsltArg.RemoveParam("myArg1", szEmpty);
m_xsltArg.Clear();
- if ((LoadXSL("showParam.xsl") != 1) || (Transform_ArgList("fruits.xml") != 1) ||
- (CheckResult(466.5112789241) != 1))
- Assert.True(false);
+ if ((LoadXSL("showParam.xsl", inputType, readerType) != 1) || (Transform_ArgList("fruits.xml", transformType, docType) != 1))
+ Assert.True(false);
+
+ VerifyResult(expected);
MyObject obj = new MyObject(26, _output);
@@ -3439,11 +4447,11 @@ namespace System.Xml.Tests
m_xsltArg.RemoveExtensionObject(szDefaultNS);
m_xsltArg.Clear();
- if ((LoadXSL("myObjectDef.xsl") == 1))
+ if ((LoadXSL("myObjectDef.xsl", inputType, readerType) == 1))
{
try
{
- Transform_ArgList("fruits.xml");
+ Transform_ArgList("fruits.xml", transformType, docType);
}
catch (System.Xml.Xsl.XsltException)
{
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs
index c3b6b95fae..bab4a2c646 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs
@@ -1,14 +1,12 @@
+
// 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 Xunit;
using Xunit.Abstractions;
-using System;
using System.Collections;
using System.IO;
-using System.Security;
-using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
@@ -371,17 +369,35 @@ namespace System.Xml.Tests
}
//[Variation("Set XmlResolver property to null, load style sheet with import/include, should not affect transform")]
- [InlineData()]
- [Theory(Skip = "Resolving of External URIs is no longer allowed")]
- public void XmlResolver1()
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void XmlResolver1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
+
try
{
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", inputType, readerType) == 1)
{
xslt.XmlResolver = null;
- if ((Transform("fruits.xml") == 1) && (CheckResult(428.8541842246) == 1))
+ if (Transform("fruits.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -396,18 +412,34 @@ namespace System.Xml.Tests
}
//[Variation("Set XmlResolver property to null, load style sheet with document function, should not resolve during transform")]
- [InlineData()]
- [Theory]
- public void XmlResolver2()
- {
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void XmlResolver2(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result></result>";
+
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", inputType, readerType) == 1)
{
xslt.XmlResolver = null;
- if ((Transform("fruits.xml") == 1) && (CheckResult(375.6079891948) == 1))
+ if (Transform("fruits.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
}
else
{
@@ -418,9 +450,20 @@ namespace System.Xml.Tests
}
//[Variation("Default XmlResolver, load style sheet with document function, should resolve during transform")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory(Skip = "SQLBU Defect Tracking Bug 430834: Skipping when input type is URI, see bug for more details.")]
- public void XmlResolver3()
+ public void XmlResolver3(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
@@ -429,9 +472,9 @@ namespace System.Xml.Tests
//if (MyInputType() == InputType.URI)
// return TEST_SKIPPED;
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", inputType, readerType) == 1)
{
- if ((Transform("fruits.xml") == 1) && (CheckResult(377.8217373898) == 1))
+ if ((Transform("fruits.xml", transformType, docType) == 1) && (CheckResult(377.8217373898, transformType) == 1))
return;
}
else
@@ -443,9 +486,20 @@ namespace System.Xml.Tests
}
//[Variation("document() has absolute URI")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory(Skip = "When style sheet URI = Intranet zone, XmlSecureResolver does not resolve document function")]
- public void XmlResolver7()
+ public void XmlResolver7(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
// Skip this test for Load(URI)
// Reason: When style sheet URI = Intranet zone, XmlSecureResolver does not resolve document function
@@ -457,12 +511,13 @@ namespace System.Xml.Tests
try
{
- if (!Directory.Exists("c:\\temp"))
+ string tempDir = Path.GetTempPath();
+ if (!Directory.Exists(tempDir))
{
- Directory.CreateDirectory("c:\\temp");
+ Directory.CreateDirectory(tempDir);
}
string xmlFile = FullFilePath("xmlResolver_document_function.xml");
- File.Copy(xmlFile, @"c:\temp\xmlResolver_document_function.xml", true);
+ File.Copy(xmlFile, Path.Combine(tempDir, "xmlResolver_document_function.xml"), true);
}
catch (Exception e)
{
@@ -471,9 +526,9 @@ namespace System.Xml.Tests
return; //return TEST_SKIPPED;
}
- if (LoadXSL("xmlResolver_document_function_absolute_uri.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function_absolute_uri.xsl", inputType, readerType) == 1)
{
- if ((Transform("fruits.xml") == 1) && (CheckResult(377.8217373898) == 1))
+ if ((Transform("fruits.xml", transformType, docType) == 1) && (CheckResult(377.8217373898, transformType) == 1))
return;
else
{
@@ -514,13 +569,15 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null value")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric1()
+ public void LoadGeneric1(InputType inputType, ReaderType readerType)
{
try
{
- LoadXSL(null);
+ LoadXSL(null, inputType, readerType);
}
catch (System.ArgumentException)
{
@@ -532,21 +589,32 @@ namespace System.Xml.Tests
}
//[Variation("Load with valid, then invalid, then valid again")]
- [InlineData()]
- [Theory]
- public void LoadGeneric2()
- {
- if (LoadXSL("showParam.xsl") == 1)
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric2(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
- LoadXSL("IDontExist.xsl");
+ LoadXSL("IDontExist.xsl", inputType, readerType);
}
catch (System.IO.FileNotFoundException)
{
try
{
- Transform("fruits.xml");
+ Transform("fruits.xml", transformType, docType);
}
catch (System.InvalidOperationException e)
{
@@ -564,84 +632,147 @@ namespace System.Xml.Tests
}
//[Variation("Load an invalid, then a valid and transform")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void LoadGeneric3()
- {
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric3(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
try
{
- LoadXSL("IDontExist.xsl");
+ LoadXSL("IDontExist.xsl", inputType, readerType);
}
catch (System.IO.FileNotFoundException)
{
- if ((LoadXSL("ShowParam.xsl") == 1) && (Transform("fruits.xml") == 1)
- && (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
}
_output.WriteLine("Exception not generated for non-existent file name");
Assert.True(false);
}
//[Variation("Call several overloaded functions")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void LoadGeneric4()
- {
- if (MyInputType() != InputType.Reader)
- LoadXSL("showParamLongName.xsl", InputType.Reader);
- if (MyInputType() != InputType.URI)
- LoadXSL("showParamLongName.xsl", InputType.URI);
- if (MyInputType() != InputType.Navigator)
- LoadXSL("showParamLongName.xsl", InputType.Navigator);
-
- if ((LoadXSL("ShowParam.xsl") == 0) || (Transform("fruits.xml") == 0)
- || (CheckResult(466.5112789241) == 0))
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric4(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
+ if (inputType != InputType.Reader)
+ LoadXSL("showParamLongName.xsl", InputType.Reader, readerType);
+ if (inputType != InputType.URI)
+ LoadXSL("showParamLongName.xsl", InputType.URI, readerType);
+ if (inputType != InputType.Navigator)
+ LoadXSL("showParamLongName.xsl", InputType.Navigator, readerType);
+
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 0) || (Transform("fruits.xml", transformType, docType) == 0))
Assert.True(false);
- if (MyInputType() != InputType.Navigator)
- LoadXSL("showParamLongName.xsl", InputType.Navigator);
- if (MyInputType() != InputType.URI)
- LoadXSL("showParamLongName.xsl", InputType.URI);
- if (MyInputType() != InputType.Reader)
- LoadXSL("showParamLongName.xsl", InputType.Reader);
+ VerifyResult(expected);
- if ((LoadXSL("ShowParam.xsl") == 1) && (Transform("fruits.xml") == 1)
- && (CheckResult(466.5112789241) == 1))
+ if (inputType != InputType.Navigator)
+ LoadXSL("showParamLongName.xsl", InputType.Navigator, readerType);
+ if (inputType != InputType.URI)
+ LoadXSL("showParamLongName.xsl", InputType.URI, readerType);
+ if (inputType != InputType.Reader)
+ LoadXSL("showParamLongName.xsl", InputType.Reader, readerType);
+
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
//[Variation("Call same overloaded Load() many times then transform")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void LoadGeneric5()
- {
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric5(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
for (int i = 0; i < 100; i++)
{
- if (LoadXSL("showParam.xsl") != 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) != 1)
{
_output.WriteLine("Failed to load stylesheet showParam.xsl on the {0} attempt", i);
Assert.True(false);
}
}
- if ((LoadXSL("ShowParam.xsl") == 1) && (Transform("fruits.xml") == 1)
- && (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
//[Variation("Call load with non-existing stylesheet")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric6()
+ public void LoadGeneric6(InputType inputType, ReaderType readerType)
{
try
{
- LoadXSL("IDontExist.xsl");
+ LoadXSL("IDontExist.xsl", inputType, readerType);
}
catch (System.IO.FileNotFoundException)
{
@@ -652,19 +783,35 @@ namespace System.Xml.Tests
}
//[Variation("Verify that style sheet is closed properly after Load - Shared Read Access")]
- [InlineData()]
- [Theory(Skip = "Resolving of External URIs is no longer allowed")]
- public void LoadGeneric7()
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric7(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
+
FileStream s2;
// check immediately after load and after transform
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", inputType, readerType) == 1)
{
s2 = new FileStream(FullFilePath("XmlResolver_Main.xsl"), FileMode.Open, FileAccess.Read, FileShare.Read);
s2.Dispose();
- if ((Transform("fruits.xml") == 1) && (CheckResult(428.8541842246) == 1))
+ if (Transform("fruits.xml", transformType, docType) == 1)
{
+ VerifyResult(expected);
s2 = new FileStream(FullFilePath("XmlResolver_Main.xsl"), FileMode.Open, FileAccess.Read, FileShare.Read);
s2.Dispose();
return;
@@ -673,46 +820,36 @@ namespace System.Xml.Tests
Assert.True(false);
}
- /*
- //[Variation("Verify that style sheet is closed properly after Load - ReadWrite Access")]
- [InlineData()]
+ //[Variation("Verify that included files are closed properly after Load - Read Access")]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void LoadGeneric8()
+ public void LoadGeneric9(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
- FileStream s2;
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
- // check immediately after load and after transform
-
- if(LoadXSL("XmlResolver_Main.xsl") == TEST_PASS)
- {
- s2 = new FileStream(FullFilePath("XmlResolver_Main.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
- if((Transform("fruits.xml") == TEST_PASS) && (CheckResult(428.8541842246)== TEST_PASS))
- {
- s2 = new FileStream(FullFilePath("XmlResolver_Main.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
- return;
- }
- }
- _output.WriteLine("Appeared to not close style sheet file properly after loading.");
- Assert.True(false);
- }
- */
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
- //[Variation("Verify that included files are closed properly after Load - Read Access")]
- [InlineData()]
- [Theory(Skip = "Resolving of External URIs is no longer allowed")]
- public void LoadGeneric9()
- {
FileStream s2;
// check immediately after load and after transform
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", inputType, readerType) == 1)
{
- s2 = new FileStream(FullFilePath("XmlResolver_sub.xsl"), FileMode.Open, FileAccess.Read);
+ s2 = new FileStream(FullFilePath("XmlResolver_Sub.xsl"), FileMode.Open, FileAccess.Read);
s2.Dispose();
- if ((Transform("fruits.xml") == 1) && (CheckResult(428.8541842246) == 1))
+ if (Transform("fruits.xml", transformType, docType) == 1)
{
+ VerifyResult(expected);
s2 = new FileStream(FullFilePath("XmlResolver_Include.xsl"), FileMode.Open, FileAccess.Read, FileShare.Read);
s2.Dispose();
return;
@@ -722,64 +859,57 @@ namespace System.Xml.Tests
Assert.True(false);
}
- /*
- //[Variation("Verify that included files are closed properly after Load - ReadWrite Access")]
- [InlineData()]
- [Theory]
- public void LoadGeneric10()
- {
- FileStream s2;
-
- // check immediately after load and after transform
- if(LoadXSL("XmlResolver_Main.xsl") == TEST_PASS)
- {
- s2 = new FileStream(FullFilePath("XmlResolver_sub.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
- if((Transform("fruits.xml") == TEST_PASS) && (CheckResult(428.8541842246)== TEST_PASS))
- {
- s2 = new FileStream(FullFilePath("XmlResolver_Include.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
- return;
- }
- }
- _output.WriteLine("Appeared to not close file properly after loading.");
- Assert.True(false);
- }
- */
-
//[Variation("Load stylesheet with entity reference: Bug #68450 ")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void LoadGeneric11()
- {
- if (MyDocType().ToString() == "DataDocument")
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric11(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><Book>
+ Name
+ </Book>";
+
+ if (docType.ToString() == "DataDocument")
// Skip the test for DataDocument
return;
else
{
- if (LoadXSL("books_entity_ref.xsl", InputType.Reader) != 1)
+ if (LoadXSL("books_entity_ref.xsl", InputType.Reader, readerType) != 1)
{
_output.WriteLine("Failed to load stylesheet books_entity_ref.xsl");
Assert.True(false);
}
- if ((LoadXSL("books_entity_ref.xsl") == 1) && (Transform("books_entity_ref.xml") == 1)
- && (CheckResult(371.4148215954) == 1))
+ if ((LoadXSL("books_entity_ref.xsl", inputType, readerType) == 1) && (Transform("books_entity_ref.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
}
//[Variation("Load with invalid stylesheet and verify that file is closed properly")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric12()
+ public void LoadGeneric12(InputType inputType, ReaderType readerType)
{
Stream strmTemp;
try
{
- int i = LoadXSL("xslt_error.xsl");
+ int i = LoadXSL("xslt_error.xsl", inputType, readerType);
}
catch (System.Xml.Xsl.XsltCompileException)
{
@@ -826,13 +956,15 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null source value and null resolver")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric1()
+ public void LoadGeneric1(InputType inputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver(null, null);
+ LoadXSL_Resolver(null, null, inputType, readerType);
}
catch (System.ArgumentException)
{
@@ -844,13 +976,15 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null source value and valid resolver")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric2()
+ public void LoadGeneric2(InputType inputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver(null, new XmlUrlResolver());
+ LoadXSL_Resolver(null, new XmlUrlResolver(), inputType, readerType);
}
catch (System.ArgumentException)
{
@@ -862,15 +996,36 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null XmlResolver, style sheet does not have include/import, should not error")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void LoadGeneric3()
- {
- if (LoadXSL_Resolver("ShowParam.xsl", null) == 1)
- {
- if ((Transform("fruits.xml") == 1) && (CheckResult(466.5112789241) == 1))
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric3(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
+ if (LoadXSL_Resolver("showParam.xsl", null, inputType, readerType) == 1)
+ {
+ if (Transform("fruits.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -882,13 +1037,15 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null XmlResolver and style sheet has import/include, should fail")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric4()
+ public void LoadGeneric4(InputType inputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver("XmlResolver_Main.xsl", null);
+ LoadXSL_Resolver("XmlResolver_Main.xsl", null, inputType, readerType);
}
catch (System.Xml.Xsl.XsltCompileException e)
{
@@ -900,9 +1057,11 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null custom resolver and style sheet has import/include, should fail")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory(Skip = "By design bug #84957: Skip this test for Load(url, resolver)")]
- public void LoadGeneric5()
+ public void LoadGeneric5(InputType inputType, ReaderType readerType)
{
// By design bug #84957: Skip this test for Load(url, resolver)
//if (MyInputType() == InputType.URI)
@@ -914,7 +1073,7 @@ namespace System.Xml.Tests
CustomNullResolver myResolver = new CustomNullResolver(null);
try
{
- LoadXSL_Resolver("XmlResolver_Main.xsl", myResolver);
+ LoadXSL_Resolver("XmlResolver_Main.xsl", myResolver, inputType, readerType);
}
catch (System.Xml.Xsl.XsltCompileException e)
{
@@ -926,9 +1085,20 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null custom resolver and style sheet has no import/include, should not error")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory(Skip = "By design bug #84957: Skip this test for Load(url, resolver)")]
- public void LoadGeneric6()
+ public void LoadGeneric6(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
// By design bug #84957: Skip this test for Load(url, resolver)
@@ -939,9 +1109,9 @@ namespace System.Xml.Tests
//}
CustomNullResolver myResolver = new CustomNullResolver(null);
- if (LoadXSL_Resolver("ShowParam.xsl", myResolver) == 1)
+ if (LoadXSL_Resolver("showParam.xsl", myResolver, inputType, readerType) == 1)
{
- if ((Transform("fruits.xml") == 1) && (CheckResult(466.5112789241) == 1))
+ if ((Transform("fruits.xml", transformType, docType) == 1) && (CheckResult(466.5112789241, transformType) == 1))
return;
else
Assert.True(false);
@@ -954,9 +1124,20 @@ namespace System.Xml.Tests
}
//[Variation("Style sheet has import/include, call Load first with custom null resolver and then default resolver, should not fail")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory(Skip = "By design bug #84957: Skip this test for Load(url, resolver)")]
- public void LoadGeneric7()
+ public void LoadGeneric7(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
// By design bug #84957: Skip this test for Load(url, resolver)
@@ -970,14 +1151,14 @@ namespace System.Xml.Tests
try
{
- LoadXSL_Resolver("XmlResolver_Main.xsl", myResolver);
+ LoadXSL_Resolver("XmlResolver_Main.xsl", myResolver, inputType, readerType);
}
catch (System.Xml.Xsl.XsltCompileException e)
{
CheckExpectedError(e.InnerException, "System.Data.Sqlxml", "Xslt_CantResolve", new string[] { new Uri(FullFilePath("XmlResolver_Include.xsl", false)).ToString() });
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", inputType, readerType) == 1)
{
- if ((Transform("fruits.xml") == 1) && (CheckResult(428.8541842246) == 1))
+ if ((Transform("fruits.xml", transformType, docType) == 1) && (CheckResult(428.8541842246, transformType) == 1))
return;
else
Assert.True(false);
@@ -992,9 +1173,20 @@ namespace System.Xml.Tests
}
//[Variation("Style sheet has import/include, call Load first with default resolver and then with custom null resolver, should fail")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory(Skip = "By design bug #84957: Skip this test for Load(url, resolver)")]
- public void LoadGeneric8()
+ public void LoadGeneric8(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
// By design bug #84957: Skip this test for Load(url, resolver)
@@ -1006,11 +1198,11 @@ namespace System.Xml.Tests
CustomNullResolver myResolver = new CustomNullResolver(null);
- if ((LoadXSL("XmlResolver_Main.xsl") == 1))
+ if ((LoadXSL("XmlResolver_Main.xsl", inputType, readerType) == 1))
{
try
{
- LoadXSL_Resolver("XmlResolver_Main.xsl", myResolver);
+ LoadXSL_Resolver("XmlResolver_Main.xsl", myResolver, inputType, readerType);
}
catch (System.Xml.Xsl.XsltCompileException e)
{
@@ -1025,15 +1217,32 @@ namespace System.Xml.Tests
}
//[Variation("Load with resolver with credentials, then load XSL that does not need cred.")]
- [InlineData()]
- [Theory(Skip = "Resolving of External URIs is no longer allowed")]
- public void LoadGeneric9()
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric9(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
- if ((LoadXSL_Resolver("XmlResolver_Main.xsl", GetDefaultCredResolver()) == 1))
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
+
+ if ((LoadXSL_Resolver("XmlResolver_Main.xsl", GetDefaultCredResolver(), inputType, readerType) == 1))
{
- if ((LoadXSL("XmlResolver_Main.xsl") == 1) && (Transform("fruits.xml") == 1)
- && (CheckResult(428.8541842246) == 1))
+ if ((LoadXSL("XmlResolver_Main.xsl", inputType, readerType) == 1) && (Transform("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
}
else
{
@@ -1044,33 +1253,55 @@ namespace System.Xml.Tests
}
//[Variation("Call Load() many times with null resolver then perform a transform")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void LoadGeneric10()
- {
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric10(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
for (int i = 0; i < 100; i++)
{
- if (LoadXSL_Resolver("showParam.xsl", null) != 1)
+ if (LoadXSL_Resolver("showParam.xsl", null, inputType, readerType) != 1)
{
_output.WriteLine("Failed to load stylesheet showParam.xsl on the {0} attempt", i);
Assert.True(false);
}
}
- if ((LoadXSL_Resolver("showParam.xsl", null) == 1) && (Transform("fruits.xml") == 1)
- && (CheckResult(466.5112789241) == 1))
+ if ((LoadXSL_Resolver("showParam.xsl", null, inputType, readerType) == 1) && (Transform("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
//[Variation("Call Load with null Resolver, file does not exist")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadGeneric11()
+ public void LoadGeneric11(InputType inputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver("IDontExist.xsl", null);
+ LoadXSL_Resolver("IDontExist.xsl", null, inputType, readerType);
}
catch (System.IO.FileNotFoundException)
{
@@ -1081,22 +1312,33 @@ namespace System.Xml.Tests
}
//[Variation("Load non existing stylesheet with null resolver and try to transform")]
- [InlineData()]
- [Theory]
- public void LoadGeneric12()
- {
- if (LoadXSL_Resolver("showParam.xsl", null) == 1)
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void LoadGeneric12(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ if (LoadXSL_Resolver("showParam.xsl", null, inputType, readerType) == 1)
{
try
{
- LoadXSL_Resolver("IDontExist.xsl", null);
+ LoadXSL_Resolver("IDontExist.xsl", null, inputType, readerType);
}
catch (System.IO.FileNotFoundException)
{
//no stylesheet loaded, should throw error
try
{
- Transform("fruits.xml");
+ Transform("fruits.xml", transformType, docType);
}
catch (System.InvalidOperationException e2)
{
@@ -1132,27 +1374,35 @@ namespace System.Xml.Tests
}
//[Variation("Basic check for usage of credentials on resolver, load XSL that needs cred. with correct resolver")]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void LoadUrlResolver1()
+ public void LoadUrlResolver1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><out>Red50Orange25</out>";
+
// XsltResolverTestMain.xsl is placed in IIS virtual directory
// which requires integrated Windows NT authentication
- if ((LoadXSL_Resolver(("XmlResolver/XsltResolverTestMain.xsl"), GetDefaultCredResolver()) == 1) &&
- (Transform("fruits.xml") == 1) && (CheckResult(382.4519733094) == 1))
+ if ((LoadXSL_Resolver(("XmlResolver/XsltResolverTestMain.xsl"), GetDefaultCredResolver(), inputType, readerType) == 1) &&
+ (Transform("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
//[Variation("Load XSL that needs cred. with null resolver, should fail")]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrlResolver2()
+ public void LoadUrlResolver2(InputType inputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver(("XmlResolver/XsltResolverTestMain.xsl"), null);
+ LoadXSL_Resolver(("XmlResolver/XsltResolverTestMain.xsl"), null, inputType, readerType);
}
catch (System.Xml.Xsl.XsltException)
{
@@ -1164,13 +1414,13 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with null source value")]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrlResolver3()
+ public void LoadUrlResolver3(InputType inputType, ReaderType readerType)
{
try
{
- LoadXSL_Resolver(null, new XmlUrlResolver());
+ LoadXSL_Resolver(null, new XmlUrlResolver(), inputType, readerType);
}
catch (System.ArgumentException)
{
@@ -1182,88 +1432,6 @@ namespace System.Xml.Tests
}
}
- /****************************************************************************************/
- /* XslTransform.Load(Reader/Navigator,XmlResolver,Evidence) - Integrity */
- /****************************************************************************************/
-
- //[TestCase(Name = "XsltTransform.Load(,XmlResolver,Evidence) : Reader, Reader", Desc = "READER,READER")]
- //[TestCase(Name = "XsltTransform.Load(,XmlResolver,Evidence) : Reader, Stream", Desc = "READER,STREAM")]
- //[TestCase(Name = "XsltTransform.Load(,XmlResolver,Evidence) : Reader, Writer", Desc = "READER,WRITER")]
- //[TestCase(Name = "XsltTransform.Load(,XmlResolver,Evidence) : Reader, TextWriter", Desc = "READER,TEXTWRITER")]
- //[TestCase(Name = "XsltTransform.Load(,XmlResolver,Evidence) : Navigator, Reader", Desc = "NAVIGATOR,READER")]
- //[TestCase(Name = "XsltTransform.Load(,XmlResolver,Evidence) : Navigator, Stream", Desc = "NAVIGATOR,STREAM")]
- //[TestCase(Name = "XsltTransform.Load(,XmlResolver,Evidence) : Navigator, Writer", Desc = "NAVIGATOR,WRITER")]
- //[TestCase(Name = "XsltTransform.Load(,XmlResolver,Evidence) : Navigator, TextWriter", Desc = "NAVIGATOR,TEXTWRITER")]
- public class CLoadReaderResolverEvidenceTest : XsltApiTestCaseBase
- {
- private ITestOutputHelper _output;
- public CLoadReaderResolverEvidenceTest(ITestOutputHelper output) : base(output)
- {
- _output = output;
- }
-
- //[Variation("Call Load with null source value, null evidence")]
- [InlineData()]
- [Theory(Skip = "URI does not apply in this case, as Load(Url, Resolver) computes evidence from the Url")]
- public void LoadGeneric1()
- {
- /*try
- {
- LoadXSL_Resolver_Evidence(null, new XmlUrlResolver(), null);
- }
- catch (System.ArgumentException)
- {
- // System.Xml.XmlUrlResolver.ResolveUri(Uri baseUri, String relativeUri) throws ArgumentException
- return;
- }
- _output.WriteLine("Did not throw an exception for null argument!");
- Assert.True(false);*/
- }
-
- //[Variation("Call Load with style sheet that has script, pass null evidence, should throw security exception")]
- [InlineData()]
- [Theory(Skip = "")]
- public void LoadGeneric2()
- {
- /*
- try
- {
- LoadXSL_Resolver_Evidence("scripting_unsafe_object.xsl", new XmlUrlResolver(), null);
- }
- catch(System.Security.Policy.PolicyException e)
- {
- _output.WriteLine(e.ToString());
- return;
- }
- _output.WriteLine("Did not throw a security exception for null evidence!");
- Assert.True(false);
- */
- //return TEST_SKIPPED;
- }
-
- //[Variation("Call Load with style sheet that has script, pass correct evidence")]
- [InlineData()]
- [Theory(Skip = "Not InProc")]
- public void LoadGeneric3()
- {
- //if (_isInProc)
- // return TEST_SKIPPED;
-
- /*Evidence evidence = new Evidence();
- evidence.AddHost(new Zone(SecurityZone.MyComputer));
- try
- {
- LoadXSL_Resolver_Evidence("scripting_unsafe_object.xsl", new XmlUrlResolver(), evidence);
- }
- catch (System.Security.Policy.PolicyException)
- {
- _output.WriteLine("Should not throw a security exception for correct evidence!");
- Assert.True(false);
- }
- return;*/
- }
- }
-
/***********************************************************/
/* XslTransform.Load(Url) */
/***********************************************************/
@@ -1278,13 +1446,13 @@ namespace System.Xml.Tests
}
//[Variation("Call Load with an invalid uri")]
- [InlineData()]
+ [InlineData(ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl1()
+ public void LoadUrl1(ReaderType readerType)
{
try
{
- LoadXSL("IDontExist.xsl", InputType.URI);
+ LoadXSL("IDontExist.xsl", InputType.URI, readerType);
}
catch (System.IO.FileNotFoundException)
{
@@ -1295,13 +1463,13 @@ namespace System.Xml.Tests
}
//[Variation("Load file with empty string")]
- [InlineData()]
+ [InlineData(ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl2()
+ public void LoadUrl2(ReaderType readerType)
{
try
{
- LoadXSL(szEmpty, InputType.URI);
+ LoadXSL(szEmpty, InputType.URI, readerType);
}
catch (System.ArgumentException)
{
@@ -1313,13 +1481,13 @@ namespace System.Xml.Tests
}
//[Variation("Load with \".\"")]
- [InlineData()]
+ [InlineData(ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl3()
+ public void LoadUrl3(ReaderType readerType)
{
try
{
- LoadXSL(".", InputType.URI);
+ LoadXSL(".", InputType.URI, readerType);
}
catch (System.UnauthorizedAccessException)
{
@@ -1330,13 +1498,13 @@ namespace System.Xml.Tests
}
//[Variation("Load with \"..\"")]
- [InlineData()]
+ [InlineData(ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl()
+ public void LoadUrl(ReaderType readerType)
{
try
{
- LoadXSL("..", InputType.URI);
+ LoadXSL("..", InputType.URI, readerType);
}
catch (System.UnauthorizedAccessException)
{
@@ -1348,13 +1516,13 @@ namespace System.Xml.Tests
//[Variation("Load with \"\\\\\"")]
[PlatformSpecific(TestPlatforms.Windows)] //Not a valid path on Unix
- [InlineData()]
+ [InlineData(ReaderType.XmlValidatingReader)]
[Theory]
- public void LoadUrl5()
+ public void LoadUrl5(ReaderType readerType)
{
try
{
- LoadXSL("\\\\", InputType.URI);
+ LoadXSL("\\\\", InputType.URI, readerType);
}
catch (System.ArgumentException)
{
@@ -1364,44 +1532,6 @@ namespace System.Xml.Tests
_output.WriteLine("Exception not generated for non-existent file parameter name");
Assert.True(false);
}
-
- /*
-
- //[Variation("Call Load with style sheet that has script, pass Url which does not have correct evidence, should fail")]
- [InlineData()]
- [Theory]
- public void LoadUrl6()
- {
- try
- {
- LoadXSL_Resolver(FullHttpPath("XmlResolver/scripting_unsafe_object.xsl"), GetDefaultCredResolver());
- }
- catch(System.Security.Policy.PolicyException)
- {
- return;
- }
- _output.WriteLine("Should throw a security exception for incorrect evidence!");
- Assert.True(false);
- }
-
- //[Variation("Call Load with style sheet that has script, pass Url which has correct evidence, should pass")]
- [InlineData()]
- [Theory]
- public void LoadUrl7()
- {
- try
- {
- LoadXSL("scripting_unsafe_object.xsl");
- }
- catch(System.Security.Policy.PolicyException)
- {
- _output.WriteLine("Should not throw a security exception for correct evidence!");
- Assert.True(false);
- }
- return;
- }
-
- */
}
/***********************************************************/
@@ -1418,11 +1548,18 @@ namespace System.Xml.Tests
}
//[Variation("Basic Verification Test")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void LoadNavigator1()
+ public void LoadNavigator1(TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
#pragma warning disable 0618
xslt = new XslTransform();
#pragma warning restore 0618
@@ -1438,17 +1575,27 @@ namespace System.Xml.Tests
xrLoad.Dispose();
xslt.Load(xdTemp);
- if ((Transform("fruits.xml") == 1) && (CheckResult(466.5112789241) == 1))
+ if (Transform("fruits.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
//[Variation("Create Navigator and navigate away from root")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void LoadNavigator2()
+ public void LoadNavigator2(TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
#pragma warning disable 0618
xslt = new XslTransform();
XmlValidatingReader xrLoad = new XmlValidatingReader(new XmlTextReader(FullFilePath("showParam.xsl")));
@@ -1460,16 +1607,21 @@ namespace System.Xml.Tests
xP.MoveToNext();
xslt.Load(xP);
- if ((Transform("fruits.xml") == 1) && (CheckResult(466.5112789241) == 1))
+ if (Transform("fruits.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
//[Variation("Basic check for usage of credentials on resolver, load XSL that needs cred. with correct resolver")]
- [InlineData()]
+ [InlineData(TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void LoadNavigator3()
+ public void LoadNavigator3(TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><out>Red50Orange25</out>";
+
#pragma warning disable 0618
xslt = new XslTransform();
XmlValidatingReader xrLoad = new XmlValidatingReader(new XmlTextReader(FullFilePath("XmlResolver/XsltResolverTestMain.xsl")));
@@ -1480,16 +1632,19 @@ namespace System.Xml.Tests
XPathNavigator xP = ((IXPathNavigable)xdTemp).CreateNavigator();
xslt.Load(xP, GetDefaultCredResolver());
- if ((Transform("fruits.xml") == 1) && (CheckResult(382.4519733094) == 1))
+ if (Transform("fruits.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
//[Variation("Regression case for bug 80768")]
- [InlineData()]
+ [InlineData(TransformType.Stream)]
[Theory(Skip = "Not InProc")]
- public void LoadNavigator4()
+ public void LoadNavigator4(TransformType transformType)
{
//if (_isInProc)
// return TEST_SKIPPED;
@@ -1508,7 +1663,7 @@ namespace System.Xml.Tests
xslt.Transform(xn, null, fs);
fs.Dispose();
- if (CheckResult(383.0855503831) == 1)
+ if (CheckResult(383.0855503831, transformType) == 1)
return;
else
Assert.True(false);
@@ -1529,11 +1684,18 @@ namespace System.Xml.Tests
}
//[Variation("Basic Verification Test")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void LoadXmlReader1()
+ public void LoadXmlReader1(TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
Boolean fTEST_FAIL = false;
#pragma warning disable 0618
xslt = new XslTransform();
@@ -1557,8 +1719,11 @@ namespace System.Xml.Tests
}
if (fTEST_FAIL)
Assert.True(false);
- if ((Transform("fruits.xml") == 1) && (CheckResult(466.5112789241) == 1))
+ if (Transform("fruits.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
@@ -1589,7 +1754,7 @@ namespace System.Xml.Tests
Assert.True(false);
}
- //[Variation("Verify Reader isn't closed after Load")]
+ //[Variation("Verify Reader isn""t closed after Load")]
[InlineData()]
[Theory]
public void LoadXmlReader3()
@@ -1717,10 +1882,12 @@ namespace System.Xml.Tests
}
//[Variation("Basic check for usage of credentials on resolver, load XSL that needs cred. with correct resolver")]
- [InlineData()]
+ [InlineData(TransformType.Stream, DocType.XPathDocument)]
[Theory]
- public void LoadXmlReader7()
+ public void LoadXmlReader7(TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><out>Red50Orange25</out>";
+
#pragma warning disable 0618
xslt = new XslTransform();
XmlValidatingReader xrLoad = new XmlValidatingReader(new XmlTextReader(FullFilePath("XmlResolver/XsltResolverTestMain.xsl")));
@@ -1729,8 +1896,11 @@ namespace System.Xml.Tests
xslt.Load(xrLoad, GetDefaultCredResolver());
xrLoad.Dispose();
- if ((Transform("fruits.xml") == 1) && (CheckResult(382.4519733094) == 1))
+ if (Transform("fruits.xml", transformType, docType) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
Assert.True(false);
}
@@ -1761,48 +1931,105 @@ namespace System.Xml.Tests
}
//[Variation("Basic Verification Test")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void TransformGeneric1()
- {
- if ((LoadXSL("showParam.xsl") == 1) && (Transform("fruits.xml") == 1) &&
- (CheckResult(466.5112789241) == 1))
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Load and Transform multiple times")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void TransformGeneric2()
- {
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric2(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
for (int i = 0; i < 5; i++)
{
- if ((LoadXSL("showParam.xsl") != 1) || (Transform("fruits.xml") != 1) ||
- (CheckResult(466.5112789241) != 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) != 1) || (Transform("fruits.xml", transformType, docType) != 1))
Assert.True(false);
+ VerifyResult(expected);
}
return;
}
//[Variation("Load once, Transform many times")]
- [ActiveIssue(9877)]
- [InlineData()]
- [Theory]
- public void TransformGeneric3()
- {
- if (LoadXSL("showParam.xsl") == 1)
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric3(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
for (int i = 0; i < 100; i++)
{
- if ((Transform("fruits.xml") != 1) || (CheckResult(466.5112789241) != 1))
+ if (Transform("fruits.xml", transformType, docType) != 1)
{
_output.WriteLine("Test failed to transform after {0} iterations", i);
Assert.True(false);
}
+ VerifyResult(expected);
}
return;
}
@@ -1810,16 +2037,27 @@ namespace System.Xml.Tests
}
//[Variation("Call Transform without loading")]
- [InlineData()]
- [Theory]
- public void TransformGeneric4()
+ [InlineData(TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric4(TransformType transformType, DocType docType)
{
#pragma warning disable 0618
xslt = new XslTransform();
#pragma warning restore 0618
try
{
- Transform("fruits.xml");
+ Transform("fruits.xml", transformType, docType);
}
catch (System.InvalidOperationException e)
{
@@ -1831,13 +2069,24 @@ namespace System.Xml.Tests
}
//[Variation("Closing XSL and XML files used in transform, Read access")]
- [InlineData()]
- [Theory]
- public void TransformGeneric5()
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric5(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
FileStream s2;
- if ((LoadXSL("showParam.xsl") == 1) && (Transform("fruits.xml") == 1))
+ if ((LoadXSL("showParam.xsl", inputType, readerType) == 1) && (Transform("fruits.xml", transformType, docType) == 1))
{
s2 = new FileStream(FullFilePath("showParam.xsl"), FileMode.Open, FileAccess.Read);
s2.Dispose();
@@ -1851,38 +2100,26 @@ namespace System.Xml.Tests
Assert.True(false);
}
- /*
- //[Variation("Closing XSL and XML files used in transform, ReadWrite access")]
- [InlineData()]
- [Theory]
- public void TransformGeneric6()
- {
- FileStream s2;
-
- if((LoadXSL("showParam.xsl") == TEST_PASS) && (Transform("fruits.xml") == TEST_PASS))
- {
- s2 = new FileStream(FullFilePath("showParam.xsl"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
-
- s2 = new FileStream(FullFilePath("fruits.xml"), FileMode.Open, FileAccess.ReadWrite);
- s2.Dispose();
-
- return;
- }
- _output.WriteLine("Encountered errors performing transform and could not verify if files were closed");
- Assert.True(false);
- }
- */
-
//[Variation("Bug358103 - ArgumentOutOfRangeException in forwards-compatible mode for <foo bar='{+1}'/>")]
- [InlineData()]
- [Theory]
- public void TransformGeneric7()
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void TransformGeneric7(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
try
{
- LoadXSL("ForwardComp2.xsl");
- Transform("data.xml", true);
+ LoadXSL("ForwardComp2.xsl", inputType, readerType);
+ Transform("data.xml", true, transformType, docType);
}
catch (XsltException)
{
@@ -1920,16 +2157,34 @@ namespace System.Xml.Tests
}
//[Variation("Pass null XmlResolver, load style sheet with import/include, should not affect transform")]
- [InlineData()]
- [Theory(Skip = "Resolving of External URIs is no longer allowed")]
- public void XmlResolver1()
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void XmlResolver1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
+
try
{
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", inputType, readerType) == 1)
{
- if ((TransformResolver("fruits.xml", null) == 1) && (CheckResult(428.8541842246) == 1))
+ if (TransformResolver("fruits.xml", transformType, docType, null) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
@@ -1943,17 +2198,33 @@ namespace System.Xml.Tests
}
//[Variation("Pass null XmlResolver, load style sheet with document function, should not resolve during transform")]
- [InlineData()]
- [Theory]
- public void XmlResolver2()
- {
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [Theory]
+ public void XmlResolver2(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
+ {
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result></result>";
+
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", inputType, readerType) == 1)
{
- if ((TransformResolver("fruits.xml", null) == 1) && (CheckResult(375.6079891948) == 1))
+ if (TransformResolver("fruits.xml", transformType, docType, null) == 1)
+ {
+ VerifyResult(expected);
return;
+ }
}
else
{
@@ -1964,9 +2235,20 @@ namespace System.Xml.Tests
}
//[Variation("Default XmlResolver, load style sheet with document function, should resolve during transform")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory(Skip = "SQLBU Defect Tracking Bug 430834: Skipping when input type is URI, see bug for more details.")]
- public void XmlResolver3()
+ public void XmlResolver3(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
@@ -1975,9 +2257,9 @@ namespace System.Xml.Tests
//if (MyInputType() == InputType.URI)
// return TEST_SKIPPED;
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", inputType, readerType) == 1)
{
- if ((Transform("fruits.xml") == 1) && (CheckResult(377.8217373898) == 1))
+ if ((Transform("fruits.xml", transformType, docType) == 1) && (CheckResult(377.8217373898, transformType) == 1))
return;
}
else
@@ -1989,9 +2271,20 @@ namespace System.Xml.Tests
}
//[Variation("document() has absolute URI")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Reader, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Writer, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory(Skip = "When style sheet URI = Intranet zone, XmlSecureResolver does not resolve document function")]
- public void XmlResolver5()
+ public void XmlResolver5(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
// Skip this test for Load(URI)
// Reason: When style sheet URI = Intranet zone, XmlSecureResolver does not resolve document function
@@ -2003,12 +2296,13 @@ namespace System.Xml.Tests
try
{
- if (!Directory.Exists("c:\\temp"))
+ string tempDir = Path.GetTempPath();
+ if (!Directory.Exists(tempDir))
{
- Directory.CreateDirectory("c:\\temp");
+ Directory.CreateDirectory(tempDir);
}
string xmlFile = FullFilePath("xmlResolver_document_function.xml");
- File.Copy(xmlFile, @"c:\temp\xmlResolver_document_function.xml", true);
+ File.Copy(xmlFile, Path.Combine(tempDir, "xmlResolver_document_function.xml"), true);
}
catch (Exception e)
{
@@ -2017,9 +2311,9 @@ namespace System.Xml.Tests
return; //return TEST_SKIPPED;
}
- if (LoadXSL("xmlResolver_document_function_absolute_uri.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function_absolute_uri.xsl", inputType, readerType) == 1)
{
- if ((TransformResolver("fruits.xml", new XmlUrlResolver()) == 1) && (CheckResult(377.8217373898) == 1))
+ if ((TransformResolver("fruits.xml", transformType, docType, new XmlUrlResolver()) == 1) && (CheckResult(377.8217373898, transformType) == 1))
return;
else
{
@@ -2051,32 +2345,43 @@ namespace System.Xml.Tests
}
//[Variation("Basic Verification Test")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr1()
+ public void TransformStrStr1(InputType inputType, ReaderType readerType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
CallTransform(xslt, szFullFilename, _strOutFile);
- if (CheckResult(466.5112789241) == 1)
- return;
+ VerifyResult(expected);
+ return;
}
Assert.True(false);
}
//[Variation("Input is null")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr2()
+ public void TransformStrStr2(InputType inputType, ReaderType readerType)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
- xslt.Transform(null, _strOutFile);
+ CallTransform(xslt, null, _strOutFile);
}
catch (System.ArgumentException)
{ return; }
@@ -2086,13 +2391,15 @@ namespace System.Xml.Tests
}
//[Variation("Output file is null")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr3()
+ public void TransformStrStr3(InputType inputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
@@ -2108,15 +2415,17 @@ namespace System.Xml.Tests
}
//[Variation("Input is nonexisting file")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr4()
+ public void TransformStrStr4(InputType inputType, ReaderType readerType)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
- xslt.Transform("IDontExist.xsl", _strOutFile);
+ CallTransform(xslt, "IDontExist.xsl", _strOutFile);
}
catch (System.IO.FileNotFoundException)
{
@@ -2129,13 +2438,15 @@ namespace System.Xml.Tests
//[Variation("Output file is invalid")]
[PlatformSpecific(TestPlatforms.Windows)] //Output file name is valid on Unix
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr5()
+ public void TransformStrStr5(InputType inputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
@@ -2151,15 +2462,17 @@ namespace System.Xml.Tests
}
//[Variation("Input is empty string")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr6()
+ public void TransformStrStr6(InputType inputType, ReaderType readerType)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
- xslt.Transform(szEmpty, _strOutFile);
+ CallTransform(xslt, szEmpty, _strOutFile);
}
catch (System.ArgumentException)
{
@@ -2171,13 +2484,15 @@ namespace System.Xml.Tests
}
//[Variation("Output file is empty string")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr7()
+ public void TransformStrStr7(InputType inputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
@@ -2193,22 +2508,35 @@ namespace System.Xml.Tests
}
//[Variation("Call Transform many times")]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr8()
+ public void TransformStrStr8(InputType inputType, ReaderType readerType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result>
+ 1.No Value Specified
+ 2.No Value Specified
+ 3.No Value Specified
+ 4.No Value Specified
+ 5.No Value Specified
+ 6.No Value Specified</result>";
+
String szFullFilename = FullFilePath("fruits.xml");
for (int i = 0; i < 50; i++)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
CallTransform(xslt, szFullFilename, _strOutFile);
- if (CheckResult(466.5112789241) != 1)
+ try
+ {
+ VerifyResult(expected);
+ }
+ catch(Exception)
{
_output.WriteLine("Failed to process Load after calling {0} times", i);
- Assert.True(false);
+ throw;
}
}
}
@@ -2225,7 +2553,7 @@ namespace System.Xml.Tests
#pragma warning restore 0618
try
{
- xslt.Transform(FullFilePath("fruits.xml"), _strOutFile);
+ CallTransform(xslt, FullFilePath("fruits.xml"), _strOutFile);
}
catch (System.InvalidOperationException e)
{
@@ -2237,15 +2565,17 @@ namespace System.Xml.Tests
}
//[Variation("Output to unreachable destination")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr10()
+ public void TransformStrStr10(InputType inputType, ReaderType readerType)
{
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
- xslt.Transform("fruits.xml", "http://www.IdontExist.com/index.xml");
+ xslt.Transform(FullFilePath("fruits.xml"), "http://www.IdontExist.com/index.xml");
}
catch (System.Exception e)
{
@@ -2258,16 +2588,18 @@ namespace System.Xml.Tests
}
//[Variation("Input filename is \'.\', \'..\', and \'\\\\\'")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr11()
+ public void TransformStrStr11(InputType inputType, ReaderType readerType)
{
int iCount = 0;
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
- xslt.Transform("..", _strOutFile);
+ CallTransform(xslt, "..", _strOutFile);
}
catch (System.Exception)
{
@@ -2276,7 +2608,7 @@ namespace System.Xml.Tests
try
{
- xslt.Transform(".", _strOutFile);
+ CallTransform(xslt, ".", _strOutFile);
}
catch (System.Exception)
{
@@ -2285,7 +2617,7 @@ namespace System.Xml.Tests
try
{
- xslt.Transform("\\\\", _strOutFile);
+ CallTransform(xslt, "\\\\", _strOutFile);
}
catch (System.Exception)
{
@@ -2301,13 +2633,15 @@ namespace System.Xml.Tests
}
//[Variation("Output filename is \'.\' and \'..\')]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr12()
+ public void TransformStrStr12(InputType inputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
int iCount = 0;
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
try
{
@@ -2337,13 +2671,15 @@ namespace System.Xml.Tests
//[Variation("Output filename is \'\\\\\'")]
[PlatformSpecific(TestPlatforms.Windows)]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr12_win()
+ public void TransformStrStr12_win(InputType inputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
Assert.Throws<System.ArgumentException>(() => xslt.Transform(szFullFilename, "\\\\"));
return;
@@ -2354,28 +2690,27 @@ namespace System.Xml.Tests
}
//[Variation("Closing files after transform")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStr13()
+ public void TransformStrStr13(InputType inputType, ReaderType readerType)
{
String szFullFilename = FullFilePath("fruits.xml");
Stream strmTemp;
- if (LoadXSL("showParam.xsl") == 1)
+ if (LoadXSL("showParam.xsl", inputType, readerType) == 1)
{
CallTransform(xslt, szFullFilename, _strOutFile);
- StreamReader fs = null;
// check if I can open and close the xml file
- fs = new StreamReader(new FileStream(szFullFilename, FileMode.Open, FileAccess.Read));
- fs.Dispose();
+ File.ReadAllText(szFullFilename);
strmTemp = new FileStream(szFullFilename, FileMode.Open, FileAccess.Read);
strmTemp.Dispose();
// check if I can open and close the output file
- fs = new StreamReader(new FileStream(_strOutFile, FileMode.Open, FileAccess.Read));
- fs.Dispose();
+ File.ReadAllText(_strOutFile);
strmTemp = new FileStream(_strOutFile, FileMode.Open, FileAccess.Read);
strmTemp.Dispose();
@@ -2384,29 +2719,6 @@ namespace System.Xml.Tests
}
Assert.True(false);
}
-
- /*
- //[Variation("Transform(test.xml, test.xml)")]
- [InlineData()]
- [Theory]
- public void TransformStrStr14()
- {
- String szFullFilename = FullFilePath("Bug75295.xml");
-
- // Copy this file to current directory
- File.Delete("out.xml");
- File.Copy(szFullFilename, "out.xml");
-
- if(LoadXSL("Bug75295.xsl") == TEST_PASS)
- {
- xslt.Transform("out.xml", "out.xml");
-
- if (CheckResult(270.5223692973) == TEST_PASS)
- return;
- }
- Assert.True(false);
- }
- */
}
/***********************************************************/
@@ -2425,21 +2737,24 @@ namespace System.Xml.Tests
}
//[Variation("Pass null XmlResolver, load style sheet with import/include, should not affect transform")]
- [InlineData()]
- [Theory(Skip = "Resolving of External URIs is no longer allowed")]
- public void TransformStrStrResolver1()
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
+ [Theory]
+ public void TransformStrStrResolver1(InputType inputType, ReaderType readerType)
{
+ AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
+
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result><fruit>Apple</fruit><fruit>orange</fruit></result>";
String szFullFilename = FullFilePath("fruits.xml");
try
{
- if (LoadXSL("XmlResolver_Main.xsl") == 1)
+ if (LoadXSL("XmlResolver_Main.xsl", inputType, readerType) == 1)
{
- xslt.Transform(szFullFilename, "out.xml", null);
- if (CheckResult(428.8541842246) == 1)
- return;
- else
- Assert.True(false);
+ CallTransform(xslt, szFullFilename, "out.xml", null);
+ VerifyResult(expected);
+ return;
}
}
catch (Exception e)
@@ -2451,20 +2766,22 @@ namespace System.Xml.Tests
}
//[Variation("Pass null XmlResolver, load style sheet with document function, should not resolve during transform")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader)]
[Theory]
- public void TransformStrStrResolver2()
+ public void TransformStrStrResolver2(InputType inputType, ReaderType readerType)
{
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
-
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><result></result>";
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", inputType, readerType) == 1)
{
CallTransform(xslt, szFullFilename, "out.xml", null);
- if (CheckResult(375.6079891948) == 1)
- return;
+ VerifyResult(expected);
+ return;
}
else
{
@@ -2475,9 +2792,11 @@ namespace System.Xml.Tests
}
//[Variation("Pass XmlUrlResolver, load style sheet with document function, should resolve during transform")]
- [InlineData()]
+ [InlineData(InputType.Reader, ReaderType.XmlValidatingReader, TransformType.Stream)]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.Stream)]
[Theory(Skip = "SQLBU Defect Tracking Bug 430834: Skipping when input type is URI, see bug for more details.")]
- public void TransformStrStrResolver3()
+ public void TransformStrStrResolver3(InputType inputType, ReaderType readerType, TransformType transformType)
{
// "xmlResolver_document_function.xsl" contains
// <xsl:for-each select="document('xmlResolver_document_function.xml')//elem">
@@ -2488,10 +2807,10 @@ namespace System.Xml.Tests
String szFullFilename = FullFilePath("fruits.xml");
- if (LoadXSL("xmlResolver_document_function.xsl") == 1)
+ if (LoadXSL("xmlResolver_document_function.xsl", inputType, readerType) == 1)
{
- xslt.Transform(szFullFilename, "out.xml", new XmlUrlResolver());
- if (CheckResult(377.8217373898) == 1)
+ CallTransform(xslt, szFullFilename, "out.xml", new XmlUrlResolver());
+ if (CheckResult(377.8217373898, transformType) == 1)
return;
}
else
@@ -2515,39 +2834,56 @@ namespace System.Xml.Tests
}
//[Variation("Local parameter gets overwritten with global param value", Pri = 1)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void var1()
+ public void var1(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><out>
+param1 (correct answer is 'local-param1-arg'): local-param1-arg
+param2 (correct answer is 'local-param2-arg'): local-param2-arg
+</out>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("param1", string.Empty, "global-param1-arg");
- if ((LoadXSL("paramScope.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) && (CheckResult(473.4644857331) == 1))
+ if ((LoadXSL("paramScope.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Local parameter gets overwritten with global variable value", Pri = 1)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void var2()
+ public void var2(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?><out>
+param1 (correct answer is 'local-param1-arg'): local-param1-arg
+param2 (correct answer is 'local-param2-arg'): local-param2-arg
+</out>";
+
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddParam("param1", string.Empty, "global-param1-arg");
- if ((LoadXSL("varScope.xsl") == 1) && (Transform_ArgList("fruits.xml") == 1) && (CheckResult(473.4644857331) == 1))
+ if ((LoadXSL("varScope.xsl", inputType, readerType) == 1) && (Transform_ArgList("fruits.xml", transformType, docType) == 1))
+ {
+ VerifyResult(expected);
return;
+ }
else
Assert.True(false);
}
//[Variation("Subclassed XPathNodeIterator returned from an extension object or XsltFunction is not accepted by XPath", Pri = 1)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory(Skip = "SQLBU Defect Tracking Bug 430834: Skipping when input type is URI, see bug for more details.")]
- public void var3()
+ public void var3(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
// SQLBU Defect Tracking Bug 430834: Skipping when input type is URI, see bug for more details.
//if (MyInputType() == InputType.URI)
@@ -2556,20 +2892,30 @@ namespace System.Xml.Tests
m_xsltArg = new XsltArgumentList();
m_xsltArg.AddExtensionObject("http://foo.com", new MyXsltExtension());
- if ((LoadXSL("Bug111075.xsl") == 1) && (Transform_ArgList("Bug111075.xml") == 1) && (CheckResult(444.7202431861) == 1))
+ if ((LoadXSL("Bug111075.xsl", inputType, readerType) == 1) && (Transform_ArgList("Bug111075.xml", transformType, docType) == 1) && (CheckResult(444.7202431861, transformType) == 1))
return;
else
Assert.True(false);
}
//[Variation("Iterator using for-each over a variable is not reset correctly while using msxsl:node-set()", Pri = 1)]
- [ActiveIssue(9877)]
- [InlineData()]
+ [InlineData(InputType.URI, ReaderType.XmlValidatingReader, TransformType.Stream, DocType.XPathDocument)]
+ [InlineData(InputType.Navigator, ReaderType.XmlValidatingReader, TransformType.TextWriter, DocType.XPathDocument)]
[Theory]
- public void var4()
+ public void var4(InputType inputType, ReaderType readerType, TransformType transformType, DocType docType)
{
- if ((LoadXSL("Bug109644.xsl") == 1) && (Transform("foo.xml") == 1) && (CheckResult(417.2501860011) == 1))
+ string expected = @"<?xml version=""1.0"" encoding=""utf-8""?>
+ Node Count: {3}
+
+
+ Correct Output: (1)(2)(3)
+ Incorrect Output: [1][2][3]";
+
+ if ((LoadXSL("Bug109644.xsl", inputType, readerType) == 1) && (Transform("foo.xml", transformType, docType) == 1))
+ {
+ Assert.Equal(expected, File.ReadAllText("out.xml"));
return;
+ }
else
Assert.True(false);
}
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransformMultith.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransformMultith.cs
index af2869b75d..bc0b366b82 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransformMultith.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransformMultith.cs
@@ -4,9 +4,7 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using XmlCoreTest.Common;
@@ -37,7 +35,7 @@ namespace System.Xml.Tests
#pragma warning disable 0618
xsltSameInstance = new XslTransform();
#pragma warning restore 0618
- _strPath = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltApi\");
+ _strPath = Path.Combine("TestFiles", FilePathUtil.GetTestDataPath(), "XsltApi");
return;
}
@@ -113,13 +111,13 @@ namespace System.Xml.Tests
public override void Load(string _strXslFile, string _strXmlFile)
{
#pragma warning disable 0618
- XmlValidatingReader xrData = new XmlValidatingReader(new XmlTextReader(_strPath + _strXmlFile));
+ XmlValidatingReader xrData = new XmlValidatingReader(new XmlTextReader(Path.Combine(_strPath, _strXmlFile)));
#pragma warning restore 0618
_xd = new XPathDocument(xrData, XmlSpace.Preserve);
xrData.Dispose();
#pragma warning disable 0618
- XmlValidatingReader xrTemp = new XmlValidatingReader(new XmlTextReader(_strPath + _strXslFile));
+ XmlValidatingReader xrTemp = new XmlValidatingReader(new XmlTextReader(Path.Combine(_strPath, _strXslFile)));
#pragma warning restore 0618
xrTemp.ValidationType = ValidationType.None;
xrTemp.EntityHandling = EntityHandling.ExpandEntities;
@@ -153,13 +151,13 @@ namespace System.Xml.Tests
public override void Load(string _strXslFile, string _strXmlFile)
{
#pragma warning disable 0618
- XmlValidatingReader xrData = new XmlValidatingReader(new XmlTextReader(_strPath + _strXmlFile));
+ XmlValidatingReader xrData = new XmlValidatingReader(new XmlTextReader(Path.Combine(_strPath, _strXmlFile)));
#pragma warning restore 0618
_xd = new XPathDocument(xrData, XmlSpace.Preserve);
xrData.Dispose();
#pragma warning disable 0618
- XmlValidatingReader xrTemp = new XmlValidatingReader(new XmlTextReader(_strPath + _strXslFile));
+ XmlValidatingReader xrTemp = new XmlValidatingReader(new XmlTextReader(Path.Combine(_strPath, _strXslFile)));
xrTemp.ValidationType = ValidationType.None;
xrTemp.EntityHandling = EntityHandling.ExpandEntities;
xsltSameInstance.Load(xrTemp);
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltArgumentListMultith.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltArgumentListMultith.cs
index e606815d90..57e1f1e5bf 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltArgumentListMultith.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltArgumentListMultith.cs
@@ -249,9 +249,9 @@ namespace System.Xml.Tests
string _strXmlFile = ((object[])args)[2].ToString();
if (_strXslFile.Substring(0, 5) != "http:")
- _strXslFile = _strPath + _strXslFile;
+ _strXslFile = Path.Combine(_strPath, _strXslFile);
if (_strXmlFile.Substring(0, 5) != "http:")
- _strXmlFile = _strPath + _strXmlFile;
+ _strXmlFile = Path.Combine(_strPath, _strXmlFile);
#pragma warning disable 0618
XmlValidatingReader xrData = new XmlValidatingReader(new XmlTextReader(_strXmlFile));
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltChecksum.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltChecksum.cs
index 68a1f9fa08..a76e0f431c 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltChecksum.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/CXsltChecksum.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Xunit;
using Xunit.Abstractions;
using System;
using System.Globalization;
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/DataHelper.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/DataHelper.cs
index 90a973cc54..ab84a3b8f4 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/DataHelper.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/DataHelper.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Xunit;
using Xunit.Abstractions;
using System;
using System.Globalization;
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/ExceptionVerifier.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/ExceptionVerifier.cs
index f5730d0526..cfff436861 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/ExceptionVerifier.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/ExceptionVerifier.cs
@@ -3,16 +3,13 @@
// See the LICENSE file in the project root for more information.
using System.Linq;
-using Xunit;
using Xunit.Abstractions;
-using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Text.RegularExpressions;
-using System.Xml;
namespace System.Xml.Tests
{
@@ -113,16 +110,9 @@ namespace System.Xml.Tests
_asm = dom.GetType().GetTypeInfo().Assembly;
}
break;
- //case "SYSTEM.DATA":
- //{
- // var ds = new DataSet();
- // asm = ds.GetType().Assembly;
- //}
- // break;
default:
- throw new FileLoadException("Cannot load assembly from " + GetRuntimeInstallDir() + assemblyName + ".dll");
- //asm = Assembly.LoadFrom(GetRuntimeInstallDir() + assemblyName + ".dll");
- //break;
+ _asm = Assembly.LoadFrom(GetRuntimeInstallDir() + assemblyName + ".dll");
+ break;
}
if (_asm == null)
@@ -186,7 +176,6 @@ namespace System.Xml.Tests
}
resReader.Dispose();
}
- //break;
}
}
@@ -220,8 +209,7 @@ namespace System.Xml.Tests
"\n===== Original Exception Message =====\n" + _ex.Message +
"\n===== Resource Id =====\n" + fInfo.GetValue(_ex) +
"\n===== HelpLink =====\n" + _ex.HelpLink +
- "\n===== Source =====\n" + _ex.Source /*+
- "\n===== TargetSite =====\n" + ex.TargetSite + "\n"*/);
+ "\n===== Source =====\n" + _ex.Source);
_output.WriteLine(
"\n===== InnerException =====\n" + _ex.InnerException +
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/MyNavigator.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/MyNavigator.cs
index 997ad1fb0e..bc3d365c64 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/MyNavigator.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/MyNavigator.cs
@@ -172,7 +172,6 @@ public class MyNavigator : XPathNavigator
//[PermissionSetAttribute(SecurityAction.Deny, Name = "FullTrust")]
public override XPathExpression Compile(string xpath)
{
- //XPathDocument xn = new XPathDocument(_strFileName);
if (xpath.IndexOf("custom", 0, xpath.Length) >= 0)
xpath = "custom:dangerous()";
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/Program.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/Program.cs
deleted file mode 100644
index 8252e1c5a2..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/Program.cs
+++ /dev/null
@@ -1,17 +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 ModuleCore;
-
-namespace XslCompiledTransformTests
-{
- internal class Program
- {
- public static int Main()
- {
- var args = @"DocType:XmlDocument trace:false Host:None";
- return 100 + TestRunner.Execute(args);
- }
- }
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/XSLTransform.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/XSLTransform.cs
index 65bb446ecd..c26bf1bbf1 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/XSLTransform.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/XSLTransform.cs
@@ -4,11 +4,8 @@
using Xunit;
using Xunit.Abstractions;
-using System;
using System.IO;
-using System.Net;
using System.Text;
-using System.Xml;
using System.Xml.XmlDiff;
using System.Xml.XPath;
using System.Xml.Xsl;
@@ -66,11 +63,7 @@ namespace System.Xml.Tests
private string _strPath; // Path of the data files
private string _httpPath; // HTTP Path of the data files
- private InputType _nInput; // reader, url, or navigator
private bool _fTrace; // Should we write out the results of the transform?
- private TransformType _nTransform; // Type of XSL Transform to do
- private DocType _docType; // Data document type
- private ReaderType _readerType; // Reader type
// Other global variables
protected string _strOutFile = "out.xml"; // File to create when using write transforms
@@ -87,30 +80,12 @@ namespace System.Xml.Tests
private ITestOutputHelper _output;
public XsltApiTestCaseBase(ITestOutputHelper output)
{
+ // Make sure that we don't cache the value of the switch to enable testing
+ AppContext.SetSwitch("TestSwitch.LocalAppContext.DisableCaching", true);
_output = output;
this.Init(null);
}
- public InputType MyInputType()
- {
- return _nInput;
- }
-
- public TransformType MyTransformType()
- {
- return _nTransform;
- }
-
- public DocType MyDocType()
- {
- return _docType;
- }
-
- public ReaderType MyReaderType()
- {
- return _readerType;
- }
-
public TransformType GetTransformType(String s)
{
if (s.EndsWith(",READER"))
@@ -132,7 +107,6 @@ namespace System.Xml.Tests
public XmlUrlResolver GetDefaultCredResolver()
{
XmlUrlResolver myDefaultCredResolver = new XmlUrlResolver();
- //myDefaultCredResolver.Credentials = CredentialCache.DefaultCredentials;
return myDefaultCredResolver;
}
@@ -188,21 +162,10 @@ namespace System.Xml.Tests
}
}
- public String InitStringValue(String str)
- {
- return String.Empty;
- }
-
public void Init(object objParam)
{
- // Get input and transform type from attribute
- _nInput = GetInputType(String.Empty);
- _nTransform = GetTransformType(String.Empty);
-
// Get parameter info from runtime variables passed to LTM
- _fTrace = (InitStringValue("trace").ToUpper() == "TRUE");
- _docType = GetDocType(InitStringValue("doctype"));
- _readerType = GetReaderType(InitStringValue("readertype"));
+ _fTrace = false;
// FullFilePath and FullHttpPath attempt to normalize file paths, however
// as an extra step we can normalize them here, when they are first read
@@ -297,12 +260,7 @@ namespace System.Xml.Tests
// --------------------------------------------------------------------------------------------------------------
// LoadXSL
// -------------------------------------------------------------------------------------------------------------
- public int LoadXSL(String _strXslFile)
- {
- return LoadXSL(_strXslFile, _nInput);
- }
-
- public int LoadXSL(String _strXslFile, InputType inputType)
+ public int LoadXSL(string _strXslFile, InputType inputType, ReaderType readerType)
{
_strXslFile = FullFilePath(_strXslFile);
#pragma warning disable 0618
@@ -317,7 +275,7 @@ namespace System.Xml.Tests
break;
case InputType.Reader:
- switch (_readerType)
+ switch (readerType)
{
case ReaderType.XmlTextReader:
XmlTextReader trTemp = new XmlTextReader(_strXslFile);
@@ -399,14 +357,14 @@ namespace System.Xml.Tests
// --------------------------------------------------------------------------------------------------------------
// LoadXSL_Resolver
// -------------------------------------------------------------------------------------------------------------
- public int LoadXSL_Resolver(String _strXslFile, XmlResolver xr)
+ public int LoadXSL_Resolver(string _strXslFile, XmlResolver xr, InputType inputType, ReaderType readerType)
{
_strXslFile = FullFilePath(_strXslFile);
#pragma warning disable 0618
xslt = new XslTransform();
#pragma warning restore 0618
- switch (_nInput)
+ switch (inputType)
{
case InputType.URI:
_output.WriteLine("Loading style sheet as URI {0}", _strXslFile);
@@ -414,7 +372,7 @@ namespace System.Xml.Tests
break;
case InputType.Reader:
- switch (_readerType)
+ switch (readerType)
{
case ReaderType.XmlTextReader:
XmlTextReader trTemp = new XmlTextReader(_strXslFile);
@@ -492,125 +450,31 @@ namespace System.Xml.Tests
return 1;
}
- // --------------------------------------------------------------------------------------------------------------
- // LoadXSL_Resolver_Evidence
- // -------------------------------------------------------------------------------------------------------------
- /*public int LoadXSL_Resolver_Evidence(String _strXslFile, XmlResolver xr, Evidence e)
- {
- _strXslFile = FullFilePath(_strXslFile);
-#pragma warning disable 0618
- xslt = new XslTransform();
-#pragma warning restore 0618
-
- switch (_nInput)
- {
- case InputType.Reader:
- switch (_readerType)
- {
- case ReaderType.XmlTextReader:
- XmlTextReader trTemp = new XmlTextReader(_strXslFile);
- try
- {
- _output.WriteLine("Loading style sheet as XmlTextReader {0}", _strXslFile);
- xslt.Load(trTemp, xr, e);
- }
- catch (Exception ex)
- {
- throw (ex);
- }
- finally
- {
- if (trTemp != null)
- trTemp.Dispose();
- }
- break;
-
- case ReaderType.XmlNodeReader:
- XmlDocument docTemp = new XmlDocument();
- docTemp.Load(_strXslFile);
- XmlNodeReader nrTemp = new XmlNodeReader(docTemp);
- try
- {
- _output.WriteLine("Loading style sheet as XmlNodeReader {0}", _strXslFile);
- xslt.Load(nrTemp, xr, e);
- }
- catch (Exception ex)
- {
- throw (ex);
- }
- finally
- {
- if (nrTemp != null)
- nrTemp.Dispose();
- }
- break;
-
- case ReaderType.XmlValidatingReader:
- default:
-#pragma warning disable 0618
- XmlValidatingReader vrTemp = new XmlValidatingReader(new XmlTextReader(_strXslFile));
-#pragma warning restore 0618
- vrTemp.ValidationType = ValidationType.None;
- vrTemp.EntityHandling = EntityHandling.ExpandEntities;
- try
- {
- _output.WriteLine("Loading style sheet as XmlValidatingReader {0}", _strXslFile);
- xslt.Load(vrTemp, xr, e);
- }
- catch (Exception ex)
- {
- throw (ex);
- }
- finally
- {
- if (vrTemp != null)
- vrTemp.Dispose();
- }
- break;
- }
- break;
-
- case InputType.Navigator:
-#pragma warning disable 0618
- XmlValidatingReader xrLoad = new XmlValidatingReader(new XmlTextReader(_strXslFile));
-#pragma warning restore 0618
- XPathDocument xdTemp = new XPathDocument(xrLoad, XmlSpace.Preserve);
- xrLoad.Dispose();
- _output.WriteLine("Loading style sheet as Navigator {0}", _strXslFile);
- xslt.Load(xdTemp.CreateNavigator(), xr, e);
- break;
- }
- return 1;
- }*/
-
//VerifyResult
public void VerifyResult(string expectedValue)
{
- XmlDiff.XmlDiff xmldiff = new XmlDiff.XmlDiff();
- xmldiff.Option = XmlDiffOption.InfosetComparison | XmlDiffOption.IgnoreEmptyElement;
-
- StreamReader sr = new StreamReader(new FileStream("out.xml", FileMode.Open, FileAccess.Read));
- string actualValue = sr.ReadToEnd();
- sr.Dispose();
-
- //Output the expected and actual values
- _output.WriteLine("Expected : " + expectedValue);
- _output.WriteLine("Actual : " + actualValue);
-
- //Load into XmlTextReaders
- XmlTextReader tr1 = new XmlTextReader("out.xml");
- XmlTextReader tr2 = new XmlTextReader(new StringReader(expectedValue));
-
- bool bResult = xmldiff.Compare(tr1, tr2);
-
- //Close the readers
- tr1.Dispose();
- tr2.Dispose();
+ lock(s_outFileMemoryLock)
+ {
+ XmlDiff.XmlDiff xmldiff = new XmlDiff.XmlDiff();
+ xmldiff.Option = XmlDiffOption.InfosetComparison | XmlDiffOption.IgnoreEmptyElement | XmlDiffOption.NormalizeNewline;
+
+ string actualValue = File.ReadAllText(_strOutFile);
+
+ //Output the expected and actual values
+ _output.WriteLine("Expected : " + expectedValue);
+ _output.WriteLine("Actual : " + actualValue);
+
+ bool result;
+
+ //Load into XmlTextReaders
+ using (XmlTextReader tr1 = new XmlTextReader(_strOutFile))
+ using (XmlTextReader tr2 = new XmlTextReader(new StringReader(expectedValue)))
+ {
+ result = xmldiff.Compare(tr1, tr2);
+ }
- if (bResult)
- return;
- else
- Assert.True(false);
+ Assert.True(result);
+ }
}
// --------------------------------------------------------------------------------------------------------------
@@ -637,28 +501,35 @@ namespace System.Xml.Tests
}
#pragma warning restore 0618
- public int Transform(String szXmlFile)
+ public int Transform(string szXmlFile, TransformType transformType, DocType docType)
{
// Default value of errorCase is false
- return Transform(szXmlFile, false);
+ return Transform(szXmlFile, false, transformType, docType);
}
- public int Transform(String szXmlFile, bool errorCase)
+ public int Transform(string szXmlFile, bool errorCase, TransformType transformType, DocType docType)
{
lock (s_outFileMemoryLock)
{
szXmlFile = FullFilePath(szXmlFile);
_output.WriteLine("Loading XML {0}", szXmlFile);
- IXPathNavigable xd = LoadXML(szXmlFile, _docType);
+ IXPathNavigable xd = LoadXML(szXmlFile, docType);
_output.WriteLine("Executing transform");
xrXSLT = null;
Stream strmTemp = null;
- switch (_nTransform)
+ switch (transformType)
{
case TransformType.Reader:
xrXSLT = xslt.Transform(xd, null);
+
+ using (FileStream outFile = new FileStream(_strOutFile, FileMode.Create, FileAccess.ReadWrite))
+ using (XmlWriter writer = XmlWriter.Create(outFile))
+ {
+ writer.WriteNode(xrXSLT, true);
+ }
+
if (errorCase)
{
try
@@ -717,18 +588,16 @@ namespace System.Xml.Tests
TextWriter tw = null;
try
{
- tw = new StreamWriter(new FileStream(_strOutFile, FileMode.Create, FileAccess.Write), Encoding.UTF8);
- xslt.Transform(xd, null, tw);
+ using (FileStream outFile = new FileStream(_strOutFile, FileMode.Create, FileAccess.Write))
+ {
+ tw = new StreamWriter(outFile, Encoding.UTF8);
+ xslt.Transform(xd, null, tw);
+ }
}
catch (Exception ex)
{
throw (ex);
}
- finally
- {
- if (tw != null)
- tw.Dispose();
- }
break;
}
return 1;
@@ -739,28 +608,35 @@ namespace System.Xml.Tests
// Transform_ArgList
// -------------------------------------------------------------------------------------------------------------
- public int Transform_ArgList(String szXmlFile)
+ public int Transform_ArgList(string szXmlFile, TransformType transformType, DocType docType)
{
// Default value of errorCase is false
- return Transform_ArgList(szXmlFile, false);
+ return Transform_ArgList(szXmlFile, false, transformType, docType);
}
- public int Transform_ArgList(String szXmlFile, bool errorCase)
+ public int Transform_ArgList(string szXmlFile, bool errorCase, TransformType transformType, DocType docType)
{
lock (s_outFileMemoryLock)
{
szXmlFile = FullFilePath(szXmlFile);
_output.WriteLine("Loading XML {0}", szXmlFile);
- IXPathNavigable xd = LoadXML(szXmlFile, _docType);
+ IXPathNavigable xd = LoadXML(szXmlFile, docType);
_output.WriteLine("Executing transform");
xrXSLT = null;
Stream strmTemp = null;
- switch (_nTransform)
+ switch (transformType)
{
case TransformType.Reader:
xrXSLT = xslt.Transform(xd, m_xsltArg);
+
+ using (FileStream outFile = new FileStream(_strOutFile, FileMode.Create, FileAccess.ReadWrite))
+ using (XmlWriter writer = XmlWriter.Create(outFile))
+ {
+ writer.WriteNode(xrXSLT, true);
+ }
+
if (errorCase)
{
try
@@ -819,20 +695,16 @@ namespace System.Xml.Tests
TextWriter tw = null;
try
{
- tw = new StreamWriter(new FileStream(_strOutFile, FileMode.Create, FileAccess.Write), Encoding.UTF8);
- xslt.Transform(xd, m_xsltArg, tw);
+ using (FileStream outFile = new FileStream(_strOutFile, FileMode.Create, FileAccess.Write))
+ {
+ tw = new StreamWriter(outFile, Encoding.UTF8);
+ xslt.Transform(xd, m_xsltArg, tw);
+ }
}
catch (Exception ex)
{
throw (ex);
}
- finally
- {
- if (tw != null)
- {
- tw.Dispose();
- }
- }
break;
}
return 1;
@@ -843,29 +715,36 @@ namespace System.Xml.Tests
// TransformResolver
// -------------------------------------------------------------------------------------------------------------
- public int TransformResolver(String szXmlFile, XmlResolver xr)
+ public int TransformResolver(string szXmlFile, TransformType transformType, DocType docType, XmlResolver xr)
{
// Default value of errorCase is false
- return TransformResolver(szXmlFile, xr, false);
+ return TransformResolver(szXmlFile, xr, false, transformType, docType);
}
- public int TransformResolver(String szXmlFile, XmlResolver xr, bool errorCase)
+ public int TransformResolver(string szXmlFile, XmlResolver xr, bool errorCase, TransformType transformType, DocType docType)
{
lock (s_outFileMemoryLock)
{
szXmlFile = FullFilePath(szXmlFile);
_output.WriteLine("Loading XML {0}", szXmlFile);
- IXPathNavigable xd = LoadXML(szXmlFile, _docType);
+ IXPathNavigable xd = LoadXML(szXmlFile, docType);
_output.WriteLine("Executing transform");
xrXSLT = null;
Stream strmTemp = null;
- switch (_nTransform)
+ switch (transformType)
{
case TransformType.Reader:
xrXSLT = xslt.Transform(xd, null, xr);
+
+ using (FileStream outFile = new FileStream(_strOutFile, FileMode.Create, FileAccess.ReadWrite))
+ using (XmlWriter writer = XmlWriter.Create(outFile))
+ {
+ writer.WriteNode(xrXSLT, true);
+ }
+
if (errorCase)
{
try
@@ -924,18 +803,16 @@ namespace System.Xml.Tests
TextWriter tw = null;
try
{
- tw = new StreamWriter(new FileStream(_strOutFile, FileMode.Create, FileAccess.Write), Encoding.UTF8);
- xslt.Transform(xd, null, tw, xr);
+ using (FileStream outFile = new FileStream(_strOutFile, FileMode.Create, FileAccess.Write))
+ {
+ tw = new StreamWriter(outFile, Encoding.UTF8);
+ xslt.Transform(xd, null, tw, xr);
+ }
}
catch (Exception ex)
{
throw (ex);
}
- finally
- {
- if (tw != null)
- tw.Dispose();
- }
break;
}
return 1;
@@ -945,14 +822,14 @@ namespace System.Xml.Tests
// --------------------------------------------------------------------------------------------------------------
// CheckResult
// -------------------------------------------------------------------------------------------------------------
- public int CheckResult(double szExpResult)
+ public int CheckResult(double szExpResult, TransformType transformType)
{
lock (s_outFileMemoryLock)
{
double checksumActual;
CXsltChecksum check = new CXsltChecksum(_fTrace, _output);
- if (_nTransform == TransformType.Reader)
+ if (transformType == TransformType.Reader)
checksumActual = check.Calc(xrXSLT);
else
checksumActual = check.Calc(_strOutFile);
diff --git a/src/System.Private.Xml/tests/Xslt/XslTransformApi/cthread.cs b/src/System.Private.Xml/tests/Xslt/XslTransformApi/cthread.cs
index bf7008e279..f7760cc601 100644
--- a/src/System.Private.Xml/tests/Xslt/XslTransformApi/cthread.cs
+++ b/src/System.Private.Xml/tests/Xslt/XslTransformApi/cthread.cs
@@ -4,7 +4,6 @@
//ArrayList
-using System;
using System.Reflection;
using System.Threading;
using Xunit;
@@ -128,7 +127,6 @@ namespace System.Xml.Tests
public virtual void Abort()
{
- //Internal.Abort();
throw new NotImplementedException();
}
@@ -174,9 +172,6 @@ namespace System.Xml.Tests
//case TEST_SKIPPED:
_output.WriteLine(eTest.Message);
return eResult; //were done
-
- //case TEST_WARNING:
- // break;
};
}
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/ApiTests/XsltcApiTest.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/ApiTests/XsltcApiTest.cs
index 554c591ad8..c95e1f9d65 100644
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/ApiTests/XsltcApiTest.cs
+++ b/src/System.Private.Xml/tests/Xslt/XsltCompiler/ApiTests/XsltcApiTest.cs
@@ -4,12 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Reflection;
-using System.Xml;
using System.Xml.Xsl;
using OLEDB.Test.ModuleCore;
@@ -57,65 +51,5 @@ namespace System.Xml.Tests
throw new CTestFailedException("Did not throw ArgumentException");
}
-
- /*//[Variation("3", Desc = "Exercise loading from the same class within different threads", Pri = 1)]
- [InlineData()]
- [Theory]
- public void Var3()
- {
- var xsltList = new SynchronizedCollection<XslCompiledTransform>();
- var rThreads = new CThreads(_output);
-
- for (int i = 0; i < 10; i++)
- {
- rThreads.Add(o =>
- {
- var xslt = new XslCompiledTransform();
- xsltList.Add(xslt);
- XsltcUtil.LoadFromAssembly(ref xslt, "IdentityTransform");
- return;
- }, i.ToString(CultureInfo.InvariantCulture));
- }
-
- //Wait until they are complete
- rThreads.Start();
- rThreads.Wait();
-
- return Verify(xsltList);
- }*/
-
- //[Variation("4", Desc = "XSLCompiledTransform Load(Type) changes the static data of the Type to XmlILCommand", Pri = 1)]
- [InlineData()]
- //[Theory] //Disabled as it tries to load an assembly which does not exist on CoreFX anymore
- public void Var4()
- {
- var xslt = new XslCompiledTransform();
-
- Type t = Assembly.Load(new AssemblyName("TestStylesheet")).GetType("TestStylesheet");
- BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Static;
-
- Type beforeLoad = t.GetTypeInfo().GetField("staticData", bindingFlags).GetValue(null).GetType();
- xslt.Load(t);
- Type afterLoad = t.GetTypeInfo().GetField("staticData", bindingFlags).GetValue(null).GetType();
- CError.Compare(beforeLoad, afterLoad, "Mismatch in type, before and after load");
- return;
- }
-
- public void Verify(IList<XslCompiledTransform> xsltList)
- {
- var inputXml = new XmlDocument();
- inputXml.LoadXml("<foo><bar>Hello, world!</bar></foo>");
-
- foreach (XslCompiledTransform xslt in xsltList)
- {
- using (var actualStream = new MemoryStream())
- using (var sw = new StreamWriter(actualStream) { AutoFlush = true })
- {
- xslt.Transform(inputXml, null, sw);
-
- CompareOutput("<?xml version=\"1.0\" encoding=\"utf-8\"?><foo><bar>Hello, world!</bar></foo>", actualStream);
- }
- }
- }
}
} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestBasicFunctionality.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestBasicFunctionality.cs
index eec881de51..c2fb77de28 100644
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestBasicFunctionality.cs
+++ b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestBasicFunctionality.cs
@@ -4,8 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
-using System.IO;
namespace System.Xml.Tests
{
@@ -18,83 +16,15 @@ namespace System.Xml.Tests
_output = output;
}
- //[Variation("1", Desc = "Exercise the basic use case, no options", Pri = 1, Params = new object[] { "bft1.xsl", "bft1", "bft1.txt" })]
- //[InlineData("bft1.xsl", "bft1", "bft1.txt")] //Skipping this, it tries to load System.dll
- //[Variation("2", Desc = "Exercise the basic use case, no options, fully qualified path", Pri = 1, Params = new object[] { @"$(CurrentWorkingDirectory)\bft2.xsl", "bft2", "bft2.txt" })]
- //[InlineData(@"$(CurrentWorkingDirectory)\bft2.xsl", "bft2", "bft2.txt")] //Skipping this, it tries to load System.dll
- //[Variation("10", Desc = "Exercise the basic use case, 2 stylesheets, 2 classes", Pri = 1, Params = new object[] { "/class:bft10a bft10a.xsl /class:bft10b bft10b.xsl", "bft10a", "bft10.txt" })]
- //[InlineData("/class:bft10a bft10a.xsl /class:bft10b bft10b.xsl", "bft10a", "bft10.txt")] //Skipping this, it tries to load System.dll
- //[Variation("11", Desc = "Exercise the basic use case, 3 stylesheets, 2 classes", Pri = 2, Params = new object[] { "/class:bft11a bft11a.xsl /class:bft11b bft11b.xsl bft11c.xsl", "bft11a", "bft11.txt" })]
- //[InlineData("/class:bft11a bft11a.xsl /class:bft11b bft11b.xsl bft11c.xsl", "bft11a", "bft11.txt")] //Skipping this, it tries to load System.dll
- //[Variation("12", Desc = "Exercise the basic use case, many stylesheets 1 class", Pri = 2, Params = new object[] { "/class:bft12az /out:bft12az.dll bft12a.xsl bft12b.xsl bft12c.xsl bft12d.xsl bft12e.xsl bft12f.xsl bft12g.xsl bft12h.xsl bft12i.xsl bft12j.xsl bft12k.xsl bft12l.xsl bft12m.xsl bft12n.xsl bft12o.xsl bft12p.xsl bft12q.xsl bft12r.xsl bft12s.xsl bft12t.xsl bft12u.xsl bft12v.xsl bft12w.xsl bft12x.xsl bft12y.xsl bft12z.xsl", "bft12az", "bft12.txt" })]
- //[InlineData("/class:bft12az /out:bft12az.dll bft12a.xsl bft12b.xsl bft12c.xsl bft12d.xsl bft12e.xsl bft12f.xsl bft12g.xsl bft12h.xsl bft12i.xsl bft12j.xsl bft12k.xsl bft12l.xsl bft12m.xsl bft12n.xsl bft12o.xsl bft12p.xsl bft12q.xsl bft12r.xsl bft12s.xsl bft12t.xsl bft12u.xsl bft12v.xsl bft12w.xsl bft12x.xsl bft12y.xsl bft12z.xsl", "bft12az", "bft12.txt")] //Skipping this, it tries to load System.dll
- //[Variation("13", Desc = "Exercise the basic use case, same stylesheet twice", Pri = 2, Params = new object[] { "bft13.xsl bft13.xsl", "bft13", "bft13.txt" })]
- //[InlineData("bft13.xsl bft13.xsl", "bft13", "bft13.txt")] //Skipping this, it tries to load System.dll
- //[Variation("14", Desc = "Exercise the basic use case, same stylesheet twice with 2 different classnames", Pri = 2, Params = new object[] { "/class:bft14a bft14a.xsl /class:bft14b bft14a.xsl", "bft14a", "bft14.txt" })]
- //[InlineData("/class:bft14a bft14a.xsl /class:bft14b bft14a.xsl", "bft14a", "bft14.txt")] //Skipping this, it tries to load System.dll
- //[Variation("17", Desc = "Exercise a very long stylesheetname with default classname and default assembly name", Pri = 2, Params = new object[] { "bft17012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.xsl", "bft17012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", "bft17.txt" })]
- //[InlineData("bft17012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.xsl", "bft17012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", "bft17.txt")]
- //[Variation("19", Desc = "Exercise relative URIs for imported documents", Pri = 1, Params = new object[] { @"bft19.xsl", "bft19", "bft19.txt" })]
- //[InlineData(@"bft19.xsl", "bft19", "bft19.txt")] //Skipping this, it tries to load System.dll
- //[Variation("20", Desc = "Exercise relative URIs for included documents", Pri = 1, Params = new object[] { @"bft20.xsl", "bft20", "bft20.txt" })]
- //[InlineData(@"bft20.xsl", "bft20", "bft20.txt")] //Skipping this, it tries to load System.dll
- //[Variation("21", Desc = "Exercise relative URIs for document function", Pri = 1, Params = new object[] { @"/settings:document+ bft21.xsl", "bft21", "bft21.txt" })]
- //[InlineData(@"/settings:document+ bft21.xsl", "bft21", "bft21.txt")] //Skipping this, it tries to load System.dll
- //[Variation("22", Desc = "Exercise the basic use case, no options, relative path", Pri = 1, Params = new object[] { @".\bft22.xsl", "bft22", "bft22.txt" })]
- //[InlineData(@".\bft22.xsl", "bft22", "bft22.txt")] //Skipping this, it tries to load System.dll
- //[Variation("23", Desc = "Exercise the basic use case, no options, relative path with fwd slashes", Pri = 1, Params = new object[] { @"./bft23.xsl", "bft23", "bft23.txt" })]
- //[InlineData(@"./bft23.xsl", "bft23", "bft23.txt")] //Skipping this, it tries to load System.dll
- //[Variation("25", Desc = "Exercise a stylesheet with space in its name", Pri = 1, Params = new object[] { "\"bft 25.xsl\"", "bft 25", "bft25.txt" })]
- //[InlineData("\"bft 25.xsl\"", "bft 25", "bft25.txt")] //Skipping this, it tries to load System.dll
- //[Variation("26", Desc = "Exercise Cyrillic e in filename", Pri = 1, Params = new object[] { "bft26.xsl", "bft26", "bft26.txt" })]
- //[InlineData("bft26.xsl", "bft26", "bft26.txt")] /*sd problems \u0400\u0400\u0400\u0400bft26.xsl, coverage addded to other test cases*/ //Skipping this, it tries to load System.dll
- //[Variation("31", Desc = "Exercise options with -", Pri = 1, Params = new object[] { "-out:bft31.dll /class:bft31 -debug- bft31.xsl", "bft31", "bft31.txt" })]
- //[InlineData("-out:bft31.dll /class:bft31 -debug- bft31.xsl", "bft31", "bft31.txt")] //Skipping this, it tries to load System.dll
- [ConditionalTheory(nameof(xsltcExeFound))]
- public void Var1(object param0, object param1, object param2)
- {
- String cmdLine = ReplaceCurrentWorkingDirectory(param0.ToString());
- String asmName = param1 + ".dll";
- String typeName = param1.ToString();
- String pdbName = param1 + ".pdb";
- String baselineFile = param2.ToString();
-
- VerifyTest(cmdLine, asmName, true, typeName, pdbName, false, baselineFile, _createFromInputFile);
- }
-
// All variations that are Invalid are run by Var2()
- //[Variation("6", Desc = "Exercise the basic use case, invalid input", Pri = 1, Params = new object[] { "/thisisinvalid foo", "bft6.txt" })]
- //[InlineData("/thisisinvalid foo", "bft6.txt")] //Skipping this, it tries to load System.dll
- //[Variation("7", Desc = "Exercise the basic use case, invalid input", Pri = 1, Params = new object[] { "mystylesheet", "bft7.txt" })]
- //[InlineData("mystylesheet", "bft7.txt")] //Skipping this, it tries to load System.dll
- //[Variation("8", Desc = "Exercise the basic use case, invalid input", Pri = 1, Params = new object[] { "mystylesheet,xsl", "bft8.txt" })]
- //[InlineData("mystylesheet,xsl", "bft8.txt")] //Skipping this, it tries to load System.dll
- //[Variation("9", Desc = "Exercise the basic use case, wildcarded stylesheet group", Pri = 1, Params = new object[] { "*.xsl", "bft9.txt", "EnglishOnly" })]
- //[InlineData("*.xsl", "bft9.txt"/*, "EnglishOnly"*/)] //Skipping this, it tries to load System.dll
//[Variation("15", Desc = "Exercise what would be a circular reference, a primary stylesheet that includes another, followed by the include itself", Pri = 2, Params = new object[] { "bft15a.xsl bft15b.xsl", "bft15.txt", "EnglishOnly" })]
[InlineData("bft15a.xsl bft15b.xsl", "bft15.txt"/*, "EnglishOnly"*/)]
- //[Variation("16", Desc = "Exercise the basic use case, 2 stylesheets with different extensions", Pri = 2, Params = new object[] { "bft16.xsl bft16.xslt", "bft16.txt" })]
- //[InlineData("bft16.xsl bft16.xslt", "bft16.txt")] //Skipping this, it tries to load System.dll
- //[Variation("18", Desc = "Exercise what would be a circular reference, a primary stylesheet that imports another, followed by the import itself", Pri = 1, Params = new object[] { "bft18a.xsl bft18b.xsl", "bft18.txt", "EnglishOnly" })]
- //[InlineData("bft18a.xsl bft18b.xsl", "bft18.txt"/*, "EnglishOnly"*/)] //Skipping this, it tries to load System.dll
- //[Variation("24", Desc = "Exercise what would be a circular reference, a primary stylesheet that imports another, followed by the include itself", Pri = 1, Params = new object[] { "bft24a.xsl bft24b.xsl", "bft24.txt", "EnglishOnly" })]
- //[InlineData("bft24a.xsl bft24b.xsl", "bft24.txt"/*, "EnglishOnly"*/)] //Skipping this, it tries to load System.dll
//[Variation("27", Desc = "Exercise whitespace before flag values", Pri = 1, Params = new object[] { "/ out:bft27.dll bft27.xsl", "bft27.txt" })]
[InlineData("/ out:bft27.dll bft27.xsl", "bft27.txt")]
- //[Variation("28", Desc = "Exercise whitespace after flag values", Pri = 1, Params = new object[] { "/out: bft28.dll bft28.xsl", "bft28.txt" })]
- //[InlineData("/out: bft28.dll bft28.xsl", "bft28.txt")] //Skipping this, it tries to load System.dll
- //[Variation("29", Desc = "Exercise help", Pri = 1, Params = new object[] { "/?", "help.txt" })]
- //[InlineData("/?", "help.txt")] //Skipping this, it tries to load System.dll
//[Variation("30", Desc = "Exercise help with option values", Pri = 1, Params = new object[] { "bft2.xsl /? bft2.xsl", "help.txt" })]
[InlineData("bft2.xsl /? bft2.xsl", "help.txt")]
- //[Variation("33", Desc = "Exercise nologo", Pri = 1, Params = new object[] { "/nologo /foo", "bft33.txt" })]
- //[InlineData("/nologo /foo", "bft33.txt")] //Skipping this, it tries to load System.dll
- //[Variation("34", Desc = "Stylesheet path containing device name", Pri = 1, Params = new object[] { "nul/bft34.xsl", "bft34.txt" })]
- //[InlineData("nul/bft34.xsl", "bft34.txt")] //Skipping this, it tries to load System.dll
//[Variation("35", Desc = "Device name as stylesheetname", Pri = 1, Params = new object[] { "nul.xsl", "bft35.txt" })]
[InlineData("nul.xsl", "bft35.txt")]
- //[Variation("36", Desc = "Stylesheet path without name", Pri = 1, Params = new object[] { "..\\", "bft36.txt" })]
- //[InlineData("..\\", "bft36.txt")] //Skipping this, it tries to load System.dll
//[Variation("37", Desc = "No input source", Pri = 1, Params = new object[] { "/debug+", "bft37.txt" })]
[InlineData("/debug+", "bft37.txt")]
//[Variation("38", Desc = "Empty string in arguments", Pri = 1, Params = new object[] { "\"\"", "bft38.txt" })]
@@ -111,18 +41,5 @@ namespace System.Xml.Tests
VerifyTest(cmdLine, baselineFile, _createFromInputFile);
}
-
- //[Variation("5", Desc = "Exercise the basic use case, no input", Pri = 1, Params = new object[] { " ", "bft5.txt" })]
- //[InlineData(" ", "bft5.txt")] //Skipping this, it tries to load System.dll
- //[Theory]
- public void Var3(object param0, object param1)
- {
- String cmdLine = param0.ToString();
- String baselineFile = _createFromInputFile
- ? param1.ToString()
- : "help.txt";
-
- VerifyTest(cmdLine, baselineFile, _createFromInputFile);
- }
}
} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCaseBase.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCaseBase.cs
index be51905c57..9614e46c0c 100644
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCaseBase.cs
+++ b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCaseBase.cs
@@ -2,16 +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 Xunit;
using Xunit.Abstractions;
-using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
-using System.Xml;
using System.Xml.Xsl;
using XmlCoreTest.Common;
using OLEDB.Test.ModuleCore;
@@ -342,16 +339,6 @@ namespace System.Xml.Tests
s_output.WriteLine(e.Message);
return false;
}
- // Turning this off as this causes noise on different platforms like IA64.
- // Also since we verify the assembly by loading there is not really a need for this verification.
- // if (succeeded && runAssemblyVerification) {
- // String peOutput = String.Empty;
- // succeeded = XsltVerificationLibrary.VerifyAssemblyUsingPEVerify(
- // asmName,
- // logger,
- // ref peOutput);
- // logger.LogMessage("Assembly Verification Result: " + peOutput);
- //}
}
private static byte[] loadFile(string filename)
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestClassname.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestClassname.cs
deleted file mode 100644
index ab4abad633..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestClassname.cs
+++ /dev/null
@@ -1,107 +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 Xunit;
-using Xunit.Abstractions;
-using System;
-using System.IO;
-
-namespace System.Xml.Tests
-{
- // Note: Skipping these tests as they try to load a dll which references System.dll
- ////[TestCase(Name = "Classname Tests", Desc = "This Testcase maps to test variations described in 'Classname Functional Tests'")]
- //public class XsltcTestClassname : XsltcTestCaseBase
- //{
- // private ITestOutputHelper _output;
- // public XsltcTestClassname(ITestOutputHelper output) : base(output)
- // {
- // _output = output;
- // }
-
- // //[Variation("1", Desc = "Exercise the basic use case, a simple valid classname", Pri = 1, Params = new object[] { "/class:MyClass cnt1.xsl", "MyClass", "cnt1.dll", "cnt1.txt" })]
- // [InlineData("/class:MyClass cnt1.xsl", "MyClass", "cnt1.dll", "cnt1.txt")]
- // //[Variation("2", Desc = "Exercise the basic use case, a fully qualified classname", Pri = 1, Params = new object[] { "/class:XmlCoreTest.MyClass cnt2.xsl", "XmlCoreTest.MyClass", "cnt2.dll", "cnt2.txt" })]
- // [InlineData("/class:XmlCoreTest.MyClass cnt2.xsl", "XmlCoreTest.MyClass", "cnt2.dll", "cnt2.txt")]
- // //[Variation("4", Desc = "Exercise a C# reserved keyword", Pri = 1, Params = new object[] { "/class:class cnt4.xsl", "class", "cnt4.dll", "cnt4.txt" })]
- // [InlineData("/class:class cnt4.xsl", "class", "cnt4.dll", "cnt4.txt")]
- // //[Variation("5", Desc = "Exercise an MSIL reserved keyword", Pri = 1, Params = new object[] { "/class:hidebysig cnt5.xsl", "hidebysig", "cnt5.dll", "cnt5.txt" })]
- // [InlineData("/class:hidebysig cnt5.xsl", "hidebysig", "cnt5.dll", "cnt5.txt")]
- // //[Variation("6", Desc = "Exercise case sensitivity", Pri = 1, Params = new object[] { "/class:MyStyleSheEt cnt6.xsl", "MyStyleSheEt", "cnt6.dll", "cnt6.txt" })]
- // [InlineData("/class:MyStyleSheEt cnt6.xsl", "MyStyleSheEt", "cnt6.dll", "cnt6.txt")]
- // //[Variation("7", Desc = "Exercise wildcards", Pri = 1, Params = new object[] { "/class:AB? cnt7.xsl", "AB?", "cnt7.dll", "cnt7.txt" })]
- // [InlineData("/class:AB? cnt7.xsl", "AB?", "cnt7.dll", "cnt7.txt")]
- // //[Variation("8", Desc = "Exercise same classname, one in defautl NS, one in fully-qualified NS", Pri = 1, Params = new object[] { "/class:myclass cnt8a.xsl /class:myns.myclass cnt8b.xsl", "myclass", "cnt8a.dll", "cnt8.txt" })]
- // [InlineData("/class:myclass cnt8a.xsl /class:myns.myclass cnt8b.xsl", "myclass", "cnt8a.dll", "cnt8.txt")]
- // //[Variation("9", Desc = "Exercise same classname, different namespaces", Pri = 1, Params = new object[] { "/class:ns1.myclass cnt9a.xsl /class:ns2.myclass cnt9b.xsl", "ns1.myclass", "cnt9a.dll", "cnt9.txt" })]
- // [InlineData("/class:ns1.myclass cnt9a.xsl /class:ns2.myclass cnt9b.xsl", "ns1.myclass", "cnt9a.dll", "cnt9.txt")]
- // //[Variation("10", Desc = "Exercise same namespace, different classnames", Pri = 1, Params = new object[] { "/class:ns.myclass1 cnt10a.xsl /class:ns.myclass2 cnt10b.xsl", "ns.myclass2", "cnt10a.dll", "cnt10.txt" })]
- // [InlineData("/class:ns.myclass1 cnt10a.xsl /class:ns.myclass2 cnt10b.xsl", "ns.myclass2", "cnt10a.dll", "cnt10.txt")]
- // //[Variation("11", Desc = "Exercise inner class classname", Pri = 2, Params = new object[] { "/class:myclass1 cnt11a.xsl /class:myclass1.myclass2 cnt11b.xsl", "myclass1", "cnt11a.dll", "cnt11.txt" })]
- // [InlineData("/class:myclass1 cnt11a.xsl /class:myclass1.myclass2 cnt11b.xsl", "myclass1", "cnt11a.dll", "cnt11.txt")]
- // //[Variation("12", Desc = "Exercise inner class classname ordered", Pri = 1, Params = new object[] { "/class:myclass1.myclass2 cnt12b.xsl /class:myclass1 cnt12a.xsl ", "myclass1", "cnt12b.dll", "cnt12.txt" })]
- // [InlineData("/class:myclass1.myclass2 cnt12b.xsl /class:myclass1 cnt12a.xsl ", "myclass1", "cnt12b.dll", "cnt12.txt")]
- // //[Variation("14", Desc = "Exercise case sensitivity-2", Pri = 1, Params = new object[] { "/class:MyStyleSheEt cnt14.xsl /class:MystylesheeT cnt14b.xsl", "MyStyleSheEt", "cnt14.dll", "cnt14.txt" })]
- // [InlineData("/class:MyStyleSheEt cnt14.xsl /class:MystylesheeT cnt14b.xsl", "MyStyleSheEt", "cnt14.dll", "cnt14.txt")]
- // //[Variation("16", Desc = "Exercise stylesheet name with multiple dots for default classname ", Pri = 2, Params = new object[] { "ns1.ns2.cnt16.xsl", "ns1.ns2.cnt16", "ns1.ns2.cnt16.dll", "cnt16.txt" })]
- // [InlineData("ns1.ns2.cnt16.xsl", "ns1.ns2.cnt16", "ns1.ns2.cnt16.dll", "cnt16.txt")]
- // //[Variation("17", Desc = "Exercise stylesheet name with multiple adjacent dots for default classname", Pri = 2, Params = new object[] { "ns1..cnt17.xsl", "ns1..cnt17", "ns1..cnt17.dll", "cnt17.txt" })]
- // [InlineData("ns1..cnt17.xsl", "ns1..cnt17", "ns1..cnt17.dll", "cnt17.txt")]
- // //[Variation("19", Desc = "Exercise a stylesheet with invalid c# classname", Pri = 1, Params = new object[] { "2-(1)cnt19.xsl", "2-(1)cnt19", "2-(1)cnt19.dll", "cnt19.txt" })]
- // [InlineData("2-(1)cnt19.xsl", "2-(1)cnt19", "2-(1)cnt19.dll", "cnt19.txt")]
- // //[Variation("21", Desc = "Exercise keyword case sensitivity", Pri = 1, Params = new object[] { "/CLasS:cnt21 cnt21.xsl", "cnt21", "cnt21.dll", "cnt21.txt" })]
- // [InlineData("/CLasS:cnt21 cnt21.xsl", "cnt21", "cnt21.dll", "cnt21.txt")]
- // //[Variation("22", Desc = "Exercise a space containing classname", Pri = 2, Params = new object[] { "/class:\"cn t22\" cnt22.xsl", "cn t22", "cnt22.dll", "cnt22.txt" })]
- // [InlineData("/class:\"cn t22\" cnt22.xsl", "cn t22", "cnt22.dll", "cnt22.txt")]
- // //[Variation("23", Desc = "Exercise short form", Pri = 1, Params = new object[] { "-c:myclass cnt23.xsl", "myclass", "cnt23.dll", "cnt23.txt" })]
- // [InlineData("-c:myclass cnt23.xsl", "myclass", "cnt23.dll", "cnt23.txt")]
- // //[Variation("25", Desc = "Exercise two classnames differentiated only by Cyrillic E", Pri = 1, Params = new object[] { "/class:\u0400cnt25\u0400 cnt25a.xsl /class:cnt25 cnt25b.xsl", "\u0400cnt25\u0400", "cnt25a.dll", "cnt25.txt" })]
- // [InlineData("/class:\u0400cnt25\u0400 cnt25a.xsl /class:cnt25 cnt25b.xsl", "\u0400cnt25\u0400", "cnt25a.dll", "cnt25.txt")]
- // //[Variation("26", Desc = "Exercise two classnames differentiated only by zero width non breaking space and zero width non joiner", Pri = 1, Params = new object[] { "/class:\uFEFFcnt26\u200B cnt26a.xsl /class:cnt26 cnt26b.xsl", "\uFEFFcnt26\u200B", "cnt26a.dll", "cnt26.txt" })]
- // [InlineData("/class:\uFEFFcnt26\u200B cnt26a.xsl /class:cnt26 cnt26b.xsl", "\uFEFFcnt26\u200B", "cnt26a.dll", "cnt26.txt")]
- // //[Variation("27", Desc = "Exercise two classnames differentiated only by latin a combined with ring above and \u00e5", Pri = 1, Params = new object[] { "/class:\u0061\u030acnt27 cnt27a.xsl /class:\u00e5cnt27 cnt27b.xsl", "\u0061\u030acnt27", "cnt27a.dll", "cnt27.txt" })]
- // [InlineData("/class:\u0061\u030acnt27 cnt27a.xsl /class:\u00e5cnt27 cnt27b.xsl", "\u0061\u030acnt27", "cnt27a.dll", "cnt27.txt")]
- // //[Variation("28", Desc = "Exercise two classnames differentiated only by latin small y and IPA block phoenetic y with load", Pri = 1, Params = new object[] { "/class:\u0079cnt28 cnt28a.xsl /class:\u028Fcnt28 cnt28b.xsl", "\u0079cnt28", "cnt28a.dll", "cnt28.txt" })]
- // [InlineData("/class:\u0079cnt28 cnt28a.xsl /class:\u028Fcnt28 cnt28b.xsl", "\u0079cnt28", "cnt28a.dll", "cnt28.txt")]
- // //[Variation("29", Desc = "Exercise classnames containing (0x03C2), (0x03A3) and (0x03C3), where 2 lower case characters have the same upper case character", Pri = 1, Params = new object[] { "/class:\u03C2\u03A3\u03C3cnt29 cnt29a.xsl /class:\u03A3\u03C2\u03C3cnt29 cnt29b.xsl", "\u03C2\u03A3\u03C3cnt29", "cnt29a.dll", "cnt29.txt" })]
- // [InlineData("/class:\u03C2\u03A3\u03C3cnt29 cnt29a.xsl /class:\u03A3\u03C2\u03C3cnt29 cnt29b.xsl", "\u03C2\u03A3\u03C3cnt29", "cnt29a.dll", "cnt29.txt")]
- // [Theory]
- // public void Var1(object param0, object param1, object param2, object param3)
- // {
- // String cmdLine = param0.ToString();
- // String asmName = param2.ToString();
- // bool asmCreated = true;
- // String typeName = param1.ToString();
- // String pdbName = Path.ChangeExtension(param2.ToString(), ".pdb");
- // bool pdbCreated = false;
- // String baselineFile = param3.ToString();
-
- // VerifyTest(cmdLine, asmName, asmCreated, typeName, pdbName, pdbCreated, baselineFile, _createFromInputFile);
- // }
-
- // //[Variation("3", Desc = "Exercise an invalid case, empty/no argument", Pri = 1, Params = new object[] { "/class: cnt3.xsl", "cnt3.txt" })]
- // [InlineData("/class: cnt3.xsl", "cnt3.txt")]
- // //[Variation("13", Desc = "Exercise an invalid case, class specified without colon", Pri = 1, Params = new object[] { "/class cnt13.xsl", "cnt13.txt" })]
- // [InlineData("/class cnt13.xsl", "cnt13.txt")]
- // //[Variation("15", Desc = "Exercise classname conflict, 2 stylesheets one with default classname and one specifying the same", Pri = 2, Params = new object[] { "cnt15a.xsl /class:cnt15a cnt15b.xsl", "cnt15.txt" })]
- // [InlineData("cnt15a.xsl /class:cnt15a cnt15b.xsl", "cnt15.txt")]
- // //[Variation("18", Desc = "Exercise the basic use case, 2 stylesheets with different extensions", Pri = 2, Params = new object[] { "cnt18.xsl cnt18.xslt", "cnt18.txt" })]
- // [InlineData("cnt18.xsl cnt18.xslt", "cnt18.txt")]
- // //[Variation("20", Desc = "Exercise a very long classname", Pri = 2, Params = new object[] { "/class:cnt2001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 cnt20.xsl", "cnt20.txt", "EnglishOnly" })]
- // //[InlineData("/class:cnt2001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 cnt20.xsl", "cnt20.txt"/*, "EnglishOnly"*/)]
- // //[Variation("24", Desc = "Exercise multiple /class flags for one stylesheet", Pri = 1, Params = new object[] { "/class:A /class:B cnt24.xsl", "cnt24.txt" })]
- // [InlineData("/class:A /class:B cnt24.xsl", "cnt24.txt")]
- // [Theory]
- // public void Var2(object param0, object param1)
- // {
- // if (ShouldSkip(new object[] { param0, param1 }))
- // {
- // return; //TEST_SKIPPED;
- // }
- // String cmdLine = param0.ToString();
- // String baselineFile = param1.ToString();
-
- // VerifyTest(cmdLine, baselineFile, _createFromInputFile);
- // }
- //}
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCompile.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCompile.cs
deleted file mode 100644
index b838861c6e..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCompile.cs
+++ /dev/null
@@ -1,48 +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 Xunit;
-//using Xunit.Abstractions;
-//using System.IO;
-//using System.Xml;
-//using System.Xml.Xsl;
-
-// BinCompat TODO: Disabling this for now, as this is loading a dll with no strong name
-//namespace System.Xml.Tests
-//{
-// //[TestCase(Name = "Compile Time Tests", Desc = "This Testcase maps to test variations described in 'CompileTime Variations Functional Tests'")]
-// public class XsltcTestCompile : XsltcTestCaseBase
-// {
-// private ITestOutputHelper _output;
-// public XsltcTestCompile(ITestOutputHelper output) : base(output)
-// {
-// _output = output;
-// }
-
-// //[Variation("1", Desc = "Test calling XslCompiledTransform(typeof()) instead of using reflection to load the assembly.", Pri = 1)]
-// [InlineData()]
-// [Theory]
-// public void Var1()
-// {
-// var inputXml = new XmlDocument();
-// inputXml.LoadXml("<foo><bar>Hello, world!</bar></foo>");
-
-// var xslt = new XslCompiledTransform();
-// xslt.Load(typeof(TestStylesheet));
-
-// using (var actualStream = new MemoryStream())
-// using (var sw = new StreamWriter(actualStream)
-// {
-// AutoFlush = true
-// })
-// {
-// xslt.Transform(inputXml, null, sw);
-
-// CompareOutput("<?xml version=\"1.0\" encoding=\"utf-8\"?>Hello foo!", actualStream);
-
-// return;
-// }
-// }
-// }
-//} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestOut.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestOut.cs
deleted file mode 100644
index 2d25120f44..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestOut.cs
+++ /dev/null
@@ -1,118 +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 Xunit;
-using Xunit.Abstractions;
-using System;
-
-namespace System.Xml.Tests
-{
- // Note: Skipping these tests as they try to load a dll which references System.dll
- ////[TestCase(Name = "Out Option Tests", Desc = "This Testcase maps to test variations described in 'Out Functional Tests'")]
- //public class XsltcTestOut : XsltcTestCaseBase
- //{
- // private ITestOutputHelper _output;
- // public XsltcTestOut(ITestOutputHelper output) : base(output)
- // {
- // _output = output;
- // }
-
- // //[Variation("1", Desc = "Exercise basic use case, no option specified", Pri = 1, Params = new object[] { "oft1.xsl", "oft1.dll", "yes", "oft1", "oft1.txt" })]
- // [InlineData("oft1.xsl", "oft1.dll", "yes", "oft1", "oft1.txt")]
- // //[Variation("2", Desc = "Exercise basic use case, no option value", Pri = 1, Params = new object[] { "/out: oft2.xsl", "oft2.dll", "no", "oft2", "oft2.txt" })]
- // [InlineData("/out: oft2.xsl", "oft2.dll", "no", "oft2", "oft2.txt")]
- // //[Variation("3", Desc = "Exercise basic use case, assembly name different from stylesheet", Pri = 1, Params = new object[] { "/out:MyFoo.dll oft3.xsl", "MyFoo.dll", "yes", "oft3", "oft3.txt" })]
- // [InlineData("/out:MyFoo.dll oft3.xsl", "MyFoo.dll", "yes", "oft3", "oft3.txt")]
- // //[Variation("4", Desc = "Exercise basic use case, multiple stylesheets, no option specified", Pri = 1, Params = new object[] { "oft4a.xsl oft4b.xsl", "oft4a.dll", "yes", "oft4a", "oft4.txt" })]
- // [InlineData("oft4a.xsl oft4b.xsl", "oft4a.dll", "yes", "oft4a", "oft4.txt")]
- // //[Variation("5", Desc = "Exercise basic use case, multiple stylesheets, no option specified-2", Pri = 1, Params = new object[] { "oft5b.xsl oft5a.xsl", "oft5b.dll", "yes", "oft5a", "oft5.txt" })]
- // [InlineData("oft5b.xsl oft5a.xsl", "oft5b.dll", "yes", "oft5a", "oft5.txt")]
- // //[Variation("6", Desc = "Exercise basic use case, multiple stylesheets in one assembly", Pri = 1, Params = new object[] { "/out:oft6.dll oft6a.xsl oft6b.xsl", "oft6.dll", "yes", "oft6a", "oft6.txt" })]
- // [InlineData("/out:oft6.dll oft6a.xsl oft6b.xsl", "oft6.dll", "yes", "oft6a", "oft6.txt")]
- // //[Variation("7", Desc = "Exercise use case where assembly extension is specified, exe", Pri = 1, Params = new object[] { "/out:oft7.exe oft7.xsl", "oft7.exe", "yes", "oft7", "oft7.txt" })]
- // [InlineData("/out:oft7.exe oft7.xsl", "oft7.exe", "yes", "oft7", "oft7.txt")]
- // //[Variation("8", Desc = "Exercise use case where assembly extension is specified but different", Pri = 1, Params = new object[] { "/out:myfoo.doc oft8.xsl", "myfoo.doc", "yes", "oft8", "oft8.txt" })]
- // [InlineData("/out:myfoo.doc oft8.xsl", "myfoo.doc", "yes", "oft8", "oft8.txt")]
- // //[Variation("9", Desc = "Exercise use case, assembly extension is shorter than 3 chars", Pri = 1, Params = new object[] { "/out:oft9.xy oft9.xsl", "oft9.xy", "yes", "oft9", "oft9.txt" })]
- // [InlineData("/out:oft9.xy oft9.xsl", "oft9.xy", "yes", "oft9", "oft9.txt")]
- // //[Variation("10", Desc = "Exercise use case, assembly extension is longer than 3 chars", Pri = 1, Params = new object[] { "/out:oft10.xyzt oft10.xsl", "oft10.xyzt", "yes", "oft10", "oft10.txt" })]
- // [InlineData("/out:oft10.xyzt oft10.xsl", "oft10.xyzt", "yes", "oft10", "oft10.txt")]
- // //[Variation("11", Desc = "Exercise a very long assembly name", Pri = 1, Params = new object[] { "/out:oft1101234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.dll oft11.xsl", "oft1101234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.dll", "no", "oft11", "oft11.txt", "EnglishOnly" })]
- // //[InlineData("/out:oft1101234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.dll oft11.xsl", "oft1101234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.dll", "no", "oft11", "oft11.txt"/*, "EnglishOnly"*/)]
- // //[Variation("12", Desc = "Exercise a case where the output assembly name contains whitespace", Pri = 1, Params = new object[] { "/out:\"oft 12.dll\" oft12.xsl", "oft 12.dll", "yes", "oft12", "oft12.txt" })]
- // [InlineData("/out:\"oft 12.dll\" oft12.xsl", "oft 12.dll", "yes", "oft12", "oft12.txt")]
- // //[Variation("13", Desc = "Exercise keyword case sensitivity", Pri = 1, Params = new object[] { "/OUt:oft13.dll oft13.xsl", "oft13.dll", "yes", "oft13", "oft13.txt" })]
- // [InlineData("/OUt:oft13.dll oft13.xsl", "oft13.dll", "yes", "oft13", "oft13.txt")]
- // //[Variation("14", Desc = "Exercise fully qualified output path", Pri = 1, Params = new object[] { @"/out:$(CurrentWorkingDirectory)\oft14.dll oft14.xsl", "oft14.dll", "yes", "oft14", "oft14.txt" })]
- // [InlineData(@"/out:$(CurrentWorkingDirectory)\oft14.dll oft14.xsl", "oft14.dll", "yes", "oft14", "oft14.txt")]
- // //[Variation("15", Desc = "Exercise relative output path", Pri = 1, Params = new object[] { @"/out:.\oft15.dll oft15.xsl", "oft15.dll", "yes", "oft15", "oft15.txt" })]
- // [InlineData(@"/out:.\oft15.dll oft15.xsl", "oft15.dll", "yes", "oft15", "oft15.txt")]
- // //[Variation("16", Desc = "Exercise relative output path with forward slash", Pri = 1, Params = new object[] { @"/out:./oft16.dll oft16.xsl", "oft16.dll", "yes", "oft16", "oft16.txt" })]
- // [InlineData(@"/out:./oft16.dll oft16.xsl", "oft16.dll", "yes", "oft16", "oft16.txt")]
- // //[Variation("18", Desc = "Exercise output to device", Pri = 1, Params = new object[] { "/out:a:\\oft18.dll oft18.xsl", "oft18.dll", "no", "oft18", "oft18.txt", "EnglishOnly" })]
- // [InlineData("/out:a:\\oft18.dll oft18.xsl", "oft18.dll", "no", "oft18", "oft18.txt"/*, "EnglishOnly"*/)]
- // //[Variation("19", Desc = "Exercise output to null device", Pri = 1, Params = new object[] { "/out:nul.dll oft19.xsl", "nul.dll", "no", "oft19", "oft19.txt" })]
- // [InlineData("/out:nul.dll oft19.xsl", "nul.dll", "no", "oft19", "oft19.txt")]
- // //[Variation("20", Desc = "Exercise assembly name with invalid chars", Pri = 1, Params = new object[] { "/out:\"oft|20.dll\" oft20.xsl", "oft|20.dll", "no", "oft20", "oft20.txt", "EnglishOnly" })]
- // [InlineData("/out:\"oft|20.dll\" oft20.xsl", "oft|20.dll", "no", "oft20", "oft20.txt"/*, "EnglishOnly"*/)]
- // //[Variation("21", Desc = "Exercise reserved device name as assembly name", Pri = 1, Params = new object[] { "/out:\"COM1.dll\" oft21.xsl", "COM1.dll", "no", "oft21", "oft21.txt" })]
- // [InlineData("/out:\"COM1.dll\" oft21.xsl", "COM1.dll", "no", "oft21", "oft21.txt")]
- // //[Variation("23", Desc = "Exercise assembly named ..a", Pri = 1, Params = new object[] { "/out:..oft23 oft23.xsl", "..oft23", "yes", "oft23", "oft23.txt" })]
- // [InlineData("/out:..oft23 oft23.xsl", "..oft23", "yes", "oft23", "oft23.txt")]
- // //[Variation("24", Desc = "Exercise file path with . in it", Pri = 1, Params = new object[] { "/out:MyFoo.dll oft3.xsl", "MyFoo.dll", "yes", "oft3", "oft3.txt" })]
- // //[Variation("25", Desc = "Exercise space containing assembly extension", Pri = 1, Params = new object[] { "/out:\"oft25.d l\" oft25.xsl", "oft25.d l", "yes", "oft25", "oft25.txt" })]
- // [InlineData("/out:\"oft25.d l\" oft25.xsl", "oft25.d l", "yes", "oft25", "oft25.txt")]
- // //[Variation("26", Desc = "Exercise space containing assembly path", Pri = 1, Params = new object[] { "/out:MyFoo.dll oft3.xsl", "MyFoo.dll", "yes", "oft3", "oft3.txt" })]
- // //[Variation("27", Desc = "Exercise multiple /out: flags", Pri = 1, Params = new object[] { "/out:oft27A.dll /out:oft27B.dll oft27.xsl", "oft27B.dll", "yes", "oft27", "oft27.txt" })]
- // [InlineData("/out:oft27A.dll /out:oft27B.dll oft27.xsl", "oft27B.dll", "yes", "oft27", "oft27.txt")]
- // //[Variation("29", Desc = "Exercise device name containing path", Pri = 1, Params = new object[] { "/out:d:/nul/oft29.dll oft29.xsl", "oft29.dll", "no", "oft29", "oft29.txt", "EnglishOnly" })]
- // [InlineData("/out:d:/nul/oft29.dll oft29.xsl", "oft29.dll", "no", "oft29", "oft29.txt"/*, "EnglishOnly"*/)]
- // //[Variation("30", Desc = "No directory with intranet path", Pri = 1, Params = new object[] { @"/out:\\foo\bar.dll oft30.xsl", "oft30.dll", "no", "oft30", "oft30.txt" })]
- // [InlineData(@"/out:\\foo\bar.dll oft30.xsl", "oft30.dll", "no", "oft30", "oft30.txt")]
- // //[Variation("31", Desc = "Invalid intranet path", Pri = 1, Params = new object[] { @"/out:\\foo\foo\bar.dll oft31.xsl", "oft31.dll", "no", "oft31", "oft31.txt", "EnglishOnly" })]
- // [InlineData(@"/out:\\foo\foo\bar.dll oft31.xsl", "oft31.dll", "no", "oft31", "oft31.txt"/*, "EnglishOnly"*/)]
- // [Theory]
- // public virtual void Var1(object param0, object param1, object param2, object param3, object param4)
- // {
- // if (ShouldSkip(new object[] { param0, param1, param2, param3, param4}))
- // {
- // return; //TEST_SKIPPED;
- // }
- // String cmdLine,
- // asmName,
- // typeName,
- // baselineFile;
- // bool asmCreated;
-
- // VarParse(param0, param1, param2, param3, param4, out cmdLine, out asmName, out asmCreated, out typeName, out baselineFile);
-
- // VerifyTest(cmdLine, asmName, asmCreated, typeName, baselineFile, _createFromInputFile);
- // }
-
- // //[Variation("28", Desc = "Exercise an assembly name composed of zero width chars and Cyrillic E", Pri = 1, Params = new object[] { "/out:\u0400\uFEFF\u200B.\u0400\uFEFF\u200B\u0400 oft28.xsl", "\u0400\uFEFF\u200B.\u0400\uFEFF\u200B\u0400", "yes", "oft28", "oft28.txt" })]
- // [InlineData("/out:\u0400\uFEFF\u200B.\u0400\uFEFF\u200B\u0400 oft28.xsl", "\u0400\uFEFF\u200B.\u0400\uFEFF\u200B\u0400", "yes", "oft28", "oft28.txt")]
- // [Theory]
- // public virtual void Var2(object param0, object param1, object param2, object param3, object param4)
- // {
- // String cmdLine,
- // asmName,
- // typeName,
- // baselineFile;
- // bool asmCreated;
-
- // VarParse(param0, param1, param2, param3, param4, out cmdLine, out asmName, out asmCreated, out typeName, out baselineFile);
-
- // VerifyTest(cmdLine, asmName, asmCreated, typeName, String.Empty, false, baselineFile, false, _createFromInputFile);
- // }
-
- // public virtual void VarParse(object param0, object param1, object param2, object param3, object param4, out String cmdLine, out String asmName, out bool asmCreated, out String typeName, out String baselineFile)
- // {
- // cmdLine = ReplaceCurrentWorkingDirectory(param0.ToString());
- // asmName = param1.ToString();
- // asmCreated = String.Compare(param2.ToString(), "yes", true) == 0;
- // typeName = param3.ToString();
- // baselineFile = param4.ToString();
- // }
- //}
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestPlatform.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestPlatform.cs
index 994d82b1e9..ab05bc9713 100644
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestPlatform.cs
+++ b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestPlatform.cs
@@ -4,8 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
-using System.Globalization;
using System.IO;
namespace System.Xml.Tests
@@ -19,20 +17,12 @@ namespace System.Xml.Tests
_output = output;
}
- //[Variation("1", Desc = "Exercise basic use case, no option specified", Pri = 1, Params = new object[] { "pft1.xsl", "pft1", "pft1.dll", "pft1.txt" })]
- //[InlineData("pft1.xsl", "pft1", "pft1.dll", "pft1.txt")] //Skipping this, it tries to load System.dll
//[Variation("3", Desc = "Exercise basic use case, a supported option val", Pri = 1, Params = new object[] { "/platform:x64 pft3.xsl", "", "pft3.dll", "pft3.txt" })]
[InlineData("/platform:x64 pft3.xsl", "", "pft3.dll", "pft3.txt")]
- //[Variation("7", Desc = "Exercise keyword case sensitivity -1 ", Pri = 1, Params = new object[] { "/PLAtforM:X86 pft7.xsl", "", "pft7.dll", "pft7.txt" })]
- //[InlineData("/PLAtforM:X86 pft7.xsl", "", "pft7.dll", "pft7.txt")] //Skipping this, it tries to load System.dll
//[Variation("8", Desc = "Exercise keyword case sensitivity -2", Pri = 1, Params = new object[] { "/PLAtforM:ItaNiuM pft8.xsl", "", "pft8.dll", "pft8.txt" })]
[InlineData("/PLAtforM:ItaNiuM pft8.xsl", "", "pft8.dll", "pft8.txt")]
- //[Variation("9", Desc = "Exercise keyword case sensitivity -3", Pri = 1, Params = new object[] { "/PLAtforM:X64 pft9.xsl", "", "pft9.dll", "pft9.txt" })]
- //[InlineData("/PLAtforM:X64 pft9.xsl", "", "pft9.dll", "pft9.txt")] //Skipping this, it tries to load System.dll
//[Variation("10", Desc = "Exercise keyword case sensitivity -4", Pri = 1, Params = new object[] { "/PLAtforM:AnyCpU pft10.xsl", "", "pft10.dll", "pft10.txt" })]
[InlineData("/PLAtforM:AnyCpU pft10.xsl", "", "pft10.dll", "pft10.txt")]
- //[Variation("17", Desc = "Compile an assembly for anycpu and load", Pri = 1, Params = new object[] { "/platform:anycpu pft17.xsl", "pft17", "pft17.dll", "pft17.txt" })]
- //[InlineData("/platform:anycpu pft17.xsl", "pft17", "pft17.dll", "pft17.txt")] //Skipping this, it tries to load System.dll
[ConditionalTheory(nameof(xsltcExeFound))]
public void Var1(object param0, object param1, object param2, object param3)
{
@@ -51,16 +41,8 @@ namespace System.Xml.Tests
[InlineData("/platform: pft2.xsl", "pft2.txt")]
//[Variation("4", Desc = "Exercise basic use case, an unsupported option value", Pri = 1, Params = new object[] { "/platform:foo pft4.xsl", "pft4.txt" })]
[InlineData("/platform:foo pft4.xsl", "pft4.txt")]
- //[Variation("11", Desc = "Exercise basic use case, an unsupported option value -1", Pri = 1, Params = new object[] { "/platform pft11.xsl", "pft11.txt" })]
- //[InlineData("/platform pft11.xsl", "pft11.txt")] //Skipping this, it tries to load System.dll
//[Variation("12", Desc = "Exercise basic use case, an unsupported option value -2", Pri = 1, Params = new object[] { "/platform: pft12.xsl", "pft12.txt" })]
[InlineData("/platform: pft12.xsl", "pft12.txt")]
- //[Variation("13", Desc = "Exercise basic use case, an unsupported option value -3", Pri = 1, Params = new object[] { "/platform:* pft13.xsl", "pft13.txt" })]
- //[InlineData("/platform:* pft13.xsl", "pft13.txt")] //Skipping this, it tries to load System.dll
- //[Variation("14", Desc = "Exercise basic use case, an unsupported option value -4", Pri = 1, Params = new object[] { "/platform:x86x64 pft14.xsl", "pft14.txt" })]
- //[InlineData("/platform:x86x64 pft14.xsl", "pft14.txt")] //Skipping this, it tries to load System.dll
- //[Variation("15", Desc = "Exercise basic use case, an unsupported option value -5", Pri = 1, Params = new object[] { "/platform:x86,x64 pft15.xsl", "pft15.txt" })]
- //[InlineData("/platform:x86,x64 pft15.xsl", "pft15.txt")] //Skipping this, it tries to load System.dll
//[Variation("16", Desc = "Exercise basic use case, an unsupported option value -6", Pri = 1, Params = new object[] { "/platform:x86;x64 pft16.xsl", "pft16.txt" })]
[InlineData("/platform:x86;x64 pft16.xsl", "pft16.txt")]
[ConditionalTheory(nameof(xsltcExeFound))]
@@ -72,12 +54,8 @@ namespace System.Xml.Tests
VerifyTest(cmdLine, baselineFile, _createFromInputFile);
}
- //[Variation("18", Desc = "Compile an assembly for machine's platform and load", Pri = 1, Params = new object[] { "pft18.xsl", "pft18.dll", "yes", "pft18", "pft18.pdb", "no", "pft18.txt", "yes" })]
- //[InlineData("pft18.xsl", "pft18.dll", "yes", "pft18", "pft18.pdb", "no", "pft18.txt", "yes")] //Skipping this, it tries to load System.dll
//[Variation("19", Desc = "Compile an assembly for different platform and load", Pri = 1, Params = new object[] { "pft19.xsl", "pft19.dll", "yes", "", "pft19.pdb", "no", "pft19.txt", "no" })]
[InlineData("pft19.xsl", "pft19.dll", "yes", "", "pft19.pdb", "no", "pft19.txt", "no")]
- //[Variation("20", Desc = "Exercise multiple /platform: flags", Pri = 1, Params = new object[] { "/platform:X64 pft20.xsl" /*+ " /platform:<current>*/, "pft20.dll", "yes", "pft20", "pft20.pdb", "no", "pft20.txt", "yes" })]
- //[InlineData("/platform:X64 pft20.xsl" /*+ " /platform:<current>*/, "pft20.dll", "yes", "pft20", "pft20.pdb", "no", "pft20.txt", "yes")] //Skipping this, it tries to load System.dll
[ConditionalTheory(nameof(xsltcExeFound))]
public void Var3(object param0, object param1, object param2, object param3, object param4, object param5, object param6, object param7)
{
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestSettings.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestSettings.cs
index 2efff0291a..39766f8234 100644
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestSettings.cs
+++ b/src/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestSettings.cs
@@ -4,7 +4,6 @@
using Xunit;
using Xunit.Abstractions;
-using System;
namespace System.Xml.Tests
{
@@ -17,78 +16,36 @@ namespace System.Xml.Tests
_output = output;
}
- //[Variation("1", Desc = "Basic /settings test cases, stylesheet has DTD, where DTD+", Pri = 0, Params = new object[] { "/settings:DTD+ sft1.xsl", "sft1.dll", "yes", "sft1", "sft1.pdb", "no", "sft1.txt" })]
- //[InlineData("/settings:DTD+ sft1.xsl", "sft1.dll", "yes", "sft1", "sft1.pdb", "no", "sft1.txt")] //Skipping this, it tries to load System.dll
- //[Variation("2", Desc = "Basic /settings test cases, stylesheet has DTD, where DTD-", Pri = 0, Params = new object[] { "/settings:DTD- sft2.xsl", "sft2.dll", "no", "sft2", "sft2.pdb", "no", "sft2.txt" })]
- //[InlineData("/settings:DTD- sft2.xsl", "sft2.dll", "no", "sft2", "sft2.pdb", "no", "sft2.txt")] //Skipping this, it tries to load System.dll
- //[Variation("3", Desc = "Basic /settings test cases, stylesheet has script, where script+", Pri = 0, Params = new object[] { "/settings:script+ sft3.xsl", "sft3.dll", "yes", "sft3", "sft3.pdb", "no", "sft3.txt" })]
- //[InlineData("/settings:script+ sft3.xsl", "sft3.dll", "yes", "sft3", "sft3.pdb", "no", "sft3.txt")] //Skipping this, it tries to load System.dll
//[Variation("4", Desc = "Basic /settings test cases, stylesheet has script, where script-", Pri = 0, Params = new object[] { "/settings:script- sft4.xsl", "sft4hack.dll", "no", "sft4", "sft4.pdb", "no", "sft4.txt" })]
[InlineData("/settings:script- sft4.xsl", "sft4hack.dll", "no", "sft4", "sft4.pdb", "no", "sft4.txt")]
- //[Variation("5", Desc = "Basic /settings test cases, stylesheet has document(), where document+", Pri = 0, Params = new object[] { "/settings:document+ sft5.xsl", "sft5.dll", "yes", "sft5", "sft5.pdb", "no", "sft5.txt" })]
- //[InlineData("/settings:document+ sft5.xsl", "sft5.dll", "yes", "sft5", "sft5.pdb", "no", "sft5.txt")] //Skipping this, it tries to load System.dll
//[Variation("6", Desc = "Basic /settings test cases, stylesheet has document(), where document-", Pri = 0, Params = new object[] { "/settings:document- sft6.xsl", "sft6hack.dll", "no", "sft6", "sft6.pdb", "no", "sft6.txt" })]
[InlineData("/settings:document- sft6.xsl", "sft6hack.dll", "no", "sft6", "sft6.pdb", "no", "sft6.txt")]
//[Variation("7", Desc = "Exercise settings with no colon", Pri = 0, Params = new object[] { "/settingsDTD+ sft7.xsl", "sft7.dll", "no", "sft7", "sft7.pdb", "no", "sft7.txt" })]
[InlineData("/settingsDTD+ sft7.xsl", "sft7.dll", "no", "sft7", "sft7.pdb", "no", "sft7.txt")]
- //[Variation("8", Desc = "Exercise settings with no option value", Pri = 0, Params = new object[] { "/settings: sft8.xsl", "sft8.dll", "yes", "sft8", "sft8.pdb", "no", "sft8.txt" })]
- //[InlineData("/settings: sft8.xsl", "sft8.dll", "yes", "sft8", "sft8.pdb", "no", "sft8.txt")] //Skipping this, it tries to load System.dll
- //[Variation("9", Desc = "Exercise DTD switch without +/-, stylesheet has DTD", Pri = 0, Params = new object[] { "/settings:DTD sft9.xsl", "sft9.dll", "yes", "sft9", "sft9.pdb", "no", "sft9.txt" })]
- //[InlineData("/settings:DTD sft9.xsl", "sft9.dll", "yes", "sft9", "sft9.pdb", "no", "sft9.txt")] //Skipping this, it tries to load System.dll
- //[Variation("10", Desc = "Exercise script switch without +/-, stylesheet has script block", Pri = 0, Params = new object[] { "/settings:script sft10.xsl", "sft10.dll", "yes", "sft10", "sft10.pdb", "no", "sft10.txt" })]
- //[InlineData("/settings:script sft10.xsl", "sft10.dll", "yes", "sft10", "sft10.pdb", "no", "sft10.txt")] //Skipping this, it tries to load System.dll
- //[Variation("11", Desc = "Exercise document switch without +/-, stylesheet has document() function", Pri = 0, Params = new object[] { "/settings:document sft11.xsl", "sft11.dll", "yes", "sft11", "sft11.pdb", "no", "sft11.txt" })]
- //[InlineData("/settings:document sft11.xsl", "sft11.dll", "yes", "sft11", "sft11.pdb", "no", "sft11.txt")] //Skipping this, it tries to load System.dll
- //[Variation("13", Desc = "Exercise keyword case sensitivity", Pri = 0, Params = new object[] { "/SeTTings:DOCument+ sft13.xsl", "sft13.dll", "yes", "sft13", "sft13.pdb", "no", "sft13.txt" })]
- //[InlineData("/SeTTings:DOCument+ sft13.xsl", "sft13.dll", "yes", "sft13", "sft13.pdb", "no", "sft13.txt")] //Skipping this, it tries to load System.dll
//[Variation("14", Desc = "Exercise Turkish I problem", Pri = 0, Params = new object[] { "/SETTİNGS:SCRİPT+ sft14.xsl", "sft14.dll", "no", "sft14", "sft14.pdb", "no", "sft14.txt", "EnglishOnly" })]
[InlineData("/SETT\u0130NGS:SCR\u0130PT+ sft14.xsl", "sft14.dll", "no", "sft14", "sft14.pdb", "no", "sft14.txt"/*, "EnglishOnly"*/)]
//[Variation("15", Desc = "Exercise conflicting +, - symbols", Pri = 0, Params = new object[] { "/settings:script+- sft15.xsl", "sft15.dll", "no", "sft15", "sft15.pdb", "no", "sft15.txt" })]
[InlineData("/settings:script+- sft15.xsl", "sft15.dll", "no", "sft15", "sft15.pdb", "no", "sft15.txt")]
- //[Variation("27", Desc = "Basic /settings test cases, imported stylesheet has DTD, where DTD+", Pri = 0, Params = new object[] { "/settings:DTD+ sft27.xsl", "sft27.dll", "yes", "sft27", "sft27.pdb", "no", "sft27.txt" })]
- //[InlineData("/settings:DTD+ sft27.xsl", "sft27.dll", "yes", "sft27", "sft27.pdb", "no", "sft27.txt")] //Skipping this, it tries to load System.dll
//[Variation("28", Desc = "Basic /settings test cases, imported stylesheet has DTD, where DTD-", Pri = 0, Params = new object[] { "/settings:DTD- sft28.xsl", "sft28.dll", "no", "sft28", "sft28.pdb", "no", "sft28.txt" })]
[InlineData("/settings:DTD- sft28.xsl", "sft28.dll", "no", "sft28", "sft28.pdb", "no", "sft28.txt")]
- //[Variation("29", Desc = "Basic /settings test cases, imported stylesheet has script, where script+", Pri = 0, Params = new object[] { "/settings:script+ sft29.xsl", "sft29.dll", "yes", "sft29", "sft29.pdb", "no", "sft29.txt" })]
- //[InlineData("/settings:script+ sft29.xsl", "sft29.dll", "yes", "sft29", "sft29.pdb", "no", "sft29.txt")] //Skipping this, it tries to load System.dll
//[Variation("30", Desc = "Basic /settings test cases, imported stylesheet has script, where script-", Pri = 0, Params = new object[] { "/settings:script- sft30.xsl", "sft30hack.dll", "no", "sft30", "sft30.pdb", "no", "sft30.txt" })]
[InlineData("/settings:script- sft30.xsl", "sft30hack.dll", "no", "sft30", "sft30.pdb", "no", "sft30.txt")]
- //[Variation("31", Desc = "Basic /settings test cases, imported stylesheet has document(), where document+", Pri = 0, Params = new object[] { "/settings:document+ sft31.xsl", "sft31.dll", "yes", "sft31", "sft31.pdb", "no", "sft31.txt" })]
- //[InlineData("/settings:document+ sft31.xsl", "sft31.dll", "yes", "sft31", "sft31.pdb", "no", "sft31.txt")] //Skipping this, it tries to load System.dll
- //[Variation("32", Desc = "Basic /settings test cases, imported stylesheet has document(), where document-", Pri = 0, Params = new object[] { "/settings:document- sft32.xsl", "sft32hack.dll", "no", "sft32", "sft32.pdb", "no", "sft32.txt" })]
- //[InlineData("/settings:document- sft32.xsl", "sft32hack.dll", "no", "sft32", "sft32.pdb", "no", "sft32.txt")] //Skipping this, it tries to load System.dll
- //[Variation("33", Desc = "Basic /settings test cases, included stylesheet has DTD, where DTD+", Pri = 0, Params = new object[] { "/settings:DTD+ sft33.xsl", "sft33.dll", "yes", "sft33", "sft33.pdb", "no", "sft33.txt" })]
- //[InlineData("/settings:DTD+ sft33.xsl", "sft33.dll", "yes", "sft33", "sft33.pdb", "no", "sft33.txt")] //Skipping this, it tries to load System.dll
- //[Variation("34", Desc = "Basic /settings test cases, included stylesheet has DTD, where DTD-", Pri = 0, Params = new object[] { "/settings:DTD- sft34.xsl", "sft34.dll", "no", "sft34", "sft34.pdb", "no", "sft34.txt" })]
- //[InlineData("/settings:DTD- sft34.xsl", "sft34.dll", "no", "sft34", "sft34.pdb", "no", "sft34.txt")] //Skipping this, it tries to load System.dll
- //[Variation("35", Desc = "Basic /settings test cases, included stylesheet has script, where script+", Pri = 0, Params = new object[] { "/settings:script+ sft35.xsl", "sft35.dll", "yes", "sft35", "sft35.pdb", "no", "sft35.txt" })]
- //[InlineData("/settings:script+ sft35.xsl", "sft35.dll", "yes", "sft35", "sft35.pdb", "no", "sft35.txt")] //Skipping this, it tries to load System.dll
//[Variation("36", Desc = "Basic /settings test cases, included stylesheet has script, where script-", Pri = 0, Params = new object[] { "/settings:script- sft36.xsl", "sft36hack.dll", "no", "sft36", "sft36.pdb", "no", "sft36.txt" })]
[InlineData("/settings:script- sft36.xsl", "sft36hack.dll", "no", "sft36", "sft36.pdb", "no", "sft36.txt")]
- //[Variation("37", Desc = "Basic /settings test cases, included stylesheet has document(), where document+", Pri = 0, Params = new object[] { "/settings:document+ sft37.xsl", "sft37.dll", "yes", "sft37", "sft37.pdb", "no", "sft37.txt" })]
- //[InlineData("/settings:document+ sft37.xsl", "sft37.dll", "yes", "sft37", "sft37.pdb", "no", "sft37.txt")] //Skipping this, it tries to load System.dll
//[Variation("38", Desc = "Basic /settings test cases, included stylesheet has document(), where document-", Pri = 0, Params = new object[] { "/settings:document- sft38.xsl", "sft38hack.dll", "no", "sft38", "sft38.pdb", "no", "sft38.txt" })]
[InlineData("/settings:document- sft38.xsl", "sft38hack.dll", "no", "sft38", "sft38.pdb", "no", "sft38.txt")]
//[Variation("41", Desc = "Exercise basic use case invalid option specified", Pri = 0, Params = new object[] { "/settings:DTD~ sft41.xsl", "sft41.dll", "no", "sft41", "sft41.pdb", "no", "sft41.txt" })]
[InlineData("/settings:DTD~ sft41.xsl", "sft41.dll", "no", "sft41", "sft41.pdb", "no", "sft41.txt")]
//[Variation("42", Desc = "Exercise basic use case invalid option specified", Pri = 0, Params = new object[] { "/settings:script* sft42.xsl", "sft42.dll", "no", "sft42", "sft42.pdb", "no", "sft42.txt" })]
[InlineData("/settings:script* sft42.xsl", "sft42.dll", "no", "sft42", "sft42.pdb", "no", "sft42.txt")]
- //[Variation("43", Desc = "Exercise basic use case invalid option specified", Pri = 0, Params = new object[] { "/settings:document% sft43.xsl", "sft43.dll", "no", "sft43", "sft43.pdb", "no", "sft43.txt" })]
- //[InlineData("/settings:document% sft43.xsl", "sft43.dll", "no", "sft43", "sft43.pdb", "no", "sft43.txt")] //Skipping this, it tries to load System.dll
//[Variation("44", Desc = "Exercise basic use case multiple options specified", Pri = 0, Params = new object[] { "/settings:script+document- sft44.xsl", "sft44.dll", "no", "sft44", "sft44.pdb", "no", "sft44.txt" })]
[InlineData("/settings:script+document- sft44.xsl", "sft44.dll", "no", "sft44", "sft44.pdb", "no", "sft44.txt")]
- //[Variation("45", Desc = "Exercise basic use case invalid option specified", Pri = 0, Params = new object[] { "/script sft45.xsl", "sft45.dll", "no", "sft45", "sft45.pdb", "no", "sft45.txt" })]
- //[InlineData("/script sft45.xsl", "sft45.dll", "no", "sft45", "sft45.pdb", "no", "sft45.txt")] //Skipping this, it tries to load System.dll
//[Variation("46", Desc = "Exercise basic use case invalid option specified", Pri = 0, Params = new object[] { "/script+ sft46.xsl", "sft46.dll", "no", "sft46", "sft46.pdb", "no", "sft46.txt" })]
[InlineData("/script+ sft46.xsl", "sft46.dll", "no", "sft46", "sft46.pdb", "no", "sft46.txt")]
- //[Variation("47", Desc = "Exercise basic use case invalid option specified", Pri = 0, Params = new object[] { "/DTD sft47.xsl", "sft47.dll", "no", "sft47", "sft47.pdb", "no", "sft47.txt" })]
- //[InlineData("/DTD sft47.xsl", "sft47.dll", "no", "sft47", "sft47.pdb", "no", "sft47.txt")] //Skipping this, it tries to load System.dll
//[Variation("48", Desc = "Exercise basic use case invalid option specified", Pri = 0, Params = new object[] { "/DTD- sft48.xsl", "sft48.dll", "no", "sft48", "sft48.pdb", "no", "sft48.txt" })]
[InlineData("/DTD- sft48.xsl", "sft48.dll", "no", "sft48", "sft48.pdb", "no", "sft48.txt")]
//[Variation("49", Desc = "Exercise basic use case invalid option specified", Pri = 0, Params = new object[] { "/document sft49.xsl", "sft49.dll", "no", "sft49", "sft49.pdb", "no", "sft49.txt" })]
[InlineData("/document sft49.xsl", "sft49.dll", "no", "sft49", "sft49.pdb", "no", "sft49.txt")]
- //[Variation("50", Desc = "Exercise basic use case invalid option specified", Pri = 0, Params = new object[] { "/document- sft50.xsl", "sft50.dll", "no", "sft50", "sft50.pdb", "no", "sft50.txt" })]
- //[InlineData("/document- sft50.xsl", "sft50.dll", "no", "sft50", "sft50.pdb", "no", "sft50.txt")] //Skipping this, it tries to load System.dll
//[Variation("51", Desc = "Regression: Basic /settings test cases, two stylesheet with the same script block", Pri = 0, Params = new object[] { "/settings:script+ sft3.xsl sft4.xsl", "sft3.dll", "yes", "", "sft3.pdb", "no", "sft3.txt" })]
[InlineData("/settings:script+ sft3.xsl sft4.xsl", "sft3.dll", "yes", "", "sft3.pdb", "no", "sft3.txt")]
[ConditionalTheory(nameof(xsltcExeFound))]
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/Program.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/Program.cs
deleted file mode 100644
index 0d8bfc4be1..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/Program.cs
+++ /dev/null
@@ -1,30 +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 ModuleCore;
-using System;
-using System.IO;
-
-namespace XsltCompilerTests
-{
- internal class Program
- {
- public static int Main()
- {
- try
- {
- // Verify xsltc.exe is available
- XmlCoreTest.Common.XsltVerificationLibrary.SearchPath("xsltc.exe");
- }
- catch (FileNotFoundException)
- {
- Console.WriteLine("Could not find 'xsltc.exe'. Make sure that the .NET SDK is installed");
- return 99;
- }
-
- string args = @"ExecutionMode:File Host:None SDKInstalled:NotInstalled";
- return 100 + TestRunner.Execute(args);
- }
- }
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/TestStylesheet.dll b/src/System.Private.Xml/tests/Xslt/XsltCompiler/TestStylesheet.dll
deleted file mode 100644
index 3797d8c4a5..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/TestStylesheet.dll
+++ /dev/null
Binary files differ
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCommon.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCommon.cs
index 221ac200ef..644e5102c3 100644
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCommon.cs
+++ b/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCommon.cs
@@ -9,11 +9,8 @@ using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
-using System.Reflection;
-using System.Text;
using System.Xml;
using System.Xml.XmlDiff;
-using System.Xml.Xsl;
namespace XmlCoreTest.Common
{
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCompiler.Tests.csproj b/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCompiler.Tests.csproj
index 275c0a445b..10ef80a4c9 100644
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCompiler.Tests.csproj
+++ b/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCompiler.Tests.csproj
@@ -14,10 +14,7 @@
<ItemGroup>
<Compile Include="CommonScenarios\XsltcTestBasicFunctionality.cs" />
<Compile Include="CommonScenarios\XsltcTestCaseBase.cs" />
- <Compile Include="CommonScenarios\XsltcTestClassname.cs" />
- <Compile Include="CommonScenarios\XsltcTestCompile.cs" />
<Compile Include="CommonScenarios\XsltcTestFile.cs" />
- <Compile Include="CommonScenarios\XsltcTestOut.cs" />
<Compile Include="CommonScenarios\XsltcTestPlatform.cs" />
<Compile Include="CommonScenarios\XsltcTestSettings.cs" />
<Compile Include="XsltcModule.cs" />
@@ -33,16 +30,5 @@
<ProjectReference Include="$(CommonTestPath)\System\Xml\XmlCoreTest\XmlCoreTest.csproj" />
<ProjectReference Include="$(CommonTestPath)\System\Xml\XmlDiff\XmlDiff.csproj" />
</ItemGroup>
- <ItemGroup>
- <Content Include="Identity.xslt" />
- <Content Include="IdentityTransform.dll">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="IdentityTransform.xslt">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- <SubType>Designer</SubType>
- </Content>
- <Content Include="TestStylesheet.xslt" />
- </ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltcModule.cs b/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltcModule.cs
index bbf7e6be63..6155f5eed3 100644
--- a/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltcModule.cs
+++ b/src/System.Private.Xml/tests/Xslt/XsltCompiler/XsltcModule.cs
@@ -2,9 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Xunit;
-using Xunit.Abstractions;
-using System;
using System.IO;
using XmlCoreTest.Common;
using OLEDB.Test.ModuleCore;
@@ -14,7 +11,7 @@ namespace System.Xml.Tests
//[TestModule(Name = "Xsltc", Desc = "Xsltc Compiler Tests", Pri = 1)]
public class XsltcModule : CTestModule
{
- public static string TargetDirectory = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"xsltc\baseline");
+ public static string TargetDirectory = Path.Combine("TestFiles", FilePathUtil.GetTestDataPath(), "xsltc", "baseline");
public void CopyDataFiles(string sourcePath, string targetDir)
{
@@ -38,18 +35,11 @@ namespace System.Xml.Tests
int ret = base.Init(objParam);
// copy all the data files to working folder
- CopyDataFiles(Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), "xsltc"), TargetDirectory);
- CopyDataFiles(Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), "xsltc", "precompiled"), TargetDirectory);
- CopyDataFiles(Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), "xsltc", "baseline"), TargetDirectory);
+ CopyDataFiles(Path.Combine("TestFiles", FilePathUtil.GetTestDataPath(), "xsltc"), TargetDirectory);
+ CopyDataFiles(Path.Combine("TestFiles", FilePathUtil.GetTestDataPath(), "xsltc", "precompiled"), TargetDirectory);
+ CopyDataFiles(Path.Combine("TestFiles", FilePathUtil.GetTestDataPath(), "xsltc", "baseline"), TargetDirectory);
return ret;
}
-
- private static string GetDirectory()
- {
- string current = Directory.GetCurrentDirectory();
-
- return current.Contains(" ") ? "C:\\xml" : current;
- }
}
} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltScenarios/AspNet.cs b/src/System.Private.Xml/tests/Xslt/XsltScenarios/AspNet.cs
deleted file mode 100644
index a05bd82a0c..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltScenarios/AspNet.cs
+++ /dev/null
@@ -1,156 +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 OLEDB.Test.ModuleCore;
-using System.IO;
-using System.Net;
-
-namespace XsltScenarios
-{
- [TestCase(id = 1, Name = "AspNet using XslTransform", Desc = "Testing XslTransform functionality under ASP.NET Environment", Pri = 2, Param = "http://dpxmldtap1/security/xmlscenarios/xslt/")]
- [TestCase(id = 2, Name = "AspNet using XslCompiledTransform", Desc = "Testing XslCompiledTransform functionality under ASP.NET Environment", Pri = 2, Param = "http://dpxmldtap1/security/xmlscenarios/xslt/")]
- internal class AspNet : CTestCase
- {
- public AspNet()
- {
- }
-
- private string ExecuteUrl(string url)
- {
- //When id is 1, ver parameter is sent as v1 and in the ASP.NET Environment XslTransform is used
- //When id is 2, ver parameter is sent as v2 and in the ASP.NET Environment XslCompiledTransform is used
- if (id == 1)
- url = Param.ToString() + url + "&ver=v1";
- else if (id == 2)
- url = Param.ToString() + url + "&ver=v2";
-
- //Special if the url doesn't have any parameters other than ver then use ? instead of &
- if (url.IndexOf("?") == -1)
- url = url.Replace("&", "?");
-
- // Create a request for the URL.
- CError.WriteLine("Executing the URL " + url);
- WebRequest request = WebRequest.Create(url);
- // If required by the server, set the credentials.
- request.Credentials = CredentialCache.DefaultCredentials;
- // Get the response.
- HttpWebResponse response = (HttpWebResponse)request.GetResponse();
- // Display the status.
- // Console.WriteLine(response.StatusDescription);
- // Get the stream containing content returned by the server.
- Stream dataStream = response.GetResponseStream();
- // Open the stream using a StreamReader for easy access.
- StreamReader reader = new StreamReader(dataStream);
- // Read the content.
- string responseFromServer = reader.ReadToEnd();
- // Cleanup the streams and the response.
- reader.Close();
- dataStream.Close();
- response.Close();
-
- return responseFromServer;
- }
-
- [Variation(id = 1, Desc = "Basic ASP.NET Test, send params and pass them to Transform", Pri = 0, Param = "test1.aspx?firstname=foo&lastname=bar&age=20&dob=2/2/1985")]
- public int Test1()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result><firstname>foo</firstname><lastname>bar</lastname><age>20</age><dob>2/2/1985</dob></result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
-
- [Variation(id = 2, Desc = "Pass an extension object to Transform in ASP.NET", Pri = 0, Param = "test2.aspx")]
- public int Test2()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result>10</result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
-
- [Variation(id = 3, Desc = "Store compiled XSLT in Session state and use it from Session", Pri = 1, Param = "test3.aspx")]
- public int Test3()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result>Xslt in Session</result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
-
- [Variation(id = 4, Desc = "Use the Xslt stored in Session state in the previous test", Pri = 2, Param = "test4.aspx")]
- public int Test4()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result>Nothing is stored in Session</result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
-
- [Variation(id = 5, Desc = "Store the XSLT Object in Application state", Pri = 1, Param = "test5.aspx")]
- public int Test5()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result>Xslt in Application</result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
-
- [Variation(id = 6, Desc = "Use the Application XSLT Object stored in previous test", Pri = 2, Param = "test6.aspx")]
- public int Test6()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result>Xslt in Application</result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
-
- [Variation(id = 7, Desc = "Store the ArgumentList in the Application state", Pri = 2, Param = "test7.aspx?firstname=foo&lastname=bar&age=20&dob=2/2/1985")]
- public int Test7()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result><firstname>foo</firstname><lastname>bar</lastname><age>20</age><dob>2/2/1985</dob></result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
-
- [Variation(id = 8, Desc = "Use the Application XSLT and ArgList Objects stored in previous test", Pri = 2, Param = "test8.aspx")]
- public int Test8()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result><firstname>foo</firstname><lastname>bar</lastname><age>20</age><dob>2/2/1985</dob></result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
-
- [Variation(id = 9, Desc = "Add more parameters to the existing Argumentlist in Application state", Pri = 2, Param = "test9.aspx?gender=male")]
- public int Test9()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result><firstname>foo</firstname><lastname>bar</lastname><age>20</age><dob>2/2/1985</dob><gender>male</gender><state>WA</state></result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
-
- [Variation(id = 10, Desc = "Transform output to TextWriter(Response.Output)", Pri = 2, Param = "test10.aspx")]
- [Variation(id = 11, Desc = "Transform output to Stream(Response.OutputStream)", Pri = 2, Param = "test11.aspx")]
- public int Test10()
- {
- string url = CurVariation.Param.ToString();
- string actResult = ExecuteUrl(url);
- string expResult = "<result><firstname>foo</firstname><lastname>bar</lastname><age>20</age><dob>2/2/1985</dob></result>";
-
- return Utils.VerifyTest(actResult, expResult);
- }
- }
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltScenarios/EXslt.cs b/src/System.Private.Xml/tests/Xslt/XsltScenarios/EXslt.cs
deleted file mode 100644
index 0ad205fb49..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltScenarios/EXslt.cs
+++ /dev/null
@@ -1,379 +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 GotDotNet.Exslt;
-using Xunit;
-using Xunit.Abstractions;
-using System;
-using System.Globalization;
-using System.IO;
-using System.Security;
-using System.Xml;
-using System.Xml.XPath;
-using System.Xml.Xsl;
-using XmlCoreTest.Common;
-using System.Reflection;
-using System.Reflection.Emit;
-
-namespace System.Xml.Tests
-{
- //[TestCase(Name = "EXslt using XslCompiledTransform", Desc = "Compatibility of EXslt Objects using XsltV2 XsltArgumentList", Pri = 2, Param = "v2")]
- //[TestCase(Name = "EXslt using XslTransform", Desc = "Compatibility of EXslt Objects using XsltV1 XsltArgumentList", Pri = 2, Param = "v1")]
- public class EXslt //: CTestCase
- {
- private string _xmlFile = string.Empty;
- private string _xslFile = string.Empty;
- private string _baseline = string.Empty;
-
-#pragma warning disable 0618
- private XslTransform _xsltV1 = null;
-#pragma warning restore 0618
- private XslCompiledTransform _xsltV2 = null;
-
- private ITestOutputHelper _output;
- //Constructor
- public EXslt(ITestOutputHelper output)
- {
- _output = output;
- }
-
- //[Variation(id = 1, Desc = "Xslt Scenarios : common-node-set)]
- [InlineData("common-source.xml", "common-node-set.xsl", "valid", "common-node-set.xml", "v2")]
- //[Variation(id = 2, Desc = "Xslt Scenarios : common-object-type)]
- [InlineData("common-source.xml", "common-object-type.xsl", "valid", "common-object-type.xml", "v2")]
- //[Variation(id = 3, Desc = "Xslt Scenarios : datetime-add-duration)]
- [InlineData("datetime-source.xml", "datetime-add-duration.xsl", "valid", "datetime-add-duration.xml", "v2")]
- //[Variation(id = 4, Desc = "Xslt Scenarios : datetime-add)]
- ///[InlineData("datetime-source.xml", "datetime-add.xsl", "valid", "datetime-add.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 5, Desc = "Xslt Scenarios : datetime-avg)]
- [InlineData("datetime-source1.xml", "datetime-avg.xsl", "valid", "datetime-avg.xml", "v2")]
- //[Variation(id = 6, Desc = "Xslt Scenarios : datetime-date-time)]
- ///[InlineData("datetime-source.xml", "datetime-date-time.xsl", "valid", "datetime-date-time.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 7, Desc = "Xslt Scenarios : datetime-date)]
- [InlineData("datetime-source.xml", "datetime-date.xsl", "valid", "datetime-date.xml", "v2")]
- //[Variation(id = 8, Desc = "Xslt Scenarios : datetime-day-abbreviation)]
- [InlineData("datetime-source.xml", "datetime-day-abbreviation.xsl", "valid", "datetime-day-abbreviation.xml", "v2")]
- //[Variation(id = 10, Desc = "Xslt Scenarios : datetime-day-in-month)]
- [InlineData("datetime-source.xml", "datetime-day-in-month.xsl", "valid", "datetime-day-in-month.xml", "v2")]
- //[Variation(id = 11, Desc = "Xslt Scenarios : datetime-day-in-week)]
- [InlineData("datetime-source.xml", "datetime-day-in-week.xsl", "valid", "datetime-day-in-week.xml", "v2")]
- //[Variation(id = 12, Desc = "Xslt Scenarios : datetime-day-in-year)]
- [InlineData("datetime-source.xml", "datetime-day-in-year.xsl", "valid", "datetime-day-in-year.xml", "v2")]
- //[Variation(id = 13, Desc = "Xslt Scenarios : datetime-day-name)]
- [InlineData("datetime-source1.xml", "datetime-day-name.xsl", "valid", "datetime-day-name.xml", "v2")]
- //[Variation(id = 14, Desc = "Xslt Scenarios : datetime-day-name1)]
- [InlineData("datetime-source1.xml", "datetime-day-name1.xsl", "valid", "datetime-day-name1.xml", "v2")]
- //[Variation(id = 15, Desc = "Xslt Scenarios : datetime-day-of-week-in-month)]
- [InlineData("datetime-source.xml", "datetime-day-of-week-in-month.xsl", "valid", "datetime-day-of-week-in-month.xml", "v2")]
- //[Variation(id = 16, Desc = "Xslt Scenarios : datetime-difference)]
- [InlineData("datetime-source.xml", "datetime-difference.xsl", "valid", "datetime-difference.xml", "v2")]
- //[Variation(id = 17, Desc = "Xslt Scenarios : datetime-duration)]
- [InlineData("datetime-source.xml", "datetime-duration.xsl", "valid", "datetime-duration.xml", "v2")]
- //[Variation(id = 18, Desc = "Xslt Scenarios : datetime-format-date)]
- ///[InlineData("datetime-source.xml", "datetime-format-date.xsl", "valid", "datetime-format-date.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 19, Desc = "Xslt Scenarios : datetime-hour-in-day)]
- [InlineData("datetime-source.xml", "datetime-hour-in-day.xsl", "valid", "datetime-hour-in-day.xml", "v2")]
- //[Variation(id = 20, Desc = "Xslt Scenarios : datetime-leap-year)]
- [InlineData("datetime-source.xml", "datetime-leap-year.xsl", "valid", "datetime-leap-year.xml", "v2")]
- //[Variation(id = 21, Desc = "Xslt Scenarios : datetime-max)]
- [InlineData("datetime-source1.xml", "datetime-max.xsl", "valid", "datetime-max.xml", "v2")]
- //[Variation(id = 22, Desc = "Xslt Scenarios : datetime-min)]
- [InlineData("datetime-source1.xml", "datetime-min.xsl", "valid", "datetime-min.xml", "v2")]
- //[Variation(id = 23, Desc = "Xslt Scenarios : datetime-minute-in-hour)]
- [InlineData("datetime-source.xml", "datetime-minute-in-hour.xsl", "valid", "datetime-minute-in-hour.xml", "v2")]
- //[Variation(id = 24, Desc = "Xslt Scenarios : datetime-month-abbreviation)]
- [InlineData("datetime-source.xml", "datetime-month-abbreviation.xsl", "valid", "datetime-month-abbreviation.xml", "v2")]
- //[Variation(id = 25, Desc = "Xslt Scenarios : datetime-month-abbreviation1)]
- [InlineData("datetime-source1.xml", "datetime-month-abbreviation1.xsl", "valid", "datetime-month-abbreviation1.xml", "v2")]
- //[Variation(id = 26, Desc = "Xslt Scenarios : datetime-month-in-year)]
- [InlineData("datetime-source.xml", "datetime-month-in-year.xsl", "valid", "datetime-month-in-year.xml", "v2")]
- //[Variation(id = 27, Desc = "Xslt Scenarios : datetime-month-name)]
- [InlineData("datetime-source1.xml", "datetime-month-name.xsl", "valid", "datetime-month-name.xml", "v2")]
- //[Variation(id = 28, Desc = "Xslt Scenarios : datetime-month-name1)]
- [InlineData("datetime-source1.xml", "datetime-month-name1.xsl", "valid", "datetime-month-name1.xml", "v2")]
- //[Variation(id = 29, Desc = "Xslt Scenarios : datetime-parse-date)]
- [InlineData("datetime-source.xml", "datetime-parse-date.xsl", "valid", "datetime-parse-date.xml", "v2")]
- //[Variation(id = 30, Desc = "Xslt Scenarios : datetime-second-in-minute)]
- [InlineData("datetime-source.xml", "datetime-second-in-minute.xsl", "valid", "datetime-second-in-minute.xml", "v2")]
- //[Variation(id = 31, Desc = "Xslt Scenarios : datetime-seconds)]
- [InlineData("datetime-source.xml", "datetime-seconds.xsl", "valid", "datetime-seconds.xml", "v2")]
- //[Variation(id = 32, Desc = "Xslt Scenarios : datetime-sum)]
- [InlineData("datetime-source.xml", "datetime-sum.xsl", "valid", "datetime-sum.xml", "v2")]
- //[Variation(id = 33, Desc = "Xslt Scenarios : datetime-time)]
- [InlineData("datetime-source.xml", "datetime-time.xsl", "valid", "datetime-time.xml", "v2")]
- //[Variation(id = 34, Desc = "Xslt Scenarios : datetime-week-in-month)]
- [InlineData("datetime-source.xml", "datetime-week-in-month.xsl", "valid", "datetime-week-in-month.xml", "v2")]
- //[Variation(id = 35, Desc = "Xslt Scenarios : datetime-week-in-year)]
- [InlineData("datetime-source.xml", "datetime-week-in-year.xsl", "valid", "datetime-week-in-year.xml", "v2")]
- //[Variation(id = 36, Desc = "Xslt Scenarios : datetime-year)]
- [InlineData("datetime-source.xml", "datetime-year.xsl", "valid", "datetime-year.xml", "v2")]
- //[Variation(id = 37, Desc = "Xslt Scenarios : dynamic-evaluate)]
- [InlineData("datetime-source1.xml", "dynamic-evaluate.xsl", "invalid", "datetime-year.xml", "v2")]
- //[Variation(id = 38, Desc = "Xslt Scenarios : math-abs)]
- [InlineData("math-source.xml", "math-abs.xsl", "valid", "math-abs.xml", "v2")]
- //[Variation(id = 39, Desc = "Xslt Scenarios : math-acos)]
- [InlineData("math-source.xml", "math-acos.xsl", "valid", "math-acos2.xml", "v2")]
- //[Variation(id = 40, Desc = "Xslt Scenarios : math-asin)]
- [InlineData("math-source.xml", "math-asin.xsl", "valid", "math-asin2.xml", "v2")]
- //[Variation(id = 41, Desc = "Xslt Scenarios : math-atan)]
- [InlineData("math-source.xml", "math-atan.xsl", "valid", "math-atan_2.xml", "v2")]
- //[Variation(id = 42, Desc = "Xslt Scenarios : math-atan2)]
- [InlineData("math-source.xml", "math-atan2.xsl", "valid", "math-atan2_2.xml", "v2")]
- //[Variation(id = 43, Desc = "Xslt Scenarios : math-avg)]
- [InlineData("math-source1.xml", "math-avg.xsl", "valid", "math-avg.xml", "v2")]
- //[Variation(id = 44, Desc = "Xslt Scenarios : math-constant)]
- [InlineData("math-source.xml", "math-constant.xsl", "valid", "math-constant2.xml", "v2")]
- //[Variation(id = 45, Desc = "Xslt Scenarios : math-cos)]
- [InlineData("math-source.xml", "math-cos.xsl", "valid", "math-cos2.xml", "v2")]
- //[Variation(id = 46, Desc = "Xslt Scenarios : math-exp)]
- [InlineData("math-source.xml", "math-exp.xsl", "valid", "math-exp2.xml", "v2")]
- //[Variation(id = 47, Desc = "Xslt Scenarios : math-highest)]
- [InlineData("math-source.xml", "math-highest.xsl", "invalid", "math-exp2.xml", "v2")]
- //[Variation(id = 48, Desc = "Xslt Scenarios : math-log)]
- [InlineData("math-source.xml", "math-log.xsl", "valid", "math-log2.xml", "v2")]
- //[Variation(id = 49, Desc = "Xslt Scenarios : math-lowest)]
- [InlineData("math-source.xml", "math-lowest.xsl", "invalid", "math-log2.xml", "v2")]
- //[Variation(id = 50, Desc = "Xslt Scenarios : math-max)]
- [InlineData("math-source.xml", "math-max.xsl", "valid", "math-max.xml", "v2")]
- //[Variation(id = 51, Desc = "Xslt Scenarios : math-min)]
- [InlineData("math-source.xml", "math-min.xsl", "valid", "math-min.xml", "v2")]
- //[Variation(id = 52, Desc = "Xslt Scenarios : math-power)]
- [InlineData("math-source.xml", "math-power.xsl", "valid", "math-power.xml", "v2")]
- //[Variation(id = 53, Desc = "Xslt Scenarios : math-random)]
- [InlineData("math-source.xml", "math-random.xsl", "valid", "math-random.xml", "v2")]
- //[Variation(id = 54, Desc = "Xslt Scenarios : math-sin)]
- [InlineData("math-source.xml", "math-sin.xsl", "valid", "math-sin2.xml", "v2")]
- //[Variation(id = 55, Desc = "Xslt Scenarios : math-sqrt)]
- [InlineData("math-source.xml", "math-sqrt.xsl", "valid", "math-sqrt.xml", "v2")]
- //[Variation(id = 56, Desc = "Xslt Scenarios : math-tan)]
- [InlineData("math-source.xml", "math-tan.xsl", "valid", "math-tan2.xml", "v2")]
- //[Variation(id = 57, Desc = "Xslt Scenarios : random-sequence)]
- [InlineData("random-source.xml", "random-sequence.xslt", "valid", "random-sequence.xml", "v2")]
- //[Variation(id = 58, Desc = "Xslt Scenarios : regex-match)]
- ///[InlineData("regex-source.xml", "regex-match.xsl", "valid", "regex-match.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 59, Desc = "Xslt Scenarios : regex-replace)]
- ///[InlineData("regex-source.xml", "regex-replace.xsl", "valid", "regex-replace.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 60, Desc = "Xslt Scenarios : regex-test)]
- ///[InlineData("regex-source.xml", "regex-test.xsl", "valid", "regex-test.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 61, Desc = "Xslt Scenarios : regex-tokenize)]
- ///[InlineData("regex-source1.xml", "regex-tokenize.xsl", "valid", "regex-tokenize.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 62, Desc = "Xslt Scenarios : sets-difference)]
- [InlineData("sets-source.xml", "sets-difference.xsl", "invalid", "regex-tokenize.xml", "v2")]
- //[Variation(id = 63, Desc = "Xslt Scenarios : sets-distinct)]
- [InlineData("sets-source.xml", "sets-distinct.xsl", "invalid", "regex-tokenize.xml", "v2")]
- //[Variation(id = 64, Desc = "Xslt Scenarios : sets-has-same-node)]
- ///[InlineData("sets-source.xml", "sets-has-same-node.xsl", "valid", "sets-has-same-node.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 65, Desc = "Xslt Scenarios : sets-intersection)]
- [InlineData("sets-source.xml", "sets-intersection.xsl", "invalid", "sets-has-same-node.xml", "v2")]
- //[Variation(id = 66, Desc = "Xslt Scenarios : sets-leading)]
- [InlineData("sets-source.xml", "sets-leading.xsl", "invalid", "sets-has-same-node.xml", "v2")]
- //[Variation(id = 67, Desc = "Xslt Scenarios : sets-subset)]
- ///[InlineData("sets-source1.xml", "sets-subset.xsl", "valid", "sets-subset.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 68, Desc = "Xslt Scenarios : sets-trailing)]
- [InlineData("sets-source.xml", "sets-trailing.xsl", "invalid", "sets-subset.xml", "v2")]
- //[Variation(id = 69, Desc = "Xslt Scenarios : string-align)]
- [InlineData("string-source.xml", "string-align.xsl", "valid", "string-align.xml", "v2")]
- //[Variation(id = 70, Desc = "Xslt Scenarios : string-concat)]
- [InlineData("string-source.xml", "string-concat.xsl", "valid", "string-concat.xml", "v2")]
- //[Variation(id = 71, Desc = "Xslt Scenarios : string-decode-uri)]
- ///[InlineData("string-source.xml", "string-decode-uri.xsl", "valid", "string-decode-uri.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 72, Desc = "Xslt Scenarios : string-encode-uri)]
- [InlineData("string-source.xml", "string-encode-uri.xsl", "valid", "string-encode-uri.xml", "v2")]
- //[Variation(id = 73, Desc = "Xslt Scenarios : string-lowercase)]
- [InlineData("string-source1.xml", "string-lowercase.xsl", "valid", "string-lowercase.xml", "v2")]
- //[Variation(id = 74, Desc = "Xslt Scenarios : string-padding)]
- [InlineData("string-source.xml", "string-padding.xsl", "valid", "string-padding.xml", "v2")]
- //[Variation(id = 75, Desc = "Xslt Scenarios : string-replace)]
- [InlineData("string-source.xml", "string-replace.xsl", "valid", "string-replace.xml", "v2")]
- //[Variation(id = 76, Desc = "Xslt Scenarios : string-split)]
- ///[InlineData("string-source.xml", "string-split.xsl", "valid", "string-split.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 77, Desc = "Xslt Scenarios : string-tokenize)]
- ///[InlineData("string-source.xml", "string-tokenize.xsl", "valid", "string-tokenize.xml", "v2")] //disabled as references libraries not present on corefx
- //[Variation(id = 78, Desc = "Xslt Scenarios : string-uppercase)]
- [InlineData("string-source1.xml", "string-uppercase.xsl", "valid", "string-uppercase.xml", "v2")]
- [Theory]
- public void RunEXslTest(object param0, object param1, object param2, object param3, object param4)
- {
- string OutFile = "out_exslt.xml";
- string xmlFile = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltScenarios\EXslt\", param0.ToString());
- string xslFile = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltScenarios\EXslt\", param1.ToString());
- string resultType = param2.ToString();
- string baseLine = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltScenarios\EXslt\out\", param3.ToString());
-
-#pragma warning disable 0618
- if (param4.ToString() == "v1")
- _xsltV1 = new XslTransform();
-#pragma warning restore 0618
- else if (param4.ToString() == "v2")
- _xsltV2 = new XslCompiledTransform();
-
- Utils util = new Utils(_output);
-
- _output.WriteLine("XmlFile : file:\\\\" + xmlFile);
- _output.WriteLine("XslFile : file:\\\\" + xslFile);
-
- if (resultType == "valid")
- _output.WriteLine("BaseLine : file:\\\\" + baseLine);
- else
- _output.WriteLine("Test Type : Invalid");
-
- //Create the argument list and load the source document
- XsltArgumentList argList = InitArgumentList();
- XPathDocument doc = null;
-
- try
- {
- doc = new XPathDocument(xmlFile);
- }
- catch (Exception e)
- {
- _output.WriteLine(e.ToString());
- Assert.True(false);
- }
-
- //Delete the output file if it exists
-
- using (Stream stm = new FileStream(OutFile, FileMode.Create, FileAccess.ReadWrite))
- {
- try
- {
- if (param4.ToString() == "v1")
- {
- XPathDocument xslDoc = new XPathDocument(xslFile);
- //Evidence evidence = new Evidence();
- //evidence.AddHost(new Zone(SecurityZone.MyComputer));
- //evidence.AddHost(new Zone(SecurityZone.Intranet));
-
- _xsltV1.Load(xslDoc, new XmlUrlResolver()/*, evidence*/);
- _xsltV1.Transform(doc, argList, stm, new XmlUrlResolver());
- }
- else if (param4.ToString() == "v2")
- {
- _xsltV2.Load(xslFile, XsltSettings.TrustedXslt, new XmlUrlResolver());
- _xsltV2.Transform(doc, argList, stm);
- }
- stm.Dispose();
- util.VerifyResult(OutFile, baseLine);
- }
-
- //For V1 Transform
- catch (XPathException ex)
- {
- _output.WriteLine(ex.Message);
- if (resultType == "invalid")
- return;
- else
- Assert.True(false);
- }
-
- //For V2 Transform
- catch (XsltException ex)
- {
- _output.WriteLine(ex.Message);
- if (resultType == "invalid")
- return;
- else
- Assert.True(false);
- }
- }
- }
-
- public enum x
- {
- None = 0,
- Common = 1,
- DatesAndTimes = 2,
- }
-
- private XsltArgumentList InitArgumentList()
- {
- XsltArgumentList argList = new XsltArgumentList();
- x xinstance = new x();
- if (xinstance.ToString() == null)
- { Assert.True(false); }
- ExsltDatesAndTimes date = new ExsltDatesAndTimes();
- ExsltCommon exsl = new ExsltCommon();
- //ExsltFunctionNamespace func = new ExsltFunctionNamespace();
- ExsltMath math = new ExsltMath();
- ExsltRandom random = new ExsltRandom();
- ExsltRegularExpressions regexp = new ExsltRegularExpressions();
- ExsltSets set = new ExsltSets();
- ExsltStrings str = new ExsltStrings();
-
- GDNDatesAndTimes date2 = new GDNDatesAndTimes();
- GDNDynamic dyn2 = new GDNDynamic();
- GDNMath math2 = new GDNMath();
- GDNRegularExpressions regexp2 = new GDNRegularExpressions();
- GDNSets set2 = new GDNSets();
- GDNStrings str2 = new GDNStrings();
-
- //EXSLT Objects
- argList.AddExtensionObject("http://exslt.org/dates-and-times", date);
- //argList.AddExtensionObject("http://exslt.org/dynamic", dyn);
- argList.AddExtensionObject("http://exslt.org/common", exsl);
- //argList.AddExtensionObject("http://exslt.org/functions", func);
- argList.AddExtensionObject("http://exslt.org/math", math);
- argList.AddExtensionObject("http://exslt.org/random", random);
- argList.AddExtensionObject("http://exslt.org/regular-expressions", regexp);
- argList.AddExtensionObject("http://exslt.org/sets", set);
- argList.AddExtensionObject("http://exslt.org/strings", str);
-
- //GotDotNet Objects
- argList.AddExtensionObject("http://gotdotnet.com/exslt/dates-and-times", date2);
- argList.AddExtensionObject("http://gotdotnet.com/exslt/dynamic", dyn2);
- argList.AddExtensionObject("http://gotdotnet.com/exslt/math", math2);
- argList.AddExtensionObject("http://gotdotnet.com/exslt/regular-expressions", regexp2);
- argList.AddExtensionObject("http://gotdotnet.com/exslt/sets", set2);
- argList.AddExtensionObject("http://gotdotnet.com/exslt/strings", str2);
-
- return argList;
- }
-
-
- // Helper method to autogenerate Exslt xunit test data from XsltScenarios.xml
- public void AutoGenerateXunitTestData()
- {
- StreamWriter sw = new StreamWriter(new FileStream("XunitTestList.txt", FileMode.Create, FileAccess.Write));
-
- //Load the control file
- XmlDocument doc = new XmlDocument { XmlResolver = new XmlUrlResolver() };
- doc.Load("XsltScenarios.xml");
-
- XmlNodeList TestCases = doc.DocumentElement.SelectNodes("//Variation");
-
- foreach (XmlNode Variation in TestCases)
- {
- foreach (string ver in new string[] { "v1", "v2" })
- {
- string variationDesc = Variation.Attributes.GetNamedItem("Desc").Value;
- int variationId = Convert.ToInt32(Variation.Attributes.GetNamedItem("Id").Value);
-
- sw.WriteLine("//[Variation(id = " + variationId.ToString() + ", Desc = \"" + variationDesc + ")]");
-
- _xmlFile = Variation.SelectSingleNode("Data/Xml").InnerText;
- _xslFile = Variation.SelectSingleNode("Data/Xsl").InnerText;
-
- string ResultType = Variation.SelectSingleNode("Data/Result[1]/@Type").Value;
- ResultType = ResultType.ToLower();
-
- if (ResultType == "valid")
- {
- _baseline = Variation.SelectSingleNode("Data/Result").InnerText;
- try
- {
- _baseline = Variation.SelectSingleNode("Data/Result[@TransformType='" + ver + "']").InnerText; ;
- }
- catch (NullReferenceException)
- {
- }
- }
- sw.WriteLine("[InlineData(" + "\"" + _xmlFile + "\", " + "\"" + _xslFile + "\", " + "\"" + ResultType + "\", " + "\"" + _baseline + "\", " + "\"" + ver + "\"" + ")]");
- }
- }
-
- sw.WriteLine("[Theory]");
- sw.Dispose();
- }
- }
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltScenarios/GotDotNet.Exslt.dll b/src/System.Private.Xml/tests/Xslt/XsltScenarios/GotDotNet.Exslt.dll
deleted file mode 100644
index 06209b7af6..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltScenarios/GotDotNet.Exslt.dll
+++ /dev/null
Binary files differ
diff --git a/src/System.Private.Xml/tests/Xslt/XsltScenarios/Schematron.cs b/src/System.Private.Xml/tests/Xslt/XsltScenarios/Schematron.cs
deleted file mode 100644
index 7dda6bf18d..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltScenarios/Schematron.cs
+++ /dev/null
@@ -1,163 +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 Xunit;
-using Xunit.Abstractions;
-using System.Globalization;
-using System.IO;
-using System.Xml;
-using System.Xml.XPath;
-using System.Xml.Xsl;
-using XmlCoreTest.Common;
-
-namespace System.Xml.Tests
-{
- //[TestCase(Name = "Schematron with XslTransform", Desc = "Test the Schematron Stylesheets with XslTransform", Pri = 2, Param = "v1")]
- //[TestCase(Name = "Schematron with XslCompiledTransform", Desc = "Test the Schematron Stylesheets with XslCompiledTransform", Pri = 2, Param = "v2")]
- public class Schematron //: CTestCase
- {
- /*
- Refer to the page at http://www.xml.com/pub/a/2003/11/12/schematron.html for testing logic.
-
- Basically, Schematron schema (not XSD) is transformed using one of the Schematron stylesheets (basic) into a
- Validating XSLT which in turn is used to transform the actual XML Instance
-
- Parameter 1 to the test is Schematron Schema
- Parameter 2 to the test is the XML instance
- Parameter 3 is the Schematron Stylesheet (schematron-basic.xsl, schematron-message.xsl, schematron-report.xsl)
- */
-
-#pragma warning disable 0618
- private XslTransform _xsltV1 = null;
-#pragma warning restore 0618
- private XslCompiledTransform _xsltV2 = null;
-
- private TextWriter _sw = null;
- private string _schemaFile = string.Empty;
- private string _xmlFile = string.Empty;
- private string _xslFile = string.Empty;
- private string _baseline = string.Empty;
- private string _outFile = "out.xml";
- private Utils _utils;
-
- private ITestOutputHelper _output;
- public Schematron(ITestOutputHelper output)
- {
- _output = output;
- }
-
- private void Init(string schemaFile, string xmlFile, string xslType, string baseline, string ver)
- {
- _utils = new Utils(_output);
-
-#pragma warning disable 0618
- if (ver == "v1")
- _xsltV1 = new XslTransform();
-#pragma warning restore 0618
-
- else if (ver == "v2")
- _xsltV2 = new XslCompiledTransform();
-
- _schemaFile = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltScenarios\schematron\" + schemaFile);
- _xmlFile = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltScenarios\schematron\" + xmlFile);
- if (baseline == string.Empty)
- _baseline = string.Empty;
- else
- _baseline = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltScenarios\schematron\" + ver + baseline);
-
- switch (xslType.ToLower())
- {
- case "basic":
- default:
- _xslFile = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltScenarios\schematron\" + "schematron-basic.xsl");
- break;
-
- case "message":
- _xslFile = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltScenarios\schematron\" + "schematron-message.xsl");
- break;
-
- case "report":
- _xslFile = Path.Combine(@"TestFiles\", FilePathUtil.GetTestDataPath(), @"XsltScenarios\schematron\" + "schematron-report.xsl");
- break;
- }
-
- //Delete the output file if it exists
- if (File.Exists(_outFile))
- File.Delete(_outFile);
- }
-
- private void GenerateValidatingXslt(string ver)
- {
- //Write the output to a string (using TextWriter)
- _sw = new StringWriter();
- _output.WriteLine("Generating Validating XSLT using Schematron schema ...");
-
- if (ver == "v1")
- {
- _xsltV1.Load(_xslFile, new XmlUrlResolver());
- XPathDocument doc = new XPathDocument(_schemaFile);
- _xsltV1.Transform(doc, null, _sw);
- }
- else if (ver == "v2")
- {
- _xsltV2.Load(_xslFile, new XsltSettings(), new XmlUrlResolver());
- _xsltV2.Transform(_schemaFile, null, _sw);
- }
- }
-
- private void ValidateInstance(string ver)
- {
- XmlReader xr = XmlReader.Create(new StringReader(_sw.ToString()));
- _output.WriteLine("Validating XML Instance using Validating XSLT ...");
-
- if (ver == "v1")
- {
- _xsltV1.Load(xr, new XmlUrlResolver());
- _xsltV1.Transform(_xmlFile, _outFile);
- }
- else if (ver == "v2")
- {
- _xsltV2.Load(xr, new XsltSettings(), new XmlUrlResolver());
- _xsltV2.Transform(_xmlFile, _outFile);
- }
-
- _utils.WriteFile(_outFile);
- }
-
- //BinCompat TODO: Re-write and re-enable checksum tests
- ////[Variation(id = 1, Desc = "Testing the XML Instance to have Male Gender when Title is Mr, using Basic Schematron Stylesheet", Pri = 2, Params = new object[] { "TestSchema.xml", "Test1.xml", "Basic", "Test1.txt" })]
- //[InlineData("TestSchema.xml", "Test1.xml", "Basic", "Test1.txt", "v1")]
- //[InlineData("TestSchema.xml", "Test1.xml", "Basic", "Test1.txt", "v2")]
- ////[Variation(id = 2, Desc = "Testing the XML Instance to have Male Gender when Title is Mr, using Message Schematron Stylesheet", Pri = 0, Params = new object[] { "TestSchema.xml", "Test1.xml", "Message", "" })]
- //[InlineData("TestSchema.xml", "Test1.xml", "Message", "", "v1")]
- //[InlineData("TestSchema.xml", "Test1.xml", "Message", "", "v2")]
- ////[Variation(id = 4, Desc = "Testing the XML Instance for a mandatory Title attribute, using Basic Schematron Stylesheet", Pri = 2, Params = new object[] { "TestSchema.xml", "Test4.xml", "Basic", "Test4.txt" })]
- //[InlineData("TestSchema.xml", "Test4.xml", "Basic", "Test4.txt", "v1")]
- //[InlineData("TestSchema.xml", "Test4.xml", "Basic", "Test4.txt", "v2")]
- ////[Variation(id = 5, Desc = "Testing the XML Instance for a mandatory Title attribute, using Message Schematron Stylesheet", Pri = 0, Params = new object[] { "TestSchema.xml", "Test4.xml", "Message", "" })]
- //[InlineData("TestSchema.xml", "Test4.xml", "Message", "", "v1")]
- //[InlineData("TestSchema.xml", "Test4.xml", "Message", "", "v2")]
- ////[Variation(id = 7, Desc = "Testing the XML Instance for unexpected children, using Basic Schematron Stylesheet", Pri = 2, Params = new object[] { "TestSchema.xml", "Test7.xml", "Basic", "Test7.txt" })]
- //[InlineData("TestSchema.xml", "Test7.xml", "Basic", "Test7.txt", "v1")]
- //[InlineData("TestSchema.xml", "Test7.xml", "Basic", "Test7.txt", "v2")]
- ////[Variation(id = 8, Desc = "Testing the XML Instance for unexpected children, using Message Schematron Stylesheet", Pri = 0, Params = new object[] { "TestSchema.xml", "Test7.xml", "Message", "" })]
- //[InlineData("TestSchema.xml", "Test7.xml", "Message", "", "v1")]
- //[InlineData("TestSchema.xml", "Test7.xml", "Message", "", "v2")]
- ////[Variation(id = 10, Desc = "Testing the XML Instance for children sequence, using Basic Schematron Stylesheet", Pri = 2, Params = new object[] { "TestSchema.xml", "Test10.xml", "Basic", "Test10.txt" })]
- //[InlineData("TestSchema.xml", "Test10.xml", "Basic", "Test10.txt", "v1")]
- //[InlineData("TestSchema.xml", "Test10.xml", "Basic", "Test10.txt", "v2")]
- ////[Variation(id = 11, Desc = "Testing the XML Instance for children sequence, using Message Schematron Stylesheet", Pri = 0, Params = new object[] { "TestSchema.xml", "Test10.xml", "Message", "" })]
- //[InlineData("TestSchema.xml", "Test10.xml", "Message", "", "v1")]
- //[InlineData("TestSchema.xml", "Test10.xml", "Message", "", "v2")]
- [Theory]
- public void SchematronTest(object param0, object param1, object param2, object param3, object param4)
- {
- Init(param0.ToString(), param1.ToString(), param2.ToString(), param3.ToString(), param4.ToString());
-
- GenerateValidatingXslt(param4.ToString());
- ValidateInstance(param4.ToString());
- _utils.VerifyChecksum(_outFile, _baseline);
- }
- }
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltScenarios/Utils.cs b/src/System.Private.Xml/tests/Xslt/XsltScenarios/Utils.cs
deleted file mode 100644
index 03a955b1eb..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltScenarios/Utils.cs
+++ /dev/null
@@ -1,184 +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 Xunit;
-using Xunit.Abstractions;
-using System;
-using System.Globalization;
-using System.IO;
-using System.Xml;
-using System.Xml.XmlDiff;
-
-namespace System.Xml.Tests
-{
- internal class Utils //: CTestCase
- {
- private static ITestOutputHelper s_output;
- public Utils(ITestOutputHelper output)
- {
- s_output = output;
- }
-
- public static void VerifyTest(string actResult, string expResult)
- {
- XmlDiff.XmlDiff diff = new XmlDiff.XmlDiff();
- diff.Option = XmlDiffOption.IgnoreEmptyElement | XmlDiffOption.IgnoreAttributeOrder;
-
- XmlTextReader xrActual = new XmlTextReader(new StringReader(actResult));
- XmlTextReader xrExpected = new XmlTextReader(new StringReader(expResult));
-
- bool bResult = false;
-
- try
- {
- bResult = diff.Compare(xrActual, xrExpected);
- }
- catch (Exception e)
- {
- bResult = false;
- s_output.WriteLine("Exception thrown in XmlDiff compare!");
- s_output.WriteLine(e.ToString());
- }
- finally
- {
- if (xrActual != null) xrActual.Dispose();
- if (xrExpected != null) xrExpected.Dispose();
- }
-
- s_output.WriteLine("Expected : " + expResult);
- s_output.WriteLine("Actual : " + actResult);
-
- if (bResult)
- return;
- else
- Assert.True(false);
- }
-
- public void VerifyResult(string actualFile, string baselineFile)
- {
- XmlDiff.XmlDiff diff = new XmlDiff.XmlDiff();
- diff.Option = XmlDiffOption.IgnoreEmptyElement | XmlDiffOption.IgnoreAttributeOrder;
-
- XmlParserContext context = new XmlParserContext(new NameTable(), null, "", XmlSpace.None);
-
- using (FileStream fsActual = new FileStream(actualFile, FileMode.Open, FileAccess.Read))
- {
- using (FileStream fsExpected = new FileStream(baselineFile, FileMode.Open, FileAccess.Read))
- {
- XmlTextReader xrActual = new XmlTextReader(fsActual, XmlNodeType.Element, context);
- XmlTextReader xrExpected = new XmlTextReader(fsExpected, XmlNodeType.Element, context);
-
- bool bResult = false;
-
- try
- {
- bResult = diff.Compare(xrActual, xrExpected);
- }
- catch (Exception e)
- {
- bResult = false;
- s_output.WriteLine("Exception thrown in XmlDiff compare!");
- s_output.WriteLine(e.ToString());
- }
- s_output.WriteLine("Actual result: ");
- this.WriteFile(actualFile);
-
- if (bResult)
- return;
- else
- {
- s_output.WriteLine("Mismatch in XmlDiff");
- Assert.True(false);
- }
- }
- }
- }
-
- public void WriteFile(string fileName)
- {
- Char[] rgBuffer = new Char[4096];
- StreamReader fs = null;
-
- fs = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read));
-
- int cBytesRead = fs.Read(rgBuffer, 0, 4096);
- while (cBytesRead > 0)
- {
- //_output.WriteLine(new string(rgBuffer));
- cBytesRead = fs.Read(rgBuffer, 0, 4096);
- }
-
- if (fs != null) fs.Dispose();
- s_output.WriteLine("");
- }
-
- public void VerifyChecksum(string outFile, string baseline)
- {
- string actualChecksum = "0"; //For no output (empty string) checksums are 0
- string expectedCheckSum = "0"; //For no output (empty string) checksums are 0
-
- if (outFile != string.Empty)
- actualChecksum = CalcChecksum(outFile);
- if (baseline != string.Empty)
- expectedCheckSum = CalcChecksum(baseline);
-
- if (expectedCheckSum == actualChecksum)
- return;
- else
- {
- s_output.WriteLine("Actual checksum: {0}, Expected checksum: {1}", actualChecksum, expectedCheckSum);
- s_output.WriteLine("Actual result: ");
- WriteFile(outFile);
- Assert.True(false);
- }
- }
-
- public string CalcChecksum(string fileName)
- {
- Decimal dResult = 0; // Numerical value of the checksum
- int i = 0; // Generic counter
- int cBytesRead = 1; // # of bytes read at one time
- int cTotalRead = 0; // Total # of bytes read so far
- Decimal dEndBuffer = 0; // Buffer to remove from the end (This is necessary because
- // notepad adds CR/LF onto the end of every file)
- Char[] rgBuffer = new Char[4096];
-
- string xml = "";
-
- StreamReader fs = null;
- try
- {
- fs = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read));
- cBytesRead = fs.Read(rgBuffer, 0, 4096);
- while (cBytesRead > 0)
- {
- // Keep XML property up to date
- xml = String.Concat(xml, new String(rgBuffer, 0, cBytesRead));
-
- // Calculate the checksum
- for (i = 0; i < cBytesRead; i++)
- {
- dResult += Math.Round((Decimal)(rgBuffer[i] / (cTotalRead + i + 1.0)), 10);
- }
-
- cTotalRead += cBytesRead;
- dEndBuffer = 0;
-
- // Keep reading (in case file is bigger than 4K)
- cBytesRead = fs.Read(rgBuffer, 0, 4096);
- }
- }
- catch (Exception ex)
- {
- s_output.WriteLine(ex.ToString());
- return "";
- }
- finally
- {
- if (fs != null) fs.Dispose();
- }
- return Convert.ToString(dResult - dEndBuffer, NumberFormatInfo.InvariantInfo);
- }
- }
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltScenarios/XsltScenarios.cs b/src/System.Private.Xml/tests/Xslt/XsltScenarios/XsltScenarios.cs
deleted file mode 100644
index 7d73d57551..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltScenarios/XsltScenarios.cs
+++ /dev/null
@@ -1,47 +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 Xunit;
-using Xunit.Abstractions;
-using System;
-using OLEDB.Test.ModuleCore;
-
-namespace System.Xml.Tests
-{
- public static class TestInfo
- {
- public static string ControlFile = string.Empty;
- public static string Path = string.Empty;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
- // CXsltScenarios (test module)
- //
- ///////////////////////////////////////////////////////////////////////////////////
- //[TestModule(Desc = "This test module tests different XSLT Scenarios listed in XML Scenarios doc")]
- public class CXsltScenarios : CTestModule
- {
- //Contstructor
- public CXsltScenarios()
- {
- }
-
- public override void DetermineTestCases()
- {
- base.DetermineTestCases();
- }
-
- public String InitStringValue(String str)
- {
- throw new NotImplementedException();
- //object obj = CModInfo.GetOption(str);
-
- //if (obj == null)
- //{
- // return String.Empty;
- //}
- //return obj.ToString();
- }
- }
-} \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltScenarios/XsltScenarios.xml b/src/System.Private.Xml/tests/Xslt/XsltScenarios/XsltScenarios.xml
deleted file mode 100644
index bb9be9c103..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltScenarios/XsltScenarios.xml
+++ /dev/null
@@ -1,568 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<TestModule Name="XSLT" Desc="XsltScenarios Tests" Created="2/22/05" Modified="1/18/06">
- <Owner Alias="alexkr" Type="test" />
- <Data>
- <FilePath>$(DataPath)\TestData\XsltScenarios\</FilePath>
- <BaselinePath>out</BaselinePath>
- </Data>
- <TestCase Name="Scenarios" Desc="Testcase for XsltScenarios">
- <Variation Id="1" Pri="2" Desc="Xslt Scenarios : common-node-set">
- <Data>
- <Xml>common-source.xml</Xml>
- <Xsl>common-node-set.xsl</Xsl>
- <Result Type="Valid">common-node-set.xml</Result>
- </Data>
- </Variation>
- <Variation Id="2" Pri="2" Desc="Xslt Scenarios : common-object-type">
- <Data>
- <Xml>common-source.xml</Xml>
- <Xsl>common-object-type.xsl</Xsl>
- <Result Type="Valid">common-object-type.xml</Result>
- </Data>
- </Variation>
- <Variation Id="3" Pri="2" Desc="Xslt Scenarios : datetime-add-duration">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-add-duration.xsl</Xsl>
- <Result Type="Valid">datetime-add-duration.xml</Result>
- </Data>
- </Variation>
- <Variation Id="4" Pri="2" Desc="Xslt Scenarios : datetime-add">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-add.xsl</Xsl>
- <Result Type="Valid">datetime-add.xml</Result>
- </Data>
- </Variation>
- <Variation Id="5" Pri="2" Desc="Xslt Scenarios : datetime-avg">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>datetime-avg.xsl</Xsl>
- <Result Type="Valid">datetime-avg.xml</Result>
- </Data>
- </Variation>
- <Variation Id="6" Pri="2" Desc="Xslt Scenarios : datetime-date-time">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-date-time.xsl</Xsl>
- <Result Type="Valid">datetime-date-time.xml</Result>
- </Data>
- </Variation>
- <Variation Id="7" Pri="2" Desc="Xslt Scenarios : datetime-date">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-date.xsl</Xsl>
- <Result Type="Valid">datetime-date.xml</Result>
- </Data>
- </Variation>
- <Variation Id="8" Pri="2" Desc="Xslt Scenarios : datetime-day-abbreviation">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-day-abbreviation.xsl</Xsl>
- <Result Type="Valid">datetime-day-abbreviation.xml</Result>
- </Data>
- </Variation>
- <!-- Day name abbreviation has different value between win7 and win8. e.g. in Swedish, monday is 'on' on win7, and 'ons' on win8
- <Variation Id="9" Pri="2" Desc="Xslt Scenarios : datetime-day-abbreviation1">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>datetime-day-abbreviation1.xsl</Xsl>
- <Result Type="Valid">datetime-day-abbreviation1.xml</Result>
- </Data>
- </Variation> -->
- <Variation Id="10" Pri="2" Desc="Xslt Scenarios : datetime-day-in-month">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-day-in-month.xsl</Xsl>
- <Result Type="Valid">datetime-day-in-month.xml</Result>
- </Data>
- </Variation>
- <Variation Id="11" Pri="2" Desc="Xslt Scenarios : datetime-day-in-week">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-day-in-week.xsl</Xsl>
- <Result Type="Valid">datetime-day-in-week.xml</Result>
- </Data>
- </Variation>
- <Variation Id="12" Pri="2" Desc="Xslt Scenarios : datetime-day-in-year">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-day-in-year.xsl</Xsl>
- <Result Type="Valid">datetime-day-in-year.xml</Result>
- </Data>
- </Variation>
- <Variation Id="13" Pri="2" Desc="Xslt Scenarios : datetime-day-name">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>datetime-day-name.xsl</Xsl>
- <Result Type="Valid">datetime-day-name.xml</Result>
- </Data>
- </Variation>
- <Variation Id="14" Pri="2" Desc="Xslt Scenarios : datetime-day-name1">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>datetime-day-name1.xsl</Xsl>
- <Result Type="Valid">datetime-day-name1.xml</Result>
- </Data>
- </Variation>
- <Variation Id="15" Pri="2" Desc="Xslt Scenarios : datetime-day-of-week-in-month">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-day-of-week-in-month.xsl</Xsl>
- <Result Type="Valid">datetime-day-of-week-in-month.xml</Result>
- </Data>
- </Variation>
- <Variation Id="16" Pri="2" Desc="Xslt Scenarios : datetime-difference">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-difference.xsl</Xsl>
- <Result Type="Valid">datetime-difference.xml</Result>
- </Data>
- </Variation>
- <Variation Id="17" Pri="2" Desc="Xslt Scenarios : datetime-duration">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-duration.xsl</Xsl>
- <Result Type="Valid">datetime-duration.xml</Result>
- </Data>
- </Variation>
- <Variation Id="18" Pri="2" Desc="Xslt Scenarios : datetime-format-date">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-format-date.xsl</Xsl>
- <Result Type="Valid">datetime-format-date.xml</Result>
- </Data>
- </Variation>
- <Variation Id="19" Pri="2" Desc="Xslt Scenarios : datetime-hour-in-day">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-hour-in-day.xsl</Xsl>
- <Result Type="Valid">datetime-hour-in-day.xml</Result>
- </Data>
- </Variation>
- <Variation Id="20" Pri="2" Desc="Xslt Scenarios : datetime-leap-year">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-leap-year.xsl</Xsl>
- <Result Type="Valid">datetime-leap-year.xml</Result>
- </Data>
- </Variation>
- <Variation Id="21" Pri="2" Desc="Xslt Scenarios : datetime-max">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>datetime-max.xsl</Xsl>
- <Result Type="Valid">datetime-max.xml</Result>
- </Data>
- </Variation>
- <Variation Id="22" Pri="2" Desc="Xslt Scenarios : datetime-min">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>datetime-min.xsl</Xsl>
- <Result Type="Valid">datetime-min.xml</Result>
- </Data>
- </Variation>
- <Variation Id="23" Pri="2" Desc="Xslt Scenarios : datetime-minute-in-hour">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-minute-in-hour.xsl</Xsl>
- <Result Type="Valid">datetime-minute-in-hour.xml</Result>
- </Data>
- </Variation>
- <Variation Id="24" Pri="2" Desc="Xslt Scenarios : datetime-month-abbreviation">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-month-abbreviation.xsl</Xsl>
- <Result Type="Valid">datetime-month-abbreviation.xml</Result>
- </Data>
- </Variation>
- <Variation Id="25" Pri="2" Desc="Xslt Scenarios : datetime-month-abbreviation1">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>datetime-month-abbreviation1.xsl</Xsl>
- <Result Type="Valid">datetime-month-abbreviation1.xml</Result>
- </Data>
- </Variation>
- <Variation Id="26" Pri="2" Desc="Xslt Scenarios : datetime-month-in-year">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-month-in-year.xsl</Xsl>
- <Result Type="Valid">datetime-month-in-year.xml</Result>
- </Data>
- </Variation>
- <Variation Id="27" Pri="2" Desc="Xslt Scenarios : datetime-month-name">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>datetime-month-name.xsl</Xsl>
- <Result Type="Valid">datetime-month-name.xml</Result>
- </Data>
- </Variation>
- <Variation Id="28" Pri="2" Desc="Xslt Scenarios : datetime-month-name1">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>datetime-month-name1.xsl</Xsl>
- <Result Type="Valid">datetime-month-name1.xml</Result>
- </Data>
- </Variation>
- <Variation Id="29" Pri="2" Desc="Xslt Scenarios : datetime-parse-date">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-parse-date.xsl</Xsl>
- <Result Type="Valid">datetime-parse-date.xml</Result>
- </Data>
- </Variation>
- <Variation Id="30" Pri="2" Desc="Xslt Scenarios : datetime-second-in-minute">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-second-in-minute.xsl</Xsl>
- <Result Type="Valid">datetime-second-in-minute.xml</Result>
- </Data>
- </Variation>
- <Variation Id="31" Pri="2" Desc="Xslt Scenarios : datetime-seconds">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-seconds.xsl</Xsl>
- <Result Type="Valid">datetime-seconds.xml</Result>
- </Data>
- </Variation>
- <Variation Id="32" Pri="2" Desc="Xslt Scenarios : datetime-sum">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-sum.xsl</Xsl>
- <Result Type="Valid">datetime-sum.xml</Result>
- </Data>
- </Variation>
- <Variation Id="33" Pri="2" Desc="Xslt Scenarios : datetime-time">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-time.xsl</Xsl>
- <Result Type="Valid">datetime-time.xml</Result>
- </Data>
- </Variation>
- <Variation Id="34" Pri="2" Desc="Xslt Scenarios : datetime-week-in-month">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-week-in-month.xsl</Xsl>
- <Result Type="Valid">datetime-week-in-month.xml</Result>
- </Data>
- </Variation>
- <Variation Id="35" Pri="2" Desc="Xslt Scenarios : datetime-week-in-year">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-week-in-year.xsl</Xsl>
- <Result Type="Valid">datetime-week-in-year.xml</Result>
- </Data>
- </Variation>
- <Variation Id="36" Pri="2" Desc="Xslt Scenarios : datetime-year">
- <Data>
- <Xml>datetime-source.xml</Xml>
- <Xsl>datetime-year.xsl</Xsl>
- <Result Type="Valid">datetime-year.xml</Result>
- </Data>
- </Variation>
- <Variation Id="37" Pri="2" Desc="Xslt Scenarios : dynamic-evaluate">
- <Data>
- <Xml>datetime-source1.xml</Xml>
- <Xsl>dynamic-evaluate.xsl</Xsl>
- <Result Type="Invalid" ExceptionId="XsltException" />
- </Data>
- </Variation>
- <Variation Id="38" Pri="2" Desc="Xslt Scenarios : math-abs">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-abs.xsl</Xsl>
- <Result Type="Valid">math-abs.xml</Result>
- </Data>
- </Variation>
- <Variation Id="39" Pri="2" Desc="Xslt Scenarios : math-acos">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-acos.xsl</Xsl>
- <Result Type="Valid">math-acos.xml</Result>
- <Result Type="Valid" TransformType="v2">math-acos2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="40" Pri="2" Desc="Xslt Scenarios : math-asin">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-asin.xsl</Xsl>
- <Result Type="Valid">math-asin.xml</Result>
- <Result Type="Valid" TransformType="v2">math-asin2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="41" Pri="2" Desc="Xslt Scenarios : math-atan">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-atan.xsl</Xsl>
- <Result Type="Valid">math-atan.xml</Result>
- <Result Type="Valid" TransformType="v2">math-atan_2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="42" Pri="2" Desc="Xslt Scenarios : math-atan2">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-atan2.xsl</Xsl>
- <Result Type="Valid">math-atan2.xml</Result>
- <Result Type="Valid" TransformType="v2">math-atan2_2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="43" Pri="2" Desc="Xslt Scenarios : math-avg">
- <Data>
- <Xml>math-source1.xml</Xml>
- <Xsl>math-avg.xsl</Xsl>
- <Result Type="Valid">math-avg.xml</Result>
- </Data>
- </Variation>
- <Variation Id="44" Pri="2" Desc="Xslt Scenarios : math-constant">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-constant.xsl</Xsl>
- <Result Type="Valid">math-constant.xml</Result>
- <Result Type="Valid" TransformType="v2">math-constant2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="45" Pri="2" Desc="Xslt Scenarios : math-cos">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-cos.xsl</Xsl>
- <Result Type="Valid">math-cos.xml</Result>
- <Result Type="Valid" TransformType="v2">math-cos2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="46" Pri="2" Desc="Xslt Scenarios : math-exp">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-exp.xsl</Xsl>
- <Result Type="Valid">math-exp.xml</Result>
- <Result Type="Valid" TransformType="v2">math-exp2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="47" Pri="2" Desc="Xslt Scenarios : math-highest">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-highest.xsl</Xsl>
- <Result Type="Invalid" ExceptionId="XsltException" />
- </Data>
- </Variation>
- <Variation Id="48" Pri="2" Desc="Xslt Scenarios : math-log">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-log.xsl</Xsl>
- <Result Type="Valid">math-log.xml</Result>
- <Result Type="Valid" TransformType="v2">math-log2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="49" Pri="2" Desc="Xslt Scenarios : math-lowest">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-lowest.xsl</Xsl>
- <Result Type="Invalid" ExceptionId="XsltException" />
- </Data>
- </Variation>
- <Variation Id="50" Pri="2" Desc="Xslt Scenarios : math-max">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-max.xsl</Xsl>
- <Result Type="Valid">math-max.xml</Result>
- </Data>
- </Variation>
- <Variation Id="51" Pri="2" Desc="Xslt Scenarios : math-min">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-min.xsl</Xsl>
- <Result Type="Valid">math-min.xml</Result>
- </Data>
- </Variation>
- <Variation Id="52" Pri="2" Desc="Xslt Scenarios : math-power">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-power.xsl</Xsl>
- <Result Type="Valid">math-power.xml</Result>
- </Data>
- </Variation>
- <Variation Id="53" Pri="2" Desc="Xslt Scenarios : math-random">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-random.xsl</Xsl>
- <Result Type="Valid">math-random.xml</Result>
- </Data>
- </Variation>
- <Variation Id="54" Pri="2" Desc="Xslt Scenarios : math-sin">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-sin.xsl</Xsl>
- <Result Type="Valid">math-sin.xml</Result>
- <Result Type="Valid" TransformType="v2">math-sin2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="55" Pri="2" Desc="Xslt Scenarios : math-sqrt">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-sqrt.xsl</Xsl>
- <Result Type="Valid">math-sqrt.xml</Result>
- </Data>
- </Variation>
- <Variation Id="56" Pri="2" Desc="Xslt Scenarios : math-tan">
- <Data>
- <Xml>math-source.xml</Xml>
- <Xsl>math-tan.xsl</Xsl>
- <Result Type="Valid">math-tan.xml</Result>
- <Result Type="Valid" TransformType="v2">math-tan2.xml</Result>
- </Data>
- </Variation>
- <Variation Id="57" Pri="2" Desc="Xslt Scenarios : random-sequence">
- <Data>
- <Xml>random-source.xml</Xml>
- <Xsl>random-sequence.xslt</Xsl>
- <Result Type="Valid">random-sequence.xml</Result>
- <!--Result Type="Invalid" ExceptionId="XsltException" /-->
- </Data>
- </Variation>
- <Variation Id="58" Pri="2" Desc="Xslt Scenarios : regex-match">
- <Data>
- <Xml>regex-source.xml</Xml>
- <Xsl>regex-match.xsl</Xsl>
- <Result Type="Valid">regex-match.xml</Result>
- </Data>
- </Variation>
- <Variation Id="59" Pri="2" Desc="Xslt Scenarios : regex-replace">
- <Data>
- <Xml>regex-source.xml</Xml>
- <Xsl>regex-replace.xsl</Xsl>
- <Result Type="Valid">regex-replace.xml</Result>
- </Data>
- </Variation>
- <Variation Id="60" Pri="2" Desc="Xslt Scenarios : regex-test">
- <Data>
- <Xml>regex-source.xml</Xml>
- <Xsl>regex-test.xsl</Xsl>
- <Result Type="Valid">regex-test.xml</Result>
- </Data>
- </Variation>
- <Variation Id="61" Pri="2" Desc="Xslt Scenarios : regex-tokenize">
- <Data>
- <Xml>regex-source1.xml</Xml>
- <Xsl>regex-tokenize.xsl</Xsl>
- <Result Type="Valid">regex-tokenize.xml</Result>
- </Data>
- </Variation>
- <Variation Id="62" Pri="2" Desc="Xslt Scenarios : sets-difference">
- <Data>
- <Xml>sets-source.xml</Xml>
- <Xsl>sets-difference.xsl</Xsl>
- <Result Type="Invalid" ExceptionId="XsltException" />
- </Data>
- </Variation>
- <Variation Id="63" Pri="2" Desc="Xslt Scenarios : sets-distinct">
- <Data>
- <Xml>sets-source.xml</Xml>
- <Xsl>sets-distinct.xsl</Xsl>
- <Result Type="Invalid" ExceptionId="XsltException" />
- </Data>
- </Variation>
- <Variation Id="64" Pri="2" Desc="Xslt Scenarios : sets-has-same-node">
- <Data>
- <Xml>sets-source.xml</Xml>
- <Xsl>sets-has-same-node.xsl</Xsl>
- <Result Type="Valid">sets-has-same-node.xml</Result>
- </Data>
- </Variation>
- <Variation Id="65" Pri="2" Desc="Xslt Scenarios : sets-intersection">
- <Data>
- <Xml>sets-source.xml</Xml>
- <Xsl>sets-intersection.xsl</Xsl>
- <Result Type="Invalid" ExceptionId="XsltException" />
- </Data>
- </Variation>
- <Variation Id="66" Pri="2" Desc="Xslt Scenarios : sets-leading">
- <Data>
- <Xml>sets-source.xml</Xml>
- <Xsl>sets-leading.xsl</Xsl>
- <Result Type="Invalid" ExceptionId="XsltException" />
- </Data>
- </Variation>
- <Variation Id="67" Pri="2" Desc="Xslt Scenarios : sets-subset">
- <Data>
- <Xml>sets-source1.xml</Xml>
- <Xsl>sets-subset.xsl</Xsl>
- <Result Type="Valid">sets-subset.xml</Result>
- </Data>
- </Variation>
- <Variation Id="68" Pri="2" Desc="Xslt Scenarios : sets-trailing">
- <Data>
- <Xml>sets-source.xml</Xml>
- <Xsl>sets-trailing.xsl</Xsl>
- <Result Type="Invalid" ExceptionId="XsltException" />
- </Data>
- </Variation>
- <Variation Id="69" Pri="2" Desc="Xslt Scenarios : string-align">
- <Data>
- <Xml>string-source.xml</Xml>
- <Xsl>string-align.xsl</Xsl>
- <Result Type="Valid">string-align.xml</Result>
- </Data>
- </Variation>
- <Variation Id="70" Pri="2" Desc="Xslt Scenarios : string-concat">
- <Data>
- <Xml>string-source.xml</Xml>
- <Xsl>string-concat.xsl</Xsl>
- <Result Type="Valid">string-concat.xml</Result>
- </Data>
- </Variation>
- <Variation Id="71" Pri="2" Desc="Xslt Scenarios : string-decode-uri">
- <Data>
- <Xml>string-source.xml</Xml>
- <Xsl>string-decode-uri.xsl</Xsl>
- <Result Type="Valid">string-decode-uri.xml</Result>
- </Data>
- </Variation>
- <Variation Id="72" Pri="2" Desc="Xslt Scenarios : string-encode-uri">
- <Data>
- <Xml>string-source.xml</Xml>
- <Xsl>string-encode-uri.xsl</Xsl>
- <Result Type="Valid">string-encode-uri.xml</Result>
- </Data>
- </Variation>
- <Variation Id="73" Pri="2" Desc="Xslt Scenarios : string-lowercase">
- <Data>
- <Xml>string-source1.xml</Xml>
- <Xsl>string-lowercase.xsl</Xsl>
- <Result Type="Valid">string-lowercase.xml</Result>
- </Data>
- </Variation>
- <Variation Id="74" Pri="2" Desc="Xslt Scenarios : string-padding">
- <Data>
- <Xml>string-source.xml</Xml>
- <Xsl>string-padding.xsl</Xsl>
- <Result Type="Valid">string-padding.xml</Result>
- </Data>
- </Variation>
- <Variation Id="75" Pri="2" Desc="Xslt Scenarios : string-replace">
- <Data>
- <Xml>string-source.xml</Xml>
- <Xsl>string-replace.xsl</Xsl>
- <Result Type="Valid">string-replace.xml</Result>
- </Data>
- </Variation>
- <Variation Id="76" Pri="2" Desc="Xslt Scenarios : string-split">
- <Data>
- <Xml>string-source.xml</Xml>
- <Xsl>string-split.xsl</Xsl>
- <Result Type="Valid">string-split.xml</Result>
- </Data>
- </Variation>
- <Variation Id="77" Pri="2" Desc="Xslt Scenarios : string-tokenize">
- <Data>
- <Xml>string-source.xml</Xml>
- <Xsl>string-tokenize.xsl</Xsl>
- <Result Type="Valid">string-tokenize.xml</Result>
- </Data>
- </Variation>
- <Variation Id="78" Pri="2" Desc="Xslt Scenarios : string-uppercase">
- <Data>
- <Xml>string-source1.xml</Xml>
- <Xsl>string-uppercase.xsl</Xsl>
- <Result Type="Valid">string-uppercase.xml</Result>
- </Data>
- </Variation>
- </TestCase>
-</TestModule> \ No newline at end of file
diff --git a/src/System.Private.Xml/tests/Xslt/XsltScenarios/XunitAssemblyAttribute.cs b/src/System.Private.Xml/tests/Xslt/XsltScenarios/XunitAssemblyAttribute.cs
deleted file mode 100644
index 3662eacea4..0000000000
--- a/src/System.Private.Xml/tests/Xslt/XsltScenarios/XunitAssemblyAttribute.cs
+++ /dev/null
@@ -1,10 +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 Xunit;
-
-// For testing purposes, we keep the output of the Transform in a file.
-// Since the content of the file ends up affecting the result of each test,
-// we want to avoid parallelism so that one test doesn't affect another.
-[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true, MaxParallelThreads = 1)]
diff --git a/src/System.Reflection.Emit.ILGeneration/tests/CustomAttributeBuilderTests.cs b/src/System.Reflection.Emit.ILGeneration/tests/CustomAttributeBuilderTests.cs
index e93d028158..3f7e75fda5 100644
--- a/src/System.Reflection.Emit.ILGeneration/tests/CustomAttributeBuilderTests.cs
+++ b/src/System.Reflection.Emit.ILGeneration/tests/CustomAttributeBuilderTests.cs
@@ -575,6 +575,10 @@ namespace System.Reflection.Emit.Tests
yield return new object[] { new int[0, 0] };
yield return new object[] { Enum.GetValues(CreateEnum(typeof(char), 'a')).GetValue(0) };
yield return new object[] { Enum.GetValues(CreateEnum(typeof(bool), true)).GetValue(0) };
+ }
+
+ public static IEnumerable<object[]> FloatEnum_DoubleEnum_TestData()
+ {
yield return new object[] { Enum.GetValues(CreateEnum(typeof(float), 0.0f)).GetValue(0) };
yield return new object[] { Enum.GetValues(CreateEnum(typeof(double), 0.0)).GetValue(0) };
}
@@ -586,6 +590,14 @@ namespace System.Reflection.Emit.Tests
}
[Theory]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Netfx doesn't support Enum.GetEnumName for float or double enums.")]
+ [MemberData(nameof(FloatEnum_DoubleEnum_TestData))]
+ public void ConstructorArgsContainsFloatEnumOrDoubleEnum_ThrowsArgumentException(object value)
+ {
+ NotSupportedObjectInConstructorArgs_ThrowsArgumentException(value);
+ }
+
+ [Theory]
[MemberData(nameof(NotSupportedObject_Constructor_TestData))]
[MemberData(nameof(NotSupportedObject_Others_TestData))]
public static void NotSupportedObjectInConstructorArgs_ThrowsArgumentException(object value)
@@ -613,10 +625,14 @@ namespace System.Reflection.Emit.Tests
Assert.Throws<ArgumentException>(null, () => new CustomAttributeBuilder(con, constructorArgs, new PropertyInfo[0], new object[0], new FieldInfo[0], new object[0]));
}
- public static IEnumerable<object[]> InvalidAttributeTypes_TestData()
+ public static IEnumerable<object[]> IntPtrAttributeTypes_TestData()
{
yield return new object[] { typeof(IntPtr), (IntPtr)1 };
yield return new object[] { typeof(UIntPtr), (UIntPtr)1 };
+ }
+
+ public static IEnumerable<object[]> InvalidAttributeTypes_TestData()
+ {
yield return new object[] { typeof(Guid), new Guid() };
yield return new object[] { typeof(int[,]), new int[5, 5] };
yield return new object[] { CreateEnum(typeof(char), 'a'), 'a' };
@@ -628,6 +644,14 @@ namespace System.Reflection.Emit.Tests
}
[Theory]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Coreclr fixed an issue where IntPtr/UIntPtr in constructorParameters causes a corrupt created binary.")]
+ [MemberData(nameof(IntPtrAttributeTypes_TestData))]
+ public void ConstructorParametersContainsIntPtrOrUIntPtrArgument_ThrowsArgumentException(Type type, object value)
+ {
+ ConstructorParametersNotSupportedInAttributes_ThrowsArgumentException(type, value);
+ }
+
+ [Theory]
[MemberData(nameof(InvalidAttributeTypes_TestData))]
public void ConstructorParametersNotSupportedInAttributes_ThrowsArgumentException(Type type, object value)
{
@@ -642,9 +666,9 @@ namespace System.Reflection.Emit.Tests
}
[Fact]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Used to throw a NullReferenceException, see issue #11702.")]
public void NullValueForPrimitiveTypeInConstructorArgs_ThrowsArgumentNullException()
{
- // Used to throw a NullReferenceException, see issue #11702
ConstructorInfo con = typeof(TestAttribute).GetConstructor(new Type[] { typeof(int) });
object[] constructorArgs = new object[] { null };
@@ -661,6 +685,7 @@ namespace System.Reflection.Emit.Tests
}
[Theory]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Coreclr fixed an issue where IntPtr/UIntPtr in constructorArgs causes a corrupt created binary.")]
[MemberData(nameof(NotSupportedPrimitives_TestData))]
public static void NotSupportedPrimitiveInConstructorArgs_ThrowsArgumentException(object value)
{
@@ -806,6 +831,7 @@ namespace System.Reflection.Emit.Tests
[Theory]
[MemberData(nameof(NotSupportedPrimitives_TestData))]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Coreclr fixed an issue where IntPtr/UIntPtr in fieldValues causes a corrupt created binary.")]
public static void NotSupportedPrimitiveInFieldValues_ThrowsArgumentException(object value)
{
// Used to assert in CustomAttributeBuilder.EmitType(), not writing any CustomAttributeEncoding.
@@ -893,6 +919,7 @@ namespace System.Reflection.Emit.Tests
[Theory]
[MemberData(nameof(InvalidAttributeTypes_TestData))]
+ [MemberData(nameof(IntPtrAttributeTypes_TestData))]
public void NamedProperties_TypeNotSupportedInAttributes_ThrowsArgumentException(Type type, object value)
{
TypeBuilder typeBuilder = Helpers.DynamicType(TypeAttributes.Public);
@@ -966,6 +993,7 @@ namespace System.Reflection.Emit.Tests
[Theory]
[MemberData(nameof(NotSupportedPrimitives_TestData))]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Coreclr fixed an issue where IntPtr/UIntPtr in propertValues causes a corrupt created binary.")]
public static void NotSupportedPrimitiveInPropertyValues_ThrowsArgumentException(object value)
{
ConstructorInfo con = typeof(TestAttribute).GetConstructor(new Type[0]);
diff --git a/src/System.Reflection.Emit.Lightweight/tests/DynamicMethodGetILGenerator.cs b/src/System.Reflection.Emit.Lightweight/tests/DynamicMethodGetILGenerator.cs
index 4b927ebea2..2083318035 100644
--- a/src/System.Reflection.Emit.Lightweight/tests/DynamicMethodGetILGenerator.cs
+++ b/src/System.Reflection.Emit.Lightweight/tests/DynamicMethodGetILGenerator.cs
@@ -13,7 +13,7 @@ namespace System.Reflection.Emit.Tests
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void ILGenerator_Int_Type(bool skipVisibility)
+ public void GetILGenerator_Int_Owner(bool skipVisibility)
{
IDClass target = new IDClass();
FieldInfo field = typeof(IDClass).GetField(FieldName, BindingFlags.Instance | BindingFlags.NonPublic);
@@ -28,10 +28,16 @@ namespace System.Reflection.Emit.Tests
VerifyILGenerator(instanceCallBack, target, 0);
}
+ [Fact]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "The coreclr ignores the skipVisibility value of DynamicMethod.")]
+ public void GetILGenerator_Int_Module_CoreclrIgnoresSkipVisibility()
+ {
+ GetILGenerator_Int_Module(skipVisibility: false);
+ }
+
[Theory]
[InlineData(true)]
- [InlineData(false)]
- public void ILGenerator_Int_Module(bool skipVisibility)
+ public void GetILGenerator_Int_Module(bool skipVisibility)
{
Module module = typeof(IDClass).GetTypeInfo().Module;
IDClass target = new IDClass();
@@ -50,7 +56,7 @@ namespace System.Reflection.Emit.Tests
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void GetILGenerator_Type(bool skipVisibility)
+ public void GetILGenerator_Owner(bool skipVisibility)
{
IDClass target = new IDClass();
FieldInfo field = typeof(IDClass).GetField(FieldName, BindingFlags.Instance | BindingFlags.NonPublic);
@@ -66,9 +72,15 @@ namespace System.Reflection.Emit.Tests
VerifyILGenerator(instanceCallBack, target, 0);
}
+ [Fact]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "The coreclr ignores the skipVisibility value of DynamicMethod.")]
+ public void GetILGenerator_Module_CoreclrIgnoresSkipVisibility()
+ {
+ GetILGenerator_Module(skipVisibility: false);
+ }
+
[Theory]
[InlineData(true)]
- [InlineData(false)]
public void GetILGenerator_Module(bool skipVisibility)
{
Module module = typeof(TestClass).GetTypeInfo().Module;
diff --git a/src/System.Reflection.Emit/tests/AssemblyBuilderTests.cs b/src/System.Reflection.Emit/tests/AssemblyBuilderTests.cs
index cc73b6ffd9..be1c7d2ad1 100644
--- a/src/System.Reflection.Emit/tests/AssemblyBuilderTests.cs
+++ b/src/System.Reflection.Emit/tests/AssemblyBuilderTests.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.InteropServices;
using Xunit;
namespace System.Reflection.Emit.Tests
@@ -71,11 +72,20 @@ namespace System.Reflection.Emit.Tests
}
[Theory]
- [InlineData((AssemblyBuilderAccess)0)] // No such case
- [InlineData((AssemblyBuilderAccess)10)] // No such case
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "The coreclr doesn't support Save or ReflectionOnly AssemblyBuilders.")]
[InlineData((AssemblyBuilderAccess)2)] // Save (not supported)
[InlineData((AssemblyBuilderAccess)2 | AssemblyBuilderAccess.Run)] // RunAndSave (not supported)
[InlineData((AssemblyBuilderAccess)6)] // ReflectionOnly (not supported)
+ public void DefineDynamicAssembly_CoreclrNotSupportedAccess_ThrowsArgumentException(AssemblyBuilderAccess access)
+ {
+ DefineDynamicAssembly_InvalidAccess_ThrowsArgumentException(access);
+ }
+
+ [Theory]
+ [InlineData((AssemblyBuilderAccess)(-1))]
+ [InlineData((AssemblyBuilderAccess)0)]
+ [InlineData((AssemblyBuilderAccess)10)]
+ [InlineData((AssemblyBuilderAccess)int.MaxValue)]
public void DefineDynamicAssembly_InvalidAccess_ThrowsArgumentException(AssemblyBuilderAccess access)
{
Assert.Throws<ArgumentException>("access", () => AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), access));
@@ -87,10 +97,10 @@ namespace System.Reflection.Emit.Tests
{
AssemblyName name = new AssemblyName("Name") { Version = new Version(0, 0, 0, 0) };
AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
- Assert.Equal(name.ToString(), assembly.FullName);
+ Assert.StartsWith(name.ToString(), assembly.FullName);
name.Name = "NewName";
- Assert.NotEqual(name.ToString(), assembly.FullName);
+ Assert.False(assembly.FullName.StartsWith(name.ToString()));
}
public static IEnumerable<object[]> DefineDynamicModule_TestData()
@@ -113,26 +123,53 @@ namespace System.Reflection.Emit.Tests
Assert.Empty(module.CustomAttributes);
Assert.Equal("<In Memory Module>", module.Name);
- Assert.Equal("RefEmit_InMemoryManifestModule", module.FullyQualifiedName);
+
+ // The coreclr ignores the name passed to AssemblyBuilder.DefineDynamicModule
+ if (RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework"))
+ {
+ Assert.Equal(name, module.FullyQualifiedName);
+ }
+ else
+ {
+ Assert.Equal("RefEmit_InMemoryManifestModule", module.FullyQualifiedName);
+ }
Assert.Equal(module, assembly.GetDynamicModule(module.FullyQualifiedName));
}
+ [Fact]
+ public void DefineDynamicModule_NullName_ThrowsArgumentNullException()
+ {
+ AssemblyBuilder assembly = Helpers.DynamicAssembly();
+ Assert.Throws<ArgumentNullException>("name", () => assembly.DefineDynamicModule(null));
+ }
+
[Theory]
- [InlineData(null, typeof(ArgumentNullException))]
- [InlineData("", typeof(ArgumentException))]
- [InlineData("\0test", typeof(ArgumentException))]
- public void DefineDyamicModule_InvalidName_ThrowsArgumentException(string name, Type exceptionType)
+ [InlineData("")]
+ [InlineData("\0test")]
+ public void DefineDynamicModule_InvalidName_ThrowsArgumentException(string name)
+ {
+ AssemblyBuilder assembly = Helpers.DynamicAssembly();
+ Assert.Throws<ArgumentException>("name", () => assembly.DefineDynamicModule(name));
+ }
+
+ [Fact]
+ [SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "The coreclr only supports AssemblyBuilders with one module.")]
+ public void DefineDynamicModule_NetFxModuleAlreadyDefined_ThrowsInvalidOperationException()
{
AssemblyBuilder assembly = Helpers.DynamicAssembly();
- Assert.Throws(exceptionType, () => assembly.DefineDynamicModule(name));
+ assembly.DefineDynamicModule("module1");
+ assembly.DefineDynamicModule("module2");
+ Assert.Throws<ArgumentException>(null, () => assembly.DefineDynamicModule("module1"));
}
[Fact]
- public void DefineDyamicModule_ModuleAlreadyDefined_ThrowsInvalidOperationException()
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "The coreclr only supports AssemblyBuilders with one module.")]
+ public void DefineDynamicModule_CoreFxModuleAlreadyDefined_ThrowsInvalidOperationException()
{
AssemblyBuilder assembly = Helpers.DynamicAssembly();
- ModuleBuilder mb = assembly.DefineDynamicModule("module1");
+ assembly.DefineDynamicModule("module1");
+ Assert.Throws<InvalidOperationException>(() => assembly.DefineDynamicModule("module1"));
Assert.Throws<InvalidOperationException>(() => assembly.DefineDynamicModule("module2"));
}
@@ -258,9 +295,9 @@ namespace System.Reflection.Emit.Tests
public static void VerifyAssemblyBuilder(AssemblyBuilder assembly, AssemblyName name, IEnumerable<CustomAttributeBuilder> attributes)
{
- Assert.Equal(name.ToString(), assembly.FullName);
- Assert.Equal(name.ToString(), assembly.GetName().ToString());
-
+ Assert.StartsWith(name.ToString(), assembly.FullName);
+ Assert.StartsWith(name.ToString(), assembly.GetName().ToString());
+
Assert.True(assembly.IsDynamic);
Assert.Equal(attributes?.Count() ?? 0, assembly.CustomAttributes.Count());
diff --git a/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs b/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs
index 8ca7619649..792fb478d4 100644
--- a/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs
+++ b/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs
@@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
namespace System.Reflection
{
- internal unsafe static class BlobUtilities
+ internal static unsafe class BlobUtilities
{
public static byte[] ReadBytes(byte* buffer, int byteCount)
{
@@ -226,7 +226,7 @@ namespace System.Reflection
}
}
- internal unsafe static int GetUTF8ByteCount(string str)
+ internal static unsafe int GetUTF8ByteCount(string str)
{
fixed (char* ptr = str)
{
@@ -234,7 +234,7 @@ namespace System.Reflection
}
}
- internal unsafe static int GetUTF8ByteCount(char* str, int charCount)
+ internal static unsafe int GetUTF8ByteCount(char* str, int charCount)
{
char* remainder;
return GetUTF8ByteCount(str, charCount, int.MaxValue, out remainder);
diff --git a/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.cs b/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.cs
index 62c27fa3ae..06371b7a81 100644
--- a/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.cs
+++ b/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.cs
@@ -46,7 +46,7 @@ namespace System.Reflection.Internal
/// (lightUpAttemptFailed || prefix != null), we give up and allocate a temporary array,
/// copy to it, decode, and throw it away.
/// </summary>
- internal unsafe static class EncodingHelper
+ internal static unsafe class EncodingHelper
{
// Size of pooled buffers. Input larger than that is prefixed or given to us on a
// platform that doesn't have unsafe Encoding.GetString, will cause us to
diff --git a/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableByteArrayInterop.cs b/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableByteArrayInterop.cs
index 0ae25437a1..0b6c7d10d2 100644
--- a/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableByteArrayInterop.cs
+++ b/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableByteArrayInterop.cs
@@ -37,7 +37,7 @@ namespace System.Reflection.Internal
/// characteristics and therefore something we (Microsoft) are comfortable defining as a contract that
/// can be depended upon as below.
/// </remarks>
- internal unsafe static class ImmutableByteArrayInterop
+ internal static unsafe class ImmutableByteArrayInterop
{
/// <summary>
/// Creates a new instance of <see cref="ImmutableArray{Byte}"/> using a given mutable array as the backing
diff --git a/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/MemoryMapLightUp.cs b/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/MemoryMapLightUp.cs
index 93263a901c..9a4afa6bc8 100644
--- a/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/MemoryMapLightUp.cs
+++ b/src/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/MemoryMapLightUp.cs
@@ -228,7 +228,7 @@ namespace System.Reflection.Internal
}
}
- internal unsafe static byte* AcquirePointer(object accessor, out SafeBuffer safeBuffer)
+ internal static unsafe byte* AcquirePointer(object accessor, out SafeBuffer safeBuffer)
{
Debug.Assert(s_lazyIsAvailable.GetValueOrDefault());
diff --git a/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs b/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs
index b14470f05f..63e023acf9 100644
--- a/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs
+++ b/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs
@@ -169,7 +169,7 @@ namespace System.Reflection.Metadata
protected int FreeBytes => _buffer.Length - Length;
// internal for testing
- internal protected int ChunkCapacity => _buffer.Length;
+ protected internal int ChunkCapacity => _buffer.Length;
// internal for testing
internal Chunks GetChunks()
diff --git a/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs b/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs
index eec0a2cfdb..191adf641d 100644
--- a/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs
+++ b/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs
@@ -53,7 +53,7 @@ namespace System.Reflection.Metadata
return FromHash(ImmutableByteArrayInterop.DangerousGetUnderlyingArray(hashCode));
}
- public unsafe static BlobContentId FromHash(byte[] hashCode)
+ public static unsafe BlobContentId FromHash(byte[] hashCode)
{
const int minHashSize = 20;
diff --git a/src/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs b/src/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs
index 413a82aa48..8dc287dde0 100644
--- a/src/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs
+++ b/src/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs
@@ -87,7 +87,7 @@ namespace System.Reflection.PortableExecutable
protected abstract BlobBuilder SerializeSection(string name, SectionLocation location);
- internal protected abstract PEDirectoriesBuilder GetDirectories();
+ protected internal abstract PEDirectoriesBuilder GetDirectories();
public BlobContentId Serialize(BlobBuilder builder)
{
@@ -515,7 +515,7 @@ namespace System.Reflection.PortableExecutable
return CalculateChecksum(GetContentToChecksum(peImage, checksumFixup)) + (uint)peImage.Count;
}
- private unsafe static uint CalculateChecksum(IEnumerable<Blob> blobs)
+ private static unsafe uint CalculateChecksum(IEnumerable<Blob> blobs)
{
uint checksum = 0;
int pendingByte = -1;
diff --git a/src/System.Reflection.Metadata/tests/Metadata/Ecma335/MetadataAggregatorTests.cs b/src/System.Reflection.Metadata/tests/Metadata/Ecma335/MetadataAggregatorTests.cs
index 30eb7d79a2..b457efb632 100644
--- a/src/System.Reflection.Metadata/tests/Metadata/Ecma335/MetadataAggregatorTests.cs
+++ b/src/System.Reflection.Metadata/tests/Metadata/Ecma335/MetadataAggregatorTests.cs
@@ -11,7 +11,7 @@ namespace System.Reflection.Metadata.Ecma335.Tests
{
public class MetadataAggregatorTests
{
- private unsafe static EnCMapTableReader CreateEncMapTable(int[] tokens)
+ private static unsafe EnCMapTableReader CreateEncMapTable(int[] tokens)
{
GCHandle handle = GCHandle.Alloc(tokens, GCHandleType.Pinned);
var block = new MemoryBlock((byte*)handle.AddrOfPinnedObject(), tokens.Length * sizeof(uint));
diff --git a/src/System.Reflection.Metadata/tests/Metadata/PortablePdb/StandalonePortablePdbStreamTests.cs b/src/System.Reflection.Metadata/tests/Metadata/PortablePdb/StandalonePortablePdbStreamTests.cs
index b5dc4895e1..558d3be48f 100644
--- a/src/System.Reflection.Metadata/tests/Metadata/PortablePdb/StandalonePortablePdbStreamTests.cs
+++ b/src/System.Reflection.Metadata/tests/Metadata/PortablePdb/StandalonePortablePdbStreamTests.cs
@@ -10,7 +10,7 @@ namespace System.Reflection.Metadata.Tests
{
public class StandalonePortablePdbStreamTests
{
- private unsafe static void ReadHeader(out DebugMetadataHeader header, out int[] externalRowCounts, byte[] buffer)
+ private static unsafe void ReadHeader(out DebugMetadataHeader header, out int[] externalRowCounts, byte[] buffer)
{
fixed (byte* bufferPtr = &buffer[0])
{
diff --git a/src/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs b/src/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs
index 9414a7015e..6873d3b529 100644
--- a/src/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs
+++ b/src/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs
@@ -35,7 +35,7 @@ namespace System.Reflection.PortableExecutable.Tests
}
}
- private unsafe static void VerifyStrongNameSignatureDirectory(PEReader peReader, byte[] expectedSignature)
+ private static unsafe void VerifyStrongNameSignatureDirectory(PEReader peReader, byte[] expectedSignature)
{
var headers = peReader.PEHeaders;
int rva = headers.CorHeader.StrongNameSignatureDirectory.RelativeVirtualAddress;
@@ -464,7 +464,7 @@ namespace System.Reflection.PortableExecutable.Tests
{
}
- internal protected override void Serialize(BlobBuilder builder, SectionLocation location)
+ protected internal override void Serialize(BlobBuilder builder, SectionLocation location)
{
builder.WriteInt32(0x12345678);
builder.WriteInt32(location.PointerToRawData);
@@ -510,7 +510,7 @@ namespace System.Reflection.PortableExecutable.Tests
{
}
- internal protected override void Serialize(BlobBuilder builder, SectionLocation location)
+ protected internal override void Serialize(BlobBuilder builder, SectionLocation location)
{
throw new NotImplementedException();
}
diff --git a/src/System.Reflection.Metadata/tests/Resources/Interop/Interop.Mock01.cs b/src/System.Reflection.Metadata/tests/Resources/Interop/Interop.Mock01.cs
index df8a92c3d4..a14c0be6b2 100644
--- a/src/System.Reflection.Metadata/tests/Resources/Interop/Interop.Mock01.cs
+++ b/src/System.Reflection.Metadata/tests/Resources/Interop/Interop.Mock01.cs
@@ -139,7 +139,6 @@ namespace MockInterop01
public delegate void EventDele02(InteropEnum p);
public delegate void EventDele03(ComplexStruct p);
- [ComVisible(false)]
// [TypeIdentifier("71B8C65D-7748-447A-B786-64682CBEF136", "MockInterop01.InteropDeleWithStructArray")]
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall, BestFitMapping = false, CharSet = CharSet.Auto)]
public delegate void InteropDeleWithStructArray([In, Out, ComAliasName("MockInterop01.UnionStruct"), MarshalAs(UnmanagedType.LPArray)] UnionStruct[] p);
diff --git a/src/System.Reflection.Metadata/tests/TestUtilities/LoaderUtilities.cs b/src/System.Reflection.Metadata/tests/TestUtilities/LoaderUtilities.cs
index eb9fe12bcd..731b6fd3f0 100644
--- a/src/System.Reflection.Metadata/tests/TestUtilities/LoaderUtilities.cs
+++ b/src/System.Reflection.Metadata/tests/TestUtilities/LoaderUtilities.cs
@@ -10,7 +10,7 @@ using System.Reflection.Internal;
namespace System.Reflection.Metadata.Tests
{
- internal unsafe static class LoaderUtilities
+ internal static unsafe class LoaderUtilities
{
public static void LoadPEAndValidate(byte[] peImage, Action<PEReader> validator, bool useStream = false)
{
diff --git a/src/System.Reflection.Primitives/src/System/Reflection/Emit/FlowControl.cs b/src/System.Reflection.Primitives/src/System/Reflection/Emit/FlowControl.cs
index 15b61859a0..8e6a373bcc 100644
--- a/src/System.Reflection.Primitives/src/System/Reflection/Emit/FlowControl.cs
+++ b/src/System.Reflection.Primitives/src/System/Reflection/Emit/FlowControl.cs
@@ -5,7 +5,6 @@
namespace System.Reflection.Emit
{
[Serializable]
- [System.Runtime.InteropServices.ComVisible(true)]
public enum FlowControl
{
Branch = 0,
diff --git a/src/System.Reflection.Primitives/src/System/Reflection/Emit/OpCodes.cs b/src/System.Reflection.Primitives/src/System/Reflection/Emit/OpCodes.cs
index 9f7a8c0eb7..2875c95818 100644
--- a/src/System.Reflection.Primitives/src/System/Reflection/Emit/OpCodes.cs
+++ b/src/System.Reflection.Primitives/src/System/Reflection/Emit/OpCodes.cs
@@ -239,7 +239,6 @@ namespace System.Reflection.Emit
// If you add more opcodes here, modify OpCode.Name to handle them correctly
};
- [System.Runtime.InteropServices.ComVisible(true)]
public class OpCodes
{
/// <summary>
@@ -1409,7 +1408,6 @@ namespace System.Reflection.Emit
(1 << OpCode.StackChangeShift)
);
- [System.Runtime.InteropServices.ComVisible(true)]
public static readonly OpCode Castclass = new OpCode(OpCodeValues.Castclass,
((int)OperandType.InlineType) |
((int)FlowControl.Next << OpCode.FlowControlShift) |
diff --git a/src/System.Reflection.Primitives/src/System/Reflection/Emit/Opcode.cs b/src/System.Reflection.Primitives/src/System/Reflection/Emit/Opcode.cs
index 37f266d2d9..b8eebb748a 100644
--- a/src/System.Reflection.Primitives/src/System/Reflection/Emit/Opcode.cs
+++ b/src/System.Reflection.Primitives/src/System/Reflection/Emit/Opcode.cs
@@ -7,7 +7,6 @@ using System.Diagnostics.Contracts;
namespace System.Reflection.Emit
{
- [System.Runtime.InteropServices.ComVisible(true)]
public struct OpCode
{
//
diff --git a/src/System.Reflection.Primitives/src/System/Reflection/Emit/OpcodeType.cs b/src/System.Reflection.Primitives/src/System/Reflection/Emit/OpcodeType.cs
index c66a54e5a4..4dddf88871 100644
--- a/src/System.Reflection.Primitives/src/System/Reflection/Emit/OpcodeType.cs
+++ b/src/System.Reflection.Primitives/src/System/Reflection/Emit/OpcodeType.cs
@@ -5,7 +5,6 @@
namespace System.Reflection.Emit
{
[Serializable]
- [System.Runtime.InteropServices.ComVisible(true)]
public enum OpCodeType
{
[Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
diff --git a/src/System.Reflection.Primitives/src/System/Reflection/Emit/OperandType.cs b/src/System.Reflection.Primitives/src/System/Reflection/Emit/OperandType.cs
index c419d9cafc..b71b09d70f 100644
--- a/src/System.Reflection.Primitives/src/System/Reflection/Emit/OperandType.cs
+++ b/src/System.Reflection.Primitives/src/System/Reflection/Emit/OperandType.cs
@@ -5,7 +5,6 @@
namespace System.Reflection.Emit
{
[Serializable]
- [System.Runtime.InteropServices.ComVisible(true)]
public enum OperandType
{
InlineBrTarget = 0,
diff --git a/src/System.Reflection.Primitives/src/System/Reflection/Emit/PackingSize.cs b/src/System.Reflection.Primitives/src/System/Reflection/Emit/PackingSize.cs
index 7ed0296774..31b92eb52f 100644
--- a/src/System.Reflection.Primitives/src/System/Reflection/Emit/PackingSize.cs
+++ b/src/System.Reflection.Primitives/src/System/Reflection/Emit/PackingSize.cs
@@ -5,7 +5,6 @@
namespace System.Reflection.Emit
{
[Serializable]
- [System.Runtime.InteropServices.ComVisible(true)]
public enum PackingSize
{
Unspecified = 0,
diff --git a/src/System.Reflection.Primitives/src/System/Reflection/Emit/StackBehaviour.cs b/src/System.Reflection.Primitives/src/System/Reflection/Emit/StackBehaviour.cs
index e0c20217ec..6a2d9aed3e 100644
--- a/src/System.Reflection.Primitives/src/System/Reflection/Emit/StackBehaviour.cs
+++ b/src/System.Reflection.Primitives/src/System/Reflection/Emit/StackBehaviour.cs
@@ -5,7 +5,6 @@
namespace System.Reflection.Emit
{
[Serializable]
- [System.Runtime.InteropServices.ComVisible(true)]
public enum StackBehaviour
{
Pop0 = 0,
diff --git a/src/System.Reflection/pkg/System.Reflection.pkgproj b/src/System.Reflection/pkg/System.Reflection.pkgproj
index 7ead423a11..8b31beb768 100644
--- a/src/System.Reflection/pkg/System.Reflection.pkgproj
+++ b/src/System.Reflection/pkg/System.Reflection.pkgproj
@@ -3,10 +3,10 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Reflection.csproj">
- <SupportedFramework>net463;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Reflection.csproj">
- <TargetGroup>net463</TargetGroup>
+ <TargetGroup>net461</TargetGroup>
</ProjectReference>
<ProjectReference Include="any\System.Reflection.pkgproj" />
<ProjectReference Include="aot\System.Reflection.pkgproj" />
@@ -21,6 +21,10 @@
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
+ <!-- the previous version of this package supported a different API version for
+ net462, but since netstandard2.0 supports the latest and net461 supports
+ netstandard2.0 we need to suppress the old net462 assembly. -->
+ <HarvestSuppressPaths Include="ref/net462;lib/net462" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/System.Reflection/src/ApiCompatBaseline.txt b/src/System.Reflection/src/ApiCompatBaseline.txt
deleted file mode 100644
index 6dbe699b0a..0000000000
--- a/src/System.Reflection/src/ApiCompatBaseline.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Compat issues with assembly System.Reflection:
-MembersMustExist : Member 'System.Reflection.Assembly.add_ModuleResolve(System.Reflection.ModuleResolveEventHandler)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.remove_ModuleResolve(System.Reflection.ModuleResolveEventHandler)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 2
diff --git a/src/System.Reflection/src/Configurations.props b/src/System.Reflection/src/Configurations.props
index f013d10b8c..d561a2dc29 100644
--- a/src/System.Reflection/src/Configurations.props
+++ b/src/System.Reflection/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
uap101aot-Windows_NT;
netstandard;
</BuildConfigurations>
diff --git a/src/System.Reflection/src/System.Reflection.csproj b/src/System.Reflection/src/System.Reflection.csproj
index 49e4745ca7..789a56ba67 100644
--- a/src/System.Reflection/src/System.Reflection.csproj
+++ b/src/System.Reflection/src/System.Reflection.csproj
@@ -9,11 +9,11 @@
<!-- Help VS understand available configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup>
- <TargetingPackReference Include="mscorlib" Condition="'$(TargetGroup)' == 'net463'" />
- <TargetingPackReference Include="System.Private.CoreLib" Condition="'$(TargetGroup)' != 'net463'" />
+ <TargetingPackReference Include="mscorlib" Condition="'$(TargetGroup)' == 'net461'" />
+ <TargetingPackReference Include="System.Private.CoreLib" Condition="'$(TargetGroup)' != 'net461'" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Private.CoreLib" />
diff --git a/src/System.Resources.Reader/pkg/System.Resources.Reader.pkgproj b/src/System.Resources.Reader/pkg/System.Resources.Reader.pkgproj
index 9e20290dd2..da2db612a4 100644
--- a/src/System.Resources.Reader/pkg/System.Resources.Reader.pkgproj
+++ b/src/System.Resources.Reader/pkg/System.Resources.Reader.pkgproj
@@ -4,7 +4,7 @@
<ItemGroup>
<ProjectReference Include="..\src\System.Resources.Reader.builds">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
</ItemGroup>
diff --git a/src/System.Resources.Writer/pkg/System.Resources.Writer.pkgproj b/src/System.Resources.Writer/pkg/System.Resources.Writer.pkgproj
index d299e34016..403252aff8 100644
--- a/src/System.Resources.Writer/pkg/System.Resources.Writer.pkgproj
+++ b/src/System.Resources.Writer/pkg/System.Resources.Writer.pkgproj
@@ -4,7 +4,7 @@
<ItemGroup>
<ProjectReference Include="..\src\System.Resources.Writer.builds">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
</ItemGroup>
diff --git a/src/System.Runtime.CompilerServices.Unsafe/pkg/System.Runtime.CompilerServices.Unsafe.pkgproj b/src/System.Runtime.CompilerServices.Unsafe/pkg/System.Runtime.CompilerServices.Unsafe.pkgproj
index 66269ad81e..b6659d64b0 100644
--- a/src/System.Runtime.CompilerServices.Unsafe/pkg/System.Runtime.CompilerServices.Unsafe.pkgproj
+++ b/src/System.Runtime.CompilerServices.Unsafe/pkg/System.Runtime.CompilerServices.Unsafe.pkgproj
@@ -2,6 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
+ <PackageIndex Include="$(ProjectDir)\pkg\baseline\packageBaseline.1.1.json" />
<ProjectReference Include="..\src\System.Runtime.CompilerServices.Unsafe.ilproj">
<SupportedFramework>net45;netcore45;wp8;wpa81;netcoreapp1.0;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
diff --git a/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.il b/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.il
index 3251744263..0eb1aa4091 100644
--- a/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.il
+++ b/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.il
@@ -130,7 +130,7 @@
ret
} // end of method Unsafe::CopyBlock
- .method public hidebysig static void CopyBlock(void* destination, void* source, native unsigned int byteCount) cil managed aggressiveinlining
+ .method public hidebysig static void CopyBlock(uint8& destination, uint8& source, uint32 byteCount) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 3
@@ -153,7 +153,7 @@
ret
} // end of method Unsafe::CopyBlockUnaligned
- .method public hidebysig static void CopyBlockUnaligned(void* destination, void* source, native unsigned int byteCount) cil managed aggressiveinlining
+ .method public hidebysig static void CopyBlockUnaligned(uint8& destination, uint8& source, uint32 byteCount) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 3
@@ -176,7 +176,7 @@
ret
} // end of method Unsafe::InitBlock
- .method public hidebysig static void InitBlock(void* startAddress, uint8 'value', native unsigned int byteCount) cil managed aggressiveinlining
+ .method public hidebysig static void InitBlock(uint8& startAddress, uint8 'value', uint32 byteCount) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 3
@@ -199,7 +199,7 @@
ret
} // end of method Unsafe::InitBlockUnaligned
- .method public hidebysig static void InitBlockUnaligned(void* startAddress, uint8 'value', native unsigned int byteCount) cil managed aggressiveinlining
+ .method public hidebysig static void InitBlockUnaligned(uint8& startAddress, uint8 'value', uint32 byteCount) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 3
@@ -222,8 +222,12 @@
.method public hidebysig static !!T& AsRef<T>(void* source) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
+ .locals (int32&)
.maxstack 1
ldarg.0
+ // Roundtrip via a local to avoid type mismatch on return that the JIT inliner chokes on.
+ stloc.0
+ ldloc.0
ret
} // end of method Unsafe::AsRef
diff --git a/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.xml b/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.xml
index bd8f42271a..4a7ea0d948 100644
--- a/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.xml
+++ b/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.xml
@@ -160,7 +160,7 @@
<param name="source">The source address to copy from.</param>
<param name="byteCount">The number of bytes to copy.</param>
</member>
- <member name="M:System.Runtime.CompilerServices.Unsafe.CopyBlock(System.Void*,System.Void*,System.UIntPtr)">
+ <member name="M:System.Runtime.CompilerServices.Unsafe.CopyBlock(System.Byte@,System.Byte@,System.UInt32)">
<summary>
Copies bytes from the source address to the destination address.
</summary>
@@ -177,7 +177,7 @@
<param name="source">The source address to copy from.</param>
<param name="byteCount">The number of bytes to copy.</param>
</member>
- <member name="M:System.Runtime.CompilerServices.Unsafe.CopyBlockUnaligned(System.Void*,System.Void*,System.UIntPtr)">
+ <member name="M:System.Runtime.CompilerServices.Unsafe.CopyBlockUnaligned(System.Byte@,System.Byte@,System.UInt32)">
<summary>
Copies bytes from the source address to the destination address
without assuming architecture dependent alignment of the addresses.
@@ -194,7 +194,7 @@
<param name="value">The value to initialize the block to.</param>
<param name="byteCount">The number of bytes to initialize.</param>
</member>
- <member name="M:System.Runtime.CompilerServices.Unsafe.InitBlock(System.Void*,System.Byte,System.UIntPtr)">
+ <member name="M:System.Runtime.CompilerServices.Unsafe.InitBlock(System.Byte@,System.Byte,System.UInt32)">
<summary>
Initializes a block of memory at the given location with a given initial value.
</summary>
@@ -211,7 +211,7 @@
<param name="value">The value to initialize the block to.</param>
<param name="byteCount">The number of bytes to initialize.</param>
</member>
- <member name="M:System.Runtime.CompilerServices.Unsafe.InitBlockUnaligned(System.Void*,System.Byte,System.UIntPtr)">
+ <member name="M:System.Runtime.CompilerServices.Unsafe.InitBlockUnaligned(System.Byte@,System.Byte,System.UInt32)">
<summary>
Initializes a block of memory at the given location with a given initial value
without assuming architecture dependent alignment of the address.
diff --git a/src/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs b/src/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
index ba6ecb1737..7511966b99 100644
--- a/src/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
+++ b/src/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
@@ -181,10 +181,10 @@ namespace System.Runtime.CompilerServices
[Theory]
[MemberData(nameof(InitBlockData))]
- public static unsafe void InitBlockUIntPtrStack(int numBytes, byte value)
+ public static unsafe void InitBlockRefStack(int numBytes, byte value)
{
byte* stackPtr = stackalloc byte[numBytes];
- Unsafe.InitBlock(stackPtr, value, (UIntPtr)numBytes);
+ Unsafe.InitBlock(ref *stackPtr, value, (uint)numBytes);
for (int i = 0; i < numBytes; i++)
{
Assert.Equal(stackPtr[i], value);
@@ -193,11 +193,11 @@ namespace System.Runtime.CompilerServices
[Theory]
[MemberData(nameof(InitBlockData))]
- public static unsafe void InitBlockUIntPtrUnmanaged(int numBytes, byte value)
+ public static unsafe void InitBlockRefUnmanaged(int numBytes, byte value)
{
IntPtr allocatedMemory = Marshal.AllocCoTaskMem(numBytes);
byte* bytePtr = (byte*)allocatedMemory.ToPointer();
- Unsafe.InitBlock(bytePtr, value, (UIntPtr)numBytes);
+ Unsafe.InitBlock(ref *bytePtr, value, (uint)numBytes);
for (int i = 0; i < numBytes; i++)
{
Assert.Equal(bytePtr[i], value);
@@ -232,11 +232,11 @@ namespace System.Runtime.CompilerServices
[Theory]
[MemberData(nameof(InitBlockData))]
- public static unsafe void InitBlockUnalignedUIntPtrStack(int numBytes, byte value)
+ public static unsafe void InitBlockUnalignedRefStack(int numBytes, byte value)
{
byte* stackPtr = stackalloc byte[numBytes + 1];
stackPtr += 1; // +1 = make unaligned
- Unsafe.InitBlockUnaligned(stackPtr, value, (UIntPtr)numBytes);
+ Unsafe.InitBlockUnaligned(ref *stackPtr, value, (uint)numBytes);
for (int i = 0; i < numBytes; i++)
{
Assert.Equal(stackPtr[i], value);
@@ -245,11 +245,11 @@ namespace System.Runtime.CompilerServices
[Theory]
[MemberData(nameof(InitBlockData))]
- public static unsafe void InitBlockUnalignedUIntPtrUnmanaged(int numBytes, byte value)
+ public static unsafe void InitBlockUnalignedRefUnmanaged(int numBytes, byte value)
{
IntPtr allocatedMemory = Marshal.AllocCoTaskMem(numBytes + 1);
byte* bytePtr = (byte*)allocatedMemory.ToPointer() + 1; // +1 = make unaligned
- Unsafe.InitBlockUnaligned(bytePtr, value, (UIntPtr)numBytes);
+ Unsafe.InitBlockUnaligned(ref *bytePtr, value, (uint)numBytes);
for (int i = 0; i < numBytes; i++)
{
Assert.Equal(bytePtr[i], value);
@@ -291,7 +291,7 @@ namespace System.Runtime.CompilerServices
[Theory]
[MemberData(nameof(CopyBlockData))]
- public static unsafe void CopyBlockUIntPtr(int numBytes)
+ public static unsafe void CopyBlockRef(int numBytes)
{
byte* source = stackalloc byte[numBytes];
byte* destination = stackalloc byte[numBytes];
@@ -302,7 +302,7 @@ namespace System.Runtime.CompilerServices
source[i] = value;
}
- Unsafe.CopyBlock(destination, source, (UIntPtr)numBytes);
+ Unsafe.CopyBlock(ref destination[0], ref source[0], (uint)numBytes);
for (int i = 0; i < numBytes; i++)
{
@@ -337,10 +337,9 @@ namespace System.Runtime.CompilerServices
}
}
-
[Theory]
[MemberData(nameof(CopyBlockData))]
- public static unsafe void CopyBlockUnalignedUIntPtr(int numBytes)
+ public static unsafe void CopyBlockUnalignedRef(int numBytes)
{
byte* source = stackalloc byte[numBytes + 1];
byte* destination = stackalloc byte[numBytes + 1];
@@ -353,7 +352,7 @@ namespace System.Runtime.CompilerServices
source[i] = value;
}
- Unsafe.CopyBlockUnaligned(destination, source, (UIntPtr)numBytes);
+ Unsafe.CopyBlockUnaligned(ref destination[0], ref source[0], (uint)numBytes);
for (int i = 0; i < numBytes; i++)
{
@@ -419,7 +418,7 @@ namespace System.Runtime.CompilerServices
}
[Fact]
- public unsafe static void AsRef()
+ public static unsafe void AsRef()
{
byte[] b = new byte[4] { 0x42, 0x42, 0x42, 0x42 };
fixed (byte * p = b)
diff --git a/src/System.Runtime.CompilerServices.VisualC/ref/System.Runtime.CompilerServices.VisualC.cs b/src/System.Runtime.CompilerServices.VisualC/ref/System.Runtime.CompilerServices.VisualC.cs
index 0601f03782..ce6b879602 100644
--- a/src/System.Runtime.CompilerServices.VisualC/ref/System.Runtime.CompilerServices.VisualC.cs
+++ b/src/System.Runtime.CompilerServices.VisualC/ref/System.Runtime.CompilerServices.VisualC.cs
@@ -12,22 +12,18 @@ namespace System.Runtime.CompilerServices
public static class CompilerMarshalOverride
{
}
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public partial class CallConvCdecl
{
public CallConvCdecl() { }
}
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public partial class CallConvFastcall
{
public CallConvFastcall() { }
}
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public partial class CallConvStdcall
{
public CallConvStdcall() { }
}
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public partial class CallConvThiscall
{
public CallConvThiscall() { }
@@ -38,7 +34,6 @@ namespace System.Runtime.CompilerServices
public static partial class IsByValue
{
}
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public static partial class IsCopyConstructed
{
}
@@ -61,13 +56,11 @@ namespace System.Runtime.CompilerServices
{
}
[System.AttributeUsageAttribute((System.AttributeTargets)(8), Inherited = true)]
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public sealed partial class NativeCppClassAttribute : System.Attribute
{
public NativeCppClassAttribute() { }
}
[System.AttributeUsageAttribute((System.AttributeTargets)(1052), AllowMultiple = true, Inherited = false)]
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public sealed partial class RequiredAttributeAttribute : System.Attribute
{
public RequiredAttributeAttribute(System.Type requiredContract) { }
diff --git a/src/System.Runtime.CompilerServices.VisualC/src/System/Runtime/CompilerServices/Attributes.cs b/src/System.Runtime.CompilerServices.VisualC/src/System/Runtime/CompilerServices/Attributes.cs
index 7d1455ce86..20bbafbf65 100644
--- a/src/System.Runtime.CompilerServices.VisualC/src/System/Runtime/CompilerServices/Attributes.cs
+++ b/src/System.Runtime.CompilerServices.VisualC/src/System/Runtime/CompilerServices/Attributes.cs
@@ -5,19 +5,15 @@
namespace System.Runtime.CompilerServices
{
// Types used in Custom Modifier to specify calling conventions.
- [System.Runtime.InteropServices.ComVisible(true)]
public class CallConvCdecl
{
}
- [System.Runtime.InteropServices.ComVisible(true)]
public class CallConvStdcall
{
}
- [System.Runtime.InteropServices.ComVisible(true)]
public class CallConvThiscall
{
}
- [System.Runtime.InteropServices.ComVisible(true)]
public class CallConvFastcall
{
}
@@ -31,7 +27,6 @@ namespace System.Runtime.CompilerServices
public static partial class IsByValue
{
}
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public static partial class IsCopyConstructed
{
}
@@ -66,14 +61,13 @@ namespace System.Runtime.CompilerServices
public ScopelessEnumAttribute(){}
}
[Serializable]
- [AttributeUsage(AttributeTargets.Struct, Inherited = true),System.Runtime.InteropServices.ComVisible(true)]
+ [AttributeUsage(AttributeTargets.Struct, Inherited = true)]
public sealed class NativeCppClassAttribute : Attribute
{
public NativeCppClassAttribute(){}
}
[Serializable]
[AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface,AllowMultiple=true, Inherited=false)]
- [System.Runtime.InteropServices.ComVisible(true)]
public sealed class RequiredAttributeAttribute : Attribute
{
private Type requiredContract;
diff --git a/src/System.Runtime.Extensions/System.Runtime.Extensions.sln b/src/System.Runtime.Extensions/System.Runtime.Extensions.sln
index 54d55b2bb6..a56140ab86 100644
--- a/src/System.Runtime.Extensions/System.Runtime.Extensions.sln
+++ b/src/System.Runtime.Extensions/System.Runtime.Extensions.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
-VisualStudioVersion = 14.0.23107.0
+VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Runtime.Extensions", "src\System.Runtime.Extensions.csproj", "{845D2B72-D8A4-42E5-9BE9-17639EC4FC1A}"
EndProject
@@ -135,6 +135,66 @@ Global
{9F312D76-9AF1-4E90-B3B0-815A1EC6C346}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
{9F312D76-9AF1-4E90-B3B0-815A1EC6C346}.Windows_Release|Any CPU.ActiveCfg = Release|Any CPU
{9F312D76-9AF1-4E90-B3B0-815A1EC6C346}.Windows_Release|Any CPU.Build.0 = Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.net46_Debug|Any CPU.ActiveCfg = net46_Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.net46_Debug|Any CPU.Build.0 = net46_Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.net46_Release|Any CPU.ActiveCfg = net46_Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.net46_Release|Any CPU.Build.0 = net46_Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.netstandard1.7_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.netstandard1.7_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.netstandard1.7_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.netstandard1.7_Release|Any CPU.Build.0 = Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Unix_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Unix_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Unix_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Unix_Release|Any CPU.Build.0 = Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Windows_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24BCEC6B-B9D2-47BC-9D66-725BD6B526FA}.Windows_Release|Any CPU.Build.0 = Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.net46_Debug|Any CPU.ActiveCfg = net46_Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.net46_Debug|Any CPU.Build.0 = net46_Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.net46_Release|Any CPU.ActiveCfg = net46_Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.net46_Release|Any CPU.Build.0 = net46_Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.netstandard1.7_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.netstandard1.7_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.netstandard1.7_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.netstandard1.7_Release|Any CPU.Build.0 = Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Unix_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Unix_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Unix_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Unix_Release|Any CPU.Build.0 = Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Windows_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD83807C-8BE5-4F27-85DF-9793613233E1}.Windows_Release|Any CPU.Build.0 = Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.net46_Debug|Any CPU.ActiveCfg = net46_Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.net46_Debug|Any CPU.Build.0 = net46_Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.net46_Release|Any CPU.ActiveCfg = net46_Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.net46_Release|Any CPU.Build.0 = net46_Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.netstandard1.7_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.netstandard1.7_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.netstandard1.7_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.netstandard1.7_Release|Any CPU.Build.0 = Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Unix_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Unix_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Unix_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Unix_Release|Any CPU.Build.0 = Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Windows_Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C44B33E3-F89F-40B9-B353-D380C1524988}.Windows_Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/System.Runtime.Extensions/pkg/System.Runtime.Extensions.pkgproj b/src/System.Runtime.Extensions/pkg/System.Runtime.Extensions.pkgproj
index 1d2f31a196..4464e4d91c 100644
--- a/src/System.Runtime.Extensions/pkg/System.Runtime.Extensions.pkgproj
+++ b/src/System.Runtime.Extensions/pkg/System.Runtime.Extensions.pkgproj
@@ -3,13 +3,13 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Runtime.Extensions.builds">
- <SupportedFramework>netcoreapp1.1;uap10.1;net463;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>netcoreapp1.1;uap10.1;net461;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Runtime.Extensions.csproj">
- <TargetGroup>net462</TargetGroup>
+ <TargetGroup>net461</TargetGroup>
</ProjectReference>
<ProjectReference Include="..\src\System.Runtime.Extensions.csproj">
- <TargetGroup>net463</TargetGroup>
+ <TargetGroup>uap101aot</TargetGroup>
</ProjectReference>
<ProjectReference Include="win\System.Runtime.Extensions.pkgproj" />
<ProjectReference Include="unix\System.Runtime.Extensions.pkgproj" />
@@ -26,6 +26,10 @@
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
+ <!-- the previous version of this package supported a different API version for
+ net462, but since netstandard2.0 supports the latest and net461 supports
+ netstandard2.0 we need to suppress the old net462 assembly. -->
+ <HarvestSuppressPaths Include="ref/net462;lib/net462" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Runtime.Extensions/pkg/win/System.Runtime.Extensions.pkgproj b/src/System.Runtime.Extensions/pkg/win/System.Runtime.Extensions.pkgproj
index b5e859fe67..fcbcf869b0 100644
--- a/src/System.Runtime.Extensions/pkg/win/System.Runtime.Extensions.pkgproj
+++ b/src/System.Runtime.Extensions/pkg/win/System.Runtime.Extensions.pkgproj
@@ -9,6 +9,11 @@
<ProjectReference Include="..\..\src\System.Runtime.Extensions.csproj">
<OSGroup>Windows_NT</OSGroup>
</ProjectReference>
+ <!-- AOT implementation comes from AOT package -->
+ <File Include="$(PlaceholderFile)">
+ <TargetPath>runtimes/aot/lib/uap10.1</TargetPath>
+ <TargetFramework>aot</TargetFramework>
+ </File>
<!-- don't use the dotnet implementation for any version of desktop, it's implementation comes from the reference package -->
<ExternalOnTargetFramework Include="net" />
</ItemGroup>
diff --git a/src/System.Runtime.Extensions/src/ApiCompatBaseline.netstandard15aot.txt b/src/System.Runtime.Extensions/src/ApiCompatBaseline.netstandard15aot.txt
deleted file mode 100644
index 574af7d283..0000000000
--- a/src/System.Runtime.Extensions/src/ApiCompatBaseline.netstandard15aot.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# API's don't exist in netcore50aot implementations yet.
-MembersMustExist : Member 'System.Environment.Exit(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Environment.GetCommandLineArgs()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Environment.MachineName.get()' does not exist in the implementation but it does exist in the contract.
diff --git a/src/System.Runtime.Extensions/src/ApiCompatBaseline.uap101aot.txt b/src/System.Runtime.Extensions/src/ApiCompatBaseline.uap101aot.txt
new file mode 100644
index 0000000000..9c2d81ddaf
--- /dev/null
+++ b/src/System.Runtime.Extensions/src/ApiCompatBaseline.uap101aot.txt
@@ -0,0 +1,77 @@
+Compat issues with assembly System.Runtime.Extensions:
+TypesMustExist : Type 'System.AppDomain' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.AssemblyLoadEventArgs' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.AssemblyLoadEventHandler' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Base64FormattingOptions' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Object System.Convert.DBNull' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ChangeType(System.Object, System.TypeCode)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.IsDBNull(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToBase64CharArray(System.Byte[], System.Int32, System.Int32, System.Char[], System.Int32, System.Base64FormattingOptions)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToBase64String(System.Byte[], System.Base64FormattingOptions)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToBase64String(System.Byte[], System.Int32, System.Int32, System.Base64FormattingOptions)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToBoolean(System.Char)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToBoolean(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToByte(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToChar(System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToChar(System.Char)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToChar(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToChar(System.Decimal)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToChar(System.Double)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToChar(System.Single)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.Byte)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.Char)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.Decimal)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.Double)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.Int16)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.SByte)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.Single)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.UInt16)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.UInt32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDateTime(System.UInt64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDecimal(System.Char)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDecimal(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDouble(System.Char)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToDouble(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToInt16(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToInt32(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToInt64(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToSByte(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToSingle(System.Char)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToSingle(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToString(System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToString(System.String, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToUInt16(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToUInt32(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Convert.ToUInt64(System.DateTime)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.BigMul(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.Byte, System.Byte, System.Byte)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.Decimal, System.Decimal, System.Decimal)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.Double, System.Double, System.Double)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.Int16, System.Int16, System.Int16)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.Int32, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.Int64, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.SByte, System.SByte, System.SByte)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.Single, System.Single, System.Single)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.UInt16, System.UInt16, System.UInt16)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.UInt32, System.UInt32, System.UInt32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.Clamp(System.UInt64, System.UInt64, System.UInt64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.DivRem(System.Int32, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Math.DivRem(System.Int64, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.MathF' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Progress<T>' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.ResolveEventHandler' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.StringComparer.Compare(System.Object, System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.StringComparer.Create(System.Globalization.CultureInfo, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.StringComparer.GetHashCode(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.StringComparer.InvariantCulture.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.StringComparer.InvariantCultureIgnoreCase.get()' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.IO.BufferedStream' does not inherit from base type 'System.MarshalByRefObject' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.IO.EndOfStreamException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.IO.MemoryStream' does not inherit from base type 'System.MarshalByRefObject' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.IO.TextReader.Synchronized(System.IO.TextReader)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.IO.TextWriter.Synchronized(System.IO.TextWriter)' does not exist in the implementation but it does exist in the contract.
+Total Issues: 75
diff --git a/src/System.Runtime.Extensions/src/Configurations.props b/src/System.Runtime.Extensions/src/Configurations.props
index cba71331f4..8659b03c29 100644
--- a/src/System.Runtime.Extensions/src/Configurations.props
+++ b/src/System.Runtime.Extensions/src/Configurations.props
@@ -4,8 +4,7 @@
<BuildConfigurations>
netstandard-Unix;
netstandard-Windows_NT;
- net462-Windows_NT;
- net463-Windows_NT;
+ net461-Windows_NT;
uap101aot-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Runtime.Extensions/src/Resources/Strings.netcore50aot.resx b/src/System.Runtime.Extensions/src/Resources/Strings.netcore50aot.resx
deleted file mode 100644
index 8a3419ed65..0000000000
--- a/src/System.Runtime.Extensions/src/Resources/Strings.netcore50aot.resx
+++ /dev/null
@@ -1,231 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
- <!--
- Microsoft ResX Schema
-
- Version 2.0
-
- The primary goals of this format is to allow a simple XML format
- that is mostly human readable. The generation and parsing of the
- various data types are done through the TypeConverter classes
- associated with the data types.
-
- Example:
-
- ... ado.net/XML headers & schema ...
- <resheader name="resmimetype">text/microsoft-resx</resheader>
- <resheader name="version">2.0</resheader>
- <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
- <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
- <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
- <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
- <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
- <value>[base64 mime encoded serialized .NET Framework object]</value>
- </data>
- <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
- <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
- <comment>This is a comment</comment>
- </data>
-
- There are any number of "resheader" rows that contain simple
- name/value pairs.
-
- Each data row contains a name, and value. The row also contains a
- type or mimetype. Type corresponds to a .NET class that support
- text/value conversion through the TypeConverter architecture.
- Classes that don't support this are serialized and stored with the
- mimetype set.
-
- The mimetype is used for serialized objects, and tells the
- ResXResourceReader how to depersist the object. This is currently not
- extensible. For a given mimetype the value must be set accordingly:
-
- Note - application/x-microsoft.net.object.binary.base64 is the format
- that the ResXResourceWriter will generate, however the reader can
- read any of the formats listed below.
-
- mimetype: application/x-microsoft.net.object.binary.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.soap.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.bytearray.base64
- value : The object must be serialized into a byte array
- : using a System.ComponentModel.TypeConverter
- : and then encoded with base64 encoding.
- -->
- <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
- <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
- <xsd:element name="root" msdata:IsDataSet="true">
- <xsd:complexType>
- <xsd:choice maxOccurs="unbounded">
- <xsd:element name="metadata">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" />
- </xsd:sequence>
- <xsd:attribute name="name" use="required" type="xsd:string" />
- <xsd:attribute name="type" type="xsd:string" />
- <xsd:attribute name="mimetype" type="xsd:string" />
- <xsd:attribute ref="xml:space" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="assembly">
- <xsd:complexType>
- <xsd:attribute name="alias" type="xsd:string" />
- <xsd:attribute name="name" type="xsd:string" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="data">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
- <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
- <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
- <xsd:attribute ref="xml:space" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="resheader">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required" />
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- </xsd:complexType>
- </xsd:element>
- </xsd:schema>
- <resheader name="resmimetype">
- <value>text/microsoft-resx</value>
- </resheader>
- <resheader name="version">
- <value>2.0</value>
- </resheader>
- <resheader name="reader">
- <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
- <resheader name="writer">
- <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
- <data name="ArgumentOutOfRange_NeedNonNegNum" xml:space="preserve">
- <value>Non-negative number required.</value>
- </data>
- <data name="ArgumentOutOfRange_SmallCapacity" xml:space="preserve">
- <value>capacity was less than the current size.</value>
- </data>
- <data name="ArgumentNull_Stream" xml:space="preserve">
- <value>Stream cannot be null.</value>
- </data>
- <data name="Argument_InvalidSeekOrigin" xml:space="preserve">
- <value>Invalid seek origin.</value>
- </data>
- <data name="IO_IO_SeekBeforeBegin" xml:space="preserve">
- <value>An attempt was made to move the position before the beginning of the stream.</value>
- </data>
- <data name="ArgumentOutOfRange_StreamLength" xml:space="preserve">
- <value>Stream length must be non-negative and less than 2^31 - 1 - origin.</value>
- </data>
- <data name="NotSupported_MemStreamNotExpandable" xml:space="preserve">
- <value>Memory stream is not expandable.</value>
- </data>
- <data name="IO_IO_StreamTooLong" xml:space="preserve">
- <value>Stream was too long.</value>
- </data>
- <data name="ArgumentOutOfRange_NegativeCapacity" xml:space="preserve">
- <value>Capacity must be positive.</value>
- </data>
- <data name="NotSupported_UnwritableStream" xml:space="preserve">
- <value>Stream does not support writing.</value>
- </data>
- <data name="NotSupported_UnreadableStream" xml:space="preserve">
- <value>Stream does not support reading.</value>
- </data>
- <data name="ObjectDisposed_StreamClosed" xml:space="preserve">
- <value>Cannot access a closed Stream.</value>
- </data>
- <data name="InvalidOperation_TimeoutsNotSupported" xml:space="preserve">
- <value>Timeouts are not supported on this stream.</value>
- </data>
- <data name="ObjectDisposed_ReaderClosed" xml:space="preserve">
- <value>Cannot read from a closed TextReader.</value>
- </data>
- <data name="ArgumentOutOfRange_NeedPosNum" xml:space="preserve">
- <value>Positive number required.</value>
- </data>
- <data name="InvalidOperation_AsyncIOInProgress" xml:space="preserve">
- <value>The stream is currently in use by a previous operation on the stream.</value>
- </data>
- <data name="Argument_StreamNotReadable" xml:space="preserve">
- <value>Stream was not readable.</value>
- </data>
- <data name="ObjectDisposed_FileClosed" xml:space="preserve">
- <value>Cannot access a closed file.</value>
- </data>
- <data name="IO_EOF_ReadBeyondEOF" xml:space="preserve">
- <value>Unable to read beyond the end of the stream.</value>
- </data>
- <data name="Arg_DecBitCtor" xml:space="preserve">
- <value>Decimal byte array constructor requires an array of length four containing valid decimal bytes.</value>
- </data>
- <data name="IO_IO_InvalidStringLen_Len" xml:space="preserve">
- <value>BinaryReader encountered an invalid string length of {0} characters.</value>
- </data>
- <data name="ArgumentNull_Buffer" xml:space="preserve">
- <value>Buffer cannot be null.</value>
- </data>
- <data name="Argument_InvalidOffLen" xml:space="preserve">
- <value>Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.</value>
- </data>
- <data name="ArgumentOutOfRange_BinaryReaderFillBuffer" xml:space="preserve">
- <value>The number of bytes requested does not fit into BinaryReader's internal buffer.</value>
- </data>
- <data name="Format_Bad7BitInt32" xml:space="preserve">
- <value>Too many bytes in what should have been a 7 bit encoded Int32.</value>
- </data>
- <data name="Argument_StreamNotWritable" xml:space="preserve">
- <value>Stream was not writable.</value>
- </data>
- <data name="Arg_SurrogatesNotAllowedAsSingleChar" xml:space="preserve">
- <value>Unicode surrogate characters must be written out as pairs together in the same call, not individually. Consider passing in a character array instead.</value>
- </data>
- <data name="Arg_EndOfStreamException" xml:space="preserve">
- <value>Attempted to read past the end of the stream.</value>
- </data>
- <data name="ObjectDisposed_WriterClosed" xml:space="preserve">
- <value>Cannot write to a closed TextWriter.</value>
- </data>
- <data name="GenericInvalidData" xml:space="preserve">
- <value>Found invalid data while decoding.</value>
- </data>
- <data name="Arg_DirectoryNotFoundException" xml:space="preserve">
- <value>Attempted to access a path that is not on the disk.</value>
- </data>
- <data name="InvalidOperation_Calling" xml:space="preserve">
- <value>WinRT Interop has already been initialized and cannot be initialized again.</value>
- </data>
- <data name="ArgumentOutOfRange_MustBePositive" xml:space="preserve">
- <value>'{0}' must be greater than zero.</value>
- </data>
- <data name="NotSupported_UnseekableStream" xml:space="preserve">
- <value>Stream does not support seeking.</value>
- </data>
- <data name="NotSupported_CannotWriteToBufferedStreamIfReadBufferCannotBeFlushed" xml:space="preserve">
- <value>Cannot write to a BufferedStream while the read buffer is not empty if the underlying stream is not seekable. Ensure that the stream underlying this BufferedStream can seek or avoid interleaving read and write operations on this BufferedStream.</value>
- </data>
- <data name="UnauthorizedAccess_MemStreamBuffer" xml:space="preserve">
- <value>MemoryStream's internal buffer cannot be accessed.</value>
- </data>
- <data name="Argument_EmptyPath" xml:space="preserve">
- <value>Empty path name is not legal.</value>
- </data>
-</root> \ No newline at end of file
diff --git a/src/System.Runtime.Extensions/src/Resources/Strings.resx b/src/System.Runtime.Extensions/src/Resources/Strings.resx
index 14fc6e899d..cf5d0ec6a9 100644
--- a/src/System.Runtime.Extensions/src/Resources/Strings.resx
+++ b/src/System.Runtime.Extensions/src/Resources/Strings.resx
@@ -525,4 +525,52 @@
<data name="Argument_InvalidFlag" xml:space="preserve">
<value>Value of flags is invalid.</value>
</data>
-</root> \ No newline at end of file
+ <data name="ObjectDisposed_FileClosed" xml:space="preserve">
+ <value>Cannot access a closed file.</value>
+ </data>
+ <data name="IO_EOF_ReadBeyondEOF" xml:space="preserve">
+ <value>Unable to read beyond the end of the stream.</value>
+ </data>
+ <data name="IO_IO_SeekBeforeBegin" xml:space="preserve">
+ <value>An attempt was made to move the position before the beginning of the stream.</value>
+ </data>
+ <data name="ArgumentOutOfRange_StreamLength" xml:space="preserve">
+ <value>Stream length must be non-negative and less than 2^31 - 1 - origin.</value>
+ </data>
+ <data name="NotSupported_MemStreamNotExpandable" xml:space="preserve">
+ <value>Memory stream is not expandable.</value>
+ </data>
+ <data name="IO_IO_StreamTooLong" xml:space="preserve">
+ <value>Stream was too long.</value>
+ </data>
+ <data name="ArgumentOutOfRange_NegativeCapacity" xml:space="preserve">
+ <value>Capacity must be positive.</value>
+ </data>
+ <data name="ArgumentOutOfRange_BinaryReaderFillBuffer" xml:space="preserve">
+ <value>The number of bytes requested does not fit into BinaryReader's internal buffer.</value>
+ </data>
+ <data name="Format_Bad7BitInt32" xml:space="preserve">
+ <value>Too many bytes in what should have been a 7 bit encoded Int32.</value>
+ </data>
+ <data name="UnauthorizedAccess_MemStreamBuffer" xml:space="preserve">
+ <value>MemoryStream's internal buffer cannot be accessed.</value>
+ </data>
+ <data name="Argument_InvalidSeekOrigin" xml:space="preserve">
+ <value>Invalid seek origin.</value>
+ </data>
+ <data name="ArgumentNull_Stream" xml:space="preserve">
+ <value>Stream cannot be null.</value>
+ </data>
+ <data name="Arg_EndOfStreamException" xml:space="preserve">
+ <value>Attempted to read past the end of the stream.</value>
+ </data>
+ <data name="Arg_SurrogatesNotAllowedAsSingleChar" xml:space="preserve">
+ <value>Unicode surrogate characters must be written out as pairs together in the same call, not individually. Consider passing in a character array instead.</value>
+ </data>
+ <data name="Arg_DecBitCtor" xml:space="preserve">
+ <value>Decimal byte array constructor requires an array of length four containing valid decimal bytes.</value>
+ </data>
+ <data name="IO_IO_InvalidStringLen_Len" xml:space="preserve">
+ <value>BinaryReader encountered an invalid string length of {0} characters.</value>
+ </data>
+</root>
diff --git a/src/System.Runtime.Extensions/src/System.Runtime.Extensions.csproj b/src/System.Runtime.Extensions/src/System.Runtime.Extensions.csproj
index 9872d1daed..ef1755cd87 100644
--- a/src/System.Runtime.Extensions/src/System.Runtime.Extensions.csproj
+++ b/src/System.Runtime.Extensions/src/System.Runtime.Extensions.csproj
@@ -4,8 +4,6 @@
<PropertyGroup>
<ProjectGuid>{845D2B72-D8A4-42E5-9BE9-17639EC4FC1A}</ProjectGuid>
<AssemblyName>System.Runtime.Extensions</AssemblyName>
- <AssemblyVersion Condition="'$(TargetGroup)'=='net462'">4.1.1.0</AssemblyVersion>
- <ContractProject Condition="'$(AssemblyVersion)'=='4.1.1.0'">../ref/4.1.0/System.Runtime.Extensions.depproj</ContractProject>
<OutputType>Library</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsPartialFacadeAssembly>true</IsPartialFacadeAssembly>
@@ -20,26 +18,21 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Unix_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net462_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net462_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_uap101aot_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_uap101aot_Release|AnyCPU'" />
<PropertyGroup Condition="'$(TargetsWindowsUap)' == 'true'">
<SkipCommonResourcesIncludes>true</SkipCommonResourcesIncludes>
- <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ExcludeAssemblyInfoPartialFile>true</ExcludeAssemblyInfoPartialFile>
- <StringResourcesPath>Resources\Strings.netcore50aot.resx</StringResourcesPath>
- <DefineConstants>$(DefineConstants);uap101aot</DefineConstants>
</PropertyGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<ContractProject Include="..\ref\System.Runtime.Extensions.csproj">
<TargetGroup>netstandard</TargetGroup>
</ContractProject>
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
- <Compile Include="System\AppDomain.cs" />
+ <ItemGroup Condition="'$(TargetGroup)' != 'net461'">
+ <Compile Include="System\AppDomain.cs" Condition="'$(TargetGroup)' != 'uap101aot' and '$(TargetGroup)' != 'netcoreapp1.2corert'" />
<Compile Include="System\Context.cs" />
<Compile Include="System\AppDomainUnloadedException.cs" />
<Compile Include="System\ApplicationId.cs" />
@@ -49,13 +42,11 @@
<Compile Include="System\Environment.cs" />
<Compile Include="System\Environment.SpecialFolder.cs" />
<Compile Include="System\Environment.SpecialFolderOption.cs" />
- <Compile Include="System\EnvironmentVariableTarget.cs" />
<Compile Include="System\LoaderOptimization.cs" />
<Compile Include="System\LoaderOptimizationAttribute.cs" />
<Compile Include="System\OperatingSystem.cs" />
<Compile Include="System\PlatformID.cs" />
<Compile Include="System\CodeDom\Compiler\IndentedTextWriter.cs" />
- <Compile Include="System\IO\Path.cs" />
<Compile Include="System\IO\EncodingCache.cs" />
<Compile Include="System\IO\StreamReader.cs" />
<Compile Include="System\IO\StreamWriter.cs" />
@@ -130,15 +121,10 @@
<Compile Include="System\IO\TextWriter.netstandard17.cs" />
</ItemGroup>
<!-- WINDOWS: Shared CoreCLR and .NET Native -->
- <ItemGroup Condition="'$(TargetsWindows)' == 'true' And '$(TargetGroup)' == 'netstandard'">
+ <ItemGroup Condition="'$(TargetsWindows)' == 'true' And '$(TargetGroup)' != 'net461'">
<Compile Include="System\Environment.Windows.cs" />
<Compile Include="System\Runtime\Versioning\VersioningHelper.Windows.cs" />
<Compile Include="System\Diagnostics\Stopwatch.Windows.cs" />
- <Compile Include="System\IO\Path.Windows.cs" />
- <Compile Include="System\IO\PathHelper.Windows.cs" />
- <Compile Include="$(CommonPath)\System\IO\DriveInfoInternal.Win32.cs">
- <Link>Common\System\IO\DriveInfoInternal.Win32.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\System\IO\Win32Marshal.cs">
<Link>Common\System\IO\Win32Marshal.cs</Link>
</Compile>
@@ -157,18 +143,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetCurrentDirectory.cs">
<Link>Common\Interop\Windows\kernel32\Interop.GetCurrentDirectory.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetFullPathNameW.cs">
- <Link>Common\Interop\Windows\kernel32\Interop.GetFullPathNameW.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetLogicalDrive.cs">
- <Link>Common\Interop\Windows\Interop.GetLogicalDrive.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetLongPathName.cs">
<Link>Common\Interop\Windows\kernel32\Interop.GetLongPathName.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetLongPathNameW.cs">
- <Link>Common\Interop\Windows\kernel32\Interop.GetLongPathNameW.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetSystemInfo.cs">
<Link>Common\Interop\Windows\kernel32\Interop.GetSystemInfo.cs</Link>
</Compile>
@@ -178,9 +155,6 @@
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetTempPathW.cs">
<Link>Common\Interop\Windows\kernel32\Interop.GetTempPathW.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetVersionExW.cs">
- <Link>Common\Interop\Windows\kernel32\Interop.GetVersionExW.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.MaxLengths.cs">
<Link>Common\Interop\Windows\kernel32\Interop.MaxLengths.cs</Link>
</Compile>
@@ -199,20 +173,14 @@
<Compile Include="$(CommonPath)\System\IO\PathInternal.Windows.cs">
<Link>Common\System\IO\PathInternal.Windows.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\System\IO\PathInternal.Windows.StringBuffer.cs">
- <Link>Common\System\IO\PathInternal.Windows.StringBuffer.cs</Link>
- </Compile>
+ </ItemGroup>
+ <!-- Win32 or Unix -->
+ <ItemGroup Condition="'$(TargetsUnix)' == 'true' or ('$(TargetsWindows)' == 'true' and '$(TargetGroup)' != 'net461' and '$(TargetsWindowsUap)' != 'true')">
+ <Compile Include="System\Environment.Win32.Unix.cs" />
</ItemGroup>
<!-- WINDOWS: Win32 -->
- <ItemGroup Condition="'$(TargetsWindows)' == 'true' And '$(TargetGroup)' == 'netstandard' and '$(TargetsWindowsUap)' != 'true'">
+ <ItemGroup Condition="'$(TargetsWindows)' == 'true' and '$(TargetGroup)' != 'net461' and '$(TargetsWindowsUap)' != 'true'">
<Compile Include="System\Environment.Win32.cs" />
- <Compile Include="System\IO\Path.Win32.cs" />
- <Compile Include="$(CommonPath)\Interop\Windows\BCrypt\Interop.BCryptGenRandom.cs">
- <Link>Common\Interop\Windows\BCrypt\Interop.BCryptGenRandom.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\BCrypt\Interop.NTSTATUS.cs">
- <Link>Common\Interop\Windows\BCrypt\Interop.NTSTATUS.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.EnvironmentVariables.cs">
<Link>Common\Interop\Windows\kernel32\Interop.EnvironmentVariables.cs</Link>
</Compile>
@@ -222,6 +190,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetCurrentProcess_IntPtr.cs">
<Link>Common\Interop\Windows\kernel32\Interop.GetCurrentProcess_IntPtr.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetLogicalDrive.cs">
+ <Link>Common\Interop\Windows\Interop.GetLogicalDrive.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetLogicalProcessorInformationEx.cs">
<Link>Common\Interop\Windows\kernel32\Interop.GetLogicalProcessorInformationEx.cs</Link>
</Compile>
@@ -231,6 +202,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\sspicli\Interop.GetUserNameExW.cs">
<Link>Common\Interop\Windows\sspicli\Interop.GetUserNameExW.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetVersionExW.cs">
+ <Link>Common\Interop\Windows\kernel32\Interop.GetVersionExW.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.IsWow64Process_IntPtr.cs">
<Link>Common\Interop\Windows\kernel32\Interop.IsWow64Process_IntPtr.cs</Link>
</Compile>
@@ -240,87 +214,8 @@
<Compile Include="$(CommonPath)\Interop\Windows\shell32\Interop.SHGetKnownFolderPath.cs">
<Link>Common\Interop\Windows\shell32\Interop.SHGetKnownFolderPath.cs</Link>
</Compile>
- <!-- Microsoft.Win32.Registry, needed for some Environment env var support -->
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\Registry.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\Registry.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryKey.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryKey.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryHive.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryHive.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryOptions.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryOptions.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryValueKind.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryValueKind.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryValueOptions.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryValueOptions.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryView.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryView.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryKey.Windows.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\Registry.Windows.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\SafeHandles\SafeRegistryHandle.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\SafeHandles\SafeRegistryHandle.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\SafeHandles\SafeRegistryHandle.Windows.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\SafeHandles\SafeRegistryHandle.Windows.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\Microsoft\Win32\ThrowHelper.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\ThrowHelper.cs</Link>
- </Compile>
- <Compile Include="..\..\Microsoft.Win32.Registry\src\System\Security\AccessControl\RegistryRights.cs">
- <Link>Microsoft.Win32.Registry\src\Microsoft\Win32\RegistryRights.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegCloseKey.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegCloseKey.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegConnectRegistry.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegConnectRegistry.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegCreateKeyEx.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegCreateKeyEx.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegDeleteKeyEx.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegDeleteKeyEx.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegDeleteValue.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegDeleteValue.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegEnumKeyEx.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegEnumKeyEx.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegEnumValue.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegEnumValue.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegFlushKey.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegFlushKey.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegOpenKeyEx.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegOpenKeyEx.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegQueryInfoKey.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegQueryInfoKey.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegQueryValueEx.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegQueryValueEx.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegSetValueEx.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegSetValueEx.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.RegistryOptions.cs">
- <Link>Common\Interop\Windows\advapi32\Interop.RegistryOptions.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\Interop.BOOL.cs">
- <Link>Common\Interop\Windows\mincore\Interop.BOOL.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SECURITY_ATTRIBUTES.cs">
- <Link>Common\Interop\Windows\kernel32\Interop.SECURITY_ATTRIBUTES.cs</Link>
+ <Compile Include="$(CommonPath)\System\IO\DriveInfoInternal.Win32.cs">
+ <Link>Common\System\IO\DriveInfoInternal.Win32.cs</Link>
</Compile>
</ItemGroup>
<!-- UNIX -->
@@ -328,13 +223,9 @@
<Compile Include="System\Environment.Unix.cs" />
<Compile Include="System\Runtime\Versioning\VersioningHelper.Unix.cs" />
<Compile Include="System\Diagnostics\Stopwatch.Unix.cs" />
- <Compile Include="System\IO\Path.Unix.cs" />
<Compile Include="$(CommonPath)\Interop\OSX\Interop.Libraries.cs">
<Link>Common\Interop\OSX\Interop.Libraries.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Interop\OSX\Interop.CommonCrypto.cs">
- <Link>Common\Interop\OSX\Interop.CommonCrypto.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Interop\Unix\Interop.Libraries.cs">
<Link>Common\Interop\Unix\Interop.Libraries.cs</Link>
</Compile>
@@ -359,9 +250,6 @@
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetCwd.cs">
<Link>Common\Interop\Unix\System.Native\Interop.GetCwd.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetEnviron.cs">
- <Link>Common\Interop\Unix\System.Native\Interop.GetEnviron.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetEUid.cs">
<Link>Common\Interop\Unix\System.Native\Interop.GetEUid.cs</Link>
</Compile>
@@ -392,11 +280,8 @@
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.SysConf.cs">
<Link>Common\Interop\Unix\System.Native\Interop.SysConf.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Interop\Unix\System.Security.Cryptography.Native\Interop.Initialization.cs">
- <Link>Common\Interop\Unix\System.Security.Cryptography.Native\Interop.Initialization.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\Interop\Unix\System.Security.Cryptography.Native\Interop.RAND.cs">
- <Link>Common\Interop\Unix\System.Security.Cryptography.Native\Interop.RAND.cs</Link>
+ <Compile Include="$(CommonPath)\System\IO\DriveInfoInternal.Unix.cs">
+ <Link>Common\System\IO\DriveInfoInternal.Unix.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\System\IO\PathInternal.Unix.cs">
<Link>Common\System\IO\PathInternal.Unix.cs</Link>
@@ -411,15 +296,28 @@
<!-- WINDOWS: UAP -->
<ItemGroup Condition="'$(TargetsWindowsUap)' == 'true'">
<Compile Include="System\Environment.Uap.cs" />
+ <Compile Include="System\EnvironmentVariableTarget.cs" />
+ <Compile Include="System\IO\Path.cs" />
+ <Compile Include="System\IO\Path.Windows.cs" />
+ <Compile Include="System\IO\PathHelper.Windows.cs" />
<Compile Include="System\IO\Path.Uap.cs" />
+ <Compile Include="$(CommonPath)\System\IO\PathInternal.Windows.StringBuffer.cs">
+ <Link>Common\System\IO\PathInternal.Windows.StringBuffer.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetFullPathNameW.cs">
+ <Link>Common\Interop\Windows\kernel32\Interop.GetFullPathNameW.cs</Link>
+ </Compile>
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetLongPathNameW.cs">
+ <Link>Common\Interop\Windows\kernel32\Interop.GetLongPathNameW.cs</Link>
+ </Compile>
<Compile Include="System\IO\BinaryReader.cs" />
<Compile Include="System\IO\BinaryWriter.cs" />
+ <Compile Include="System\IO\FileStreamHelpers.Uap.cs" />
<Compile Include="System\IO\EndOfStreamException.cs" />
<Compile Include="System\IO\MemoryStream.cs" />
- <Compile Include="$(CommonPath)\System\SystemException.cs" />
- <Compile Include="System\Net\Configuration\UnicodeDecodingConformance.cs" />
- <Compile Include="System\Net\Configuration\UnicodeEncodingConformance.cs" />
- <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetLastError.cs" Condition="'$(TargetsWindows)'=='true'" />
+ <Compile Include="$(CommonPath)\System\IO\DriveInfoInternal.Uap.cs">
+ <Link>Common\System\IO\DriveInfoInternal.Uap.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\System\SR.Core.cs" />
</ItemGroup>
<ItemGroup>
@@ -434,7 +332,7 @@
</ProjectReference>
<ProjectReference Include="..\..\System.Runtime\src\System.Runtime.csproj" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net462' Or '$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System" />
</ItemGroup>
@@ -444,9 +342,8 @@
<ItemGroup Condition="'$(TargetsWindowsUap)' == 'true'">
<TargetingPackReference Include="System.Private.Interop" />
<ProjectReference Include="$(SourceDir)/mscorlib.WinRT-Facade/mscorlib.WinRT-Facade.csproj" />
- <ProjectReference Include="..\..\System.Runtime\src\System.Runtime.depproj">
- <TargetGroup>uap101aot</TargetGroup>
- </ProjectReference>
+ <ProjectReference Include="..\..\System.Runtime\src\System.Runtime.csproj" />
+ <ProjectReference Include="..\..\System.Private.Uri\src\System.Private.Uri.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Private.CoreLib" />
diff --git a/src/System.Runtime.Extensions/src/System/BitConverter.cs b/src/System.Runtime.Extensions/src/System/BitConverter.cs
index 62475d582d..f9542af45e 100644
--- a/src/System.Runtime.Extensions/src/System/BitConverter.cs
+++ b/src/System.Runtime.Extensions/src/System/BitConverter.cs
@@ -45,7 +45,7 @@ namespace System
// Converts a short into an array of bytes with length
// two.
[System.Security.SecuritySafeCritical] // auto-generated
- public unsafe static byte[] GetBytes(short value)
+ public static unsafe byte[] GetBytes(short value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 2);
@@ -59,7 +59,7 @@ namespace System
// Converts an int into an array of bytes with length
// four.
[System.Security.SecuritySafeCritical] // auto-generated
- public unsafe static byte[] GetBytes(int value)
+ public static unsafe byte[] GetBytes(int value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 4);
@@ -73,7 +73,7 @@ namespace System
// Converts a long into an array of bytes with length
// eight.
[System.Security.SecuritySafeCritical] // auto-generated
- public unsafe static byte[] GetBytes(long value)
+ public static unsafe byte[] GetBytes(long value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 8);
@@ -120,7 +120,7 @@ namespace System
// Converts a float into an array of bytes with length
// four.
[System.Security.SecuritySafeCritical] // auto-generated
- public unsafe static byte[] GetBytes(float value)
+ public static unsafe byte[] GetBytes(float value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 4);
@@ -131,7 +131,7 @@ namespace System
// Converts a double into an array of bytes with length
// eight.
[System.Security.SecuritySafeCritical] // auto-generated
- public unsafe static byte[] GetBytes(double value)
+ public static unsafe byte[] GetBytes(double value)
{
Contract.Ensures(Contract.Result<byte[]>() != null);
Contract.Ensures(Contract.Result<byte[]>().Length == 8);
@@ -298,7 +298,7 @@ namespace System
// Converts an array of bytes into a float.
[System.Security.SecuritySafeCritical] // auto-generated
- public unsafe static float ToSingle(byte[] value, int startIndex)
+ public static unsafe float ToSingle(byte[] value, int startIndex)
{
if (value == null)
ThrowValueArgumentNull();
@@ -314,7 +314,7 @@ namespace System
// Converts an array of bytes into a double.
[System.Security.SecuritySafeCritical] // auto-generated
- public unsafe static double ToDouble(byte[] value, int startIndex)
+ public static unsafe double ToDouble(byte[] value, int startIndex)
{
if (value == null)
ThrowValueArgumentNull();
diff --git a/src/System.Runtime.Extensions/src/System/Context.cs b/src/System.Runtime.Extensions/src/System/Context.cs
index 5d0ffefc3a..2520873586 100644
--- a/src/System.Runtime.Extensions/src/System/Context.cs
+++ b/src/System.Runtime.Extensions/src/System/Context.cs
@@ -38,7 +38,6 @@ namespace System
[Serializable]
[AttributeUsage(AttributeTargets.Field, Inherited = false)]
- [System.Runtime.InteropServices.ComVisible(true)]
public partial class ContextStaticAttribute : System.Attribute
{
public ContextStaticAttribute() { }
diff --git a/src/System.Runtime.Extensions/src/System/Environment.Uap.cs b/src/System.Runtime.Extensions/src/System/Environment.Uap.cs
index 3781f39b91..226ce363ca 100644
--- a/src/System.Runtime.Extensions/src/System/Environment.Uap.cs
+++ b/src/System.Runtime.Extensions/src/System/Environment.Uap.cs
@@ -2,6 +2,7 @@
// 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.Collections.Generic;
namespace System
@@ -57,5 +58,104 @@ namespace System
public static string UserName { get { throw new PlatformNotSupportedException(); } }
public static string UserDomainName { get { throw new PlatformNotSupportedException(); } }
+
+
+ public static string GetEnvironmentVariable(string variable)
+ {
+ if (variable == null)
+ {
+ throw new ArgumentNullException(nameof(variable));
+ }
+
+ // separated from the EnvironmentVariableTarget overload to help with tree shaking in common case
+ return GetEnvironmentVariableCore(variable);
+ }
+
+ public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target)
+ {
+ if (variable == null)
+ {
+ throw new ArgumentNullException(nameof(variable));
+ }
+
+ ValidateTarget(target);
+
+ return GetEnvironmentVariableCore(variable, target);
+ }
+
+ public static IDictionary GetEnvironmentVariables()
+ {
+ // separated from the EnvironmentVariableTarget overload to help with tree shaking in common case
+ return GetEnvironmentVariablesCore();
+ }
+
+ public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target)
+ {
+ ValidateTarget(target);
+
+ return GetEnvironmentVariablesCore(target);
+ }
+
+ public static void SetEnvironmentVariable(string variable, string value)
+ {
+ ValidateVariableAndValue(variable, ref value);
+
+ // separated from the EnvironmentVariableTarget overload to help with tree shaking in common case
+ SetEnvironmentVariableCore(variable, value);
+ }
+
+ public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target)
+ {
+ ValidateVariableAndValue(variable, ref value);
+ ValidateTarget(target);
+
+ SetEnvironmentVariableCore(variable, value, target);
+ }
+
+ private static void ValidateVariableAndValue(string variable, ref string value)
+ {
+ const int MaxEnvVariableValueLength = 32767;
+
+ if (variable == null)
+ {
+ throw new ArgumentNullException(nameof(variable));
+ }
+ if (variable.Length == 0)
+ {
+ throw new ArgumentException(SR.Argument_StringZeroLength, nameof(variable));
+ }
+ if (variable[0] == '\0')
+ {
+ throw new ArgumentException(SR.Argument_StringFirstCharIsZero, nameof(variable));
+ }
+ if (variable.Length >= MaxEnvVariableValueLength)
+ {
+ throw new ArgumentException(SR.Argument_LongEnvVarValue, nameof(variable));
+ }
+ if (variable.IndexOf('=') != -1)
+ {
+ throw new ArgumentException(SR.Argument_IllegalEnvVarName, nameof(variable));
+ }
+
+ if (string.IsNullOrEmpty(value) || value[0] == '\0')
+ {
+ // Explicitly null out value if it's empty
+ value = null;
+ }
+ else if (value.Length >= MaxEnvVariableValueLength)
+ {
+ throw new ArgumentException(SR.Argument_LongEnvVarValue, nameof(value));
+ }
+ }
+
+ private static void ValidateTarget(EnvironmentVariableTarget target)
+ {
+ if (target != EnvironmentVariableTarget.Process &&
+ target != EnvironmentVariableTarget.Machine &&
+ target != EnvironmentVariableTarget.User)
+ {
+ throw new ArgumentOutOfRangeException(nameof(target), target, SR.Format(SR.Arg_EnumIllegalVal, target));
+ }
+ }
}
}
diff --git a/src/System.Runtime.Extensions/src/System/Environment.Unix.cs b/src/System.Runtime.Extensions/src/System/Environment.Unix.cs
index 449d201f4e..3d01bfa839 100644
--- a/src/System.Runtime.Extensions/src/System/Environment.Unix.cs
+++ b/src/System.Runtime.Extensions/src/System/Environment.Unix.cs
@@ -16,28 +16,6 @@ namespace System
{
public static partial class Environment
{
- private static readonly unsafe Lazy<LowLevelDictionary<string, string>> s_environ = new Lazy<LowLevelDictionary<string, string>>(() =>
- {
- var results = new LowLevelDictionary<string, string>();
- byte** environ = Interop.Sys.GetEnviron();
- if (environ != null)
- {
- for (byte** ptr = environ; *ptr != null; ptr++)
- {
- string entry = Marshal.PtrToStringAnsi((IntPtr)(*ptr));
- int equalsPos = entry.IndexOf('=');
- if (equalsPos != -1)
- {
- results.Add(entry.Substring(0, equalsPos), entry.Substring(equalsPos + 1));
- }
- else
- {
- results.Add(entry, string.Empty);
- }
- }
- }
- return results;
- });
internal static readonly bool IsMac = Interop.Sys.GetUnixName() == "OSX";
private static Func<string, IEnumerable<string>> s_fileReadLines;
private static Action<string> s_directoryCreateDirectory;
@@ -76,45 +54,6 @@ namespace System
return StringBuilderCache.GetStringAndRelease(result);
}
- private static string GetEnvironmentVariableCore(string variable)
- {
- // Ensure variable doesn't include a null char
- int nullEnd = variable.IndexOf('\0');
- if (nullEnd != -1)
- {
- variable = variable.Substring(0, nullEnd);
- }
-
- // Get the value of the variable
- lock (s_environ)
- {
- string value;
- return s_environ.Value.TryGetValue(variable, out value) ? value : null;
- }
- }
-
- private static string GetEnvironmentVariableCore(string variable, EnvironmentVariableTarget target)
- {
- return target == EnvironmentVariableTarget.Process ?
- GetEnvironmentVariableCore(variable) :
- null;
- }
-
- private static IDictionary GetEnvironmentVariablesCore()
- {
- lock (s_environ)
- {
- return s_environ.Value.Clone();
- }
- }
-
- private static IDictionary GetEnvironmentVariablesCore(EnvironmentVariableTarget target)
- {
- return target == EnvironmentVariableTarget.Process ?
- GetEnvironmentVariablesCore() :
- new LowLevelDictionary<string, string>();
- }
-
private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option)
{
// Get the path for the SpecialFolder
@@ -419,50 +358,6 @@ namespace System
public static int ProcessorCount => (int)Interop.Sys.SysConf(Interop.Sys.SysConfName._SC_NPROCESSORS_ONLN);
- private static void SetEnvironmentVariableCore(string variable, string value)
- {
- int nullEnd;
-
- // Ensure variable doesn't include a null char
- nullEnd = variable.IndexOf('\0');
- if (nullEnd != -1)
- {
- variable = variable.Substring(0, nullEnd);
- }
-
- // Ensure value doesn't include a null char
- if (value != null)
- {
- nullEnd = value.IndexOf('\0');
- if (nullEnd != -1)
- {
- value = value.Substring(0, nullEnd);
- }
- }
-
- lock (s_environ)
- {
- // Remove the entry if the value is null, otherwise add/overwrite it
- if (value == null)
- {
- s_environ.Value.Remove(variable);
- }
- else
- {
- s_environ.Value[variable] = value;
- }
- }
- }
-
- private static void SetEnvironmentVariableCore(string variable, string value, EnvironmentVariableTarget target)
- {
- if (target == EnvironmentVariableTarget.Process)
- {
- SetEnvironmentVariableCore(variable, value);
- }
- // other targets ignored
- }
-
public static string SystemDirectory => GetFolderPathCore(SpecialFolder.System, SpecialFolderOption.None);
public static int SystemPageSize => (int)Interop.Sys.SysConf(Interop.Sys.SysConfName._SC_PAGESIZE);
diff --git a/src/System.Runtime.Extensions/src/System/Environment.Win32.Unix.cs b/src/System.Runtime.Extensions/src/System/Environment.Win32.Unix.cs
new file mode 100644
index 0000000000..862a732f42
--- /dev/null
+++ b/src/System.Runtime.Extensions/src/System/Environment.Win32.Unix.cs
@@ -0,0 +1,50 @@
+// 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 Internal.Runtime.Augments;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System
+{
+ public static partial class Environment
+ {
+ public static string GetEnvironmentVariable(string variable)
+ {
+ return EnvironmentAugments.GetEnvironmentVariable(variable);
+ }
+
+ public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target)
+ {
+ return EnvironmentAugments.GetEnvironmentVariable(variable, target);
+ }
+
+ public static IDictionary GetEnvironmentVariables()
+ {
+ // To maintain complete compatibility with prior versions we need to return a Hashtable.
+ // We did ship a prior version of Core with LowLevelDictionary, which does iterate the
+ // same (e.g. yields DictionaryEntry), but it is not a public type.
+ //
+ // While we could pass Hashtable back from CoreCLR the type is also defined here. We only
+ // want to surface the local Hashtable.
+ return new Hashtable(EnvironmentAugments.GetEnvironmentVariables());
+ }
+
+ public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target)
+ {
+ // See comments in GetEnvironmentVariables()
+ return new Hashtable(EnvironmentAugments.GetEnvironmentVariables(target));
+ }
+
+ public static void SetEnvironmentVariable(string variable, string value)
+ {
+ EnvironmentAugments.SetEnvironmentVariable(variable, value);
+ }
+
+ public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target)
+ {
+ EnvironmentAugments.SetEnvironmentVariable(variable, value, target);
+ }
+ }
+}
diff --git a/src/System.Runtime.Extensions/src/System/Environment.Win32.cs b/src/System.Runtime.Extensions/src/System/Environment.Win32.cs
index 4f357039e9..ffdf5218d4 100644
--- a/src/System.Runtime.Extensions/src/System/Environment.Win32.cs
+++ b/src/System.Runtime.Extensions/src/System/Environment.Win32.cs
@@ -47,165 +47,6 @@ namespace System
return StringBuilderCache.GetStringAndRelease(result);
}
- private static string GetEnvironmentVariableCore(string variable)
- {
- StringBuilder sb = StringBuilderCache.Acquire(128); // a somewhat reasonable default size
- int requiredSize = Interop.Kernel32.GetEnvironmentVariableW(variable, sb, sb.Capacity);
- if (requiredSize == 0 && Marshal.GetLastWin32Error() == Interop.Errors.ERROR_ENVVAR_NOT_FOUND)
- {
- StringBuilderCache.Release(sb);
- return null;
- }
-
- while (requiredSize > sb.Capacity)
- {
- sb.Capacity = requiredSize;
- sb.Length = 0;
- requiredSize = Interop.Kernel32.GetEnvironmentVariableW(variable, sb, sb.Capacity);
- }
-
- return StringBuilderCache.GetStringAndRelease(sb);
- }
-
- private static string GetEnvironmentVariableCore(string variable, EnvironmentVariableTarget target)
- {
- if (target == EnvironmentVariableTarget.Process)
- {
- return GetEnvironmentVariableCore(variable);
- }
- else
- {
- RegistryKey baseKey;
- string keyName;
-
- if (target == EnvironmentVariableTarget.Machine)
- {
- baseKey = Registry.LocalMachine;
- keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
- }
- else
- {
- Debug.Assert(target == EnvironmentVariableTarget.User);
- baseKey = Registry.CurrentUser;
- keyName = "Environment";
- }
-
- using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: false))
- {
- return environmentKey?.GetValue(variable) as string;
- }
- }
- }
-
- private static IDictionary GetEnvironmentVariablesCore()
- {
- // Format for GetEnvironmentStrings is:
- // (=HiddenVar=value\0 | Variable=value\0)* \0
- // See the description of Environment Blocks in MSDN's
- // CreateProcess page (null-terminated array of null-terminated strings).
- // Note the =HiddenVar's aren't always at the beginning.
-
- // Copy strings out, parsing into pairs and inserting into the table.
- // The first few environment variable entries start with an '='.
- // The current working directory of every drive (except for those drives
- // you haven't cd'ed into in your DOS window) are stored in the
- // environment block (as =C:=pwd) and the program's exit code is
- // as well (=ExitCode=00000000).
-
- var results = new LowLevelDictionary<string, string>();
- char[] block = GetEnvironmentCharArray();
- for (int i = 0; i < block.Length; i++)
- {
- int startKey = i;
-
- // Skip to key. On some old OS, the environment block can be corrupted.
- // Some will not have '=', so we need to check for '\0'.
- while (block[i] != '=' && block[i] != '\0') i++;
- if (block[i] == '\0') continue;
-
- // Skip over environment variables starting with '='
- if (i - startKey == 0)
- {
- while (block[i] != 0) i++;
- continue;
- }
-
- string key = new string(block, startKey, i - startKey);
- i++; // skip over '='
-
- int startValue = i;
- while (block[i] != 0) i++; // Read to end of this entry
- string value = new string(block, startValue, i - startValue); // skip over 0 handled by for loop's i++
-
- results[key] = value;
- }
- return results;
- }
-
- private static IDictionary GetEnvironmentVariablesCore(EnvironmentVariableTarget target)
- {
- if (target == EnvironmentVariableTarget.Process)
- {
- return GetEnvironmentVariablesCore();
- }
- else
- {
- RegistryKey baseKey;
- string keyName;
- if (target == EnvironmentVariableTarget.Machine)
- {
- baseKey = Registry.LocalMachine;
- keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
- }
- else
- {
- Debug.Assert(target == EnvironmentVariableTarget.User);
- baseKey = Registry.CurrentUser;
- keyName = @"Environment";
- }
-
- using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: false))
- {
- var table = new LowLevelDictionary<string, string>();
- if (environmentKey != null)
- {
- foreach (string name in environmentKey.GetValueNames())
- {
- table.Add(name, environmentKey.GetValue(name, "").ToString());
- }
- }
- return table;
- }
- }
- }
-
- private unsafe static char[] GetEnvironmentCharArray()
- {
- // Format for GetEnvironmentStrings is:
- // [=HiddenVar=value\0]* [Variable=value\0]* \0
- // See the description of Environment Blocks in MSDN's
- // CreateProcess page (null-terminated array of null-terminated strings).
- char* pStrings = Interop.Kernel32.GetEnvironmentStringsW();
- if (pStrings == null)
- {
- throw new OutOfMemoryException();
- }
- try
- {
- // Search for terminating \0\0 (two unicode \0's).
- char* p = pStrings;
- while (!(*p == '\0' && *(p + 1) == '\0')) p++;
-
- var block = new char[(int)(p - pStrings + 1)];
- Marshal.Copy((IntPtr)pStrings, block, 0, block.Length);
- return block;
- }
- finally
- {
- Interop.Kernel32.FreeEnvironmentStringsW(pStrings); // ignore any cleanup error
- }
- }
-
private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option)
{
// We're using SHGetKnownFolderPath instead of SHGetFolderPath as SHGetFolderPath is
@@ -478,82 +319,12 @@ namespace System
return 0;
});
- private static void SetEnvironmentVariableCore(string variable, string value)
- {
- if (!Interop.Kernel32.SetEnvironmentVariableW(variable, value))
- {
- int errorCode = Marshal.GetLastWin32Error();
- switch (errorCode)
- {
- case Interop.Errors.ERROR_ENVVAR_NOT_FOUND: // Allow user to try to clear a environment variable
- return;
- case Interop.Errors.ERROR_FILENAME_EXCED_RANGE: // Fix inaccurate error code from Win32
- throw new ArgumentException(SR.Argument_LongEnvVarValue, nameof(value));
- default:
- throw new ArgumentException(Interop.Kernel32.GetMessage(errorCode));
- }
- }
- }
-
- private static void SetEnvironmentVariableCore(string variable, string value, EnvironmentVariableTarget target)
- {
- if (target == EnvironmentVariableTarget.Process)
- {
- SetEnvironmentVariableCore(variable, value);
- }
- else
- {
- RegistryKey baseKey;
- string keyName;
-
- if (target == EnvironmentVariableTarget.Machine)
- {
- baseKey = Registry.LocalMachine;
- keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
- }
- else
- {
- Debug.Assert(target == EnvironmentVariableTarget.User);
-
- // User-wide environment variables stored in the registry are limited to 255 chars for the environment variable name.
- const int MaxUserEnvVariableLength = 255;
- if (variable.Length >= MaxUserEnvVariableLength)
- {
- throw new ArgumentException(SR.Argument_LongEnvVarValue, nameof(variable));
- }
-
- baseKey = Registry.CurrentUser;
- keyName = "Environment";
- }
-
- using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: true))
- {
- if (environmentKey != null)
- {
- if (value == null)
- {
- environmentKey.DeleteValue(variable, throwOnMissingValue: false);
- }
- else
- {
- environmentKey.SetValue(variable, value);
- }
- }
- }
- }
-
- //// Desktop sends a WM_SETTINGCHANGE message to all windows. Not available on all platforms.
- //Interop.Kernel32.SendMessageTimeout(
- // new IntPtr(Interop.Kernel32.HWND_BROADCAST), Interop.Kernel32.WM_SETTINGCHANGE,
- // IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero);
- }
-
public static string SystemDirectory
{
get
{
- StringBuilder sb = StringBuilderCache.Acquire(Path.MaxPath);
- if (Interop.Kernel32.GetSystemDirectoryW(sb, Path.MaxPath) == 0)
+ StringBuilder sb = StringBuilderCache.Acquire(PathInternal.MaxShortPath);
+ if (Interop.Kernel32.GetSystemDirectoryW(sb, PathInternal.MaxShortPath) == 0)
{
StringBuilderCache.Release(sb);
throw Win32Marshal.GetExceptionForLastWin32Error();
diff --git a/src/System.Runtime.Extensions/src/System/Environment.cs b/src/System.Runtime.Extensions/src/System/Environment.cs
index 97bea9c5f8..2ee6efc7da 100644
--- a/src/System.Runtime.Extensions/src/System/Environment.cs
+++ b/src/System.Runtime.Extensions/src/System/Environment.cs
@@ -3,8 +3,6 @@
// See the LICENSE file in the project root for more information.
using Internal.Runtime.Augments;
-using System;
-using System.Collections;
using System.IO;
using System.Reflection;
using System.Text;
@@ -93,42 +91,6 @@ namespace System
public static string[] GetCommandLineArgs() => EnvironmentAugments.GetCommandLineArgs();
- public static string GetEnvironmentVariable(string variable)
- {
- if (variable == null)
- {
- throw new ArgumentNullException(nameof(variable));
- }
-
- // separated from the EnvironmentVariableTarget overload to help with tree shaking in common case
- return GetEnvironmentVariableCore(variable);
- }
-
- public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target)
- {
- if (variable == null)
- {
- throw new ArgumentNullException(nameof(variable));
- }
-
- ValidateTarget(target);
-
- return GetEnvironmentVariableCore(variable, target);
- }
-
- public static IDictionary GetEnvironmentVariables()
- {
- // separated from the EnvironmentVariableTarget overload to help with tree shaking in common case
- return GetEnvironmentVariablesCore();
- }
-
- public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target)
- {
- ValidateTarget(target);
-
- return GetEnvironmentVariablesCore(target);
- }
-
public static string GetFolderPath(SpecialFolder folder) => GetFolderPath(folder, SpecialFolderOption.None);
public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option)
@@ -151,58 +113,6 @@ namespace System
public static bool Is64BitProcess => IntPtr.Size == 8;
public static bool Is64BitOperatingSystem => Is64BitProcess || Is64BitOperatingSystemWhen32BitProcess;
-
- public static void SetEnvironmentVariable(string variable, string value)
- {
- ValidateVariableAndValue(variable, ref value);
-
- // separated from the EnvironmentVariableTarget overload to help with tree shaking in common case
- SetEnvironmentVariableCore(variable, value);
- }
-
- public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target)
- {
- ValidateVariableAndValue(variable, ref value);
- ValidateTarget(target);
-
- SetEnvironmentVariableCore(variable, value, target);
- }
-
- private static void ValidateVariableAndValue(string variable, ref string value)
- {
- const int MaxEnvVariableValueLength = 32767;
-
- if (variable == null)
- {
- throw new ArgumentNullException(nameof(variable));
- }
- if (variable.Length == 0)
- {
- throw new ArgumentException(SR.Argument_StringZeroLength, nameof(variable));
- }
- if (variable[0] == '\0')
- {
- throw new ArgumentException(SR.Argument_StringFirstCharIsZero, nameof(variable));
- }
- if (variable.Length >= MaxEnvVariableValueLength)
- {
- throw new ArgumentException(SR.Argument_LongEnvVarValue, nameof(variable));
- }
- if (variable.IndexOf('=') != -1)
- {
- throw new ArgumentException(SR.Argument_IllegalEnvVarName, nameof(variable));
- }
-
- if (string.IsNullOrEmpty(value) || value[0] == '\0')
- {
- // Explicitly null out value if it's empty
- value = null;
- }
- else if (value.Length >= MaxEnvVariableValueLength)
- {
- throw new ArgumentException(SR.Argument_LongEnvVarValue, nameof(value));
- }
- }
public static OperatingSystem OSVersion => s_osVersion.Value;
@@ -244,15 +154,5 @@ namespace System
return 0;
}
}
-
- private static void ValidateTarget(EnvironmentVariableTarget target)
- {
- if (target != EnvironmentVariableTarget.Process &&
- target != EnvironmentVariableTarget.Machine &&
- target != EnvironmentVariableTarget.User)
- {
- throw new ArgumentOutOfRangeException(nameof(target), target, SR.Format(SR.Arg_EnumIllegalVal, target));
- }
- }
}
}
diff --git a/src/System.Runtime.Extensions/src/System/IO/BinaryReader.cs b/src/System.Runtime.Extensions/src/System/IO/BinaryReader.cs
index 8070ccc643..4ca3a76482 100644
--- a/src/System.Runtime.Extensions/src/System/IO/BinaryReader.cs
+++ b/src/System.Runtime.Extensions/src/System/IO/BinaryReader.cs
@@ -654,7 +654,7 @@ namespace System.IO
} while (bytesRead < numBytes);
}
- internal protected int Read7BitEncodedInt()
+ protected internal int Read7BitEncodedInt()
{
// Read out an Int32 7 bits at a time. The high bit
// of the byte when on means to continue reading more bytes.
diff --git a/src/System.Runtime.Extensions/src/System/IO/BufferedStream.cs b/src/System.Runtime.Extensions/src/System/IO/BufferedStream.cs
index c27a448244..b771bce451 100644
--- a/src/System.Runtime.Extensions/src/System/IO/BufferedStream.cs
+++ b/src/System.Runtime.Extensions/src/System/IO/BufferedStream.cs
@@ -274,10 +274,10 @@ namespace System.IO
// If the underlying stream is not seekable AND we have something in the read buffer, then FlushRead would throw.
// We can either throw away the buffer resulting in data loss (!) or ignore the Flush.
// (We cannot throw because it would be a breaking change.) We opt into ignoring the Flush in that situation.
- if (!_stream.CanSeek)
- return;
-
- FlushRead();
+ if (_stream.CanSeek)
+ {
+ FlushRead();
+ }
// User streams may have opted to throw from Flush if CanWrite is false (although the abstract Stream does not do so).
// However, if we do not forward the Flush to the underlying stream, we may have problems when chaining several streams.
@@ -285,7 +285,8 @@ namespace System.IO
if (_stream.CanWrite)
_stream.Flush();
- Debug.Assert(_writePos == 0 && _readPos == 0 && _readLen == 0);
+ // If the Stream was seekable, then we should have called FlushRead which resets _readPos & _readLen.
+ Debug.Assert(_writePos == 0 && (!_stream.CanSeek || (_readPos == 0 && _readLen == 0)));
return;
}
@@ -326,18 +327,19 @@ namespace System.IO
// If the underlying stream is not seekable AND we have something in the read buffer, then FlushRead would throw.
// We can either throw away the buffer resulting in date loss (!) or ignore the Flush. (We cannot throw because it
// would be a breaking change.) We opt into ignoring the Flush in that situation.
- if (!_stream.CanSeek)
- return;
-
- FlushRead(); // not async; it uses Seek, but there's no SeekAsync
+ if (_stream.CanSeek)
+ {
+ FlushRead(); // not async; it uses Seek, but there's no SeekAsync
+ }
// User streams may have opted to throw from Flush if CanWrite is false (although the abstract Stream does not do so).
// However, if we do not forward the Flush to the underlying stream, we may have problems when chaining several streams.
// Let us make a best effort attempt:
- if (_stream.CanRead)
+ if (_stream.CanWrite)
await _stream.FlushAsync(cancellationToken).ConfigureAwait(false);
- Debug.Assert(_writePos == 0 && _readPos == 0 && _readLen == 0);
+ // If the Stream was seekable, then we should have called FlushRead which resets _readPos & _readLen.
+ Debug.Assert(_writePos == 0 && (!_stream.CanSeek || (_readPos == 0 && _readLen == 0)));
return;
}
diff --git a/src/System.Runtime.Extensions/src/System/IO/EndOfStreamException.cs b/src/System.Runtime.Extensions/src/System/IO/EndOfStreamException.cs
index 36ab4bf595..96aea80c81 100644
--- a/src/System.Runtime.Extensions/src/System/IO/EndOfStreamException.cs
+++ b/src/System.Runtime.Extensions/src/System/IO/EndOfStreamException.cs
@@ -6,7 +6,8 @@ using System.Runtime.Serialization;
namespace System.IO
{
- [Serializable]
+ // TODO: Uncomment for uap101aot build when base ctor available
+ //[Serializable]
public class EndOfStreamException : IOException
{
public EndOfStreamException()
diff --git a/src/System.Runtime.Extensions/src/System/IO/PathHelper.Windows.cs b/src/System.Runtime.Extensions/src/System/IO/PathHelper.Windows.cs
index f03f15c6a5..4ef4d5cddf 100644
--- a/src/System.Runtime.Extensions/src/System/IO/PathHelper.Windows.cs
+++ b/src/System.Runtime.Extensions/src/System/IO/PathHelper.Windows.cs
@@ -11,7 +11,7 @@ namespace System.IO
/// <summary>
/// Wrapper to help with path normalization.
/// </summary>
- unsafe internal class PathHelper
+ internal unsafe class PathHelper
{
// Can't be over 8.3 and be a short name
private const int MaxShortName = 12;
diff --git a/src/System.Runtime.Extensions/src/System/Net/Configuration/UnicodeDecodingConformance.cs b/src/System.Runtime.Extensions/src/System/Net/Configuration/UnicodeDecodingConformance.cs
deleted file mode 100644
index fc6ab3a3e1..0000000000
--- a/src/System.Runtime.Extensions/src/System/Net/Configuration/UnicodeDecodingConformance.cs
+++ /dev/null
@@ -1,58 +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.Diagnostics.CodeAnalysis;
-
-namespace System.Net.Configuration
-{
- /// <summary>
- /// Controls how Unicode characters are interpreted by the WebUtility.HtmlDecode routine.
- /// </summary>
- /// <remarks>
- /// See http://www.w3.org/International/questions/qa-escapes#bytheway for more information
- /// on how Unicode characters in the SMP are supposed to be encoded in HTML.
- /// </remarks>
- internal enum UnicodeDecodingConformance
- {
- /// <summary>
- /// The Unicode encoding behavior is determined by current application's
- /// TargetFrameworkAttribute. Framework40 and earlier gets Compat behavior; Framework45
- /// and later gets Strict behavior.
- /// </summary>
- Auto,
-
- /// <summary>
- /// Specifies that the incoming encoded data is checked for validity before being
- /// decoded. For example, an input string of "&amp;#144308;" would decode as U+233B4,
- /// but an input string of "&amp;#xD84C;&amp;#xDFB4;" would fail to decode properly.
- /// </summary>
- /// <remarks>
- /// Already-decoded data in the string is not checked for validity. For example, an
- /// input string of "\ud800" will result in an output string of "\ud800", as the
- /// already-decoded surrogate is skipped during decoding, even though it is unpaired.
- /// </remarks>
- Strict,
-
- /// <summary>
- /// Specifies that incoming data is not checked for validity before being decoded.
- /// For example, an input string of "&amp;#xD84C;" would decode as U+D84C, which is
- /// an unpaired surrogate. Additionally, the decoder does not understand code points
- /// in the SMP unless they're represented as HTML-encoded surrogates, so the input
- /// string "&amp;#144308;" would result in the output string "&amp;#144308;".
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Compat", Justification = "Shorthand for 'compatibility mode'.")]
- Compat,
-
- /// <summary>
- /// Similar to 'Compat' in that there are no validity checks, but the decoder also
- /// understands SMP code points. The input string "&amp;#144308;" will thus decode
- /// into the character U+233B4 correctly.
- /// </summary>
- /// <remarks>
- /// This switch is meant to provide maximum interoperability when the decoder doesn't
- /// know which format the provider is using to generate the encoded string.
- /// </remarks>
- Loose,
- }
-}
diff --git a/src/System.Runtime.Extensions/src/System/Net/Configuration/UnicodeEncodingConformance.cs b/src/System.Runtime.Extensions/src/System/Net/Configuration/UnicodeEncodingConformance.cs
deleted file mode 100644
index b361094bb8..0000000000
--- a/src/System.Runtime.Extensions/src/System/Net/Configuration/UnicodeEncodingConformance.cs
+++ /dev/null
@@ -1,45 +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.Diagnostics.CodeAnalysis;
-
-namespace System.Net.Configuration
-{
- /// <summary>
- /// Controls how Unicode characters are output by the WebUtility.HtmlEncode routine.
- /// </summary>
- /// <remarks>
- /// See http://www.w3.org/International/questions/qa-escapes#bytheway for more information
- /// on how Unicode characters in the SMP are supposed to be encoded in HTML.
- /// </remarks>
- internal enum UnicodeEncodingConformance
- {
- /// <summary>
- /// The Unicode encoding behavior is determined by current application's
- /// TargetFrameworkAttribute. Framework40 and earlier gets Compat behavior; Framework45
- /// and later gets Strict behavior.
- /// </summary>
- Auto,
-
- /// <summary>
- /// Specifies that individual UTF-16 surrogate code points are combined into a single
- /// SMP code point when a call to HtmlEncode takes place. For example, given the input
- /// string "\uD84C\uDFB4" (or "\U000233B4"), the output of HtmlEncode is "&amp;#144308;".
- /// </summary>
- /// <remarks>
- /// If the input is a malformed UTF-16 string, e.g. it contains unpaired surrogates,
- /// the bad code points will be replaced with U+FFFD (Unicode replacement char) before
- /// being HTML-encoded.
- /// </remarks>
- Strict,
-
- /// <summary>
- /// Specifies that individual UTF-16 surrogate code points are output as-is when a call to
- /// HtmlEncode takes place. For example, given a string "\uD84C\uDFB4" (or "\U000233B4"),
- /// the output of HtmlEncode is "\uD84C\uDFB4" (the input is not encoded).
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Compat", Justification = "Shorthand for 'compatibility mode'.")]
- Compat,
- }
-}
diff --git a/src/System.Runtime.Extensions/src/System/Reflection/AssemblyNameProxy.cs b/src/System.Runtime.Extensions/src/System/Reflection/AssemblyNameProxy.cs
index 6fe47cc651..9c4c60a7aa 100644
--- a/src/System.Runtime.Extensions/src/System/Reflection/AssemblyNameProxy.cs
+++ b/src/System.Runtime.Extensions/src/System/Reflection/AssemblyNameProxy.cs
@@ -6,7 +6,6 @@ namespace System.Reflection {
using System;
using System.Runtime.Versioning;
- [System.Runtime.InteropServices.ComVisible(true)]
public class AssemblyNameProxy : MarshalByRefObject
{
public AssemblyName GetAssemblyName(String assemblyFile)
diff --git a/src/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj b/src/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj
index 8173f0c8f1..4c8148131f 100644
--- a/src/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj
+++ b/src/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj
@@ -46,6 +46,7 @@
<Compile Include="System\IO\Path.GetRelativePath.cs" />
<Compile Include="System\MathTests.netcoreapp1.1.cs" />
<Compile Include="System\MathF.netcoreapp1.1.cs" />
+ <Compile Include="System\UnloadingAndProcessExitTests.netcoreapp1.1.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="System\Diagnostics\Stopwatch.cs" />
diff --git a/src/System.Runtime.Extensions/tests/System/Environment.GetEnvironmentVariable.cs b/src/System.Runtime.Extensions/tests/System/Environment.GetEnvironmentVariable.cs
index e5add5ba72..c0c45b7688 100644
--- a/src/System.Runtime.Extensions/tests/System/Environment.GetEnvironmentVariable.cs
+++ b/src/System.Runtime.Extensions/tests/System/Environment.GetEnvironmentVariable.cs
@@ -134,7 +134,55 @@ namespace System.Tests
}
}
+ public void EnumerateYieldsDictionaryEntryFromIEnumerable()
+ {
+ // GetEnvironmentVariables has always yielded DictionaryEntry from IEnumerable
+ IDictionary vars = Environment.GetEnvironmentVariables();
+ IEnumerator enumerator = ((IEnumerable)vars).GetEnumerator();
+ if (enumerator.MoveNext())
+ {
+ Assert.IsType<DictionaryEntry>(enumerator.Current);
+ }
+ else
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current);
+ }
+ }
+
#if netstandard17
+ public void EnvironmentVariablesAreHashtable()
+ {
+ // On NetFX, the type returned was always Hashtable
+ Assert.IsType<Hashtable>(Environment.GetEnvironmentVariables());
+ }
+
+ [InlineData(EnvironmentVariableTarget.Process)]
+ [InlineData(EnvironmentVariableTarget.Machine)]
+ [InlineData(EnvironmentVariableTarget.User)]
+ public void EnvironmentVariablesAreHashtable(EnvironmentVariableTarget target)
+ {
+ // On NetFX, the type returned was always Hashtable
+ Assert.IsType<Hashtable>(Environment.GetEnvironmentVariables(target));
+ }
+
+ [InlineData(EnvironmentVariableTarget.Process)]
+ [InlineData(EnvironmentVariableTarget.Machine)]
+ [InlineData(EnvironmentVariableTarget.User)]
+ public void EnumerateYieldsDictionaryEntryFromIEnumerable(EnvironmentVariableTarget target)
+ {
+ // GetEnvironmentVariables has always yielded DictionaryEntry from IEnumerable
+ IDictionary vars = Environment.GetEnvironmentVariables(target);
+ IEnumerator enumerator = ((IEnumerable)vars).GetEnumerator();
+ if (enumerator.MoveNext())
+ {
+ Assert.IsType<DictionaryEntry>(enumerator.Current);
+ }
+ else
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current);
+ }
+ }
+
[OuterLoop] // manipulating environment variables broader in scope than the process
[Theory]
[InlineData(EnvironmentVariableTarget.Process)]
diff --git a/src/System.Runtime.Extensions/tests/System/EnvironmentTests.cs b/src/System.Runtime.Extensions/tests/System/EnvironmentTests.cs
index 86ed3a434b..51561a2ad3 100644
--- a/src/System.Runtime.Extensions/tests/System/EnvironmentTests.cs
+++ b/src/System.Runtime.Extensions/tests/System/EnvironmentTests.cs
@@ -349,7 +349,7 @@ namespace System.Tests
internal static extern int GetLogicalDrives();
[DllImport("shell32.dll", SetLastError = false, BestFitMapping = false, ExactSpelling = true)]
- internal unsafe static extern int SHGetFolderPathW(
+ internal static extern unsafe int SHGetFolderPathW(
IntPtr hwndOwner,
int nFolder,
IntPtr hToken,
diff --git a/src/System.Runtime.Extensions/tests/System/UnloadingAndProcessExitTests.netcoreapp1.1.cs b/src/System.Runtime.Extensions/tests/System/UnloadingAndProcessExitTests.netcoreapp1.1.cs
new file mode 100644
index 0000000000..49b10b0fe3
--- /dev/null
+++ b/src/System.Runtime.Extensions/tests/System/UnloadingAndProcessExitTests.netcoreapp1.1.cs
@@ -0,0 +1,37 @@
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using Xunit;
+
+namespace System.Tests
+{
+ public class UnloadingAndProcessExitTests : RemoteExecutorTestBase
+ {
+ [Fact]
+ public void UnloadingEventMustHappenBeforeProcessExitEvent()
+ {
+ string fileName = GetTestFilePath();
+
+ File.WriteAllText(fileName, string.Empty);
+
+ Func<string, int> otherProcess = f =>
+ {
+ Action<int> OnUnloading = i => File.AppendAllText(f, string.Format("u{0}", i));
+ Action<int> OnProcessExit = i => File.AppendAllText(f, string.Format("e{0}", i));
+
+ AppDomain.CurrentDomain.ProcessExit += (sender, e) => OnProcessExit(0);
+ System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += acl => OnUnloading(0);
+ AppDomain.CurrentDomain.ProcessExit += (sender, e) => OnProcessExit(1);
+ System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += acl => OnUnloading(1);
+
+ return SuccessExitCode;
+ };
+
+ using (var remote = RemoteInvoke(otherProcess, fileName))
+ {
+ }
+
+ Assert.Equal(File.ReadAllText(fileName), "u0u1e0e1");
+ }
+ }
+}
diff --git a/src/System.Runtime.InteropServices/pkg/System.Runtime.InteropServices.pkgproj b/src/System.Runtime.InteropServices/pkg/System.Runtime.InteropServices.pkgproj
index 2627bb36cd..d27acfc81e 100644
--- a/src/System.Runtime.InteropServices/pkg/System.Runtime.InteropServices.pkgproj
+++ b/src/System.Runtime.InteropServices/pkg/System.Runtime.InteropServices.pkgproj
@@ -3,10 +3,10 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Runtime.InteropServices.builds">
- <SupportedFramework>net463;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Runtime.InteropServices.csproj">
- <TargetGroup>net463</TargetGroup>
+ <TargetGroup>net461</TargetGroup>
</ProjectReference>
<ProjectReference Include="any\System.Runtime.InteropServices.pkgproj" />
<ProjectReference Include="aot\System.Runtime.InteropServices.pkgproj" />
@@ -22,6 +22,10 @@
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
+ <!-- the previous version of this package supported a different API version for
+ net462 & net463, but since netstandard2.0 supports the latest and net461
+ supports netstandard2.0 we need to suppress the old net462 & net463 assembly.-->
+ <HarvestSuppressPaths Include="ref/net462;lib/net462;ref/net463;lib/net463" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Runtime.InteropServices/src/ApiCompatBaseline.uap101aot.txt b/src/System.Runtime.InteropServices/src/ApiCompatBaseline.uap101aot.txt
index 226b3588ab..220e287e95 100644
--- a/src/System.Runtime.InteropServices/src/ApiCompatBaseline.uap101aot.txt
+++ b/src/System.Runtime.InteropServices/src/ApiCompatBaseline.uap101aot.txt
@@ -1,4 +1,5 @@
Compat issues with assembly System.Runtime.InteropServices:
+CannotRemoveBaseTypeOrInterface : Type 'System.IO.UnmanagedMemoryStream' does not inherit from base type 'System.MarshalByRefObject' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.DataMisalignedException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.DllNotFoundException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
MembersMustExist : Member 'System.DllNotFoundException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
@@ -54,4 +55,4 @@ MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.BindToMoniker(
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.ChangeWrapperHandleStrength(System.Object, System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.Marshal.CleanupUnusedObjectsInCurrentContext()' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.InteropServices.ProgIdAttribute' does not exist in the implementation but it does exist in the contract.
-Total Issues: 54
+Total Issues: 55
diff --git a/src/System.Runtime.InteropServices/src/Configurations.props b/src/System.Runtime.InteropServices/src/Configurations.props
index a25a6691e3..f2a0c6d114 100644
--- a/src/System.Runtime.InteropServices/src/Configurations.props
+++ b/src/System.Runtime.InteropServices/src/Configurations.props
@@ -3,7 +3,7 @@
<PropertyGroup>
<BuildConfigurations>
uap101aot-Windows_NT;
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Runtime.InteropServices/src/System.Runtime.InteropServices.csproj b/src/System.Runtime.InteropServices/src/System.Runtime.InteropServices.csproj
index 2415d7bb05..5a00550968 100644
--- a/src/System.Runtime.InteropServices/src/System.Runtime.InteropServices.csproj
+++ b/src/System.Runtime.InteropServices/src/System.Runtime.InteropServices.csproj
@@ -14,11 +14,11 @@
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_uap101aot_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_uap101aot_Release|AnyCPU'" />
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<ContractProject Include="..\ref\System.Runtime.InteropServices.csproj">
<TargetGroup>netstandard</TargetGroup>
</ContractProject>
@@ -46,7 +46,7 @@
<ItemGroup Condition="'$(TargetGroup)'!='uap101aot'">
<Compile Include="System\Security\SecureStringMarshal.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' != 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' != 'net461'">
<Compile Include="System\Runtime\CompilerServices\Attributes.cs" />
<Compile Include="System\Runtime\InteropServices\Attributes.cs" />
<Compile Include="System\Runtime\InteropServices\ComTypes\IDataObject.cs" />
@@ -54,12 +54,12 @@
<Compile Include="System\Runtime\InteropServices\ICustomFactory.cs" />
<Compile Include="System\Runtime\InteropServices\ICustomMarshaler.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System.Core" />
<TargetingPackReference Include="System" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' != 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' != 'net461'">
<TargetingPackReference Include="System.Private.CoreLib" />
<TargetingPackReference Include="System.Private.Interop" Condition="'$(TargetGroup)' == 'uap101aot'" />
</ItemGroup>
diff --git a/src/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/MarshalTests.cs b/src/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/MarshalTests.cs
index d193da01aa..1a5ecdf37e 100644
--- a/src/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/MarshalTests.cs
+++ b/src/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/MarshalTests.cs
@@ -428,7 +428,10 @@ namespace System.Runtime.InteropServices
String monikerName = null;
if(PlatformDetection.IsWindows)
{
- Assert.Throws<ArgumentException>(() => Marshal.BindToMoniker(monikerName));
+ if (PlatformDetection.IsNotWindowsNanoServer)
+ {
+ Assert.Throws<ArgumentException>(() => Marshal.BindToMoniker(monikerName));
+ }
}
else
{
diff --git a/src/System.Runtime.Loader/pkg/System.Runtime.Loader.pkgproj b/src/System.Runtime.Loader/pkg/System.Runtime.Loader.pkgproj
index 5c1571b647..d4f33b0d0f 100644
--- a/src/System.Runtime.Loader/pkg/System.Runtime.Loader.pkgproj
+++ b/src/System.Runtime.Loader/pkg/System.Runtime.Loader.pkgproj
@@ -8,7 +8,7 @@
</ProjectReference>
<ProjectReference Include="..\src\System.Runtime.Loader.builds"/>
- <NotSupportedOnTargetFramework Include="net462" />
+ <NotSupportedOnTargetFramework Include="net461" />
<NotSupportedOnTargetFramework Include="$(AllXamarinFrameworks)" />
</ItemGroup>
diff --git a/src/System.Runtime.Loader/ref/System.Runtime.Loader.cs b/src/System.Runtime.Loader/ref/System.Runtime.Loader.cs
index 062a17fa66..19360f71da 100644
--- a/src/System.Runtime.Loader/ref/System.Runtime.Loader.cs
+++ b/src/System.Runtime.Loader/ref/System.Runtime.Loader.cs
@@ -11,7 +11,7 @@ namespace System.Reflection.Metadata
public static partial class AssemblyExtensions
{
[CLSCompliant(false)] // out byte* blob
- public unsafe static bool TryGetRawMetadata(this System.Reflection.Assembly assembly, out byte* blob, out int length) { throw null; }
+ public static unsafe bool TryGetRawMetadata(this System.Reflection.Assembly assembly, out byte* blob, out int length) { throw null; }
}
}
namespace System.Runtime.Loader
diff --git a/src/System.Runtime.Loader/tests/DefaultContext/System.Runtime.Loader.DefaultContext.Tests.csproj b/src/System.Runtime.Loader/tests/DefaultContext/System.Runtime.Loader.DefaultContext.Tests.csproj
index 40bd38e10a..0cd1187a7c 100644
--- a/src/System.Runtime.Loader/tests/DefaultContext/System.Runtime.Loader.DefaultContext.Tests.csproj
+++ b/src/System.Runtime.Loader/tests/DefaultContext/System.Runtime.Loader.DefaultContext.Tests.csproj
@@ -16,6 +16,7 @@
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ <KeepProjectReference>true</KeepProjectReference>
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/System.Runtime.Loader/tests/RefEmitLoadContext/System.Runtime.Loader.RefEmitLoadContext.Tests.csproj b/src/System.Runtime.Loader/tests/RefEmitLoadContext/System.Runtime.Loader.RefEmitLoadContext.Tests.csproj
index c1eab146e4..23f88661d9 100644
--- a/src/System.Runtime.Loader/tests/RefEmitLoadContext/System.Runtime.Loader.RefEmitLoadContext.Tests.csproj
+++ b/src/System.Runtime.Loader/tests/RefEmitLoadContext/System.Runtime.Loader.RefEmitLoadContext.Tests.csproj
@@ -13,6 +13,7 @@
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ <KeepProjectReference>true</KeepProjectReference>
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.AddSub.cs b/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.AddSub.cs
index d872c48bcb..29cb11ccf1 100644
--- a/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.AddSub.cs
+++ b/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.AddSub.cs
@@ -36,7 +36,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- public unsafe static uint[] Add(uint[] left, uint[] right)
+ public static unsafe uint[] Add(uint[] left, uint[] right)
{
Debug.Assert(left != null);
Debug.Assert(right != null);
@@ -58,7 +58,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static void Add(uint* left, int leftLength,
+ private static unsafe void Add(uint* left, int leftLength,
uint* right, int rightLength,
uint* bits, int bitsLength)
{
@@ -91,7 +91,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static void AddSelf(uint* left, int leftLength,
+ private static unsafe void AddSelf(uint* left, int leftLength,
uint* right, int rightLength)
{
Debug.Assert(leftLength >= 0);
@@ -148,7 +148,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- public unsafe static uint[] Subtract(uint[] left, uint[] right)
+ public static unsafe uint[] Subtract(uint[] left, uint[] right)
{
Debug.Assert(left != null);
Debug.Assert(right != null);
@@ -171,7 +171,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static void Subtract(uint* left, int leftLength,
+ private static unsafe void Subtract(uint* left, int leftLength,
uint* right, int rightLength,
uint* bits, int bitsLength)
{
@@ -206,7 +206,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static void SubtractSelf(uint* left, int leftLength,
+ private static unsafe void SubtractSelf(uint* left, int leftLength,
uint* right, int rightLength)
{
Debug.Assert(leftLength >= 0);
@@ -259,7 +259,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static int Compare(uint* left, int leftLength,
+ private static unsafe int Compare(uint* left, int leftLength,
uint* right, int rightLength)
{
Debug.Assert(leftLength >= 0);
diff --git a/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs b/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs
index 89bc8b05f7..c3a4ab3a51 100644
--- a/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs
+++ b/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs
@@ -71,7 +71,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- public unsafe static uint[] Divide(uint[] left, uint[] right,
+ public static unsafe uint[] Divide(uint[] left, uint[] right,
out uint[] remainder)
{
Debug.Assert(left != null);
@@ -101,7 +101,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- public unsafe static uint[] Divide(uint[] left, uint[] right)
+ public static unsafe uint[] Divide(uint[] left, uint[] right)
{
Debug.Assert(left != null);
Debug.Assert(right != null);
@@ -125,7 +125,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- public unsafe static uint[] Remainder(uint[] left, uint[] right)
+ public static unsafe uint[] Remainder(uint[] left, uint[] right)
{
Debug.Assert(left != null);
Debug.Assert(right != null);
@@ -148,7 +148,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static void Divide(uint* left, int leftLength,
+ private static unsafe void Divide(uint* left, int leftLength,
uint* right, int rightLength,
uint* bits, int bitsLength)
{
@@ -235,7 +235,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static uint AddDivisor(uint* left, int leftLength,
+ private static unsafe uint AddDivisor(uint* left, int leftLength,
uint* right, int rightLength)
{
Debug.Assert(leftLength >= 0);
@@ -256,7 +256,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static uint SubtractDivisor(uint* left, int leftLength,
+ private static unsafe uint SubtractDivisor(uint* left, int leftLength,
uint* right, int rightLength,
ulong q)
{
diff --git a/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.FastReducer.cs b/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.FastReducer.cs
index 7e9accd436..b19d4f543a 100644
--- a/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.FastReducer.cs
+++ b/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.FastReducer.cs
@@ -67,7 +67,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static int DivMul(uint[] left, int leftLength,
+ private static unsafe int DivMul(uint[] left, int leftLength,
uint[] right, int rightLength,
uint[] bits, int k)
{
@@ -112,7 +112,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static int SubMod(uint[] left, int leftLength,
+ private static unsafe int SubMod(uint[] left, int leftLength,
uint[] right, int rightLength,
uint[] modulus, int k)
{
diff --git a/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs b/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs
index a74aba06f0..01015d30bd 100644
--- a/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs
+++ b/src/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs
@@ -10,7 +10,7 @@ namespace System.Numerics
internal static partial class BigIntegerCalculator
{
[SecuritySafeCritical]
- public unsafe static uint[] Square(uint[] value)
+ public static unsafe uint[] Square(uint[] value)
{
Debug.Assert(value != null);
@@ -33,7 +33,7 @@ namespace System.Numerics
private static int AllocationThreshold = 256;
[SecuritySafeCritical]
- private unsafe static void Square(uint* value, int valueLength,
+ private static unsafe void Square(uint* value, int valueLength,
uint* bits, int bitsLength)
{
Debug.Assert(valueLength >= 0);
@@ -186,7 +186,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- public unsafe static uint[] Multiply(uint[] left, uint[] right)
+ public static unsafe uint[] Multiply(uint[] left, uint[] right)
{
Debug.Assert(left != null);
Debug.Assert(right != null);
@@ -211,7 +211,7 @@ namespace System.Numerics
private static int MultiplyThreshold = 32;
[SecuritySafeCritical]
- private unsafe static void Multiply(uint* left, int leftLength,
+ private static unsafe void Multiply(uint* left, int leftLength,
uint* right, int rightLength,
uint* bits, int bitsLength)
{
@@ -359,7 +359,7 @@ namespace System.Numerics
}
[SecuritySafeCritical]
- private unsafe static void SubtractCore(uint* left, int leftLength,
+ private static unsafe void SubtractCore(uint* left, int leftLength,
uint* right, int rightLength,
uint* core, int coreLength)
{
diff --git a/src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs b/src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs
index 9ebe0fc0b3..ebc1a92686 100644
--- a/src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs
+++ b/src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs
@@ -371,7 +371,7 @@ namespace System.Numerics
return result;
}
- private unsafe static bool HexNumberToBigInteger(ref BigNumberBuffer number, ref BigInteger value)
+ private static unsafe bool HexNumberToBigInteger(ref BigNumberBuffer number, ref BigInteger value)
{
if (number.digits == null || number.digits.Length == 0)
return false;
@@ -425,7 +425,7 @@ namespace System.Numerics
return true;
}
- private unsafe static bool NumberToBigInteger(ref BigNumberBuffer number, ref BigInteger value)
+ private static unsafe bool NumberToBigInteger(ref BigNumberBuffer number, ref BigInteger value)
{
int i = number.scale;
int cur = 0;
diff --git a/src/System.Runtime.Numerics/tests/BigInteger/divrem.cs b/src/System.Runtime.Numerics/tests/BigInteger/divrem.cs
index a817680471..1fc5b9ff7d 100644
--- a/src/System.Runtime.Numerics/tests/BigInteger/divrem.cs
+++ b/src/System.Runtime.Numerics/tests/BigInteger/divrem.cs
@@ -181,11 +181,19 @@ namespace System.Numerics.Tests
private static void VerifyDivRemString(string opstring)
{
- StackCalc sc = new StackCalc(opstring);
- while (sc.DoNextOperation())
+ try
{
- Assert.Equal(sc.snCalc.Peek().ToString(), sc.myCalc.Peek().ToString());
- sc.VerifyOutParameter();
+ StackCalc sc = new StackCalc(opstring);
+ while (sc.DoNextOperation())
+ {
+ Assert.Equal(sc.snCalc.Peek().ToString(), sc.myCalc.Peek().ToString());
+ sc.VerifyOutParameter();
+ }
+ }
+ catch(Exception e) when (!(e is DivideByZeroException))
+ {
+ // Log the original parameters, so we can reproduce any failure given the log
+ throw new Exception($"VerifyDivRemString failed: {opstring} {e.ToString()}", e);
}
}
diff --git a/src/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs b/src/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs
index 4a632e56d3..bbac171d8e 100644
--- a/src/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs
+++ b/src/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs
@@ -2240,9 +2240,6 @@ public static partial class DataContractJsonSerializerTests
}
}
-#if ReflectionOnly
- [ActiveIssue(13071)]
-#endif
[Fact]
public static void DCJS_MyISerializableType()
{
diff --git a/src/System.Runtime.Serialization.Json/tests/System.Runtime.Serialization.Json.Tests.builds b/src/System.Runtime.Serialization.Json/tests/System.Runtime.Serialization.Json.Tests.builds
index bed1a61582..f232a413ed 100644
--- a/src/System.Runtime.Serialization.Json/tests/System.Runtime.Serialization.Json.Tests.builds
+++ b/src/System.Runtime.Serialization.Json/tests/System.Runtime.Serialization.Json.Tests.builds
@@ -5,7 +5,7 @@
<Project Include="System.Runtime.Serialization.Json.Tests.csproj" />
<Project Include="System.Runtime.Serialization.Json.Tests.csproj">
<OSGroup>Windows_NT</OSGroup>
- <TestTFMs>netcore50;net46</TestTFMs>
+ <TestTFMs>net463</TestTFMs>
</Project>
<Project Include="Performance\System.Runtime.Serialization.Json.Performance.Tests.csproj" />
<Project Include="ReflectionOnly\System.Runtime.Serialization.Json.ReflectionOnly.Tests.csproj" />
diff --git a/src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs b/src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs
index b4e9bb5323..9d58475c90 100644
--- a/src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs
+++ b/src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs
@@ -1431,9 +1431,6 @@ public static partial class DataContractSerializerTests
Assert.StrictEqual(((SimpleKnownTypeValue)actual.SimpleTypeValue).StrProperty, "PropertyValue");
}
-#if ReflectionOnly
- [ActiveIssue(13071)]
-#endif
[Fact]
public static void DCS_ExceptionObject()
{
@@ -1448,9 +1445,6 @@ public static partial class DataContractSerializerTests
Assert.StrictEqual(value.HelpLink, actual.HelpLink);
}
-#if ReflectionOnly
- [ActiveIssue(13071)]
-#endif
[Fact]
public static void DCS_ArgumentExceptionObject()
{
@@ -1465,9 +1459,6 @@ public static partial class DataContractSerializerTests
Assert.StrictEqual(value.HelpLink, actual.HelpLink);
}
-#if ReflectionOnly
- [ActiveIssue(13071)]
-#endif
[Fact]
public static void DCS_ExceptionMesageWithSpecialChars()
{
@@ -1482,9 +1473,6 @@ public static partial class DataContractSerializerTests
Assert.StrictEqual(value.HelpLink, actual.HelpLink);
}
-#if ReflectionOnly
- [ActiveIssue(13071)]
-#endif
[Fact]
public static void DCS_InnerExceptionMesageWithSpecialChars()
{
@@ -2748,29 +2736,14 @@ public static partial class DataContractSerializerTests
t, mi, out xname);
}
- [ActiveIssue(12772)]
[Fact]
public static void XsdDataContractExporterTest()
{
XsdDataContractExporter exporter = new XsdDataContractExporter();
- if (exporter.CanExport(typeof(Employee)))
- {
- exporter.Export(typeof(Employee));
- Assert.Equal(3,exporter.Schemas.Count);
-
- XmlSchemaSet mySchemas = exporter.Schemas;
-
- XmlQualifiedName XmlNameValue = exporter.GetRootElementName(typeof(Employee));
- string EmployeeNameSpace = XmlNameValue.Namespace;
- Assert.Equal("www.msn.com/Examples/", EmployeeNameSpace);
- XmlSchema schema = mySchemas.Schemas(EmployeeNameSpace).Cast<XmlSchema>().FirstOrDefault();
- Assert.NotNull(schema);
- }
+ Assert.Throws<PlatformNotSupportedException>(() => exporter.CanExport(typeof(Employee)));
+ Assert.Throws<PlatformNotSupportedException>(() => exporter.Export(typeof(Employee)));
}
-#if ReflectionOnly
- [ActiveIssue(13071)]
-#endif
[Fact]
public static void DCS_MyISerializableType()
{
diff --git a/src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs b/src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs
index 01577b2cfc..421ca6cde8 100644
--- a/src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs
+++ b/src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs
@@ -4155,3 +4155,8 @@ public class SampleTextWriter : IXmlTextWriterInitializer
Stream = stream;
}
}
+
+public class MycodeGenerator : XmlSerializationGeneratedCode
+{
+
+}
diff --git a/src/System.Runtime.Serialization.Xml/tests/System.Runtime.Serialization.Xml.Tests.builds b/src/System.Runtime.Serialization.Xml/tests/System.Runtime.Serialization.Xml.Tests.builds
index 6db5fa12dc..3023525cb5 100644
--- a/src/System.Runtime.Serialization.Xml/tests/System.Runtime.Serialization.Xml.Tests.builds
+++ b/src/System.Runtime.Serialization.Xml/tests/System.Runtime.Serialization.Xml.Tests.builds
@@ -5,7 +5,7 @@
<Project Include="System.Runtime.Serialization.Xml.Tests.csproj" />
<Project Include="System.Runtime.Serialization.Xml.Tests.csproj">
<OSGroup>Windows_NT</OSGroup>
- <TestTFMs>netcore50;net46</TestTFMs>
+ <TestTFMs>net463</TestTFMs>
</Project>
<Project Include="Performance\System.Runtime.Serialization.Xml.Performance.Tests.csproj" />
<Project Include="ReflectionOnly\System.Runtime.Serialization.Xml.ReflectionOnly.Tests.csproj" />
diff --git a/src/System.Runtime.Serialization.Xml/tests/XmlDictionaryWriterTest.cs b/src/System.Runtime.Serialization.Xml/tests/XmlDictionaryWriterTest.cs
index 4a367491b6..e37b7ba3ba 100644
--- a/src/System.Runtime.Serialization.Xml/tests/XmlDictionaryWriterTest.cs
+++ b/src/System.Runtime.Serialization.Xml/tests/XmlDictionaryWriterTest.cs
@@ -287,7 +287,6 @@ public static class XmlDictionaryWriterTest
writer.SetOutput(ms, encoding, true);
}
- [ActiveIssue(13375)]
[Fact]
public static void FragmentTest()
{
@@ -295,26 +294,11 @@ public static class XmlDictionaryWriterTest
ReaderWriterFactory.ReaderWriterType rwType = (ReaderWriterFactory.ReaderWriterType)
Enum.Parse(typeof(ReaderWriterFactory.ReaderWriterType), rwTypeStr, true);
Encoding encoding = Encoding.GetEncoding("utf-8");
- int numberOfNestedFragments = 1;
- MemoryStream ms1 = new MemoryStream();
- MemoryStream ms2 = new MemoryStream();
- XmlDictionaryWriter writer1 = (XmlDictionaryWriter)ReaderWriterFactory.CreateXmlWriter(rwType, ms1, encoding);
- XmlDictionaryWriter writer2 = (XmlDictionaryWriter)ReaderWriterFactory.CreateXmlWriter(rwType, ms2, encoding);
- Assert.True(FragmentHelper.CanFragment(writer1));
- Assert.True(FragmentHelper.CanFragment(writer2));
- writer1.WriteStartDocument(); writer2.WriteStartDocument();
- writer1.WriteStartElement(ReaderWriterConstants.RootElementName); writer2.WriteStartElement(ReaderWriterConstants.RootElementName);
- SimulateWriteFragment(writer1, true, numberOfNestedFragments);
- SimulateWriteFragment(writer2, false, numberOfNestedFragments);
- writer1.WriteEndElement(); writer2.WriteEndElement();
- writer1.WriteEndDocument(); writer2.WriteEndDocument();
- writer1.Flush();
- writer2.Flush();
-
- byte[] doc1 = ms1.ToArray();
- byte[] doc2 = ms2.ToArray();
- CompareArrays(doc1, 0, doc2, 0, doc1.Length);
+ MemoryStream ms = new MemoryStream();
+ XmlDictionaryWriter writer = (XmlDictionaryWriter)ReaderWriterFactory.CreateXmlWriter(rwType, ms, encoding);
+ Assert.False(FragmentHelper.CanFragment(writer));
}
+
private static bool ReadTest(MemoryStream ms, Encoding encoding, ReaderWriterFactory.ReaderWriterType rwType, byte[] byteArray)
{
ms.Position = 0;
@@ -414,15 +398,6 @@ public static class XmlDictionaryWriterTest
}
}
-
- private static void CompareArrays(byte[] array1, int offset1, byte[] array2, int offset2, int count)
- {
- for (int i = 0; i < count; i++)
- {
- Assert.Equal(array1[i + offset1], array2[i + offset2]);
- }
- }
-
private static void SimulateWriteFragment(XmlDictionaryWriter writer, bool useFragmentAPI, int nestedLevelsLeft)
{
if (nestedLevelsLeft <= 0)
diff --git a/src/System.Runtime.WindowsRuntime.UI.Xaml/pkg/System.Runtime.WindowsRuntime.UI.Xaml.pkgproj b/src/System.Runtime.WindowsRuntime.UI.Xaml/pkg/System.Runtime.WindowsRuntime.UI.Xaml.pkgproj
index a67cf595d5..72a06cd6bd 100644
--- a/src/System.Runtime.WindowsRuntime.UI.Xaml/pkg/System.Runtime.WindowsRuntime.UI.Xaml.pkgproj
+++ b/src/System.Runtime.WindowsRuntime.UI.Xaml/pkg/System.Runtime.WindowsRuntime.UI.Xaml.pkgproj
@@ -16,7 +16,7 @@
<ItemGroup>
<!-- This package is only supported on win8 and later RIDs -->
<ValidatePackageSuppression Include="PermitImplementation">
- <Value>.NETCoreApp,Version=v1.1/win10-arm64</Value>
+ <Value>.NETCoreApp,Version=v1.1/win10-arm64;.NETCoreApp,Version=v2.0/win10-arm64</Value>
</ValidatePackageSuppression>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/System.Runtime.WindowsRuntime/pkg/System.Runtime.WindowsRuntime.pkgproj b/src/System.Runtime.WindowsRuntime/pkg/System.Runtime.WindowsRuntime.pkgproj
index 346cadfa1c..3b76c35865 100644
--- a/src/System.Runtime.WindowsRuntime/pkg/System.Runtime.WindowsRuntime.pkgproj
+++ b/src/System.Runtime.WindowsRuntime/pkg/System.Runtime.WindowsRuntime.pkgproj
@@ -15,7 +15,7 @@
<ItemGroup>
<!-- This package is only supported on win8 and later RIDs -->
<ValidatePackageSuppression Include="PermitImplementation">
- <Value>.NETCoreApp,Version=v1.1/win10-arm64</Value>
+ <Value>.NETCoreApp,Version=v1.1/win10-arm64;.NETCoreApp,Version=v2.0/win10-arm64</Value>
</ValidatePackageSuppression>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/System.Runtime.WindowsRuntime/src/System/InternalHelpers.cs b/src/System.Runtime.WindowsRuntime/src/System/InternalHelpers.cs
index 27e5220dc7..b28a9cb163 100644
--- a/src/System.Runtime.WindowsRuntime/src/System/InternalHelpers.cs
+++ b/src/System.Runtime.WindowsRuntime/src/System/InternalHelpers.cs
@@ -42,7 +42,7 @@ namespace System.Runtime.WindowsRuntime.Internal
internal class Helpers
{
- internal unsafe static void ZeroMemory(byte* src, long len)
+ internal static unsafe void ZeroMemory(byte* src, long len)
{
while (len-- > 0)
*(src + len) = 0;
diff --git a/src/System.Runtime.WindowsRuntime/src/System/Runtime/InteropServices/WindowsRuntime/MarshalingHelpers.cs b/src/System.Runtime.WindowsRuntime/src/System/Runtime/InteropServices/WindowsRuntime/MarshalingHelpers.cs
index 6ff9d2ddbe..90418f0729 100644
--- a/src/System.Runtime.WindowsRuntime/src/System/Runtime/InteropServices/WindowsRuntime/MarshalingHelpers.cs
+++ b/src/System.Runtime.WindowsRuntime/src/System/Runtime/InteropServices/WindowsRuntime/MarshalingHelpers.cs
@@ -81,7 +81,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
// Extracts properties from a managed NotifyCollectionChangedEventArgs and passes them to
// a VM-implemented helper that creates a WinRT NotifyCollectionChangedEventArgs instance.
// This method is called from IL stubs and needs to have its token stabilized.
- static internal IntPtr ConvertToNative(NotifyCollectionChangedEventArgs managedArgs)
+ internal static IntPtr ConvertToNative(NotifyCollectionChangedEventArgs managedArgs)
{
if (managedArgs == null)
return IntPtr.Zero;
@@ -97,7 +97,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
// Extracts properties from a WinRT NotifyCollectionChangedEventArgs and creates a new
// managed NotifyCollectionChangedEventArgs instance.
// This method is called from IL stubs and needs to have its token stabilized.
- static internal NotifyCollectionChangedEventArgs ConvertToManaged(IntPtr nativeArgsIP)
+ internal static NotifyCollectionChangedEventArgs ConvertToManaged(IntPtr nativeArgsIP)
{
if (nativeArgsIP == IntPtr.Zero)
return null;
@@ -113,7 +113,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
nativeArgs.OldStartingIndex);
}
- static internal NotifyCollectionChangedEventArgs CreateNotifyCollectionChangedEventArgs(
+ internal static NotifyCollectionChangedEventArgs CreateNotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction action, IList newItems, IList oldItems, int newStartingIndex, int oldStartingIndex)
{
switch (action)
@@ -143,7 +143,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
// Extracts PropertyName from a managed PropertyChangedEventArgs and passes them to
// a VM-implemented helper that creates a WinRT PropertyChangedEventArgs instance.
// This method is called from IL stubs and needs to have its token stabilized.
- static internal IntPtr ConvertToNative(PropertyChangedEventArgs managedArgs)
+ internal static IntPtr ConvertToNative(PropertyChangedEventArgs managedArgs)
{
if (managedArgs == null)
return IntPtr.Zero;
@@ -154,7 +154,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
// Extracts properties from a WinRT PropertyChangedEventArgs and creates a new
// managed PropertyChangedEventArgs instance.
// This method is called from IL stubs and needs to have its token stabilized.
- static internal PropertyChangedEventArgs ConvertToManaged(IntPtr nativeArgsIP)
+ internal static PropertyChangedEventArgs ConvertToManaged(IntPtr nativeArgsIP)
{
if (nativeArgsIP == IntPtr.Zero)
return null;
diff --git a/src/System.Runtime.WindowsRuntime/src/System/Windows/Rect.cs b/src/System.Runtime.WindowsRuntime/src/System/Windows/Rect.cs
index fd62b0bfbc..e8a9c75fa2 100644
--- a/src/System.Runtime.WindowsRuntime/src/System/Windows/Rect.cs
+++ b/src/System.Runtime.WindowsRuntime/src/System/Windows/Rect.cs
@@ -43,7 +43,7 @@ namespace Windows.Foundation
private const double EmptyWidth = Double.NegativeInfinity;
private const double EmptyHeight = Double.NegativeInfinity;
- private readonly static Rect s_empty = CreateEmptyRect();
+ private static readonly Rect s_empty = CreateEmptyRect();
public Rect(double x,
double y,
diff --git a/src/System.Runtime.WindowsRuntime/src/System/Windows/Size.cs b/src/System.Runtime.WindowsRuntime/src/System/Windows/Size.cs
index 29486f7f34..81a2495dd9 100644
--- a/src/System.Runtime.WindowsRuntime/src/System/Windows/Size.cs
+++ b/src/System.Runtime.WindowsRuntime/src/System/Windows/Size.cs
@@ -35,7 +35,7 @@ namespace Windows.Foundation
private float _width;
private float _height;
- private readonly static Size s_empty = CreateEmptySize();
+ private static readonly Size s_empty = CreateEmptySize();
public Size(double width, double height)
{
@@ -82,7 +82,7 @@ namespace Windows.Foundation
get { return Width < 0; }
}
- static private Size CreateEmptySize()
+ private static Size CreateEmptySize()
{
Size size = new Size();
// We can't set these via the property setters because negatives widths
diff --git a/src/System.Runtime/pkg/System.Runtime.pkgproj b/src/System.Runtime/pkg/System.Runtime.pkgproj
index 193a0a6ed5..f87ccc1094 100644
--- a/src/System.Runtime/pkg/System.Runtime.pkgproj
+++ b/src/System.Runtime/pkg/System.Runtime.pkgproj
@@ -3,13 +3,10 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Runtime.builds">
- <SupportedFramework>net463;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Runtime.csproj">
- <TargetGroup>net462</TargetGroup>
- </ProjectReference>
- <ProjectReference Include="..\src\System.Runtime.csproj">
- <TargetGroup>net463</TargetGroup>
+ <TargetGroup>net461</TargetGroup>
</ProjectReference>
<ProjectReference Include="any\System.Runtime.pkgproj" />
<ProjectReference Include="aot\System.Runtime.pkgproj" />
@@ -26,6 +23,10 @@
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
+ <!-- the previous version of this package supported a different API version for
+ net462, but since netstandard2.0 supports the latest and net461 supports
+ netstandard2.0 we need to suppress the old net462 assembly. -->
+ <HarvestSuppressPaths Include="ref/net462;lib/net462" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/System.Runtime/pkg/any/System.Runtime.pkgproj b/src/System.Runtime/pkg/any/System.Runtime.pkgproj
index 8aef5d9bce..968fa69639 100644
--- a/src/System.Runtime/pkg/any/System.Runtime.pkgproj
+++ b/src/System.Runtime/pkg/any/System.Runtime.pkgproj
@@ -10,6 +10,9 @@
<ProjectReference Include="..\..\src\System.Runtime.csproj">
<TargetGroup>netstandard1.5</TargetGroup>
</ProjectReference>
+ <ProjectReference Include="..\..\src\System.Runtime.csproj">
+ <TargetGroup>netcoreapp1.2corert</TargetGroup>
+ </ProjectReference>
<!-- AOT implementation comes from AOT package -->
<File Include="$(PlaceholderFile)">
<TargetPath>runtimes/aot/lib/netcore50</TargetPath>
@@ -27,4 +30,4 @@
<InboxOnTargetFramework Include="xamarinwatchos10" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/System.Runtime/ref/System.Runtime.cs b/src/System.Runtime/ref/System.Runtime.cs
index 11c5333609..9ce0edfa9e 100644
--- a/src/System.Runtime/ref/System.Runtime.cs
+++ b/src/System.Runtime/ref/System.Runtime.cs
@@ -482,10 +482,10 @@ namespace System
public static byte GetByte(System.Array array, int index) { throw null; }
[System.CLSCompliantAttribute(false)]
[System.Security.SecurityCriticalAttribute]
- public unsafe static void MemoryCopy(void* source, void* destination, long destinationSizeInBytes, long sourceBytesToCopy) { }
+ public static unsafe void MemoryCopy(void* source, void* destination, long destinationSizeInBytes, long sourceBytesToCopy) { }
[System.CLSCompliantAttribute(false)]
[System.Security.SecurityCriticalAttribute]
- public unsafe static void MemoryCopy(void* source, void* destination, ulong destinationSizeInBytes, ulong sourceBytesToCopy) { }
+ public static unsafe void MemoryCopy(void* source, void* destination, ulong destinationSizeInBytes, ulong sourceBytesToCopy) { }
public static void SetByte(System.Array array, int index, byte value) { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
@@ -1513,10 +1513,10 @@ namespace System
public static explicit operator int (System.IntPtr value) { throw null; }
public static explicit operator long (System.IntPtr value) { throw null; }
[System.CLSCompliantAttribute(false)]
- public unsafe static explicit operator void* (System.IntPtr value) { throw null; }
+ public static unsafe explicit operator void* (System.IntPtr value) { throw null; }
[System.CLSCompliantAttribute(false)]
[System.Security.SecurityCriticalAttribute]
- public unsafe static explicit operator System.IntPtr(void* value) { throw null; }
+ public static unsafe explicit operator System.IntPtr(void* value) { throw null; }
public static bool operator !=(System.IntPtr value1, System.IntPtr value2) { throw null; }
public static System.IntPtr operator -(System.IntPtr pointer, int offset) { throw null; }
public static System.IntPtr Subtract(System.IntPtr pointer, int offset) { throw null; }
@@ -2846,10 +2846,10 @@ namespace System
public static explicit operator ulong (System.UIntPtr value) { throw null; }
[System.CLSCompliantAttribute(false)]
[System.Security.SecurityCriticalAttribute]
- public unsafe static explicit operator void* (System.UIntPtr value) { throw null; }
+ public static unsafe explicit operator void* (System.UIntPtr value) { throw null; }
[System.CLSCompliantAttribute(false)]
[System.Security.SecurityCriticalAttribute]
- public unsafe static explicit operator System.UIntPtr(void* value) { throw null; }
+ public static unsafe explicit operator System.UIntPtr(void* value) { throw null; }
public static bool operator !=(System.UIntPtr value1, System.UIntPtr value2) { throw null; }
public static System.UIntPtr operator -(System.UIntPtr pointer, int offset) { throw null; }
public static System.UIntPtr Subtract(System.UIntPtr pointer, int offset) { throw null; }
@@ -3564,6 +3564,16 @@ namespace System.ComponentModel
public DefaultValueAttribute(object value) { }
public DefaultValueAttribute(float value) { }
public DefaultValueAttribute(string value) { }
+#if netcoreapp11
+ [System.CLSCompliantAttribute(false)]
+ public DefaultValueAttribute(sbyte value) { }
+ [System.CLSCompliantAttribute(false)]
+ public DefaultValueAttribute(ushort value) { }
+ [System.CLSCompliantAttribute(false)]
+ public DefaultValueAttribute(uint value) { }
+ [System.CLSCompliantAttribute(false)]
+ public DefaultValueAttribute(ulong value) { }
+#endif
public DefaultValueAttribute(System.Type type, string value) { }
public virtual object Value { get { throw null; } }
public override bool Equals(object obj) { throw null; }
@@ -4908,7 +4918,7 @@ namespace System.Reflection
public void SetPublicKey(byte[] publicKey) { }
public void SetPublicKeyToken(byte[] publicKeyToken) { }
public override string ToString() { throw null; }
- static public bool ReferenceMatchesDefinition(System.Reflection.AssemblyName reference, System.Reflection.AssemblyName definition) { throw null; }
+ public static bool ReferenceMatchesDefinition(System.Reflection.AssemblyName reference, System.Reflection.AssemblyName definition) { throw null; }
[System.Security.SecurityCriticalAttribute]
public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { throw null; }
public void OnDeserialization(Object sender) { throw null; }
@@ -5929,6 +5939,9 @@ namespace System.Runtime.CompilerServices
{
public ConditionalWeakTable() { }
public void Add(TKey key, TValue value) { }
+#if netcoreapp11
+ public void AddOrUpdate(TKey key, TValue value) { }
+#endif //netcoreapp11
~ConditionalWeakTable() { }
public TValue GetOrCreateValue(TKey key) { throw null; }
public TValue GetValue(TKey key, System.Runtime.CompilerServices.ConditionalWeakTable<TKey, TValue>.CreateValueCallback createValueCallback) { throw null; }
diff --git a/src/System.Runtime/src/ApiCompatBaseline.netcoreapp1.2corert.txt b/src/System.Runtime/src/ApiCompatBaseline.netcoreapp1.2corert.txt
new file mode 100644
index 0000000000..5136839833
--- /dev/null
+++ b/src/System.Runtime/src/ApiCompatBaseline.netcoreapp1.2corert.txt
@@ -0,0 +1,387 @@
+Compat issues with assembly System.Runtime:
+TypesMustExist : Type 'Microsoft.Win32.SafeHandles.CriticalHandleMinusOneIsInvalid' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'Microsoft.Win32.SafeHandles.CriticalHandleZeroOrMinusOneIsInvalid' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'Microsoft.Win32.SafeHandles.SafeFileHandle' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'Microsoft.Win32.SafeHandles.SafeHandleMinusOneIsInvalid' does not inherit from base type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid' does not inherit from base type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'Microsoft.Win32.SafeHandles.SafeWaitHandle' does not inherit from base type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+TypesMustExist : Type 'System.AppContext' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.ConvertAll<TInput, TOutput>(TInput[], System.Converter<TInput, TOutput>)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.Copy(System.Array, System.Array, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.Copy(System.Array, System.Int64, System.Array, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.CopyTo(System.Array, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.CreateInstance(System.Type, System.Int64[])' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.ForEach<T>(T[], System.Action<T>)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.GetLongLength(System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.GetValue(System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.GetValue(System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.GetValue(System.Int64, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.GetValue(System.Int64[])' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.IsFixedSize.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.IsReadOnly.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.IsSynchronized.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.LongLength.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int64, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int64[])' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Array.SyncRoot.get()' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.AsyncCallback' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.Attribute.IsDefaultAttribute()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Attribute.Match(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Attribute.TypeId.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Boolean.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Boolean.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Boolean.ToString(System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Byte.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Byte.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Char.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Char.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Char.GetUnicodeCategory(System.Char)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Char.GetUnicodeCategory(System.String, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Char.ToLower(System.Char, System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Char.ToString(System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Char.ToUpper(System.Char, System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.CharEnumerator' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Comparison<T>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Converter<TInput, TOutput>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.DateTime' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.DateTime..ctor(System.Int32, System.Int32, System.Int32, System.Globalization.Calendar)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime..ctor(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Globalization.Calendar)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime..ctor(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Globalization.Calendar)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime..ctor(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Globalization.Calendar, System.DateTimeKind)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime.FromOADate(System.Double)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime.ToLongDateString()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime.ToLongTimeString()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime.ToOADate()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime.ToShortDateString()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DateTime.ToShortTimeString()' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.DateTimeOffset' does not implement interface 'System.Runtime.Serialization.IDeserializationCallback' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.DateTimeOffset..ctor(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Int32, System.Globalization.Calendar, System.TimeSpan)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.DBNull' does not implement interface 'System.IConvertible' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.DBNull.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DBNull.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.DBNull.ToString(System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Decimal' does not implement interface 'System.Runtime.Serialization.IDeserializationCallback' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.Decimal.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Decimal.FromOACurrency(System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Decimal.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Decimal.Round(System.Decimal)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Decimal.Round(System.Decimal, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Decimal.Round(System.Decimal, System.Int32, System.MidpointRounding)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Decimal.Round(System.Decimal, System.MidpointRounding)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Decimal.ToOACurrency(System.Decimal)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Delegate' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotSealType : Type 'System.Delegate' is sealed in the implementation but not sealed in the contract.
+MembersMustExist : Member 'System.Delegate..ctor(System.Object, System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate..ctor(System.Type, System.String)' does not exist in the implementation but it does exist in the contract.
+CannotMakeMemberNonVirtual : Member 'System.Delegate.Clone()' is non-virtual in the implementation but is virtual in the contract.
+MembersMustExist : Member 'System.Delegate.CombineImpl(System.Delegate)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Object, System.Reflection.MethodInfo)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Object, System.Reflection.MethodInfo, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Object, System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Object, System.String, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Object, System.String, System.Boolean, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Reflection.MethodInfo)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Reflection.MethodInfo, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Type, System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Type, System.String, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.CreateDelegate(System.Type, System.Type, System.String, System.Boolean, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.DynamicInvokeImpl(System.Object[])' does not exist in the implementation but it does exist in the contract.
+CannotMakeMemberNonVirtual : Member 'System.Delegate.Equals(System.Object)' is non-virtual in the implementation but is virtual in the contract.
+CannotMakeMemberNonVirtual : Member 'System.Delegate.GetHashCode()' is non-virtual in the implementation but is virtual in the contract.
+CannotMakeMemberNonVirtual : Member 'System.Delegate.GetInvocationList()' is non-virtual in the implementation but is virtual in the contract.
+CannotMakeMemberNonVirtual : Member 'System.Delegate.GetMethodImpl()' is non-virtual in the implementation but is virtual in the contract.
+MembersMustExist : Member 'System.Delegate.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Delegate.RemoveImpl(System.Delegate)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Double.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Double.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.Byte)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.Int16)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.SByte)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.UInt16)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.UInt32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.UInt64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToString(System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Enum.ToString(System.String, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.EventHandler' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.EventHandler<TEventArgs>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.Exception.add_SerializeObjectState(System.EventHandler<System.Runtime.Serialization.SafeSerializationEventArgs>)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Exception.remove_SerializeObjectState(System.EventHandler<System.Runtime.Serialization.SafeSerializationEventArgs>)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Exception.TargetSite.get()' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.GC.CancelFullGCNotification()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.EndNoGCRegion()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.GetGeneration(System.WeakReference)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.RegisterForFullGCNotification(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.TryStartNoGCRegion(System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.TryStartNoGCRegion(System.Int64, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.TryStartNoGCRegion(System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.TryStartNoGCRegion(System.Int64, System.Int64, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.WaitForFullGCApproach()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.WaitForFullGCApproach(System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.WaitForFullGCComplete()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.GC.WaitForFullGCComplete(System.Int32)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.GCNotificationStatus' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Guid.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Guid.ToString(System.String, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Int16.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Int16.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Int32.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Int32.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Int64.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Int64.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.IntPtr' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.MarshalByRefObject.GetLifetimeService()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.MarshalByRefObject.InitializeLifetimeService()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.MarshalByRefObject.MemberwiseClone(System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle System.ModuleHandle.EmptyHandle' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.Equals(System.ModuleHandle)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.GetRuntimeFieldHandleFromMetadataToken(System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.GetRuntimeMethodHandleFromMetadataToken(System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.GetRuntimeTypeHandleFromMetadataToken(System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.MDStreamVersion.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.op_Equality(System.ModuleHandle, System.ModuleHandle)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.op_Inequality(System.ModuleHandle, System.ModuleHandle)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.ResolveFieldHandle(System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.ResolveFieldHandle(System.Int32, System.RuntimeTypeHandle[], System.RuntimeTypeHandle[])' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.ResolveMethodHandle(System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.ResolveMethodHandle(System.Int32, System.RuntimeTypeHandle[], System.RuntimeTypeHandle[])' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.ResolveTypeHandle(System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ModuleHandle.ResolveTypeHandle(System.Int32, System.RuntimeTypeHandle[], System.RuntimeTypeHandle[])' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.MulticastDelegate' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotSealType : Type 'System.MulticastDelegate' is sealed in the implementation but not sealed in the contract.
+MembersMustExist : Member 'System.MulticastDelegate..ctor(System.Object, System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.MulticastDelegate..ctor(System.Type, System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.MulticastDelegate.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Predicate<T>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.RuntimeFieldHandle' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.RuntimeFieldHandle.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.RuntimeFieldHandle.Value.get()' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.RuntimeMethodHandle' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.RuntimeMethodHandle.GetFunctionPointer()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.RuntimeMethodHandle.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.RuntimeMethodHandle.Value.get()' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.RuntimeTypeHandle' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.RuntimeTypeHandle.GetModuleHandle()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.RuntimeTypeHandle.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.RuntimeTypeHandle.Value.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.SByte.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.SByte.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Single.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Single.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String..ctor(System.SByte*)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String..ctor(System.SByte*, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String..ctor(System.SByte*, System.Int32, System.Int32, System.Text.Encoding)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.Compare(System.String, System.Int32, System.String, System.Int32, System.Int32, System.Boolean, System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.Compare(System.String, System.Int32, System.String, System.Int32, System.Int32, System.Globalization.CultureInfo, System.Globalization.CompareOptions)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.Compare(System.String, System.String, System.Boolean, System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.Compare(System.String, System.String, System.Globalization.CultureInfo, System.Globalization.CompareOptions)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.Copy(System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.EndsWith(System.String, System.Boolean, System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.GetEnumerator()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.Intern(System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.IsInterned(System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.StartsWith(System.String, System.Boolean, System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.ToLower(System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.ToString(System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.String.ToUpper(System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.StringComparison System.StringComparison.InvariantCulture' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.StringComparison System.StringComparison.InvariantCultureIgnoreCase' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.TimeSpan.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.TimeZone' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.TimeZoneInfo.HasSameRules(System.TimeZoneInfo)' does not exist in the implementation but it does exist in the contract.
+CannotMakeMemberNonVirtual : Member 'System.Type.IsEnum' is non-virtual in the implementation but is virtual in the contract.
+CannotMakeMemberNonVirtual : Member 'System.Type.Equals(System.Type)' is non-virtual in the implementation but is virtual in the contract.
+CannotMakeMemberNonVirtual : Member 'System.Type.IsEnum.get()' is non-virtual in the implementation but is virtual in the contract.
+TypesMustExist : Type 'System.TypeUnloadedException' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.UInt16.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.UInt16.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.UInt32.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.UInt32.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.UInt64.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.UInt64.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.UIntPtr' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.UnhandledExceptionEventHandler' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Uri' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.Uri..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Uri.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.UriFormatException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Version..ctor()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Version.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.WeakReference' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.WeakReference..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.WeakReference.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.WeakReference<T>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.WeakReference<T>.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ComponentModel.DefaultValueAttribute.SetValue(System.Object)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.ComponentModel.EditorBrowsableAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.ComponentModel.EditorBrowsableState' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Diagnostics.DebuggableAttribute..ctor(System.Boolean, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Diagnostics.DebuggableAttribute.DebuggingFlags.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Diagnostics.DebuggableAttribute.IsJITOptimizerDisabled.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Diagnostics.DebuggableAttribute.IsJITTrackingEnabled.get()' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Globalization.CompareInfo' does not implement interface 'System.Runtime.Serialization.IDeserializationCallback' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Globalization.TextInfo' does not implement interface 'System.Runtime.Serialization.IDeserializationCallback' in the implementation but it does in the contract.
+TypesMustExist : Type 'System.IO.FileAccess' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.IO.FileMode' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.IO.FileOptions' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.IO.FileShare' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.IO.FileStream' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.IO.Stream' does not inherit from base type 'System.MarshalByRefObject' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.IO.Stream.CreateWaitHandle()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.IO.Stream.ObjectInvariant()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.IO.Stream.Synchronized(System.IO.Stream)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.EscapedCodeBase.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.GetFile(System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.GetFiles()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.GetFiles(System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.GlobalAssemblyCache.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.HostContext.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.IsFullyTrusted.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.LoadFile(System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.LoadFrom(System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.LoadFrom(System.String, System.Byte[], System.Configuration.Assemblies.AssemblyHashAlgorithm)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.LoadModule(System.String, System.Byte[])' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.LoadModule(System.String, System.Byte[], System.Byte[])' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.LoadWithPartialName(System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.SecurityRuleSet.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.Assembly.UnsafeLoadFrom(System.String)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.AssemblyName.EscapedCodeBase.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.AssemblyName.KeyPair.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Reflection.AssemblyName.KeyPair.set(System.Reflection.StrongNameKeyPair)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.MemberFilter' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ModuleResolveEventHandler' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+TypesMustExist : Type 'System.Reflection.ObfuscateAssemblyAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Reflection.ObfuscationAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Reflection.StrongNameKeyPair' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Reflection.TypeDelegator' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TypeFilter' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.Runtime.GCLatencyMode System.Runtime.GCLatencyMode.NoGCRegion' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.MemoryFailPoint' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.CompilationRelaxations' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.CompilationRelaxationsAttribute..ctor(System.Runtime.CompilerServices.CompilationRelaxations)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.CompilerGlobalScopeAttribute' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.CompilerServices.ConditionalWeakTable<TKey, TValue>.CreateValueCallback' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.DefaultDependencyAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.DependencyAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.DiscardableAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.FixedAddressValueTypeAttribute' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.InternalsVisibleToAttribute.AllInternalsVisible.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.InternalsVisibleToAttribute.AllInternalsVisible.set(System.Boolean)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.LoadHint' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.MethodCodeType' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.MethodCodeType System.Runtime.CompilerServices.MethodImplAttribute.MethodCodeType' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.MethodImplAttribute..ctor()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.MethodImplAttribute..ctor(System.Int16)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(System.Runtime.CompilerServices.RuntimeHelpers.TryCode, System.Runtime.CompilerServices.RuntimeHelpers.CleanupCode, System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegionsNoOP()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareContractedDelegate(System.Delegate)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareDelegate(System.Delegate)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(System.RuntimeMethodHandle)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(System.RuntimeMethodHandle, System.RuntimeTypeHandle[])' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.ProbeForSufficientStack()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.RunModuleConstructor(System.ModuleHandle)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.RuntimeHelpers.CleanupCode' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.RuntimeHelpers.TryCode' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.StringFreezingAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.CompilerServices.SuppressIldasmAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.ConstrainedExecution.Cer' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.ConstrainedExecution.Consistency' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.ConstrainedExecution.ReliabilityContractAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.InteropServices.CriticalHandle' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.SafeHandle' does not inherit from base type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.Runtime.InteropServices.SafeHandle.Close()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.InteropServices.StructLayoutAttribute..ctor(System.Int16)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.Serialization.ISafeSerializationData' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Runtime.Serialization.SafeSerializationEventArgs' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Runtime.Serialization.SerializationInfo..ctor(System.Type, System.Runtime.Serialization.IFormatterConverter, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Security.AllowPartiallyTrustedCallersAttribute.PartialTrustVisibilityLevel.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Security.AllowPartiallyTrustedCallersAttribute.PartialTrustVisibilityLevel.set(System.Security.PartialTrustVisibilityLevel)' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Security.PartialTrustVisibilityLevel' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Security.SecurityCriticalAttribute..ctor(System.Security.SecurityCriticalScope)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Security.SecurityCriticalAttribute.Scope.get()' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Security.SecurityCriticalScope' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Security.SecurityRulesAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Security.SecurityRuleSet' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Security.SecurityTreatAsSafeAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Security.SuppressUnmanagedCodeSecurityAttribute' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Security.UnverifiableCodeAttribute' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Decoder.Convert(System.Byte*, System.Int32, System.Char*, System.Int32, System.Boolean, System.Int32, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Decoder.GetCharCount(System.Byte*, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Decoder.GetChars(System.Byte*, System.Int32, System.Char*, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoder.Convert(System.Char*, System.Int32, System.Byte*, System.Int32, System.Boolean, System.Int32, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoder.GetBytes(System.Char*, System.Int32, System.Byte*, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.BodyName.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.Default.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.GetEncodings()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.HeaderName.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.IsAlwaysNormalized()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.IsAlwaysNormalized(System.Text.NormalizationForm)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.IsBrowserDisplay.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.IsBrowserSave.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.IsMailNewsDisplay.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.IsMailNewsSave.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Encoding.WindowsCodePage.get()' does not exist in the implementation but it does exist in the contract.
+TypesMustExist : Type 'System.Text.EncodingInfo' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Text.StringBuilder' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Threading.WaitHandle' does not inherit from base type 'System.MarshalByRefObject' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.Close()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.Handle.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.Handle.set(System.IntPtr)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.SignalAndWait(System.Threading.WaitHandle, System.Threading.WaitHandle)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.SignalAndWait(System.Threading.WaitHandle, System.Threading.WaitHandle, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.SignalAndWait(System.Threading.WaitHandle, System.Threading.WaitHandle, System.TimeSpan, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.WaitAll(System.Threading.WaitHandle[], System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.WaitAll(System.Threading.WaitHandle[], System.TimeSpan, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.WaitAny(System.Threading.WaitHandle[], System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.WaitAny(System.Threading.WaitHandle[], System.TimeSpan, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.WaitOne(System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.WaitHandle.WaitOne(System.TimeSpan, System.Boolean)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.Task' does not implement interface 'System.IDisposable' in the implementation but it does in the contract.
+MembersMustExist : Member 'System.Threading.Tasks.Task.Dispose()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Threading.Tasks.Task.Dispose(System.Boolean)' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.Task<TResult>' does not implement interface 'System.IDisposable' in the implementation but it does in the contract.
+Total Issues: 385
diff --git a/src/System.Runtime/src/ApiCompatBaseline.txt b/src/System.Runtime/src/ApiCompatBaseline.txt
deleted file mode 100644
index 81724ada63..0000000000
--- a/src/System.Runtime/src/ApiCompatBaseline.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Compat issues with assembly System.Runtime:
-MembersMustExist : Member 'System.Type.GetType(System.String, System.Func<System.Reflection.AssemblyName, System.Reflection.Assembly>, System.Func<System.Reflection.Assembly, System.String, System.Boolean, System.Type>)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Type.GetType(System.String, System.Func<System.Reflection.AssemblyName, System.Reflection.Assembly>, System.Func<System.Reflection.Assembly, System.String, System.Boolean, System.Type>, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Type.GetType(System.String, System.Func<System.Reflection.AssemblyName, System.Reflection.Assembly>, System.Func<System.Reflection.Assembly, System.String, System.Boolean, System.Type>, System.Boolean, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Type.IsContextful.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Type.IsContextfulImpl()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.add_ModuleResolve(System.Reflection.ModuleResolveEventHandler)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Reflection.Assembly.remove_ModuleResolve(System.Reflection.ModuleResolveEventHandler)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 8
diff --git a/src/System.Runtime/src/ApiCompatBaseline.uap101aot.txt b/src/System.Runtime/src/ApiCompatBaseline.uap101aot.txt
index 2cb33a67d5..354a7cfcd4 100644
--- a/src/System.Runtime/src/ApiCompatBaseline.uap101aot.txt
+++ b/src/System.Runtime/src/ApiCompatBaseline.uap101aot.txt
@@ -5,7 +5,6 @@ TypesMustExist : Type 'Microsoft.Win32.SafeHandles.SafeFileHandle' does not exis
CannotRemoveBaseTypeOrInterface : Type 'Microsoft.Win32.SafeHandles.SafeHandleMinusOneIsInvalid' does not inherit from base type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid' does not inherit from base type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Microsoft.Win32.SafeHandles.SafeWaitHandle' does not inherit from base type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' in the implementation but it does in the contract.
-TypesMustExist : Type 'System.AccessViolationException' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Action' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Action<T>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
@@ -23,28 +22,14 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7
CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.AggregateException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.AppContext' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.ApplicationException' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.ArgumentException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.ArgumentException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.ArgumentNullException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.ArgumentNullException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.ArgumentOutOfRangeException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.ArgumentOutOfRangeException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.ArithmeticException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.ArithmeticException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.ConvertAll<TInput, TOutput>(TInput[], System.Converter<TInput, TOutput>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.Copy(System.Array, System.Array, System.Int64)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.Copy(System.Array, System.Int64, System.Array, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.CopyTo(System.Array, System.Int64)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Array.CreateInstance(System.Type, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Array.CreateInstance(System.Type, System.Int32, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.CreateInstance(System.Type, System.Int64[])' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.ForEach<T>(T[], System.Action<T>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.GetLongLength(System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Array.GetValue(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Array.GetValue(System.Int32, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.GetValue(System.Int64)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.GetValue(System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.GetValue(System.Int64, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
@@ -53,22 +38,15 @@ MembersMustExist : Member 'System.Array.IsFixedSize.get()' does not exist in the
MembersMustExist : Member 'System.Array.IsReadOnly.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.IsSynchronized.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.LongLength.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int32, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int64)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int64, System.Int64, System.Int64)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.SetValue(System.Object, System.Int64[])' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Array.SyncRoot.get()' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.ArrayTypeMismatchException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.ArrayTypeMismatchException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.AsyncCallback' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Attribute.IsDefaultAttribute()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Attribute.Match(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Attribute.TypeId.get()' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.BadImageFormatException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.BadImageFormatException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.BadImageFormatException.FusionLog.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Boolean.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Boolean.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Boolean.ToString(System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
@@ -135,12 +113,8 @@ CannotMakeMemberNonVirtual : Member 'System.Delegate.GetInvocationList()' is non
CannotMakeMemberNonVirtual : Member 'System.Delegate.GetMethodImpl()' is non-virtual in the implementation but is virtual in the contract.
MembersMustExist : Member 'System.Delegate.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Delegate.RemoveImpl(System.Delegate)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.DivideByZeroException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.DivideByZeroException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Double.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Double.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.DuplicateWaitObjectException' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.EntryPointNotFoundException' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Enum.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.Byte)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Enum.ToObject(System.Type, System.Int16)' does not exist in the implementation but it does exist in the contract.
@@ -157,10 +131,6 @@ CannotRemoveBaseTypeOrInterface : Type 'System.EventHandler<TEventArgs>' does no
MembersMustExist : Member 'System.Exception.add_SerializeObjectState(System.EventHandler<System.Runtime.Serialization.SafeSerializationEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Exception.remove_SerializeObjectState(System.EventHandler<System.Runtime.Serialization.SafeSerializationEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Exception.TargetSite.get()' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.ExecutionEngineException' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.FieldAccessException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.FieldAccessException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.FormatException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Func<TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Func<T, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
@@ -179,7 +149,6 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7,
CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
MembersMustExist : Member 'System.GC.CancelFullGCNotification()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.GC.Collect(System.Int32, System.GCCollectionMode, System.Boolean, System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.GC.EndNoGCRegion()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.GC.GetGeneration(System.WeakReference)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.GC.RegisterForFullGCNotification(System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
@@ -194,9 +163,6 @@ MembersMustExist : Member 'System.GC.WaitForFullGCComplete(System.Int32)' does n
TypesMustExist : Type 'System.GCNotificationStatus' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Guid.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Guid.ToString(System.String, System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.IndexOutOfRangeException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.InsufficientExecutionStackException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-TypesMustExist : Type 'System.InsufficientMemoryException' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Int16.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Int16.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Int32.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
@@ -204,25 +170,9 @@ MembersMustExist : Member 'System.Int32.GetTypeCode()' does not exist in the imp
MembersMustExist : Member 'System.Int64.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Int64.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.IntPtr' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.InvalidCastException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.InvalidCastException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.InvalidOperationException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.InvalidOperationException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.InvalidProgramException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.InvalidTimeZoneException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.MarshalByRefObject.GetLifetimeService()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.MarshalByRefObject.InitializeLifetimeService()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.MarshalByRefObject.MemberwiseClone(System.Boolean)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.MemberAccessException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.MemberAccessException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.MethodAccessException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.MethodAccessException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.MissingFieldException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.MissingFieldException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.MissingMemberException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.MissingMemberException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.MissingMethodException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.MissingMethodException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.ModuleHandle System.ModuleHandle.EmptyHandle' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.ModuleHandle.Equals(System.ModuleHandle)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.ModuleHandle.GetRuntimeFieldHandleFromMetadataToken(System.Int32)' does not exist in the implementation but it does exist in the contract.
@@ -242,25 +192,7 @@ CannotSealType : Type 'System.MulticastDelegate' is sealed in the implementation
MembersMustExist : Member 'System.MulticastDelegate..ctor(System.Object, System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.MulticastDelegate..ctor(System.Type, System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.MulticastDelegate.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.MulticastNotSupportedException' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.NotFiniteNumberException' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.NotImplementedException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.NotImplementedException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.NotSupportedException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.NotSupportedException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.NullReferenceException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.NullReferenceException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.ObjectDisposedException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.ObjectDisposedException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.OutOfMemoryException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.OutOfMemoryException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.OverflowException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.OverflowException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.PlatformNotSupportedException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.PlatformNotSupportedException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Predicate<T>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.RankException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.RankException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.RuntimeFieldHandle' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
MembersMustExist : Member 'System.RuntimeFieldHandle.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.RuntimeFieldHandle.Value.get()' does not exist in the implementation but it does exist in the contract.
@@ -276,7 +208,6 @@ MembersMustExist : Member 'System.SByte.CompareTo(System.Object)' does not exist
MembersMustExist : Member 'System.SByte.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Single.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Single.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.StackOverflowException' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.String..ctor(System.SByte*)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.String..ctor(System.SByte*, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.String..ctor(System.SByte*, System.Int32, System.Int32, System.Text.Encoding)' does not exist in the implementation but it does exist in the contract.
@@ -291,64 +222,18 @@ MembersMustExist : Member 'System.String.GetEnumerator()' does not exist in the
MembersMustExist : Member 'System.String.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.String.Intern(System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.String.IsInterned(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.String.IsNormalized()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.String.IsNormalized(System.Text.NormalizationForm)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.String.Normalize()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.String.Normalize(System.Text.NormalizationForm)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.String.StartsWith(System.String, System.Boolean, System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.String.ToLower(System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.String.ToString(System.IFormatProvider)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.String.ToUpper(System.Globalization.CultureInfo)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.StringComparison System.StringComparison.InvariantCulture' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.StringComparison System.StringComparison.InvariantCultureIgnoreCase' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.TimeoutException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.TimeoutException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.TimeSpan.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.TimeZone' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.TimeZoneInfo' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.ClearCachedData()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.ConvertTimeBySystemTimeZoneId(System.DateTime, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.ConvertTimeBySystemTimeZoneId(System.DateTime, System.String, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.ConvertTimeBySystemTimeZoneId(System.DateTimeOffset, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.ConvertTimeFromUtc(System.DateTime, System.TimeZoneInfo)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.ConvertTimeToUtc(System.DateTime)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.ConvertTimeToUtc(System.DateTime, System.TimeZoneInfo)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.CreateCustomTimeZone(System.String, System.TimeSpan, System.String, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.CreateCustomTimeZone(System.String, System.TimeSpan, System.String, System.String, System.String, System.TimeZoneInfo.AdjustmentRule[])' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.CreateCustomTimeZone(System.String, System.TimeSpan, System.String, System.String, System.String, System.TimeZoneInfo.AdjustmentRule[], System.Boolean)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.FromSerializedString(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.GetAdjustmentRules()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.TimeZoneInfo.HasSameRules(System.TimeZoneInfo)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.ToSerializedString()' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.TimeZoneInfo.AdjustmentRule' does not implement interface 'System.Runtime.Serialization.IDeserializationCallback' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(System.DateTime, System.DateTime, System.TimeSpan, System.TimeZoneInfo.TransitionTime, System.TimeZoneInfo.TransitionTime)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.AdjustmentRule.DateEnd.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.AdjustmentRule.DateStart.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.AdjustmentRule.DaylightDelta.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.AdjustmentRule.DaylightTransitionEnd.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.AdjustmentRule.DaylightTransitionStart.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.AdjustmentRule.Equals(System.TimeZoneInfo.AdjustmentRule)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.TimeZoneInfo.TransitionTime' does not implement interface 'System.Runtime.Serialization.IDeserializationCallback' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.CreateFixedDateRule(System.DateTime, System.Int32, System.Int32)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.CreateFloatingDateRule(System.DateTime, System.Int32, System.Int32, System.DayOfWeek)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.Day.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.DayOfWeek.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.Equals(System.TimeZoneInfo.TransitionTime)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.IsFixedDateRule.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.Month.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.op_Equality(System.TimeZoneInfo.TransitionTime, System.TimeZoneInfo.TransitionTime)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.op_Inequality(System.TimeZoneInfo.TransitionTime, System.TimeZoneInfo.TransitionTime)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.TimeOfDay.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.TimeZoneInfo.TransitionTime.Week.get()' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.TimeZoneNotFoundException' does not exist in the implementation but it does exist in the contract.
CannotMakeMemberNonVirtual : Member 'System.Type.IsEnum' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Type.Equals(System.Type)' is non-virtual in the implementation but is virtual in the contract.
CannotMakeMemberNonVirtual : Member 'System.Type.IsEnum.get()' is non-virtual in the implementation but is virtual in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.TypeAccessException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.TypeAccessException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.TypeInitializationException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.TypeLoadException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.TypeLoadException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.TypeUnloadedException' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.UInt16.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.UInt16.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
@@ -357,14 +242,10 @@ MembersMustExist : Member 'System.UInt32.GetTypeCode()' does not exist in the im
MembersMustExist : Member 'System.UInt64.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.UInt64.GetTypeCode()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.UIntPtr' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.UnauthorizedAccessException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.UnauthorizedAccessException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.UnhandledExceptionEventArgs' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.UnhandledExceptionEventHandler' does not exist in the implementation but it does exist in the contract.
+CannotRemoveBaseTypeOrInterface : Type 'System.UnhandledExceptionEventHandler' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Uri' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Uri..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Uri.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.UriFormatException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
MembersMustExist : Member 'System.UriFormatException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Version..ctor()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Version.CompareTo(System.Object)' does not exist in the implementation but it does exist in the contract.
@@ -373,41 +254,23 @@ MembersMustExist : Member 'System.WeakReference..ctor(System.Runtime.Serializati
MembersMustExist : Member 'System.WeakReference.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.WeakReference<T>' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
MembersMustExist : Member 'System.WeakReference<T>.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Collections.Generic.KeyNotFoundException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Collections.Generic.KeyNotFoundException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.ComponentModel.DefaultValueAttribute.SetValue(System.Object)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.ComponentModel.EditorBrowsableAttribute..ctor()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Diagnostics.DebuggableAttribute..ctor(System.Boolean, System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Diagnostics.DebuggableAttribute.DebuggingFlags.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Diagnostics.DebuggableAttribute.IsJITOptimizerDisabled.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Diagnostics.DebuggableAttribute.IsJITTrackingEnabled.get()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Globalization.CompareInfo' does not implement interface 'System.Runtime.Serialization.IDeserializationCallback' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Globalization.CultureNotFoundException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Globalization.CultureNotFoundException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Globalization.DaylightTime' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Globalization.IdnMapping' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Globalization.TextInfo' does not implement interface 'System.Runtime.Serialization.IDeserializationCallback' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.IO.DirectoryNotFoundException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.IO.DirectoryNotFoundException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.IO.FileAccess' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.IO.FileLoadException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.IO.FileLoadException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.IO.FileLoadException.FusionLog.get()' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.IO.FileMode' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.IO.FileNotFoundException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.IO.FileNotFoundException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.IO.FileNotFoundException.FusionLog.get()' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.IO.FileOptions' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.IO.FileShare' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.IO.FileStream' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.IO.IOException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.IO.IOException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.IO.PathTooLongException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.IO.PathTooLongException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.IO.Stream' does not inherit from base type 'System.MarshalByRefObject' in the implementation but it does in the contract.
MembersMustExist : Member 'System.IO.Stream.CreateWaitHandle()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.IO.Stream.ObjectInvariant()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.IO.Stream.Synchronized(System.IO.Stream)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.AmbiguousMatchException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.EscapedCodeBase.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.GetFile(System.String)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.Assembly.GetFiles()' does not exist in the implementation but it does exist in the contract.
@@ -426,17 +289,11 @@ MembersMustExist : Member 'System.Reflection.Assembly.UnsafeLoadFrom(System.Stri
MembersMustExist : Member 'System.Reflection.AssemblyName.EscapedCodeBase.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.AssemblyName.KeyPair.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Reflection.AssemblyName.KeyPair.set(System.Reflection.StrongNameKeyPair)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.CustomAttributeFormatException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.InvalidFilterCriteriaException' does not inherit from base type 'System.ApplicationException' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.MemberFilter' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ModuleResolveEventHandler' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Reflection.ObfuscateAssemblyAttribute' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Reflection.ObfuscationAttribute' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.ReflectionTypeLoadException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Reflection.StrongNameKeyPair' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TargetException' does not inherit from base type 'System.ApplicationException' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TargetInvocationException' does not inherit from base type 'System.ApplicationException' in the implementation but it does in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TargetParameterCountException' does not inherit from base type 'System.ApplicationException' in the implementation but it does in the contract.
TypesMustExist : Type 'System.Reflection.TypeDelegator' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Reflection.TypeFilter' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Runtime.GCLatencyMode System.Runtime.GCLatencyMode.NoGCRegion' does not exist in the implementation but it does exist in the contract.
@@ -456,9 +313,6 @@ TypesMustExist : Type 'System.Runtime.CompilerServices.MethodCodeType' does not
MembersMustExist : Member 'System.Runtime.CompilerServices.MethodCodeType System.Runtime.CompilerServices.MethodImplAttribute.MethodCodeType' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.CompilerServices.MethodImplAttribute..ctor()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.CompilerServices.MethodImplAttribute..ctor(System.Int16)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.CompilerServices.MethodImplOptions System.Runtime.CompilerServices.MethodImplOptions.ForwardRef' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.CompilerServices.MethodImplOptions System.Runtime.CompilerServices.MethodImplOptions.Synchronized' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Runtime.CompilerServices.MethodImplOptions System.Runtime.CompilerServices.MethodImplOptions.Unmanaged' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(System.Runtime.CompilerServices.RuntimeHelpers.TryCode, System.Runtime.CompilerServices.RuntimeHelpers.CleanupCode, System.Object)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegionsNoOP()' does not exist in the implementation but it does exist in the contract.
@@ -470,24 +324,18 @@ MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.ProbeF
MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.RunModuleConstructor(System.ModuleHandle)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.CompilerServices.RuntimeHelpers.CleanupCode' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.CompilerServices.RuntimeHelpers.TryCode' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Runtime.CompilerServices.RuntimeWrappedException' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.CompilerServices.StringFreezingAttribute' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.CompilerServices.SuppressIldasmAttribute' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.ConstrainedExecution.Cer' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.ConstrainedExecution.Consistency' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.ConstrainedExecution.ReliabilityContractAttribute' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.InteropServices.CriticalHandle' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Runtime.InteropServices.ExternalException' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.SafeHandle' does not inherit from base type 'System.Runtime.ConstrainedExecution.CriticalFinalizerObject' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.SafeHandle.Close()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.InteropServices.StructLayoutAttribute..ctor(System.Int16)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.Serialization.ISafeSerializationData' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Runtime.Serialization.SafeSerializationEventArgs' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.Serialization.SerializationException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Runtime.Serialization.SerializationException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Runtime.Serialization.SerializationInfo..ctor(System.Type, System.Runtime.Serialization.IFormatterConverter, System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.AllowPartiallyTrustedCallersAttribute.PartialTrustVisibilityLevel.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.AllowPartiallyTrustedCallersAttribute.PartialTrustVisibilityLevel.set(System.Security.PartialTrustVisibilityLevel)' does not exist in the implementation but it does exist in the contract.
@@ -495,45 +343,16 @@ TypesMustExist : Type 'System.Security.PartialTrustVisibilityLevel' does not exi
MembersMustExist : Member 'System.Security.SecurityCriticalAttribute..ctor(System.Security.SecurityCriticalScope)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Security.SecurityCriticalAttribute.Scope.get()' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.SecurityCriticalScope' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Security.SecurityException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Security.SecurityException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException..ctor(System.String, System.Type)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException..ctor(System.String, System.Type, System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.Demanded.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.Demanded.set(System.Object)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.DenySetInstance.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.DenySetInstance.set(System.Object)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.FailedAssemblyInfo.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.FailedAssemblyInfo.set(System.Reflection.AssemblyName)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.GrantedSet.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.GrantedSet.set(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.Method.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.Method.set(System.Reflection.MethodInfo)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.PermissionState.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.PermissionState.set(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.PermissionType.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.PermissionType.set(System.Type)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.PermitOnlySetInstance.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.PermitOnlySetInstance.set(System.Object)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.RefusedSet.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.RefusedSet.set(System.String)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.Url.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'System.Security.SecurityException.Url.set(System.String)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.SecurityRulesAttribute' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.SecurityRuleSet' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.SecurityTreatAsSafeAttribute' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.SuppressUnmanagedCodeSecurityAttribute' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Security.UnverifiableCodeAttribute' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Security.VerificationException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
-MembersMustExist : Member 'System.Security.VerificationException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Security.Cryptography.CryptographicException' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Text.Decoder.Convert(System.Byte*, System.Int32, System.Char*, System.Int32, System.Boolean, System.Int32, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Text.Decoder.GetCharCount(System.Byte*, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Text.Decoder.GetChars(System.Byte*, System.Int32, System.Char*, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Text.DecoderFallbackException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Text.Encoder.Convert(System.Char*, System.Int32, System.Byte*, System.Int32, System.Boolean, System.Int32, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Text.Encoder.GetBytes(System.Char*, System.Int32, System.Byte*, System.Int32, System.Boolean)' does not exist in the implementation but it does exist in the contract.
-CannotRemoveBaseTypeOrInterface : Type 'System.Text.EncoderFallbackException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Text.Encoding.BodyName.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Text.Encoding.Default.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Text.Encoding.GetEncodings()' does not exist in the implementation but it does exist in the contract.
@@ -546,7 +365,6 @@ MembersMustExist : Member 'System.Text.Encoding.IsMailNewsDisplay.get()' does no
MembersMustExist : Member 'System.Text.Encoding.IsMailNewsSave.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Text.Encoding.WindowsCodePage.get()' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'System.Text.EncodingInfo' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'System.Text.NormalizationForm' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Text.StringBuilder' does not implement interface 'System.Runtime.Serialization.ISerializable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.WaitHandle' does not inherit from base type 'System.MarshalByRefObject' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Threading.WaitHandle.Close()' does not exist in the implementation but it does exist in the contract.
@@ -565,4 +383,4 @@ CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.Task' does not im
MembersMustExist : Member 'System.Threading.Tasks.Task.Dispose()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.Tasks.Task.Dispose(System.Boolean)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.Task<TResult>' does not implement interface 'System.IDisposable' in the implementation but it does in the contract.
-Total Issues: 566
+Total Issues: 384
diff --git a/src/System.Runtime/src/Configurations.props b/src/System.Runtime/src/Configurations.props
index 5097dd6037..323984f16b 100644
--- a/src/System.Runtime/src/Configurations.props
+++ b/src/System.Runtime/src/Configurations.props
@@ -3,9 +3,9 @@
<PropertyGroup>
<BuildConfigurations>
netstandard1.5;
- net463-Windows_NT;
- net462-Windows_NT;
+ net461-Windows_NT;
uap101aot-Windows_NT;
+ netcoreapp1.2corert-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Runtime/src/System.Runtime.csproj b/src/System.Runtime/src/System.Runtime.csproj
index 185c1b69ee..5f3beb4cf9 100644
--- a/src/System.Runtime/src/System.Runtime.csproj
+++ b/src/System.Runtime/src/System.Runtime.csproj
@@ -4,10 +4,10 @@
<PropertyGroup>
<ProjectGuid>{56B9D0A9-44D3-488E-8B42-C14A6E30CAB2}</ProjectGuid>
<AssemblyName>System.Runtime</AssemblyName>
- <AssemblyVersion Condition="'$(TargetGroup)'=='net462' OR '$(TargetGroup)'=='netstandard1.5'">4.1.1.0</AssemblyVersion>
+ <AssemblyVersion Condition="'$(TargetGroup)'=='netstandard1.5'">4.1.1.0</AssemblyVersion>
<ContractProject Condition="'$(AssemblyVersion)'=='4.1.1.0'">../ref/4.1.0/System.Runtime.depproj</ContractProject>
<IsPartialFacadeAssembly>true</IsPartialFacadeAssembly>
- <GenFacadesArgs Condition="'$(TargetGroup)' == 'uap101aot'">$(GenFacadesArgs) -ignoreMissingTypes</GenFacadesArgs>
+ <GenFacadesArgs Condition="'$(TargetGroup)' == 'uap101aot' Or '$(TargetGroup)' == 'netcoreapp1.2corert'">$(GenFacadesArgs) -ignoreMissingTypes</GenFacadesArgs>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
@@ -16,11 +16,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard1.5_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101aot_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101aot_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net462_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net462_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
- <ItemGroup Condition="'$(TargetGroup)' == 'net463' OR '$(TargetGroup)' == 'uap101aot'">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461' OR '$(TargetGroup)' == 'uap101aot' OR '$(TargetGroup)' == 'netcoreapp1.2corert'">
<ContractProject Include="..\ref\System.Runtime.csproj">
<TargetGroup>netstandard</TargetGroup>
</ContractProject>
@@ -28,18 +26,17 @@
<ItemGroup>
<Compile Include="System.Runtime.Forwards.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'netstandard1.5' or '$(TargetGroup)' == 'netstandard' or '$(TargetGroup)' == 'uap101aot'">
+ <ItemGroup Condition="'$(TargetGroup)' != 'net461'">
<Compile Include="System\Action.cs" />
<Compile Include="System\Function.cs" />
<Compile Include="System\LazyOfTTMetadata.cs" />
<Compile Include="System\Collections\Generic\ISet.cs" />
- <Compile Include="System\ComponentModel\EditorBrowsableAttribute.cs" />
<Compile Include="System\Runtime\CompilerServices\StrongBox.cs" />
<Compile Include="System\Reflection\RuntimeReflectionExtensions.cs" />
<Compile Include="System\Runtime\CompilerServices\Attributes.cs" />
<Compile Include="System\IO\FileAttributes.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'netstandard' or '$(TargetGroup)' == 'uap101aot'">
+ <ItemGroup Condition="'$(TargetGroup)' != 'net461' and '$(TargetGroup)' != 'netstandard1.5'">
<Compile Include="System\Runtime\NgenServicingAttributes.cs" />
<Compile Include="System\IO\HandleInheritability.cs" />
<Compile Include="System\Runtime\ConstrainedExecution\PrePrepareMethodAttribute.cs" />
@@ -49,16 +46,13 @@
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard1.5' or '$(TargetGroup)' == 'netstandard'">
<Compile Include="System\ComponentModel\DefaultValueAttribute.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)'=='uap101aot' or '$(TargetGroup)'=='uap101'">
- <Compile Include="$(CommonPath)\System\SystemException.cs" />
- </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\System.Private.Uri\src\System.Private.Uri.csproj" Condition="'$(TargetGroup)' == 'netstandard1.5' or '$(TargetGroup)' == 'netstandard' or '$(TargetGroup)' == 'uap101aot'" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'netstandard1.5' or '$(TargetGroup)' == 'netstandard' or '$(TargetGroup)' == 'uap101aot'">
+ <ItemGroup Condition="'$(TargetGroup)' != 'net461'">
<TargetingPackReference Include="System.Private.CoreLib" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net462' OR '$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="System" />
<TargetingPackReference Include="System.Core" />
<TargetingPackReference Include="System.ComponentModel.Composition" />
diff --git a/src/System.Runtime/src/System/ComponentModel/DefaultValueAttribute.cs b/src/System.Runtime/src/System/ComponentModel/DefaultValueAttribute.cs
index 0caf8b85a8..cca5f7bfbc 100644
--- a/src/System.Runtime/src/System/ComponentModel/DefaultValueAttribute.cs
+++ b/src/System.Runtime/src/System/ComponentModel/DefaultValueAttribute.cs
@@ -139,6 +139,46 @@ namespace System.ComponentModel
}
/// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.ComponentModel.DefaultValueAttribute'/> class using a <see cref='System.SByte'/>
+ /// value.</para>
+ /// </devdoc>
+ [CLSCompliant(false)]
+ public DefaultValueAttribute(sbyte value)
+ {
+ this.value = value;
+ }
+
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.ComponentModel.DefaultValueAttribute'/> class using a <see cref='System.UInt16'/>
+ /// value.</para>
+ /// </devdoc>
+ [CLSCompliant(false)]
+ public DefaultValueAttribute(ushort value)
+ {
+ this.value = value;
+ }
+
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.ComponentModel.DefaultValueAttribute'/> class using a <see cref='System.UInt32'/>
+ /// value.</para>
+ /// </devdoc>
+ [CLSCompliant(false)]
+ public DefaultValueAttribute(uint value)
+ {
+ this.value = value;
+ }
+
+ /// <devdoc>
+ /// <para>Initializes a new instance of the <see cref='System.ComponentModel.DefaultValueAttribute'/> class using a <see cref='System.UInt64'/>
+ /// value.</para>
+ /// </devdoc>
+ [CLSCompliant(false)]
+ public DefaultValueAttribute(ulong value)
+ {
+ this.value = value;
+ }
+
+ /// <devdoc>
/// <para>
/// Gets the default value of the property this
/// attribute is
diff --git a/src/System.Runtime/src/System/ComponentModel/EditorBrowsableAttribute.cs b/src/System.Runtime/src/System/ComponentModel/EditorBrowsableAttribute.cs
deleted file mode 100644
index a7946f8203..0000000000
--- a/src/System.Runtime/src/System/ComponentModel/EditorBrowsableAttribute.cs
+++ /dev/null
@@ -1,48 +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.
-
-namespace System.ComponentModel
-{
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Delegate | AttributeTargets.Interface)]
- public sealed class EditorBrowsableAttribute : Attribute
- {
- private EditorBrowsableState browsableState;
-
- public EditorBrowsableAttribute(EditorBrowsableState state)
- {
- browsableState = state;
- }
-
- public EditorBrowsableAttribute () : this(EditorBrowsableState.Always) { }
-
- public EditorBrowsableState State
- {
- get { return browsableState; }
- }
-
- public override bool Equals(object obj)
- {
- if (obj == this)
- {
- return true;
- }
-
- EditorBrowsableAttribute other = obj as EditorBrowsableAttribute;
-
- return (other != null) && other.browsableState == browsableState;
- }
-
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
- }
-
- public enum EditorBrowsableState
- {
- Always,
- Never,
- Advanced
- }
-}
diff --git a/src/System.Runtime/tests/System.Runtime.Tests.csproj b/src/System.Runtime/tests/System.Runtime.Tests.csproj
index 51c1bbe350..f487a93390 100644
--- a/src/System.Runtime/tests/System.Runtime.Tests.csproj
+++ b/src/System.Runtime/tests/System.Runtime.Tests.csproj
@@ -24,6 +24,24 @@
<Compile Include="$(CommonTestPath)\System\EnumTypes.cs">
<Link>Common\System\EnumTypes.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\tests\System\Collections\CollectionAsserts.cs">
+ <Link>Common\System\Collections\CollectionAsserts.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\tests\System\Collections\ICollection.Generic.Tests.cs">
+ <Link>Common\System\Collections\ICollection.Generic.Tests.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\tests\System\Collections\IEnumerable.Generic.Tests.cs">
+ <Link>Common\System\Collections\IEnumerable.Generic.Tests.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\tests\System\Collections\IList.Generic.Tests.cs">
+ <Link>Common\System\Collections\IList.Generic.Tests.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\tests\System\Collections\TestBase.Generic.cs">
+ <Link>Common\System\Collections\TestBase.Generic.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\tests\System\Collections\TestBase.NonGeneric.cs">
+ <Link>Common\System\Collections\TestBase.NonGeneric.cs</Link>
+ </Compile>
<Compile Include="Helpers.cs" />
<Compile Include="System\ActivatorTests.cs" />
<Compile Include="System\ArrayTests.cs" />
@@ -111,12 +129,17 @@
<Compile Include="System\IntPtrTests.netcoreapp1.1.cs" />
<Compile Include="System\LazyTests.netcoreapp1.1.cs" />
<Compile Include="System\Runtime\CompilerServices\RuntimeHelpersTests.netcoreapp1.1.cs" />
+ <Compile Include="System\Runtime\CompilerServices\ConditionalWeakTableTests.netcoreapp1.1.cs" />
<Compile Include="System\UIntPtrTests.netcoreapp1.1.cs" />
+ <Compile Include="System\ComponentModel\DefaultValueAttributeTests.netcoreapp1.1.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' != 'netcoreapp1.1'">
<Compile Include="System\StringSplitExtensions.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard1.7'">
+ <Compile Include="..\..\Common\tests\System\Collections\IEnumerable.Generic.Serialization.Tests.cs">
+ <Link>Common\System\Collections\IEnumerable.Generic.Serialization.Tests.cs</Link>
+ </Compile>
<Compile Include="ArrayTests.netstandard1.7.cs" />
<Compile Include="System\DelegateTests.netstandard1.7.cs" />
<Compile Include="System\AttributeTests.netstandard1.7.cs" />
diff --git a/src/System.Runtime/tests/System/ArraySegmentTests.cs b/src/System.Runtime/tests/System/ArraySegmentTests.cs
index d171eaaef3..3b367635f5 100644
--- a/src/System.Runtime/tests/System/ArraySegmentTests.cs
+++ b/src/System.Runtime/tests/System/ArraySegmentTests.cs
@@ -5,64 +5,115 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Collections.Tests;
+using System.Linq;
using Xunit;
namespace System.Tests
{
- public static class ArraySegmentTests
+ public abstract class ArraySegment_Tests<T>: IList_Generic_Tests<T>
{
- [Fact]
- public static void Ctor_Empty()
+ #region IList<T> Helper Methods
+
+ protected override IList<T> GenericIListFactory()
{
- var segment = new ArraySegment<int>();
- Assert.Null(segment.Array);
- Assert.Equal(0, segment.Offset);
- Assert.Equal(0, segment.Count);
+ return Factory();
}
- [Theory]
- [InlineData(new int[] { 7, 8, 9, 10, 11 })]
- [InlineData(new int[0])]
- public static void Ctor_Array(int[] array)
+ protected override IList<T> GenericIListFactory(int count)
+ {
+ return Factory(count * 2, count / 2, count);
+ }
+
+ protected override bool Enumerator_Current_UndefinedOperation_Throws => true;
+ protected override bool Enumerator_ModifiedDuringEnumeration_ThrowsInvalidOperationException => false;
+ protected override bool IsReadOnly_ValidityValue => true;
+ protected override bool AddRemoveClear_ThrowsNotSupported => true;
+
+ #endregion
+
+ #region List<T> Helper Methods
+
+ protected virtual ArraySegment<T> Factory()
+ {
+ return new ArraySegment<T>();
+ }
+
+ protected virtual ArraySegment<T> Factory(int count, int offset, int length)
{
- var segment = new ArraySegment<int>(array);
+ T[] array = CreateEnumerable(EnumerableType.List, null, count, 0, 0).ToArray();
+ ArraySegment<T> segment = new ArraySegment<T>(array, offset, length);
Assert.Same(array, segment.Array);
- Assert.Equal(0, segment.Offset);
- Assert.Equal(array.Length, segment.Count);
+ Assert.Equal(offset, segment.Offset);
+ Assert.Equal(length, segment.Count);
+
+ return segment;
}
- [Fact]
- public static void Ctor_Array_NullArray_ThrowsArgumentNullException()
+ protected void VerifySegment(List<T> expected, ArraySegment<T> segment)
{
- Assert.Throws<ArgumentNullException>("array", () => new ArraySegment<int>(null)); // Array is null
+ Assert.Equal(expected.Count, segment.Count);
+
+ for (int i = 0; i < expected.Count; ++i)
+ {
+ Assert.True(expected[i] == null ? (segment as IList<T>)[i] == null : expected[i].Equals((segment as IList<T>)[i]));
+ }
}
- [Theory]
- [InlineData(new int[] { 7, 8, 9, 10, 11 }, 2, 3)]
- [InlineData(new int[] { 7, 8, 9, 10, 11 }, 0, 5)]
- [InlineData(new int[0], 0, 0)]
- public static void Ctor_Array_Int_Int(int[] array, int offset, int count)
+ #endregion
+
+ [Fact]
+ public void Ctor_Empty()
{
- var segment = new ArraySegment<int>(array, offset, count);
+ var segment = new ArraySegment<T>();
+ Assert.Null(segment.Array);
+ Assert.Equal(0, segment.Offset);
+ Assert.Equal(0, segment.Count);
+ T[] array = new T[10];
+ segment = new ArraySegment<T>(array, 10, 0);
Assert.Same(array, segment.Array);
- Assert.Equal(offset, segment.Offset);
- Assert.Equal(count, segment.Count);
+ Assert.Equal(10, segment.Offset);
+ Assert.Equal(0, segment.Count);
}
[Fact]
- public static void Ctor_Array_Int_Int_Invalid()
+ public static void Ctor_Invalid()
{
- Assert.Throws<ArgumentNullException>("array", () => new ArraySegment<int>(null, 0, 0)); // Array is null
+ Assert.Throws<ArgumentNullException>("array", () => new ArraySegment<T>(null));
+ Assert.Throws<ArgumentNullException>("array", () => new ArraySegment<T>(null, -1, 1));
+ Assert.Throws<ArgumentOutOfRangeException>("offset", () => new ArraySegment<T>(new T[10], -1, 0)); // Offset < 0
+ Assert.Throws<ArgumentOutOfRangeException>("count", () => new ArraySegment<T>(new T[10], 0, -1)); // Count < 0
+ Assert.Throws<ArgumentException>(null, () => new ArraySegment<T>(new T[10], 10, 1)); // Offset + count > array.Length
+ Assert.Throws<ArgumentException>(null, () => new ArraySegment<T>(new T[10], 9, 2)); // Offset + count > array.Length
+ }
+ }
- Assert.Throws<ArgumentOutOfRangeException>("offset", () => new ArraySegment<int>(new int[10], -1, 0)); // Offset < 0
- Assert.Throws<ArgumentOutOfRangeException>("count", () => new ArraySegment<int>(new int[10], 0, -1)); // Count < 0
+ public class ArraySegment_Tests_string : ArraySegment_Tests<string>
+ {
+ protected override string CreateT(int seed)
+ {
+ int stringLength = seed % 10 + 5;
+ Random rand = new Random(seed);
+ byte[] bytes = new byte[stringLength];
+ rand.NextBytes(bytes);
+ return Convert.ToBase64String(bytes);
+ }
+ }
- Assert.Throws<ArgumentException>(null, () => new ArraySegment<int>(new int[10], 10, 1)); // Offset + count > array.Length
- Assert.Throws<ArgumentException>(null, () => new ArraySegment<int>(new int[10], 9, 2)); // Offset + count > array.Length
+ public class ArraySegment_Tests_int : ArraySegment_Tests<int>
+ {
+ protected override int CreateT(int seed)
+ {
+ Random rand = new Random(seed);
+ return rand.Next();
}
+ }
+
+ public static class ArraySegment_Tests
+ {
public static IEnumerable<object[]> Equals_TestData()
{
var intArray1 = new int[] { 7, 8, 9, 10, 11, 12 };
@@ -194,21 +245,6 @@ namespace System.Tests
}
[Fact]
- public static void IList_Contains()
- {
- var intArray = new int[] { 7, 8, 9, 10, 11, 12, 13 };
- var segment = new ArraySegment<int>(intArray, 2, 3);
- IList<int> iList = segment;
-
- for (int i = segment.Offset; i < segment.Count; i++)
- {
- Assert.True(iList.Contains(intArray[i]));
- }
- Assert.False(iList.Contains(999)); // No such value
- Assert.False(iList.Contains(7)); // No such value in range
- }
-
- [Fact]
public static void IList_Contains_NullArray_ThrowsInvalidOperationException()
{
IList<int> iList = new ArraySegment<int>();
@@ -219,54 +255,10 @@ namespace System.Tests
public static void IList_GetEnumerator()
{
var intArray = new int[] { 7, 8, 9, 10, 11, 12, 13 };
- IList<int> iList = new ArraySegment<int>(intArray, 2, 3);
-
- IEnumerator<int> enumerator = iList.GetEnumerator();
- for (int i = 0; i < 2; i++)
- {
- int counter = 0;
- while (enumerator.MoveNext())
- {
- Assert.Equal(intArray[counter + 2], enumerator.Current);
- counter++;
- }
- Assert.Equal(iList.Count, counter);
-
- enumerator.Reset();
- }
- }
-
- [Fact]
- public static void IList_GetEnumerator_Invalid()
- {
- var intArray = new int[] { 7, 8, 9, 10, 11, 12, 13 };
- IList<int> iList = new ArraySegment<int>(intArray, 2, 3);
- IEnumerator<int> enumerator = iList.GetEnumerator();
-
- // Enumerator should throw when accessing Current before starting enumeration
- Assert.Throws<InvalidOperationException>(() => enumerator.Current);
- while (enumerator.MoveNext()) ;
-
- // Enumerator should throw when accessing Current after finishing enumeration
- Assert.False(enumerator.MoveNext());
- Assert.Throws<InvalidOperationException>(() => enumerator.Current);
-
- // Enumerator should throw when accessing Current after being reset
- enumerator.Reset();
- Assert.Throws<InvalidOperationException>(() => enumerator.Current);
-
- iList = new ArraySegment<int>();
- Assert.Throws<InvalidOperationException>(() => iList.GetEnumerator()); // Underlying array is null
- }
-
- [Fact]
- public static void IEnumerable_GetEnumerator()
- {
- var intArray = new int[] { 7, 8, 9, 10, 11, 12, 13 };
- var segment = new ArraySegment<int>(intArray, 2, 3);
- IEnumerable iList = segment;
+ ArraySegment<int> segment = new ArraySegment<int>(intArray, 2, 3);
- IEnumerator enumerator = iList.GetEnumerator();
+ //ArraySegment<int>.Enumerator enumerator = segment.GetEnumerator();
+ IEnumerator<int> enumerator = (segment as IEnumerable<int>).GetEnumerator();
for (int i = 0; i < 2; i++)
{
int counter = 0;
@@ -277,70 +269,8 @@ namespace System.Tests
}
Assert.Equal(segment.Count, counter);
- enumerator.Reset();
+ (enumerator as IEnumerator<int>).Reset();
}
}
-
- [Fact]
- public static void IEnumerable_GetEnumerator_Invalid()
- {
- var intArray = new int[] { 7, 8, 9, 10, 11, 12, 13 };
- IEnumerable enumerable = new ArraySegment<int>(intArray, 2, 3);
- IEnumerator enumerator = enumerable.GetEnumerator();
-
- // Enumerator should throw when accessing Current before starting enumeration
- Assert.Throws<InvalidOperationException>(() => enumerator.Current);
- while (enumerator.MoveNext()) ;
-
- // Enumerator should throw when accessing Current after finishing enumeration
- Assert.False(enumerator.MoveNext());
- Assert.Throws<InvalidOperationException>(() => enumerator.Current);
-
- // Enumerator should throw when accessing Current after being reset
- enumerator.Reset();
- Assert.Throws<InvalidOperationException>(() => enumerator.Current);
-
- enumerable = new ArraySegment<int>();
- Assert.Throws<InvalidOperationException>(() => enumerable.GetEnumerator()); // Underlying array is null
- }
-
- [Fact]
- public static void IList_CopyTo()
- {
- var stringArray = new string[] { "0", "1", "2", "3", "4" };
- IList<string> stringSegment = new ArraySegment<string>(stringArray, 1, 3);
- stringSegment.CopyTo(stringArray, 2);
- Assert.Equal(new string[] { "0", "1", "1", "2", "3" }, stringArray);
-
- stringArray = new string[] { "0", "1", "2", "3", "4" };
- stringSegment = new ArraySegment<string>(stringArray, 1, 3);
- stringSegment.CopyTo(stringArray, 0);
- Assert.Equal(new string[] { "1", "2", "3", "3", "4" }, stringArray);
-
- var intArray = new int[] { 0, 1, 2, 3, 4 };
- IList<int> intSegment = new ArraySegment<int>(intArray, 1, 3);
- intSegment.CopyTo(intArray, 2);
- Assert.Equal(new int[] { 0, 1, 1, 2, 3 }, intArray);
-
- intArray = new int[] { 0, 1, 2, 3, 4 };
- intSegment = new ArraySegment<int>(intArray, 1, 3);
- intSegment.CopyTo(intArray, 0);
- Assert.Equal(new int[] { 1, 2, 3, 3, 4 }, intArray);
- }
-
- [Fact]
- public static void IList_CopyTo_Invalid()
- {
- IList<int> iList = new ArraySegment<int>();
- Assert.Throws<InvalidOperationException>(() => iList.CopyTo(new int[7], 0)); // Array is null
-
- var intArray = new int[] { 7, 8, 9, 10, 11, 12, 13 };
- iList = new ArraySegment<int>(intArray, 2, 3);
-
- Assert.Throws<ArgumentNullException>("dest", () => iList.CopyTo(null, 0)); // Destination array is null
-
- Assert.Throws<ArgumentOutOfRangeException>("dstIndex", () => iList.CopyTo(new int[7], -1)); // Index < 0
- Assert.Throws<ArgumentException>("", () => iList.CopyTo(new int[7], 8)); // Index > destinationArray.Length
- }
}
}
diff --git a/src/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.cs b/src/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.cs
index 9271ec78dc..477cf47142 100644
--- a/src/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.cs
+++ b/src/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.cs
@@ -7,7 +7,7 @@ using Xunit;
namespace System.ComponentModel.Tests
{
- public static class DefaultValueAttributeTests
+ public static partial class DefaultValueAttributeTests
{
[Fact]
public static void Ctor()
diff --git a/src/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.netcoreapp1.1.cs b/src/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.netcoreapp1.1.cs
new file mode 100644
index 0000000000..d0ddd3103b
--- /dev/null
+++ b/src/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.netcoreapp1.1.cs
@@ -0,0 +1,21 @@
+// 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.Generic;
+using Xunit;
+
+namespace System.ComponentModel.Tests
+{
+ public static partial class DefaultValueAttributeTests
+ {
+ [Fact]
+ public static void Ctor_netcoreapp11()
+ {
+ Assert.Equal((sbyte)42, new DefaultValueAttribute((sbyte)42).Value);
+ Assert.Equal((ushort)42, new DefaultValueAttribute((ushort)42).Value);
+ Assert.Equal((uint)42, new DefaultValueAttribute((uint)42).Value);
+ Assert.Equal((ulong)42, new DefaultValueAttribute((ulong)42).Value);
+ }
+ }
+}
diff --git a/src/System.Runtime/tests/System/Reflection/ModuleTests.cs b/src/System.Runtime/tests/System/Reflection/ModuleTests.cs
index 558d477dae..dd70b3f2db 100644
--- a/src/System.Runtime/tests/System/Reflection/ModuleTests.cs
+++ b/src/System.Runtime/tests/System/Reflection/ModuleTests.cs
@@ -188,7 +188,7 @@ namespace System.Reflection.Tests
{
new object[] { 1234 },
new object[] { typeof(ModuleTests).GetMethod("ResolveType").MetadataToken },
- new object[] { typeof(ModuleTests).MetadataToken + 1000 },
+ new object[] { typeof(ModuleTests).MetadataToken + 10000 },
};
[Theory]
diff --git a/src/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.cs b/src/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.cs
index 166682c26b..c1299a912c 100644
--- a/src/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.cs
+++ b/src/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.cs
@@ -2,46 +2,214 @@
// 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.CompilerServices;
-
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
using Xunit;
namespace System.Runtime.CompilerServices.Tests
{
- public class ConditionalWeakTableTests
+ public partial class ConditionalWeakTableTests
{
[Fact]
- public static void Add()
+ public static void InvalidArgs_Throws()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+
+ object ignored;
+ Assert.Throws<ArgumentNullException>("key", () => cwt.Add(null, new object())); // null key
+ Assert.Throws<ArgumentNullException>("key", () => cwt.TryGetValue(null, out ignored)); // null key
+ Assert.Throws<ArgumentNullException>("key", () => cwt.Remove(null)); // null key
+ Assert.Throws<ArgumentNullException>("createValueCallback", () => cwt.GetValue(new object(), null)); // null delegate
+
+ object key = new object();
+ cwt.Add(key, key);
+ Assert.Throws<ArgumentException>(null, () => cwt.Add(key, key)); // duplicate key
+ }
+
+ [Theory]
+ [InlineData(1)]
+ [InlineData(100)]
+ public static void Add(int numObjects)
+ {
+ // Isolated to ensure we drop all references even in debug builds where lifetime is extended by the JIT to the end of the method
+ Func<int, Tuple<ConditionalWeakTable<object, object>, WeakReference[], WeakReference[]>> body = count =>
+ {
+ object[] keys = Enumerable.Range(0, count).Select(_ => new object()).ToArray();
+ object[] values = Enumerable.Range(0, count).Select(_ => new object()).ToArray();
+ var cwt = new ConditionalWeakTable<object, object>();
+
+ for (int i = 0; i < count; i++)
+ {
+ cwt.Add(keys[i], values[i]);
+ }
+
+ for (int i = 0; i < count; i++)
+ {
+ object value;
+ Assert.True(cwt.TryGetValue(keys[i], out value));
+ Assert.Same(values[i], value);
+ Assert.Same(value, cwt.GetOrCreateValue(keys[i]));
+ Assert.Same(value, cwt.GetValue(keys[i], _ => new object()));
+ }
+
+ return Tuple.Create(cwt, keys.Select(k => new WeakReference(k)).ToArray(), values.Select(v => new WeakReference(v)).ToArray());
+ };
+
+ Tuple<ConditionalWeakTable<object, object>, WeakReference[], WeakReference[]> result = body(numObjects);
+ GC.Collect();
+
+ Assert.NotNull(result.Item1);
+
+ for (int i = 0; i < numObjects; i++)
+ {
+ Assert.False(result.Item2[i].IsAlive, $"Expected not to find key #{i}");
+ Assert.False(result.Item3[i].IsAlive, $"Expected not to find value #{i}");
+ }
+ }
+
+ [Theory]
+ [InlineData(1)]
+ [InlineData(100)]
+ public static void AddMany_ThenRemoveAll(int numObjects)
+ {
+ object[] keys = Enumerable.Range(0, numObjects).Select(_ => new object()).ToArray();
+ object[] values = Enumerable.Range(0, numObjects).Select(_ => new object()).ToArray();
+ var cwt = new ConditionalWeakTable<object, object>();
+
+ for (int i = 0; i < numObjects; i++)
+ {
+ cwt.Add(keys[i], values[i]);
+ }
+
+ for (int i = 0; i < numObjects; i++)
+ {
+ Assert.Same(values[i], cwt.GetValue(keys[i], _ => new object()));
+ }
+
+ for (int i = 0; i < numObjects; i++)
+ {
+ Assert.True(cwt.Remove(keys[i]));
+ Assert.False(cwt.Remove(keys[i]));
+ }
+
+ for (int i = 0; i < numObjects; i++)
+ {
+ object ignored;
+ Assert.False(cwt.TryGetValue(keys[i], out ignored));
+ }
+ }
+
+ [Theory]
+ [InlineData(100)]
+ public static void AddRemoveIteratively(int numObjects)
+ {
+ object[] keys = Enumerable.Range(0, numObjects).Select(_ => new object()).ToArray();
+ object[] values = Enumerable.Range(0, numObjects).Select(_ => new object()).ToArray();
+ var cwt = new ConditionalWeakTable<object, object>();
+
+ for (int i = 0; i < numObjects; i++)
+ {
+ cwt.Add(keys[i], values[i]);
+ Assert.Same(values[i], cwt.GetValue(keys[i], _ => new object()));
+ Assert.True(cwt.Remove(keys[i]));
+ Assert.False(cwt.Remove(keys[i]));
+ }
+ }
+
+ [Fact]
+ public static void Concurrent_AddMany_DropReferences() // no asserts, just making nothing throws
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ for (int i = 0; i < 10000; i++)
+ {
+ cwt.Add(i.ToString(), i.ToString());
+ if (i % 1000 == 0) GC.Collect();
+ }
+ }
+
+ [Fact]
+ public static void Concurrent_Add_Read_Remove_DifferentObjects()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(0.25);
+ Parallel.For(0, Environment.ProcessorCount, i =>
+ {
+ while (DateTime.UtcNow < end)
+ {
+ object key = new object();
+ object value = new object();
+ cwt.Add(key, value);
+ Assert.Same(value, cwt.GetValue(key, _ => new object()));
+ Assert.True(cwt.Remove(key));
+ Assert.False(cwt.Remove(key));
+ }
+ });
+ }
+
+ [Fact]
+ public static void Concurrent_GetValue_Read_Remove_DifferentObjects()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(0.25);
+ Parallel.For(0, Environment.ProcessorCount, i =>
+ {
+ while (DateTime.UtcNow < end)
+ {
+ object key = new object();
+ object value = new object();
+ Assert.Same(value, cwt.GetValue(key, _ => value));
+ Assert.True(cwt.Remove(key));
+ Assert.False(cwt.Remove(key));
+ }
+ });
+ }
+
+ [Fact]
+ public static void Concurrent_GetValue_Read_Remove_SameObject()
{
- ConditionalWeakTable<object, object> cwt = new ConditionalWeakTable<object, object>();
object key = new object();
object value = new object();
- object obj = null;
- cwt.Add(key, value);
+ var cwt = new ConditionalWeakTable<object, object>();
+ DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(0.25);
+ Parallel.For(0, Environment.ProcessorCount, i =>
+ {
+ while (DateTime.UtcNow < end)
+ {
+ Assert.Same(value, cwt.GetValue(key, _ => value));
+ cwt.Remove(key);
+ }
+ });
+ }
- Assert.True(cwt.TryGetValue(key, out value));
- Assert.Equal(value, cwt.GetOrCreateValue(key));
- Assert.Equal(value, cwt.GetValue(key, k => new object()));
+ [Fact]
+ public static void AddRemove_DropValue()
+ {
+ var key = new object();
+ var value = new object();
- WeakReference<object> wrValue = new WeakReference<object>(value, false);
- WeakReference<object> wrkey = new WeakReference<object>(key, false);
- key = null;
+ var cwt = new ConditionalWeakTable<object, object>();
+
+ cwt.Add(key, value);
+ cwt.Remove(key);
+
+ // Verify that the removed entry is not keeping the value alive
+ var wrValue = new WeakReference(value);
value = null;
GC.Collect();
+ Assert.False(wrValue.IsAlive);
- // key and value must be collected
- Assert.False(wrValue.TryGetTarget(out obj));
- Assert.False(wrkey.TryGetTarget(out obj));
+ GC.KeepAlive(cwt);
+ GC.KeepAlive(key);
}
[Fact]
public static void GetOrCreateValue()
{
- ConditionalWeakTable<object, object> cwt = new ConditionalWeakTable<object, object>();
- object key = new object();
+ var cwt = new ConditionalWeakTable<object, object>();
+ var key = new object();
object obj = null;
object value = cwt.GetOrCreateValue(key);
@@ -49,8 +217,8 @@ namespace System.Runtime.CompilerServices.Tests
Assert.True(cwt.TryGetValue(key, out value));
Assert.Equal(value, cwt.GetValue(key, k => new object()));
- WeakReference<object> wrValue = new WeakReference<object>(value, false);
- WeakReference<object> wrkey = new WeakReference<object>(key, false);
+ var wrValue = new WeakReference<object>(value, false);
+ var wrkey = new WeakReference<object>(key, false);
key = null;
value = null;
@@ -64,8 +232,8 @@ namespace System.Runtime.CompilerServices.Tests
[Fact]
public static void GetValue()
{
- ConditionalWeakTable<object, object> cwt = new ConditionalWeakTable<object, object>();
- object key = new object();
+ var cwt = new ConditionalWeakTable<object, object>();
+ var key = new object();
object obj = null;
object value = cwt.GetValue(key, k => new object());
@@ -84,5 +252,46 @@ namespace System.Runtime.CompilerServices.Tests
Assert.False(wrValue.TryGetTarget(out obj));
Assert.False(wrkey.TryGetTarget(out obj));
}
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(100)]
+ public static void Clear_AllValuesRemoved(int numObjects)
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+
+ MethodInfo clear = cwt.GetType().GetMethod("Clear", BindingFlags.NonPublic | BindingFlags.Instance);
+ if (clear == null)
+ {
+ // Couldn't access the Clear method; skip the test.
+ return;
+ }
+
+ object[] keys = Enumerable.Range(0, numObjects).Select(_ => new object()).ToArray();
+ object[] values = Enumerable.Range(0, numObjects).Select(_ => new object()).ToArray();
+
+ for (int iter = 0; iter < 2; iter++)
+ {
+ // Add the objects
+ for (int i = 0; i < numObjects; i++)
+ {
+ cwt.Add(keys[i], values[i]);
+ Assert.Same(values[i], cwt.GetValue(keys[i], _ => new object()));
+ }
+
+ // Clear the table
+ clear.Invoke(cwt, null);
+
+ // Verify the objects are removed
+ for (int i = 0; i < numObjects; i++)
+ {
+ object ignored;
+ Assert.False(cwt.TryGetValue(keys[i], out ignored));
+ }
+
+ // Do it a couple of times, to make sure the table is still usable after a clear.
+ }
+ }
}
}
diff --git a/src/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.netcoreapp1.1.cs b/src/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.netcoreapp1.1.cs
new file mode 100644
index 0000000000..82dc4fbe73
--- /dev/null
+++ b/src/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.netcoreapp1.1.cs
@@ -0,0 +1,36 @@
+// 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.CompilerServices;
+
+using Xunit;
+
+namespace System.Runtime.CompilerServices.Tests
+{
+ public partial class ConditionalWeakTableTests
+ {
+ [Fact]
+ public static void AddOrUpdateDataTest()
+ {
+ ConditionalWeakTable<string, string> cwt = new ConditionalWeakTable<string, string>();
+ string key = "key1";
+ cwt.AddOrUpdate(key, "value1");
+
+ string value;
+ Assert.True(cwt.TryGetValue(key, out value));
+ Assert.Equal(value, "value1");
+ Assert.Equal(value, cwt.GetOrCreateValue(key));
+ Assert.Equal(value, cwt.GetValue(key, k => "value1"));
+
+ Assert.Throws<ArgumentNullException>(() => cwt.AddOrUpdate(null, "value2"));
+
+ cwt.AddOrUpdate(key, "value2");
+ Assert.True(cwt.TryGetValue(key, out value));
+ Assert.Equal(value, "value2");
+ Assert.Equal(value, cwt.GetOrCreateValue(key));
+ Assert.Equal(value, cwt.GetValue(key, k => "value1"));
+ }
+ }
+}
diff --git a/src/System.Runtime/tests/System/StringTests.cs b/src/System.Runtime/tests/System/StringTests.cs
index e3cf3be985..db92512b29 100644
--- a/src/System.Runtime/tests/System/StringTests.cs
+++ b/src/System.Runtime/tests/System/StringTests.cs
@@ -1618,23 +1618,32 @@ namespace System.Tests
yield return new object[] { null, new object[] { "Foo", "Bar", "Baz" }, "FooBarBaz" };
yield return new object[] { "$$", new object[] { "Foo", null, "Baz" }, "Foo$$$$Baz" };
- // Join does nothing if array[0] is null
- yield return new object[] { "$$", new object[] { null, "Bar", "Baz" }, "" };
+ // Test join when first value is null
+ yield return new object[] { "$$", new object[] { null, "Bar", "Baz" }, "$$Bar$$Baz" };
// Join should ignore objects that have a null ToString() value
yield return new object[] { "|", new object[] { new ObjectWithNullToString(), "Foo", new ObjectWithNullToString(), "Bar", new ObjectWithNullToString() }, "|Foo||Bar|" };
}
- [ActiveIssue(13747)]
[Theory]
[MemberData(nameof(Join_ObjectArray_TestData))]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework | TargetFrameworkMonikers.NetcoreUwp | TargetFrameworkMonikers.Netcoreapp1_0)]
public static void Join_ObjectArray(string separator, object[] values, string expected)
{
Assert.Equal(expected, string.Join(separator, values));
- if (!(values.Length > 0 && values[0] == null))
- {
- Assert.Equal(expected, string.Join(separator, (IEnumerable<object>)values));
- }
+ Assert.Equal(expected, string.Join(separator, (IEnumerable<object>)values));
+ }
+
+ [Theory]
+ [MemberData(nameof(Join_ObjectArray_TestData))]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.Netcoreapp1_1)]
+ public static void Join_ObjectArray_WithNullIssue(string separator, object[] values, string expected)
+ {
+ string enumerableExpected = expected;
+ if (values.Length > 0 && values[0] == null) // Join return nothing when first value is null
+ expected = "";
+ Assert.Equal(expected, string.Join(separator, values));
+ Assert.Equal(enumerableExpected, string.Join(separator, (IEnumerable<object>)values));
}
[Fact]
diff --git a/src/System.Runtime/tests/System/TimeSpanTests.cs b/src/System.Runtime/tests/System/TimeSpanTests.cs
index 89a26d0524..89d28912db 100644
--- a/src/System.Runtime/tests/System/TimeSpanTests.cs
+++ b/src/System.Runtime/tests/System/TimeSpanTests.cs
@@ -270,7 +270,6 @@ namespace System.Tests
yield return new object[] { new TimeSpan(1, 2, 3, 4, 5), new TimeSpan(1, 2, 4, 4, 5), false };
yield return new object[] { new TimeSpan(1, 2, 3, 4, 5), new TimeSpan(1, 3, 3, 4, 5), false };
yield return new object[] { new TimeSpan(1, 2, 3, 4, 5), new TimeSpan(2, 2, 3, 4, 5), false };
- yield return new object[] { new TimeSpan(1, 2, 3, 4, 5), new TimeSpan(2, 2, 3, 4, 5), false };
yield return new object[] { new TimeSpan(1, 2, 3, 4, 5), new TimeSpan(1, 2, 3, 4), false };
yield return new object[] { new TimeSpan(1, 2, 3, 4, 5), new TimeSpan(2, 2, 3), false };
diff --git a/src/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/System.Runtime/tests/System/TimeZoneInfoTests.cs
index 1f0b6c50d7..2e9546bab0 100644
--- a/src/System.Runtime/tests/System/TimeZoneInfoTests.cs
+++ b/src/System.Runtime/tests/System/TimeZoneInfoTests.cs
@@ -1957,7 +1957,7 @@ namespace System.Tests
VerifyTimeSpanArray(ret, expectedOffsets, string.Format("Wrong offsets when used {0} with the zone {1}", dt, tz.Id));
}
- static public void VerifyTimeSpanArray(TimeSpan[] actual, TimeSpan[] expected, string errorMsg)
+ public static void VerifyTimeSpanArray(TimeSpan[] actual, TimeSpan[] expected, string errorMsg)
{
Assert.True(actual != null);
Assert.True(expected != null);
diff --git a/src/System.Runtime/tests/TimeZoneInfoTests.netstandard1.7.cs b/src/System.Runtime/tests/TimeZoneInfoTests.netstandard1.7.cs
index de277116ad..48911a7bb9 100644
--- a/src/System.Runtime/tests/TimeZoneInfoTests.netstandard1.7.cs
+++ b/src/System.Runtime/tests/TimeZoneInfoTests.netstandard1.7.cs
@@ -2,11 +2,7 @@
// 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.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Globalization;
-using System.Runtime.InteropServices;
using Xunit;
namespace System.Tests
@@ -259,6 +255,25 @@ namespace System.Tests
Assert.Equal(utcOffsetNow, TimeZoneInfo.ConvertTimeBySystemTimeZoneId(offsetNow, TimeZoneInfo.Utc.Id));
}
+ public static IEnumerable<object[]> SystemTimeZonesTestData()
+ {
+ foreach (TimeZoneInfo tz in TimeZoneInfo.GetSystemTimeZones())
+ {
+ yield return new object[] { tz };
+ }
+ }
+
+ [ActiveIssue(14797, TestPlatforms.AnyUnix)]
+ [Theory]
+ [MemberData(nameof(SystemTimeZonesTestData))]
+ public static void ToSerializedString_FromSerializedString_RoundTrips(TimeZoneInfo timeZone)
+ {
+ string serialized = timeZone.ToSerializedString();
+ TimeZoneInfo deserializedTimeZone = TimeZoneInfo.FromSerializedString(serialized);
+ Assert.Equal(timeZone, deserializedTimeZone);
+ Assert.Equal(serialized, deserializedTimeZone.ToSerializedString());
+ }
+
private static TimeZoneInfo CreateCustomLondonTimeZone()
{
TimeZoneInfo.TransitionTime start = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 1, 0, 0), 3, 5, DayOfWeek.Sunday);
diff --git a/src/System.Security.AccessControl/src/System/Security/AccessControl/ACL.cs b/src/System.Security.AccessControl/src/System/Security/AccessControl/ACL.cs
index 320867cee6..2e06ae2e97 100644
--- a/src/System.Security.AccessControl/src/System/Security/AccessControl/ACL.cs
+++ b/src/System.Security.AccessControl/src/System/Security/AccessControl/ACL.cs
@@ -639,8 +639,8 @@ nameof(binaryForm));
Invalid = GO, // not a valid combination of flags
}
- private readonly static PM[] s_AFtoPM = CreateAFtoPMConversionMatrix(); // AceFlags-to-Propagation conversion matrix
- private readonly static AF[] s_PMtoAF = CreatePMtoAFConversionMatrix(); // Propagation-to-AceFlags conversion matrix
+ private static readonly PM[] s_AFtoPM = CreateAFtoPMConversionMatrix(); // AceFlags-to-Propagation conversion matrix
+ private static readonly AF[] s_PMtoAF = CreatePMtoAFConversionMatrix(); // Propagation-to-AceFlags conversion matrix
private static PM[] CreateAFtoPMConversionMatrix()
{
@@ -1502,7 +1502,7 @@ nameof(binaryForm));
}
- static private bool AceOpaquesMatch( QualifiedAce ace, QualifiedAce newAce )
+ private static bool AceOpaquesMatch( QualifiedAce ace, QualifiedAce newAce )
{
byte[] aceOpaque = ace.GetOpaque();
byte[] newAceOpaque = newAce.GetOpaque();
@@ -1528,7 +1528,7 @@ nameof(binaryForm));
return true;
}
- static private bool AcesAreMergeable( QualifiedAce ace, QualifiedAce newAce )
+ private static bool AcesAreMergeable( QualifiedAce ace, QualifiedAce newAce )
{
//
// Only interested in ACEs with the specified type
@@ -3093,7 +3093,7 @@ nameof(flags));
public sealed class DiscretionaryAcl : CommonAcl
{
#region
- static private SecurityIdentifier _sidEveryone = new SecurityIdentifier( WellKnownSidType.WorldSid, null );
+ private static SecurityIdentifier _sidEveryone = new SecurityIdentifier( WellKnownSidType.WorldSid, null );
private bool everyOneFullAccessForNullDacl = false;
#endregion
@@ -3290,7 +3290,7 @@ nameof(flags));
/// <returns>The single ACE DACL</returns>
/// Note: This method is created to get the best behavior for using "allow everyone full access"
/// single ACE DACL to replace null DACL from CommonSecurityObject.
- static internal DiscretionaryAcl CreateAllowEveryoneFullAccess(bool isDS, bool isContainer)
+ internal static DiscretionaryAcl CreateAllowEveryoneFullAccess(bool isDS, bool isContainer)
{
DiscretionaryAcl dcl = new DiscretionaryAcl( isContainer, isDS, 1 );
dcl.AddAccess(
diff --git a/src/System.Security.AccessControl/src/System/Security/AccessControl/NativeObjectSecurity.cs b/src/System.Security.AccessControl/src/System/Security/AccessControl/NativeObjectSecurity.cs
index 01047c42eb..619e48bce5 100644
--- a/src/System.Security.AccessControl/src/System/Security/AccessControl/NativeObjectSecurity.cs
+++ b/src/System.Security.AccessControl/src/System/Security/AccessControl/NativeObjectSecurity.cs
@@ -40,7 +40,7 @@ namespace System.Security.AccessControl
#region Delegates
- internal protected delegate System.Exception ExceptionFromErrorCode(int errorCode, string name, SafeHandle handle, object context);
+ protected internal delegate System.Exception ExceptionFromErrorCode(int errorCode, string name, SafeHandle handle, object context);
#endregion
diff --git a/src/System.Security.AccessControl/src/System/Security/AccessControl/ObjectSecurity.cs b/src/System.Security.AccessControl/src/System/Security/AccessControl/ObjectSecurity.cs
index e1304b4942..61b47ec00c 100644
--- a/src/System.Security.AccessControl/src/System/Security/AccessControl/ObjectSecurity.cs
+++ b/src/System.Security.AccessControl/src/System/Security/AccessControl/ObjectSecurity.cs
@@ -49,14 +49,14 @@ namespace System.Security.AccessControl
// only these SACL control flags will be automatically carry forward
// when update with new security descriptor.
- static private readonly ControlFlags SACL_CONTROL_FLAGS =
+ private static readonly ControlFlags SACL_CONTROL_FLAGS =
ControlFlags.SystemAclPresent |
ControlFlags.SystemAclAutoInherited |
ControlFlags.SystemAclProtected;
// only these DACL control flags will be automatically carry forward
// when update with new security descriptor
- static private readonly ControlFlags DACL_CONTROL_FLAGS =
+ private static readonly ControlFlags DACL_CONTROL_FLAGS =
ControlFlags.DiscretionaryAclPresent |
ControlFlags.DiscretionaryAclAutoInherited |
ControlFlags.DiscretionaryAclProtected;
diff --git a/src/System.Security.AccessControl/src/System/Security/AccessControl/PrivilegeNotHeldException.cs b/src/System.Security.AccessControl/src/System/Security/AccessControl/PrivilegeNotHeldException.cs
index 9b385cd51c..583ced24d0 100644
--- a/src/System.Security.AccessControl/src/System/Security/AccessControl/PrivilegeNotHeldException.cs
+++ b/src/System.Security.AccessControl/src/System/Security/AccessControl/PrivilegeNotHeldException.cs
@@ -30,7 +30,7 @@ namespace System.Security.AccessControl
_privilegeName = privilege;
}
- internal PrivilegeNotHeldException(SerializationInfo info, StreamingContext context) : base(info, context)
+ private PrivilegeNotHeldException(SerializationInfo info, StreamingContext context) : base(info, context)
{
_privilegeName = info.GetString(nameof(PrivilegeName));
}
diff --git a/src/System.Security.AccessControl/src/System/Security/AccessControl/Rules.cs b/src/System.Security.AccessControl/src/System/Security/AccessControl/Rules.cs
index 9475428122..44fc3e9855 100644
--- a/src/System.Security.AccessControl/src/System/Security/AccessControl/Rules.cs
+++ b/src/System.Security.AccessControl/src/System/Security/AccessControl/Rules.cs
@@ -32,7 +32,7 @@ namespace System.Security.AccessControl
#region Constructors
- internal protected AuthorizationRule(
+ protected internal AuthorizationRule(
IdentityReference identity,
int accessMask,
bool isInherited,
@@ -97,7 +97,7 @@ nameof(identity));
get { return _identity; }
}
- internal protected int AccessMask
+ protected internal int AccessMask
{
get { return _accessMask; }
}
diff --git a/src/System.Security.Claims/src/System/Security/Claims/GenericIdentity.cs b/src/System.Security.Claims/src/System/Security/Claims/GenericIdentity.cs
index 0df61d2494..24eea09915 100644
--- a/src/System.Security.Claims/src/System/Security/Claims/GenericIdentity.cs
+++ b/src/System.Security.Claims/src/System/Security/Claims/GenericIdentity.cs
@@ -9,7 +9,6 @@ using System.Collections.Generic;
namespace System.Security.Principal
{
- [System.Runtime.InteropServices.ComVisible(true)]
[Serializable]
public class GenericIdentity : ClaimsIdentity
{
diff --git a/src/System.Security.Claims/src/System/Security/Claims/GenericPrincipal.cs b/src/System.Security.Claims/src/System/Security/Claims/GenericPrincipal.cs
index 6d009d6033..734387b750 100644
--- a/src/System.Security.Claims/src/System/Security/Claims/GenericPrincipal.cs
+++ b/src/System.Security.Claims/src/System/Security/Claims/GenericPrincipal.cs
@@ -9,7 +9,6 @@ using System.Security.Claims;
namespace System.Security.Principal
{
- [System.Runtime.InteropServices.ComVisible(true)]
[Serializable]
public class GenericPrincipal : ClaimsPrincipal
{
diff --git a/src/System.Security.Claims/src/System/Security/Claims/RoleClaimProvider.cs b/src/System.Security.Claims/src/System/Security/Claims/RoleClaimProvider.cs
index 4da92f909f..e5f87df38d 100644
--- a/src/System.Security.Claims/src/System/Security/Claims/RoleClaimProvider.cs
+++ b/src/System.Security.Claims/src/System/Security/Claims/RoleClaimProvider.cs
@@ -18,7 +18,6 @@ namespace System.Security.Claims
/// made on parameters.
/// </summary>
- [System.Runtime.InteropServices.ComVisible(false)]
internal class RoleClaimProvider
{
string m_issuer;
diff --git a/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs b/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs
index 4514546f43..ef2a460b68 100644
--- a/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs
+++ b/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs
@@ -82,6 +82,7 @@ namespace System.Security.Cryptography
public static void AddOID(string oid, params string[] names) { }
public static object CreateFromName(string name) { throw null; }
public static object CreateFromName(string name, params object[] args) { throw null; }
+ public static byte[] EncodeOID(string str) { throw null; }
public static string MapNameToOID(string name) { throw null; }
}
[System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))]
@@ -246,7 +247,6 @@ namespace System.Security.Cryptography
{
public HMACMD5() { }
public HMACMD5(byte[] key) { }
- public override int HashSize { get { throw null; } }
public override byte[] Key { get { throw null; } set { } }
protected override void Dispose(bool disposing) { }
protected override void HashCore(byte[] rgb, int ib, int cb) { }
@@ -259,7 +259,6 @@ namespace System.Security.Cryptography
public HMACSHA1(byte[] key) { }
[System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))]
public HMACSHA1(byte[] key, bool useManagedSha1) { }
- public override int HashSize { get { throw null; } }
public override byte[] Key { get { throw null; } set { } }
protected override void Dispose(bool disposing) { }
protected override void HashCore(byte[] rgb, int ib, int cb) { }
@@ -270,7 +269,6 @@ namespace System.Security.Cryptography
{
public HMACSHA256() { }
public HMACSHA256(byte[] key) { }
- public override int HashSize { get { throw null; } }
public override byte[] Key { get { throw null; } set { } }
protected override void Dispose(bool disposing) { }
protected override void HashCore(byte[] rgb, int ib, int cb) { }
@@ -282,7 +280,6 @@ namespace System.Security.Cryptography
public HMACSHA384() { }
public HMACSHA384(byte[] key) { }
public bool ProduceLegacyHmacValues { get; set; }
- public override int HashSize { get { throw null; } }
public override byte[] Key { get { throw null; } set { } }
protected override void Dispose(bool disposing) { }
protected override void HashCore(byte[] rgb, int ib, int cb) { }
@@ -294,7 +291,6 @@ namespace System.Security.Cryptography
public HMACSHA512() { }
public HMACSHA512(byte[] key) { }
public bool ProduceLegacyHmacValues { get; set; }
- public override int HashSize { get { throw null; } }
public override byte[] Key { get { throw null; } set { } }
protected override void Dispose(bool disposing) { }
protected override void HashCore(byte[] rgb, int ib, int cb) { }
@@ -384,6 +380,7 @@ namespace System.Security.Cryptography
public Rfc2898DeriveBytes(string password, int saltSize, int iterations) { }
public int IterationCount { get { throw null; } set { } }
public byte[] Salt { get { throw null; } set { } }
+ public byte[] CryptDeriveKey(string algname, string alghashname, int keySize, byte[] rgbIV) { throw null; }
protected override void Dispose(bool disposing) { }
public override byte[] GetBytes(int cb) { throw null; }
public override void Reset() { }
@@ -531,7 +528,6 @@ namespace System.Security.Cryptography
public sealed partial class SHA1Managed : System.Security.Cryptography.SHA1
{
public SHA1Managed() { }
- public sealed override int HashSize { get { throw null; } }
protected sealed override void Dispose(bool disposing) { }
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) { }
protected sealed override byte[] HashFinal() { throw null; }
@@ -547,7 +543,6 @@ namespace System.Security.Cryptography
public sealed partial class SHA256Managed : System.Security.Cryptography.SHA256
{
public SHA256Managed() { }
- public sealed override int HashSize { get { throw null; } }
protected sealed override void Dispose(bool disposing) { }
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) { }
protected sealed override byte[] HashFinal() { throw null; }
@@ -563,7 +558,6 @@ namespace System.Security.Cryptography
public sealed partial class SHA384Managed : System.Security.Cryptography.SHA384
{
public SHA384Managed() { }
- public sealed override int HashSize { get { throw null; } }
protected sealed override void Dispose(bool disposing) { }
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) { }
protected sealed override byte[] HashFinal() { throw null; }
@@ -579,7 +573,6 @@ namespace System.Security.Cryptography
public sealed partial class SHA512Managed : System.Security.Cryptography.SHA512
{
public SHA512Managed() { }
- public sealed override int HashSize { get { throw null; } }
protected sealed override void Dispose(bool disposing) { }
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) { }
protected sealed override byte[] HashFinal() { throw null; }
diff --git a/src/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx b/src/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx
index 6d0f2849eb..099d97eb78 100644
--- a/src/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx
+++ b/src/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx
@@ -138,6 +138,9 @@
<data name="Arg_CryptographyException" xml:space="preserve">
<value>Error occurred during a cryptographic operation.</value>
</data>
+ <data name="Cryptography_Config_EncodedOIDError" xml:space="preserve">
+ <value>Encoded OID length is too large (greater than 0x7f bytes).</value>
+ </data>
<data name="Cryptography_CSP_NoPrivateKey" xml:space="preserve">
<value>Object contains only the public half of a key pair. A private key must also be provided.</value>
</data>
@@ -147,6 +150,9 @@
<data name="Cryptography_HashAlgorithmNameNullOrEmpty" xml:space="preserve">
<value>The hash algorithm name cannot be null or empty.</value>
</data>
+ <data name="Cryptography_InvalidOID" xml:space="preserve">
+ <value>Object identifier (OID) is unknown.</value>
+ </data>
<data name="Cryptography_CurveNotSupported" xml:space="preserve">
<value>The specified curve '{0}' or its parameters are not valid for this platform.</value>
</data>
diff --git a/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj
index 0991a2ce5d..a272af017e 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj
+++ b/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj
@@ -412,24 +412,12 @@
<Link>Common\System\Security\Cryptography\RSAOpenSsl.cs</Link>
</Compile>
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463' And '$(IsPartialFacadeAssembly)' != 'true'">
- <Compile Include="$(CommonPath)\System\SerializableAttribute.cs">
- <Link>Common\System\SerializableAttribute.cs</Link>
- </Compile>
- <Compile Include="$(CommonPath)\System\NonSerializedAttribute.cs">
- <Link>Common\System\NonSerializedAttribute.cs</Link>
- </Compile>
- </ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)'=='true'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System" />
<TargetingPackReference Include="System.Core" />
<Compile Include="System\Security\Cryptography\IncrementalHash.net46.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
- <!-- TODO: Remove this after a package update -->
- <ProjectReference Include="../../System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj" />
- </ItemGroup>
<ItemGroup>
<Reference Include="System.Runtime" />
<Reference Include="System.Resources.ResourceManager" />
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs
index 2844157e60..b94d64eb6b 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
+using System.Globalization;
using System.Reflection;
namespace System.Security.Cryptography
@@ -31,6 +32,8 @@ namespace System.Security.Cryptography
private static volatile Dictionary<string, string> s_defaultOidHT = null;
private static volatile Dictionary<string, object> s_defaultNameHT = null;
+ private static readonly char[] SepArray = { '.' }; // valid ASN.1 separators
+
// CoreFx does not support AllowOnlyFipsAlgorithms
public static bool AllowOnlyFipsAlgorithms => false;
@@ -439,5 +442,125 @@ namespace System.Security.Cryptography
return oidName;
}
+
+ public static byte[] EncodeOID(string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException(nameof(str));
+
+ string[] oidString = str.Split(SepArray);
+ uint[] oidNums = new uint[oidString.Length];
+ for (int i = 0; i < oidString.Length; i++)
+ {
+ oidNums[i] = (uint)int.Parse(oidString[i], CultureInfo.InvariantCulture);
+ }
+
+ // Handle the first two oidNums special
+ if (oidNums.Length < 2)
+ throw new CryptographicUnexpectedOperationException(SR.Cryptography_InvalidOID);
+
+ uint firstTwoOidNums = (oidNums[0] * 40) + oidNums[1];
+
+ // Determine length of output array
+ int encodedOidNumsLength = 2; // Reserve first two bytes for later
+ EncodeSingleOidNum(firstTwoOidNums, null, ref encodedOidNumsLength);
+ for (int i = 2; i < oidNums.Length; i++)
+ {
+ EncodeSingleOidNum(oidNums[i], null, ref encodedOidNumsLength);
+ }
+
+ // Allocate the array to receive encoded oidNums
+ byte[] encodedOidNums = new byte[encodedOidNumsLength];
+ int encodedOidNumsIndex = 2;
+
+ // Encode each segment
+ EncodeSingleOidNum(firstTwoOidNums, encodedOidNums, ref encodedOidNumsIndex);
+ for (int i = 2; i < oidNums.Length; i++)
+ {
+ EncodeSingleOidNum(oidNums[i], encodedOidNums, ref encodedOidNumsIndex);
+ }
+
+ Debug.Assert(encodedOidNumsIndex == encodedOidNumsLength);
+
+ // Final return value is 06 <length> encodedOidNums[]
+ if (encodedOidNumsIndex - 2 > 0x7f)
+ throw new CryptographicUnexpectedOperationException(SR.Cryptography_Config_EncodedOIDError);
+
+ encodedOidNums[0] = (byte)0x06;
+ encodedOidNums[1] = (byte)(encodedOidNumsIndex - 2);
+
+ return encodedOidNums;
+ }
+
+ private static void EncodeSingleOidNum(uint value, byte[] destination, ref int index)
+ {
+ // Write directly to destination starting at index, and update index based on how many bytes written.
+ // If destination is null, just return updated index.
+ if (unchecked((int)value) < 0x80)
+ {
+ if (destination != null)
+ {
+ destination[index++] = (byte)value;
+ }
+ else
+ {
+ index += 1;
+ }
+ }
+ else if (value < 0x4000)
+ {
+ if (destination != null)
+ {
+ destination[index++] = (byte)((value >> 7) | 0x80);
+ destination[index++] = (byte)(value & 0x7f);
+ }
+ else
+ {
+ index += 2;
+ }
+ }
+ else if (value < 0x200000)
+ {
+ if (destination != null)
+ {
+ destination[index++] = (byte)((value >> 14) | 0x80);
+ destination[index++] = (byte)((value >> 7) | 0x80);
+ destination[index++] = (byte)(value & 0x7f);
+ }
+ else
+ {
+ index += 3;
+ }
+ }
+ else if (value < 0x10000000)
+ {
+ if (destination != null)
+ {
+ destination[index++] = (byte)((value >> 21) | 0x80);
+ destination[index++] = (byte)((value >> 14) | 0x80);
+ destination[index++] = (byte)((value >> 7) | 0x80);
+ destination[index++] = (byte)(value & 0x7f);
+ }
+ else
+ {
+ index += 4;
+ }
+ }
+ else
+ {
+ if (destination != null)
+ {
+ destination[index++] = (byte)((value >> 28) | 0x80);
+ destination[index++] = (byte)((value >> 21) | 0x80);
+ destination[index++] = (byte)((value >> 14) | 0x80);
+ destination[index++] = (byte)((value >> 7) | 0x80);
+ destination[index++] = (byte)(value & 0x7f);
+ }
+ else
+ {
+ index += 5;
+ }
+ }
+ }
}
}
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACMD5.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACMD5.cs
index 0e8fd30a73..6e9e633d09 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACMD5.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACMD5.cs
@@ -29,15 +29,8 @@ namespace System.Security.Cryptography
base.Key = _hMacCommon.ActualKey;
// this not really needed as it'll initialize BlockSizeValue with same value it has which is 64.
// we just want to be explicit in all HMAC extended classes
- BlockSizeValue = BlockSize;
- }
-
- public override int HashSize
- {
- get
- {
- return _hMacCommon.HashSizeInBits;
- }
+ BlockSizeValue = BlockSize;
+ HashSizeValue = _hMacCommon.HashSizeInBits;
}
public override byte[] Key
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA1.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA1.cs
index 356207611f..3277039ad0 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA1.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA1.cs
@@ -26,7 +26,8 @@ namespace System.Security.Cryptography
base.Key = _hMacCommon.ActualKey;
// this not really needed as it'll initialize BlockSizeValue with same value it has which is 64.
// we just want to be explicit in all HMAC extended classes
- BlockSizeValue = BlockSize;
+ BlockSizeValue = BlockSize;
+ HashSizeValue = _hMacCommon.HashSizeInBits;
}
[EditorBrowsable(EditorBrowsableState.Never)]
@@ -35,14 +36,6 @@ namespace System.Security.Cryptography
// useManagedSha1 is ignored
}
- public override int HashSize
- {
- get
- {
- return _hMacCommon.HashSizeInBits;
- }
- }
-
public override byte[] Key
{
get
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA256.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA256.cs
index f31436a081..268d4b79f1 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA256.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA256.cs
@@ -29,15 +29,8 @@ namespace System.Security.Cryptography
base.Key = _hMacCommon.ActualKey;
// this not really needed as it'll initialize BlockSizeValue with same value it has which is 64.
// we just want to be explicit in all HMAC extended classes
- BlockSizeValue = BlockSize;
- }
-
- public override int HashSize
- {
- get
- {
- return _hMacCommon.HashSizeInBits;
- }
+ BlockSizeValue = BlockSize;
+ HashSizeValue = _hMacCommon.HashSizeInBits;
}
public override byte[] Key
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA384.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA384.cs
index f68d5b7581..64f73980b7 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA384.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA384.cs
@@ -28,7 +28,8 @@ namespace System.Security.Cryptography
_hMacCommon = new HMACCommon(HashAlgorithmNames.SHA384, key, BlockSize);
base.Key = _hMacCommon.ActualKey;
// change the default value of BlockSizeValue to 128 instead of 64
- BlockSizeValue = BlockSize;
+ BlockSizeValue = BlockSize;
+ HashSizeValue = _hMacCommon.HashSizeInBits;
}
public bool ProduceLegacyHmacValues
@@ -48,14 +49,6 @@ namespace System.Security.Cryptography
}
}
- public override int HashSize
- {
- get
- {
- return _hMacCommon.HashSizeInBits;
- }
- }
-
public override byte[] Key
{
get
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA512.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA512.cs
index 6439afc3d0..f512bcb602 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA512.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA512.cs
@@ -28,7 +28,8 @@ namespace System.Security.Cryptography
_hMacCommon = new HMACCommon(HashAlgorithmNames.SHA512, key, BlockSize);
base.Key = _hMacCommon.ActualKey;
// change the default value of BlockSizeValue to 128 instead of 64
- BlockSizeValue = BlockSize;
+ BlockSizeValue = BlockSize;
+ HashSizeValue = _hMacCommon.HashSizeInBits;
}
public bool ProduceLegacyHmacValues
@@ -48,14 +49,6 @@ namespace System.Security.Cryptography
}
}
- public override int HashSize
- {
- get
- {
- return _hMacCommon.HashSizeInBits;
- }
- }
-
public override byte[] Key
{
get
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs
index f3c530079a..444ec604c3 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs
@@ -21,7 +21,7 @@ namespace System.Security.Cryptography
return new Implementation();
}
- static public new MD5 Create(String algName)
+ public static new MD5 Create(String algName)
{
return (MD5)CryptoConfig.CreateFromName(algName);
}
@@ -33,14 +33,7 @@ namespace System.Security.Cryptography
public Implementation()
{
_hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.MD5);
- }
-
- public sealed override int HashSize
- {
- get
- {
- return _hashProvider.HashSizeInBytes * 8;
- }
+ HashSizeValue = _hashProvider.HashSizeInBytes * 8;
}
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize)
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs
index 6c7019ff1b..94f0b919a2 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs
@@ -162,6 +162,17 @@ namespace System.Security.Cryptography
return password;
}
+ public byte[] CryptDeriveKey(string algname, string alghashname, int keySize, byte[] rgbIV)
+ {
+ // If this were to be implemented here, CAPI would need to be used (not CNG) because of
+ // unfortunate differences between the two. Using CNG would break compatibility. Since this
+ // assembly currently doesn't use CAPI it would require non-trivial additions.
+ // In addition, if implemented here, only Windows would be supported as it is intended as
+ // a thin wrapper over the corresponding native API.
+ // Note that this method is implemented in PasswordDeriveBytes (in the Csp assembly) using CAPI.
+ throw new PlatformNotSupportedException();
+ }
+
public override void Reset()
{
Initialize();
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs
index 8995d67db4..1d075f9d88 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs
@@ -34,14 +34,7 @@ namespace System.Security.Cryptography
public Implementation()
{
_hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA1);
- }
-
- public sealed override int HashSize
- {
- get
- {
- return _hashProvider.HashSizeInBytes * 8;
- }
+ HashSizeValue = _hashProvider.HashSizeInBytes * 8;
}
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize)
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs
index 90f273763c..1bd1c7867b 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs
@@ -16,14 +16,7 @@ namespace System.Security.Cryptography
public SHA1Managed()
{
_hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA1);
- }
-
- public sealed override int HashSize
- {
- get
- {
- return _hashProvider.HashSizeInBytes * 8;
- }
+ HashSizeValue = _hashProvider.HashSizeInBytes * 8;
}
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize)
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs
index 69ee0e4dc8..d8695c40c3 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs
@@ -33,14 +33,7 @@ namespace System.Security.Cryptography
public Implementation()
{
_hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA256);
- }
-
- public sealed override int HashSize
- {
- get
- {
- return _hashProvider.HashSizeInBytes * 8;
- }
+ HashSizeValue = _hashProvider.HashSizeInBytes * 8;
}
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize)
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs
index 900e4a3cfc..7ea4f77873 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs
@@ -16,14 +16,7 @@ namespace System.Security.Cryptography
public SHA256Managed()
{
_hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA256);
- }
-
- public sealed override int HashSize
- {
- get
- {
- return _hashProvider.HashSizeInBytes * 8;
- }
+ HashSizeValue = _hashProvider.HashSizeInBytes * 8;
}
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize)
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs
index 93fa6dc644..2311d7b25e 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs
@@ -33,14 +33,7 @@ namespace System.Security.Cryptography
public Implementation()
{
_hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA384);
- }
-
- public sealed override int HashSize
- {
- get
- {
- return _hashProvider.HashSizeInBytes * 8;
- }
+ HashSizeValue = _hashProvider.HashSizeInBytes * 8;
}
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize)
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs
index 63a16f5f61..d9c1aff058 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs
@@ -16,14 +16,7 @@ namespace System.Security.Cryptography
public SHA384Managed()
{
_hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA384);
- }
-
- public sealed override int HashSize
- {
- get
- {
- return _hashProvider.HashSizeInBytes * 8;
- }
+ HashSizeValue = _hashProvider.HashSizeInBytes * 8;
}
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize)
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs
index 34d321ff28..584dd0553c 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs
@@ -33,14 +33,7 @@ namespace System.Security.Cryptography
public Implementation()
{
_hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA512);
- }
-
- public sealed override int HashSize
- {
- get
- {
- return _hashProvider.HashSizeInBytes * 8;
- }
+ HashSizeValue = _hashProvider.HashSizeInBytes * 8;
}
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize)
diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs
index 6f5a7352f2..cd88bd422e 100644
--- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs
+++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs
@@ -16,14 +16,7 @@ namespace System.Security.Cryptography
public SHA512Managed()
{
_hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA512);
- }
-
- public sealed override int HashSize
- {
- get
- {
- return _hashProvider.HashSizeInBytes * 8;
- }
+ HashSizeValue = _hashProvider.HashSizeInBytes * 8;
}
protected sealed override void HashCore(byte[] array, int ibStart, int cbSize)
diff --git a/src/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs b/src/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs
index 896cff74b4..9b2f374147 100644
--- a/src/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs
+++ b/src/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs
@@ -5,6 +5,8 @@
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
+using System.Text;
+using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.CryptoConfigTests
@@ -234,6 +236,69 @@ namespace System.Security.Cryptography.CryptoConfigTests
Assert.Equal("Hello", ctorObj.MyString);
}
+ [Fact]
+ public static void EncodeOID_Validation()
+ {
+ Assert.Throws<ArgumentNullException>(() => CryptoConfig.EncodeOID(null));
+ Assert.Throws<FormatException>(() => CryptoConfig.EncodeOID(string.Empty));
+ Assert.Throws<FormatException>(() => CryptoConfig.EncodeOID("BAD.OID"));
+ Assert.Throws<FormatException>(() => CryptoConfig.EncodeOID("1.2.BAD.OID"));
+ Assert.Throws<OverflowException>(() => CryptoConfig.EncodeOID("1." + uint.MaxValue));
+ }
+
+ [Fact]
+ public static void EncodeOID_Compat()
+ {
+ string actual = CryptoConfig.EncodeOID("-1.2.-3").ByteArrayToHex();
+ Assert.Equal("0602DAFD", actual); // Negative values not checked
+ }
+
+ [Fact]
+ public static void EncodeOID_Length_Boundary()
+ {
+ string valueToRepeat = "1.1";
+
+ // Build a string like 1.11.11.11. ... .11.1, which has 0x80 separators.
+ // The BER/DER encoding of an OID has a minimum number of bytes as the number of separator characters,
+ // so this would produce an OID with a length segment of more than one byte, which EncodeOID can't handle.
+ string s = new StringBuilder(valueToRepeat.Length * 0x80).Insert(0, valueToRepeat, 0x80).ToString();
+ Assert.Throws<CryptographicUnexpectedOperationException>(() => CryptoConfig.EncodeOID(s));
+
+ // Try again with one less separator for the boundary case, but the particular output is really long
+ // and would just clutter up this test, so only verify it doesn't throw.
+ s = new StringBuilder(valueToRepeat.Length * 0x7f).Insert(0, valueToRepeat, 0x7f).ToString();
+ CryptoConfig.EncodeOID(s);
+ }
+
+ [Theory]
+ [InlineData(0x4000, "0603818028")]
+ [InlineData(0x200000, "060481808028")]
+ [InlineData(0x10000000, "06058180808028")]
+ [InlineData(0x10000001, "06058180808029")]
+ [InlineData(int.MaxValue, "060127")]
+ public static void EncodeOID_Value_Boundary_And_Compat(uint elementValue, string expectedEncoding)
+ {
+ // Boundary cases in EncodeOID; output may produce the wrong value mathematically due to encoding
+ // algorithm semantics but included here for compat reasons.
+ byte[] actual = CryptoConfig.EncodeOID("1." + elementValue.ToString());
+ byte[] expected = expectedEncoding.HexToByteArray();
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory]
+ [InlineData("SHA1", "1.3.14.3.2.26", "06052B0E03021A")]
+ [InlineData("DES", "1.3.14.3.2.7", "06052B0E030207")]
+ [InlineData("MD5", "1.2.840.113549.2.5", "06082A864886F70D0205")]
+ public static void MapAndEncodeOID(string alg, string expectedOid, string expectedEncoding)
+ {
+ string oid = CryptoConfig.MapNameToOID(alg);
+ Assert.Equal(expectedOid, oid);
+
+ byte[] actual = CryptoConfig.EncodeOID(oid);
+ byte[] expected = expectedEncoding.HexToByteArray();
+ Assert.Equal(expected, actual);
+ }
+
private static void VerifyCreateFromName<TExpected>(string name)
{
object obj = CryptoConfig.CreateFromName(name);
diff --git a/src/System.Security.Cryptography.Algorithms/tests/PaddingModeTests.cs b/src/System.Security.Cryptography.Algorithms/tests/PaddingModeTests.cs
new file mode 100644
index 0000000000..de0828de38
--- /dev/null
+++ b/src/System.Security.Cryptography.Algorithms/tests/PaddingModeTests.cs
@@ -0,0 +1,147 @@
+// 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.Collections.Generic;
+using System.IO;
+using System.Security.Cryptography;
+using Test.Cryptography;
+using Xunit;
+
+namespace System.Security.Cryptography.Tests
+{
+ public static class PaddingModeTests
+ {
+ [Theory]
+ [InlineData(PaddingMode.Zeros, 0, "", "")] // no block is added in this case!
+ [InlineData(PaddingMode.Zeros, 1, "46785BDE46622B92FF7C8EBB91508A", "1BE8AA365A15D11FC7826B3A10602D09" )]
+ [InlineData(PaddingMode.Zeros, 13, "E505A2", "0A2E62938B03E5822EE251117A4CE066")]
+ [InlineData(PaddingMode.PKCS7, 1, "46785BDE46622B92FF7C8EBB91508A", "DB5B7829CCE732BFE609140CF45A8843")]
+ [InlineData(PaddingMode.PKCS7, 13, "E505A2", "46785BDE46622B92FF7C8EBB91508A4D")]
+ [InlineData(PaddingMode.PKCS7, 16, "", "D5450767BCC31793FE5065251B96B715")]
+ [InlineData(PaddingMode.ANSIX923, 1, "46785BDE46622B92FF7C8EBB91508A", "DB5B7829CCE732BFE609140CF45A8843" )]
+ [InlineData(PaddingMode.ANSIX923, 13, "E505A2", "43B27D41A9FDE73CA5DB22C0FDA76CB1")]
+ [InlineData(PaddingMode.ANSIX923, 16, "", "A3D32A3A9DCA71B6F961F5A8ED7E414F")]
+ private static void ValidatePaddingMode_NonISO10126(PaddingMode paddingMode, int expectedPaddingSize, string plainTextStr, string expectedCipherStr)
+ {
+ Assert.True(paddingMode != PaddingMode.ISO10126, "This tests only non-ISO10126 padding");
+
+ byte[] key = "1ed2f625c187b993256a8b3ccf9dcbfa5b44b4795c731012f70e4e64732efd5d".HexToByteArray();
+ byte[] iv = "47d1e060ba3c8643f9f8b65feeda4b30".HexToByteArray();
+
+ byte[] plainText = plainTextStr.HexToByteArray();
+ byte[] expectedCipher = expectedCipherStr == null ? Array.Empty<byte>() : expectedCipherStr.HexToByteArray();
+
+ using (Aes a = Aes.Create())
+ {
+ a.Key = key;
+ a.IV = iv;
+ a.Mode = CipherMode.CBC;
+ a.Padding = paddingMode;
+
+ byte[] cipher = a.Encrypt(plainText);
+
+ Assert.Equal(expectedCipherStr, cipher.ByteArrayToHex());
+
+ // decrypt it with PaddingMode.None so that we can inspect the padding manually
+ a.Padding = PaddingMode.None;
+ byte[] decrypted = a.Decrypt(cipher);
+ ValidatePadding(decrypted, paddingMode, expectedPaddingSize);
+ }
+ }
+
+ [Theory]
+ [InlineData(1, "46785BDE46622B92FF7C8EBB91508A")]
+ [InlineData(13, "E505A2")]
+ [InlineData(16, "")]
+ private static void ValidatePaddingMode_ISO10126(int expectedPaddingSize, string plainTextStr)
+ {
+ byte[] key = "1ed2f625c187b993256a8b3ccf9dcbfa5b44b4795c731012f70e4e64732efd5d".HexToByteArray();
+ byte[] iv = "47d1e060ba3c8643f9f8b65feeda4b30".HexToByteArray();
+
+ byte[] plainText = plainTextStr.HexToByteArray();
+
+ using (Aes a = Aes.Create())
+ {
+ a.Key = key;
+ a.IV = iv;
+ a.Mode = CipherMode.CBC;
+ a.Padding = PaddingMode.ISO10126;
+
+ // for ISO10126 we are going to encrypt it twice and assert that the ciphers produced are going to be different
+ byte[] cipher = a.Encrypt(plainText);
+ byte[] secondCipher = a.Encrypt(plainText);
+
+ // decrypt it with PaddingMode.None so that we can inspect the padding manually
+ a.Padding = PaddingMode.None;
+ byte[] decrypted = a.Decrypt(cipher);
+
+ if (expectedPaddingSize >= 5)
+ {
+ byte[] secondDecrypted = a.Decrypt(secondCipher);
+
+ // after we decrypted, the two ciphers are going to be different
+ Assert.NotEqual(decrypted.ByteArrayToHex(), secondDecrypted.ByteArrayToHex());
+ }
+
+ ValidatePadding(decrypted, PaddingMode.ISO10126, expectedPaddingSize);
+ }
+ }
+
+ private static void ValidatePadding(byte[] buffer, PaddingMode paddingMode, int expectedPaddingSize)
+ {
+ switch (paddingMode)
+ {
+ case PaddingMode.PKCS7:
+ ValidatePKCS7Padding(buffer, expectedPaddingSize);
+ break;
+ case PaddingMode.ANSIX923:
+ ValidateANSIX923Padding(buffer, expectedPaddingSize);
+ break;
+ case PaddingMode.ISO10126:
+ ValidateISO10126Padding(buffer, expectedPaddingSize);
+ break;
+ case PaddingMode.Zeros:
+ ValidateZerosPadding(buffer, expectedPaddingSize);
+ break;
+ case PaddingMode.None:
+ break;
+ default:
+ break;
+ }
+ }
+
+ private static void ValidateZerosPadding(byte[] buffer, int expectedPaddingSize)
+ {
+ for (int i = buffer.Length - 1; i > buffer.Length - 1 - expectedPaddingSize; i--)
+ {
+ Assert.Equal(0, buffer[i]);
+ }
+ }
+
+ private static void ValidatePKCS7Padding(byte[] buffer, int expectedPaddingSize)
+ {
+ for (int i = buffer.Length - 1; i > buffer.Length - 1 - expectedPaddingSize; i--)
+ {
+ Assert.Equal(expectedPaddingSize, buffer[i]);
+ }
+ }
+
+ private static void ValidateANSIX923Padding(byte[] buffer, int expectedPaddingSize)
+ {
+ Assert.Equal(buffer[buffer.Length - 1], expectedPaddingSize);
+
+ for (int i = buffer.Length - expectedPaddingSize; i < buffer.Length - 1; i++)
+ {
+ Assert.Equal(0, buffer[i]);
+ }
+ }
+
+ private static void ValidateISO10126Padding(byte[] buffer, int expectedPaddingSize)
+ {
+ // there is nothing else to validate as all the other padding bytes are random.
+ Assert.Equal(buffer[buffer.Length - 1], expectedPaddingSize);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Security.Cryptography.Algorithms/tests/Rfc2898Tests.cs b/src/System.Security.Cryptography.Algorithms/tests/Rfc2898Tests.cs
index 0f8d51ad83..40458da2fe 100644
--- a/src/System.Security.Cryptography.Algorithms/tests/Rfc2898Tests.cs
+++ b/src/System.Security.Cryptography.Algorithms/tests/Rfc2898Tests.cs
@@ -271,6 +271,16 @@ namespace System.Security.Cryptography.DeriveBytesTests
});
}
+#if netstandard17
+ public static void CryptDeriveKey_NotSupported()
+ {
+ using (var deriveBytes = new Rfc2898DeriveBytes(TestPassword, s_testSalt))
+ {
+ Assert.Throws<PlatformNotSupportedException>(() => deriveBytes.CryptDeriveKey("RC2", "SHA1", 128, new byte[8]));
+ }
+ }
+#endif
+
private static void TestKnownValue(string password, byte[] salt, int iterationCount, byte[] expected)
{
byte[] output;
diff --git a/src/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj b/src/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj
index 8c46da0eca..e06e09f10f 100644
--- a/src/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj
+++ b/src/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj
@@ -132,6 +132,7 @@
<Compile Include="DESTests.cs" />
<Compile Include="DSASignatureFormatterTests.cs" />
<Compile Include="ECDiffieHellmanPublicKeyTests.cs" />
+ <Compile Include="PaddingModeTests.cs" />
<Compile Include="PKCS1MaskGenerationMethodTest.cs" />
<Compile Include="RC2Provider.cs" />
<Compile Include="RC2Tests.cs" />
diff --git a/src/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj b/src/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj
index 614bf7de71..b78c167933 100644
--- a/src/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj
+++ b/src/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj
@@ -11,14 +11,5 @@
<ProjectReference Include="..\..\System.Security.Cryptography.Algorithms\ref\System.Security.Cryptography.Algorithms.csproj" />
<ProjectReference Include="..\..\System.Security.Cryptography.Primitives\ref\System.Security.Cryptography.Primitives.csproj" />
</ItemGroup>
- <ItemGroup>
- <!-- ToDo: Remove once prerelease gets updated again -->
- <ProjectReference Include="..\..\System.Security.Cryptography.Primitives\ref\System.Security.Cryptography.Primitives.csproj">
- <Name>System.Security.Cryptography.Primitives</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\System.Security.Cryptography.Algorithms\ref\System.Security.Cryptography.Algorithms.csproj">
- <Name>System.Security.Cryptography.Algorithms</Name>
- </ProjectReference>
- </ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/System.Security.Cryptography.Cng/src/Internal/Cryptography/BasicSymmetricCipherNCrypt.cs b/src/System.Security.Cryptography.Cng/src/Internal/Cryptography/BasicSymmetricCipherNCrypt.cs
index 47b918684b..0a3d5a975a 100644
--- a/src/System.Security.Cryptography.Cng/src/Internal/Cryptography/BasicSymmetricCipherNCrypt.cs
+++ b/src/System.Security.Cryptography.Cng/src/Internal/Cryptography/BasicSymmetricCipherNCrypt.cs
@@ -140,7 +140,7 @@ namespace Internal.Cryptography
private CngKey _cngKey;
private readonly bool _encrypting;
- private readonly static CngProperty s_ECBMode = CreateCngPropertyForCipherMode(Interop.BCrypt.BCRYPT_CHAIN_MODE_ECB);
- private readonly static CngProperty s_CBCMode = CreateCngPropertyForCipherMode(Interop.BCrypt.BCRYPT_CHAIN_MODE_CBC);
+ private static readonly CngProperty s_ECBMode = CreateCngPropertyForCipherMode(Interop.BCrypt.BCRYPT_CHAIN_MODE_ECB);
+ private static readonly CngProperty s_CBCMode = CreateCngPropertyForCipherMode(Interop.BCrypt.BCRYPT_CHAIN_MODE_CBC);
}
}
diff --git a/src/System.Security.Cryptography.Cng/tests/DSACngTests.cs b/src/System.Security.Cryptography.Cng/tests/DSACngTests.cs
index c241d03804..55a50c6311 100644
--- a/src/System.Security.Cryptography.Cng/tests/DSACngTests.cs
+++ b/src/System.Security.Cryptography.Cng/tests/DSACngTests.cs
@@ -70,7 +70,7 @@ namespace System.Security.Cryptography.Dsa.Tests
}
}
- static internal bool SupportsFips186_3
+ internal static bool SupportsFips186_3
{
get
{
diff --git a/src/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs b/src/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs
index 125aeff550..f8eb8e997b 100644
--- a/src/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs
+++ b/src/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs
@@ -123,7 +123,6 @@ namespace System.Security.Cryptography
public sealed partial class MD5CryptoServiceProvider : System.Security.Cryptography.MD5
{
public MD5CryptoServiceProvider() { }
- public override int HashSize { get { throw null; } }
protected sealed override void Dispose(bool disposing) { }
protected override void HashCore(byte[] array, int ibStart, int cbSize) { }
protected override byte[] HashFinal() { throw null; }
@@ -135,6 +134,28 @@ namespace System.Security.Cryptography
Signature = 2,
}
[System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))]
+ public partial class PasswordDeriveBytes : System.Security.Cryptography.DeriveBytes
+ {
+ public PasswordDeriveBytes(byte[] password, byte[] salt) { }
+ public PasswordDeriveBytes(byte[] password, byte[] salt, System.Security.Cryptography.CspParameters cspParams) { }
+ public PasswordDeriveBytes(byte[] password, byte[] salt, string hashName, int iterations) { }
+ public PasswordDeriveBytes(byte[] password, byte[] salt, string hashName, int iterations, System.Security.Cryptography.CspParameters cspParams) { }
+ public PasswordDeriveBytes(string strPassword, byte[] rgbSalt) { }
+ public PasswordDeriveBytes(string strPassword, byte[] rgbSalt, System.Security.Cryptography.CspParameters cspParams) { }
+ public PasswordDeriveBytes(string strPassword, byte[] rgbSalt, string strHashName, int iterations) { }
+ public PasswordDeriveBytes(string strPassword, byte[] rgbSalt, string strHashName, int iterations, System.Security.Cryptography.CspParameters cspParams) { }
+ public string HashName { get { throw null; } set { } }
+ public int IterationCount { get { throw null; } set { } }
+ public byte[] Salt { get { throw null; } set { } }
+ public byte[] CryptDeriveKey(string algname, string alghashname, int keySize, byte[] rgbIV) { throw null; }
+ protected override void Dispose(bool disposing) { }
+ [System.ObsoleteAttribute("Rfc2898DeriveBytes replaces PasswordDeriveBytes for deriving key material from a password and is preferred in new applications.")]
+#pragma warning disable 0809
+ public override byte[] GetBytes(int cb) { throw null; }
+#pragma warning restore 0809
+ public override void Reset() { }
+ }
+ [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))]
public sealed partial class RC2CryptoServiceProvider : System.Security.Cryptography.RC2
{
public RC2CryptoServiceProvider() { }
@@ -194,7 +215,6 @@ namespace System.Security.Cryptography
public sealed partial class SHA1CryptoServiceProvider : System.Security.Cryptography.SHA1
{
public SHA1CryptoServiceProvider() { }
- public override int HashSize { get { throw null; } }
protected sealed override void Dispose(bool disposing) { }
protected override void HashCore(byte[] array, int ibStart, int cbSize) { }
protected override byte[] HashFinal() { throw null; }
diff --git a/src/System.Security.Cryptography.Csp/src/Resources/Strings.resx b/src/System.Security.Cryptography.Csp/src/Resources/Strings.resx
index 4de04d214f..e01bd74bd6 100644
--- a/src/System.Security.Cryptography.Csp/src/Resources/Strings.resx
+++ b/src/System.Security.Cryptography.Csp/src/Resources/Strings.resx
@@ -138,6 +138,9 @@
<data name="ArgumentOutOfRange_NeedNonNegNum" xml:space="preserve">
<value>Non-negative number required.</value>
</data>
+ <data name="ArgumentOutOfRange_NeedPosNum" xml:space="preserve">
+ <value>Positive number required.</value>
+ </data>
<data name="CryptDecrypt_Failed" xml:space="preserve">
<value>CryptDecrypt failed with error code </value>
</data>
@@ -228,6 +231,18 @@
<data name="Cryptography_PartialBlock" xml:space="preserve">
<value>The input data is not a complete block.</value>
</data>
+ <data name="Cryptography_PasswordDerivedBytes_InvalidAlgorithm" xml:space="preserve">
+ <value>Algorithm is unavailable or is not supported for this operation.</value>
+ </data>
+ <data name="Cryptography_PasswordDerivedBytes_InvalidIV" xml:space="preserve">
+ <value>The Initialization vector should have the same length as the algorithm block size in bytes.</value>
+ </data>
+ <data name="Cryptography_PasswordDerivedBytes_TooManyBytes" xml:space="preserve">
+ <value>Requested number of bytes exceeds the maximum.</value>
+ </data>
+ <data name="Cryptography_PasswordDerivedBytes_ValuesFixed" xml:space="preserve">
+ <value> Value of '{0}' cannot be changed after the bytes have been retrieved.</value>
+ </data>
<data name="Cryptography_RC2_EKSKS2" xml:space="preserve">
<value>EffectiveKeySize must be the same as KeySize in this implementation.</value>
</data>
diff --git a/src/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj b/src/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj
index bd0f6e13d9..c54f86d5ad 100644
--- a/src/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj
+++ b/src/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj
@@ -7,23 +7,25 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net463'">true</IsPartialFacadeAssembly>
<ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net463'">None</ResourcesSourceOutputDirectory>
+ <NoWarn Condition="'$(TargetsUnix)' == 'true'">CS0809</NoWarn>
<GeneratePlatformNotSupportedAssembly Condition="'$(TargetsUnix)' == 'true'">true</GeneratePlatformNotSupportedAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_NT_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_NT_Release|AnyCPU'" />
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard' AND '$(TargetsWindows)' == 'true'">
<Compile Include="System\Security\Cryptography\AesCryptoServiceProvider.cs" />
- <Compile Include="System\Security\Cryptography\CspProviderFlags.cs" />
- <Compile Include="System\Security\Cryptography\ICspAsymmetricAlgorithm.cs" />
- <Compile Include="System\Security\Cryptography\KeyNumber.cs" />
<Compile Include="System\Security\Cryptography\CapiHelper.cs" />
<Compile Include="System\Security\Cryptography\CapiHelper.DSA.cs" />
<Compile Include="System\Security\Cryptography\CapiHelper.SymmetricKey.cs" />
<Compile Include="System\Security\Cryptography\CspKeyContainerInfo.cs" />
<Compile Include="System\Security\Cryptography\CspParameters.cs" />
+ <Compile Include="System\Security\Cryptography\CspProviderFlags.cs" />
<Compile Include="System\Security\Cryptography\DESCryptoServiceProvider.cs" />
<Compile Include="System\Security\Cryptography\DSACryptoServiceProvider.cs" />
+ <Compile Include="System\Security\Cryptography\ICspAsymmetricAlgorithm.cs" />
+ <Compile Include="System\Security\Cryptography\KeyNumber.cs" />
<Compile Include="System\Security\Cryptography\MD5CryptoServiceProvider.cs" />
+ <Compile Include="System\Security\Cryptography\PasswordDeriveBytes.cs" />
<Compile Include="System\Security\Cryptography\RC2CryptoServiceProvider.cs" />
<Compile Include="System\Security\Cryptography\RNGCryptoServiceProvider.cs" />
<Compile Include="System\Security\Cryptography\RSACryptoServiceProvider.cs" />
diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.cs
index 53485c4cc2..edea0e6ecb 100644
--- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.cs
+++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/CapiHelper.cs
@@ -21,6 +21,21 @@ namespace Internal.NativeCrypto
/// </summary>
internal static partial class CapiHelper
{
+ private static readonly byte[] s_RgbPubKey =
+ {
+ 0x06, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
+ 0x52, 0x53, 0x41, 0x31, 0x00, 0x02, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xab, 0xef, 0xfa, 0xc6,
+ 0x7d, 0xe8, 0xde, 0xfb, 0x68, 0x38, 0x09, 0x92,
+ 0xd9, 0x42, 0x7e, 0x6b, 0x89, 0x9e, 0x21, 0xd7,
+ 0x52, 0x1c, 0x99, 0x3c, 0x17, 0x48, 0x4e, 0x3a,
+ 0x44, 0x02, 0xf2, 0xfa, 0x74, 0x57, 0xda, 0xe4,
+ 0xd3, 0xc0, 0x35, 0x67, 0xfa, 0x6e, 0xdf, 0x78,
+ 0x4c, 0x75, 0x35, 0x1c, 0xa0, 0x74, 0x49, 0xe3,
+ 0x20, 0x13, 0x71, 0x35, 0x65, 0xdf, 0x12, 0x20,
+ 0xf5, 0xf5, 0xf5, 0xc1
+ };
+
/// <summary>
/// Check to see if a better CSP than the one requested is available
/// RSA providers are supersets of each other in the following order:
@@ -1223,16 +1238,17 @@ namespace Internal.NativeCrypto
/// <summary>
/// Helper for signing and verifications that accept a string to specify a hashing algorithm.
/// </summary>
- public static int NameOrOidToHashAlgId(String nameOrOid)
+ public static int NameOrOidToHashAlgId(string nameOrOid, OidGroup oidGroup)
{
// Default Algorithm Id is CALG_SHA1
if (nameOrOid == null)
return CapiHelper.CALG_SHA1;
- String oidValue = new Oid(nameOrOid).Value;
+
+ string oidValue = CryptoConfig.MapNameToOID(nameOrOid);
if (oidValue == null)
oidValue = nameOrOid; // we were probably passed an OID value directly
- int algId = GetAlgIdFromOid(oidValue, OidGroup.HashAlgorithm);
+ int algId = GetAlgIdFromOid(oidValue, oidGroup);
if (algId == 0 || algId == -1)
throw new CryptographicException(SR.Cryptography_InvalidOID);
@@ -1250,7 +1266,7 @@ namespace Internal.NativeCrypto
String hashAlgString = hashAlg as String;
if (hashAlgString != null)
{
- int algId = NameOrOidToHashAlgId(hashAlgString);
+ int algId = NameOrOidToHashAlgId(hashAlgString, OidGroup.HashAlgorithm);
return algId;
}
else if (hashAlg is HashAlgorithm)
@@ -1346,7 +1362,7 @@ namespace Internal.NativeCrypto
}
else
{
- return global::Interop.Crypt32.FindOidInfo(CryptOidInfoKeyType.CRYPT_OID_INFO_OID_KEY, oid, OidGroup.HashAlgorithm, fallBackToAllGroups: false).AlgId;
+ return global::Interop.Crypt32.FindOidInfo(CryptOidInfoKeyType.CRYPT_OID_INFO_OID_KEY, oid, oidGroup, fallBackToAllGroups: false).AlgId;
}
}
@@ -1415,6 +1431,148 @@ namespace Internal.NativeCrypto
}
}
+ /// Helper method used by PasswordDeriveBytes.CryptDeriveKey to invoke CAPI CryptDeriveKey.
+ public static void DeriveKey(
+ SafeProvHandle hProv,
+ int algid,
+ int algidHash,
+ byte[] password,
+ int cbPassword,
+ int dwFlags,
+ byte[] IV_Out,
+ int cbIV_In,
+ ref byte[] pbKey)
+ {
+ VerifyValidHandle(hProv);
+
+ SafeHashHandle hHash = null;
+ SafeKeyHandle hKey = null;
+ try
+ {
+ if (!Interop.CryptCreateHash(hProv, algidHash, SafeKeyHandle.InvalidHandle, CryptCreateHashFlags.None, out hHash))
+ {
+ int hr = Marshal.GetHRForLastWin32Error();
+ throw hr.ToCryptographicException();
+ }
+
+ // Hash the password string
+ if (!Interop.CryptHashData(hHash, password, cbPassword, 0))
+ {
+ int hr = Marshal.GetHRForLastWin32Error();
+ throw hr.ToCryptographicException();
+ }
+
+ // Create a block cipher session key based on the hash of the password
+ if (!Interop.CryptDeriveKey(hProv, algid, hHash, dwFlags | (int)CryptGenKeyFlags.CRYPT_EXPORTABLE, out hKey))
+ {
+ int hr = Marshal.GetHRForLastWin32Error();
+ throw hr.ToCryptographicException();
+ }
+
+ // Get the key contents
+ byte[] rgbKey = null;
+ int cbKey = 0;
+ UnloadKey(hProv, hKey, ref rgbKey, ref cbKey);
+
+ // Get the length of the IV
+ int cbIV = 0;
+ if (!Interop.CryptGetKeyParam(hKey, (int)CryptGetKeyParamFlags.KP_IV, null, ref cbIV, 0))
+ {
+ int hr = Marshal.GetHRForLastWin32Error();
+ throw hr.ToCryptographicException();
+ }
+
+ // Now allocate space for the IV
+ byte[] pbIV = new byte[cbIV];
+ if (!Interop.CryptGetKeyParam(hKey, (int)CryptGetKeyParamFlags.KP_IV, pbIV, ref cbIV, 0))
+ {
+ int hr = Marshal.GetHRForLastWin32Error();
+ throw hr.ToCryptographicException();
+ }
+
+ if (cbIV != cbIV_In)
+ {
+ throw new CryptographicException(SR.Cryptography_PasswordDerivedBytes_InvalidIV);
+ }
+
+ // Copy the IV
+ Buffer.BlockCopy(pbIV, 0, IV_Out, 0, cbIV);
+
+ pbKey = new byte[cbKey];
+ Buffer.BlockCopy(rgbKey, 0, pbKey, 0, cbKey);
+ }
+ finally
+ {
+ hKey?.Dispose();
+ hHash?.Dispose();
+ }
+ }
+
+ // Helper method used by DeriveKey (above) to return the key contents.
+ // WARNING: This function side-effects its first argument (hProv)
+ private static void UnloadKey(SafeProvHandle hProv, SafeKeyHandle hKey, ref byte[] key_out, ref int cb_out)
+ {
+ SafeKeyHandle hPubKey = null;
+ try
+ {
+ // Import the public key
+ if (!Interop.CryptImportKey(hProv, s_RgbPubKey, s_RgbPubKey.Length, SafeKeyHandle.InvalidHandle, 0, out hPubKey))
+ {
+ int hr = Marshal.GetHRForLastWin32Error();
+ throw hr.ToCryptographicException();
+ }
+
+ // Determine length of hKey
+ int cbOut = 0;
+ if (!Interop.CryptExportKey(hKey, hPubKey, SIMPLEBLOB, 0, null, ref cbOut))
+ {
+ int hr = Marshal.GetHRForLastWin32Error();
+ throw hr.ToCryptographicException();
+ }
+
+ // Export hKey
+ byte[] key_full = new byte[cbOut];
+ if (!Interop.CryptExportKey(hKey, hPubKey, SIMPLEBLOB, 0, key_full, ref cbOut))
+ {
+ int hr = Marshal.GetHRForLastWin32Error();
+ throw hr.ToCryptographicException();
+ }
+
+ // Get size of the key without the header parts
+ int sizeOfBlobHeader = sizeof(byte) + sizeof(byte) + sizeof(ushort) + sizeof(int);
+ // The format of BLOBHEADER:
+ // BYTE bType
+ // BYTE bVersion
+ // WORD reserved
+ // ALG_ID aiKeyAlg
+ int offsetPastHeader = sizeOfBlobHeader + sizeof(int);
+ int i;
+ checked
+ {
+ i = cbOut - sizeOfBlobHeader - sizeof(int) - 2;
+ }
+ while (i > 0)
+ {
+ if (key_full[i + offsetPastHeader] == 0)
+ {
+ break;
+ }
+
+ i--;
+ }
+
+ // Allocate and initialize the return buffer
+ key_out = new byte[i];
+ Buffer.BlockCopy(key_full, offsetPastHeader, key_out, 0, i);
+ Array.Reverse(key_out);
+ cb_out = i;
+ }
+ finally
+ {
+ hPubKey?.Dispose();
+ }
+ }
+
/// <summary>
/// Create a CAPI-1 hash handle that contains the specified bits as its hash value.
/// </summary>
@@ -1546,6 +1704,10 @@ namespace Internal.NativeCrypto
bool Final, int dwFlags, byte[] pbData, ref int pdwDataLen,
int dwBufLen);
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CryptDeriveKey")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool _CryptDeriveKey(SafeProvHandle safeProvHandle, int algId, SafeHashHandle phHash, int dwFlags, out SafeKeyHandle phKey);
+
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptExportKey(SafeKeyHandle hKey, SafeKeyHandle hExpKey, int dwBlobType,
@@ -1561,6 +1723,10 @@ namespace Internal.NativeCrypto
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool CryptHashData(SafeHashHandle hHash, byte[] pbData, int dwDataLen, int dwFlags);
+
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetHashParam(SafeHashHandle hHash, CryptHashProperty dwParam, out int pbData, [In, Out] ref int pdwDataLen, int dwFlags);
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
@@ -1636,6 +1802,20 @@ namespace Internal.NativeCrypto
return response;
}
+
+ public static bool CryptDeriveKey(
+ SafeProvHandle hProv,
+ int algId,
+ SafeHashHandle phHash,
+ int dwFlags,
+ out SafeKeyHandle phKey)
+ {
+ bool response = _CryptDeriveKey(hProv, algId, phHash, dwFlags, out phKey);
+
+ phKey.SetParent(hProv);
+
+ return response;
+ }
}
} //End CapiHelper : Pinvokes
@@ -1676,6 +1856,7 @@ namespace Internal.NativeCrypto
internal const string OID_OIWSEC_SHA384 = "2.16.840.1.101.3.4.2.2";
internal const string OID_OIWSEC_SHA512 = "2.16.840.1.101.3.4.2.3";
+ internal const int SIMPLEBLOB = 0x1;
internal const int PUBLICKEYBLOB = 0x6;
internal const int PRIVATEKEYBLOB = 0x7;
internal const int PLAINTEXTKEYBLOB = 0x8;
@@ -1711,7 +1892,8 @@ namespace Internal.NativeCrypto
internal enum CryptGetKeyParamFlags : int
{
CRYPT_EXPORT = 0x0004,
- KP_PERMISSIONS = 6
+ KP_IV = 1,
+ KP_PERMISSIONS = 6,
}
internal enum CryptGetProvParam : int
diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.cs
index 73723cc0d7..16de657286 100644
--- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.cs
+++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.cs
@@ -441,7 +441,7 @@ namespace System.Security.Cryptography
if (PublicOnly)
throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
- int calgHash = CapiHelper.NameOrOidToHashAlgId(str);
+ int calgHash = CapiHelper.NameOrOidToHashAlgId(str, OidGroup.HashAlgorithm);
if (rgbHash.Length != _sha1.HashSize / 8)
throw new CryptographicException(string.Format(SR.Cryptography_InvalidHashSize, "SHA1", _sha1.HashSize / 8));
@@ -469,7 +469,7 @@ namespace System.Security.Cryptography
if (rgbSignature == null)
throw new ArgumentNullException(nameof(rgbSignature));
- int calgHash = CapiHelper.NameOrOidToHashAlgId(str);
+ int calgHash = CapiHelper.NameOrOidToHashAlgId(str, OidGroup.HashAlgorithm);
return CapiHelper.VerifySign(
SafeProvHandle,
diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs
index dbd6dbc1fc..5ef0139508 100644
--- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs
+++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs
@@ -15,6 +15,7 @@ namespace System.Security.Cryptography
public MD5CryptoServiceProvider()
{
_incrementalHash = IncrementalHash.CreateHash(HashAlgorithmName.MD5);
+ HashSizeValue = HashSizeBits;
}
public override void Initialize()
@@ -33,8 +34,7 @@ namespace System.Security.Cryptography
return _incrementalHash.GetHashAndReset();
}
- // The Hash property is not overridden since the correct value exists on base.
- public override int HashSize => HashSizeBits;
+ // The Hash and HashSize properties are not overridden since the correct values are returned from base.
protected sealed override void Dispose(bool disposing)
{
diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs
new file mode 100644
index 0000000000..c9c9e9c989
--- /dev/null
+++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs
@@ -0,0 +1,327 @@
+// 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 Internal.NativeCrypto;
+using System.ComponentModel;
+using System.IO;
+using System.Text;
+
+namespace System.Security.Cryptography
+{
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class PasswordDeriveBytes : DeriveBytes
+ {
+ private int _extraCount;
+ private int _prefix;
+ private int _iterations;
+ private byte[] _baseValue;
+ private byte[] _extra;
+ private byte[] _salt;
+ private byte[] _password;
+ private string _hashName;
+ private HashAlgorithm _hash;
+ private CspParameters _cspParams;
+ private SafeProvHandle _safeProvHandle = null;
+
+ public PasswordDeriveBytes(string strPassword, byte[] rgbSalt) : this(strPassword, rgbSalt, new CspParameters()) { }
+
+ public PasswordDeriveBytes(byte[] password, byte[] salt) : this(password, salt, new CspParameters()) { }
+
+ public PasswordDeriveBytes(string strPassword, byte[] rgbSalt, string strHashName, int iterations) :
+ this(strPassword, rgbSalt, strHashName, iterations, new CspParameters()) { }
+
+ public PasswordDeriveBytes(byte[] password, byte[] salt, string hashName, int iterations) :
+ this(password, salt, hashName, iterations, new CspParameters()) { }
+
+ public PasswordDeriveBytes(string strPassword, byte[] rgbSalt, CspParameters cspParams) :
+ this(strPassword, rgbSalt, "SHA1", 100, cspParams) { }
+
+ public PasswordDeriveBytes(byte[] password, byte[] salt, CspParameters cspParams) :
+ this(password, salt, "SHA1", 100, cspParams) { }
+
+ public PasswordDeriveBytes(string strPassword, byte[] rgbSalt, string strHashName, int iterations, CspParameters cspParams) :
+ this((new UTF8Encoding(false)).GetBytes(strPassword), rgbSalt, strHashName, iterations, cspParams) { }
+
+ public PasswordDeriveBytes(byte[] password, byte[] salt, string hashName, int iterations, CspParameters cspParams)
+ {
+ IterationCount = iterations;
+ Salt = salt;
+ HashName = hashName;
+ _password = password;
+ _cspParams = cspParams;
+ }
+
+ public string HashName
+ {
+ get { return _hashName; }
+ set
+ {
+ if (_baseValue != null)
+ throw new CryptographicException(SR.Cryptography_PasswordDerivedBytes_ValuesFixed, nameof(HashName));
+
+ _hashName = value;
+ _hash = (HashAlgorithm)CryptoConfig.CreateFromName(_hashName);
+ }
+ }
+
+ public int IterationCount
+ {
+ get { return _iterations; }
+ set
+ {
+ if (value <= 0)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_NeedPosNum);
+ if (_baseValue != null)
+ throw new CryptographicException(SR.Cryptography_PasswordDerivedBytes_ValuesFixed, nameof(IterationCount));
+
+ _iterations = value;
+ }
+ }
+
+ public byte[] Salt
+ {
+ get
+ {
+ return (byte[])_salt?.Clone();
+ }
+ set
+ {
+ if (_baseValue != null)
+ throw new CryptographicException(SR.Cryptography_PasswordDerivedBytes_ValuesFixed, nameof(Salt));
+
+ _salt = (byte[])value?.Clone();
+ }
+ }
+
+ [Obsolete("Rfc2898DeriveBytes replaces PasswordDeriveBytes for deriving key material from a password and is preferred in new applications.")]
+#pragma warning disable 0809 // obsolete member overrides non-obsolete member
+ public override byte[] GetBytes(int cb)
+ {
+ int ib = 0;
+ byte[] rgb;
+ byte[] rgbOut = new byte[cb];
+
+ if (_baseValue == null)
+ {
+ ComputeBaseValue();
+ }
+ else if (_extra != null)
+ {
+ ib = _extra.Length - _extraCount;
+ if (ib >= cb)
+ {
+ Buffer.BlockCopy(_extra, _extraCount, rgbOut, 0, cb);
+
+ if (ib > cb)
+ {
+ _extraCount += cb;
+ }
+ else
+ {
+ _extra = null;
+ }
+
+ return rgbOut;
+ }
+ else
+ {
+ // Note: The second parameter should really be _extraCount instead.
+ // However, changing this would constitute a breaking change.
+ Buffer.BlockCopy(_extra, ib, rgbOut, 0, ib);
+ _extra = null;
+ }
+ }
+
+ rgb = ComputeBytes(cb - ib);
+ Buffer.BlockCopy(rgb, 0, rgbOut, ib, cb - ib);
+ if (rgb.Length + ib > cb)
+ {
+ _extra = rgb;
+ _extraCount = cb - ib;
+ }
+ return rgbOut;
+ }
+#pragma warning restore 0809
+
+ public override void Reset()
+ {
+ _prefix = 0;
+ _extra = null;
+ _baseValue = null;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (disposing)
+ {
+ _hash?.Dispose();
+
+ if (_baseValue != null)
+ {
+ Array.Clear(_baseValue, 0, _baseValue.Length);
+ }
+
+ if (_extra != null)
+ {
+ Array.Clear(_extra, 0, _extra.Length);
+ }
+
+ if (_password != null)
+ {
+ Array.Clear(_password, 0, _password.Length);
+ }
+
+ if (_salt != null)
+ {
+ Array.Clear(_salt, 0, _salt.Length);
+ }
+ }
+ }
+
+ public byte[] CryptDeriveKey(string algname, string alghashname, int keySize, byte[] rgbIV)
+ {
+ if (keySize < 0)
+ throw new CryptographicException(SR.Cryptography_InvalidKeySize);
+
+ int algidhash = CapiHelper.NameOrOidToHashAlgId(alghashname, OidGroup.HashAlgorithm);
+ if (algidhash == 0)
+ throw new CryptographicException(SR.Cryptography_PasswordDerivedBytes_InvalidAlgorithm);
+
+ int algid = CapiHelper.NameOrOidToHashAlgId(algname, OidGroup.All);
+ if (algid == 0)
+ throw new CryptographicException(SR.Cryptography_PasswordDerivedBytes_InvalidAlgorithm);
+
+ if (rgbIV == null)
+ throw new CryptographicException(SR.Cryptography_PasswordDerivedBytes_InvalidIV);
+
+ byte[] key = null;
+ CapiHelper.DeriveKey(ProvHandle, algid, algidhash, _password, _password.Length, keySize << 16, rgbIV, rgbIV.Length, ref key);
+ return key;
+ }
+
+ private SafeProvHandle ProvHandle
+ {
+ get
+ {
+ if (_safeProvHandle == null)
+ {
+ lock (this)
+ {
+ if (_safeProvHandle == null)
+ {
+ SafeProvHandle safeProvHandle = AcquireSafeProviderHandle(_cspParams);
+ System.Threading.Thread.MemoryBarrier();
+ _safeProvHandle = safeProvHandle;
+ }
+ }
+ }
+ return _safeProvHandle;
+ }
+ }
+
+ private static SafeProvHandle AcquireSafeProviderHandle(CspParameters cspParams)
+ {
+ if (cspParams == null)
+ {
+ cspParams = new CspParameters(CapiHelper.DefaultRsaProviderType);
+ }
+
+ SafeProvHandle safeProvHandle = null;
+ CapiHelper.AcquireCsp(cspParams, out safeProvHandle);
+ return safeProvHandle;
+ }
+
+ private byte[] ComputeBaseValue()
+ {
+ _hash.Initialize();
+ _hash.TransformBlock(_password, 0, _password.Length, _password, 0);
+
+ if (_salt != null)
+ {
+ _hash.TransformBlock(_salt, 0, _salt.Length, _salt, 0);
+ }
+
+ _hash.TransformFinalBlock(Array.Empty<Byte>(), 0, 0);
+ _baseValue = _hash.Hash;
+ _hash.Initialize();
+
+ for (int i = 1; i < (_iterations - 1); i++)
+ {
+ _hash.ComputeHash(_baseValue);
+ _baseValue = _hash.Hash;
+ }
+
+ return _baseValue;
+ }
+
+ private byte[] ComputeBytes(int cb)
+ {
+ int cbHash;
+ int ib = 0;
+ byte[] rgb;
+
+ _hash.Initialize();
+ cbHash = _hash.HashSize / 8;
+ rgb = new byte[((cb + cbHash - 1) / cbHash) * cbHash];
+
+ using (CryptoStream cs = new CryptoStream(Stream.Null, _hash, CryptoStreamMode.Write))
+ {
+ HashPrefix(cs);
+ cs.Write(_baseValue, 0, _baseValue.Length);
+ cs.Close();
+ }
+
+ Buffer.BlockCopy(_hash.Hash, 0, rgb, ib, cbHash);
+ ib += cbHash;
+
+ while (cb > ib)
+ {
+ _hash.Initialize();
+ using (CryptoStream cs = new CryptoStream(Stream.Null, _hash, CryptoStreamMode.Write))
+ {
+ HashPrefix(cs);
+ cs.Write(_baseValue, 0, _baseValue.Length);
+ cs.Close();
+ }
+
+ Buffer.BlockCopy(_hash.Hash, 0, rgb, ib, cbHash);
+ ib += cbHash;
+ }
+
+ return rgb;
+ }
+
+ private void HashPrefix(CryptoStream cs)
+ {
+ if (_prefix > 999)
+ throw new CryptographicException(SR.Cryptography_PasswordDerivedBytes_TooManyBytes);
+
+ int cb = 0;
+ byte[] rgb = { (byte)'0', (byte)'0', (byte)'0' };
+
+ if (_prefix >= 100)
+ {
+ rgb[0] += (byte)(_prefix / 100);
+ cb += 1;
+ }
+
+ if (_prefix >= 10)
+ {
+ rgb[cb] += (byte)((_prefix % 100) / 10);
+ cb += 1;
+ }
+
+ if (_prefix > 0)
+ {
+ rgb[cb] += (byte)(_prefix % 10);
+ cb += 1;
+ cs.Write(rgb, 0, cb);
+ }
+
+ _prefix += 1;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.cs
index ef3d99ad34..b99e853b0b 100644
--- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.cs
+++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RSACryptoServiceProvider.cs
@@ -439,7 +439,7 @@ namespace System.Security.Cryptography
if (PublicOnly)
throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
- int calgHash = CapiHelper.NameOrOidToHashAlgId(str);
+ int calgHash = CapiHelper.NameOrOidToHashAlgId(str, OidGroup.HashAlgorithm);
return SignHash(rgbHash, calgHash);
}
@@ -485,7 +485,7 @@ namespace System.Security.Cryptography
if (rgbSignature == null)
throw new ArgumentNullException(nameof(rgbSignature));
- int calgHash = CapiHelper.NameOrOidToHashAlgId(str);
+ int calgHash = CapiHelper.NameOrOidToHashAlgId(str, OidGroup.HashAlgorithm);
return VerifyHash(rgbHash, calgHash, rgbSignature);
}
diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs
index 4b185e9fdc..8ad5bee4ec 100644
--- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs
+++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs
@@ -15,6 +15,7 @@ namespace System.Security.Cryptography
public SHA1CryptoServiceProvider()
{
_incrementalHash = IncrementalHash.CreateHash(HashAlgorithmName.SHA1);
+ HashSizeValue = HashSizeBits;
}
public override void Initialize()
@@ -33,8 +34,7 @@ namespace System.Security.Cryptography
return _incrementalHash.GetHashAndReset();
}
- // The Hash property is not overridden since the correct value exists on base.
- public override int HashSize => HashSizeBits;
+ // The Hash and HashSize properties are not overridden since the correct values are returned from base.
protected sealed override void Dispose(bool disposing)
{
diff --git a/src/System.Security.Cryptography.Csp/tests/PasswordDeriveBytesTests.cs b/src/System.Security.Cryptography.Csp/tests/PasswordDeriveBytesTests.cs
new file mode 100644
index 0000000000..cb3dc8ce1f
--- /dev/null
+++ b/src/System.Security.Cryptography.Csp/tests/PasswordDeriveBytesTests.cs
@@ -0,0 +1,552 @@
+// 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 Test.Cryptography;
+using Xunit;
+
+namespace System.Security.Cryptography.DeriveBytesTests
+{
+ public class PasswordDeriveBytesTests
+ {
+ // Note some tests were copied from Rfc2898DeriveBytes (and modified accordingly).
+
+ private static readonly byte[] s_testSalt = new byte[] { 9, 5, 5, 5, 1, 2, 1, 2 };
+ private static readonly byte[] s_testSaltB = new byte[] { 0, 4, 0, 4, 1, 9, 7, 5 };
+ private const string TestPassword = "PasswordGoesHere";
+ private const string TestPasswordB = "FakePasswordsAreHard";
+ private const int DefaultIterationCount = 100;
+
+ [Fact]
+ public static void Ctor_NullPasswordBytes()
+ {
+ using (var pdb = new PasswordDeriveBytes((byte[])null, s_testSalt))
+ {
+ Assert.Equal(DefaultIterationCount, pdb.IterationCount);
+ Assert.Equal(s_testSalt, pdb.Salt);
+ Assert.Equal("SHA1", pdb.HashName);
+ }
+ }
+
+ [Fact]
+ public static void Ctor_NullPasswordString()
+ {
+ Assert.Throws<ArgumentNullException>(() => new PasswordDeriveBytes((string)null, s_testSalt));
+ }
+
+ [Fact]
+ public static void Ctor_NullSalt()
+ {
+ using (var pdb = new PasswordDeriveBytes(TestPassword, null))
+ {
+ Assert.Equal(DefaultIterationCount, pdb.IterationCount);
+ Assert.Equal(null, pdb.Salt);
+ Assert.Equal("SHA1", pdb.HashName);
+ }
+ }
+
+ [Fact]
+ public static void Ctor_EmptySalt()
+ {
+ using (var pdb = new PasswordDeriveBytes(TestPassword, Array.Empty<byte>()))
+ {
+ Assert.Equal(DefaultIterationCount, pdb.IterationCount);
+ Assert.Equal(Array.Empty<byte>(), pdb.Salt);
+ Assert.Equal("SHA1", pdb.HashName);
+ }
+ }
+
+ [Fact]
+ public static void Ctor_DiminishedSalt()
+ {
+ using (var pdb = new PasswordDeriveBytes(TestPassword, new byte[7]))
+ {
+ Assert.Equal(DefaultIterationCount, pdb.IterationCount);
+ Assert.Equal(7, pdb.Salt.Length);
+ Assert.Equal("SHA1", pdb.HashName);
+ }
+ }
+
+ [Fact]
+ public static void Ctor_TooFewIterations()
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => new PasswordDeriveBytes(TestPassword, s_testSalt, "SHA1", 0));
+ }
+
+ [Fact]
+ public static void Ctor_NegativeIterations()
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => new PasswordDeriveBytes(TestPassword, s_testSalt, "SHA1", -1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => new PasswordDeriveBytes(TestPassword, s_testSalt, "SHA1", int.MinValue));
+ Assert.Throws<ArgumentOutOfRangeException>(() => new PasswordDeriveBytes(TestPassword, s_testSalt, "SHA1", int.MinValue / 2));
+ }
+
+ [Fact]
+ public static void Ctor_DefaultIterations()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ Assert.Equal(DefaultIterationCount, deriveBytes.IterationCount);
+ }
+ }
+
+ [Fact]
+ public static void Ctor_IterationsRespected()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt, "SHA1", 1))
+ {
+ Assert.Equal(1, deriveBytes.IterationCount);
+ }
+ }
+
+ [Fact]
+ public static void Ctor_CspParameters()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt, new CspParameters())) { }
+ using (var deriveBytes = new PasswordDeriveBytes(string.Empty, s_testSalt, new CspParameters())) { }
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt, "SHA1", 100, new CspParameters())) { }
+ using (var deriveBytes = new PasswordDeriveBytes(string.Empty, s_testSalt, "SHA1", 100, new CspParameters())) { }
+ }
+
+ [Fact]
+ public static void Ctor_CspParameters_Null()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt, null)) { }
+ using (var deriveBytes = new PasswordDeriveBytes(string.Empty, s_testSalt, null)) { }
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt, "SHA1", 100, null)) { }
+ using (var deriveBytes = new PasswordDeriveBytes(string.Empty, s_testSalt, "SHA1", 100, null)) { }
+ }
+
+ [Fact]
+ public static void Ctor_SaltCopied()
+ {
+ byte[] saltIn = (byte[])s_testSalt.Clone();
+
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, saltIn, "SHA1", DefaultIterationCount))
+ {
+ byte[] saltOut = deriveBytes.Salt;
+
+ Assert.NotSame(saltIn, saltOut);
+ Assert.Equal(saltIn, saltOut);
+
+ // Right now we know that at least one of the constructor and get_Salt made a copy, if it was
+ // only get_Salt then this next part would fail.
+
+ saltIn[0] = (byte)~saltIn[0];
+
+ // Have to read the property again to prove it's detached.
+ Assert.NotEqual(saltIn, deriveBytes.Salt);
+ }
+ }
+
+ [Fact]
+ public static void GetSaltCopies()
+ {
+ byte[] first;
+ byte[] second;
+
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt, "SHA1", DefaultIterationCount))
+ {
+ first = deriveBytes.Salt;
+ second = deriveBytes.Salt;
+ }
+
+ Assert.NotSame(first, second);
+ Assert.Equal(first, second);
+ }
+
+ [Fact]
+ public static void SetSaltAfterGetBytes_Throws()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ deriveBytes.GetBytes(1);
+ Assert.Throws<CryptographicException>(() => deriveBytes.Salt = s_testSalt);
+ }
+ }
+
+ [Fact]
+ public static void SetSaltAfterGetBytes_Reset()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ deriveBytes.GetBytes(1);
+ deriveBytes.Reset();
+ deriveBytes.Salt = s_testSaltB;
+ Assert.Equal(s_testSaltB, deriveBytes.Salt);
+ }
+ }
+
+ [Fact]
+ public static void MinimumAcceptableInputs()
+ {
+ byte[] output;
+
+ using (var deriveBytes = new PasswordDeriveBytes(string.Empty, new byte[8], "SHA1", 1))
+ {
+ output = deriveBytes.GetBytes(1);
+ }
+
+ Assert.Equal(1, output.Length);
+ Assert.Equal(0xF8, output[0]);
+ }
+
+ [Fact]
+ public static void GetBytes_ZeroLength()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ Assert.Throws<ArgumentException>(() => deriveBytes.GetBytes(0));
+ }
+ }
+
+ [Fact]
+ public static void GetBytes_NegativeLength()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ Assert.Throws<OverflowException>(() => deriveBytes.GetBytes(-1));
+ Assert.Throws<OverflowException>(() => deriveBytes.GetBytes(int.MinValue));
+ Assert.Throws<OverflowException>(() => deriveBytes.GetBytes(int.MinValue / 2));
+ }
+ }
+
+ [Fact]
+ public static void GetBytes_NotIdempotent()
+ {
+ byte[] first;
+ byte[] second;
+
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ first = deriveBytes.GetBytes(32);
+ second = deriveBytes.GetBytes(32);
+ }
+
+ Assert.NotEqual(first, second);
+ }
+
+ [Fact]
+ public static void GetBytes_StableIfReset()
+ {
+ byte[] first;
+ byte[] second;
+
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ first = deriveBytes.GetBytes(32);
+ deriveBytes.Reset();
+ second = deriveBytes.GetBytes(32);
+ }
+
+ Assert.Equal(first, second);
+ }
+
+ [Fact]
+ public static void GetBytes_StreamLike_ExtraBytes()
+ {
+ byte[] first;
+
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ // SHA1 default
+ Assert.Equal("SHA1", deriveBytes.HashName);
+
+ // Request double of SHA1 hash size
+ first = deriveBytes.GetBytes(40);
+ }
+
+ byte[] second = new byte[first.Length];
+
+ // Reset
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ // Make two passes over the hash
+ byte[] secondFirstHalf = deriveBytes.GetBytes(first.Length / 2);
+ // Since we requested 20 bytes there are no 'extra' bytes left over to cause the "_extraCount" bug
+ // in GetBytes(); that issue is tested in GetBytes_StreamLike_Bug_Compat.
+
+ // Request 20 'extra' bytes in one call
+ byte[] secondSecondHalf = deriveBytes.GetBytes(first.Length - secondFirstHalf.Length);
+
+ Buffer.BlockCopy(secondFirstHalf, 0, second, 0, secondFirstHalf.Length);
+ Buffer.BlockCopy(secondSecondHalf, 0, second, secondFirstHalf.Length, secondSecondHalf.Length);
+ }
+
+ Assert.Equal(first, second);
+ }
+
+ [Fact]
+ public static void GetBytes_StreamLike_Bug_Compat()
+ {
+ byte[] first;
+
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ Assert.Equal("SHA1", deriveBytes.HashName);
+
+ // Request 20 bytes (SHA1 hash size) plus 12 extra bytes
+ first = deriveBytes.GetBytes(32);
+ }
+
+ byte[] second = new byte[first.Length];
+
+ // Reset
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ // Ask for half now (16 bytes)
+ byte[] firstHalf = deriveBytes.GetBytes(first.Length / 2);
+
+ // Ask for the other half now (16 bytes)
+ byte[] lastHalf = deriveBytes.GetBytes(first.Length - firstHalf.Length);
+
+ // lastHalf should contain the last 4 bytes from the SHA1 hash plus 12 extra bytes
+ // but due to the _extraCount bug it doesn't.
+
+ // Merge the two buffers into the second array
+ Buffer.BlockCopy(firstHalf, 0, second, 0, firstHalf.Length);
+ Buffer.BlockCopy(lastHalf, 0, second, firstHalf.Length, lastHalf.Length);
+ }
+
+ // Fails due to _extraCount bug (the bug is fixed in Rfc2898DeriveBytes)
+ Assert.NotEqual(first, second);
+
+ // However, the first 16 bytes will be equal because the _extraCount bug does
+ // not affect the first call, only the subsequent GetBytes() call.
+ byte[] first_firstHalf = new byte[first.Length / 2];
+ byte[] second_firstHalf = new byte[first.Length / 2];
+ Buffer.BlockCopy(first, 0, first_firstHalf, 0, first_firstHalf.Length);
+ Buffer.BlockCopy(second, 0, second_firstHalf, 0, second_firstHalf.Length);
+ Assert.Equal(first_firstHalf, second_firstHalf);
+ }
+
+ [Fact]
+ public static void GetBytes_Boundary()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ // Boundary case success
+ deriveBytes.GetBytes(1000 * 20);
+
+ // Boundary case failure
+ Assert.Throws<CryptographicException>(() => deriveBytes.GetBytes(1));
+ }
+ }
+
+ [Fact]
+ public static void GetBytes_KnownValues_MD5_32()
+ {
+ TestKnownValue_GetBytes(
+ HashAlgorithmName.MD5,
+ TestPassword,
+ s_testSalt,
+ DefaultIterationCount,
+ ByteUtils.HexToByteArray("F8D88E9DAFC828DA2400F5144271C2F630A1C061C654FC9DE2E7900E121461B9"));
+ }
+
+ [Fact]
+ public static void GetBytes_KnownValues_SHA256_40()
+ {
+ TestKnownValue_GetBytes(
+ HashAlgorithmName.SHA256,
+ TestPassword,
+ s_testSalt,
+ DefaultIterationCount,
+ ByteUtils.HexToByteArray("3774A17468276057717A90C25B72915921D8F8C046F7868868DBB99BB4C4031CADE9E26BE77BEA39"));
+ }
+
+ [Fact]
+ public static void GetBytes_KnownValues_SHA1_40()
+ {
+ TestKnownValue_GetBytes(
+ HashAlgorithmName.SHA1,
+ TestPassword,
+ s_testSalt,
+ DefaultIterationCount,
+ ByteUtils.HexToByteArray("12F2497EC3EB78B0EA32AABFD8B9515FBC800BEEB6316A4DDF4EA62518341488A116DA3BBC26C685"));
+ }
+
+ [Fact]
+ public static void GetBytes_KnownValues_SHA1_40_2()
+ {
+ TestKnownValue_GetBytes(
+ HashAlgorithmName.SHA1,
+ TestPassword,
+ s_testSalt,
+ DefaultIterationCount + 1,
+ ByteUtils.HexToByteArray("FB6199E4D9BB017D2F3AF6964F3299971607C6B984934A9E43140631957429160C33A6630EF12E31"));
+ }
+
+ [Fact]
+ public static void GetBytes_KnownValues_SHA1_40_3()
+ {
+ TestKnownValue_GetBytes(
+ HashAlgorithmName.SHA1,
+ TestPassword,
+ s_testSaltB,
+ DefaultIterationCount,
+ ByteUtils.HexToByteArray("DCA4851AB3C9960CF387E64DE7A1B2E09616BEA6A4666AAFAC31F1670F23530E38BD4BF4D9248A08"));
+ }
+
+ [Fact]
+ public static void GetBytes_KnownValues_SHA1_40_4()
+ {
+ TestKnownValue_GetBytes(
+ HashAlgorithmName.SHA1,
+ TestPasswordB,
+ s_testSalt,
+ DefaultIterationCount,
+ ByteUtils.HexToByteArray("1DCA2A3405E93D9E3F7CD10653444F2FD93F5BE32C4B1BEDDF94D0D67461CBE86B5BDFEB32071E96"));
+ }
+
+ [Fact]
+ public static void CryptDeriveKey_KnownValues_TripleDes()
+ {
+ byte[] key = TestKnownValue_CryptDeriveKey(
+ HashAlgorithmName.SHA1,
+ TestPassword,
+ "TripleDES",
+ 192,
+ s_testSalt,
+ ByteUtils.HexToByteArray("97628A641949D99DCED35DB0ABCE20F21FF4DA9B46E00BCE"));
+
+ // Verify key is valid
+ using (var alg = new TripleDESCryptoServiceProvider())
+ {
+ alg.Key = key;
+ alg.IV = new byte[8];
+ alg.Padding = PaddingMode.None;
+ alg.Mode = CipherMode.CBC;
+
+ byte[] plainText = "79a86903608e133e020e1dc68c9835250c2f17b0ebeed91b".HexToByteArray();
+ byte[] cipher = alg.Encrypt(plainText);
+ byte[] expectedCipher = "9DC863445642B88AC46B3B107CB5A0ACC1596A176962EE8F".HexToByteArray();
+ Assert.Equal<byte>(expectedCipher, cipher);
+
+ byte[] decrypted = alg.Decrypt(cipher);
+ byte[] expectedDecrypted = "79a86903608e133e020e1dc68c9835250c2f17b0ebeed91b".HexToByteArray();
+ Assert.Equal<byte>(expectedDecrypted, decrypted);
+ }
+ }
+
+ [Fact]
+ public static void CryptDeriveKey_KnownValues_RC2()
+ {
+ TestKnownValue_CryptDeriveKey(
+ HashAlgorithmName.SHA1,
+ TestPassword,
+ "RC2",
+ 128,
+ s_testSalt,
+ ByteUtils.HexToByteArray("B0695D8D98F5844B9650A9F68EFF105B"));
+
+ TestKnownValue_CryptDeriveKey(
+ HashAlgorithmName.SHA256,
+ TestPassword,
+ "RC2",
+ 128,
+ s_testSalt,
+ ByteUtils.HexToByteArray("CF4A1CA60093E71D6B740DBB962B3C66"));
+
+ TestKnownValue_CryptDeriveKey(
+ HashAlgorithmName.MD5,
+ TestPassword,
+ "RC2",
+ 128,
+ s_testSalt,
+ ByteUtils.HexToByteArray("84F4B6854CDF896A86FB493B852B6E1F"));
+ }
+
+ [Fact]
+ public static void CryptDeriveKey_KnownValues_RC2_NoSalt()
+ {
+ TestKnownValue_CryptDeriveKey(
+ HashAlgorithmName.SHA1,
+ TestPassword,
+ "RC2",
+ 128,
+ null, // Salt is not used here so we should get same key value
+ ByteUtils.HexToByteArray("B0695D8D98F5844B9650A9F68EFF105B"));
+ }
+
+ [Fact]
+ public static void CryptDeriveKey_KnownValues_DES()
+ {
+ TestKnownValue_CryptDeriveKey(
+ HashAlgorithmName.SHA1,
+ TestPassword,
+ "DES",
+ 64,
+ s_testSalt,
+ ByteUtils.HexToByteArray("B0685D8C98F4854A"));
+ }
+
+ [Fact]
+ public static void CryptDeriveKey_Invalid_KeyLength()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ Assert.ThrowsAny<CryptographicException>(() => deriveBytes.CryptDeriveKey("RC2", "SHA1", 127, s_testSalt));
+ Assert.ThrowsAny<CryptographicException>(() => deriveBytes.CryptDeriveKey("RC2", "SHA1", 129, s_testSalt));
+ }
+ }
+
+ [Fact]
+ public static void CryptDeriveKey_Invalid_Algorithm()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ Assert.Throws<CryptographicException>(() => deriveBytes.CryptDeriveKey("BADALG", "SHA1", 128, s_testSalt));
+ }
+ }
+
+ [Fact]
+ public static void CryptDeriveKey_Invalid_HashAlgorithm()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ Assert.Throws<CryptographicException>(() => deriveBytes.CryptDeriveKey("RC2", "BADALG", 128, s_testSalt));
+ }
+ }
+
+ [Fact]
+ public static void CryptDeriveKey_Invalid_IV()
+ {
+ using (var deriveBytes = new PasswordDeriveBytes(TestPassword, s_testSalt))
+ {
+ Assert.Throws<CryptographicException>(() => deriveBytes.CryptDeriveKey("RC2", "SHA1", 128, null));
+ Assert.Throws<CryptographicException>(() => deriveBytes.CryptDeriveKey("RC2", "SHA1", 128, new byte[1]));
+ }
+ }
+
+ private static byte[] TestKnownValue_CryptDeriveKey(HashAlgorithmName hashName, string password, string alg, int keySize, byte[] salt, byte[] expected)
+ {
+ byte[] output;
+ byte[] iv = new byte[8];
+
+ using (var deriveBytes = new PasswordDeriveBytes(password, salt))
+ {
+ output = deriveBytes.CryptDeriveKey(alg, hashName.Name, keySize, iv);
+ }
+
+ Assert.Equal(expected, output);
+
+ // For these tests, the returned IV is always zero
+ Assert.Equal(new byte[8], iv);
+
+ return output;
+ }
+
+ private static void TestKnownValue_GetBytes(HashAlgorithmName hashName, string password, byte[] salt, int iterationCount, byte[] expected)
+ {
+ byte[] output;
+
+ using (var deriveBytes = new PasswordDeriveBytes(password, salt, hashName.Name, iterationCount))
+ {
+ output = deriveBytes.GetBytes(expected.Length);
+ }
+
+ Assert.Equal(expected, output);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj b/src/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj
index 7d78c0081a..202f778dd0 100644
--- a/src/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj
+++ b/src/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj
@@ -47,6 +47,7 @@
<Compile Include="DSACryptoServiceProviderProvider.cs" />
<Compile Include="DSACryptoServiceProviderTests.cs" />
<Compile Include="MD5CryptoServiceProviderTests.cs" />
+ <Compile Include="PasswordDeriveBytesTests.cs" />
<Compile Include="RC2CryptoServiceProviderProvider.cs" />
<Compile Include="RC2CryptoServiceProviderTests.cs" />
<Compile Include="RNGCryptoServiceProviderTests.cs" />
diff --git a/src/System.Security.Cryptography.OpenSsl/pkg/System.Security.Cryptography.OpenSsl.pkgproj b/src/System.Security.Cryptography.OpenSsl/pkg/System.Security.Cryptography.OpenSsl.pkgproj
index a3ec82f02f..b4c0484f81 100644
--- a/src/System.Security.Cryptography.OpenSsl/pkg/System.Security.Cryptography.OpenSsl.pkgproj
+++ b/src/System.Security.Cryptography.OpenSsl/pkg/System.Security.Cryptography.OpenSsl.pkgproj
@@ -3,7 +3,7 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Security.Cryptography.OpenSsl.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Security.Cryptography.OpenSsl.builds" />
</ItemGroup>
diff --git a/src/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/HelpersWindows.cs b/src/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/HelpersWindows.cs
index 838ebb404c..ccb11353ce 100644
--- a/src/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/HelpersWindows.cs
+++ b/src/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/Windows/HelpersWindows.cs
@@ -146,7 +146,7 @@ namespace Internal.Cryptography.Pal.Windows
return hCertContext;
}
- public unsafe static byte[] GetSubjectKeyIdentifer(this SafeCertContextHandle hCertContext)
+ public static unsafe byte[] GetSubjectKeyIdentifer(this SafeCertContextHandle hCertContext)
{
int cbData = 0;
if (!Interop.Crypt32.CertGetCertificateContextProperty(hCertContext, CertContextPropId.CERT_KEY_IDENTIFIER_PROP_ID, null, ref cbData))
diff --git a/src/System.Security.Cryptography.Pkcs/src/Interop/Windows/Crypt32/Interop.CryptMsgOpenToEncode.cs b/src/System.Security.Cryptography.Pkcs/src/Interop/Windows/Crypt32/Interop.CryptMsgOpenToEncode.cs
index 4be1abb24c..61b9b6dc32 100644
--- a/src/System.Security.Cryptography.Pkcs/src/Interop/Windows/Crypt32/Interop.CryptMsgOpenToEncode.cs
+++ b/src/System.Security.Cryptography.Pkcs/src/Interop/Windows/Crypt32/Interop.CryptMsgOpenToEncode.cs
@@ -14,7 +14,7 @@ internal static partial class Interop
internal static partial class Crypt32
{
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
- internal static unsafe extern SafeCryptMsgHandle CryptMsgOpenToEncode(MsgEncodingType dwMsgEncodingType, int dwFlags, CryptMsgType dwMsgType, CMSG_ENVELOPED_ENCODE_INFO* pvMsgEncodeInfo, [MarshalAs(UnmanagedType.LPStr)] string pszInnerContentObjID, IntPtr pStreamInfo);
+ internal static extern unsafe SafeCryptMsgHandle CryptMsgOpenToEncode(MsgEncodingType dwMsgEncodingType, int dwFlags, CryptMsgType dwMsgType, CMSG_ENVELOPED_ENCODE_INFO* pvMsgEncodeInfo, [MarshalAs(UnmanagedType.LPStr)] string pszInnerContentObjID, IntPtr pStreamInfo);
}
}
diff --git a/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs b/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs
index 17bc72a66d..9010a3620f 100644
--- a/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs
+++ b/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs
@@ -78,6 +78,7 @@ namespace System.Security.Cryptography
public abstract partial class HashAlgorithm : System.IDisposable, System.Security.Cryptography.ICryptoTransform
{
protected internal byte[] HashValue;
+ protected int HashSizeValue;
protected int State;
protected HashAlgorithm() { }
public virtual bool CanReuseTransform { get { throw null; } }
diff --git a/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj b/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj
index 9d1a5285d1..311a8ca364 100644
--- a/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj
+++ b/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj
@@ -38,7 +38,6 @@
<ItemGroup Condition="'$(TargetGroup)' == 'net463'">
<TargetingPackReference Include="mscorlib" />
</ItemGroup>
-
<ItemGroup>
<Reference Include="System.Runtime" />
<Reference Include="System.Resources.ResourceManager" />
diff --git a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HMAC.cs b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HMAC.cs
index c69bcab431..4291e6250c 100644
--- a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HMAC.cs
+++ b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HMAC.cs
@@ -23,12 +23,12 @@ namespace System.Security.Cryptography
protected HMAC() { }
- static public new HMAC Create()
+ public static new HMAC Create()
{
return Create("System.Security.Cryptography.HMAC");
}
- static public new HMAC Create(string algorithmName)
+ public static new HMAC Create(string algorithmName)
{
throw new PlatformNotSupportedException();
}
diff --git a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs
index f5d0d695d5..50a79aaa3a 100644
--- a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs
+++ b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs
@@ -8,6 +8,11 @@ namespace System.Security.Cryptography
{
public abstract class HashAlgorithm : IDisposable, ICryptoTransform
{
+ private bool _disposed;
+ protected int HashSizeValue;
+ protected internal byte[] HashValue;
+ protected int State = 0;
+
protected HashAlgorithm() { }
public static HashAlgorithm Create()
@@ -20,13 +25,7 @@ namespace System.Security.Cryptography
throw new PlatformNotSupportedException();
}
- public virtual int HashSize
- {
- get
- {
- return 0; // For desktop compatibility, return 0 as this property was always initialized by a subclass.
- }
- }
+ public virtual int HashSize => HashSizeValue;
public virtual byte[] Hash
{
@@ -199,9 +198,5 @@ namespace System.Security.Cryptography
protected abstract void HashCore(byte[] array, int ibStart, int cbSize);
protected abstract byte[] HashFinal();
public abstract void Initialize();
-
- private bool _disposed;
- protected internal byte[] HashValue;
- protected int State = 0;
}
}
diff --git a/src/System.Security.Cryptography.Primitives/tests/CryptoStream.cs b/src/System.Security.Cryptography.Primitives/tests/CryptoStream.cs
index 303b43423c..da8cb61402 100644
--- a/src/System.Security.Cryptography.Primitives/tests/CryptoStream.cs
+++ b/src/System.Security.Cryptography.Primitives/tests/CryptoStream.cs
@@ -257,6 +257,7 @@ namespace System.Security.Cryptography.Encryption.Tests.Asymmetric
{
private readonly int _inputBlockSize, _outputBlockSize;
private readonly bool _canTransformMultipleBlocks;
+ private readonly object _lock = new object();
private long _writePos, _readPos;
private MemoryStream _stream;
@@ -281,31 +282,36 @@ namespace System.Security.Cryptography.Encryption.Tests.Asymmetric
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
- _stream.Position = _writePos;
- _stream.Write(inputBuffer, inputOffset, inputCount);
- _writePos = _stream.Position;
-
- _stream.Position = _readPos;
- int copied = _stream.Read(outputBuffer, outputOffset, outputBuffer.Length - outputOffset);
- _readPos = _stream.Position;
-
- return copied;
+ lock (_lock)
+ {
+ _stream.Position = _writePos;
+ _stream.Write(inputBuffer, inputOffset, inputCount);
+ _writePos = _stream.Position;
+
+ _stream.Position = _readPos;
+ int copied = _stream.Read(outputBuffer, outputOffset, outputBuffer.Length - outputOffset);
+ _readPos = _stream.Position;
+ return copied;
+ }
}
public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
{
- _stream.Position = _writePos;
- _stream.Write(inputBuffer, inputOffset, inputCount);
-
- _stream.Position = _readPos;
- long len = _stream.Length - _stream.Position;
- byte[] outputBuffer = new byte[len];
- _stream.Read(outputBuffer, 0, outputBuffer.Length);
-
- _stream = new MemoryStream();
- _writePos = 0;
- _readPos = 0;
- return outputBuffer;
+ lock (_lock)
+ {
+ _stream.Position = _writePos;
+ _stream.Write(inputBuffer, inputOffset, inputCount);
+
+ _stream.Position = _readPos;
+ long len = _stream.Length - _stream.Position;
+ byte[] outputBuffer = new byte[len];
+ _stream.Read(outputBuffer, 0, outputBuffer.Length);
+
+ _stream = new MemoryStream();
+ _writePos = 0;
+ _readPos = 0;
+ return outputBuffer;
+ }
}
}
diff --git a/src/System.Security.Cryptography.Primitives/tests/Length32Hash.cs b/src/System.Security.Cryptography.Primitives/tests/Length32Hash.cs
index 84f7ccc441..5594888b3d 100644
--- a/src/System.Security.Cryptography.Primitives/tests/Length32Hash.cs
+++ b/src/System.Security.Cryptography.Primitives/tests/Length32Hash.cs
@@ -8,10 +8,17 @@ namespace System.Security.Cryptography.Hashing.Tests
{
private uint _length;
+#if netstandard17
+ public Length32Hash()
+ {
+ HashSizeValue = sizeof(uint);
+ }
+#else
public override int HashSize
{
get { return sizeof(uint); }
}
+#endif
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
diff --git a/src/System.Security.Cryptography.Primitives/tests/Sum32Hash.cs b/src/System.Security.Cryptography.Primitives/tests/Sum32Hash.cs
index d6c6a83de2..ca04c1bf24 100644
--- a/src/System.Security.Cryptography.Primitives/tests/Sum32Hash.cs
+++ b/src/System.Security.Cryptography.Primitives/tests/Sum32Hash.cs
@@ -8,10 +8,17 @@ namespace System.Security.Cryptography.Hashing.Tests
{
private uint _sum;
+#if netstandard17
+ public Sum32Hash()
+ {
+ HashSizeValue = sizeof(uint);
+ }
+#else
public override int HashSize
{
get { return sizeof(uint); }
}
+#endif
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs
index 72773d4bf0..5ca8bc47d5 100644
--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs
+++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs
@@ -24,6 +24,8 @@ namespace Internal.Cryptography.Pal
{
internal sealed partial class CertificatePal : IDisposable, ICertificatePal
{
+ private SafeCertContextHandle _certContext;
+
public static ICertificatePal FromHandle(IntPtr handle)
{
if (handle == IntPtr.Zero)
@@ -40,20 +42,14 @@ namespace Internal.Cryptography.Pal
}
/// <summary>
- /// Returns the SafeCertContextHandle. Use this instead of FromHandle property when
+ /// Returns the SafeCertContextHandle. Use this instead of FromHandle() when
/// creating another X509Certificate object based on this one to ensure the underlying
/// cert context is not released at the wrong time.
/// </summary>
- /// <param name="cert"></param>
- /// <returns></returns>
- public static ICertificatePal FromOtherCert(X509Certificate cert)
+ public static ICertificatePal FromOtherCert(X509Certificate copyFrom)
{
- CertificatePal newCert = (CertificatePal)FromHandle(cert.Handle);
- newCert._certContextCloned = true;
-
- ((CertificatePal)cert.Pal)._certContextCloned = true;
-
- return newCert;
+ CertificatePal pal = new CertificatePal((CertificatePal)copyFrom.Pal);
+ return pal;
}
public IntPtr Handle
@@ -490,10 +486,7 @@ namespace Internal.Cryptography.Pal
_certContext = null;
if (certContext != null && !certContext.IsInvalid)
{
- if (!_certContextCloned)
- {
- certContext.Dispose();
- }
+ certContext.Dispose();
}
}
@@ -549,6 +542,13 @@ namespace Internal.Cryptography.Pal
return sb.ToString();
}
+ private CertificatePal(CertificatePal copyFrom)
+ {
+ // Use _certContext (instead of CertContext) to keep the original context handle from being
+ // finalized until all cert copies are no longer referenced.
+ _certContext = new SafeCertContextHandle(copyFrom._certContext);
+ }
+
private CertificatePal(SafeCertContextHandle certContext, bool deleteKeyContainer)
{
if (deleteKeyContainer)
@@ -561,8 +561,5 @@ namespace Internal.Cryptography.Pal
}
_certContext = certContext;
}
-
- private SafeCertContextHandle _certContext;
- private bool _certContextCloned;
}
}
diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs
index 2a65582c65..d3b5c8953f 100644
--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs
+++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs
@@ -23,7 +23,7 @@ internal static partial class Interop
public static partial class crypt32
{
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
- public static unsafe extern bool CryptQueryObject(
+ public static extern unsafe bool CryptQueryObject(
CertQueryObjectType dwObjectType,
void* pvObject,
ExpectedContentTypeFlags dwExpectedContentTypeFlags,
@@ -38,7 +38,7 @@ internal static partial class Interop
);
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
- public static unsafe extern bool CryptQueryObject(
+ public static extern unsafe bool CryptQueryObject(
CertQueryObjectType dwObjectType,
void* pvObject,
ExpectedContentTypeFlags dwExpectedContentTypeFlags,
@@ -53,7 +53,7 @@ internal static partial class Interop
);
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
- public static unsafe extern bool CryptQueryObject(
+ public static extern unsafe bool CryptQueryObject(
CertQueryObjectType dwObjectType,
void* pvObject,
ExpectedContentTypeFlags dwExpectedContentTypeFlags,
@@ -252,21 +252,21 @@ internal static partial class Interop
}
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
- private static unsafe extern SafeCertContextHandle CertFindCertificateInStore(SafeCertStoreHandle hCertStore, CertEncodingType dwCertEncodingType, CertFindFlags dwFindFlags, CertFindType dwFindType, void* pvFindPara, CERT_CONTEXT* pPrevCertContext);
+ private static extern unsafe SafeCertContextHandle CertFindCertificateInStore(SafeCertStoreHandle hCertStore, CertEncodingType dwCertEncodingType, CertFindFlags dwFindFlags, CertFindType dwFindType, void* pvFindPara, CERT_CONTEXT* pPrevCertContext);
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
- public static unsafe extern int CertVerifyTimeValidity([In] ref FILETIME pTimeToVerify, [In] CERT_INFO* pCertInfo);
+ public static extern unsafe int CertVerifyTimeValidity([In] ref FILETIME pTimeToVerify, [In] CERT_INFO* pCertInfo);
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
- public static unsafe extern CERT_EXTENSION* CertFindExtension([MarshalAs(UnmanagedType.LPStr)] string pszObjId, int cExtensions, CERT_EXTENSION* rgExtensions);
+ public static extern unsafe CERT_EXTENSION* CertFindExtension([MarshalAs(UnmanagedType.LPStr)] string pszObjId, int cExtensions, CERT_EXTENSION* rgExtensions);
// Note: It's somewhat unusual to use an API enum as a parameter type to a P/Invoke but in this case, X509KeyUsageFlags was intentionally designed as bit-wise
// identical to the wincrypt CERT_*_USAGE values.
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
- public static unsafe extern bool CertGetIntendedKeyUsage(CertEncodingType dwCertEncodingType, CERT_INFO* pCertInfo, out X509KeyUsageFlags pbKeyUsage, int cbKeyUsage);
+ public static extern unsafe bool CertGetIntendedKeyUsage(CertEncodingType dwCertEncodingType, CERT_INFO* pCertInfo, out X509KeyUsageFlags pbKeyUsage, int cbKeyUsage);
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
- public static unsafe extern bool CertGetValidUsages(int cCerts, [In] ref SafeCertContextHandle rghCerts, out int cNumOIDs, [Out] void* rghOIDs, [In, Out] ref int pcbOIDs);
+ public static extern unsafe bool CertGetValidUsages(int cCerts, [In] ref SafeCertContextHandle rghCerts, out int cNumOIDs, [Out] void* rghOIDs, [In, Out] ref int pcbOIDs);
[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CertControlStore(SafeCertStoreHandle hCertStore, CertControlStoreFlags dwFlags, CertControlStoreType dwControlType, IntPtr pvCtrlPara);
diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/SafeHandles.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/SafeHandles.cs
index fbf58c3508..cc1705b181 100644
--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/SafeHandles.cs
+++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/SafeHandles.cs
@@ -44,9 +44,38 @@ namespace Internal.Cryptography.Pal.Native
/// </summary>
internal class SafeCertContextHandle : SafePointerHandle<SafeCertContextHandle>
{
+ private SafeCertContextHandle _parent;
+
+ public SafeCertContextHandle() { }
+
+ public SafeCertContextHandle(SafeCertContextHandle parent)
+ {
+ if (parent == null)
+ throw new ArgumentNullException(nameof(parent));
+
+ Debug.Assert(!parent.IsInvalid);
+ Debug.Assert(!parent.IsClosed);
+
+ bool ignored = false;
+ parent.DangerousAddRef(ref ignored);
+ _parent = parent;
+
+ SetHandle(_parent.handle);
+ }
+
protected override bool ReleaseHandle()
{
- Interop.crypt32.CertFreeCertificateContext(handle); // CertFreeCertificateContext always returns true so checking the return value is pointless.
+ if (_parent != null)
+ {
+ _parent.DangerousRelease();
+ _parent = null;
+ }
+ else
+ {
+ Interop.crypt32.CertFreeCertificateContext(handle);
+ }
+
+ SetHandle(IntPtr.Zero);
return true;
}
@@ -135,7 +164,7 @@ namespace Internal.Cryptography.Pal.Native
{
// dwProvType being 0 indicates that the key is stored in CNG.
// dwProvType being non-zero indicates that the key is stored in CAPI.
-
+
string providerName = Marshal.PtrToStringUni((IntPtr)(pProvInfo->pwszProvName));
string keyContainerName = Marshal.PtrToStringUni((IntPtr)(pProvInfo->pwszContainerName));
diff --git a/src/System.Security.Cryptography.X509Certificates/tests/CertTests.cs b/src/System.Security.Cryptography.X509Certificates/tests/CertTests.cs
index bfc06926ca..c68a2c62ff 100644
--- a/src/System.Security.Cryptography.X509Certificates/tests/CertTests.cs
+++ b/src/System.Security.Cryptography.X509Certificates/tests/CertTests.cs
@@ -4,11 +4,19 @@
using System.IO;
using Xunit;
+using Xunit.Abstractions;
namespace System.Security.Cryptography.X509Certificates.Tests
{
- public static class CertTests
+ public class CertTests
{
+ private readonly ITestOutputHelper _log;
+
+ public CertTests(ITestOutputHelper output)
+ {
+ _log = output;
+ }
+
[Fact]
public static void X509CertTest()
{
@@ -81,22 +89,63 @@ namespace System.Security.Cryptography.X509Certificates.Tests
#if netstandard17
[Fact]
- public static void TestVerify()
+ [OuterLoop("May require using the network, to download CRLs and intermediates")]
+ public void TestVerify()
{
+ bool success;
+
using (var microsoftDotCom = new X509Certificate2(TestData.MicrosoftDotComSslCertBytes))
{
// Fails because expired (NotAfter = 10/16/2016)
- Assert.False(microsoftDotCom.Verify());
+ Assert.False(microsoftDotCom.Verify(), "MicrosoftDotComSslCertBytes");
}
using (var microsoftDotComIssuer = new X509Certificate2(TestData.MicrosoftDotComIssuerBytes))
{
- Assert.True(microsoftDotComIssuer.Verify()); // NotAfter=10/31/2023
+ // NotAfter=10/31/2023
+ success = microsoftDotComIssuer.Verify();
+ if (!success)
+ {
+ LogVerifyErrors(microsoftDotComIssuer, "MicrosoftDotComIssuerBytes");
+ }
+ Assert.True(success, "MicrosoftDotComIssuerBytes");
}
using (var microsoftDotComRoot = new X509Certificate2(TestData.MicrosoftDotComRootBytes))
{
- Assert.True(microsoftDotComRoot.Verify()); // NotAfter=7/17/2036
+ // NotAfter=7/17/2036
+ success = microsoftDotComRoot.Verify();
+ if (!success)
+ {
+ LogVerifyErrors(microsoftDotComRoot, "MicrosoftDotComRootBytes");
+ }
+ Assert.True(success, "MicrosoftDotComRootBytes");
+ }
+ }
+
+ private void LogVerifyErrors(X509Certificate2 cert, string testName)
+ {
+ // Emulate cert.Verify() implementation in order to capture and log errors.
+ try
+ {
+ using (var chain = new X509Chain())
+ {
+ if (!chain.Build(cert))
+ {
+ foreach (X509ChainStatus chainStatus in chain.ChainStatus)
+ {
+ _log.WriteLine(string.Format($"X509Certificate2.Verify error: {testName}, {chainStatus.Status}, {chainStatus.StatusInformation}"));
+ }
+ }
+ else
+ {
+ _log.WriteLine(string.Format($"X509Certificate2.Verify expected error; received none: {testName}"));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _log.WriteLine($"X509Certificate2.Verify exception: {testName}, {e}");
}
}
#endif
diff --git a/src/System.Security.Cryptography.X509Certificates/tests/CtorTests.cs b/src/System.Security.Cryptography.X509Certificates/tests/CtorTests.cs
index a7b89cd29b..f3e6e6895e 100644
--- a/src/System.Security.Cryptography.X509Certificates/tests/CtorTests.cs
+++ b/src/System.Security.Cryptography.X509Certificates/tests/CtorTests.cs
@@ -217,6 +217,9 @@ namespace System.Security.Cryptography.X509Certificates.Tests
c1.Dispose();
rsa.Dispose();
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
// Verify other cert and previous key do not affect cert
using (rsa = c2.GetRSAPrivateKey())
{
@@ -236,10 +239,16 @@ namespace System.Security.Cryptography.X509Certificates.Tests
TestPrivateKey(c2, true);
c1.Dispose();
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
TestPrivateKey(c1, false);
TestPrivateKey(c2, true);
c2.Dispose();
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
TestPrivateKey(c2, false);
}
@@ -252,10 +261,16 @@ namespace System.Security.Cryptography.X509Certificates.Tests
TestPrivateKey(c2, true);
c2.Dispose();
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
TestPrivateKey(c1, true);
TestPrivateKey(c2, false);
c1.Dispose();
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
TestPrivateKey(c1, false);
}
diff --git a/src/System.Security.Cryptography.Xml/System.Security.Cryptography.Xml.sln b/src/System.Security.Cryptography.Xml/System.Security.Cryptography.Xml.sln
new file mode 100644
index 0000000000..4a05d18f79
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/System.Security.Cryptography.Xml.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Security.Cryptography.Xml", "src\System.Security.Cryptography.Xml.csproj", "{E7F19085-6570-4811-8D3F-16B576049403}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Security.Cryptography.Xml.Tests", "tests\System.Security.Cryptography.Xml.Tests.csproj", "{3C32659A-6DB9-410A-8E24-BE91BFF4C024}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E7F19085-6570-4811-8D3F-16B576049403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7F19085-6570-4811-8D3F-16B576049403}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E7F19085-6570-4811-8D3F-16B576049403}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E7F19085-6570-4811-8D3F-16B576049403}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3C32659A-6DB9-410A-8E24-BE91BFF4C024}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3C32659A-6DB9-410A-8E24-BE91BFF4C024}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3C32659A-6DB9-410A-8E24-BE91BFF4C024}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {3C32659A-6DB9-410A-8E24-BE91BFF4C024}.Release|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/System.Security.Cryptography.Xml/dir.props b/src/System.Security.Cryptography.Xml/dir.props
new file mode 100644
index 0000000000..86aacdb931
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/dir.props
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\dir.props" />
+ <PropertyGroup>
+ <AssemblyVersion>4.0.0.0</AssemblyVersion>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/src/System.Security.Cryptography.Xml/pkg/System.Security.Cryptography.Xml.builds b/src/System.Security.Cryptography.Xml/pkg/System.Security.Cryptography.Xml.builds
new file mode 100644
index 0000000000..9533fbb23c
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/pkg/System.Security.Cryptography.Xml.builds
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!-- Disabling the builds for Xml until we get it up and running. This excludes it from being built by build.cmd
+ <Project Include="System.Security.Cryptography.Xml.pkgproj"/>
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.Security.Cryptography.Xml/pkg/System.Security.Cryptography.Xml.pkgproj b/src/System.Security.Cryptography.Xml/pkg/System.Security.Cryptography.Xml.pkgproj
new file mode 100644
index 0000000000..84b587e178
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/pkg/System.Security.Cryptography.Xml.pkgproj
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <ProjectReference Include="..\ref\System.Security.Cryptography.Xml.builds">
+ <SupportedFramework>net462;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ </ProjectReference>
+ <ProjectReference Include="..\src\System.Security.Cryptography.Xml.builds" />
+ </ItemGroup>
+ <ItemGroup>
+ <InboxOnTargetFramework Include="MonoAndroid10" />
+ <InboxOnTargetFramework Include="MonoTouch10" />
+ <InboxOnTargetFramework Include="xamarinios10" />
+ <InboxOnTargetFramework Include="xamarinmac20" />
+ <InboxOnTargetFramework Include="xamarintvos10" />
+ <InboxOnTargetFramework Include="xamarinwatchos10" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.builds b/src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.builds
new file mode 100644
index 0000000000..f7b01e5eb3
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.builds
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!-- Disabling the builds for Xml until we get it up and running. This excludes it from being built by build.cmd
+ <Project Include="System.Security.Cryptography.Xml.csproj" />
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project>
diff --git a/src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs b/src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs
new file mode 100644
index 0000000000..5c2f593e66
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs
@@ -0,0 +1,7 @@
+// 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.
+// ------------------------------------------------------------------------------
+// Changes to this file must follow the http://aka.ms/api-review process.
+// ------------------------------------------------------------------------------
+
diff --git a/src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj b/src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj
new file mode 100644
index 0000000000..fa7757d645
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="System.Security.Cryptography.Xml.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.Security.Cryptography.Xml/src/Resources/System.Security.txt b/src/System.Security.Cryptography.Xml/src/Resources/System.Security.txt
new file mode 100644
index 0000000000..8739a987fa
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/Resources/System.Security.txt
@@ -0,0 +1,129 @@
+README: this file copied from netfx to corefx as left as-is except for this comment. It needs to be deleted once all of the System.Security.Cryptography.Xml strings have been added to a resource file (like in other corefx projects)
+
+
+
+
+; System.Security.dll resources.
+
+Arg_RankMultiDimNotSupported = Only single dimensional arrays are supported for the requested action.
+Arg_EnumIllegalVal = Illegal enum value: {0}.
+Argument_InvalidOffLen = Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
+Argument_InvalidPermissionState = Invalid permission state.
+Argument_InvalidValue = Value was invalid.
+Argument_WrongType = Operation on type '{0}' attempted with target of incorrect type.
+ArgumentOutOfRange_Index = Index was out of range. Must be non-negative and less than the size of the collection.
+Arg_EmptyOrNullString = String cannot be empty or null.
+Argument_InvalidClassAttribute = The value of "class" attribute is invalid.
+InvalidOperation_DuplicateItemNotAllowed = Duplicate items are not allowed in the collection.
+
+Cryptography_Cms_Envelope_Empty_Content = Cannot create CMS enveloped for empty content.
+Cryptography_Cms_Invalid_Subject_Identifier_Type = The subject identifier type {0} is not valid.
+Cryptography_Cms_Invalid_Subject_Identifier_Type_Value_Mismatch = The subject identifier type {0} does not match the value data type {1}.
+Cryptography_Cms_Key_Agree_Date_Not_Available = The Date property is not available for none KID key agree recipient.
+Cryptography_Cms_Key_Agree_Other_Key_Attribute_Not_Available = The OtherKeyAttribute property is not available for none KID key agree recipient.
+Cryptography_Cms_MessageNotSigned = The CMS message is not signed.
+Cryptography_Cms_MessageNotEncrypted = The CMS message is not encrypted.
+Cryptography_Cms_Not_Supported = The Cryptographic Message Standard (CMS) is not supported on this platform.
+Cryptography_Cms_RecipientCertificateNotFound = The recipient certificate is not specified.
+Cryptography_Cms_Sign_Empty_Content = Cannot create CMS signature for empty content.
+Cryptography_Cms_Sign_No_Signature_First_Signer = CmsSigner has to be the first signer with NoSignature.
+Cryptography_DataProtector_InvalidAppNameOrPurpose = Application names and purposes must contain at least one character which is not white space.
+Cryptography_DataProtector_InvalidPurpose = The purpose of the protected blob does not match the expected purpose value of this data protector instance.
+Cryptography_DpApi_InvalidMemoryLength = The length of the data should be a multiple of 16 bytes.
+Cryptography_DpApi_ProfileMayNotBeLoaded = The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating.
+Cryptography_InvalidHandle = {0} is an invalid handle.
+Cryptography_InvalidContextHandle = The chain context handle is invalid.
+Cryptography_Pkcs9_MultipleSigningTimeNotAllowed = Cannot add multiple PKCS 9 signing time attributes.
+Cryptography_Pkcs9_AttributeMismatch = The parameter should be a PKCS 9 attribute.
+Cryptography_X509_InvalidEncodingFormat = Invalid encoding format.
+Cryptography_Xml_CipherValueElementRequired = A Cipher Data element should have either a CipherValue or a CipherReference element.
+Cryptography_Xml_CreateHashAlgorithmFailed = Could not create hash algorithm object.
+Cryptography_Xml_CreateTransformFailed = Could not create the XML transformation identified by the URI {0}.
+Cryptography_Xml_CreatedKeyFailed = Failed to create signing key.
+Cryptography_Xml_DigestMethodRequired = A DigestMethod must be specified on a Reference prior to generating XML.
+Cryptography_Xml_DigestValueRequired = A Reference must contain a DigestValue.
+Cryptography_Xml_EnvelopedSignatureRequiresContext = An XmlDocument context is required for enveloped transforms.
+Cryptography_Xml_InvalidElement = Malformed element {0}.
+Cryptography_Xml_InvalidEncryptionProperty = Malformed encryption property element.
+Cryptography_Xml_InvalidKeySize = The key size should be a non negative integer.
+Cryptography_Xml_InvalidReference = Malformed reference element.
+Cryptography_Xml_InvalidSignatureLength = The length of the signature with a MAC should be less than the hash output length.
+Cryptography_Xml_InvalidSignatureLength2 = The length in bits of the signature with a MAC should be a multiple of 8.
+Cryptography_Xml_KeyInfoRequired = A KeyInfo element is required to check the signature.
+Cryptography_Xml_KW_BadKeySize = The length of the encrypted data in Key Wrap is either 32, 40 or 48 bytes.
+Cryptography_Xml_LoadKeyFailed = Signing key is not loaded.
+Cryptography_Xml_MissingAlgorithm = Symmetric algorithm is not specified.
+Cryptography_Xml_MissingCipherData = Cipher data is not specified.
+Cryptography_Xml_MissingDecryptionKey = Unable to retrieve the decryption key.
+Cryptography_Xml_MissingEncryptionKey = Unable to retrieve the encryption key.
+Cryptography_Xml_NotSupportedCryptographicTransform = The specified cryptographic transform is not supported.
+Cryptography_Xml_ReferenceElementRequired = At least one Reference element is required.
+Cryptography_Xml_ReferenceTypeRequired = The Reference type must be set in an EncryptedReference object.
+Cryptography_Xml_SelfReferenceRequiresContext = An XmlDocument context is required to resolve the Reference Uri {0}.
+Cryptography_Xml_SignatureDescriptionNotCreated = SignatureDescription could not be created for the signature algorithm supplied.
+Cryptography_Xml_SignatureMethodKeyMismatch = The key does not fit the SignatureMethod.
+Cryptography_Xml_SignatureMethodRequired = A signature method is required.
+Cryptography_Xml_SignatureValueRequired = Signature requires a SignatureValue.
+Cryptography_Xml_SignedInfoRequired = Signature requires a SignedInfo.
+Cryptography_Xml_TransformIncorrectInputType = The input type was invalid for this transform.
+Cryptography_Xml_IncorrectObjectType = Type of input object is invalid.
+Cryptography_Xml_UnknownTransform = Unknown transform has been encountered.
+Cryptography_Xml_UriNotResolved = Unable to resolve Uri {0}.
+Cryptography_Xml_UriNotSupported = The specified Uri is not supported.
+Cryptography_Xml_UriRequired = A Uri attribute is required for a CipherReference element.
+Cryptography_Xml_XrmlMissingContext = Null Context property encountered.
+Cryptography_Xml_XrmlMissingIRelDecryptor = IRelDecryptor is required.
+Cryptography_Xml_XrmlMissingIssuer = Issuer node is required.
+Cryptography_Xml_XrmlMissingLicence = License node is required.
+Cryptography_Xml_XrmlUnableToDecryptGrant = Unable to decrypt grant content.
+
+Environment_NotInteractive = The current session is not interactive.
+
+NotSupported_KeyAlgorithm = The certificate key algorithm is not supported.
+NotSupported_PlatformRequiresNT = This operation is only supported on Windows 2000, Windows XP, and higher.
+
+; Strings used in the SignedXMl debug log
+Log_ActualHashValue=Actual hash value: {0}
+Log_ApplicationPolicies=Application policies:
+Log_BeginCanonicalization=Beginning canonicalization using "{0}" ({1}).
+Log_BeginSignatureComputation=Beginning signature computation.
+Log_BeginSignatureVerification=Beginning signature verification.
+Log_BuildX509Chain=Building and verifying the X509 chain for certificate {0}.
+Log_CanonicalizationSettings=Canonicalization transform is using resolver {0} and base URI "{1}".
+Log_CanonicalizedOutput=Output of canonicalization transform: {0}
+Log_CertificatePolicies=Certificate policies:
+Log_CertificateChain=Certificate chain:
+Log_CheckSignatureFormat=Checking signature format using format validator "[{0}] {1}.{2}".
+Log_CheckSignedInfo=Checking signature on SignedInfo with id "{0}".
+Log_ExtraCertificateForChain=Certificate {0} is available for chain building.
+Log_FormatValidationSuccessful=Signature format validation was successful.
+Log_FormatValidationNotSuccessful=Signature format validation failed.
+Log_KeyUsages=Found key usages "{0}" in extension {1} on certificate {2}.
+Log_NoNamespacesPropagated=No namespaces are being propagated.
+Log_PropagatingNamespace=Propagating namespace {0}="{1}".
+Log_RawSignatureValue=Raw signature: {0}
+Log_ReferenceHash=Reference {0} hashed with "{1}" ({2}) has hash value {3}, expected hash value {4}.
+Log_RevocationMode=Revocation mode for chain building: {0}.
+Log_RevocationFlag=Revocation flag for chain building: {0}.
+Log_SigningAsymmetric=Calculating signature with key {0} using signature description {1}, hash algorithm {2}, and asymmetric signature formatter {3}.
+Log_SigningHmac=Calculating signature using keyed hash algorithm {0}.
+Log_SigningReference=Hashing reference {0}, Uri "{1}", Id "{2}", Type "{3}" with hash algorithm "{4}" ({5}).
+Log_TransformedReferenceContents=Transformed reference contents: {0}
+Log_UnsafeCanonicalizationMethod=Canonicalization method "{0}" is not on the safe list. Safe canonicalization methods are: {1}.
+Log_UrlTimeout=URL retrieval timeout for chain building: {0}.
+Log_VerificationFailed=Verification failed checking {0}.
+Log_VerificationFailed_References=references
+Log_VerificationFailed_SignedInfo=SignedInfo
+Log_VerificationFailed_X509Chain=X509 chain verification
+Log_VerificationFailed_X509KeyUsage=X509 key usage verification
+Log_VerificationFlag=Verification flags for chain building: {0}.
+Log_VerificationTime=Verification time for chain building: {0}.
+Log_VerificationWithKeySuccessful=Verification with key {0} was successful.
+Log_VerificationWithKeyNotSuccessful=Verification with key {0} was not successful.
+Log_VerifyReference=Processing reference {0}, Uri "{1}", Id "{2}", Type "{3}".
+Log_VerifySignedInfoAsymmetric=Verifying SignedInfo using key {0}, signature description {1}, hash algorithm {2}, and asymmetric signature deformatter {3}.
+Log_VerifySignedInfoHmac=Verifying SignedInfo using keyed hash algorithm {0}.
+Log_X509ChainError=Error building X509 chain: {0}: {1}.
+Log_XmlContext=Using context: {0}
+Log_SignedXmlRecursionLimit=Signed xml recursion limit hit while trying to decrypt the key. Reference {0} hashed with "{1}" and ({2}).
+Log_UnsafeTransformMethod=Transform method "{0}" is not on the safe list. Safe transform methods are: {1}.
diff --git a/src/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.builds b/src/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.builds
new file mode 100644
index 0000000000..1dfbdf3a00
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.builds
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!-- Disabling the builds for Xml until we get it up and running. This excludes it from being built by build.cmd
+ <Project Include="System.Security.Cryptography.Xml.csproj" />
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project>
+
diff --git a/src/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj b/src/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj
new file mode 100644
index 0000000000..6f71be6193
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <Configuration Condition="'$(Configuration)'=='' AND '$(TargetGroup)' == ''">Debug</Configuration>
+ </PropertyGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <ProjectGuid>{E7F19085-6570-4811-8D3F-16B576049403}</ProjectGuid>
+ <AssemblyName>System.Security.Cryptography.Xml</AssemblyName>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net462'">true</IsPartialFacadeAssembly>
+ <NuGetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.7</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Help VS understand available configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
+ <ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
+ <Compile Include="System\Security\Cryptography\Xml\AncestralNamespaceContextManager.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\AttributeSortOrder.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\C14NAncestralNamespaceContextManager.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalizationDispatcher.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXml.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlAttribute.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlCDataSection.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlComment.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlDocument.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlElement.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlEntityReference.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlNodeList.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlProcessingInstruction.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlSignificantWhitespace.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlText.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CanonicalXmlWhitespace.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CertUsageType.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CipherData.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CipherReference.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\CryptoSignedXmlRecursionException.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\DataObject.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\DataReference.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\DocPosition.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\DSAKeyValue.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\EncryptedData.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\EncryptedKey.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\EncryptedReference.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\EncryptedType.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\EncryptedXml.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\EncryptionMethod.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\EncryptionProperty.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\EncryptionPropertyCollection.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\ExcAncestralNamespaceContextManager.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\ExcCanonicalXml.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\ICanonicalizableNode.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\IRelDecryptor.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\KeyInfo.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\KeyInfoClause.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\KeyInfoEncryptedKey.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\KeyInfoName.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\KeyInfoNode.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\KeyInfoRetrievalMethod.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\KeyInfoX509Data.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\KeyReference.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\MyXmlDocument.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\NamespaceFrame.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\NamespaceSortOrder.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\Reference.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\ReferenceList.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\ReferenceTargetType.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\RSAKeyValue.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\Signature.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\SignedInfo.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\SignedXml.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\SignedXmlDebugLog.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\SymmetricKeyWrap.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\Transform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\TransformChain.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\TransformInputType.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\Utils.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\X509IssuerSerial.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlDecryptionTransform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlDsigBase64Transform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlDsigC14NTransform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlDsigC14NWithCommentsTransform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlDsigEnvelopedSignatureTransform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlDsigExcC14NTransform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlDsigExcC14NWithCommentsTransform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlDsigXPathTransform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlDsigXsltTransform.cs" />
+ <Compile Include="System\Security\Cryptography\Xml\XmlLicenseTransform.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AncestralNamespaceContextManager.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AncestralNamespaceContextManager.cs
new file mode 100644
index 0000000000..337c2b1ac0
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AncestralNamespaceContextManager.cs
@@ -0,0 +1,99 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+
+namespace System.Security.Cryptography.Xml
+{
+ internal abstract class AncestralNamespaceContextManager
+ {
+ internal ArrayList _ancestorStack = new ArrayList();
+
+ internal NamespaceFrame GetScopeAt(int i)
+ {
+ return (NamespaceFrame)_ancestorStack[i];
+ }
+
+ internal NamespaceFrame GetCurrentScope()
+ {
+ return GetScopeAt(_ancestorStack.Count - 1);
+ }
+
+ protected XmlAttribute GetNearestRenderedNamespaceWithMatchingPrefix(string nsPrefix, out int depth)
+ {
+ XmlAttribute attr = null;
+ depth = -1;
+ for (int i = _ancestorStack.Count - 1; i >= 0; i--)
+ {
+ if ((attr = GetScopeAt(i).GetRendered(nsPrefix)) != null)
+ {
+ depth = i;
+ return attr;
+ }
+ }
+ return null;
+ }
+
+ protected XmlAttribute GetNearestUnrenderedNamespaceWithMatchingPrefix(string nsPrefix, out int depth)
+ {
+ XmlAttribute attr = null;
+ depth = -1;
+ for (int i = _ancestorStack.Count - 1; i >= 0; i--)
+ {
+ if ((attr = GetScopeAt(i).GetUnrendered(nsPrefix)) != null)
+ {
+ depth = i;
+ return attr;
+ }
+ }
+ return null;
+ }
+
+ internal void EnterElementContext()
+ {
+ _ancestorStack.Add(new NamespaceFrame());
+ }
+
+ internal void ExitElementContext()
+ {
+ _ancestorStack.RemoveAt(_ancestorStack.Count - 1);
+ }
+
+ internal abstract void TrackNamespaceNode(XmlAttribute attr, SortedList nsListToRender, Hashtable nsLocallyDeclared);
+ internal abstract void TrackXmlNamespaceNode(XmlAttribute attr, SortedList nsListToRender, SortedList attrListToRender, Hashtable nsLocallyDeclared);
+ internal abstract void GetNamespacesToRender(XmlElement element, SortedList attrListToRender, SortedList nsListToRender, Hashtable nsLocallyDeclared);
+
+ internal void LoadUnrenderedNamespaces(Hashtable nsLocallyDeclared)
+ {
+ object[] attrs = new object[nsLocallyDeclared.Count];
+ nsLocallyDeclared.Values.CopyTo(attrs, 0);
+ foreach (object attr in attrs)
+ {
+ AddUnrendered((XmlAttribute)attr);
+ }
+ }
+
+ internal void LoadRenderedNamespaces(SortedList nsRenderedList)
+ {
+ foreach (object attr in nsRenderedList.GetKeyList())
+ {
+ AddRendered((XmlAttribute)attr);
+ }
+ }
+
+ internal void AddRendered(XmlAttribute attr)
+ {
+ GetCurrentScope().AddRendered(attr);
+ }
+
+ internal void AddUnrendered(XmlAttribute attr)
+ {
+ GetCurrentScope().AddUnrendered(attr);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AttributeSortOrder.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AttributeSortOrder.cs
new file mode 100644
index 0000000000..beb2fcb8fa
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AttributeSortOrder.cs
@@ -0,0 +1,29 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+
+namespace System.Security.Cryptography.Xml
+{
+ // This class does lexicographic sorting by NamespaceURI first and then by LocalName.
+ internal class AttributeSortOrder : IComparer
+ {
+ internal AttributeSortOrder() { }
+
+ public int Compare(object a, object b)
+ {
+ XmlNode nodeA = a as XmlNode;
+ XmlNode nodeB = b as XmlNode;
+ if ((a == null) || (b == null))
+ throw new ArgumentException();
+ int namespaceCompare = string.CompareOrdinal(nodeA.NamespaceURI, nodeB.NamespaceURI);
+ if (namespaceCompare != 0) return namespaceCompare;
+ return string.CompareOrdinal(nodeA.LocalName, nodeB.LocalName);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/C14NAncestralNamespaceContextManager.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/C14NAncestralNamespaceContextManager.cs
new file mode 100644
index 0000000000..48289fa334
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/C14NAncestralNamespaceContextManager.cs
@@ -0,0 +1,100 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the stack of currently active NamespaceFrame contexts. this
+ // object also maintains the inclusive prefix list in a tokenized form.
+ internal class C14NAncestralNamespaceContextManager : AncestralNamespaceContextManager
+ {
+ internal C14NAncestralNamespaceContextManager() { }
+
+ private void GetNamespaceToRender(string nsPrefix, SortedList attrListToRender, SortedList nsListToRender, Hashtable nsLocallyDeclared)
+ {
+ foreach (object a in nsListToRender.GetKeyList())
+ {
+ if (Utils.HasNamespacePrefix((XmlAttribute)a, nsPrefix))
+ return;
+ }
+ foreach (object a in attrListToRender.GetKeyList())
+ {
+ if (((XmlAttribute)a).LocalName.Equals(nsPrefix))
+ return;
+ }
+
+ int rDepth;
+ XmlAttribute local = (XmlAttribute)nsLocallyDeclared[nsPrefix];
+ XmlAttribute rAncestral = GetNearestRenderedNamespaceWithMatchingPrefix(nsPrefix, out rDepth);
+ if (local != null)
+ {
+ if (Utils.IsNonRedundantNamespaceDecl(local, rAncestral))
+ {
+ nsLocallyDeclared.Remove(nsPrefix);
+ if (Utils.IsXmlNamespaceNode(local))
+ attrListToRender.Add(local, null);
+ else
+ nsListToRender.Add(local, null);
+ }
+ }
+ else
+ {
+ int uDepth;
+ XmlAttribute uAncestral = GetNearestUnrenderedNamespaceWithMatchingPrefix(nsPrefix, out uDepth);
+ if (uAncestral != null && uDepth > rDepth && Utils.IsNonRedundantNamespaceDecl(uAncestral, rAncestral))
+ {
+ if (Utils.IsXmlNamespaceNode(uAncestral))
+ attrListToRender.Add(uAncestral, null);
+ else
+ nsListToRender.Add(uAncestral, null);
+ }
+ }
+ }
+
+ internal override void GetNamespacesToRender(XmlElement element, SortedList attrListToRender, SortedList nsListToRender, Hashtable nsLocallyDeclared)
+ {
+ XmlAttribute attrib = null;
+ object[] attrs = new object[nsLocallyDeclared.Count];
+ nsLocallyDeclared.Values.CopyTo(attrs, 0);
+ foreach (object a in attrs)
+ {
+ attrib = (XmlAttribute)a;
+ int rDepth;
+ XmlAttribute rAncestral = GetNearestRenderedNamespaceWithMatchingPrefix(Utils.GetNamespacePrefix(attrib), out rDepth);
+ if (Utils.IsNonRedundantNamespaceDecl(attrib, rAncestral))
+ {
+ nsLocallyDeclared.Remove(Utils.GetNamespacePrefix(attrib));
+ if (Utils.IsXmlNamespaceNode(attrib))
+ attrListToRender.Add(attrib, null);
+ else
+ nsListToRender.Add(attrib, null);
+ }
+ }
+
+ for (int i = _ancestorStack.Count - 1; i >= 0; i--)
+ {
+ foreach (object a in GetScopeAt(i).GetUnrendered().Values)
+ {
+ attrib = (XmlAttribute)a;
+ if (attrib != null)
+ GetNamespaceToRender(Utils.GetNamespacePrefix(attrib), attrListToRender, nsListToRender, nsLocallyDeclared);
+ }
+ }
+ }
+
+ internal override void TrackNamespaceNode(XmlAttribute attr, SortedList nsListToRender, Hashtable nsLocallyDeclared)
+ {
+ nsLocallyDeclared.Add(Utils.GetNamespacePrefix(attr), attr);
+ }
+
+ internal override void TrackXmlNamespaceNode(XmlAttribute attr, SortedList nsListToRender, SortedList attrListToRender, Hashtable nsLocallyDeclared)
+ {
+ nsLocallyDeclared.Add(Utils.GetNamespacePrefix(attr), attr);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXml.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXml.cs
new file mode 100644
index 0000000000..b709767fca
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXml.cs
@@ -0,0 +1,128 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+using System;
+
+namespace System.Security.Cryptography.Xml
+{
+ internal class CanonicalXml
+ {
+ private CanonicalXmlDocument _c14nDoc;
+ private C14NAncestralNamespaceContextManager _ancMgr;
+
+ // private static string defaultXPathWithoutComments = "(//. | //@* | //namespace::*)[not(self::comment())]";
+ // private static string defaultXPathWithoutComments = "(//. | //@* | //namespace::*)";
+ // private static string defaultXPathWithComments = "(//. | //@* | //namespace::*)";
+ // private static string defaultXPathWithComments = "(//. | //@* | //namespace::*)";
+
+ internal CanonicalXml(Stream inputStream, bool includeComments, XmlResolver resolver, string strBaseUri)
+ {
+ if (inputStream == null)
+ throw new ArgumentNullException("inputStream");
+
+ _c14nDoc = new CanonicalXmlDocument(true, includeComments);
+ _c14nDoc.XmlResolver = resolver;
+ _c14nDoc.Load(Utils.PreProcessStreamInput(inputStream, resolver, strBaseUri));
+ _ancMgr = new C14NAncestralNamespaceContextManager();
+ }
+
+ internal CanonicalXml(XmlDocument document, XmlResolver resolver) : this(document, resolver, false) { }
+ internal CanonicalXml(XmlDocument document, XmlResolver resolver, bool includeComments)
+ {
+ if (document == null)
+ throw new ArgumentNullException("document");
+
+ _c14nDoc = new CanonicalXmlDocument(true, includeComments);
+ _c14nDoc.XmlResolver = resolver;
+ _c14nDoc.Load(new XmlNodeReader(document));
+ _ancMgr = new C14NAncestralNamespaceContextManager();
+ }
+
+ internal CanonicalXml(XmlNodeList nodeList, XmlResolver resolver, bool includeComments)
+ {
+ if (nodeList == null)
+ throw new ArgumentNullException("nodeList");
+
+ XmlDocument doc = Utils.GetOwnerDocument(nodeList);
+ if (doc == null)
+ throw new ArgumentException("nodeList");
+
+ _c14nDoc = new CanonicalXmlDocument(false, includeComments);
+ _c14nDoc.XmlResolver = resolver;
+ _c14nDoc.Load(new XmlNodeReader(doc));
+ _ancMgr = new C14NAncestralNamespaceContextManager();
+
+ MarkInclusionStateForNodes(nodeList, doc, _c14nDoc);
+ }
+
+ private static void MarkNodeAsIncluded(XmlNode node)
+ {
+ if (node is ICanonicalizableNode)
+ ((ICanonicalizableNode)node).IsInNodeSet = true;
+ }
+
+ private static void MarkInclusionStateForNodes(XmlNodeList nodeList, XmlDocument inputRoot, XmlDocument root)
+ {
+ CanonicalXmlNodeList elementList = new CanonicalXmlNodeList();
+ CanonicalXmlNodeList elementListCanonical = new CanonicalXmlNodeList();
+ elementList.Add(inputRoot);
+ elementListCanonical.Add(root);
+ int index = 0;
+
+ do
+ {
+ XmlNode currentNode = (XmlNode)elementList[index];
+ XmlNode currentNodeCanonical = (XmlNode)elementListCanonical[index];
+ XmlNodeList childNodes = currentNode.ChildNodes;
+ XmlNodeList childNodesCanonical = currentNodeCanonical.ChildNodes;
+ for (int i = 0; i < childNodes.Count; i++)
+ {
+ elementList.Add(childNodes[i]);
+ elementListCanonical.Add(childNodesCanonical[i]);
+
+ if (Utils.NodeInList(childNodes[i], nodeList))
+ {
+ MarkNodeAsIncluded(childNodesCanonical[i]);
+ }
+
+ XmlAttributeCollection attribNodes = childNodes[i].Attributes;
+ if (attribNodes != null)
+ {
+ for (int j = 0; j < attribNodes.Count; j++)
+ {
+ if (Utils.NodeInList(attribNodes[j], nodeList))
+ {
+ MarkNodeAsIncluded(childNodesCanonical[i].Attributes.Item(j));
+ }
+ }
+ }
+ }
+ index++;
+ } while (index < elementList.Count);
+ }
+
+ internal byte[] GetBytes()
+ {
+ StringBuilder sb = new StringBuilder();
+ _c14nDoc.Write(sb, DocPosition.BeforeRootElement, _ancMgr);
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ return utf8.GetBytes(sb.ToString());
+ }
+
+ internal byte[] GetDigestedBytes(HashAlgorithm hash)
+ {
+ _c14nDoc.WriteHash(hash, DocPosition.BeforeRootElement, _ancMgr);
+ hash.TransformFinalBlock(new byte[0], 0, 0);
+ byte[] res = (byte[])hash.Hash.Clone();
+ // reinitialize the hash so it is still usable after the call
+ hash.Initialize();
+ return res;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlAttribute.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlAttribute.cs
new file mode 100644
index 0000000000..add37e152b
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlAttribute.cs
@@ -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;
+using System.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the class that provides node subset state and canonicalization function to XmlAttribute
+ internal class CanonicalXmlAttribute : XmlAttribute, ICanonicalizableNode
+ {
+ private bool _isInNodeSet;
+
+ public CanonicalXmlAttribute(string prefix, string localName, string namespaceURI, XmlDocument doc, bool defaultNodeSetInclusionState)
+ : base(prefix, localName, namespaceURI, doc)
+ {
+ IsInNodeSet = defaultNodeSetInclusionState;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ strBuilder.Append(" " + Name + "=\"");
+ strBuilder.Append(Utils.EscapeAttributeValue(Value));
+ strBuilder.Append("\"");
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ byte[] rgbData = utf8.GetBytes(" " + Name + "=\"");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ rgbData = utf8.GetBytes(Utils.EscapeAttributeValue(Value));
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ rgbData = utf8.GetBytes("\"");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlCDataSection.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlCDataSection.cs
new file mode 100644
index 0000000000..63fa99da8c
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlCDataSection.cs
@@ -0,0 +1,45 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the class that provides node subset state and canonicalization function to XmlCDataSection
+ internal class CanonicalXmlCDataSection : XmlCDataSection, ICanonicalizableNode
+ {
+ private bool _isInNodeSet;
+ public CanonicalXmlCDataSection(string data, XmlDocument doc, bool defaultNodeSetInclusionState) : base(data, doc)
+ {
+ _isInNodeSet = defaultNodeSetInclusionState;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet)
+ strBuilder.Append(Utils.EscapeCData(Data));
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet)
+ {
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ byte[] rgbData = utf8.GetBytes(Utils.EscapeCData(Data));
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlComment.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlComment.cs
new file mode 100644
index 0000000000..57df4e44a8
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlComment.cs
@@ -0,0 +1,74 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the class that provides node subset state and canonicalization function to XmlComment
+ internal class CanonicalXmlComment : XmlComment, ICanonicalizableNode
+ {
+ private bool _isInNodeSet;
+ private bool _includeComments;
+
+ public CanonicalXmlComment(string comment, XmlDocument doc, bool defaultNodeSetInclusionState, bool includeComments)
+ : base(comment, doc)
+ {
+ _isInNodeSet = defaultNodeSetInclusionState;
+ _includeComments = includeComments;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public bool IncludeComments
+ {
+ get { return _includeComments; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (!IsInNodeSet || !IncludeComments)
+ return;
+
+ if (docPos == DocPosition.AfterRootElement)
+ strBuilder.Append((char)10);
+ strBuilder.Append("<!--");
+ strBuilder.Append(Value);
+ strBuilder.Append("-->");
+ if (docPos == DocPosition.BeforeRootElement)
+ strBuilder.Append((char)10);
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (!IsInNodeSet || !IncludeComments)
+ return;
+
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ byte[] rgbData = utf8.GetBytes("(char) 10");
+ if (docPos == DocPosition.AfterRootElement)
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ rgbData = utf8.GetBytes("<!--");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ rgbData = utf8.GetBytes(Value);
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ rgbData = utf8.GetBytes("-->");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ if (docPos == DocPosition.BeforeRootElement)
+ {
+ rgbData = utf8.GetBytes("(char) 10");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlDocument.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlDocument.cs
new file mode 100644
index 0000000000..ab23277579
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlDocument.cs
@@ -0,0 +1,119 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // all input types eventually lead to the creation of an XmlDocument document
+ // of this type. it maintains the node subset state and performs output rendering during canonicalization
+ internal class CanonicalXmlDocument : XmlDocument, ICanonicalizableNode
+ {
+ private bool _defaultNodeSetInclusionState;
+ private bool _includeComments;
+ private bool _isInNodeSet;
+
+ public CanonicalXmlDocument(bool defaultNodeSetInclusionState, bool includeComments) : base()
+ {
+ PreserveWhitespace = true;
+ _includeComments = includeComments;
+ _isInNodeSet = _defaultNodeSetInclusionState = defaultNodeSetInclusionState;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ docPos = DocPosition.BeforeRootElement;
+ foreach (XmlNode childNode in ChildNodes)
+ {
+ if (childNode.NodeType == XmlNodeType.Element)
+ {
+ CanonicalizationDispatcher.Write(childNode, strBuilder, DocPosition.InRootElement, anc);
+ docPos = DocPosition.AfterRootElement;
+ }
+ else
+ {
+ CanonicalizationDispatcher.Write(childNode, strBuilder, docPos, anc);
+ }
+ }
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ docPos = DocPosition.BeforeRootElement;
+ foreach (XmlNode childNode in ChildNodes)
+ {
+ if (childNode.NodeType == XmlNodeType.Element)
+ {
+ CanonicalizationDispatcher.WriteHash(childNode, hash, DocPosition.InRootElement, anc);
+ docPos = DocPosition.AfterRootElement;
+ }
+ else
+ {
+ CanonicalizationDispatcher.WriteHash(childNode, hash, docPos, anc);
+ }
+ }
+ }
+
+ public override XmlElement CreateElement(string prefix, string localName, string namespaceURI)
+ {
+ return new CanonicalXmlElement(prefix, localName, namespaceURI, this, _defaultNodeSetInclusionState);
+ }
+
+ public override XmlAttribute CreateAttribute(string prefix, string localName, string namespaceURI)
+ {
+ return new CanonicalXmlAttribute(prefix, localName, namespaceURI, this, _defaultNodeSetInclusionState);
+ }
+
+ protected override XmlAttribute CreateDefaultAttribute(string prefix, string localName, string namespaceURI)
+ {
+ return new CanonicalXmlAttribute(prefix, localName, namespaceURI, this, _defaultNodeSetInclusionState);
+ }
+
+ public override XmlText CreateTextNode(string text)
+ {
+ return new CanonicalXmlText(text, this, _defaultNodeSetInclusionState);
+ }
+
+ public override XmlWhitespace CreateWhitespace(string prefix)
+ {
+ return new CanonicalXmlWhitespace(prefix, this, _defaultNodeSetInclusionState);
+ }
+
+ public override XmlSignificantWhitespace CreateSignificantWhitespace(string text)
+ {
+ return new CanonicalXmlSignificantWhitespace(text, this, _defaultNodeSetInclusionState);
+ }
+
+ public override XmlProcessingInstruction CreateProcessingInstruction(string target, string data)
+ {
+ return new CanonicalXmlProcessingInstruction(target, data, this, _defaultNodeSetInclusionState);
+ }
+
+ public override XmlComment CreateComment(string data)
+ {
+ return new CanonicalXmlComment(data, this, _defaultNodeSetInclusionState, _includeComments);
+ }
+
+ public override XmlEntityReference CreateEntityReference(string name)
+ {
+ return new CanonicalXmlEntityReference(name, this, _defaultNodeSetInclusionState);
+ }
+
+ public override XmlCDataSection CreateCDataSection(string data)
+ {
+ return new CanonicalXmlCDataSection(data, this, _defaultNodeSetInclusionState);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlElement.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlElement.cs
new file mode 100644
index 0000000000..98dea2df63
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlElement.cs
@@ -0,0 +1,177 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the class that provides node subset state and canonicalization function to XmlElement
+ internal class CanonicalXmlElement : XmlElement, ICanonicalizableNode
+ {
+ private bool _isInNodeSet;
+
+ public CanonicalXmlElement(string prefix, string localName, string namespaceURI, XmlDocument doc, bool defaultNodeSetInclusionState)
+ : base(prefix, localName, namespaceURI, doc)
+ {
+ _isInNodeSet = defaultNodeSetInclusionState;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ Hashtable nsLocallyDeclared = new Hashtable();
+ SortedList nsListToRender = new SortedList(new NamespaceSortOrder());
+ SortedList attrListToRender = new SortedList(new AttributeSortOrder());
+
+ XmlAttributeCollection attrList = Attributes;
+ if (attrList != null)
+ {
+ foreach (XmlAttribute attr in attrList)
+ {
+ if (((CanonicalXmlAttribute)attr).IsInNodeSet || Utils.IsNamespaceNode(attr) || Utils.IsXmlNamespaceNode(attr))
+ {
+ if (Utils.IsNamespaceNode(attr))
+ {
+ anc.TrackNamespaceNode(attr, nsListToRender, nsLocallyDeclared);
+ }
+ else if (Utils.IsXmlNamespaceNode(attr))
+ {
+ anc.TrackXmlNamespaceNode(attr, nsListToRender, attrListToRender, nsLocallyDeclared);
+ }
+ else if (IsInNodeSet)
+ {
+ attrListToRender.Add(attr, null);
+ }
+ }
+ }
+ }
+
+ if (!Utils.IsCommittedNamespace(this, Prefix, NamespaceURI))
+ {
+ string name = ((Prefix.Length > 0) ? "xmlns" + ":" + Prefix : "xmlns");
+ XmlAttribute nsattrib = (XmlAttribute)OwnerDocument.CreateAttribute(name);
+ nsattrib.Value = NamespaceURI;
+ anc.TrackNamespaceNode(nsattrib, nsListToRender, nsLocallyDeclared);
+ }
+
+ if (IsInNodeSet)
+ {
+ anc.GetNamespacesToRender(this, attrListToRender, nsListToRender, nsLocallyDeclared);
+
+ strBuilder.Append("<" + Name);
+ foreach (object attr in nsListToRender.GetKeyList())
+ {
+ (attr as CanonicalXmlAttribute).Write(strBuilder, docPos, anc);
+ }
+ foreach (object attr in attrListToRender.GetKeyList())
+ {
+ (attr as CanonicalXmlAttribute).Write(strBuilder, docPos, anc);
+ }
+ strBuilder.Append(">");
+ }
+
+ anc.EnterElementContext();
+ anc.LoadUnrenderedNamespaces(nsLocallyDeclared);
+ anc.LoadRenderedNamespaces(nsListToRender);
+
+ XmlNodeList childNodes = ChildNodes;
+ foreach (XmlNode childNode in childNodes)
+ {
+ CanonicalizationDispatcher.Write(childNode, strBuilder, docPos, anc);
+ }
+
+ anc.ExitElementContext();
+
+ if (IsInNodeSet)
+ {
+ strBuilder.Append("</" + Name + ">");
+ }
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ Hashtable nsLocallyDeclared = new Hashtable();
+ SortedList nsListToRender = new SortedList(new NamespaceSortOrder());
+ SortedList attrListToRender = new SortedList(new AttributeSortOrder());
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ byte[] rgbData;
+
+ XmlAttributeCollection attrList = Attributes;
+ if (attrList != null)
+ {
+ foreach (XmlAttribute attr in attrList)
+ {
+ if (((CanonicalXmlAttribute)attr).IsInNodeSet || Utils.IsNamespaceNode(attr) || Utils.IsXmlNamespaceNode(attr))
+ {
+ if (Utils.IsNamespaceNode(attr))
+ {
+ anc.TrackNamespaceNode(attr, nsListToRender, nsLocallyDeclared);
+ }
+ else if (Utils.IsXmlNamespaceNode(attr))
+ {
+ anc.TrackXmlNamespaceNode(attr, nsListToRender, attrListToRender, nsLocallyDeclared);
+ }
+ else if (IsInNodeSet)
+ {
+ attrListToRender.Add(attr, null);
+ }
+ }
+ }
+ }
+
+ if (!Utils.IsCommittedNamespace(this, Prefix, NamespaceURI))
+ {
+ string name = ((Prefix.Length > 0) ? "xmlns" + ":" + Prefix : "xmlns");
+ XmlAttribute nsattrib = (XmlAttribute)OwnerDocument.CreateAttribute(name);
+ nsattrib.Value = NamespaceURI;
+ anc.TrackNamespaceNode(nsattrib, nsListToRender, nsLocallyDeclared);
+ }
+
+ if (IsInNodeSet)
+ {
+ anc.GetNamespacesToRender(this, attrListToRender, nsListToRender, nsLocallyDeclared);
+ rgbData = utf8.GetBytes("<" + Name);
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ foreach (object attr in nsListToRender.GetKeyList())
+ {
+ (attr as CanonicalXmlAttribute).WriteHash(hash, docPos, anc);
+ }
+ foreach (object attr in attrListToRender.GetKeyList())
+ {
+ (attr as CanonicalXmlAttribute).WriteHash(hash, docPos, anc);
+ }
+ rgbData = utf8.GetBytes(">");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+
+ anc.EnterElementContext();
+ anc.LoadUnrenderedNamespaces(nsLocallyDeclared);
+ anc.LoadRenderedNamespaces(nsListToRender);
+
+ XmlNodeList childNodes = ChildNodes;
+ foreach (XmlNode childNode in childNodes)
+ {
+ CanonicalizationDispatcher.WriteHash(childNode, hash, docPos, anc);
+ }
+
+ anc.ExitElementContext();
+
+ if (IsInNodeSet)
+ {
+ rgbData = utf8.GetBytes("</" + Name + ">");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlEntityReference.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlEntityReference.cs
new file mode 100644
index 0000000000..fc03daf056
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlEntityReference.cs
@@ -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;
+using System.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the class that provides node subset state and canonicalization function to XmlEntityReference
+ internal class CanonicalXmlEntityReference : XmlEntityReference, ICanonicalizableNode
+ {
+ private bool _isInNodeSet;
+
+ public CanonicalXmlEntityReference(string name, XmlDocument doc, bool defaultNodeSetInclusionState)
+ : base(name, doc)
+ {
+ _isInNodeSet = defaultNodeSetInclusionState;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet)
+ CanonicalizationDispatcher.WriteGenericNode(this, strBuilder, docPos, anc);
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet)
+ CanonicalizationDispatcher.WriteHashGenericNode(this, hash, docPos, anc);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlNodeList.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlNodeList.cs
new file mode 100644
index 0000000000..fa6ac76918
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlNodeList.cs
@@ -0,0 +1,113 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+
+namespace System.Security.Cryptography.Xml
+{
+ internal class CanonicalXmlNodeList : XmlNodeList, IList
+ {
+ private ArrayList _nodeArray;
+
+ internal CanonicalXmlNodeList()
+ {
+ _nodeArray = new ArrayList();
+ }
+
+ public override XmlNode Item(int index)
+ {
+ return (XmlNode)_nodeArray[index];
+ }
+
+ public override IEnumerator GetEnumerator()
+ {
+ return _nodeArray.GetEnumerator();
+ }
+
+ public override int Count
+ {
+ get { return _nodeArray.Count; }
+ }
+
+ // IList methods
+ public int Add(object value)
+ {
+ if (!(value is XmlNode))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "node");
+ return _nodeArray.Add(value);
+ }
+
+ public void Clear()
+ {
+ _nodeArray.Clear();
+ }
+
+ public bool Contains(object value)
+ {
+ return _nodeArray.Contains(value);
+ }
+
+ public int IndexOf(object value)
+ {
+ return _nodeArray.IndexOf(value);
+ }
+
+ public void Insert(int index, object value)
+ {
+ if (!(value is XmlNode))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+ _nodeArray.Insert(index, value);
+ }
+
+ public void Remove(object value)
+ {
+ _nodeArray.Remove(value);
+ }
+
+ public void RemoveAt(int index)
+ {
+ _nodeArray.RemoveAt(index);
+ }
+
+ public bool IsFixedSize
+ {
+ get { return _nodeArray.IsFixedSize; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return _nodeArray.IsReadOnly; }
+ }
+
+ object IList.this[int index]
+ {
+ get { return _nodeArray[index]; }
+ set
+ {
+ if (!(value is XmlNode))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+ _nodeArray[index] = value;
+ }
+ }
+
+ public void CopyTo(Array array, int index)
+ {
+ _nodeArray.CopyTo(array, index);
+ }
+
+ public object SyncRoot
+ {
+ get { return _nodeArray.SyncRoot; }
+ }
+
+ public bool IsSynchronized
+ {
+ get { return _nodeArray.IsSynchronized; }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlProcessingInstruction.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlProcessingInstruction.cs
new file mode 100644
index 0000000000..a424c572af
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlProcessingInstruction.cs
@@ -0,0 +1,77 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the class that provides node subset state and canonicalization function to XmlProcessingInstruction
+ internal class CanonicalXmlProcessingInstruction : XmlProcessingInstruction, ICanonicalizableNode
+ {
+ private bool _isInNodeSet;
+
+ public CanonicalXmlProcessingInstruction(string target, string data, XmlDocument doc, bool defaultNodeSetInclusionState)
+ : base(target, data, doc)
+ {
+ _isInNodeSet = defaultNodeSetInclusionState;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (!IsInNodeSet)
+ return;
+
+ if (docPos == DocPosition.AfterRootElement)
+ strBuilder.Append((char)10);
+ strBuilder.Append("<?");
+ strBuilder.Append(Name);
+ if ((Value != null) && (Value.Length > 0))
+ strBuilder.Append(" " + Value);
+ strBuilder.Append("?>");
+ if (docPos == DocPosition.BeforeRootElement)
+ strBuilder.Append((char)10);
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (!IsInNodeSet)
+ return;
+
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ byte[] rgbData;
+ if (docPos == DocPosition.AfterRootElement)
+ {
+ rgbData = utf8.GetBytes("(char) 10");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ rgbData = utf8.GetBytes("<?");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ rgbData = utf8.GetBytes((Name));
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ if ((Value != null) && (Value.Length > 0))
+ {
+ rgbData = utf8.GetBytes(" " + Value);
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ rgbData = utf8.GetBytes("?>");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ if (docPos == DocPosition.BeforeRootElement)
+ {
+ rgbData = utf8.GetBytes("(char) 10");
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlSignificantWhitespace.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlSignificantWhitespace.cs
new file mode 100644
index 0000000000..1715018bac
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlSignificantWhitespace.cs
@@ -0,0 +1,47 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the class that provides node subset state and canonicalization function to XmlSignificantWhitespace
+ internal class CanonicalXmlSignificantWhitespace : XmlSignificantWhitespace, ICanonicalizableNode
+ {
+ private bool _isInNodeSet;
+
+ public CanonicalXmlSignificantWhitespace(string strData, XmlDocument doc, bool defaultNodeSetInclusionState)
+ : base(strData, doc)
+ {
+ _isInNodeSet = defaultNodeSetInclusionState;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet && docPos == DocPosition.InRootElement)
+ strBuilder.Append(Utils.EscapeWhitespaceData(Value));
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet && docPos == DocPosition.InRootElement)
+ {
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ byte[] rgbData = utf8.GetBytes(Utils.EscapeWhitespaceData(Value));
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlText.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlText.cs
new file mode 100644
index 0000000000..c8e07d9b72
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlText.cs
@@ -0,0 +1,47 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the class that provides node subset state and canonicalization function to XmlText
+ internal class CanonicalXmlText : XmlText, ICanonicalizableNode
+ {
+ private bool _isInNodeSet;
+
+ public CanonicalXmlText(string strData, XmlDocument doc, bool defaultNodeSetInclusionState)
+ : base(strData, doc)
+ {
+ _isInNodeSet = defaultNodeSetInclusionState;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet)
+ strBuilder.Append(Utils.EscapeTextData(Value));
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet)
+ {
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ byte[] rgbData = utf8.GetBytes(Utils.EscapeTextData(Value));
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlWhitespace.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlWhitespace.cs
new file mode 100644
index 0000000000..b620e563bb
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalXmlWhitespace.cs
@@ -0,0 +1,47 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the class that provides node subset state and canonicalization function to XmlWhitespace
+ internal class CanonicalXmlWhitespace : XmlWhitespace, ICanonicalizableNode
+ {
+ private bool _isInNodeSet;
+
+ public CanonicalXmlWhitespace(string strData, XmlDocument doc, bool defaultNodeSetInclusionState)
+ : base(strData, doc)
+ {
+ _isInNodeSet = defaultNodeSetInclusionState;
+ }
+
+ public bool IsInNodeSet
+ {
+ get { return _isInNodeSet; }
+ set { _isInNodeSet = value; }
+ }
+
+ public void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet && docPos == DocPosition.InRootElement)
+ strBuilder.Append(Utils.EscapeWhitespaceData(Value));
+ }
+
+ public void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (IsInNodeSet && docPos == DocPosition.InRootElement)
+ {
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ byte[] rgbData = utf8.GetBytes(Utils.EscapeWhitespaceData(Value));
+ hash.TransformBlock(rgbData, 0, rgbData.Length, rgbData, 0);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalizationDispatcher.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalizationDispatcher.cs
new file mode 100644
index 0000000000..150b5d8e61
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CanonicalizationDispatcher.cs
@@ -0,0 +1,68 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the central dispatcher for canonicalization writes. not all node classes
+ // implement ICanonicalizableNode; so a manual dispatch is sometimes necessary.
+ internal class CanonicalizationDispatcher
+ {
+ private CanonicalizationDispatcher() { }
+
+ public static void Write(XmlNode node, StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (node is ICanonicalizableNode)
+ {
+ ((ICanonicalizableNode)node).Write(strBuilder, docPos, anc);
+ }
+ else
+ {
+ WriteGenericNode(node, strBuilder, docPos, anc);
+ }
+ }
+
+ public static void WriteGenericNode(XmlNode node, StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (node == null)
+ throw new ArgumentNullException("node");
+
+ XmlNodeList childNodes = node.ChildNodes;
+ foreach (XmlNode childNode in childNodes)
+ {
+ Write(childNode, strBuilder, docPos, anc);
+ }
+ }
+
+ public static void WriteHash(XmlNode node, HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (node is ICanonicalizableNode)
+ {
+ ((ICanonicalizableNode)node).WriteHash(hash, docPos, anc);
+ }
+ else
+ {
+ WriteHashGenericNode(node, hash, docPos, anc);
+ }
+ }
+
+ public static void WriteHashGenericNode(XmlNode node, HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc)
+ {
+ if (node == null)
+ throw new ArgumentNullException("node");
+
+ XmlNodeList childNodes = node.ChildNodes;
+ foreach (XmlNode childNode in childNodes)
+ {
+ WriteHash(childNode, hash, docPos, anc);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CertUsageType.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CertUsageType.cs
new file mode 100644
index 0000000000..aa0ab16d9d
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CertUsageType.cs
@@ -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.
+
+using Microsoft.Win32;
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Permissions;
+using System.Text;
+using System.Threading;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ [Serializable]
+ internal enum CertUsageType
+ {
+ Verification = 0,
+ Decryption = 1
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherData.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherData.cs
new file mode 100644
index 0000000000..ad741470ba
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherData.cs
@@ -0,0 +1,126 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public sealed class CipherData
+ {
+ private XmlElement _cachedXml = null;
+ private CipherReference _cipherReference = null;
+ private byte[] _cipherValue = null;
+
+ public CipherData() { }
+
+ public CipherData(byte[] cipherValue)
+ {
+ CipherValue = cipherValue;
+ }
+
+ public CipherData(CipherReference cipherReference)
+ {
+ CipherReference = cipherReference;
+ }
+
+ private bool CacheValid
+ {
+ get
+ {
+ return (_cachedXml != null);
+ }
+ }
+
+ public CipherReference CipherReference
+ {
+ get { return _cipherReference; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ if (CipherValue != null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CipherValueElementRequired"));
+
+ _cipherReference = value;
+ _cachedXml = null;
+ }
+ }
+
+ public byte[] CipherValue
+ {
+ get { return _cipherValue; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ if (CipherReference != null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CipherValueElementRequired"));
+
+ _cipherValue = (byte[])value.Clone();
+ _cachedXml = null;
+ }
+ }
+
+ public XmlElement GetXml()
+ {
+ if (CacheValid) return _cachedXml;
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ // Create the CipherData element
+ XmlElement cipherDataElement = (XmlElement)document.CreateElement("CipherData", EncryptedXml.XmlEncNamespaceUrl);
+ if (CipherValue != null)
+ {
+ XmlElement cipherValueElement = document.CreateElement("CipherValue", EncryptedXml.XmlEncNamespaceUrl);
+ cipherValueElement.AppendChild(document.CreateTextNode(Convert.ToBase64String(CipherValue)));
+ cipherDataElement.AppendChild(cipherValueElement);
+ }
+ else
+ {
+ // No CipherValue specified, see if there is a CipherReference
+ if (CipherReference == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CipherValueElementRequired"));
+ cipherDataElement.AppendChild(CipherReference.GetXml(document));
+ }
+ return cipherDataElement;
+ }
+
+ public void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+
+ XmlNode cipherValueNode = value.SelectSingleNode("enc:CipherValue", nsm);
+ XmlNode cipherReferenceNode = value.SelectSingleNode("enc:CipherReference", nsm);
+ if (cipherValueNode != null)
+ {
+ if (cipherReferenceNode != null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CipherValueElementRequired"));
+ _cipherValue = Convert.FromBase64String(Utils.DiscardWhiteSpaces(cipherValueNode.InnerText));
+ }
+ else if (cipherReferenceNode != null)
+ {
+ _cipherReference = new CipherReference();
+ _cipherReference.LoadXml((XmlElement)cipherReferenceNode);
+ }
+ else
+ {
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CipherValueElementRequired"));
+ }
+
+ // Save away the cached value
+ _cachedXml = value;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherReference.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherReference.cs
new file mode 100644
index 0000000000..6449912b64
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherReference.cs
@@ -0,0 +1,90 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public sealed class CipherReference : EncryptedReference
+ {
+ private byte[] _cipherValue;
+
+ public CipherReference() : base()
+ {
+ ReferenceType = "CipherReference";
+ }
+
+ public CipherReference(string uri) : base(uri)
+ {
+ ReferenceType = "CipherReference";
+ }
+
+ public CipherReference(string uri, TransformChain transformChain) : base(uri, transformChain)
+ {
+ ReferenceType = "CipherReference";
+ }
+
+ // This method is used to cache results from resolved cipher references.
+ internal byte[] CipherValue
+ {
+ get
+ {
+ if (!CacheValid)
+ return null;
+ return _cipherValue;
+ }
+ set
+ {
+ _cipherValue = value;
+ }
+ }
+
+ public override XmlElement GetXml()
+ {
+ if (CacheValid) return _cachedXml;
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ new internal XmlElement GetXml(XmlDocument document)
+ {
+ if (ReferenceType == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_ReferenceTypeRequired"));
+
+ // Create the Reference
+ XmlElement referenceElement = document.CreateElement(ReferenceType, EncryptedXml.XmlEncNamespaceUrl);
+ if (!string.IsNullOrEmpty(Uri))
+ referenceElement.SetAttribute("URI", Uri);
+
+ // Add the transforms to the CipherReference
+ if (TransformChain.Count > 0)
+ referenceElement.AppendChild(TransformChain.GetXml(document, EncryptedXml.XmlEncNamespaceUrl));
+
+ return referenceElement;
+ }
+
+ public override void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ ReferenceType = value.LocalName;
+ Uri = Utils.GetAttribute(value, "URI", EncryptedXml.XmlEncNamespaceUrl);
+
+ // Transforms
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+ XmlNode transformsNode = value.SelectSingleNode("enc:Transforms", nsm);
+ if (transformsNode != null)
+ TransformChain.LoadXml(transformsNode as XmlElement);
+
+ // cache the Xml
+ _cachedXml = value;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoSignedXmlRecursionException.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoSignedXmlRecursionException.cs
new file mode 100644
index 0000000000..fcfd5fb346
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoSignedXmlRecursionException.cs
@@ -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;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ /// <summary>
+ /// This exception helps catch the signed XML recursion limit error.
+ /// This is being caught in the SignedXml class while computing the
+ /// hash. ComputeHash can throw different kind of exceptions.
+ /// This unique exception helps catch the recursion limit issue.
+ /// </summary>
+ [Serializable]
+ internal class CryptoSignedXmlRecursionException : XmlException
+ {
+ public CryptoSignedXmlRecursionException() : base() { }
+ public CryptoSignedXmlRecursionException(string message) : base(message) { }
+ public CryptoSignedXmlRecursionException(string message, System.Exception inner) : base(message, inner) { }
+ // A constructor is needed for serialization when an
+ // exception propagates from a remoting server to the client.
+ protected CryptoSignedXmlRecursionException(System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context)
+ { }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs
new file mode 100644
index 0000000000..283f6c4dac
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs
@@ -0,0 +1,107 @@
+// 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.Collections;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class DSAKeyValue : KeyInfoClause
+ {
+ private DSA _key;
+
+ //
+ // public constructors
+ //
+
+ public DSAKeyValue()
+ {
+ _key = DSA.Create();
+ }
+
+ public DSAKeyValue(DSA key)
+ {
+ _key = key;
+ }
+
+ //
+ // public properties
+ //
+
+ public DSA Key
+ {
+ get { return _key; }
+ set { _key = value; }
+ }
+
+ //
+ // public methods
+ //
+
+ public override XmlElement GetXml()
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.PreserveWhitespace = true;
+ return GetXml(xmlDocument);
+ }
+
+ internal override XmlElement GetXml(XmlDocument xmlDocument)
+ {
+ DSAParameters dsaParams = _key.ExportParameters(false);
+
+ XmlElement keyValueElement = xmlDocument.CreateElement("KeyValue", SignedXml.XmlDsigNamespaceUrl);
+ XmlElement dsaKeyValueElement = xmlDocument.CreateElement("DSAKeyValue", SignedXml.XmlDsigNamespaceUrl);
+
+ XmlElement pElement = xmlDocument.CreateElement("P", SignedXml.XmlDsigNamespaceUrl);
+ pElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(dsaParams.P)));
+ dsaKeyValueElement.AppendChild(pElement);
+
+ XmlElement qElement = xmlDocument.CreateElement("Q", SignedXml.XmlDsigNamespaceUrl);
+ qElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(dsaParams.Q)));
+ dsaKeyValueElement.AppendChild(qElement);
+
+ XmlElement gElement = xmlDocument.CreateElement("G", SignedXml.XmlDsigNamespaceUrl);
+ gElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(dsaParams.G)));
+ dsaKeyValueElement.AppendChild(gElement);
+
+ XmlElement yElement = xmlDocument.CreateElement("Y", SignedXml.XmlDsigNamespaceUrl);
+ yElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(dsaParams.Y)));
+ dsaKeyValueElement.AppendChild(yElement);
+
+ // Add optional components if present
+ if (dsaParams.J != null)
+ {
+ XmlElement jElement = xmlDocument.CreateElement("J", SignedXml.XmlDsigNamespaceUrl);
+ jElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(dsaParams.J)));
+ dsaKeyValueElement.AppendChild(jElement);
+ }
+
+ if (dsaParams.Seed != null)
+ { // note we assume counter is correct if Seed is present
+ XmlElement seedElement = xmlDocument.CreateElement("Seed", SignedXml.XmlDsigNamespaceUrl);
+ seedElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(dsaParams.Seed)));
+ dsaKeyValueElement.AppendChild(seedElement);
+
+ XmlElement counterElement = xmlDocument.CreateElement("PgenCounter", SignedXml.XmlDsigNamespaceUrl);
+ counterElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(Utils.ConvertIntToByteArray(dsaParams.Counter))));
+ dsaKeyValueElement.AppendChild(counterElement);
+ }
+
+ keyValueElement.AppendChild(dsaKeyValueElement);
+
+ return keyValueElement;
+ }
+
+ public override void LoadXml(XmlElement value)
+ {
+ // Until DSA implements FromXmlString, throw here
+ throw new PlatformNotSupportedException();
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DataObject.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DataObject.cs
new file mode 100644
index 0000000000..67390a9ba1
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DataObject.cs
@@ -0,0 +1,155 @@
+// 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.IO;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class DataObject
+ {
+ private string _id;
+ private string _mimeType;
+ private string _encoding;
+ private CanonicalXmlNodeList _elData;
+ private XmlElement _cachedXml;
+
+ //
+ // public constructors
+ //
+
+ public DataObject()
+ {
+ _cachedXml = null;
+ _elData = new CanonicalXmlNodeList();
+ }
+
+ public DataObject(string id, string mimeType, string encoding, XmlElement data)
+ {
+ if (data == null)
+ throw new ArgumentNullException("data");
+
+ _id = id;
+ _mimeType = mimeType;
+ _encoding = encoding;
+ _elData = new CanonicalXmlNodeList();
+ _elData.Add(data);
+ _cachedXml = null;
+ }
+
+ //
+ // public properties
+ //
+
+ public string Id
+ {
+ get { return _id; }
+ set
+ {
+ _id = value;
+ _cachedXml = null;
+ }
+ }
+
+ public string MimeType
+ {
+ get { return _mimeType; }
+ set
+ {
+ _mimeType = value;
+ _cachedXml = null;
+ }
+ }
+
+ public string Encoding
+ {
+ get { return _encoding; }
+ set
+ {
+ _encoding = value;
+ _cachedXml = null;
+ }
+ }
+
+ public XmlNodeList Data
+ {
+ get { return _elData; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ // Reset the node list
+ _elData = new CanonicalXmlNodeList();
+ foreach (XmlNode node in value)
+ {
+ _elData.Add(node);
+ }
+ _cachedXml = null;
+ }
+ }
+
+ private bool CacheValid
+ {
+ get
+ {
+ return (_cachedXml != null);
+ }
+ }
+
+ //
+ // public methods
+ //
+
+ public XmlElement GetXml()
+ {
+ if (CacheValid) return (_cachedXml);
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ XmlElement objectElement = document.CreateElement("Object", SignedXml.XmlDsigNamespaceUrl);
+
+ if (!string.IsNullOrEmpty(_id))
+ objectElement.SetAttribute("Id", _id);
+ if (!string.IsNullOrEmpty(_mimeType))
+ objectElement.SetAttribute("MimeType", _mimeType);
+ if (!string.IsNullOrEmpty(_encoding))
+ objectElement.SetAttribute("Encoding", _encoding);
+
+ if (_elData != null)
+ {
+ foreach (XmlNode node in _elData)
+ {
+ objectElement.AppendChild(document.ImportNode(node, true));
+ }
+ }
+
+ return objectElement;
+ }
+
+ public void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _id = Utils.GetAttribute(value, "Id", SignedXml.XmlDsigNamespaceUrl);
+ _mimeType = Utils.GetAttribute(value, "MimeType", SignedXml.XmlDsigNamespaceUrl);
+ _encoding = Utils.GetAttribute(value, "Encoding", SignedXml.XmlDsigNamespaceUrl);
+
+ foreach (XmlNode node in value.ChildNodes)
+ {
+ _elData.Add(node);
+ }
+
+ // Save away the cached value
+ _cachedXml = value;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DataReference.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DataReference.cs
new file mode 100644
index 0000000000..b2af1fbcf8
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DataReference.cs
@@ -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;
+using System.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public sealed class DataReference : EncryptedReference
+ {
+ public DataReference() : base()
+ {
+ ReferenceType = "DataReference";
+ }
+
+ public DataReference(string uri) : base(uri)
+ {
+ ReferenceType = "DataReference";
+ }
+
+ public DataReference(string uri, TransformChain transformChain) : base(uri, transformChain)
+ {
+ ReferenceType = "DataReference";
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DocPosition.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DocPosition.cs
new file mode 100644
index 0000000000..7472e29743
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DocPosition.cs
@@ -0,0 +1,16 @@
+// 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;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the current rendering position in document
+ internal enum DocPosition
+ {
+ BeforeRootElement,
+ InRootElement,
+ AfterRootElement
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedData.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedData.cs
new file mode 100644
index 0000000000..ba9dc78a3a
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedData.cs
@@ -0,0 +1,120 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public sealed class EncryptedData : EncryptedType
+ {
+ public override void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+ nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
+
+ Id = Utils.GetAttribute(value, "Id", EncryptedXml.XmlEncNamespaceUrl);
+ Type = Utils.GetAttribute(value, "Type", EncryptedXml.XmlEncNamespaceUrl);
+ MimeType = Utils.GetAttribute(value, "MimeType", EncryptedXml.XmlEncNamespaceUrl);
+ Encoding = Utils.GetAttribute(value, "Encoding", EncryptedXml.XmlEncNamespaceUrl);
+
+ XmlNode encryptionMethodNode = value.SelectSingleNode("enc:EncryptionMethod", nsm);
+
+ // EncryptionMethod
+ EncryptionMethod = new EncryptionMethod();
+ if (encryptionMethodNode != null)
+ EncryptionMethod.LoadXml(encryptionMethodNode as XmlElement);
+
+ // Key Info
+ KeyInfo = new KeyInfo();
+ XmlNode keyInfoNode = value.SelectSingleNode("ds:KeyInfo", nsm);
+ if (keyInfoNode != null)
+ KeyInfo.LoadXml(keyInfoNode as XmlElement);
+
+ // CipherData
+ XmlNode cipherDataNode = value.SelectSingleNode("enc:CipherData", nsm);
+ if (cipherDataNode == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingCipherData"));
+
+ CipherData = new CipherData();
+ CipherData.LoadXml(cipherDataNode as XmlElement);
+
+ // EncryptionProperties
+ XmlNode encryptionPropertiesNode = value.SelectSingleNode("enc:EncryptionProperties", nsm);
+ if (encryptionPropertiesNode != null)
+ {
+ // Select the EncryptionProperty elements inside the EncryptionProperties element
+ XmlNodeList encryptionPropertyNodes = encryptionPropertiesNode.SelectNodes("enc:EncryptionProperty", nsm);
+ if (encryptionPropertyNodes != null)
+ {
+ foreach (XmlNode node in encryptionPropertyNodes)
+ {
+ EncryptionProperty ep = new EncryptionProperty();
+ ep.LoadXml(node as XmlElement);
+ EncryptionProperties.Add(ep);
+ }
+ }
+ }
+
+ // Save away the cached value
+ _cachedXml = value;
+ }
+
+ public override XmlElement GetXml()
+ {
+ if (CacheValid) return (_cachedXml);
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ // Create the EncryptedData element
+ XmlElement encryptedDataElement = (XmlElement)document.CreateElement("EncryptedData", EncryptedXml.XmlEncNamespaceUrl);
+
+ // Deal with attributes
+ if (!string.IsNullOrEmpty(Id))
+ encryptedDataElement.SetAttribute("Id", Id);
+ if (!string.IsNullOrEmpty(Type))
+ encryptedDataElement.SetAttribute("Type", Type);
+ if (!string.IsNullOrEmpty(MimeType))
+ encryptedDataElement.SetAttribute("MimeType", MimeType);
+ if (!string.IsNullOrEmpty(Encoding))
+ encryptedDataElement.SetAttribute("Encoding", Encoding);
+
+ // EncryptionMethod
+ if (EncryptionMethod != null)
+ encryptedDataElement.AppendChild(EncryptionMethod.GetXml(document));
+
+ // KeyInfo
+ if (KeyInfo.Count > 0)
+ encryptedDataElement.AppendChild(KeyInfo.GetXml(document));
+
+ // CipherData is required.
+ if (CipherData == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingCipherData"));
+ encryptedDataElement.AppendChild(CipherData.GetXml(document));
+
+ // EncryptionProperties
+ if (EncryptionProperties.Count > 0)
+ {
+ XmlElement encryptionPropertiesElement = document.CreateElement("EncryptionProperties", EncryptedXml.XmlEncNamespaceUrl);
+ for (int index = 0; index < EncryptionProperties.Count; index++)
+ {
+ EncryptionProperty ep = EncryptionProperties.Item(index);
+ encryptionPropertiesElement.AppendChild(ep.GetXml(document));
+ }
+ encryptedDataElement.AppendChild(encryptionPropertiesElement);
+ }
+ return encryptedDataElement;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedKey.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedKey.cs
new file mode 100644
index 0000000000..bcbce160d7
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedKey.cs
@@ -0,0 +1,231 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public sealed class EncryptedKey : EncryptedType
+ {
+ private string _recipient;
+ private string _carriedKeyName;
+ private ReferenceList _referenceList;
+
+ public EncryptedKey() { }
+
+ public string Recipient
+ {
+ get
+ {
+ // an unspecified value for an XmlAttribute is string.Empty
+ if (_recipient == null)
+ _recipient = string.Empty;
+ return _recipient;
+ }
+ set
+ {
+ _recipient = value;
+ _cachedXml = null;
+ }
+ }
+
+ public string CarriedKeyName
+ {
+ get { return _carriedKeyName; }
+ set
+ {
+ _carriedKeyName = value;
+ _cachedXml = null;
+ }
+ }
+
+ public ReferenceList ReferenceList
+ {
+ get
+ {
+ if (_referenceList == null)
+ _referenceList = new ReferenceList();
+ return _referenceList;
+ }
+ }
+
+ public void AddReference(DataReference dataReference)
+ {
+ ReferenceList.Add(dataReference);
+ }
+
+ public void AddReference(KeyReference keyReference)
+ {
+ ReferenceList.Add(keyReference);
+ }
+
+ public override void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+ nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
+
+ Id = Utils.GetAttribute(value, "Id", EncryptedXml.XmlEncNamespaceUrl);
+ Type = Utils.GetAttribute(value, "Type", EncryptedXml.XmlEncNamespaceUrl);
+ MimeType = Utils.GetAttribute(value, "MimeType", EncryptedXml.XmlEncNamespaceUrl);
+ Encoding = Utils.GetAttribute(value, "Encoding", EncryptedXml.XmlEncNamespaceUrl);
+ Recipient = Utils.GetAttribute(value, "Recipient", EncryptedXml.XmlEncNamespaceUrl);
+
+ XmlNode encryptionMethodNode = value.SelectSingleNode("enc:EncryptionMethod", nsm);
+
+ // EncryptionMethod
+ EncryptionMethod = new EncryptionMethod();
+ if (encryptionMethodNode != null)
+ EncryptionMethod.LoadXml(encryptionMethodNode as XmlElement);
+
+ // Key Info
+ KeyInfo = new KeyInfo();
+ XmlNode keyInfoNode = value.SelectSingleNode("ds:KeyInfo", nsm);
+ if (keyInfoNode != null)
+ KeyInfo.LoadXml(keyInfoNode as XmlElement);
+
+ // CipherData
+ XmlNode cipherDataNode = value.SelectSingleNode("enc:CipherData", nsm);
+ if (cipherDataNode == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingCipherData"));
+
+ CipherData = new CipherData();
+ CipherData.LoadXml(cipherDataNode as XmlElement);
+
+ // EncryptionProperties
+ XmlNode encryptionPropertiesNode = value.SelectSingleNode("enc:EncryptionProperties", nsm);
+ if (encryptionPropertiesNode != null)
+ {
+ // Select the EncryptionProperty elements inside the EncryptionProperties element
+ XmlNodeList encryptionPropertyNodes = encryptionPropertiesNode.SelectNodes("enc:EncryptionProperty", nsm);
+ if (encryptionPropertyNodes != null)
+ {
+ foreach (XmlNode node in encryptionPropertyNodes)
+ {
+ EncryptionProperty ep = new EncryptionProperty();
+ ep.LoadXml(node as XmlElement);
+ EncryptionProperties.Add(ep);
+ }
+ }
+ }
+
+ // CarriedKeyName
+ XmlNode carriedKeyNameNode = value.SelectSingleNode("enc:CarriedKeyName", nsm);
+ if (carriedKeyNameNode != null)
+ {
+ CarriedKeyName = carriedKeyNameNode.InnerText;
+ }
+
+ // ReferenceList
+ XmlNode referenceListNode = value.SelectSingleNode("enc:ReferenceList", nsm);
+ if (referenceListNode != null)
+ {
+ // Select the DataReference elements inside the ReferenceList element
+ XmlNodeList dataReferenceNodes = referenceListNode.SelectNodes("enc:DataReference", nsm);
+ if (dataReferenceNodes != null)
+ {
+ foreach (XmlNode node in dataReferenceNodes)
+ {
+ DataReference dr = new DataReference();
+ dr.LoadXml(node as XmlElement);
+ ReferenceList.Add(dr);
+ }
+ }
+ // Select the KeyReference elements inside the ReferenceList element
+ XmlNodeList keyReferenceNodes = referenceListNode.SelectNodes("enc:KeyReference", nsm);
+ if (keyReferenceNodes != null)
+ {
+ foreach (XmlNode node in keyReferenceNodes)
+ {
+ KeyReference kr = new KeyReference();
+ kr.LoadXml(node as XmlElement);
+ ReferenceList.Add(kr);
+ }
+ }
+ }
+
+ // Save away the cached value
+ _cachedXml = value;
+ }
+
+ public override XmlElement GetXml()
+ {
+ if (CacheValid) return _cachedXml;
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ // Create the EncryptedKey element
+ XmlElement encryptedKeyElement = (XmlElement)document.CreateElement("EncryptedKey", EncryptedXml.XmlEncNamespaceUrl);
+
+ // Deal with attributes
+ if (!string.IsNullOrEmpty(Id))
+ encryptedKeyElement.SetAttribute("Id", Id);
+ if (!string.IsNullOrEmpty(Type))
+ encryptedKeyElement.SetAttribute("Type", Type);
+ if (!string.IsNullOrEmpty(MimeType))
+ encryptedKeyElement.SetAttribute("MimeType", MimeType);
+ if (!string.IsNullOrEmpty(Encoding))
+ encryptedKeyElement.SetAttribute("Encoding", Encoding);
+ if (!string.IsNullOrEmpty(Recipient))
+ encryptedKeyElement.SetAttribute("Recipient", Recipient);
+
+ // EncryptionMethod
+ if (EncryptionMethod != null)
+ encryptedKeyElement.AppendChild(EncryptionMethod.GetXml(document));
+
+ // KeyInfo
+ if (KeyInfo.Count > 0)
+ encryptedKeyElement.AppendChild(KeyInfo.GetXml(document));
+
+ // CipherData
+ if (CipherData == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingCipherData"));
+ encryptedKeyElement.AppendChild(CipherData.GetXml(document));
+
+ // EncryptionProperties
+ if (EncryptionProperties.Count > 0)
+ {
+ XmlElement encryptionPropertiesElement = document.CreateElement("EncryptionProperties", EncryptedXml.XmlEncNamespaceUrl);
+ for (int index = 0; index < EncryptionProperties.Count; index++)
+ {
+ EncryptionProperty ep = EncryptionProperties.Item(index);
+ encryptionPropertiesElement.AppendChild(ep.GetXml(document));
+ }
+ encryptedKeyElement.AppendChild(encryptionPropertiesElement);
+ }
+
+ // ReferenceList
+ if (ReferenceList.Count > 0)
+ {
+ XmlElement referenceListElement = document.CreateElement("ReferenceList", EncryptedXml.XmlEncNamespaceUrl);
+ for (int index = 0; index < ReferenceList.Count; index++)
+ {
+ referenceListElement.AppendChild(ReferenceList[index].GetXml(document));
+ }
+ encryptedKeyElement.AppendChild(referenceListElement);
+ }
+
+ // CarriedKeyName
+ if (CarriedKeyName != null)
+ {
+ XmlElement carriedKeyNameElement = (XmlElement)document.CreateElement("CarriedKeyName", EncryptedXml.XmlEncNamespaceUrl);
+ XmlText carriedKeyNameText = document.CreateTextNode(CarriedKeyName);
+ carriedKeyNameElement.AppendChild(carriedKeyNameText);
+ encryptedKeyElement.AppendChild(carriedKeyNameElement);
+ }
+
+ return encryptedKeyElement;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedReference.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedReference.cs
new file mode 100644
index 0000000000..f5b13bdb71
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedReference.cs
@@ -0,0 +1,128 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public abstract class EncryptedReference
+ {
+ private string _uri;
+ private string _referenceType;
+ private TransformChain _transformChain;
+ internal XmlElement _cachedXml = null;
+
+ protected EncryptedReference() : this(string.Empty, new TransformChain())
+ {
+ }
+
+ protected EncryptedReference(string uri) : this(uri, new TransformChain())
+ {
+ }
+
+ protected EncryptedReference(string uri, TransformChain transformChain)
+ {
+ TransformChain = transformChain;
+ Uri = uri;
+ _cachedXml = null;
+ }
+
+ public string Uri
+ {
+ get { return _uri; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException(SecurityResources.GetResourceString("Cryptography_Xml_UriRequired"));
+ _uri = value;
+ _cachedXml = null;
+ }
+ }
+
+ public TransformChain TransformChain
+ {
+ get
+ {
+ if (_transformChain == null)
+ _transformChain = new TransformChain();
+ return _transformChain;
+ }
+ set
+ {
+ _transformChain = value;
+ _cachedXml = null;
+ }
+ }
+
+ public void AddTransform(Transform transform)
+ {
+ TransformChain.Add(transform);
+ }
+
+ protected string ReferenceType
+ {
+ get { return _referenceType; }
+ set
+ {
+ _referenceType = value;
+ _cachedXml = null;
+ }
+ }
+
+ internal protected bool CacheValid
+ {
+ get
+ {
+ return (_cachedXml != null);
+ }
+ }
+
+ public virtual XmlElement GetXml()
+ {
+ if (CacheValid) return _cachedXml;
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ if (ReferenceType == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_ReferenceTypeRequired"));
+
+ // Create the Reference
+ XmlElement referenceElement = document.CreateElement(ReferenceType, EncryptedXml.XmlEncNamespaceUrl);
+ if (!string.IsNullOrEmpty(_uri))
+ referenceElement.SetAttribute("URI", _uri);
+
+ // Add the transforms to the CipherReference
+ if (TransformChain.Count > 0)
+ referenceElement.AppendChild(TransformChain.GetXml(document, SignedXml.XmlDsigNamespaceUrl));
+
+ return referenceElement;
+ }
+
+ public virtual void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ ReferenceType = value.LocalName;
+ Uri = Utils.GetAttribute(value, "URI", EncryptedXml.XmlEncNamespaceUrl);
+
+ // Transforms
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
+ XmlNode transformsNode = value.SelectSingleNode("ds:Transforms", nsm);
+ if (transformsNode != null)
+ TransformChain.LoadXml(transformsNode as XmlElement);
+
+ // cache the Xml
+ _cachedXml = value;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedType.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedType.cs
new file mode 100644
index 0000000000..6b49051b05
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedType.cs
@@ -0,0 +1,129 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public abstract class EncryptedType
+ {
+ private string _id;
+ private string _type;
+ private string _mimeType;
+ private string _encoding;
+ private EncryptionMethod _encryptionMethod;
+ private CipherData _cipherData;
+ private EncryptionPropertyCollection _props;
+ private KeyInfo _keyInfo;
+ internal XmlElement _cachedXml = null;
+
+ internal bool CacheValid
+ {
+ get
+ {
+ return (_cachedXml != null);
+ }
+ }
+
+ public virtual string Id
+ {
+ get { return _id; }
+ set
+ {
+ _id = value;
+ _cachedXml = null;
+ }
+ }
+
+ public virtual string Type
+ {
+ get { return _type; }
+ set
+ {
+ _type = value;
+ _cachedXml = null;
+ }
+ }
+
+ public virtual string MimeType
+ {
+ get { return _mimeType; }
+ set
+ {
+ _mimeType = value;
+ _cachedXml = null;
+ }
+ }
+
+ public virtual string Encoding
+ {
+ get { return _encoding; }
+ set
+ {
+ _encoding = value;
+ _cachedXml = null;
+ }
+ }
+
+ public KeyInfo KeyInfo
+ {
+ get
+ {
+ if (_keyInfo == null)
+ _keyInfo = new KeyInfo();
+ return _keyInfo;
+ }
+ set { _keyInfo = value; }
+ }
+
+ public virtual EncryptionMethod EncryptionMethod
+ {
+ get { return _encryptionMethod; }
+ set
+ {
+ _encryptionMethod = value;
+ _cachedXml = null;
+ }
+ }
+
+ public virtual EncryptionPropertyCollection EncryptionProperties
+ {
+ get
+ {
+ if (_props == null)
+ _props = new EncryptionPropertyCollection();
+ return _props;
+ }
+ }
+
+ public void AddProperty(EncryptionProperty ep)
+ {
+ EncryptionProperties.Add(ep);
+ }
+
+ public virtual CipherData CipherData
+ {
+ get
+ {
+ if (_cipherData == null)
+ _cipherData = new CipherData();
+
+ return _cipherData;
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _cipherData = value;
+ _cachedXml = null;
+ }
+ }
+
+ public abstract void LoadXml(XmlElement value);
+ public abstract XmlElement GetXml();
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedXml.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedXml.cs
new file mode 100644
index 0000000000..dbac36f469
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedXml.cs
@@ -0,0 +1,919 @@
+// 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.Collections;
+using System.IO;
+using System.Net;
+using System.Security;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class EncryptedXml
+ {
+ //
+ // public constant Url identifiers used within the XML Encryption classes
+ //
+
+ public const string XmlEncNamespaceUrl = "http://www.w3.org/2001/04/xmlenc#";
+ public const string XmlEncElementUrl = "http://www.w3.org/2001/04/xmlenc#Element";
+ public const string XmlEncElementContentUrl = "http://www.w3.org/2001/04/xmlenc#Content";
+ public const string XmlEncEncryptedKeyUrl = "http://www.w3.org/2001/04/xmlenc#EncryptedKey";
+
+ //
+ // Symmetric Block Encryption
+ //
+
+ public const string XmlEncDESUrl = "http://www.w3.org/2001/04/xmlenc#des-cbc";
+ public const string XmlEncTripleDESUrl = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc";
+ public const string XmlEncAES128Url = "http://www.w3.org/2001/04/xmlenc#aes128-cbc";
+ public const string XmlEncAES256Url = "http://www.w3.org/2001/04/xmlenc#aes256-cbc";
+ public const string XmlEncAES192Url = "http://www.w3.org/2001/04/xmlenc#aes192-cbc";
+
+ //
+ // Key Transport
+ //
+
+ public const string XmlEncRSA15Url = "http://www.w3.org/2001/04/xmlenc#rsa-1_5";
+ public const string XmlEncRSAOAEPUrl = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p";
+
+ //
+ // Symmetric Key Wrap
+ //
+
+ public const string XmlEncTripleDESKeyWrapUrl = "http://www.w3.org/2001/04/xmlenc#kw-tripledes";
+ public const string XmlEncAES128KeyWrapUrl = "http://www.w3.org/2001/04/xmlenc#kw-aes128";
+ public const string XmlEncAES256KeyWrapUrl = "http://www.w3.org/2001/04/xmlenc#kw-aes256";
+ public const string XmlEncAES192KeyWrapUrl = "http://www.w3.org/2001/04/xmlenc#kw-aes192";
+
+ //
+ // Message Digest
+ //
+
+ public const string XmlEncSHA256Url = "http://www.w3.org/2001/04/xmlenc#sha256";
+ public const string XmlEncSHA512Url = "http://www.w3.org/2001/04/xmlenc#sha512";
+
+ //
+ // private members
+ //
+
+ private XmlDocument _document;
+ private Evidence _evidence;
+ private XmlResolver _xmlResolver;
+ // hash table defining the key name mapping
+ private const int _capacity = 4; // 4 is a reasonable capacity for
+ // the key name mapping hash table
+ private Hashtable _keyNameMapping;
+ private PaddingMode _padding;
+ private CipherMode _mode;
+ private Encoding _encoding;
+ private string _recipient;
+ private int _xmlDsigSearchDepthCounter = 0;
+ private int _xmlDsigSearchDepth;
+
+ //
+ // public constructors
+ //
+ public EncryptedXml() : this(new XmlDocument()) { }
+
+ public EncryptedXml(XmlDocument document) : this(document, null) { }
+
+ public EncryptedXml(XmlDocument document, Evidence evidence)
+ {
+ _document = document;
+ _evidence = evidence;
+ _xmlResolver = null;
+ // set the default padding to ISO-10126
+ _padding = PaddingMode.ISO10126;
+ // set the default cipher mode to CBC
+ _mode = CipherMode.CBC;
+ // By default the encoding is going to be UTF8
+ _encoding = Encoding.UTF8;
+ _keyNameMapping = new Hashtable(_capacity);
+ _xmlDsigSearchDepth = Utils.GetXmlDsigSearchDepth();
+ }
+
+ /// <summary>
+ /// This mentod validates the _xmlDsigSearchDepthCounter counter
+ /// if the counter is over the limit defined by admin or developer.
+ /// </summary>
+ /// <returns>returns true if the limit has reached otherwise false</returns>
+ private bool IsOverXmlDsigRecursionLimit()
+ {
+ if (_xmlDsigSearchDepthCounter > XmlDSigSearchDepth)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Gets / Sets the max limit for recursive search of encryption key in signed XML
+ /// </summary>
+ public int XmlDSigSearchDepth
+ {
+ get
+ {
+ return _xmlDsigSearchDepth;
+ }
+ set
+ {
+ _xmlDsigSearchDepth = value;
+ }
+ }
+
+ //
+ // public properties
+ //
+
+ // The evidence of the document being loaded: will be used to resolve external URIs
+ public Evidence DocumentEvidence
+ {
+ get { return _evidence; }
+ set { _evidence = value; }
+ }
+
+ // The resolver to use for external entities
+ public XmlResolver Resolver
+ {
+ get { return _xmlResolver; }
+ set { _xmlResolver = value; }
+ }
+
+ // The padding to be used. XML Encryption uses ISO 10126
+ // but it's nice to provide a way to extend this to include other forms of paddings
+ public PaddingMode Padding
+ {
+ get { return _padding; }
+ set { _padding = value; }
+ }
+
+ // The cipher mode to be used. XML Encryption uses CBC padding
+ // but it's nice to provide a way to extend this to include other cipher modes
+ public CipherMode Mode
+ {
+ get { return _mode; }
+ set { _mode = value; }
+ }
+
+ // The encoding of the XML document
+ public Encoding Encoding
+ {
+ get { return _encoding; }
+ set { _encoding = value; }
+ }
+
+ // This is used to specify the EncryptedKey elements that should be considered
+ // when an EncyptedData references an EncryptedKey using a CarriedKeyName and Recipient
+ public string Recipient
+ {
+ get
+ {
+ // an unspecified value for an XmlAttribute is string.Empty
+ if (_recipient == null)
+ _recipient = string.Empty;
+ return _recipient;
+ }
+ set { _recipient = value; }
+ }
+
+ //
+ // private methods
+ //
+
+ private byte[] GetCipherValue(CipherData cipherData)
+ {
+ if (cipherData == null)
+ throw new ArgumentNullException("cipherData");
+
+ WebResponse response = null;
+ Stream inputStream = null;
+
+ if (cipherData.CipherValue != null)
+ {
+ return cipherData.CipherValue;
+ }
+ else if (cipherData.CipherReference != null)
+ {
+ if (cipherData.CipherReference.CipherValue != null)
+ return cipherData.CipherReference.CipherValue;
+ Stream decInputStream = null;
+ // See if the CipherReference is a local URI
+ if (cipherData.CipherReference.Uri.Length == 0)
+ {
+ // self referenced Uri
+ string baseUri = (_document == null ? null : _document.BaseURI);
+ TransformChain tc = cipherData.CipherReference.TransformChain;
+ decInputStream = tc.TransformToOctetStream(_document, _xmlResolver, baseUri);
+ }
+ else if (cipherData.CipherReference.Uri[0] == '#')
+ {
+ string idref = Utils.ExtractIdFromLocalUri(cipherData.CipherReference.Uri);
+ // Serialize
+ inputStream = new MemoryStream(_encoding.GetBytes(GetIdElement(_document, idref).OuterXml));
+ string baseUri = (_document == null ? null : _document.BaseURI);
+ TransformChain tc = cipherData.CipherReference.TransformChain;
+ decInputStream = tc.TransformToOctetStream(inputStream, _xmlResolver, baseUri);
+ }
+ else
+ {
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotResolved"), cipherData.CipherReference.Uri);
+ }
+ // read the output stream into a memory stream
+ byte[] cipherValue = null;
+ using (MemoryStream ms = new MemoryStream())
+ {
+ Utils.Pump(decInputStream, ms);
+ cipherValue = ms.ToArray();
+ // Close the stream and return
+ if (response != null)
+ response.Close();
+ if (inputStream != null)
+ inputStream.Close();
+ decInputStream.Close();
+ }
+
+ // cache the cipher value for Perf reasons in case we call this routine twice
+ cipherData.CipherReference.CipherValue = cipherValue;
+ return cipherValue;
+ }
+
+ // Throw a CryptographicException if we were unable to retrieve the cipher data.
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingCipherData"));
+ }
+
+ //
+ // public virtual methods
+ //
+
+ // This describes how the application wants to associate id references to elements
+ public virtual XmlElement GetIdElement(XmlDocument document, string idValue)
+ {
+ return SignedXml.DefaultGetIdElement(document, idValue);
+ }
+
+ // default behaviour is to look for the IV in the CipherValue
+ public virtual byte[] GetDecryptionIV(EncryptedData encryptedData, string symmetricAlgorithmUri)
+ {
+ if (encryptedData == null)
+ throw new ArgumentNullException("encryptedData");
+
+ int initBytesSize = 0;
+ // If the Uri is not provided by the application, try to get it from the EncryptionMethod
+ if (symmetricAlgorithmUri == null)
+ {
+ if (encryptedData.EncryptionMethod == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm"));
+ symmetricAlgorithmUri = encryptedData.EncryptionMethod.KeyAlgorithm;
+ }
+ switch (symmetricAlgorithmUri)
+ {
+ case EncryptedXml.XmlEncDESUrl:
+ case EncryptedXml.XmlEncTripleDESUrl:
+ initBytesSize = 8;
+ break;
+ case EncryptedXml.XmlEncAES128Url:
+ case EncryptedXml.XmlEncAES192Url:
+ case EncryptedXml.XmlEncAES256Url:
+ initBytesSize = 16;
+ break;
+ default:
+ // The Uri is not supported.
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotSupported"));
+ }
+ byte[] IV = new byte[initBytesSize];
+ byte[] cipherValue = GetCipherValue(encryptedData.CipherData);
+ Buffer.BlockCopy(cipherValue, 0, IV, 0, IV.Length);
+ return IV;
+ }
+
+ // default behaviour is to look for keys defined by an EncryptedKey clause
+ // either directly or through a KeyInfoRetrievalMethod, and key names in the key mapping
+ public virtual SymmetricAlgorithm GetDecryptionKey(EncryptedData encryptedData, string symmetricAlgorithmUri)
+ {
+ if (encryptedData == null)
+ throw new ArgumentNullException("encryptedData");
+
+ if (encryptedData.KeyInfo == null)
+ return null;
+ IEnumerator keyInfoEnum = encryptedData.KeyInfo.GetEnumerator();
+ KeyInfoRetrievalMethod kiRetrievalMethod;
+ KeyInfoName kiName;
+ KeyInfoEncryptedKey kiEncKey;
+ EncryptedKey ek = null;
+
+ while (keyInfoEnum.MoveNext())
+ {
+ kiName = keyInfoEnum.Current as KeyInfoName;
+ if (kiName != null)
+ {
+ // Get the decryption key from the key mapping
+ string keyName = kiName.Value;
+ if ((SymmetricAlgorithm)_keyNameMapping[keyName] != null)
+ return (SymmetricAlgorithm)_keyNameMapping[keyName];
+ // try to get it from a CarriedKeyName
+ XmlNamespaceManager nsm = new XmlNamespaceManager(_document.NameTable);
+ nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+ XmlNodeList encryptedKeyList = _document.SelectNodes("//enc:EncryptedKey", nsm);
+ if (encryptedKeyList != null)
+ {
+ foreach (XmlNode encryptedKeyNode in encryptedKeyList)
+ {
+ XmlElement encryptedKeyElement = encryptedKeyNode as XmlElement;
+ EncryptedKey ek1 = new EncryptedKey();
+ ek1.LoadXml(encryptedKeyElement);
+ if (ek1.CarriedKeyName == keyName && ek1.Recipient == Recipient)
+ {
+ ek = ek1;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ kiRetrievalMethod = keyInfoEnum.Current as KeyInfoRetrievalMethod;
+ if (kiRetrievalMethod != null)
+ {
+ string idref = Utils.ExtractIdFromLocalUri(kiRetrievalMethod.Uri);
+ ek = new EncryptedKey();
+ ek.LoadXml(GetIdElement(_document, idref));
+ break;
+ }
+ kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey;
+ if (kiEncKey != null)
+ {
+ ek = kiEncKey.EncryptedKey;
+ break;
+ }
+ }
+
+ // if we have an EncryptedKey, decrypt to get the symmetric key
+ if (ek != null)
+ {
+ // now process the EncryptedKey, loop recursively
+ // If the Uri is not provided by the application, try to get it from the EncryptionMethod
+ if (symmetricAlgorithmUri == null)
+ {
+ if (encryptedData.EncryptionMethod == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm"));
+ symmetricAlgorithmUri = encryptedData.EncryptionMethod.KeyAlgorithm;
+ }
+ byte[] key = DecryptEncryptedKey(ek);
+ if (key == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingDecryptionKey"));
+
+ SymmetricAlgorithm symAlg = (SymmetricAlgorithm)CryptoConfig.CreateFromName(symmetricAlgorithmUri);
+ symAlg.Key = key;
+ return symAlg;
+ }
+ return null;
+ }
+
+ // Try to decrypt the EncryptedKey given the key mapping
+ public virtual byte[] DecryptEncryptedKey(EncryptedKey encryptedKey)
+ {
+ if (encryptedKey == null)
+ throw new ArgumentNullException("encryptedKey");
+ if (encryptedKey.KeyInfo == null)
+ return null;
+
+ IEnumerator keyInfoEnum = encryptedKey.KeyInfo.GetEnumerator();
+ KeyInfoName kiName;
+ KeyInfoX509Data kiX509Data;
+ KeyInfoRetrievalMethod kiRetrievalMethod;
+ KeyInfoEncryptedKey kiEncKey;
+ EncryptedKey ek = null;
+ bool fOAEP = false;
+
+ while (keyInfoEnum.MoveNext())
+ {
+ kiName = keyInfoEnum.Current as KeyInfoName;
+ if (kiName != null)
+ {
+ // Get the decryption key from the key mapping
+ string keyName = kiName.Value;
+ object kek = _keyNameMapping[keyName];
+ if (kek != null)
+ {
+ // kek is either a SymmetricAlgorithm or an RSA key, otherwise, we wouldn't be able to insert it in the hash table
+ if (kek is SymmetricAlgorithm)
+ return EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (SymmetricAlgorithm)kek);
+
+ // kek is an RSA key: get fOAEP from the algorithm, default to false
+ fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl);
+ return EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (RSA)kek, fOAEP);
+ }
+ break;
+ }
+ kiX509Data = keyInfoEnum.Current as KeyInfoX509Data;
+ if (kiX509Data != null)
+ {
+ X509Certificate2Collection collection = Utils.BuildBagOfCerts(kiX509Data, CertUsageType.Decryption);
+ foreach (X509Certificate2 certificate in collection)
+ {
+ using (RSA privateKey = certificate.GetRSAPrivateKey())
+ {
+ if (privateKey != null)
+ {
+ fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl);
+ return EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, privateKey, fOAEP);
+ }
+ }
+ }
+ break;
+ }
+ kiRetrievalMethod = keyInfoEnum.Current as KeyInfoRetrievalMethod;
+ if (kiRetrievalMethod != null)
+ {
+ string idref = Utils.ExtractIdFromLocalUri(kiRetrievalMethod.Uri);
+ ek = new EncryptedKey();
+ ek.LoadXml(GetIdElement(_document, idref));
+ try
+ {
+ //Following checks if XML dsig processing is in loop and within the limit defined by machine
+ // admin or developer. Once the recursion depth crosses the defined limit it will throw exception.
+ _xmlDsigSearchDepthCounter++;
+ if (IsOverXmlDsigRecursionLimit())
+ {
+ //Throw exception once recursion limit is hit.
+ throw new CryptoSignedXmlRecursionException();
+ }
+ else
+ {
+ return DecryptEncryptedKey(ek);
+ }
+ }
+ finally
+ {
+ _xmlDsigSearchDepthCounter--;
+ }
+ }
+ kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey;
+ if (kiEncKey != null)
+ {
+ ek = kiEncKey.EncryptedKey;
+ // recursively process EncryptedKey elements
+ byte[] encryptionKey = DecryptEncryptedKey(ek);
+ if (encryptionKey != null)
+ {
+ // this is a symmetric algorithm for sure
+ SymmetricAlgorithm symAlg = (SymmetricAlgorithm)CryptoConfig.CreateFromName(encryptedKey.EncryptionMethod.KeyAlgorithm);
+ symAlg.Key = encryptionKey;
+ return EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, symAlg);
+ }
+ }
+ }
+ return null;
+ }
+
+ //
+ // public methods
+ //
+
+ // defines a key name mapping. Default behaviour is to require the key object
+ // to be an RSA key or a SymmetricAlgorithm
+ public void AddKeyNameMapping(string keyName, object keyObject)
+ {
+ if (keyName == null)
+ throw new ArgumentNullException("keyName");
+ if (keyObject == null)
+ throw new ArgumentNullException("keyObject");
+
+ if (!(keyObject is SymmetricAlgorithm) && !(keyObject is RSA))
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_NotSupportedCryptographicTransform"));
+ _keyNameMapping.Add(keyName, keyObject);
+ }
+
+ public void ClearKeyNameMappings()
+ {
+ _keyNameMapping.Clear();
+ }
+
+ // Encrypts the given element with the certificate specified. The certificate is added as
+ // an X509Data KeyInfo to an EncryptedKey (AES session key) generated randomly.
+ public EncryptedData Encrypt(XmlElement inputElement, X509Certificate2 certificate)
+ {
+ if (inputElement == null)
+ throw new ArgumentNullException("inputElement");
+ if (certificate == null)
+ throw new ArgumentNullException("certificate");
+
+ using (RSA rsaPublicKey = certificate.GetRSAPublicKey())
+ {
+ if (rsaPublicKey == null)
+ throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_KeyAlgorithm"));
+
+ // Create the EncryptedData object, using an AES-256 session key by default.
+ EncryptedData ed = new EncryptedData();
+ ed.Type = EncryptedXml.XmlEncElementUrl;
+ ed.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
+
+ // Include the certificate in the EncryptedKey KeyInfo.
+ EncryptedKey ek = new EncryptedKey();
+ ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);
+ ek.KeyInfo.AddClause(new KeyInfoX509Data(certificate));
+
+ // Create a random AES session key and encrypt it with the public key associated with the certificate.
+ RijndaelManaged rijn = new RijndaelManaged();
+ ek.CipherData.CipherValue = EncryptedXml.EncryptKey(rijn.Key, rsaPublicKey, false);
+
+ // Encrypt the input element with the random session key that we've created above.
+ KeyInfoEncryptedKey kek = new KeyInfoEncryptedKey(ek);
+ ed.KeyInfo.AddClause(kek);
+ ed.CipherData.CipherValue = EncryptData(inputElement, rijn, false);
+
+ return ed;
+ }
+ }
+
+ // Encrypts the given element with the key name specified. A corresponding key name mapping
+ // has to be defined before calling this method. The key name is added as
+ // a KeyNameInfo KeyInfo to an EncryptedKey (AES session key) generated randomly.
+ public EncryptedData Encrypt(XmlElement inputElement, string keyName)
+ {
+ if (inputElement == null)
+ throw new ArgumentNullException("inputElement");
+ if (keyName == null)
+ throw new ArgumentNullException("keyName");
+
+ object encryptionKey = null;
+ if (_keyNameMapping != null)
+ encryptionKey = _keyNameMapping[keyName];
+
+ if (encryptionKey == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingEncryptionKey"));
+
+ // kek is either a SymmetricAlgorithm or an RSA key, otherwise, we wouldn't be able to insert it in the hash table
+ SymmetricAlgorithm symKey = encryptionKey as SymmetricAlgorithm;
+ RSA rsa = encryptionKey as RSA;
+
+ // Create the EncryptedData object, using an AES-256 session key by default.
+ EncryptedData ed = new EncryptedData();
+ ed.Type = EncryptedXml.XmlEncElementUrl;
+ ed.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
+
+ // Include the key name in the EncryptedKey KeyInfo.
+ string encryptionMethod = null;
+ if (symKey == null)
+ {
+ encryptionMethod = EncryptedXml.XmlEncRSA15Url;
+ }
+ else if (symKey is TripleDES)
+ {
+ // CMS Triple DES Key Wrap
+ encryptionMethod = EncryptedXml.XmlEncTripleDESKeyWrapUrl;
+ }
+ else if (symKey is Rijndael || symKey is Aes)
+ {
+ // FIPS AES Key Wrap
+ switch (symKey.KeySize)
+ {
+ case 128:
+ encryptionMethod = EncryptedXml.XmlEncAES128KeyWrapUrl;
+ break;
+ case 192:
+ encryptionMethod = EncryptedXml.XmlEncAES192KeyWrapUrl;
+ break;
+ case 256:
+ encryptionMethod = EncryptedXml.XmlEncAES256KeyWrapUrl;
+ break;
+ }
+ }
+ else
+ {
+ // throw an exception if the transform is not in the previous categories
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_NotSupportedCryptographicTransform"));
+ }
+ EncryptedKey ek = new EncryptedKey();
+ ek.EncryptionMethod = new EncryptionMethod(encryptionMethod);
+ ek.KeyInfo.AddClause(new KeyInfoName(keyName));
+
+ // Create a random AES session key and encrypt it with the public key associated with the certificate.
+ RijndaelManaged rijn = new RijndaelManaged();
+ ek.CipherData.CipherValue = (symKey == null ? EncryptedXml.EncryptKey(rijn.Key, rsa, false) : EncryptedXml.EncryptKey(rijn.Key, symKey));
+
+ // Encrypt the input element with the random session key that we've created above.
+ KeyInfoEncryptedKey kek = new KeyInfoEncryptedKey(ek);
+ ed.KeyInfo.AddClause(kek);
+ ed.CipherData.CipherValue = EncryptData(inputElement, rijn, false);
+
+ return ed;
+ }
+
+ // decrypts the document using the defined key mapping in GetDecryptionKey
+ // The behaviour of this method can be extended because GetDecryptionKey is virtual
+ // the document is decrypted in place
+ public void DecryptDocument()
+ {
+ // Look for all EncryptedData elements and decrypt them
+ XmlNamespaceManager nsm = new XmlNamespaceManager(_document.NameTable);
+ nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+ XmlNodeList encryptedDataList = _document.SelectNodes("//enc:EncryptedData", nsm);
+ if (encryptedDataList != null)
+ {
+ foreach (XmlNode encryptedDataNode in encryptedDataList)
+ {
+ XmlElement encryptedDataElement = encryptedDataNode as XmlElement;
+ EncryptedData ed = new EncryptedData();
+ ed.LoadXml(encryptedDataElement);
+ SymmetricAlgorithm symAlg = GetDecryptionKey(ed, null);
+ if (symAlg == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingDecryptionKey"));
+ byte[] decrypted = DecryptData(ed, symAlg);
+ ReplaceData(encryptedDataElement, decrypted);
+ }
+ }
+ }
+
+ // encrypts the supplied arbitrary data
+ public byte[] EncryptData(byte[] plaintext, SymmetricAlgorithm symmetricAlgorithm)
+ {
+ if (plaintext == null)
+ throw new ArgumentNullException("plaintext");
+ if (symmetricAlgorithm == null)
+ throw new ArgumentNullException("symmetricAlgorithm");
+
+ // save the original symmetric algorithm
+ CipherMode origMode = symmetricAlgorithm.Mode;
+ PaddingMode origPadding = symmetricAlgorithm.Padding;
+
+ byte[] cipher = null;
+ try
+ {
+ symmetricAlgorithm.Mode = _mode;
+ symmetricAlgorithm.Padding = _padding;
+
+ ICryptoTransform enc = symmetricAlgorithm.CreateEncryptor();
+ cipher = enc.TransformFinalBlock(plaintext, 0, plaintext.Length);
+ }
+ finally
+ {
+ // now restore the original symmetric algorithm
+ symmetricAlgorithm.Mode = origMode;
+ symmetricAlgorithm.Padding = origPadding;
+ }
+
+ byte[] output = null;
+ if (_mode == CipherMode.ECB)
+ {
+ output = cipher;
+ }
+ else
+ {
+ byte[] IV = symmetricAlgorithm.IV;
+ output = new byte[cipher.Length + IV.Length];
+ Buffer.BlockCopy(IV, 0, output, 0, IV.Length);
+ Buffer.BlockCopy(cipher, 0, output, IV.Length, cipher.Length);
+ }
+ return output;
+ }
+
+ // encrypts the supplied input element
+ public byte[] EncryptData(XmlElement inputElement, SymmetricAlgorithm symmetricAlgorithm, bool content)
+ {
+ if (inputElement == null)
+ throw new ArgumentNullException("inputElement");
+ if (symmetricAlgorithm == null)
+ throw new ArgumentNullException("symmetricAlgorithm");
+
+ byte[] plainText = (content ? _encoding.GetBytes(inputElement.InnerXml) : _encoding.GetBytes(inputElement.OuterXml));
+ return EncryptData(plainText, symmetricAlgorithm);
+ }
+
+ // decrypts the supplied EncryptedData
+ public byte[] DecryptData(EncryptedData encryptedData, SymmetricAlgorithm symmetricAlgorithm)
+ {
+ if (encryptedData == null)
+ throw new ArgumentNullException("encryptedData");
+ if (symmetricAlgorithm == null)
+ throw new ArgumentNullException("symmetricAlgorithm");
+
+ // get the cipher value and decrypt
+ byte[] cipherValue = GetCipherValue(encryptedData.CipherData);
+
+ // save the original symmetric algorithm
+ CipherMode origMode = symmetricAlgorithm.Mode;
+ PaddingMode origPadding = symmetricAlgorithm.Padding;
+ byte[] origIV = symmetricAlgorithm.IV;
+
+ // read the IV from cipherValue
+ byte[] decryptionIV = null;
+ if (_mode != CipherMode.ECB)
+ decryptionIV = GetDecryptionIV(encryptedData, null);
+
+ byte[] output = null;
+ try
+ {
+ int lengthIV = 0;
+ if (decryptionIV != null)
+ {
+ symmetricAlgorithm.IV = decryptionIV;
+ lengthIV = decryptionIV.Length;
+ }
+ symmetricAlgorithm.Mode = _mode;
+ symmetricAlgorithm.Padding = _padding;
+
+ ICryptoTransform dec = symmetricAlgorithm.CreateDecryptor();
+ output = dec.TransformFinalBlock(cipherValue, lengthIV, cipherValue.Length - lengthIV);
+ }
+ finally
+ {
+ // now restore the original symmetric algorithm
+ symmetricAlgorithm.Mode = origMode;
+ symmetricAlgorithm.Padding = origPadding;
+ symmetricAlgorithm.IV = origIV;
+ }
+
+ return output;
+ }
+
+ // This method replaces an EncryptedData element with the decrypted sequence of bytes
+ public void ReplaceData(XmlElement inputElement, byte[] decryptedData)
+ {
+ if (inputElement == null)
+ throw new ArgumentNullException("inputElement");
+ if (decryptedData == null)
+ throw new ArgumentNullException("decryptedData");
+
+ XmlNode parent = inputElement.ParentNode;
+ if (parent.NodeType == XmlNodeType.Document)
+ {
+ // We're replacing the root element, but we can't just wholesale replace the owner
+ // document's InnerXml, since we need to preserve any other top-level XML elements (such as
+ // comments or the XML entity declaration. Instead, create a new document with the
+ // decrypted XML, import it into the existing document, and replace just the root element.
+ XmlDocument importDocument = new XmlDocument();
+ importDocument.PreserveWhitespace = true;
+ string decryptedString = _encoding.GetString(decryptedData);
+ using (StringReader sr = new StringReader(decryptedString))
+ {
+ using (XmlReader xr = XmlReader.Create(sr, Utils.GetSecureXmlReaderSettings(_xmlResolver)))
+ {
+ importDocument.Load(xr);
+ }
+ }
+
+ XmlNode importedNode = inputElement.OwnerDocument.ImportNode(importDocument.DocumentElement, true);
+
+ parent.RemoveChild(inputElement);
+ parent.AppendChild(importedNode);
+ }
+ else
+ {
+ XmlNode dummy = parent.OwnerDocument.CreateElement(parent.Prefix, parent.LocalName, parent.NamespaceURI);
+
+ try
+ {
+ parent.AppendChild(dummy);
+
+ // Replace the children of the dummy node with the sequence of bytes passed in.
+ // The string will be parsed into DOM objects in the context of the parent of the EncryptedData element.
+ dummy.InnerXml = _encoding.GetString(decryptedData);
+
+ // Move the children of the dummy node up to the parent.
+ XmlNode child = dummy.FirstChild;
+ XmlNode sibling = inputElement.NextSibling;
+
+ XmlNode nextChild = null;
+ while (child != null)
+ {
+ nextChild = child.NextSibling;
+ parent.InsertBefore(child, sibling);
+ child = nextChild;
+ }
+ }
+ finally
+ {
+ // Remove the dummy element.
+ parent.RemoveChild(dummy);
+ }
+
+ // Remove the EncryptedData element
+ parent.RemoveChild(inputElement);
+ }
+ }
+
+ //
+ // public static methods
+ //
+
+ // replaces the inputElement with the provided EncryptedData
+ public static void ReplaceElement(XmlElement inputElement, EncryptedData encryptedData, bool content)
+ {
+ if (inputElement == null)
+ throw new ArgumentNullException("inputElement");
+ if (encryptedData == null)
+ throw new ArgumentNullException("encryptedData");
+
+ // First, get the XML representation of the EncryptedData object
+ XmlElement elemED = encryptedData.GetXml(inputElement.OwnerDocument);
+ switch (content)
+ {
+ case true:
+ // remove all children of the input element
+ Utils.RemoveAllChildren(inputElement);
+ // then append the encrypted data as a child of the input element
+ inputElement.AppendChild(elemED);
+ break;
+ case false:
+ XmlNode parentNode = inputElement.ParentNode;
+ // remove the input element from the containing document
+ parentNode.ReplaceChild(elemED, inputElement);
+ break;
+ }
+ }
+
+ // wraps the supplied input key data using the provided symmetric algorithm
+ public static byte[] EncryptKey(byte[] keyData, SymmetricAlgorithm symmetricAlgorithm)
+ {
+ if (keyData == null)
+ throw new ArgumentNullException("keyData");
+ if (symmetricAlgorithm == null)
+ throw new ArgumentNullException("symmetricAlgorithm");
+
+ if (symmetricAlgorithm is TripleDES)
+ {
+ // CMS Triple DES Key Wrap
+ return SymmetricKeyWrap.TripleDESKeyWrapEncrypt(symmetricAlgorithm.Key, keyData);
+ }
+ else if (symmetricAlgorithm is Rijndael || symmetricAlgorithm is Aes)
+ {
+ // FIPS AES Key Wrap
+ return SymmetricKeyWrap.AESKeyWrapEncrypt(symmetricAlgorithm.Key, keyData);
+ }
+ // throw an exception if the transform is not in the previous categories
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_NotSupportedCryptographicTransform"));
+ }
+
+
+ // encrypts the supplied input key data using an RSA key and specifies whether we want to use OAEP
+ // padding or PKCS#1 v1.5 padding as described in the PKCS specification
+ public static byte[] EncryptKey(byte[] keyData, RSA rsa, bool useOAEP)
+ {
+ if (keyData == null)
+ throw new ArgumentNullException("keyData");
+ if (rsa == null)
+ throw new ArgumentNullException("rsa");
+
+ if (useOAEP)
+ {
+ RSAOAEPKeyExchangeFormatter rsaFormatter = new RSAOAEPKeyExchangeFormatter(rsa);
+ return rsaFormatter.CreateKeyExchange(keyData);
+ }
+ else
+ {
+ RSAPKCS1KeyExchangeFormatter rsaFormatter = new RSAPKCS1KeyExchangeFormatter(rsa);
+ return rsaFormatter.CreateKeyExchange(keyData);
+ }
+ }
+
+ // decrypts the supplied wrapped key using the provided symmetric algorithm
+ public static byte[] DecryptKey(byte[] keyData, SymmetricAlgorithm symmetricAlgorithm)
+ {
+ if (keyData == null)
+ throw new ArgumentNullException("keyData");
+ if (symmetricAlgorithm == null)
+ throw new ArgumentNullException("symmetricAlgorithm");
+
+ if (symmetricAlgorithm is TripleDES)
+ {
+ // CMS Triple DES Key Wrap
+ return SymmetricKeyWrap.TripleDESKeyWrapDecrypt(symmetricAlgorithm.Key, keyData);
+ }
+ else if (symmetricAlgorithm is Rijndael || symmetricAlgorithm is Aes)
+ {
+ // FIPS AES Key Wrap
+ return SymmetricKeyWrap.AESKeyWrapDecrypt(symmetricAlgorithm.Key, keyData);
+ }
+ // throw an exception if the transform is not in the previous categories
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_NotSupportedCryptographicTransform"));
+ }
+
+ // decrypts the supplied data using an RSA key and specifies whether we want to use OAEP
+ // padding or PKCS#1 v1.5 padding as described in the PKCS specification
+ public static byte[] DecryptKey(byte[] keyData, RSA rsa, bool useOAEP)
+ {
+ if (keyData == null)
+ throw new ArgumentNullException("keyData");
+ if (rsa == null)
+ throw new ArgumentNullException("rsa");
+
+ if (useOAEP)
+ {
+ RSAOAEPKeyExchangeDeformatter rsaDeformatter = new RSAOAEPKeyExchangeDeformatter(rsa);
+ return rsaDeformatter.DecryptKeyExchange(keyData);
+ }
+ else
+ {
+ RSAPKCS1KeyExchangeDeformatter rsaDeformatter = new RSAPKCS1KeyExchangeDeformatter(rsa);
+ return rsaDeformatter.DecryptKeyExchange(keyData);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionMethod.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionMethod.cs
new file mode 100644
index 0000000000..2b39aa3dd5
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionMethod.cs
@@ -0,0 +1,104 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class EncryptionMethod
+ {
+ private XmlElement _cachedXml = null;
+ private int _keySize = 0;
+ private string _algorithm;
+
+ public EncryptionMethod()
+ {
+ _cachedXml = null;
+ }
+
+ public EncryptionMethod(string algorithm)
+ {
+ _algorithm = algorithm;
+ _cachedXml = null;
+ }
+
+ private bool CacheValid
+ {
+ get
+ {
+ return (_cachedXml != null);
+ }
+ }
+
+ public int KeySize
+ {
+ get { return _keySize; }
+ set
+ {
+ if (value <= 0)
+ throw new ArgumentOutOfRangeException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidKeySize"));
+ _keySize = value;
+ _cachedXml = null;
+ }
+ }
+
+ public string KeyAlgorithm
+ {
+ get { return _algorithm; }
+ set
+ {
+ _algorithm = value;
+ _cachedXml = null;
+ }
+ }
+
+ public XmlElement GetXml()
+ {
+ if (CacheValid) return (_cachedXml);
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ // Create the EncryptionMethod element
+ XmlElement encryptionMethodElement = (XmlElement)document.CreateElement("EncryptionMethod", EncryptedXml.XmlEncNamespaceUrl);
+ if (!string.IsNullOrEmpty(_algorithm))
+ encryptionMethodElement.SetAttribute("Algorithm", _algorithm);
+ if (_keySize > 0)
+ {
+ // Construct a KeySize element
+ XmlElement keySizeElement = document.CreateElement("KeySize", EncryptedXml.XmlEncNamespaceUrl);
+ keySizeElement.AppendChild(document.CreateTextNode(_keySize.ToString(null, null)));
+ encryptionMethodElement.AppendChild(keySizeElement);
+ }
+ return encryptionMethodElement;
+ }
+
+ public void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+
+ XmlElement encryptionMethodElement = value;
+ _algorithm = Utils.GetAttribute(encryptionMethodElement, "Algorithm", EncryptedXml.XmlEncNamespaceUrl);
+
+ XmlNode keySizeNode = value.SelectSingleNode("enc:KeySize", nsm);
+ if (keySizeNode != null)
+ {
+ KeySize = Convert.ToInt32(Utils.DiscardWhiteSpaces(keySizeNode.InnerText), null);
+ }
+
+ // Save away the cached value
+ _cachedXml = value;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionProperty.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionProperty.cs
new file mode 100644
index 0000000000..77f4c0712f
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionProperty.cs
@@ -0,0 +1,93 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public sealed class EncryptionProperty
+ {
+ private string _target;
+ private string _id;
+ private XmlElement _elemProp;
+ private XmlElement _cachedXml = null;
+
+ // We are being lax here as per the spec
+ public EncryptionProperty() { }
+
+ public EncryptionProperty(XmlElement elementProperty)
+ {
+ if (elementProperty == null)
+ throw new ArgumentNullException("elementProperty");
+ if (elementProperty.LocalName != "EncryptionProperty" || elementProperty.NamespaceURI != EncryptedXml.XmlEncNamespaceUrl)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidEncryptionProperty"));
+
+ _elemProp = elementProperty;
+ _cachedXml = null;
+ }
+
+ public string Id
+ {
+ get { return _id; }
+ }
+
+ public string Target
+ {
+ get { return _target; }
+ }
+
+ public XmlElement PropertyElement
+ {
+ get { return _elemProp; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ if (value.LocalName != "EncryptionProperty" || value.NamespaceURI != EncryptedXml.XmlEncNamespaceUrl)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidEncryptionProperty"));
+
+ _elemProp = value;
+ _cachedXml = null;
+ }
+ }
+
+ private bool CacheValid
+ {
+ get
+ {
+ return (_cachedXml != null);
+ }
+ }
+
+ public XmlElement GetXml()
+ {
+ if (CacheValid) return _cachedXml;
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ return document.ImportNode(_elemProp, true) as XmlElement;
+ }
+
+ public void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ if (value.LocalName != "EncryptionProperty" || value.NamespaceURI != EncryptedXml.XmlEncNamespaceUrl)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidEncryptionProperty"));
+
+ // cache the Xml
+ _cachedXml = value;
+ _id = Utils.GetAttribute(value, "Id", EncryptedXml.XmlEncNamespaceUrl);
+ _target = Utils.GetAttribute(value, "Target", EncryptedXml.XmlEncNamespaceUrl);
+ _elemProp = value;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionPropertyCollection.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionPropertyCollection.cs
new file mode 100644
index 0000000000..5cafec0423
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptionPropertyCollection.cs
@@ -0,0 +1,172 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public sealed class EncryptionPropertyCollection : IList
+ {
+ private ArrayList _props;
+
+ public EncryptionPropertyCollection()
+ {
+ _props = new ArrayList();
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _props.GetEnumerator();
+ }
+
+ public int Count
+ {
+ get { return _props.Count; }
+ }
+
+ /// <internalonly/>
+ int IList.Add(object value)
+ {
+ if (!(value is EncryptionProperty))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+
+ return _props.Add(value);
+ }
+
+ public int Add(EncryptionProperty value)
+ {
+ return _props.Add(value);
+ }
+
+ public void Clear()
+ {
+ _props.Clear();
+ }
+
+ /// <internalonly/>
+ bool IList.Contains(object value)
+ {
+ if (!(value is EncryptionProperty))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+
+ return _props.Contains(value);
+ }
+
+ public bool Contains(EncryptionProperty value)
+ {
+ return _props.Contains(value);
+ }
+
+ /// <internalonly/>
+ int IList.IndexOf(object value)
+ {
+ if (!(value is EncryptionProperty))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+
+ return _props.IndexOf(value);
+ }
+
+ public int IndexOf(EncryptionProperty value)
+ {
+ return _props.IndexOf(value);
+ }
+
+ /// <internalonly/>
+ void IList.Insert(int index, object value)
+ {
+ if (!(value is EncryptionProperty))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+
+ _props.Insert(index, value);
+ }
+
+ public void Insert(int index, EncryptionProperty value)
+ {
+ _props.Insert(index, value);
+ }
+
+ /// <internalonly/>
+ void IList.Remove(object value)
+ {
+ if (!(value is EncryptionProperty))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+
+ _props.Remove(value);
+ }
+
+ public void Remove(EncryptionProperty value)
+ {
+ _props.Remove(value);
+ }
+
+ public void RemoveAt(int index)
+ {
+ _props.RemoveAt(index);
+ }
+
+ public bool IsFixedSize
+ {
+ get { return _props.IsFixedSize; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return _props.IsReadOnly; }
+ }
+
+ public EncryptionProperty Item(int index)
+ {
+ return (EncryptionProperty)_props[index];
+ }
+
+ [System.Runtime.CompilerServices.IndexerName("ItemOf")]
+ public EncryptionProperty this[int index]
+ {
+ get
+ {
+ return (EncryptionProperty)((IList)this)[index];
+ }
+ set
+ {
+ ((IList)this)[index] = value;
+ }
+ }
+
+ /// <internalonly/>
+ object IList.this[int index]
+ {
+ get { return _props[index]; }
+ set
+ {
+ if (!(value is EncryptionProperty))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+
+ _props[index] = value;
+ }
+ }
+
+ /// <internalonly/>
+ public void CopyTo(Array array, int index)
+ {
+ _props.CopyTo(array, index);
+ }
+
+ public void CopyTo(EncryptionProperty[] array, int index)
+ {
+ _props.CopyTo(array, index);
+ }
+
+ public object SyncRoot
+ {
+ get { return _props.SyncRoot; }
+ }
+
+ public bool IsSynchronized
+ {
+ get { return _props.IsSynchronized; }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ExcAncestralNamespaceContextManager.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ExcAncestralNamespaceContextManager.cs
new file mode 100644
index 0000000000..b55a30442c
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ExcAncestralNamespaceContextManager.cs
@@ -0,0 +1,90 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the stack of currently active NamespaceFrame contexts. this
+ // object also maintains the inclusive prefix list in a tokenized form.
+ internal class ExcAncestralNamespaceContextManager : AncestralNamespaceContextManager
+ {
+ private Hashtable _inclusivePrefixSet = null;
+
+ internal ExcAncestralNamespaceContextManager(string inclusiveNamespacesPrefixList)
+ {
+ _inclusivePrefixSet = Utils.TokenizePrefixListString(inclusiveNamespacesPrefixList);
+ }
+
+ private bool HasNonRedundantInclusivePrefix(XmlAttribute attr)
+ {
+ int tmp;
+ string nsPrefix = Utils.GetNamespacePrefix(attr);
+ return _inclusivePrefixSet.ContainsKey(nsPrefix) &&
+ Utils.IsNonRedundantNamespaceDecl(attr, GetNearestRenderedNamespaceWithMatchingPrefix(nsPrefix, out tmp));
+ }
+
+ private void GatherNamespaceToRender(string nsPrefix, SortedList nsListToRender, Hashtable nsLocallyDeclared)
+ {
+ foreach (object a in nsListToRender.GetKeyList())
+ {
+ if (Utils.HasNamespacePrefix((XmlAttribute)a, nsPrefix))
+ return;
+ }
+
+ int rDepth;
+ XmlAttribute local = (XmlAttribute)nsLocallyDeclared[nsPrefix];
+ XmlAttribute rAncestral = GetNearestRenderedNamespaceWithMatchingPrefix(nsPrefix, out rDepth);
+
+ if (local != null)
+ {
+ if (Utils.IsNonRedundantNamespaceDecl(local, rAncestral))
+ {
+ nsLocallyDeclared.Remove(nsPrefix);
+ nsListToRender.Add(local, null);
+ }
+ }
+ else
+ {
+ int uDepth;
+ XmlAttribute uAncestral = GetNearestUnrenderedNamespaceWithMatchingPrefix(nsPrefix, out uDepth);
+ if (uAncestral != null && uDepth > rDepth && Utils.IsNonRedundantNamespaceDecl(uAncestral, rAncestral))
+ {
+ nsListToRender.Add(uAncestral, null);
+ }
+ }
+ }
+
+ internal override void GetNamespacesToRender(XmlElement element, SortedList attrListToRender, SortedList nsListToRender, Hashtable nsLocallyDeclared)
+ {
+ GatherNamespaceToRender(element.Prefix, nsListToRender, nsLocallyDeclared);
+ foreach (object attr in attrListToRender.GetKeyList())
+ {
+ string prefix = ((XmlAttribute)attr).Prefix;
+ if (prefix.Length > 0)
+ GatherNamespaceToRender(prefix, nsListToRender, nsLocallyDeclared);
+ }
+ }
+
+ internal override void TrackNamespaceNode(XmlAttribute attr, SortedList nsListToRender, Hashtable nsLocallyDeclared)
+ {
+ if (!Utils.IsXmlPrefixDefinitionNode(attr))
+ {
+ if (HasNonRedundantInclusivePrefix(attr))
+ nsListToRender.Add(attr, null);
+ else
+ nsLocallyDeclared.Add(Utils.GetNamespacePrefix(attr), attr);
+ }
+ }
+
+ internal override void TrackXmlNamespaceNode(XmlAttribute attr, SortedList nsListToRender, SortedList attrListToRender, Hashtable nsLocallyDeclared)
+ {
+ // exclusive canonicalization treats Xml namespaces as simple attributes. They are not propagated.
+ attrListToRender.Add(attr, null);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ExcCanonicalXml.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ExcCanonicalXml.cs
new file mode 100644
index 0000000000..e3a914b1bf
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ExcCanonicalXml.cs
@@ -0,0 +1,122 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+using System;
+
+namespace System.Security.Cryptography.Xml
+{
+ internal class ExcCanonicalXml
+ {
+ private CanonicalXmlDocument _c14nDoc;
+ private ExcAncestralNamespaceContextManager _ancMgr;
+
+ internal ExcCanonicalXml(Stream inputStream, bool includeComments, string inclusiveNamespacesPrefixList, XmlResolver resolver, string strBaseUri)
+ {
+ if (inputStream == null)
+ throw new ArgumentNullException("inputStream");
+
+ _c14nDoc = new CanonicalXmlDocument(true, includeComments);
+ _c14nDoc.XmlResolver = resolver;
+ _c14nDoc.Load(Utils.PreProcessStreamInput(inputStream, resolver, strBaseUri));
+ _ancMgr = new ExcAncestralNamespaceContextManager(inclusiveNamespacesPrefixList);
+ }
+
+ internal ExcCanonicalXml(XmlDocument document, bool includeComments, string inclusiveNamespacesPrefixList, XmlResolver resolver)
+ {
+ if (document == null)
+ throw new ArgumentNullException("document");
+
+ _c14nDoc = new CanonicalXmlDocument(true, includeComments);
+ _c14nDoc.XmlResolver = resolver;
+ _c14nDoc.Load(new XmlNodeReader(document));
+ _ancMgr = new ExcAncestralNamespaceContextManager(inclusiveNamespacesPrefixList);
+ }
+
+ internal ExcCanonicalXml(XmlNodeList nodeList, bool includeComments, string inclusiveNamespacesPrefixList, XmlResolver resolver)
+ {
+ if (nodeList == null)
+ throw new ArgumentNullException("nodeList");
+
+ XmlDocument doc = Utils.GetOwnerDocument(nodeList);
+ if (doc == null)
+ throw new ArgumentException("nodeList");
+
+ _c14nDoc = new CanonicalXmlDocument(false, includeComments);
+ _c14nDoc.XmlResolver = resolver;
+ _c14nDoc.Load(new XmlNodeReader(doc));
+ _ancMgr = new ExcAncestralNamespaceContextManager(inclusiveNamespacesPrefixList);
+
+ MarkInclusionStateForNodes(nodeList, doc, _c14nDoc);
+ }
+
+ internal byte[] GetBytes()
+ {
+ StringBuilder sb = new StringBuilder();
+ _c14nDoc.Write(sb, DocPosition.BeforeRootElement, _ancMgr);
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ return utf8.GetBytes(sb.ToString());
+ }
+
+ internal byte[] GetDigestedBytes(HashAlgorithm hash)
+ {
+ _c14nDoc.WriteHash(hash, DocPosition.BeforeRootElement, _ancMgr);
+ hash.TransformFinalBlock(new byte[0], 0, 0);
+ byte[] res = (byte[])hash.Hash.Clone();
+ // reinitialize the hash so it is still usable after the call
+ hash.Initialize();
+ return res;
+ }
+
+ private static void MarkInclusionStateForNodes(XmlNodeList nodeList, XmlDocument inputRoot, XmlDocument root)
+ {
+ CanonicalXmlNodeList elementList = new CanonicalXmlNodeList();
+ CanonicalXmlNodeList elementListCanonical = new CanonicalXmlNodeList();
+ elementList.Add(inputRoot);
+ elementListCanonical.Add(root);
+ int index = 0;
+
+ do
+ {
+ XmlNode currentNode = (XmlNode)elementList[index];
+ XmlNode currentNodeCanonical = (XmlNode)elementListCanonical[index];
+ XmlNodeList childNodes = currentNode.ChildNodes;
+ XmlNodeList childNodesCanonical = currentNodeCanonical.ChildNodes;
+ for (int i = 0; i < childNodes.Count; i++)
+ {
+ elementList.Add(childNodes[i]);
+ elementListCanonical.Add(childNodesCanonical[i]);
+
+ if (Utils.NodeInList(childNodes[i], nodeList))
+ {
+ MarkNodeAsIncluded(childNodesCanonical[i]);
+ }
+
+ XmlAttributeCollection attribNodes = childNodes[i].Attributes;
+ if (attribNodes != null)
+ {
+ for (int j = 0; j < attribNodes.Count; j++)
+ {
+ if (Utils.NodeInList(attribNodes[j], nodeList))
+ {
+ MarkNodeAsIncluded(childNodesCanonical[i].Attributes.Item(j));
+ }
+ }
+ }
+ }
+ index++;
+ } while (index < elementList.Count);
+ }
+
+ private static void MarkNodeAsIncluded(XmlNode node)
+ {
+ if (node is ICanonicalizableNode)
+ ((ICanonicalizableNode)node).IsInNodeSet = true;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ICanonicalizableNode.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ICanonicalizableNode.cs
new file mode 100644
index 0000000000..385e23a144
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ICanonicalizableNode.cs
@@ -0,0 +1,27 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the interface to be implemented by all subclasses of XmlNode
+ // that have to provide node subsetting and canonicalization features.
+ internal interface ICanonicalizableNode
+ {
+ bool IsInNodeSet
+ {
+ get;
+ set;
+ }
+
+ void Write(StringBuilder strBuilder, DocPosition docPos, AncestralNamespaceContextManager anc);
+ void WriteHash(HashAlgorithm hash, DocPosition docPos, AncestralNamespaceContextManager anc);
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/IRelDecryptor.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/IRelDecryptor.cs
new file mode 100644
index 0000000000..f5dc2f119a
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/IRelDecryptor.cs
@@ -0,0 +1,13 @@
+// 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.IO;
+
+namespace System.Security.Cryptography.Xml
+{
+ public interface IRelDecryptor
+ {
+ Stream Decrypt(EncryptionMethod encryptionMethod, KeyInfo keyInfo, Stream toDecrypt);
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfo.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfo.cs
new file mode 100644
index 0000000000..ebb9dc7a68
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfo.cs
@@ -0,0 +1,147 @@
+// 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.Collections;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class KeyInfo : IEnumerable
+ {
+ private string _id = null;
+ private ArrayList _keyInfoClauses;
+
+ //
+ // public constructors
+ //
+
+ public KeyInfo()
+ {
+ _keyInfoClauses = new ArrayList();
+ }
+
+ //
+ // public properties
+ //
+
+ public string Id
+ {
+ get { return _id; }
+ set { _id = value; }
+ }
+
+ public XmlElement GetXml()
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.PreserveWhitespace = true;
+ return GetXml(xmlDocument);
+ }
+
+ internal XmlElement GetXml(XmlDocument xmlDocument)
+ {
+ // Create the KeyInfo element itself
+ XmlElement keyInfoElement = xmlDocument.CreateElement("KeyInfo", SignedXml.XmlDsigNamespaceUrl);
+ if (!string.IsNullOrEmpty(_id))
+ {
+ keyInfoElement.SetAttribute("Id", _id);
+ }
+
+ // Add all the clauses that go underneath it
+ for (int i = 0; i < _keyInfoClauses.Count; ++i)
+ {
+ XmlElement xmlElement = ((KeyInfoClause)_keyInfoClauses[i]).GetXml(xmlDocument);
+ if (xmlElement != null)
+ {
+ keyInfoElement.AppendChild(xmlElement);
+ }
+ }
+ return keyInfoElement;
+ }
+
+ public void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ XmlElement keyInfoElement = value;
+ _id = Utils.GetAttribute(keyInfoElement, "Id", SignedXml.XmlDsigNamespaceUrl);
+
+ XmlNode child = keyInfoElement.FirstChild;
+ while (child != null)
+ {
+ XmlElement elem = child as XmlElement;
+ if (elem != null)
+ {
+ // Create the right type of KeyInfoClause; we use a combination of the namespace and tag name (local name)
+ string kicString = elem.NamespaceURI + " " + elem.LocalName;
+ // Special-case handling for KeyValue -- we have to go one level deeper
+ if (kicString == "http://www.w3.org/2000/09/xmldsig# KeyValue")
+ {
+ XmlNodeList nodeList2 = elem.ChildNodes;
+ foreach (XmlNode node2 in nodeList2)
+ {
+ XmlElement elem2 = node2 as XmlElement;
+ if (elem2 != null)
+ {
+ kicString += "/" + elem2.LocalName;
+ break;
+ }
+ }
+ }
+ KeyInfoClause keyInfoClause = (KeyInfoClause)CryptoConfig.CreateFromName(kicString);
+ // if we don't know what kind of KeyInfoClause we're looking at, use a generic KeyInfoNode:
+ if (keyInfoClause == null)
+ keyInfoClause = new KeyInfoNode();
+
+ // Ask the create clause to fill itself with the corresponding XML
+ keyInfoClause.LoadXml(elem);
+ // Add it to our list of KeyInfoClauses
+ AddClause(keyInfoClause);
+ }
+ child = child.NextSibling;
+ }
+ }
+
+ public int Count
+ {
+ get { return _keyInfoClauses.Count; }
+ }
+
+ //
+ // public constructors
+ //
+
+ public void AddClause(KeyInfoClause clause)
+ {
+ _keyInfoClauses.Add(clause);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _keyInfoClauses.GetEnumerator();
+ }
+
+ public IEnumerator GetEnumerator(Type requestedObjectType)
+ {
+ ArrayList requestedList = new ArrayList();
+
+ object tempObj;
+ IEnumerator tempEnum = _keyInfoClauses.GetEnumerator();
+
+ while (tempEnum.MoveNext())
+ {
+ tempObj = tempEnum.Current;
+ if (requestedObjectType.Equals(tempObj.GetType()))
+ requestedList.Add(tempObj);
+ }
+
+ return requestedList.GetEnumerator();
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoClause.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoClause.cs
new file mode 100644
index 0000000000..684749bad2
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoClause.cs
@@ -0,0 +1,30 @@
+// 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.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public abstract class KeyInfoClause
+ {
+ //
+ // protected constructors
+ //
+
+ protected KeyInfoClause() { }
+
+ //
+ // public methods
+ //
+
+ public abstract XmlElement GetXml();
+ internal virtual XmlElement GetXml(XmlDocument xmlDocument)
+ {
+ XmlElement keyInfo = GetXml();
+ return (XmlElement)xmlDocument.ImportNode(keyInfo, true);
+ }
+
+ public abstract void LoadXml(XmlElement element);
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoEncryptedKey.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoEncryptedKey.cs
new file mode 100644
index 0000000000..9aea758359
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoEncryptedKey.cs
@@ -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.Collections;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class KeyInfoEncryptedKey : KeyInfoClause
+ {
+ private EncryptedKey _encryptedKey;
+
+ public KeyInfoEncryptedKey() { }
+
+ public KeyInfoEncryptedKey(EncryptedKey encryptedKey)
+ {
+ _encryptedKey = encryptedKey;
+ }
+
+ public EncryptedKey EncryptedKey
+ {
+ get { return _encryptedKey; }
+ set { _encryptedKey = value; }
+ }
+
+ public override XmlElement GetXml()
+ {
+ if (_encryptedKey == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "KeyInfoEncryptedKey");
+ return _encryptedKey.GetXml();
+ }
+
+ internal override XmlElement GetXml(XmlDocument xmlDocument)
+ {
+ if (_encryptedKey == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "KeyInfoEncryptedKey");
+ return _encryptedKey.GetXml(xmlDocument);
+ }
+
+ public override void LoadXml(XmlElement value)
+ {
+ _encryptedKey = new EncryptedKey();
+ _encryptedKey.LoadXml(value);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoName.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoName.cs
new file mode 100644
index 0000000000..b5b29f2e13
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoName.cs
@@ -0,0 +1,66 @@
+// 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.Collections;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class KeyInfoName : KeyInfoClause
+ {
+ private string _keyName;
+
+ //
+ // public constructors
+ //
+
+ public KeyInfoName() : this(null) { }
+
+ public KeyInfoName(string keyName)
+ {
+ Value = keyName;
+ }
+
+ //
+ // public properties
+ //
+
+ public string Value
+ {
+ get { return _keyName; }
+ set { _keyName = value; }
+ }
+
+ //
+ // public methods
+ //
+
+ public override XmlElement GetXml()
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.PreserveWhitespace = true;
+ return GetXml(xmlDocument);
+ }
+
+ internal override XmlElement GetXml(XmlDocument xmlDocument)
+ {
+ XmlElement nameElement = xmlDocument.CreateElement("KeyName", SignedXml.XmlDsigNamespaceUrl);
+ nameElement.AppendChild(xmlDocument.CreateTextNode(_keyName));
+ return nameElement;
+ }
+
+ public override void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ XmlElement nameElement = value;
+ _keyName = nameElement.InnerText.Trim();
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoNode.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoNode.cs
new file mode 100644
index 0000000000..8dc21d9437
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoNode.cs
@@ -0,0 +1,62 @@
+// 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.Collections;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ // This is for generic, unknown nodes
+ public class KeyInfoNode : KeyInfoClause
+ {
+ private XmlElement _node;
+
+ //
+ // public constructors
+ //
+
+ public KeyInfoNode() { }
+
+ public KeyInfoNode(XmlElement node)
+ {
+ _node = node;
+ }
+
+ //
+ // public properties
+ //
+
+ public XmlElement Value
+ {
+ get { return _node; }
+ set { _node = value; }
+ }
+
+ //
+ // public methods
+ //
+
+ public override XmlElement GetXml()
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.PreserveWhitespace = true;
+ return GetXml(xmlDocument);
+ }
+
+ internal override XmlElement GetXml(XmlDocument xmlDocument)
+ {
+ return xmlDocument.ImportNode(_node, true) as XmlElement;
+ }
+
+ public override void LoadXml(XmlElement value)
+ {
+ _node = value;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoRetrievalMethod.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoRetrievalMethod.cs
new file mode 100644
index 0000000000..e0b98cb69e
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoRetrievalMethod.cs
@@ -0,0 +1,83 @@
+// 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.Collections;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class KeyInfoRetrievalMethod : KeyInfoClause
+ {
+ private string _uri;
+ private string _type;
+
+ //
+ // public constructors
+ //
+
+ public KeyInfoRetrievalMethod() { }
+
+ public KeyInfoRetrievalMethod(string strUri)
+ {
+ _uri = strUri;
+ }
+
+ public KeyInfoRetrievalMethod(string strUri, string typeName)
+ {
+ _uri = strUri;
+ _type = typeName;
+ }
+
+ //
+ // public properties
+ //
+
+ public string Uri
+ {
+ get { return _uri; }
+ set { _uri = value; }
+ }
+
+ public string Type
+ {
+ get { return _type; }
+ set { _type = value; }
+ }
+
+ public override XmlElement GetXml()
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.PreserveWhitespace = true;
+ return GetXml(xmlDocument);
+ }
+
+ internal override XmlElement GetXml(XmlDocument xmlDocument)
+ {
+ // Create the actual element
+ XmlElement retrievalMethodElement = xmlDocument.CreateElement("RetrievalMethod", SignedXml.XmlDsigNamespaceUrl);
+
+ if (!string.IsNullOrEmpty(_uri))
+ retrievalMethodElement.SetAttribute("URI", _uri);
+ if (!string.IsNullOrEmpty(_type))
+ retrievalMethodElement.SetAttribute("Type", _type);
+
+ return retrievalMethodElement;
+ }
+
+ public override void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ XmlElement retrievalMethodElement = value;
+ _uri = Utils.GetAttribute(value, "URI", SignedXml.XmlDsigNamespaceUrl);
+ _type = Utils.GetAttribute(value, "Type", SignedXml.XmlDsigNamespaceUrl);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoX509Data.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoX509Data.cs
new file mode 100644
index 0000000000..a2a8eb8141
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoX509Data.cs
@@ -0,0 +1,305 @@
+// 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.Collections;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class KeyInfoX509Data : KeyInfoClause
+ {
+ // An array of certificates representing the certificate chain
+ private ArrayList _certificates = null;
+ // An array of issuer serial structs
+ private ArrayList _issuerSerials = null;
+ // An array of SKIs
+ private ArrayList _subjectKeyIds = null;
+ // An array of subject names
+ private ArrayList _subjectNames = null;
+ // A raw byte data representing a certificate revocation list
+ private byte[] _CRL = null;
+
+ //
+ // public constructors
+ //
+
+ public KeyInfoX509Data() { }
+
+ public KeyInfoX509Data(byte[] rgbCert)
+ {
+ X509Certificate2 certificate = new X509Certificate2(rgbCert);
+ AddCertificate(certificate);
+ }
+
+ public KeyInfoX509Data(X509Certificate cert)
+ {
+ AddCertificate(cert);
+ }
+
+ public KeyInfoX509Data(X509Certificate cert, X509IncludeOption includeOption)
+ {
+ if (cert == null)
+ throw new ArgumentNullException("cert");
+
+ X509Certificate2 certificate = new X509Certificate2(cert);
+ X509ChainElementCollection elements = null;
+ X509Chain chain = null;
+ switch (includeOption)
+ {
+ case X509IncludeOption.ExcludeRoot:
+ // Build the certificate chain
+ chain = new X509Chain();
+ chain.Build(certificate);
+
+ // Can't honor the option if we only have a partial chain.
+ if ((chain.ChainStatus.Length > 0) &&
+ ((chain.ChainStatus[0].Status & X509ChainStatusFlags.PartialChain) == X509ChainStatusFlags.PartialChain))
+ throw new CryptographicException(CAPI.CERT_E_CHAINING);
+
+ elements = (X509ChainElementCollection)chain.ChainElements;
+ for (int index = 0; index < (X509Utils.IsSelfSigned(chain) ? 1 : elements.Count - 1); index++)
+ {
+ AddCertificate(elements[index].Certificate);
+ }
+ break;
+ case X509IncludeOption.EndCertOnly:
+ AddCertificate(certificate);
+ break;
+ case X509IncludeOption.WholeChain:
+ // Build the certificate chain
+ chain = new X509Chain();
+ chain.Build(certificate);
+
+ // Can't honor the option if we only have a partial chain.
+ if ((chain.ChainStatus.Length > 0) &&
+ ((chain.ChainStatus[0].Status & X509ChainStatusFlags.PartialChain) == X509ChainStatusFlags.PartialChain))
+ throw new CryptographicException(CAPI.CERT_E_CHAINING);
+
+ elements = (X509ChainElementCollection)chain.ChainElements;
+ foreach (X509ChainElement element in elements)
+ {
+ AddCertificate(element.Certificate);
+ }
+ break;
+ }
+ }
+
+ //
+ // public properties
+ //
+
+ public ArrayList Certificates
+ {
+ get { return _certificates; }
+ }
+
+ public void AddCertificate(X509Certificate certificate)
+ {
+ if (certificate == null)
+ throw new ArgumentNullException("certificate");
+
+ if (_certificates == null)
+ _certificates = new ArrayList();
+
+ X509Certificate2 x509 = new X509Certificate2(certificate);
+ _certificates.Add(x509);
+ }
+
+ public ArrayList SubjectKeyIds
+ {
+ get { return _subjectKeyIds; }
+ }
+
+ public void AddSubjectKeyId(byte[] subjectKeyId)
+ {
+ if (_subjectKeyIds == null)
+ _subjectKeyIds = new ArrayList();
+ _subjectKeyIds.Add(subjectKeyId);
+ }
+
+ public void AddSubjectKeyId(string subjectKeyId)
+ {
+ if (_subjectKeyIds == null)
+ _subjectKeyIds = new ArrayList();
+ _subjectKeyIds.Add(X509Utils.DecodeHexString(subjectKeyId));
+ }
+
+ public ArrayList SubjectNames
+ {
+ get { return _subjectNames; }
+ }
+
+ public void AddSubjectName(string subjectName)
+ {
+ if (_subjectNames == null)
+ _subjectNames = new ArrayList();
+ _subjectNames.Add(subjectName);
+ }
+
+ public ArrayList IssuerSerials
+ {
+ get { return _issuerSerials; }
+ }
+
+ public void AddIssuerSerial(string issuerName, string serialNumber)
+ {
+ BigInt h = new BigInt();
+ h.FromHexadecimal(serialNumber);
+ if (_issuerSerials == null)
+ _issuerSerials = new ArrayList();
+ _issuerSerials.Add(new X509IssuerSerial(issuerName, h.ToDecimal()));
+ }
+
+ // When we load an X509Data from Xml, we know the serial number is in decimal representation.
+ internal void InternalAddIssuerSerial(string issuerName, string serialNumber)
+ {
+ if (_issuerSerials == null)
+ _issuerSerials = new ArrayList();
+ _issuerSerials.Add(new X509IssuerSerial(issuerName, serialNumber));
+ }
+
+ public byte[] CRL
+ {
+ get { return _CRL; }
+ set { _CRL = value; }
+ }
+
+ //
+ // private methods
+ //
+
+ private void Clear()
+ {
+ _CRL = null;
+ if (_subjectKeyIds != null) _subjectKeyIds.Clear();
+ if (_subjectNames != null) _subjectNames.Clear();
+ if (_issuerSerials != null) _issuerSerials.Clear();
+ if (_certificates != null) _certificates.Clear();
+ }
+
+ //
+ // public methods
+ //
+
+ public override XmlElement GetXml()
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.PreserveWhitespace = true;
+ return GetXml(xmlDocument);
+ }
+
+ internal override XmlElement GetXml(XmlDocument xmlDocument)
+ {
+ XmlElement x509DataElement = xmlDocument.CreateElement("X509Data", SignedXml.XmlDsigNamespaceUrl);
+
+ if (_issuerSerials != null)
+ {
+ foreach (X509IssuerSerial issuerSerial in _issuerSerials)
+ {
+ XmlElement issuerSerialElement = xmlDocument.CreateElement("X509IssuerSerial", SignedXml.XmlDsigNamespaceUrl);
+ XmlElement issuerNameElement = xmlDocument.CreateElement("X509IssuerName", SignedXml.XmlDsigNamespaceUrl);
+ issuerNameElement.AppendChild(xmlDocument.CreateTextNode(issuerSerial.IssuerName));
+ issuerSerialElement.AppendChild(issuerNameElement);
+ XmlElement serialNumberElement = xmlDocument.CreateElement("X509SerialNumber", SignedXml.XmlDsigNamespaceUrl);
+ serialNumberElement.AppendChild(xmlDocument.CreateTextNode(issuerSerial.SerialNumber));
+ issuerSerialElement.AppendChild(serialNumberElement);
+ x509DataElement.AppendChild(issuerSerialElement);
+ }
+ }
+
+ if (_subjectKeyIds != null)
+ {
+ foreach (byte[] subjectKeyId in _subjectKeyIds)
+ {
+ XmlElement subjectKeyIdElement = xmlDocument.CreateElement("X509SKI", SignedXml.XmlDsigNamespaceUrl);
+ subjectKeyIdElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(subjectKeyId)));
+ x509DataElement.AppendChild(subjectKeyIdElement);
+ }
+ }
+
+ if (_subjectNames != null)
+ {
+ foreach (string subjectName in _subjectNames)
+ {
+ XmlElement subjectNameElement = xmlDocument.CreateElement("X509SubjectName", SignedXml.XmlDsigNamespaceUrl);
+ subjectNameElement.AppendChild(xmlDocument.CreateTextNode(subjectName));
+ x509DataElement.AppendChild(subjectNameElement);
+ }
+ }
+
+ if (_certificates != null)
+ {
+ foreach (X509Certificate certificate in _certificates)
+ {
+ XmlElement x509Element = xmlDocument.CreateElement("X509Certificate", SignedXml.XmlDsigNamespaceUrl);
+ x509Element.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(certificate.GetRawCertData())));
+ x509DataElement.AppendChild(x509Element);
+ }
+ }
+
+ if (_CRL != null)
+ {
+ XmlElement crlElement = xmlDocument.CreateElement("X509CRL", SignedXml.XmlDsigNamespaceUrl);
+ crlElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(_CRL)));
+ x509DataElement.AppendChild(crlElement);
+ }
+
+ return x509DataElement;
+ }
+
+ public override void LoadXml(XmlElement element)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ XmlNamespaceManager nsm = new XmlNamespaceManager(element.OwnerDocument.NameTable);
+ nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
+
+ XmlNodeList x509IssuerSerialNodes = element.SelectNodes("ds:X509IssuerSerial", nsm);
+ XmlNodeList x509SKINodes = element.SelectNodes("ds:X509SKI", nsm);
+ XmlNodeList x509SubjectNameNodes = element.SelectNodes("ds:X509SubjectName", nsm);
+ XmlNodeList x509CertificateNodes = element.SelectNodes("ds:X509Certificate", nsm);
+ XmlNodeList x509CRLNodes = element.SelectNodes("ds:X509CRL", nsm);
+
+ if ((x509CRLNodes.Count == 0 && x509IssuerSerialNodes.Count == 0 && x509SKINodes.Count == 0
+ && x509SubjectNameNodes.Count == 0 && x509CertificateNodes.Count == 0)) // Bad X509Data tag, or Empty tag
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "X509Data");
+
+ // Flush anything in the lists
+ Clear();
+
+ if (x509CRLNodes.Count != 0)
+ _CRL = Convert.FromBase64String(Utils.DiscardWhiteSpaces(x509CRLNodes.Item(0).InnerText));
+
+ foreach (XmlNode issuerSerialNode in x509IssuerSerialNodes)
+ {
+ XmlNode x509IssuerNameNode = issuerSerialNode.SelectSingleNode("ds:X509IssuerName", nsm);
+ XmlNode x509SerialNumberNode = issuerSerialNode.SelectSingleNode("ds:X509SerialNumber", nsm);
+ if (x509IssuerNameNode == null || x509SerialNumberNode == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "IssuerSerial");
+ InternalAddIssuerSerial(x509IssuerNameNode.InnerText.Trim(), x509SerialNumberNode.InnerText.Trim());
+ }
+
+ foreach (XmlNode node in x509SKINodes)
+ {
+ AddSubjectKeyId(Convert.FromBase64String(Utils.DiscardWhiteSpaces(node.InnerText)));
+ }
+
+ foreach (XmlNode node in x509SubjectNameNodes)
+ {
+ AddSubjectName(node.InnerText.Trim());
+ }
+
+ foreach (XmlNode node in x509CertificateNodes)
+ {
+ AddCertificate(new X509Certificate2(Convert.FromBase64String(Utils.DiscardWhiteSpaces(node.InnerText))));
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyReference.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyReference.cs
new file mode 100644
index 0000000000..ad1939cd25
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyReference.cs
@@ -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;
+using System.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public sealed class KeyReference : EncryptedReference
+ {
+ public KeyReference() : base()
+ {
+ ReferenceType = "KeyReference";
+ }
+
+ public KeyReference(string uri) : base(uri)
+ {
+ ReferenceType = "KeyReference";
+ }
+
+ public KeyReference(string uri, TransformChain transformChain) : base(uri, transformChain)
+ {
+ ReferenceType = "KeyReference";
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/MyXmlDocument.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/MyXmlDocument.cs
new file mode 100644
index 0000000000..b9f93ec432
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/MyXmlDocument.cs
@@ -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.
+
+using Microsoft.Win32;
+using System.Collections;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Permissions;
+using System.Text;
+using System.Threading;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ internal class MyXmlDocument : XmlDocument
+ {
+ protected override XmlAttribute CreateDefaultAttribute(string prefix, string localName, string namespaceURI)
+ {
+ return CreateAttribute(prefix, localName, namespaceURI);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceFrame.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceFrame.cs
new file mode 100644
index 0000000000..0084387f4b
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceFrame.cs
@@ -0,0 +1,48 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+
+namespace System.Security.Cryptography.Xml
+{
+ // the namespaces context corresponding to one XmlElement. the rendered list contains the namespace nodes that are actually
+ // rendered to the canonicalized output. the unrendered list contains the namespace nodes that are in the node set and have
+ // the XmlElement as the owner, but are not rendered.
+ internal class NamespaceFrame
+ {
+ private Hashtable _rendered = new Hashtable();
+ private Hashtable _unrendered = new Hashtable();
+
+ internal NamespaceFrame() { }
+
+ internal void AddRendered(XmlAttribute attr)
+ {
+ _rendered.Add(Utils.GetNamespacePrefix(attr), attr);
+ }
+
+ internal XmlAttribute GetRendered(string nsPrefix)
+ {
+ return (XmlAttribute)_rendered[nsPrefix];
+ }
+
+ internal void AddUnrendered(XmlAttribute attr)
+ {
+ _unrendered.Add(Utils.GetNamespacePrefix(attr), attr);
+ }
+
+ internal XmlAttribute GetUnrendered(string nsPrefix)
+ {
+ return (XmlAttribute)_unrendered[nsPrefix];
+ }
+
+ internal Hashtable GetUnrendered()
+ {
+ return _unrendered;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceSortOrder.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceSortOrder.cs
new file mode 100644
index 0000000000..f54cdd3da4
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceSortOrder.cs
@@ -0,0 +1,31 @@
+// 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.Xml;
+using System.IO;
+using System.Text;
+using System.Collections;
+
+namespace System.Security.Cryptography.Xml
+{
+ internal class NamespaceSortOrder : IComparer
+ {
+ internal NamespaceSortOrder() { }
+
+ public int Compare(object a, object b)
+ {
+ XmlNode nodeA = a as XmlNode;
+ XmlNode nodeB = b as XmlNode;
+ if ((a == null) || (b == null))
+ throw new ArgumentException();
+ bool nodeAdefault = Utils.IsDefaultNamespaceNode(nodeA);
+ bool nodeBdefault = Utils.IsDefaultNamespaceNode(nodeB);
+ if (nodeAdefault && nodeBdefault) return 0;
+ if (nodeAdefault) return -1;
+ if (nodeBdefault) return 1;
+ return string.CompareOrdinal(nodeA.LocalName, nodeB.LocalName);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAKeyValue.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAKeyValue.cs
new file mode 100644
index 0000000000..2c1f1738cf
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAKeyValue.cs
@@ -0,0 +1,80 @@
+// 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.Collections;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class RSAKeyValue : KeyInfoClause
+ {
+ private RSA _key;
+
+ //
+ // public constructors
+ //
+
+ public RSAKeyValue()
+ {
+ _key = RSA.Create();
+ }
+
+ public RSAKeyValue(RSA key)
+ {
+ _key = key;
+ }
+
+ //
+ // public properties
+ //
+
+ public RSA Key
+ {
+ get { return _key; }
+ set { _key = value; }
+ }
+
+ //
+ // public methods
+ //
+
+ public override XmlElement GetXml()
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.PreserveWhitespace = true;
+ return GetXml(xmlDocument);
+ }
+
+ internal override XmlElement GetXml(XmlDocument xmlDocument)
+ {
+ RSAParameters rsaParams = _key.ExportParameters(false);
+
+ XmlElement keyValueElement = xmlDocument.CreateElement("KeyValue", SignedXml.XmlDsigNamespaceUrl);
+ XmlElement rsaKeyValueElement = xmlDocument.CreateElement("RSAKeyValue", SignedXml.XmlDsigNamespaceUrl);
+
+ XmlElement modulusElement = xmlDocument.CreateElement("Modulus", SignedXml.XmlDsigNamespaceUrl);
+ modulusElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(rsaParams.Modulus)));
+ rsaKeyValueElement.AppendChild(modulusElement);
+
+ XmlElement exponentElement = xmlDocument.CreateElement("Exponent", SignedXml.XmlDsigNamespaceUrl);
+ exponentElement.AppendChild(xmlDocument.CreateTextNode(Convert.ToBase64String(rsaParams.Exponent)));
+ rsaKeyValueElement.AppendChild(exponentElement);
+
+ keyValueElement.AppendChild(rsaKeyValueElement);
+
+ return keyValueElement;
+ }
+
+ public override void LoadXml(XmlElement value)
+ {
+ // Until RSA implements FromXmlString, throw here
+ throw new PlatformNotSupportedException();
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs
new file mode 100644
index 0000000000..156bff06ac
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs
@@ -0,0 +1,461 @@
+// 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.IO;
+using System.Net;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Xml;
+using System.Globalization;
+using System.Runtime.Versioning;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class Reference
+ {
+ private string _id;
+ private string _uri;
+ private string _type;
+ private TransformChain _transformChain;
+ private string _digestMethod;
+ private byte[] _digestValue;
+ private HashAlgorithm _hashAlgorithm;
+ private object _refTarget;
+ private ReferenceTargetType _refTargetType;
+ private XmlElement _cachedXml;
+ private SignedXml _signedXml = null;
+ internal CanonicalXmlNodeList _namespaces = null;
+
+ //
+ // public constructors
+ //
+
+ public Reference()
+ {
+ _transformChain = new TransformChain();
+ _refTarget = null;
+ _refTargetType = ReferenceTargetType.UriReference;
+ _cachedXml = null;
+ _digestMethod = SignedXml.XmlDsigSHA1Url;
+ }
+
+ public Reference(Stream stream)
+ {
+ _transformChain = new TransformChain();
+ _refTarget = stream;
+ _refTargetType = ReferenceTargetType.Stream;
+ _cachedXml = null;
+ _digestMethod = SignedXml.XmlDsigSHA1Url;
+ }
+
+ public Reference(string uri)
+ {
+ _transformChain = new TransformChain();
+ _refTarget = uri;
+ _uri = uri;
+ _refTargetType = ReferenceTargetType.UriReference;
+ _cachedXml = null;
+ _digestMethod = SignedXml.XmlDsigSHA1Url;
+ }
+
+ internal Reference(XmlElement element)
+ {
+ _transformChain = new TransformChain();
+ _refTarget = element;
+ _refTargetType = ReferenceTargetType.XmlElement;
+ _cachedXml = null;
+ _digestMethod = SignedXml.XmlDsigSHA1Url;
+ }
+
+ //
+ // public properties
+ //
+
+ public string Id
+ {
+ get { return _id; }
+ set { _id = value; }
+ }
+
+ public string Uri
+ {
+ get { return _uri; }
+ set
+ {
+ _uri = value;
+ _cachedXml = null;
+ }
+ }
+
+ public string Type
+ {
+ get { return _type; }
+ set
+ {
+ _type = value;
+ _cachedXml = null;
+ }
+ }
+
+ public string DigestMethod
+ {
+ get { return _digestMethod; }
+ set
+ {
+ _digestMethod = value;
+ _cachedXml = null;
+ }
+ }
+
+ public byte[] DigestValue
+ {
+ get { return _digestValue; }
+ set
+ {
+ _digestValue = value;
+ _cachedXml = null;
+ }
+ }
+
+ public TransformChain TransformChain
+ {
+ get
+ {
+ if (_transformChain == null)
+ _transformChain = new TransformChain();
+ return _transformChain;
+ }
+ set
+ {
+ _transformChain = value;
+ _cachedXml = null;
+ }
+ }
+
+ internal bool CacheValid
+ {
+ get
+ {
+ return (_cachedXml != null);
+ }
+ }
+
+ internal SignedXml SignedXml
+ {
+ get { return _signedXml; }
+ set { _signedXml = value; }
+ }
+
+ internal ReferenceTargetType ReferenceTargetType
+ {
+ get
+ {
+ return _refTargetType;
+ }
+ }
+
+ //
+ // public methods
+ //
+
+ public XmlElement GetXml()
+ {
+ if (CacheValid) return (_cachedXml);
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ // Create the Reference
+ XmlElement referenceElement = document.CreateElement("Reference", SignedXml.XmlDsigNamespaceUrl);
+
+ if (!string.IsNullOrEmpty(_id))
+ referenceElement.SetAttribute("Id", _id);
+
+ if (_uri != null)
+ referenceElement.SetAttribute("URI", _uri);
+
+ if (!string.IsNullOrEmpty(_type))
+ referenceElement.SetAttribute("Type", _type);
+
+ // Add the transforms to the Reference
+ if (TransformChain.Count != 0)
+ referenceElement.AppendChild(TransformChain.GetXml(document, SignedXml.XmlDsigNamespaceUrl));
+
+ // Add the DigestMethod
+ if (string.IsNullOrEmpty(_digestMethod))
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_DigestMethodRequired"));
+
+ XmlElement digestMethodElement = document.CreateElement("DigestMethod", SignedXml.XmlDsigNamespaceUrl);
+ digestMethodElement.SetAttribute("Algorithm", _digestMethod);
+ referenceElement.AppendChild(digestMethodElement);
+
+ if (DigestValue == null)
+ {
+ if (_hashAlgorithm.Hash == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_DigestValueRequired"));
+ DigestValue = _hashAlgorithm.Hash;
+ }
+
+ XmlElement digestValueElement = document.CreateElement("DigestValue", SignedXml.XmlDsigNamespaceUrl);
+ digestValueElement.AppendChild(document.CreateTextNode(Convert.ToBase64String(_digestValue)));
+ referenceElement.AppendChild(digestValueElement);
+
+ return referenceElement;
+ }
+
+ public void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _id = Utils.GetAttribute(value, "Id", SignedXml.XmlDsigNamespaceUrl);
+ _uri = Utils.GetAttribute(value, "URI", SignedXml.XmlDsigNamespaceUrl);
+ _type = Utils.GetAttribute(value, "Type", SignedXml.XmlDsigNamespaceUrl);
+
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
+
+ // Transforms
+ TransformChain = new TransformChain();
+ XmlElement transformsElement = value.SelectSingleNode("ds:Transforms", nsm) as XmlElement;
+ if (transformsElement != null)
+ {
+ XmlNodeList transformNodes = transformsElement.SelectNodes("ds:Transform", nsm);
+ if (transformNodes != null)
+ {
+ foreach (XmlNode transformNode in transformNodes)
+ {
+ XmlElement transformElement = transformNode as XmlElement;
+ string algorithm = Utils.GetAttribute(transformElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl);
+ Transform transform = CryptoConfig.CreateFromName(algorithm) as Transform;
+ if (transform == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UnknownTransform"));
+ AddTransform(transform);
+ // let the transform read the children of the transformElement for data
+ transform.LoadInnerXml(transformElement.ChildNodes);
+ // Hack! this is done to get around the lack of here() function support in XPath
+ if (transform is XmlDsigEnvelopedSignatureTransform)
+ {
+ // Walk back to the Signature tag. Find the nearest signature ancestor
+ // Signature-->SignedInfo-->Reference-->Transforms-->Transform
+ XmlNode signatureTag = transformElement.SelectSingleNode("ancestor::ds:Signature[1]", nsm);
+ XmlNodeList signatureList = transformElement.SelectNodes("//ds:Signature", nsm);
+ if (signatureList != null)
+ {
+ int position = 0;
+ foreach (XmlNode node in signatureList)
+ {
+ position++;
+ if (node == signatureTag)
+ {
+ ((XmlDsigEnvelopedSignatureTransform)transform).SignaturePosition = position;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // DigestMethod
+ XmlElement digestMethodElement = value.SelectSingleNode("ds:DigestMethod", nsm) as XmlElement;
+ if (digestMethodElement == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "Reference/DigestMethod");
+ _digestMethod = Utils.GetAttribute(digestMethodElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl);
+
+ // DigestValue
+ XmlElement digestValueElement = value.SelectSingleNode("ds:DigestValue", nsm) as XmlElement;
+ if (digestValueElement == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "Reference/DigestValue");
+ _digestValue = Convert.FromBase64String(Utils.DiscardWhiteSpaces(digestValueElement.InnerText));
+
+ // cache the Xml
+ _cachedXml = value;
+ }
+
+ public void AddTransform(Transform transform)
+ {
+ if (transform == null)
+ throw new ArgumentNullException("transform");
+
+ transform.Reference = this;
+ TransformChain.Add(transform);
+ }
+
+ internal void UpdateHashValue(XmlDocument document, CanonicalXmlNodeList refList)
+ {
+ DigestValue = CalculateHashValue(document, refList);
+ }
+
+ // What we want to do is pump the input throug the TransformChain and then
+ // hash the output of the chain document is the document context for resolving relative references
+ [ResourceExposure(ResourceScope.None)]
+ [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
+ internal byte[] CalculateHashValue(XmlDocument document, CanonicalXmlNodeList refList)
+ {
+ // refList is a list of elements that might be targets of references
+ // Now's the time to create our hashing algorithm
+ _hashAlgorithm = CryptoConfig.CreateFromName(_digestMethod) as HashAlgorithm;
+ if (_hashAlgorithm == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CreateHashAlgorithmFailed"));
+
+ // Let's go get the target.
+ string baseUri = (document == null ? System.Environment.CurrentDirectory + "\\" : document.BaseURI);
+ Stream hashInputStream = null;
+ WebRequest request = null;
+ WebResponse response = null;
+ Stream inputStream = null;
+ XmlResolver resolver = null;
+ byte[] hashval = null;
+
+ try
+ {
+ switch (_refTargetType)
+ {
+ case ReferenceTargetType.Stream:
+ // This is the easiest case. We already have a stream, so just pump it through the TransformChain
+ resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri));
+ hashInputStream = TransformChain.TransformToOctetStream((Stream)_refTarget, resolver, baseUri);
+ break;
+ case ReferenceTargetType.UriReference:
+ // Second-easiest case -- dereference the URI & pump through the TransformChain
+ // handle the special cases where the URI is null (meaning whole doc)
+ // or the URI is just a fragment (meaning a reference to an embedded Object)
+ if (_uri == null)
+ {
+ // We need to create a DocumentNavigator out of the XmlElement
+ resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri));
+ // In the case of a Uri-less reference, we will simply pass null to the transform chain.
+ // The first transform in the chain is expected to know how to retrieve the data to hash.
+ hashInputStream = TransformChain.TransformToOctetStream((Stream)null, resolver, baseUri);
+ }
+ else if (_uri.Length == 0)
+ {
+ // This is the self-referential case. First, check that we have a document context.
+ // The Enveloped Signature does not discard comments as per spec; those will be omitted during the transform chain process
+ if (document == null)
+ throw new CryptographicException(string.Format(CultureInfo.CurrentCulture, SecurityResources.GetResourceString("Cryptography_Xml_SelfReferenceRequiresContext"), _uri));
+
+ // Normalize the containing document
+ resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri));
+ XmlDocument docWithNoComments = Utils.DiscardComments(Utils.PreProcessDocumentInput(document, resolver, baseUri));
+ hashInputStream = TransformChain.TransformToOctetStream(docWithNoComments, resolver, baseUri);
+ }
+ else if (_uri[0] == '#')
+ {
+ // If we get here, then we are constructing a Reference to an embedded DataObject
+ // referenced by an Id = attribute. Go find the relevant object
+ bool discardComments = true;
+ string idref = Utils.GetIdFromLocalUri(_uri, out discardComments);
+ if (idref == "xpointer(/)")
+ {
+ // This is a self referencial case
+ if (document == null)
+ throw new CryptographicException(string.Format(CultureInfo.CurrentCulture, SecurityResources.GetResourceString("Cryptography_Xml_SelfReferenceRequiresContext"), _uri));
+
+ // We should not discard comments here!!!
+ resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri));
+ hashInputStream = TransformChain.TransformToOctetStream(Utils.PreProcessDocumentInput(document, resolver, baseUri), resolver, baseUri);
+ break;
+ }
+
+ XmlElement elem = SignedXml.GetIdElement(document, idref);
+ if (elem != null)
+ _namespaces = Utils.GetPropagatedAttributes(elem.ParentNode as XmlElement);
+
+ if (elem == null)
+ {
+ // Go throw the referenced items passed in
+ if (refList != null)
+ {
+ foreach (XmlNode node in refList)
+ {
+ XmlElement tempElem = node as XmlElement;
+ if ((tempElem != null) && (Utils.HasAttribute(tempElem, "Id", SignedXml.XmlDsigNamespaceUrl))
+ && (Utils.GetAttribute(tempElem, "Id", SignedXml.XmlDsigNamespaceUrl).Equals(idref)))
+ {
+ elem = tempElem;
+ if (_signedXml._context != null)
+ _namespaces = Utils.GetPropagatedAttributes(_signedXml._context);
+ break;
+ }
+ }
+ }
+ }
+
+ if (elem == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidReference"));
+
+ XmlDocument normDocument = Utils.PreProcessElementInput(elem, resolver, baseUri);
+ // Add the propagated attributes
+ Utils.AddNamespaces(normDocument.DocumentElement, _namespaces);
+
+ resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri));
+ if (discardComments)
+ {
+ // We should discard comments before going into the transform chain
+ XmlDocument docWithNoComments = Utils.DiscardComments(normDocument);
+ hashInputStream = TransformChain.TransformToOctetStream(docWithNoComments, resolver, baseUri);
+ }
+ else
+ {
+ // This is an XPointer reference, do not discard comments!!!
+ hashInputStream = TransformChain.TransformToOctetStream(normDocument, resolver, baseUri);
+ }
+ }
+ else if (Utils.AllowDetachedSignature())
+ {
+ // WebRequest always expects an Absolute Uri, so try to resolve if we were passed a relative Uri.
+ System.Uri uri = new System.Uri(_uri, UriKind.RelativeOrAbsolute);
+ if (!uri.IsAbsoluteUri)
+ {
+ uri = new Uri(new Uri(baseUri), uri);
+ }
+ request = WebRequest.Create(uri);
+ if (request == null) goto default;
+ response = request.GetResponse();
+ if (response == null) goto default;
+ inputStream = response.GetResponseStream();
+ if (inputStream == null) goto default;
+ resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri));
+ hashInputStream = TransformChain.TransformToOctetStream(inputStream, resolver, _uri);
+ }
+ else
+ {
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotResolved"), _uri);
+ }
+ break;
+ case ReferenceTargetType.XmlElement:
+ // We need to create a DocumentNavigator out of the XmlElement
+ resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri));
+ hashInputStream = TransformChain.TransformToOctetStream(Utils.PreProcessElementInput((XmlElement)_refTarget, resolver, baseUri), resolver, baseUri);
+ break;
+ default:
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotResolved"), _uri);
+ }
+
+ // Compute the new hash value
+ hashInputStream = SignedXmlDebugLog.LogReferenceData(this, hashInputStream);
+ hashval = _hashAlgorithm.ComputeHash(hashInputStream);
+ }
+ finally
+ {
+ if (hashInputStream != null)
+ hashInputStream.Close();
+ if (response != null)
+ response.Close();
+ if (inputStream != null)
+ inputStream.Close();
+ }
+
+ return hashval;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ReferenceList.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ReferenceList.cs
new file mode 100644
index 0000000000..ef1b7ed85c
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ReferenceList.cs
@@ -0,0 +1,138 @@
+// 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.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace System.Security.Cryptography.Xml
+{
+ public sealed class ReferenceList : IList
+ {
+ private ArrayList _references;
+
+ public ReferenceList()
+ {
+ _references = new ArrayList();
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _references.GetEnumerator();
+ }
+
+ public int Count
+ {
+ get { return _references.Count; }
+ }
+
+ public int Add(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!(value is DataReference) && !(value is KeyReference))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+
+ return _references.Add(value);
+ }
+
+ public void Clear()
+ {
+ _references.Clear();
+ }
+
+ public bool Contains(object value)
+ {
+ return _references.Contains(value);
+ }
+
+ public int IndexOf(object value)
+ {
+ return _references.IndexOf(value);
+ }
+
+ public void Insert(int index, object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!(value is DataReference) && !(value is KeyReference))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+
+ _references.Insert(index, value);
+ }
+
+ public void Remove(object value)
+ {
+ _references.Remove(value);
+ }
+
+ public void RemoveAt(int index)
+ {
+ _references.RemoveAt(index);
+ }
+
+ public EncryptedReference Item(int index)
+ {
+ return (EncryptedReference)_references[index];
+ }
+
+ [System.Runtime.CompilerServices.IndexerName("ItemOf")]
+ public EncryptedReference this[int index]
+ {
+ get
+ {
+ return Item(index);
+ }
+ set
+ {
+ ((IList)this)[index] = value;
+ }
+ }
+
+ /// <internalonly/>
+ object IList.this[int index]
+ {
+ get { return _references[index]; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!(value is DataReference) && !(value is KeyReference))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "value");
+
+ _references[index] = value;
+ }
+ }
+
+ public void CopyTo(Array array, int index)
+ {
+ _references.CopyTo(array, index);
+ }
+
+ bool IList.IsFixedSize
+ {
+ get { return _references.IsFixedSize; }
+ }
+
+ bool IList.IsReadOnly
+ {
+ get { return _references.IsReadOnly; }
+ }
+
+ public object SyncRoot
+ {
+ get { return _references.SyncRoot; }
+ }
+
+ public bool IsSynchronized
+ {
+ get { return _references.IsSynchronized; }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ReferenceTargetType.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ReferenceTargetType.cs
new file mode 100644
index 0000000000..762929a7f3
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/ReferenceTargetType.cs
@@ -0,0 +1,16 @@
+// 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;
+
+namespace System.Security.Cryptography.Xml
+{
+ [Serializable]
+ internal enum ReferenceTargetType
+ {
+ Stream,
+ XmlElement,
+ UriReference
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Signature.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Signature.cs
new file mode 100644
index 0000000000..88e751cbd6
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Signature.cs
@@ -0,0 +1,215 @@
+// 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.Collections;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class Signature
+ {
+ private string _id;
+ private SignedInfo _signedInfo;
+ private byte[] _signatureValue;
+ private string _signatureValueId;
+ private KeyInfo _keyInfo;
+ private IList _embeddedObjects;
+ private CanonicalXmlNodeList _referencedItems;
+ private SignedXml _signedXml = null;
+
+ internal SignedXml SignedXml
+ {
+ get { return _signedXml; }
+ set { _signedXml = value; }
+ }
+
+ //
+ // public constructors
+ //
+
+ public Signature()
+ {
+ _embeddedObjects = new ArrayList();
+ _referencedItems = new CanonicalXmlNodeList();
+ }
+
+ //
+ // public properties
+ //
+
+ public string Id
+ {
+ get { return _id; }
+ set { _id = value; }
+ }
+
+ public SignedInfo SignedInfo
+ {
+ get { return _signedInfo; }
+ set
+ {
+ _signedInfo = value;
+ if (SignedXml != null && _signedInfo != null)
+ _signedInfo.SignedXml = SignedXml;
+ }
+ }
+
+ public byte[] SignatureValue
+ {
+ get { return _signatureValue; }
+ set { _signatureValue = value; }
+ }
+
+ public KeyInfo KeyInfo
+ {
+ get
+ {
+ if (_keyInfo == null)
+ _keyInfo = new KeyInfo();
+ return _keyInfo;
+ }
+ set { _keyInfo = value; }
+ }
+
+ public IList ObjectList
+ {
+ get { return _embeddedObjects; }
+ set { _embeddedObjects = value; }
+ }
+
+ internal CanonicalXmlNodeList ReferencedItems
+ {
+ get { return _referencedItems; }
+ }
+
+ //
+ // public methods
+ //
+
+ public XmlElement GetXml()
+ {
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ // Create the Signature
+ XmlElement signatureElement = (XmlElement)document.CreateElement("Signature", SignedXml.XmlDsigNamespaceUrl);
+ if (!string.IsNullOrEmpty(_id))
+ signatureElement.SetAttribute("Id", _id);
+
+ // Add the SignedInfo
+ if (_signedInfo == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_SignedInfoRequired"));
+
+ signatureElement.AppendChild(_signedInfo.GetXml(document));
+
+ // Add the SignatureValue
+ if (_signatureValue == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_SignatureValueRequired"));
+
+ XmlElement signatureValueElement = document.CreateElement("SignatureValue", SignedXml.XmlDsigNamespaceUrl);
+ signatureValueElement.AppendChild(document.CreateTextNode(Convert.ToBase64String(_signatureValue)));
+ if (!string.IsNullOrEmpty(_signatureValueId))
+ signatureValueElement.SetAttribute("Id", _signatureValueId);
+ signatureElement.AppendChild(signatureValueElement);
+
+ // Add the KeyInfo
+ if (KeyInfo.Count > 0)
+ signatureElement.AppendChild(KeyInfo.GetXml(document));
+
+ // Add the Objects
+ foreach (object obj in _embeddedObjects)
+ {
+ DataObject dataObj = obj as DataObject;
+ if (dataObj != null)
+ {
+ signatureElement.AppendChild(dataObj.GetXml(document));
+ }
+ }
+
+ return signatureElement;
+ }
+
+ public void LoadXml(XmlElement value)
+ {
+ // Make sure we don't get passed null
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ // Signature
+ XmlElement signatureElement = value;
+ if (!signatureElement.LocalName.Equals("Signature"))
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "Signature");
+
+ // Id attribute -- optional
+ _id = Utils.GetAttribute(signatureElement, "Id", SignedXml.XmlDsigNamespaceUrl);
+
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
+
+ // SignedInfo
+ XmlElement signedInfoElement = signatureElement.SelectSingleNode("ds:SignedInfo", nsm) as XmlElement;
+ if (signedInfoElement == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "SignedInfo");
+
+ SignedInfo = new SignedInfo();
+ SignedInfo.LoadXml(signedInfoElement);
+
+ // SignatureValue
+ XmlElement signatureValueElement = signatureElement.SelectSingleNode("ds:SignatureValue", nsm) as XmlElement;
+ if (signatureValueElement == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "SignedInfo/SignatureValue");
+ _signatureValue = Convert.FromBase64String(Utils.DiscardWhiteSpaces(signatureValueElement.InnerText));
+ _signatureValueId = Utils.GetAttribute(signatureValueElement, "Id", SignedXml.XmlDsigNamespaceUrl);
+
+ XmlNodeList keyInfoNodes = signatureElement.SelectNodes("ds:KeyInfo", nsm);
+ _keyInfo = new KeyInfo();
+ if (keyInfoNodes != null)
+ {
+ foreach (XmlNode node in keyInfoNodes)
+ {
+ XmlElement keyInfoElement = node as XmlElement;
+ if (keyInfoElement != null)
+ _keyInfo.LoadXml(keyInfoElement);
+ }
+ }
+
+ XmlNodeList objectNodes = signatureElement.SelectNodes("ds:Object", nsm);
+ _embeddedObjects.Clear();
+ if (objectNodes != null)
+ {
+ foreach (XmlNode node in objectNodes)
+ {
+ XmlElement objectElement = node as XmlElement;
+ if (objectElement != null)
+ {
+ DataObject dataObj = new DataObject();
+ dataObj.LoadXml(objectElement);
+ _embeddedObjects.Add(dataObj);
+ }
+ }
+ }
+
+ // Select all elements that have Id attributes
+ XmlNodeList nodeList = signatureElement.SelectNodes("//*[@Id]", nsm);
+ if (nodeList != null)
+ {
+ foreach (XmlNode node in nodeList)
+ {
+ _referencedItems.Add(node);
+ }
+ }
+ }
+
+ public void AddObject(DataObject dataObject)
+ {
+ _embeddedObjects.Add(dataObject);
+ }
+ }
+}
+
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedInfo.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedInfo.cs
new file mode 100644
index 0000000000..bd6167d3cb
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedInfo.cs
@@ -0,0 +1,268 @@
+// 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.Collections;
+using System.Runtime.InteropServices;
+using System.Xml;
+using System.Globalization;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class SignedInfo : ICollection
+ {
+ private string _id;
+ private string _canonicalizationMethod;
+ private string _signatureMethod;
+ private string _signatureLength;
+ private ArrayList _references;
+ private XmlElement _cachedXml = null;
+ private SignedXml _signedXml = null;
+ private Transform _canonicalizationMethodTransform = null;
+
+ internal SignedXml SignedXml
+ {
+ get { return _signedXml; }
+ set { _signedXml = value; }
+ }
+
+ public SignedInfo()
+ {
+ _references = new ArrayList();
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ throw new NotSupportedException();
+ }
+
+ public void CopyTo(Array array, int index)
+ {
+ throw new NotSupportedException();
+ }
+
+ public int Count
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public bool IsReadOnly
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public bool IsSynchronized
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public object SyncRoot
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ //
+ // public properties
+ //
+
+ public string Id
+ {
+ get { return _id; }
+ set
+ {
+ _id = value;
+ _cachedXml = null;
+ }
+ }
+
+ public string CanonicalizationMethod
+ {
+ get
+ {
+ // Default the canonicalization method to C14N
+ if (_canonicalizationMethod == null)
+ return SignedXml.XmlDsigC14NTransformUrl;
+ return _canonicalizationMethod;
+ }
+ set
+ {
+ _canonicalizationMethod = value;
+ _cachedXml = null;
+ }
+ }
+
+ public Transform CanonicalizationMethodObject
+ {
+ get
+ {
+ if (_canonicalizationMethodTransform == null)
+ {
+ _canonicalizationMethodTransform = CryptoConfig.CreateFromName(CanonicalizationMethod) as Transform;
+ if (_canonicalizationMethodTransform == null)
+ throw new CryptographicException(string.Format(CultureInfo.CurrentCulture, SecurityResources.GetResourceString("Cryptography_Xml_CreateTransformFailed"), CanonicalizationMethod));
+ _canonicalizationMethodTransform.SignedXml = SignedXml;
+ _canonicalizationMethodTransform.Reference = null;
+ }
+ return _canonicalizationMethodTransform;
+ }
+ }
+
+ public string SignatureMethod
+ {
+ get { return _signatureMethod; }
+ set
+ {
+ _signatureMethod = value;
+ _cachedXml = null;
+ }
+ }
+
+ public string SignatureLength
+ {
+ get { return _signatureLength; }
+ set
+ {
+ _signatureLength = value;
+ _cachedXml = null;
+ }
+ }
+
+ public ArrayList References
+ {
+ get { return _references; }
+ }
+
+ internal bool CacheValid
+ {
+ get
+ {
+ if (_cachedXml == null) return false;
+ // now check all the references
+ foreach (Reference reference in References)
+ {
+ if (!reference.CacheValid) return false;
+ }
+ return true;
+ }
+ }
+
+ //
+ // public methods
+ //
+
+ public XmlElement GetXml()
+ {
+ if (CacheValid) return _cachedXml;
+
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ // Create the root element
+ XmlElement signedInfoElement = document.CreateElement("SignedInfo", SignedXml.XmlDsigNamespaceUrl);
+ if (!string.IsNullOrEmpty(_id))
+ signedInfoElement.SetAttribute("Id", _id);
+
+ // Add the canonicalization method, defaults to SignedXml.XmlDsigNamespaceUrl
+ XmlElement canonicalizationMethodElement = CanonicalizationMethodObject.GetXml(document, "CanonicalizationMethod");
+ signedInfoElement.AppendChild(canonicalizationMethodElement);
+
+ // Add the signature method
+ if (string.IsNullOrEmpty(_signatureMethod))
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_SignatureMethodRequired"));
+
+ XmlElement signatureMethodElement = document.CreateElement("SignatureMethod", SignedXml.XmlDsigNamespaceUrl);
+ signatureMethodElement.SetAttribute("Algorithm", _signatureMethod);
+ // Add HMACOutputLength tag if we have one
+ if (_signatureLength != null)
+ {
+ XmlElement hmacLengthElement = document.CreateElement(null, "HMACOutputLength", SignedXml.XmlDsigNamespaceUrl);
+ XmlText outputLength = document.CreateTextNode(_signatureLength);
+ hmacLengthElement.AppendChild(outputLength);
+ signatureMethodElement.AppendChild(hmacLengthElement);
+ }
+
+ signedInfoElement.AppendChild(signatureMethodElement);
+
+ // Add the references
+ if (_references.Count == 0)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_ReferenceElementRequired"));
+
+ for (int i = 0; i < _references.Count; ++i)
+ {
+ Reference reference = (Reference)_references[i];
+ signedInfoElement.AppendChild(reference.GetXml(document));
+ }
+
+ return signedInfoElement;
+ }
+
+ public void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ // SignedInfo
+ XmlElement signedInfoElement = value;
+ if (!signedInfoElement.LocalName.Equals("SignedInfo"))
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "SignedInfo");
+
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
+
+ // Id attribute -- optional
+ _id = Utils.GetAttribute(signedInfoElement, "Id", SignedXml.XmlDsigNamespaceUrl);
+
+ // CanonicalizationMethod -- must be present
+ XmlElement canonicalizationMethodElement = signedInfoElement.SelectSingleNode("ds:CanonicalizationMethod", nsm) as XmlElement;
+ if (canonicalizationMethodElement == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "SignedInfo/CanonicalizationMethod");
+ _canonicalizationMethod = Utils.GetAttribute(canonicalizationMethodElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl);
+ _canonicalizationMethodTransform = null;
+ if (canonicalizationMethodElement.ChildNodes.Count > 0)
+ CanonicalizationMethodObject.LoadInnerXml(canonicalizationMethodElement.ChildNodes);
+
+ // SignatureMethod -- must be present
+ XmlElement signatureMethodElement = signedInfoElement.SelectSingleNode("ds:SignatureMethod", nsm) as XmlElement;
+ if (signatureMethodElement == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "SignedInfo/SignatureMethod");
+ _signatureMethod = Utils.GetAttribute(signatureMethodElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl);
+
+ // Now get the output length if we are using a MAC algorithm
+ XmlElement signatureLengthElement = signatureMethodElement.SelectSingleNode("ds:HMACOutputLength", nsm) as XmlElement;
+ if (signatureLengthElement != null)
+ _signatureLength = signatureLengthElement.InnerXml;
+
+ // flush out any reference that was there
+ _references.Clear();
+
+ XmlNodeList referenceNodes = signedInfoElement.SelectNodes("ds:Reference", nsm);
+ if (referenceNodes != null)
+ {
+ foreach (XmlNode node in referenceNodes)
+ {
+ XmlElement referenceElement = node as XmlElement;
+ Reference reference = new Reference();
+ AddReference(reference);
+ reference.LoadXml(referenceElement);
+ }
+ }
+
+ // Save away the cached value
+ _cachedXml = signedInfoElement;
+ }
+
+ public void AddReference(Reference reference)
+ {
+ if (reference == null)
+ throw new ArgumentNullException("reference");
+
+ reference.SignedXml = SignedXml;
+ _references.Add(reference);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs
new file mode 100644
index 0000000000..0fdb85e866
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs
@@ -0,0 +1,1199 @@
+// 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.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Globalization;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Permissions;
+using System.Xml;
+using Microsoft.Win32;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class SignedXml
+ {
+ protected Signature m_signature;
+ protected string m_strSigningKeyName;
+
+ private AsymmetricAlgorithm _signingKey;
+ private XmlDocument _containingDocument = null;
+ private IEnumerator _keyInfoEnum = null;
+ private X509Certificate2Collection _x509Collection = null;
+ private IEnumerator _x509Enum = null;
+
+ private bool[] _refProcessed = null;
+ private int[] _refLevelCache = null;
+
+ internal XmlResolver _xmlResolver = null;
+ internal XmlElement _context = null;
+ private bool _bResolverSet = false;
+
+ private Func<SignedXml, bool> _signatureFormatValidator = DefaultSignatureFormatValidator;
+ private Collection<string> _safeCanonicalizationMethods;
+
+ // Built in canonicalization algorithm URIs
+ private static IList<string> s_knownCanonicalizationMethods = null;
+ // Built in transform algorithm URIs (excluding canonicalization URIs)
+ private static IList<string> s_defaultSafeTransformMethods = null;
+
+ // additional HMAC Url identifiers
+ private const string XmlDsigMoreHMACMD5Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-md5";
+ private const string XmlDsigMoreHMACSHA256Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
+ private const string XmlDsigMoreHMACSHA384Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384";
+ private const string XmlDsigMoreHMACSHA512Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512";
+ private const string XmlDsigMoreHMACRIPEMD160Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160";
+
+ // defines the XML encryption processing rules
+ private EncryptedXml _exml = null;
+
+ //
+ // public constant Url identifiers most frequently used within the XML Signature classes
+ //
+
+ public const string XmlDsigNamespaceUrl = "http://www.w3.org/2000/09/xmldsig#";
+ public const string XmlDsigMinimalCanonicalizationUrl = "http://www.w3.org/2000/09/xmldsig#minimal";
+ public const string XmlDsigCanonicalizationUrl = XmlDsigC14NTransformUrl;
+ public const string XmlDsigCanonicalizationWithCommentsUrl = XmlDsigC14NWithCommentsTransformUrl;
+
+ public const string XmlDsigSHA1Url = "http://www.w3.org/2000/09/xmldsig#sha1";
+ public const string XmlDsigDSAUrl = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
+ public const string XmlDsigRSASHA1Url = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
+ public const string XmlDsigHMACSHA1Url = "http://www.w3.org/2000/09/xmldsig#hmac-sha1";
+
+ public const string XmlDsigSHA256Url = "http://www.w3.org/2001/04/xmlenc#sha256";
+ public const string XmlDsigRSASHA256Url = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
+
+ // Yes, SHA384 is in the xmldsig-more namespace even though all the other SHA variants are in xmlenc. That's the standard.
+ public const string XmlDsigSHA384Url = "http://www.w3.org/2001/04/xmldsig-more#sha384";
+ public const string XmlDsigRSASHA384Url = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384";
+
+ public const string XmlDsigSHA512Url = "http://www.w3.org/2001/04/xmlenc#sha512";
+ public const string XmlDsigRSASHA512Url = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";
+
+ public const string XmlDsigC14NTransformUrl = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
+ public const string XmlDsigC14NWithCommentsTransformUrl = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments";
+ public const string XmlDsigExcC14NTransformUrl = "http://www.w3.org/2001/10/xml-exc-c14n#";
+ public const string XmlDsigExcC14NWithCommentsTransformUrl = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";
+ public const string XmlDsigBase64TransformUrl = "http://www.w3.org/2000/09/xmldsig#base64";
+ public const string XmlDsigXPathTransformUrl = "http://www.w3.org/TR/1999/REC-xpath-19991116";
+ public const string XmlDsigXsltTransformUrl = "http://www.w3.org/TR/1999/REC-xslt-19991116";
+ public const string XmlDsigEnvelopedSignatureTransformUrl = "http://www.w3.org/2000/09/xmldsig#enveloped-signature";
+ public const string XmlDecryptionTransformUrl = "http://www.w3.org/2002/07/decrypt#XML";
+ public const string XmlLicenseTransformUrl = "urn:mpeg:mpeg21:2003:01-REL-R-NS:licenseTransform";
+
+ //
+ // public constructors
+ //
+
+ public SignedXml()
+ {
+ Initialize(null);
+ }
+
+ public SignedXml(XmlDocument document)
+ {
+ if (document == null)
+ throw new ArgumentNullException("document");
+ Initialize(document.DocumentElement);
+ }
+
+ public SignedXml(XmlElement elem)
+ {
+ if (elem == null)
+ throw new ArgumentNullException("elem");
+ Initialize(elem);
+ }
+
+ private void Initialize(XmlElement element)
+ {
+ _containingDocument = (element == null ? null : element.OwnerDocument);
+ _context = element;
+ m_signature = new Signature();
+ m_signature.SignedXml = this;
+ m_signature.SignedInfo = new SignedInfo();
+ _signingKey = null;
+
+ _safeCanonicalizationMethods = new Collection<string>(KnownCanonicalizationMethods);
+ }
+
+ //
+ // public properties
+ //
+
+ /// <internalonly/>
+ public string SigningKeyName
+ {
+ get { return m_strSigningKeyName; }
+ set { m_strSigningKeyName = value; }
+ }
+
+ public XmlResolver Resolver
+ {
+ // This property only has a setter. The rationale for this is that we don't have a good value
+ // to return when it has not been explicitely set, as we are using XmlSecureResolver by default
+ set
+ {
+ _xmlResolver = value;
+ _bResolverSet = true;
+ }
+ }
+
+ internal bool ResolverSet
+ {
+ get { return _bResolverSet; }
+ }
+
+ public Func<SignedXml, bool> SignatureFormatValidator
+ {
+ get { return _signatureFormatValidator; }
+ set { _signatureFormatValidator = value; }
+ }
+
+ public Collection<string> SafeCanonicalizationMethods
+ {
+ get { return _safeCanonicalizationMethods; }
+ }
+
+ public AsymmetricAlgorithm SigningKey
+ {
+ get { return _signingKey; }
+ set { _signingKey = value; }
+ }
+
+ public EncryptedXml EncryptedXml
+ {
+ get
+ {
+ if (_exml == null)
+ _exml = new EncryptedXml(_containingDocument); // default processing rules
+ return _exml;
+ }
+ set { _exml = value; }
+ }
+
+ public Signature Signature
+ {
+ get { return m_signature; }
+ }
+
+ public SignedInfo SignedInfo
+ {
+ get { return m_signature.SignedInfo; }
+ }
+
+ public string SignatureMethod
+ {
+ get { return m_signature.SignedInfo.SignatureMethod; }
+ }
+
+ public string SignatureLength
+ {
+ get { return m_signature.SignedInfo.SignatureLength; }
+ }
+
+ public byte[] SignatureValue
+ {
+ get { return m_signature.SignatureValue; }
+ }
+
+ public KeyInfo KeyInfo
+ {
+ get { return m_signature.KeyInfo; }
+ set { m_signature.KeyInfo = value; }
+ }
+
+ public XmlElement GetXml()
+ {
+ // If we have a document context, then return a signature element in this context
+ if (_containingDocument != null)
+ return m_signature.GetXml(_containingDocument);
+ else
+ return m_signature.GetXml();
+ }
+
+ public void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ m_signature.LoadXml(value);
+
+ if (_context == null)
+ {
+ _context = value;
+ }
+
+ _bCacheValid = false;
+ }
+
+ //
+ // public methods
+ //
+
+ public void AddReference(Reference reference)
+ {
+ m_signature.SignedInfo.AddReference(reference);
+ }
+
+ public void AddObject(DataObject dataObject)
+ {
+ m_signature.AddObject(dataObject);
+ }
+
+ public bool CheckSignature()
+ {
+ AsymmetricAlgorithm signingKey;
+ return CheckSignatureReturningKey(out signingKey);
+ }
+
+ public bool CheckSignatureReturningKey(out AsymmetricAlgorithm signingKey)
+ {
+ SignedXmlDebugLog.LogBeginSignatureVerification(this, _context);
+
+ signingKey = null;
+ bool bRet = false;
+ AsymmetricAlgorithm key = null;
+
+ if (!CheckSignatureFormat())
+ {
+ return false;
+ }
+
+ do
+ {
+ key = GetPublicKey();
+ if (key != null)
+ {
+ bRet = CheckSignature(key);
+ SignedXmlDebugLog.LogVerificationResult(this, key, bRet);
+ }
+ } while (key != null && bRet == false);
+
+ signingKey = key;
+ return bRet;
+ }
+
+ public bool CheckSignature(AsymmetricAlgorithm key)
+ {
+ if (!CheckSignatureFormat())
+ {
+ return false;
+ }
+
+ if (!CheckSignedInfo(key))
+ {
+ SignedXmlDebugLog.LogVerificationFailure(this, SecurityResources.GetResourceString("Log_VerificationFailed_SignedInfo"));
+ return false;
+ }
+
+ // Now is the time to go through all the references and see if their DigestValues are good
+ if (!CheckDigestedReferences())
+ {
+ SignedXmlDebugLog.LogVerificationFailure(this, SecurityResources.GetResourceString("Log_VerificationFailed_References"));
+ return false;
+ }
+
+ SignedXmlDebugLog.LogVerificationResult(this, key, true);
+ return true;
+ }
+
+ public bool CheckSignature(KeyedHashAlgorithm macAlg)
+ {
+ if (!CheckSignatureFormat())
+ {
+ return false;
+ }
+
+ if (!CheckSignedInfo(macAlg))
+ {
+ SignedXmlDebugLog.LogVerificationFailure(this, SecurityResources.GetResourceString("Log_VerificationFailed_SignedInfo"));
+ return false;
+ }
+
+ if (!CheckDigestedReferences())
+ {
+ SignedXmlDebugLog.LogVerificationFailure(this, SecurityResources.GetResourceString("Log_VerificationFailed_References"));
+ return false;
+ }
+
+ SignedXmlDebugLog.LogVerificationResult(this, macAlg, true);
+ return true;
+ }
+
+ public bool CheckSignature(X509Certificate2 certificate, bool verifySignatureOnly)
+ {
+ if (!verifySignatureOnly)
+ {
+ // Check key usages to make sure it is good for signing.
+ foreach (X509Extension extension in certificate.Extensions)
+ {
+ if (string.Compare(extension.Oid.Value, CAPI.szOID_KEY_USAGE, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ X509KeyUsageExtension keyUsage = new X509KeyUsageExtension();
+ keyUsage.CopyFrom(extension);
+ SignedXmlDebugLog.LogVerifyKeyUsage(this, certificate, keyUsage);
+
+ bool validKeyUsage = (keyUsage.KeyUsages & X509KeyUsageFlags.DigitalSignature) != 0 ||
+ (keyUsage.KeyUsages & X509KeyUsageFlags.NonRepudiation) != 0;
+
+ if (!validKeyUsage)
+ {
+ SignedXmlDebugLog.LogVerificationFailure(this, SecurityResources.GetResourceString("Log_VerificationFailed_X509KeyUsage"));
+ return false;
+ }
+ break;
+ }
+ }
+
+ // Do the chain verification to make sure the certificate is valid.
+ X509Chain chain = new X509Chain();
+ chain.ChainPolicy.ExtraStore.AddRange(BuildBagOfCerts());
+ bool chainVerified = chain.Build(certificate);
+ SignedXmlDebugLog.LogVerifyX509Chain(this, chain, certificate);
+
+ if (!chainVerified)
+ {
+ SignedXmlDebugLog.LogVerificationFailure(this, SecurityResources.GetResourceString("Log_VerificationFailed_X509Chain"));
+ return false;
+ }
+ }
+
+ if (!CheckSignature(certificate.GetAnyPublicKey()))
+ {
+ return false;
+ }
+
+ SignedXmlDebugLog.LogVerificationResult(this, certificate, true);
+ return true;
+ }
+
+ public void ComputeSignature()
+ {
+ SignedXmlDebugLog.LogBeginSignatureComputation(this, _context);
+
+ BuildDigestedReferences();
+
+ // Load the key
+ AsymmetricAlgorithm key = SigningKey;
+
+ if (key == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_LoadKeyFailed"));
+
+ // Check the signature algorithm associated with the key so that we can accordingly set the signature method
+ if (SignedInfo.SignatureMethod == null)
+ {
+ if (key is DSA)
+ {
+ SignedInfo.SignatureMethod = XmlDsigDSAUrl;
+ }
+ else if (key is RSA)
+ {
+ // Default to RSA-SHA1
+ if (SignedInfo.SignatureMethod == null)
+ SignedInfo.SignatureMethod = XmlDsigRSASHA1Url;
+ }
+ else
+ {
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CreatedKeyFailed"));
+ }
+ }
+
+ // See if there is a signature description class defined in the Config file
+ SignatureDescription signatureDescription = CryptoConfig.CreateFromName(SignedInfo.SignatureMethod) as SignatureDescription;
+ if (signatureDescription == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_SignatureDescriptionNotCreated"));
+ HashAlgorithm hashAlg = signatureDescription.CreateDigest();
+ if (hashAlg == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CreateHashAlgorithmFailed"));
+ byte[] hashvalue = GetC14NDigest(hashAlg);
+ AsymmetricSignatureFormatter asymmetricSignatureFormatter = signatureDescription.CreateFormatter(key);
+
+ SignedXmlDebugLog.LogSigning(this, key, signatureDescription, hashAlg, asymmetricSignatureFormatter);
+ m_signature.SignatureValue = asymmetricSignatureFormatter.CreateSignature(hashAlg);
+ }
+
+ public void ComputeSignature(KeyedHashAlgorithm macAlg)
+ {
+ if (macAlg == null)
+ throw new ArgumentNullException("macAlg");
+
+ HMAC hash = macAlg as HMAC;
+ if (hash == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_SignatureMethodKeyMismatch"));
+
+ int signatureLength;
+ if (m_signature.SignedInfo.SignatureLength == null)
+ signatureLength = hash.HashSize;
+ else
+ signatureLength = Convert.ToInt32(m_signature.SignedInfo.SignatureLength, null);
+ // signatureLength should be less than hash size
+ if (signatureLength < 0 || signatureLength > hash.HashSize)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidSignatureLength"));
+ if (signatureLength % 8 != 0)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidSignatureLength2"));
+
+ BuildDigestedReferences();
+ switch (hash.HashName)
+ {
+ case "SHA1":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigHMACSHA1Url;
+ break;
+ case "SHA256":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACSHA256Url;
+ break;
+ case "SHA384":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACSHA384Url;
+ break;
+ case "SHA512":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACSHA512Url;
+ break;
+ case "MD5":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACMD5Url;
+ break;
+ case "RIPEMD160":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACRIPEMD160Url;
+ break;
+ default:
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_SignatureMethodKeyMismatch"));
+ }
+
+ byte[] hashValue = GetC14NDigest(hash);
+
+ SignedXmlDebugLog.LogSigning(this, hash);
+ m_signature.SignatureValue = new byte[signatureLength / 8];
+ Buffer.BlockCopy(hashValue, 0, m_signature.SignatureValue, 0, signatureLength / 8);
+ }
+
+ //
+ // virtual methods
+ //
+
+ protected virtual AsymmetricAlgorithm GetPublicKey()
+ {
+ if (KeyInfo == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KeyInfoRequired"));
+
+ if (_x509Enum != null)
+ {
+ AsymmetricAlgorithm key = GetNextCertificatePublicKey();
+ if (key != null)
+ return key;
+ }
+
+ if (_keyInfoEnum == null)
+ _keyInfoEnum = KeyInfo.GetEnumerator();
+
+ // In our implementation, we move to the next KeyInfo clause which is an RSAKeyValue, DSAKeyValue or KeyInfoX509Data
+ while (_keyInfoEnum.MoveNext())
+ {
+ RSAKeyValue rsaKeyValue = _keyInfoEnum.Current as RSAKeyValue;
+ if (rsaKeyValue != null)
+ return rsaKeyValue.Key;
+
+ DSAKeyValue dsaKeyValue = _keyInfoEnum.Current as DSAKeyValue;
+ if (dsaKeyValue != null)
+ return dsaKeyValue.Key;
+
+ KeyInfoX509Data x509Data = _keyInfoEnum.Current as KeyInfoX509Data;
+ if (x509Data != null)
+ {
+ _x509Collection = Utils.BuildBagOfCerts(x509Data, CertUsageType.Verification);
+ if (_x509Collection.Count > 0)
+ {
+ _x509Enum = _x509Collection.GetEnumerator();
+ AsymmetricAlgorithm key = GetNextCertificatePublicKey();
+ if (key != null)
+ return key;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private X509Certificate2Collection BuildBagOfCerts()
+ {
+ X509Certificate2Collection collection = new X509Certificate2Collection();
+ if (KeyInfo != null)
+ {
+ foreach (KeyInfoClause clause in KeyInfo)
+ {
+ KeyInfoX509Data x509Data = clause as KeyInfoX509Data;
+ if (x509Data != null)
+ collection.AddRange(Utils.BuildBagOfCerts(x509Data, CertUsageType.Verification));
+ }
+ }
+
+ return collection;
+ }
+
+ private AsymmetricAlgorithm GetNextCertificatePublicKey()
+ {
+ while (_x509Enum.MoveNext())
+ {
+ X509Certificate2 certificate = (X509Certificate2)_x509Enum.Current;
+ if (certificate != null)
+ return certificate.GetAnyPublicKey();
+ }
+
+ return null;
+ }
+
+ public virtual XmlElement GetIdElement(XmlDocument document, string idValue)
+ {
+ return DefaultGetIdElement(document, idValue);
+ }
+
+ internal static XmlElement DefaultGetIdElement(XmlDocument document, string idValue)
+ {
+ if (document == null)
+ return null;
+
+ if (Utils.RequireNCNameIdentifier())
+ {
+ try
+ {
+ XmlConvert.VerifyNCName(idValue);
+ }
+ catch (XmlException)
+ {
+ // Identifiers are required to be an NCName
+ // (xml:id version 1.0, part 4, paragraph 2, bullet 1)
+ //
+ // If it isn't an NCName, it isn't allowed to match.
+ return null;
+ }
+ }
+
+ // Get the element with idValue
+ XmlElement elem = document.GetElementById(idValue);
+
+ if (elem != null)
+ {
+ if (!Utils.AllowAmbiguousReferenceTargets())
+ {
+ // Have to check for duplicate ID values from the DTD.
+
+ XmlDocument docClone = (XmlDocument)document.CloneNode(true);
+ XmlElement cloneElem = docClone.GetElementById(idValue);
+
+ // If it's null here we want to know about it, because it means that
+ // GetElementById failed to work across the cloning, and our uniqueness
+ // test is invalid.
+ System.Diagnostics.Debug.Assert(cloneElem != null);
+
+ // Guard against null anyways
+ if (cloneElem != null)
+ {
+ cloneElem.Attributes.RemoveAll();
+
+ XmlElement cloneElem2 = docClone.GetElementById(idValue);
+
+ if (cloneElem2 != null)
+ {
+ throw new CryptographicException(
+ SecurityResources.GetResourceString("Cryptography_Xml_InvalidReference"));
+ }
+ }
+ }
+
+ return elem;
+ }
+
+ elem = GetSingleReferenceTarget(document, "Id", idValue);
+ if (elem != null)
+ return elem;
+ elem = GetSingleReferenceTarget(document, "id", idValue);
+ if (elem != null)
+ return elem;
+ elem = GetSingleReferenceTarget(document, "ID", idValue);
+
+ return elem;
+ }
+
+ //
+ // private methods
+ //
+
+ private bool _bCacheValid = false;
+ private byte[] _digestedSignedInfo = null;
+
+ private static bool DefaultSignatureFormatValidator(SignedXml signedXml)
+ {
+ // Reject the signature if it uses a truncated HMAC
+ if (signedXml.DoesSignatureUseTruncatedHmac())
+ {
+ return false;
+ }
+
+ // Reject the signature if it uses a canonicalization algorithm other than
+ // one of the ones explicitly allowed
+ if (!signedXml.DoesSignatureUseSafeCanonicalizationMethod())
+ {
+ return false;
+ }
+
+ // Otherwise accept it
+ return true;
+ }
+
+ // Validation function to see if the current signature is signed with a truncated HMAC - one which
+ // has a signature length of fewer bits than the whole HMAC output.
+ private bool DoesSignatureUseTruncatedHmac()
+ {
+ // If we're not using the SignatureLength property, then we're not truncating the signature length
+ if (SignedInfo.SignatureLength == null)
+ {
+ return false;
+ }
+
+ // See if we're signed witn an HMAC algorithm
+ HMAC hmac = CryptoConfig.CreateFromName(SignatureMethod) as HMAC;
+ if (hmac == null)
+ {
+ // We aren't signed with an HMAC algorithm, so we cannot have a truncated HMAC
+ return false;
+ }
+
+ // Figure out how many bits the signature is using
+ int actualSignatureSize = 0;
+ if (!int.TryParse(SignedInfo.SignatureLength, out actualSignatureSize))
+ {
+ // If the value wasn't a valid integer, then we'll conservatively reject it all together
+ return true;
+ }
+
+ // Make sure the full HMAC signature size is the same size that was specified in the XML
+ // signature. If the actual signature size is not exactly the same as the full HMAC size, then
+ // reject the signature.
+ return actualSignatureSize != hmac.HashSize;
+ }
+
+ // Validation function to see if the signature uses a canonicalization algorithm from our list
+ // of approved algorithm URIs.
+ private bool DoesSignatureUseSafeCanonicalizationMethod()
+ {
+ foreach (string safeAlgorithm in SafeCanonicalizationMethods)
+ {
+ if (string.Equals(safeAlgorithm, SignedInfo.CanonicalizationMethod, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ SignedXmlDebugLog.LogUnsafeCanonicalizationMethod(this, SignedInfo.CanonicalizationMethod, SafeCanonicalizationMethods);
+ return false;
+ }
+
+ private bool ReferenceUsesSafeTransformMethods(Reference reference)
+ {
+ TransformChain transformChain = reference.TransformChain;
+ int transformCount = transformChain.Count;
+
+ for (int i = 0; i < transformCount; i++)
+ {
+ Transform transform = transformChain[i];
+
+ if (!IsSafeTransform(transform.Algorithm))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private bool IsSafeTransform(string transformAlgorithm)
+ {
+ // All canonicalization algorithms are valid transform algorithms.
+ foreach (string safeAlgorithm in SafeCanonicalizationMethods)
+ {
+ if (string.Equals(safeAlgorithm, transformAlgorithm, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ foreach (string safeAlgorithm in DefaultSafeTransformMethods)
+ {
+ if (string.Equals(safeAlgorithm, transformAlgorithm, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ SignedXmlDebugLog.LogUnsafeTransformMethod(
+ this,
+ transformAlgorithm,
+ SafeCanonicalizationMethods,
+ DefaultSafeTransformMethods);
+
+ return false;
+ }
+
+ // Get a list of the built in canonicalization algorithms, as well as any that the machine admin has
+ // added to the valid set.
+ private static IList<string> KnownCanonicalizationMethods
+ {
+ get
+ {
+ if (s_knownCanonicalizationMethods == null)
+ {
+ // Start with the list that the machine admin added, if any
+ List<string> safeAlgorithms = ReadAdditionalSafeCanonicalizationMethods();
+
+ // And add the built in algorithms as well
+ safeAlgorithms.Add(XmlDsigC14NTransformUrl);
+ safeAlgorithms.Add(XmlDsigC14NWithCommentsTransformUrl);
+ safeAlgorithms.Add(XmlDsigExcC14NTransformUrl);
+ safeAlgorithms.Add(XmlDsigExcC14NWithCommentsTransformUrl);
+
+ s_knownCanonicalizationMethods = safeAlgorithms;
+ }
+
+ return s_knownCanonicalizationMethods;
+ }
+ }
+
+ private static IList<string> DefaultSafeTransformMethods
+ {
+ get
+ {
+ if (s_defaultSafeTransformMethods == null)
+ {
+ List<string> safeAlgorithms = ReadAdditionalSafeTransformMethods();
+
+ // And the built in algorithms
+
+ // KnownCanonicalizationMethods don't need to be added here, because
+ // the validator will automatically accept those.
+ //
+ // xmldsig 6.6.1:
+ // Any canonicalization algorithm that can be used for
+ // CanonicalizationMethod can be used as a Transform.
+ safeAlgorithms.Add(XmlDsigEnvelopedSignatureTransformUrl);
+ safeAlgorithms.Add(XmlDsigBase64TransformUrl);
+ safeAlgorithms.Add(XmlLicenseTransformUrl);
+ safeAlgorithms.Add(XmlDecryptionTransformUrl);
+
+ s_defaultSafeTransformMethods = safeAlgorithms;
+ }
+
+ return s_defaultSafeTransformMethods;
+ }
+ }
+
+ // Allow machine admins to add additional canonicalization algorithms that should be considered valid when
+ // validating XML signatuers by supplying a list in the
+ // HKLM\Software\Microsoft\.NETFramework\Security\SafeCanonicalizationMethods
+ // key. Each REG_SZ entry in this key will be considered a canonicalziation algorithm URI that should be
+ // allowed by SignedXml instances on this machine.
+ [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
+ private static List<string> ReadAdditionalSafeCanonicalizationMethods()
+ {
+ return ReadFxSecurityStringValues("SafeCanonicalizationMethods");
+ }
+
+ // Allow machine admins to add additional transform algorithms that should be considered valid when
+ // validating XML signatuers by supplying a list in the
+ // HKLM\Software\Microsoft\.NETFramework\Security\SafeTransformMethods
+ // key. Each REG_SZ entry in this key will be considered a transform algorithm URI that should be
+ // allowed by SignedXml instances on this machine.
+ [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
+ private static List<string> ReadAdditionalSafeTransformMethods()
+ {
+ return ReadFxSecurityStringValues("SafeTransformMethods");
+ }
+
+ private static List<string> ReadFxSecurityStringValues(string subkey)
+ {
+ List<string> values = new List<string>();
+
+ try
+ {
+ using (RegistryKey stringListKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework\Security\" + subkey, false))
+ {
+ if (stringListKey != null)
+ {
+ foreach (string value in stringListKey.GetValueNames())
+ {
+ if (stringListKey.GetValueKind(value) == RegistryValueKind.String)
+ {
+ string stringValue = stringListKey.GetValue(value) as string;
+ if (!string.IsNullOrWhiteSpace(stringValue))
+ {
+ values.Add(stringValue);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (SecurityException) { /* we could not open the key - that's fine, we can proceed with no additional values */ }
+ return values;
+ }
+
+ private byte[] GetC14NDigest(HashAlgorithm hash)
+ {
+ if (!_bCacheValid || !SignedInfo.CacheValid)
+ {
+ string baseUri = (_containingDocument == null ? null : _containingDocument.BaseURI);
+ XmlResolver resolver = (_bResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri));
+ XmlDocument doc = Utils.PreProcessElementInput(SignedInfo.GetXml(), resolver, baseUri);
+
+ // Add non default namespaces in scope
+ CanonicalXmlNodeList namespaces = (_context == null ? null : Utils.GetPropagatedAttributes(_context));
+ SignedXmlDebugLog.LogNamespacePropagation(this, namespaces);
+ Utils.AddNamespaces(doc.DocumentElement, namespaces);
+
+ Transform c14nMethodTransform = SignedInfo.CanonicalizationMethodObject;
+ c14nMethodTransform.Resolver = resolver;
+ c14nMethodTransform.BaseURI = baseUri;
+
+ SignedXmlDebugLog.LogBeginCanonicalization(this, c14nMethodTransform);
+ c14nMethodTransform.LoadInput(doc);
+ SignedXmlDebugLog.LogCanonicalizedOutput(this, c14nMethodTransform);
+ _digestedSignedInfo = c14nMethodTransform.GetDigestedOutput(hash);
+
+ _bCacheValid = true;
+ }
+ return _digestedSignedInfo;
+ }
+
+ private int GetReferenceLevel(int index, ArrayList references)
+ {
+ if (_refProcessed[index]) return _refLevelCache[index];
+ _refProcessed[index] = true;
+ Reference reference = (Reference)references[index];
+ if (reference.Uri == null || reference.Uri.Length == 0 || (reference.Uri.Length > 0 && reference.Uri[0] != '#'))
+ {
+ _refLevelCache[index] = 0;
+ return 0;
+ }
+ if (reference.Uri.Length > 0 && reference.Uri[0] == '#')
+ {
+ string idref = Utils.ExtractIdFromLocalUri(reference.Uri);
+ if (idref == "xpointer(/)")
+ {
+ _refLevelCache[index] = 0;
+ return 0;
+ }
+ // If this is pointing to another reference
+ for (int j = 0; j < references.Count; ++j)
+ {
+ if (((Reference)references[j]).Id == idref)
+ {
+ _refLevelCache[index] = GetReferenceLevel(j, references) + 1;
+ return (_refLevelCache[index]);
+ }
+ }
+ // Then the reference points to an object tag
+ _refLevelCache[index] = 0;
+ return 0;
+ }
+ // Malformed reference
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidReference"));
+ }
+
+ private class ReferenceLevelSortOrder : IComparer
+ {
+ private ArrayList _references = null;
+ public ReferenceLevelSortOrder() { }
+
+ public ArrayList References
+ {
+ get { return _references; }
+ set { _references = value; }
+ }
+
+ public int Compare(object a, object b)
+ {
+ Reference referenceA = a as Reference;
+ Reference referenceB = b as Reference;
+
+ // Get the indexes
+ int iIndexA = 0;
+ int iIndexB = 0;
+ int i = 0;
+ foreach (Reference reference in References)
+ {
+ if (reference == referenceA) iIndexA = i;
+ if (reference == referenceB) iIndexB = i;
+ i++;
+ }
+
+ int iLevelA = referenceA.SignedXml.GetReferenceLevel(iIndexA, References);
+ int iLevelB = referenceB.SignedXml.GetReferenceLevel(iIndexB, References);
+ return iLevelA.CompareTo(iLevelB);
+ }
+ }
+
+ private void BuildDigestedReferences()
+ {
+ // Default the DigestMethod and Canonicalization
+ ArrayList references = SignedInfo.References;
+ // Reset the cache
+ _refProcessed = new bool[references.Count];
+ _refLevelCache = new int[references.Count];
+
+ ReferenceLevelSortOrder sortOrder = new ReferenceLevelSortOrder();
+ sortOrder.References = references;
+ // Don't alter the order of the references array list
+ ArrayList sortedReferences = new ArrayList();
+ foreach (Reference reference in references)
+ {
+ sortedReferences.Add(reference);
+ }
+ sortedReferences.Sort(sortOrder);
+
+ CanonicalXmlNodeList nodeList = new CanonicalXmlNodeList();
+ foreach (DataObject obj in m_signature.ObjectList)
+ {
+ nodeList.Add(obj.GetXml());
+ }
+ foreach (Reference reference in sortedReferences)
+ {
+ // If no DigestMethod has yet been set, default it to sha1
+ if (reference.DigestMethod == null)
+ reference.DigestMethod = XmlDsigSHA1Url;
+
+ SignedXmlDebugLog.LogSigningReference(this, reference);
+
+ reference.UpdateHashValue(_containingDocument, nodeList);
+ // If this reference has an Id attribute, add it
+ if (reference.Id != null)
+ nodeList.Add(reference.GetXml());
+ }
+ }
+
+ private bool CheckDigestedReferences()
+ {
+ ArrayList references = m_signature.SignedInfo.References;
+ for (int i = 0; i < references.Count; ++i)
+ {
+ Reference digestedReference = (Reference)references[i];
+
+ if (!ReferenceUsesSafeTransformMethods(digestedReference))
+ {
+ return false;
+ }
+
+ SignedXmlDebugLog.LogVerifyReference(this, digestedReference);
+ byte[] calculatedHash = null;
+ try
+ {
+ calculatedHash = digestedReference.CalculateHashValue(_containingDocument, m_signature.ReferencedItems);
+ }
+ catch (CryptoSignedXmlRecursionException)
+ {
+ SignedXmlDebugLog.LogSignedXmlRecursionLimit(this, digestedReference);
+ return false;
+ }
+ // Compare both hashes
+ SignedXmlDebugLog.LogVerifyReferenceHash(this, digestedReference, calculatedHash, digestedReference.DigestValue);
+
+ if (!CryptographicEquals(calculatedHash, digestedReference.DigestValue))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // Methods _must_ be marked both No Inlining and No Optimization to be fully opted out of optimization.
+ // This is because if a candidate method is inlined, its method level attributes, including the NoOptimization
+ // attribute, are lost.
+ // This method makes no attempt to disguise the length of either of its inputs. It is assumed the attacker has
+ // knowledge of the algorithms used, and thus the output length. Length is difficult to properly blind in modern CPUs.
+ [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
+ private static bool CryptographicEquals(byte[] a, byte[] b)
+ {
+ System.Diagnostics.Debug.Assert(a != null);
+ System.Diagnostics.Debug.Assert(b != null);
+
+ int result = 0;
+
+ // Short cut if the lengths are not identical
+ if (a.Length != b.Length)
+ return false;
+
+ unchecked
+ {
+ // Normally this caching doesn't matter, but with the optimizer off, this nets a non-trivial speedup.
+ int aLength = a.Length;
+
+ for (int i = 0; i < aLength; i++)
+ // We use subtraction here instead of XOR because the XOR algorithm gets ever so
+ // slightly faster as more and more differences pile up.
+ // This cannot overflow more than once (and back to 0) because bytes are 1 byte
+ // in length, and result is 4 bytes. The OR propagates all set bytes, so the differences
+ // can't add up and overflow a second time.
+ result = result | (a[i] - b[i]);
+ }
+
+ return (0 == result);
+ }
+
+ // If we have a signature format validation callback, check to see if this signature's format (not
+ // the signautre itself) is valid according to the validator. A return value of true indicates that
+ // the signature format is acceptable, false means that the format is not valid.
+ private bool CheckSignatureFormat()
+ {
+ if (_signatureFormatValidator == null)
+ {
+ // No format validator means that we default to accepting the signature. (This is
+ // effectively compatibility mode with v3.5).
+ return true;
+ }
+
+ SignedXmlDebugLog.LogBeginCheckSignatureFormat(this, _signatureFormatValidator);
+
+ bool formatValid = _signatureFormatValidator(this);
+ SignedXmlDebugLog.LogFormatValidationResult(this, formatValid);
+ return formatValid;
+ }
+
+ private bool CheckSignedInfo(AsymmetricAlgorithm key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ SignedXmlDebugLog.LogBeginCheckSignedInfo(this, m_signature.SignedInfo);
+
+ SignatureDescription signatureDescription = CryptoConfig.CreateFromName(SignatureMethod) as SignatureDescription;
+ if (signatureDescription == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_SignatureDescriptionNotCreated"));
+
+ // Let's see if the key corresponds with the SignatureMethod
+ Type ta = Type.GetType(signatureDescription.KeyAlgorithm);
+ if (!IsKeyTheCorrectAlgorithm(key, ta))
+ return false;
+
+ HashAlgorithm hashAlgorithm = signatureDescription.CreateDigest();
+ if (hashAlgorithm == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CreateHashAlgorithmFailed"));
+ byte[] hashval = GetC14NDigest(hashAlgorithm);
+
+ AsymmetricSignatureDeformatter asymmetricSignatureDeformatter = signatureDescription.CreateDeformatter(key);
+ SignedXmlDebugLog.LogVerifySignedInfo(this,
+ key,
+ signatureDescription,
+ hashAlgorithm,
+ asymmetricSignatureDeformatter,
+ hashval,
+ m_signature.SignatureValue);
+ return asymmetricSignatureDeformatter.VerifySignature(hashval, m_signature.SignatureValue);
+ }
+
+ private bool CheckSignedInfo(KeyedHashAlgorithm macAlg)
+ {
+ if (macAlg == null)
+ throw new ArgumentNullException("macAlg");
+
+ SignedXmlDebugLog.LogBeginCheckSignedInfo(this, m_signature.SignedInfo);
+
+ int signatureLength;
+ if (m_signature.SignedInfo.SignatureLength == null)
+ signatureLength = macAlg.HashSize;
+ else
+ signatureLength = Convert.ToInt32(m_signature.SignedInfo.SignatureLength, null);
+
+ // signatureLength should be less than hash size
+ if (signatureLength < 0 || signatureLength > macAlg.HashSize)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidSignatureLength"));
+ if (signatureLength % 8 != 0)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidSignatureLength2"));
+ if (m_signature.SignatureValue == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_SignatureValueRequired"));
+ if (m_signature.SignatureValue.Length != signatureLength / 8)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidSignatureLength"));
+
+ // Calculate the hash
+ byte[] hashValue = GetC14NDigest(macAlg);
+ SignedXmlDebugLog.LogVerifySignedInfo(this, macAlg, hashValue, m_signature.SignatureValue);
+ for (int i = 0; i < m_signature.SignatureValue.Length; i++)
+ {
+ if (m_signature.SignatureValue[i] != hashValue[i]) return false;
+ }
+ return true;
+ }
+
+ private static XmlElement GetSingleReferenceTarget(XmlDocument document, string idAttributeName, string idValue)
+ {
+ // idValue has already been tested as an NCName (unless overridden for compatibility), so there's no
+ // escaping that needs to be done here.
+ string xPath = "//*[@" + idAttributeName + "=\"" + idValue + "\"]";
+
+ if (Utils.AllowAmbiguousReferenceTargets())
+ {
+ return document.SelectSingleNode(xPath) as XmlElement;
+ }
+
+ // http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel says that for the form URI="#chapter1":
+ //
+ // Identifies a node-set containing the element with ID attribute value 'chapter1' ...
+ //
+ // Note that it uses the singular. Therefore, if the match is ambiguous, we should consider the document invalid.
+ //
+ // In this case, we'll treat it the same as having found nothing across all fallbacks (but shortcut so that we don't
+ // fall into a trap of finding a secondary element which wasn't the originally signed one).
+
+ XmlNodeList nodeList = document.SelectNodes(xPath);
+
+ if (nodeList == null || nodeList.Count == 0)
+ {
+ return null;
+ }
+
+ if (nodeList.Count == 1)
+ {
+ return nodeList[0] as XmlElement;
+ }
+
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidReference"));
+ }
+
+ private static bool IsKeyTheCorrectAlgorithm(AsymmetricAlgorithm key, Type expectedType)
+ {
+ Type actualType = key.GetType();
+
+ if (actualType == expectedType)
+ return true;
+
+ // This check exists solely for compatibility with 4.6. Normally, we would expect "expectedType" to be the superclass type and
+ // the actualType to be the subclass.
+ if (expectedType.IsSubclassOf(actualType))
+ return true;
+
+ //
+ // "expectedType" comes from the KeyAlgorithm property of a SignatureDescription. The BCL SignatureDescription classes have historically
+ // denoted provider-specific implementations ("RSACryptoServiceProvider") rather than the base class for the algorithm ("RSA"). We could
+ // change those (at the risk of creating other compat problems) but we have no control over third party SignatureDescriptions.
+ //
+ // So, in the absence of a better approach, walk up the parent hierarchy until we find the ancestor that's a direct subclass of
+ // AsymmetricAlgorithm and treat that as the algorithm identifier.
+ //
+ while (expectedType != null && expectedType.BaseType != typeof(AsymmetricAlgorithm))
+ {
+ expectedType = expectedType.BaseType;
+ }
+
+ if (expectedType == null)
+ return false; // SignatureDescription specified something that isn't even a subclass of AsymmetricAlgorithm. For compatibility with 4.6, return false rather throw.
+
+ if (actualType.IsSubclassOf(expectedType))
+ return true;
+
+ return false;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs
new file mode 100644
index 0000000000..aca1e9b039
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs
@@ -0,0 +1,1080 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ /// <summary>
+ /// Trace support for debugging issues signing and verifying XML signatures.
+ /// </summary>
+ internal static class SignedXmlDebugLog
+ {
+ //
+ // In order to enable XML digital signature debug loggging, applications should setup their config
+ // file to be similar to the following:
+ //
+ // <configuration>
+ // <system.diagnostics>
+ // <sources>
+ // <source name="System.Security.Cryptography.Xml.SignedXml"
+ // switchName="XmlDsigLogSwitch">
+ // <listeners>
+ // <add name="logFile" />
+ // </listeners>
+ // </source>
+ // </sources>
+ // <switches>
+ // <add name="XmlDsigLogSwitch" value="Verbose" />
+ // </switches>
+ // <sharedListeners>
+ // <add name="logFile"
+ // type="System.Diagnostics.TextWriterTraceListener"
+ // initializeData="XmlDsigLog.txt"/>
+ // </sharedListeners>
+ // <trace autoflush="true">
+ // <listeners>
+ // <add name="logFile" />
+ // </listeners>
+ // </trace>
+ // </system.diagnostics>
+ // </configuration>
+ //
+
+ private const string NullString = "(null)";
+
+ private static TraceSource s_traceSource = new TraceSource("System.Security.Cryptography.Xml.SignedXml");
+ private static volatile bool s_haveVerboseLogging;
+ private static volatile bool s_verboseLogging;
+ private static volatile bool s_haveInformationLogging;
+ private static volatile bool s_informationLogging;
+
+ /// <summary>
+ /// Types of events that are logged to the debug log
+ /// </summary>
+ internal enum SignedXmlDebugEvent
+ {
+ /// <summary>
+ /// Canonicalization of input XML has begun
+ /// </summary>
+ BeginCanonicalization,
+
+ /// <summary>
+ /// Verificaiton of the signature format itself is beginning
+ /// </summary>
+ BeginCheckSignatureFormat,
+
+ /// <summary>
+ /// Verification of a signed info is beginning
+ /// </summary>
+ BeginCheckSignedInfo,
+
+ /// <summary>
+ /// Signing is beginning
+ /// </summary>
+ BeginSignatureComputation,
+
+ /// <summary>
+ /// Signature verification is beginning
+ /// </summary>
+ BeginSignatureVerification,
+
+ /// <summary>
+ /// Input data has been transformed to its canonicalized form
+ /// </summary>
+ CanonicalizedData,
+
+ /// <summary>
+ /// The result of signature format validation
+ /// </summary>
+ FormatValidationResult,
+
+ /// <summary>
+ /// Namespaces are being propigated into the signature
+ /// </summary>
+ NamespacePropagation,
+
+ /// <summary>
+ /// Output from a Reference
+ /// </summary>
+ ReferenceData,
+
+ /// <summary>
+ /// The result of a signature verification
+ /// </summary>
+ SignatureVerificationResult,
+
+ /// <summary>
+ /// Calculating the final signature
+ /// </summary>
+ Signing,
+
+ /// <summary>
+ /// A reference is being hashed
+ /// </summary>
+ SigningReference,
+
+ /// <summary>
+ /// A signature has failed to verify
+ /// </summary>
+ VerificationFailure,
+
+ /// <summary>
+ /// Verify that a reference has the correct hash value
+ /// </summary>
+ VerifyReference,
+
+ /// <summary>
+ /// Verification is processing the SignedInfo section of the signature
+ /// </summary>
+ VerifySignedInfo,
+
+ /// <summary>
+ /// Verification status on the x.509 certificate in use
+ /// </summary>
+ X509Verification,
+
+ /// <summary>
+ /// The signature is being rejected by the signature format verifier due to having
+ /// a canonicalization algorithm which is not on the known valid list.
+ /// </summary>
+ UnsafeCanonicalizationMethod,
+
+ /// <summary>
+ /// The signature is being rejected by the signature verifier due to having
+ /// a transform algorithm which is not on the known valid list.
+ /// </summary>
+ UnsafeTransformMethod,
+ }
+
+ /// <summary>
+ /// Check to see if logging should be done in this process
+ /// </summary>
+ private static bool InformationLoggingEnabled
+ {
+ get
+ {
+ if (!s_haveInformationLogging)
+ {
+ s_informationLogging = s_traceSource.Switch.ShouldTrace(TraceEventType.Information);
+ s_haveInformationLogging = true;
+ }
+
+ return s_informationLogging;
+ }
+ }
+
+ /// <summary>
+ /// Check to see if verbose log messages should be generated
+ /// </summary>
+ private static bool VerboseLoggingEnabled
+ {
+ get
+ {
+ if (!s_haveVerboseLogging)
+ {
+ s_verboseLogging = s_traceSource.Switch.ShouldTrace(TraceEventType.Verbose);
+ s_haveVerboseLogging = true;
+ }
+
+ return s_verboseLogging;
+ }
+ }
+
+ /// <summary>
+ /// Convert the byte array into a hex string
+ /// </summary>
+ private static string FormatBytes(byte[] bytes)
+ {
+ if (bytes == null)
+ return NullString;
+
+ StringBuilder builder = new StringBuilder(bytes.Length * 2);
+ foreach (byte b in bytes)
+ {
+ builder.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+ }
+
+ return builder.ToString();
+ }
+
+ /// <summary>
+ /// Map a key to a string describing the key
+ /// </summary>
+ private static string GetKeyName(object key)
+ {
+ Debug.Assert(key != null, "key != null");
+
+ ICspAsymmetricAlgorithm cspKey = key as ICspAsymmetricAlgorithm;
+ X509Certificate certificate = key as X509Certificate;
+ X509Certificate2 certificate2 = key as X509Certificate2;
+
+ //
+ // Use the following sources for key names, if available:
+ //
+ // * CAPI key -> key container name
+ // * X509Certificate2 -> subject simple name
+ // * X509Certificate -> subject name
+ // * All others -> hash code
+ //
+
+ string keyName = null;
+ if (cspKey != null && cspKey.CspKeyContainerInfo.KeyContainerName != null)
+ {
+ keyName = string.Format(CultureInfo.InvariantCulture,
+ "\"{0}\"",
+ cspKey.CspKeyContainerInfo.KeyContainerName);
+ }
+ else if (certificate2 != null)
+ {
+ keyName = string.Format(CultureInfo.InvariantCulture,
+ "\"{0}\"",
+ certificate2.GetNameInfo(X509NameType.SimpleName, false));
+ }
+ else if (certificate != null)
+ {
+ keyName = string.Format(CultureInfo.InvariantCulture,
+ "\"{0}\"",
+ certificate.Subject);
+ }
+ else
+ {
+ keyName = key.GetHashCode().ToString("x8", CultureInfo.InvariantCulture);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "{0}#{1}", key.GetType().Name, keyName);
+ }
+
+ /// <summary>
+ /// Map an object to a string describing the object
+ /// </summary>
+ private static string GetObjectId(object o)
+ {
+ Debug.Assert(o != null, "o != null");
+
+ return string.Format(CultureInfo.InvariantCulture,
+ "{0}#{1}", o.GetType().Name,
+ o.GetHashCode().ToString("x8", CultureInfo.InvariantCulture));
+ }
+
+ /// <summary>
+ /// Map an OID to the friendliest name possible
+ /// </summary>
+ private static string GetOidName(Oid oid)
+ {
+ Debug.Assert(oid != null, "oid != null");
+
+ string friendlyName = oid.FriendlyName;
+ if (string.IsNullOrEmpty(friendlyName))
+ friendlyName = oid.Value;
+
+ return friendlyName;
+ }
+
+ /// <summary>
+ /// Log that canonicalization has begun on input data
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the signing or verification</param>
+ /// <param name="canonicalizationTransform">transform canonicalizing the input</param>
+ internal static void LogBeginCanonicalization(SignedXml signedXml, Transform canonicalizationTransform)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(canonicalizationTransform != null, "canonicalizationTransform != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_BeginCanonicalization"),
+ canonicalizationTransform.Algorithm,
+ canonicalizationTransform.GetType().Name);
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.BeginCanonicalization,
+ logMessage);
+ }
+
+ if (VerboseLoggingEnabled)
+ {
+ string canonicalizationSettings = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_CanonicalizationSettings"),
+ canonicalizationTransform.Resolver.GetType(),
+ canonicalizationTransform.BaseURI);
+ WriteLine(signedXml,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.BeginCanonicalization,
+ canonicalizationSettings);
+ }
+ }
+
+ /// <summary>
+ /// Log that we're going to be validating the signature format itself
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the verification</param>
+ /// <param name="formatValidator">Callback delegate which is being used for format verification</param>
+ internal static void LogBeginCheckSignatureFormat(SignedXml signedXml, Func<SignedXml, bool> formatValidator)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(formatValidator != null, "formatValidator != null");
+
+ if (InformationLoggingEnabled)
+ {
+ MethodInfo validationMethod = formatValidator.Method;
+
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_CheckSignatureFormat"),
+ validationMethod.Module.Assembly.FullName,
+ validationMethod.DeclaringType.FullName,
+ validationMethod.Name);
+ WriteLine(signedXml, TraceEventType.Information, SignedXmlDebugEvent.BeginCheckSignatureFormat, logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log that checking SignedInfo is beginning
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the verification</param>
+ /// <param name="signedInfo">SignedInfo object being verified</param>
+ internal static void LogBeginCheckSignedInfo(SignedXml signedXml, SignedInfo signedInfo)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(signedInfo != null, " signedInfo != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_CheckSignedInfo"),
+ signedInfo.Id != null ? signedInfo.Id : NullString);
+ WriteLine(signedXml, TraceEventType.Information, SignedXmlDebugEvent.BeginCheckSignedInfo, logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log that signature computation is beginning
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the signing</param>
+ /// <param name="context">Context of the signature</param>
+ internal static void LogBeginSignatureComputation(SignedXml signedXml, XmlElement context)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+
+ if (InformationLoggingEnabled)
+ {
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.BeginSignatureComputation,
+ SecurityResources.GetResourceString("Log_BeginSignatureComputation"));
+ }
+
+ if (VerboseLoggingEnabled)
+ {
+ string contextData = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_XmlContext"),
+ context != null ? context.OuterXml : NullString);
+
+ WriteLine(signedXml,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.BeginSignatureComputation,
+ contextData);
+ }
+ }
+
+ /// <summary>
+ /// Log that signature verification is beginning
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the verification</param>
+ /// <param name="context">Context of the verification</param>
+ internal static void LogBeginSignatureVerification(SignedXml signedXml, XmlElement context)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+
+ if (InformationLoggingEnabled)
+ {
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.BeginSignatureVerification,
+ SecurityResources.GetResourceString("Log_BeginSignatureVerification"));
+ }
+
+ if (VerboseLoggingEnabled)
+ {
+ string contextData = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_XmlContext"),
+ context != null ? context.OuterXml : NullString);
+
+ WriteLine(signedXml,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.BeginSignatureVerification,
+ contextData);
+ }
+ }
+
+ /// <summary>
+ /// Log the canonicalized data
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the signing or verification</param>
+ /// <param name="canonicalizationTransform">transform canonicalizing the input</param>
+ internal static void LogCanonicalizedOutput(SignedXml signedXml, Transform canonicalizationTransform)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(canonicalizationTransform != null, "canonicalizationTransform != null");
+
+ if (VerboseLoggingEnabled)
+ {
+ using (StreamReader reader = new StreamReader(canonicalizationTransform.GetOutput(typeof(Stream)) as Stream))
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_CanonicalizedOutput"),
+ reader.ReadToEnd());
+ WriteLine(signedXml,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.CanonicalizedData,
+ logMessage);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Log that the signature format callback has rejected the signature
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the signature verification</param>
+ /// <param name="result">result of the signature format verification</param>
+ internal static void LogFormatValidationResult(SignedXml signedXml, bool result)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = result ? SecurityResources.GetResourceString("Log_FormatValidationSuccessful") :
+ SecurityResources.GetResourceString("Log_FormatValidationNotSuccessful");
+ WriteLine(signedXml, TraceEventType.Information, SignedXmlDebugEvent.FormatValidationResult, logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log that a signature is being rejected as having an invalid format due to its canonicalization
+ /// algorithm not being on the valid list.
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the signature verification</param>
+ /// <param name="result">result of the signature format verification</param>
+ internal static void LogUnsafeCanonicalizationMethod(SignedXml signedXml, string algorithm, IEnumerable<string> validAlgorithms)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(validAlgorithms != null, "validAlgorithms != null");
+
+ if (InformationLoggingEnabled)
+ {
+ StringBuilder validAlgorithmBuilder = new StringBuilder();
+ foreach (string validAlgorithm in validAlgorithms)
+ {
+ if (validAlgorithmBuilder.Length != 0)
+ {
+ validAlgorithmBuilder.Append(", ");
+ }
+
+ validAlgorithmBuilder.AppendFormat("\"{0}\"", validAlgorithm);
+ }
+
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_UnsafeCanonicalizationMethod"),
+ algorithm,
+ validAlgorithmBuilder.ToString());
+
+ WriteLine(signedXml, TraceEventType.Information, SignedXmlDebugEvent.UnsafeCanonicalizationMethod, logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log that a signature is being rejected as having an invalid signature due to a transform
+ /// algorithm not being on the valid list.
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the signature verification</param>
+ /// <param name="algorithm">Transform algorithm that was not allowed</param>
+ /// <param name="validC14nAlgorithms">The valid C14N algorithms</param>
+ /// <param name="validTransformAlgorithms">The valid C14N algorithms</param>
+ internal static void LogUnsafeTransformMethod(
+ SignedXml signedXml,
+ string algorithm,
+ IEnumerable<string> validC14nAlgorithms,
+ IEnumerable<string> validTransformAlgorithms)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(validC14nAlgorithms != null, "validC14nAlgorithms != null");
+ Debug.Assert(validTransformAlgorithms != null, "validTransformAlgorithms != null");
+
+ if (InformationLoggingEnabled)
+ {
+ StringBuilder validAlgorithmBuilder = new StringBuilder();
+ foreach (string validAlgorithm in validC14nAlgorithms)
+ {
+ if (validAlgorithmBuilder.Length != 0)
+ {
+ validAlgorithmBuilder.Append(", ");
+ }
+
+ validAlgorithmBuilder.AppendFormat("\"{0}\"", validAlgorithm);
+ }
+
+ foreach (string validAlgorithm in validTransformAlgorithms)
+ {
+ if (validAlgorithmBuilder.Length != 0)
+ {
+ validAlgorithmBuilder.Append(", ");
+ }
+
+ validAlgorithmBuilder.AppendFormat("\"{0}\"", validAlgorithm);
+ }
+
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_UnsafeTransformMethod"),
+ algorithm,
+ validAlgorithmBuilder.ToString());
+
+ WriteLine(signedXml, TraceEventType.Information, SignedXmlDebugEvent.UnsafeTransformMethod, logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log namespaces which are being propigated into the singature
+ /// </summary>
+ /// <param name="signedXml">SignedXml doing the signing or verification</param>
+ /// <param name="namespaces">namespaces being propigated</param>
+ internal static void LogNamespacePropagation(SignedXml signedXml, XmlNodeList namespaces)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+
+ if (InformationLoggingEnabled)
+ {
+ if (namespaces != null)
+ {
+ foreach (XmlAttribute propagatedNamespace in namespaces)
+ {
+ string propagationMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_PropagatingNamespace"),
+ propagatedNamespace.Name,
+ propagatedNamespace.Value);
+
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.NamespacePropagation,
+ propagationMessage);
+ }
+ }
+ else
+ {
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.NamespacePropagation,
+ SecurityResources.GetResourceString("Log_NoNamespacesPropagated"));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Log the output of a reference
+ /// </summary>
+ /// <param name="reference">The reference being processed</param>
+ /// <param name="data">Stream containing the output of the reference</param>
+ /// <returns>Stream containing the output of the reference</returns>
+ internal static Stream LogReferenceData(Reference reference, Stream data)
+ {
+ if (VerboseLoggingEnabled)
+ {
+ //
+ // Since the input data stream could be from the network or another source that does not
+ // support rewinding, we will read the stream into a temporary MemoryStream that can be used
+ // to stringify the output and also return to the reference so that it can produce the hash
+ // value.
+ //
+
+ MemoryStream ms = new MemoryStream();
+
+ // First read the input stream into our temporary stream
+ byte[] buffer = new byte[4096];
+ int readBytes = 0;
+ do
+ {
+ readBytes = data.Read(buffer, 0, buffer.Length);
+ ms.Write(buffer, 0, readBytes);
+ } while (readBytes == buffer.Length);
+
+ // Log out information about it
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_TransformedReferenceContents"),
+ Encoding.UTF8.GetString(ms.ToArray()));
+ WriteLine(reference,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.ReferenceData,
+ logMessage);
+
+ // Rewind to the beginning, so that the entire input stream is hashed
+ ms.Seek(0, SeekOrigin.Begin);
+ return ms;
+ }
+ else
+ {
+ return data;
+ }
+ }
+
+ /// <summary>
+ /// Log the computation of a signature value when signing with an asymmetric algorithm
+ /// </summary>
+ /// <param name="signedXml">SignedXml object calculating the signature</param>
+ /// <param name="key">key used for signing</param>
+ /// <param name="signatureDescription">signature description being used to create the signature</param>
+ /// <param name="hash">hash algorithm used to digest the output</param>
+ /// <param name="asymmetricSignatureFormatter">signature formatter used to do the signing</param>
+ internal static void LogSigning(SignedXml signedXml,
+ object key,
+ SignatureDescription signatureDescription,
+ HashAlgorithm hash,
+ AsymmetricSignatureFormatter asymmetricSignatureFormatter)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(signatureDescription != null, "signatureDescription != null");
+ Debug.Assert(hash != null, "hash != null");
+ Debug.Assert(asymmetricSignatureFormatter != null, "asymmetricSignatureFormatter != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_SigningAsymmetric"),
+ GetKeyName(key),
+ signatureDescription.GetType().Name,
+ hash.GetType().Name,
+ asymmetricSignatureFormatter.GetType().Name);
+
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.Signing,
+ logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log the computation of a signature value when signing with a keyed hash algorithm
+ /// </summary>
+ /// <param name="signedXml">SignedXml object calculating the signature</param>
+ /// <param name="key">key the signature is created with</param>
+ /// <param name="hash">hash algorithm used to digest the output</param>
+ /// <param name="asymmetricSignatureFormatter">signature formatter used to do the signing</param>
+ internal static void LogSigning(SignedXml signedXml, KeyedHashAlgorithm key)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(key != null, "key != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_SigningHmac"),
+ key.GetType().Name);
+
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.Signing,
+ logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log the calculation of a hash value of a reference
+ /// </summary>
+ /// <param name="signedXml">SignedXml object driving the signature</param>
+ /// <param name="reference">Reference being hashed</param>
+ internal static void LogSigningReference(SignedXml signedXml, Reference reference)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(reference != null, "reference != null");
+
+ if (VerboseLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_SigningReference"),
+ GetObjectId(reference),
+ reference.Uri,
+ reference.Id,
+ reference.Type,
+ reference.DigestMethod,
+ CryptoConfig.CreateFromName(reference.DigestMethod).GetType().Name);
+
+ WriteLine(signedXml,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.SigningReference,
+ logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log the specific point where a signature is determined to not be verifiable
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the verification</param>
+ /// <param name="failureLocation">location that the signature was determined to be invalid</param>
+ internal static void LogVerificationFailure(SignedXml signedXml, string failureLocation)
+ {
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_VerificationFailed"),
+ failureLocation);
+
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.VerificationFailure,
+ logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log the success or failure of a signature verification operation
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the verification</param>
+ /// <param name="key">public key used to verify the signature</param>
+ /// <param name="verified">true if the signature verified, false otherwise</param>
+ internal static void LogVerificationResult(SignedXml signedXml, object key, bool verified)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(key != null, "key != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string resource = verified ? SecurityResources.GetResourceString("Log_VerificationWithKeySuccessful") :
+ SecurityResources.GetResourceString("Log_VerificationWithKeyNotSuccessful");
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ resource,
+ GetKeyName(key));
+
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.SignatureVerificationResult,
+ logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log the check for appropriate X509 key usage
+ /// </summary>
+ /// <param name="signedXml">SignedXml doing the signature verification</param>
+ /// <param name="certificate">certificate having its key usages checked</param>
+ /// <param name="keyUsages">key usages being examined</param>
+ internal static void LogVerifyKeyUsage(SignedXml signedXml, X509Certificate certificate, X509KeyUsageExtension keyUsages)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(certificate != null, "certificate != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_KeyUsages"),
+ keyUsages.KeyUsages,
+ GetOidName(keyUsages.Oid),
+ GetKeyName(certificate));
+
+ WriteLine(signedXml,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.X509Verification,
+ logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log that we are verifying a reference
+ /// </summary>
+ /// <param name="signedXml">SignedXMl object doing the verification</param>
+ /// <param name="reference">reference being verified</param>
+ internal static void LogVerifyReference(SignedXml signedXml, Reference reference)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(reference != null, "reference != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_VerifyReference"),
+ GetObjectId(reference),
+ reference.Uri,
+ reference.Id,
+ reference.Type);
+
+ WriteLine(signedXml,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.VerifyReference,
+ logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log the hash comparison when verifying a reference
+ /// </summary>
+ /// <param name="signedXml">SignedXml object verifying the signature</param>
+ /// <param name="reference">reference being verified</param>
+ /// <param name="actualHash">actual hash value of the reference</param>
+ /// <param name="expectedHash">hash value the signature expected the reference to have</param>
+ internal static void LogVerifyReferenceHash(SignedXml signedXml,
+ Reference reference,
+ byte[] actualHash,
+ byte[] expectedHash)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(reference != null, "reference != null");
+ Debug.Assert(actualHash != null, "actualHash != null");
+ Debug.Assert(expectedHash != null, "expectedHash != null");
+
+ if (VerboseLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_ReferenceHash"),
+ GetObjectId(reference),
+ reference.DigestMethod,
+ CryptoConfig.CreateFromName(reference.DigestMethod).GetType().Name,
+ FormatBytes(actualHash),
+ FormatBytes(expectedHash));
+
+ WriteLine(signedXml,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.VerifyReference,
+ logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Log the verification parameters when verifying the SignedInfo section of a signature using an
+ /// asymmetric key
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the verification</param>
+ /// <param name="key">key being used to verify the signed info</param>
+ /// <param name="signatureDescription">type of signature description class used</param>
+ /// <param name="hashAlgorithm">type of hash algorithm used</param>
+ /// <param name="asymmetricSignatureDeformatter">type of signature deformatter used</param>
+ /// <param name="actualHashValue">hash value of the signed info</param>
+ /// <param name="signatureValue">raw signature value</param>
+ internal static void LogVerifySignedInfo(SignedXml signedXml,
+ AsymmetricAlgorithm key,
+ SignatureDescription signatureDescription,
+ HashAlgorithm hashAlgorithm,
+ AsymmetricSignatureDeformatter asymmetricSignatureDeformatter,
+ byte[] actualHashValue,
+ byte[] signatureValue)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(signatureDescription != null, "signatureDescription != null");
+ Debug.Assert(hashAlgorithm != null, "hashAlgorithm != null");
+ Debug.Assert(asymmetricSignatureDeformatter != null, "asymmetricSignatureDeformatter != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_VerifySignedInfoAsymmetric"),
+ GetKeyName(key),
+ signatureDescription.GetType().Name,
+ hashAlgorithm.GetType().Name,
+ asymmetricSignatureDeformatter.GetType().Name);
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.VerifySignedInfo,
+ logMessage);
+ }
+
+ if (VerboseLoggingEnabled)
+ {
+ string hashLog = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_ActualHashValue"),
+ FormatBytes(actualHashValue));
+ WriteLine(signedXml, TraceEventType.Verbose, SignedXmlDebugEvent.VerifySignedInfo, hashLog);
+
+ string signatureLog = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_RawSignatureValue"),
+ FormatBytes(signatureValue));
+ WriteLine(signedXml, TraceEventType.Verbose, SignedXmlDebugEvent.VerifySignedInfo, signatureLog);
+ }
+ }
+
+ /// <summary>
+ /// Log the verification parameters when verifying the SignedInfo section of a signature using a
+ /// keyed hash algorithm
+ /// </summary>
+ /// <param name="signedXml">SignedXml object doing the verification</param>
+ /// <param name="mac">hash algoirthm doing the verification</param>
+ /// <param name="actualHashValue">hash value of the signed info</param>
+ /// <param name="signatureValue">raw signature value</param>
+ internal static void LogVerifySignedInfo(SignedXml signedXml,
+ KeyedHashAlgorithm mac,
+ byte[] actualHashValue,
+ byte[] signatureValue)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(mac != null, "mac != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_VerifySignedInfoHmac"),
+ mac.GetType().Name);
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.VerifySignedInfo,
+ logMessage);
+ }
+
+ if (VerboseLoggingEnabled)
+ {
+ string hashLog = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_ActualHashValue"),
+ FormatBytes(actualHashValue));
+ WriteLine(signedXml, TraceEventType.Verbose, SignedXmlDebugEvent.VerifySignedInfo, hashLog);
+
+ string signatureLog = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_RawSignatureValue"),
+ FormatBytes(signatureValue));
+ WriteLine(signedXml, TraceEventType.Verbose, SignedXmlDebugEvent.VerifySignedInfo, signatureLog);
+ }
+ }
+
+ /// <summary>
+ /// Log that an X509 chain is being built for a certificate
+ /// </summary>
+ /// <param name="signedXml">SignedXml object building the chain</param>
+ /// <param name="chain">chain built for the certificate</param>
+ /// <param name="certificate">certificate having the chain built for it</param>
+ internal static void LogVerifyX509Chain(SignedXml signedXml, X509Chain chain, X509Certificate certificate)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(certificate != null, "certificate != null");
+ Debug.Assert(chain != null, "chain != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string buildMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_BuildX509Chain"),
+ GetKeyName(certificate));
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.X509Verification,
+ buildMessage);
+ }
+
+ if (VerboseLoggingEnabled)
+ {
+ // Dump out the flags and other miscelanious information used for building
+ string revocationMode = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_RevocationMode"),
+ chain.ChainPolicy.RevocationFlag);
+ WriteLine(signedXml, TraceEventType.Verbose, SignedXmlDebugEvent.X509Verification, revocationMode);
+
+ string revocationFlag = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_RevocationFlag"),
+ chain.ChainPolicy.RevocationFlag);
+ WriteLine(signedXml, TraceEventType.Verbose, SignedXmlDebugEvent.X509Verification, revocationFlag);
+
+ string verificationFlags = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_VerificationFlag"),
+ chain.ChainPolicy.VerificationFlags);
+ WriteLine(signedXml, TraceEventType.Verbose, SignedXmlDebugEvent.X509Verification, verificationFlags);
+
+ string verificationTime = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_VerificationTime"),
+ chain.ChainPolicy.VerificationTime);
+ WriteLine(signedXml, TraceEventType.Verbose, SignedXmlDebugEvent.X509Verification, verificationTime);
+
+ string urlTimeout = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_UrlTimeout"),
+ chain.ChainPolicy.UrlRetrievalTimeout);
+ WriteLine(signedXml, TraceEventType.Verbose, SignedXmlDebugEvent.X509Verification, urlTimeout);
+ }
+
+ // If there were any errors in the chain, make sure to dump those out
+ if (InformationLoggingEnabled)
+ {
+ foreach (X509ChainStatus status in chain.ChainStatus)
+ {
+ if (status.Status != X509ChainStatusFlags.NoError)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_X509ChainError"),
+ status.Status,
+ status.StatusInformation);
+
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.X509Verification,
+ logMessage);
+ }
+ }
+ }
+
+ // Finally, dump out the chain itself
+ if (VerboseLoggingEnabled)
+ {
+ StringBuilder chainElements = new StringBuilder();
+ chainElements.Append(SecurityResources.GetResourceString("Log_CertificateChain"));
+
+ foreach (X509ChainElement element in chain.ChainElements)
+ {
+ chainElements.AppendFormat(CultureInfo.InvariantCulture, " {0}", GetKeyName(element.Certificate));
+ }
+
+ WriteLine(signedXml,
+ TraceEventType.Verbose,
+ SignedXmlDebugEvent.X509Verification,
+ chainElements.ToString());
+ }
+ }
+
+ /// <summary>
+ /// Write informaiton when user hits the Signed XML recursion depth limit issue.
+ /// This is helpful in debugging this kind of issues.
+ /// </summary>
+ /// <param name="signedXml">SignedXml object verifying the signature</param>
+ /// <param name="reference">reference being verified</param>
+ internal static void LogSignedXmlRecursionLimit(SignedXml signedXml,
+ Reference reference)
+ {
+ Debug.Assert(signedXml != null, "signedXml != null");
+ Debug.Assert(reference != null, "reference != null");
+
+ if (InformationLoggingEnabled)
+ {
+ string logMessage = string.Format(CultureInfo.InvariantCulture,
+ SecurityResources.GetResourceString("Log_SignedXmlRecursionLimit"),
+ GetObjectId(reference),
+ reference.DigestMethod,
+ CryptoConfig.CreateFromName(reference.DigestMethod).GetType().Name);
+
+ WriteLine(signedXml,
+ TraceEventType.Information,
+ SignedXmlDebugEvent.VerifySignedInfo,
+ logMessage);
+ }
+ }
+
+ /// <summary>
+ /// Write data to the log
+ /// </summary>
+ /// <param name="source">object doing the trace</param>
+ /// <param name="eventType">severity of the debug event</param>
+ /// <param name="data">data being written</param>
+ /// <param name="eventId">type of event being traced</param>
+ private static void WriteLine(object source, TraceEventType eventType, SignedXmlDebugEvent eventId, string data)
+ {
+ Debug.Assert(source != null, "source != null");
+ Debug.Assert(!string.IsNullOrEmpty(data), "!string.IsNullOrEmpty(data)");
+ Debug.Assert(InformationLoggingEnabled, "InformationLoggingEnabled");
+
+ s_traceSource.TraceEvent(eventType,
+ (int)eventId,
+ "[{0}, {1}] {2}",
+ GetObjectId(source),
+ eventId,
+ data);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SymmetricKeyWrap.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SymmetricKeyWrap.cs
new file mode 100644
index 0000000000..a023d818ca
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SymmetricKeyWrap.cs
@@ -0,0 +1,193 @@
+// 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.Security.Cryptography;
+
+namespace System.Security.Cryptography.Xml
+{
+ // abstract class providing symmetric key wrap implementation
+ internal static class SymmetricKeyWrap
+ {
+ private readonly static byte[] s_rgbTripleDES_KW_IV = { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 };
+ private readonly static byte[] s_rgbAES_KW_IV = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
+
+ //
+ // internal static methods
+ //
+
+ // CMS TripleDES KeyWrap as described in "http://www.w3.org/2001/04/xmlenc#kw-tripledes"
+ internal static byte[] TripleDESKeyWrapEncrypt(byte[] rgbKey, byte[] rgbWrappedKeyData)
+ {
+ // checksum the key
+ SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
+ byte[] rgbCKS = sha.ComputeHash(rgbWrappedKeyData);
+
+ // generate a random IV
+ RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
+ byte[] rgbIV = new byte[8];
+ rng.GetBytes(rgbIV);
+
+ // rgbWKCS = rgbWrappedKeyData | (first 8 bytes of the hash)
+ byte[] rgbWKCKS = new byte[rgbWrappedKeyData.Length + 8];
+ TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
+ // Don't add padding, use CBC mode: for example, a 192 bits key will yield 40 bytes of encrypted data
+ tripleDES.Padding = PaddingMode.None;
+ ICryptoTransform enc1 = tripleDES.CreateEncryptor(rgbKey, rgbIV);
+ Buffer.BlockCopy(rgbWrappedKeyData, 0, rgbWKCKS, 0, rgbWrappedKeyData.Length);
+ Buffer.BlockCopy(rgbCKS, 0, rgbWKCKS, rgbWrappedKeyData.Length, 8);
+ byte[] temp1 = enc1.TransformFinalBlock(rgbWKCKS, 0, rgbWKCKS.Length);
+ byte[] temp2 = new byte[rgbIV.Length + temp1.Length];
+ Buffer.BlockCopy(rgbIV, 0, temp2, 0, rgbIV.Length);
+ Buffer.BlockCopy(temp1, 0, temp2, rgbIV.Length, temp1.Length);
+ // temp2 = REV (rgbIV | E_k(rgbWrappedKeyData | rgbCKS))
+ Array.Reverse(temp2);
+
+ ICryptoTransform enc2 = tripleDES.CreateEncryptor(rgbKey, s_rgbTripleDES_KW_IV);
+ return enc2.TransformFinalBlock(temp2, 0, temp2.Length);
+ }
+
+ internal static byte[] TripleDESKeyWrapDecrypt(byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData)
+ {
+ // Check to see whether the length of the encrypted key is reasonable
+ if (rgbEncryptedWrappedKeyData.Length != 32 && rgbEncryptedWrappedKeyData.Length != 40
+ && rgbEncryptedWrappedKeyData.Length != 48)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KW_BadKeySize"));
+
+ TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
+ // Assume no padding, use CBC mode
+ tripleDES.Padding = PaddingMode.None;
+ ICryptoTransform dec1 = tripleDES.CreateDecryptor(rgbKey, s_rgbTripleDES_KW_IV);
+ byte[] temp2 = dec1.TransformFinalBlock(rgbEncryptedWrappedKeyData, 0, rgbEncryptedWrappedKeyData.Length);
+ Array.Reverse(temp2);
+ // Get the IV and temp1
+ byte[] rgbIV = new byte[8];
+ Buffer.BlockCopy(temp2, 0, rgbIV, 0, 8);
+ byte[] temp1 = new byte[temp2.Length - rgbIV.Length];
+ Buffer.BlockCopy(temp2, 8, temp1, 0, temp1.Length);
+
+ ICryptoTransform dec2 = tripleDES.CreateDecryptor(rgbKey, rgbIV);
+ byte[] rgbWKCKS = dec2.TransformFinalBlock(temp1, 0, temp1.Length);
+
+ // checksum the key
+ byte[] rgbWrappedKeyData = new byte[rgbWKCKS.Length - 8];
+ Buffer.BlockCopy(rgbWKCKS, 0, rgbWrappedKeyData, 0, rgbWrappedKeyData.Length);
+ SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
+ byte[] rgbCKS = sha.ComputeHash(rgbWrappedKeyData);
+ for (int index = rgbWrappedKeyData.Length, index1 = 0; index < rgbWKCKS.Length; index++, index1++)
+ if (rgbWKCKS[index] != rgbCKS[index1])
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_BadWrappedKeySize"));
+ return rgbWrappedKeyData;
+ }
+
+ // AES KeyWrap described in "http://www.w3.org/2001/04/xmlenc#kw-aes***", as suggested by NIST
+ internal static byte[] AESKeyWrapEncrypt(byte[] rgbKey, byte[] rgbWrappedKeyData)
+ {
+ int N = rgbWrappedKeyData.Length >> 3;
+ // The information wrapped need not actually be a key, but it needs to be a multiple of 64 bits
+ if ((rgbWrappedKeyData.Length % 8 != 0) || N <= 0)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KW_BadKeySize"));
+
+ RijndaelManaged rijn = new RijndaelManaged();
+ rijn.Key = rgbKey;
+ // Use ECB mode, no padding
+ rijn.Mode = CipherMode.ECB;
+ rijn.Padding = PaddingMode.None;
+ ICryptoTransform enc = rijn.CreateEncryptor();
+ // special case: only 1 block -- 8 bytes
+ if (N == 1)
+ {
+ // temp = 0xa6a6a6a6a6a6a6a6 | P(1)
+ byte[] temp = new byte[s_rgbAES_KW_IV.Length + rgbWrappedKeyData.Length];
+ Buffer.BlockCopy(s_rgbAES_KW_IV, 0, temp, 0, s_rgbAES_KW_IV.Length);
+ Buffer.BlockCopy(rgbWrappedKeyData, 0, temp, s_rgbAES_KW_IV.Length, rgbWrappedKeyData.Length);
+ return enc.TransformFinalBlock(temp, 0, temp.Length);
+ }
+ // second case: more than 1 block
+ long t = 0;
+ byte[] rgbOutput = new byte[(N + 1) << 3];
+ // initialize the R_i's
+ Buffer.BlockCopy(rgbWrappedKeyData, 0, rgbOutput, 8, rgbWrappedKeyData.Length);
+ byte[] rgbA = new byte[8];
+ byte[] rgbBlock = new byte[16];
+ Buffer.BlockCopy(s_rgbAES_KW_IV, 0, rgbA, 0, 8);
+ for (int j = 0; j <= 5; j++)
+ {
+ for (int i = 1; i <= N; i++)
+ {
+ t = i + j * N;
+ Buffer.BlockCopy(rgbA, 0, rgbBlock, 0, 8);
+ Buffer.BlockCopy(rgbOutput, 8 * i, rgbBlock, 8, 8);
+ byte[] rgbB = enc.TransformFinalBlock(rgbBlock, 0, 16);
+ for (int k = 0; k < 8; k++)
+ {
+ byte tmp = (byte)((t >> (8 * (7 - k))) & 0xFF);
+ rgbA[k] = (byte)(tmp ^ rgbB[k]);
+ }
+ Buffer.BlockCopy(rgbB, 8, rgbOutput, 8 * i, 8);
+ }
+ }
+ // Set the first block of rgbOutput to rgbA
+ Buffer.BlockCopy(rgbA, 0, rgbOutput, 0, 8);
+ return rgbOutput;
+ }
+
+ internal static byte[] AESKeyWrapDecrypt(byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData)
+ {
+ int N = (rgbEncryptedWrappedKeyData.Length >> 3) - 1;
+ // The information wrapped need not actually be a key, but it needs to be a multiple of 64 bits
+ if ((rgbEncryptedWrappedKeyData.Length % 8 != 0) || N <= 0)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KW_BadKeySize"));
+
+ byte[] rgbOutput = new byte[N << 3];
+ RijndaelManaged rijn = new RijndaelManaged();
+ rijn.Key = rgbKey;
+ // Use ECB mode, no padding
+ rijn.Mode = CipherMode.ECB;
+ rijn.Padding = PaddingMode.None;
+ ICryptoTransform dec = rijn.CreateDecryptor();
+ // special case: only 1 block -- 8 bytes
+ if (N == 1)
+ {
+ byte[] temp = dec.TransformFinalBlock(rgbEncryptedWrappedKeyData, 0, rgbEncryptedWrappedKeyData.Length);
+ // checksum the key
+ for (int index = 0; index < 8; index++)
+ if (temp[index] != s_rgbAES_KW_IV[index])
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_BadWrappedKeySize"));
+ // rgbOutput is LSB(temp)
+ Buffer.BlockCopy(temp, 8, rgbOutput, 0, 8);
+ return rgbOutput;
+ }
+ // second case: more than 1 block
+ long t = 0;
+ // initialize the C_i's
+ Buffer.BlockCopy(rgbEncryptedWrappedKeyData, 8, rgbOutput, 0, rgbOutput.Length);
+ byte[] rgbA = new byte[8];
+ byte[] rgbBlock = new byte[16];
+ Buffer.BlockCopy(rgbEncryptedWrappedKeyData, 0, rgbA, 0, 8);
+ for (int j = 5; j >= 0; j--)
+ {
+ for (int i = N; i >= 1; i--)
+ {
+ t = i + j * N;
+ for (int k = 0; k < 8; k++)
+ {
+ byte tmp = (byte)((t >> (8 * (7 - k))) & 0xFF);
+ rgbA[k] ^= tmp;
+ }
+ Buffer.BlockCopy(rgbA, 0, rgbBlock, 0, 8);
+ Buffer.BlockCopy(rgbOutput, 8 * (i - 1), rgbBlock, 8, 8);
+ byte[] rgbB = dec.TransformFinalBlock(rgbBlock, 0, 16);
+ Buffer.BlockCopy(rgbB, 8, rgbOutput, 8 * (i - 1), 8);
+ Buffer.BlockCopy(rgbB, 0, rgbA, 0, 8);
+ }
+ }
+ // checksum the key
+ for (int index = 0; index < 8; index++)
+ if (rgbA[index] != s_rgbAES_KW_IV[index])
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_BadWrappedKeySize"));
+ return rgbOutput;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Transform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Transform.cs
new file mode 100644
index 0000000000..e4535d8812
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Transform.cs
@@ -0,0 +1,229 @@
+// 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.
+
+// This file contains the classes necessary to represent the Transform processing model used in
+// XMLDSIG. The basic idea is as follows. A Reference object contains within it a TransformChain, which
+// is an ordered set of XMLDSIG transforms (represented by <Transform>...</Transform> clauses in the XML).
+// A transform in XMLDSIG operates on an input of either an octet stream or a node set and produces
+// either an octet stream or a node set. Conversion between the two types is performed by parsing (octet stream->
+// node set) or C14N (node set->octet stream). We generalize this slightly to allow a transform to define an array of
+// input and output types (because I believe in the future there will be perf gains by being smarter about what goes in & comes out)
+// Each XMLDSIG transform is represented by a subclass of the abstract Transform class. We need to use CryptoConfig to
+// associate Transform classes with URLs for transform extensibility, but that's a future concern for this code.
+// Once the Transform chain is constructed, call TransformToOctetStream to convert some sort of input type to an octet
+// stream. (We only bother implementing that much now since every use of transform chains in XmlDsig ultimately yields something to hash).
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ public abstract class Transform
+ {
+ private string _algorithm;
+ private string _baseUri = null;
+ internal XmlResolver _xmlResolver = null;
+ private bool _bResolverSet = false;
+ private SignedXml _signedXml = null;
+ private Reference _reference = null;
+ private Hashtable _propagatedNamespaces = null;
+ private XmlElement _context = null;
+
+ internal string BaseURI
+ {
+ get { return _baseUri; }
+ set { _baseUri = value; }
+ }
+
+ internal SignedXml SignedXml
+ {
+ get { return _signedXml; }
+ set { _signedXml = value; }
+ }
+
+ internal Reference Reference
+ {
+ get { return _reference; }
+ set { _reference = value; }
+ }
+
+ //
+ // protected constructors
+ //
+
+ protected Transform() { }
+
+ //
+ // public properties
+ //
+
+ public string Algorithm
+ {
+ get { return _algorithm; }
+ set { _algorithm = value; }
+ }
+
+ public XmlResolver Resolver
+ {
+ // This property only has a setter. The rationale for this is that we don't have a good value
+ // to return when it has not been explicitely set, as we are using XmlSecureResolver by default
+ set
+ {
+ _xmlResolver = value;
+ _bResolverSet = true;
+ }
+
+ internal get
+ {
+ return _xmlResolver;
+ }
+ }
+
+ internal bool ResolverSet
+ {
+ get { return _bResolverSet; }
+ }
+
+ public abstract Type[] InputTypes
+ {
+ get;
+ }
+
+ public abstract Type[] OutputTypes
+ {
+ get;
+ }
+
+ internal bool AcceptsType(Type inputType)
+ {
+ if (InputTypes != null)
+ {
+ for (int i = 0; i < InputTypes.Length; i++)
+ {
+ if (inputType == InputTypes[i] || inputType.IsSubclassOf(InputTypes[i]))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //
+ // public methods
+ //
+
+ public XmlElement GetXml()
+ {
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ return GetXml(document);
+ }
+
+ internal XmlElement GetXml(XmlDocument document)
+ {
+ return GetXml(document, "Transform");
+ }
+
+ internal XmlElement GetXml(XmlDocument document, string name)
+ {
+ XmlElement transformElement = document.CreateElement(name, SignedXml.XmlDsigNamespaceUrl);
+ if (!string.IsNullOrEmpty(Algorithm))
+ transformElement.SetAttribute("Algorithm", Algorithm);
+ XmlNodeList children = GetInnerXml();
+ if (children != null)
+ {
+ foreach (XmlNode node in children)
+ {
+ transformElement.AppendChild(document.ImportNode(node, true));
+ }
+ }
+ return transformElement;
+ }
+
+ public abstract void LoadInnerXml(XmlNodeList nodeList);
+
+ protected abstract XmlNodeList GetInnerXml();
+
+ public abstract void LoadInput(object obj);
+
+ public abstract object GetOutput();
+
+ public abstract object GetOutput(Type type);
+
+ public virtual byte[] GetDigestedOutput(HashAlgorithm hash)
+ {
+ return hash.ComputeHash((Stream)GetOutput(typeof(Stream)));
+ }
+
+ public XmlElement Context
+ {
+ get
+ {
+ if (_context != null)
+ return _context;
+
+ Reference reference = Reference;
+ SignedXml signedXml = (reference == null ? SignedXml : reference.SignedXml);
+ if (signedXml == null)
+ return null;
+
+ return signedXml._context;
+ }
+ set
+ {
+ _context = value;
+ }
+ }
+
+ public Hashtable PropagatedNamespaces
+ {
+ get
+ {
+ if (_propagatedNamespaces != null)
+ return _propagatedNamespaces;
+
+ Reference reference = Reference;
+ SignedXml signedXml = (reference == null ? SignedXml : reference.SignedXml);
+
+ // If the reference is not a Uri reference with a DataObject target, return an empty hashtable.
+ if (reference != null &&
+ ((reference.ReferenceTargetType != ReferenceTargetType.UriReference) ||
+ (reference.Uri == null || reference.Uri.Length == 0 || reference.Uri[0] != '#')))
+ {
+ _propagatedNamespaces = new Hashtable(0);
+ return _propagatedNamespaces;
+ }
+
+ CanonicalXmlNodeList namespaces = null;
+ if (reference != null)
+ namespaces = reference._namespaces;
+ else if (signedXml._context != null)
+ namespaces = Utils.GetPropagatedAttributes(signedXml._context);
+
+ // if no namespaces have been propagated, return an empty hashtable.
+ if (namespaces == null)
+ {
+ _propagatedNamespaces = new Hashtable(0);
+ return _propagatedNamespaces;
+ }
+
+ _propagatedNamespaces = new Hashtable(namespaces.Count);
+ foreach (XmlNode attrib in namespaces)
+ {
+ string key = ((attrib.Prefix.Length > 0) ? attrib.Prefix + ":" + attrib.LocalName : attrib.LocalName);
+ if (!_propagatedNamespaces.Contains(key))
+ _propagatedNamespaces.Add(key, attrib.Value);
+ }
+ return _propagatedNamespaces;
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformChain.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformChain.cs
new file mode 100644
index 0000000000..c7ab8f08d0
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformChain.cs
@@ -0,0 +1,213 @@
+// 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.
+
+// This file contains the classes necessary to represent the Transform processing model used in
+// XMLDSIG. The basic idea is as follows. A Reference object contains within it a TransformChain, which
+// is an ordered set of XMLDSIG transforms (represented by <Transform>...</Transform> clauses in the XML).
+// A transform in XMLDSIG operates on an input of either an octet stream or a node set and produces
+// either an octet stream or a node set. Conversion between the two types is performed by parsing (octet stream->
+// node set) or C14N (node set->octet stream). We generalize this slightly to allow a transform to define an array of
+// input and output types (because I believe in the future there will be perf gains by being smarter about what goes in & comes out)
+// Each XMLDSIG transform is represented by a subclass of the abstract Transform class. We need to use CryptoConfig to
+// associate Transform classes with URLs for transform extensibility, but that's a future concern for this code.
+// Once the Transform chain is constructed, call TransformToOctetStream to convert some sort of input type to an octet
+// stream. (We only bother implementing that much now since every use of transform chains in XmlDsig ultimately yields something to hash).
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ // This class represents an ordered chain of transforms
+
+ public class TransformChain
+ {
+ private ArrayList _transforms;
+
+ public TransformChain()
+ {
+ _transforms = new ArrayList();
+ }
+
+ public void Add(Transform transform)
+ {
+ if (transform != null)
+ _transforms.Add(transform);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _transforms.GetEnumerator();
+ }
+
+ public int Count
+ {
+ get { return _transforms.Count; }
+ }
+
+ public Transform this[int index]
+ {
+ get
+ {
+ if (index >= _transforms.Count)
+ throw new ArgumentException(SecurityResources.GetResourceString("ArgumentOutOfRange_Index"), "index");
+ return (Transform)_transforms[index];
+ }
+ }
+
+ // The goal behind this method is to pump the input stream through the transforms and get back something that
+ // can be hashed
+ internal Stream TransformToOctetStream(object inputObject, Type inputType, XmlResolver resolver, string baseUri)
+ {
+ object currentInput = inputObject;
+ foreach (Transform transform in _transforms)
+ {
+ if (currentInput == null || transform.AcceptsType(currentInput.GetType()))
+ {
+ //in this case, no translation necessary, pump it through
+ transform.Resolver = resolver;
+ transform.BaseURI = baseUri;
+ transform.LoadInput(currentInput);
+ currentInput = transform.GetOutput();
+ }
+ else
+ {
+ // We need translation
+ // For now, we just know about Stream->{XmlNodeList,XmlDocument} and {XmlNodeList,XmlDocument}->Stream
+ if (currentInput is Stream)
+ {
+ if (transform.AcceptsType(typeof(XmlDocument)))
+ {
+ Stream currentInputStream = currentInput as Stream;
+ XmlDocument doc = new XmlDocument();
+ doc.PreserveWhitespace = true;
+ XmlReader valReader = Utils.PreProcessStreamInput(currentInputStream, resolver, baseUri);
+ doc.Load(valReader);
+ transform.LoadInput(doc);
+ currentInputStream.Close();
+ currentInput = transform.GetOutput();
+ continue;
+ }
+ else
+ {
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"));
+ }
+ }
+ if (currentInput is XmlNodeList)
+ {
+ if (transform.AcceptsType(typeof(Stream)))
+ {
+ CanonicalXml c14n = new CanonicalXml((XmlNodeList)currentInput, resolver, false);
+ MemoryStream ms = new MemoryStream(c14n.GetBytes());
+ transform.LoadInput(ms);
+ currentInput = transform.GetOutput();
+ ms.Close();
+ continue;
+ }
+ else
+ {
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"));
+ }
+ }
+ if (currentInput is XmlDocument)
+ {
+ if (transform.AcceptsType(typeof(Stream)))
+ {
+ CanonicalXml c14n = new CanonicalXml((XmlDocument)currentInput, resolver);
+ MemoryStream ms = new MemoryStream(c14n.GetBytes());
+ transform.LoadInput(ms);
+ currentInput = transform.GetOutput();
+ ms.Close();
+ continue;
+ }
+ else
+ {
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"));
+ }
+ }
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"));
+ }
+ }
+
+ // Final processing, either we already have a stream or have to canonicalize
+ if (currentInput is Stream)
+ {
+ return currentInput as Stream;
+ }
+ if (currentInput is XmlNodeList)
+ {
+ CanonicalXml c14n = new CanonicalXml((XmlNodeList)currentInput, resolver, false);
+ MemoryStream ms = new MemoryStream(c14n.GetBytes());
+ return ms;
+ }
+ if (currentInput is XmlDocument)
+ {
+ CanonicalXml c14n = new CanonicalXml((XmlDocument)currentInput, resolver);
+ MemoryStream ms = new MemoryStream(c14n.GetBytes());
+ return ms;
+ }
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"));
+ }
+
+ internal Stream TransformToOctetStream(Stream input, XmlResolver resolver, string baseUri)
+ {
+ return TransformToOctetStream(input, typeof(Stream), resolver, baseUri);
+ }
+
+ internal Stream TransformToOctetStream(XmlDocument document, XmlResolver resolver, string baseUri)
+ {
+ return TransformToOctetStream(document, typeof(XmlDocument), resolver, baseUri);
+ }
+
+ internal XmlElement GetXml(XmlDocument document, string ns)
+ {
+ XmlElement transformsElement = document.CreateElement("Transforms", ns);
+ foreach (Transform transform in _transforms)
+ {
+ if (transform != null)
+ {
+ // Construct the individual transform element
+ XmlElement transformElement = transform.GetXml(document);
+ if (transformElement != null)
+ transformsElement.AppendChild(transformElement);
+ }
+ }
+ return transformsElement;
+ }
+
+ internal void LoadXml(XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
+ nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
+
+ XmlNodeList transformNodes = value.SelectNodes("ds:Transform", nsm);
+ if (transformNodes.Count == 0)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidElement"), "Transforms");
+
+ _transforms.Clear();
+ for (int i = 0; i < transformNodes.Count; ++i)
+ {
+ XmlElement transformElement = (XmlElement)transformNodes.Item(i);
+ string algorithm = Utils.GetAttribute(transformElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl);
+ Transform transform = CryptoConfig.CreateFromName(algorithm) as Transform;
+ if (transform == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UnknownTransform"));
+ // let the transform read the children of the transformElement for data
+ transform.LoadInnerXml(transformElement.ChildNodes);
+ _transforms.Add(transform);
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformInputType.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformInputType.cs
new file mode 100644
index 0000000000..79e03cd816
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformInputType.cs
@@ -0,0 +1,16 @@
+// 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;
+
+namespace System.Security.Cryptography.Xml
+{
+ [Serializable]
+ internal enum TransformInputType
+ {
+ XmlDocument = 1,
+ XmlStream = 2,
+ XmlNodeSet = 3
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs
new file mode 100644
index 0000000000..4fb9f20f89
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs
@@ -0,0 +1,822 @@
+// 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;
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Security;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Permissions;
+using System.Text;
+using System.Threading;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ internal class Utils
+ {
+ private Utils() { }
+
+ private static bool HasNamespace(XmlElement element, string prefix, string value)
+ {
+ if (IsCommittedNamespace(element, prefix, value)) return true;
+ if (element.Prefix == prefix && element.NamespaceURI == value) return true;
+ return false;
+ }
+
+ // A helper function that determines if a namespace node is a committed attribute
+ internal static bool IsCommittedNamespace(XmlElement element, string prefix, string value)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ string name = ((prefix.Length > 0) ? "xmlns:" + prefix : "xmlns");
+ if (element.HasAttribute(name) && element.GetAttribute(name) == value) return true;
+ return false;
+ }
+
+ internal static bool IsRedundantNamespace(XmlElement element, string prefix, string value)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ XmlNode ancestorNode = ((XmlNode)element).ParentNode;
+ while (ancestorNode != null)
+ {
+ XmlElement ancestorElement = ancestorNode as XmlElement;
+ if (ancestorElement != null)
+ if (HasNamespace(ancestorElement, prefix, value)) return true;
+ ancestorNode = ancestorNode.ParentNode;
+ }
+
+ return false;
+ }
+
+ internal static string GetAttribute(XmlElement element, string localName, string namespaceURI)
+ {
+ string s = (element.HasAttribute(localName) ? element.GetAttribute(localName) : null);
+ if (s == null && element.HasAttribute(localName, namespaceURI))
+ s = element.GetAttribute(localName, namespaceURI);
+ return s;
+ }
+
+ internal static bool HasAttribute(XmlElement element, string localName, string namespaceURI)
+ {
+ return element.HasAttribute(localName) || element.HasAttribute(localName, namespaceURI);
+ }
+
+ internal static bool IsNamespaceNode(XmlNode n)
+ {
+ return n.NodeType == XmlNodeType.Attribute && (n.Prefix.Equals("xmlns") || (n.Prefix.Length == 0 && n.LocalName.Equals("xmlns")));
+ }
+
+ internal static bool IsXmlNamespaceNode(XmlNode n)
+ {
+ return n.NodeType == XmlNodeType.Attribute && n.Prefix.Equals("xml");
+ }
+
+ // We consider xml:space style attributes as default namespace nodes since they obey the same propagation rules
+ internal static bool IsDefaultNamespaceNode(XmlNode n)
+ {
+ bool b1 = n.NodeType == XmlNodeType.Attribute && n.Prefix.Length == 0 && n.LocalName.Equals("xmlns");
+ bool b2 = IsXmlNamespaceNode(n);
+ return b1 || b2;
+ }
+
+ internal static bool IsEmptyDefaultNamespaceNode(XmlNode n)
+ {
+ return IsDefaultNamespaceNode(n) && n.Value.Length == 0;
+ }
+
+ internal static string GetNamespacePrefix(XmlAttribute a)
+ {
+ Debug.Assert(IsNamespaceNode(a) || IsXmlNamespaceNode(a));
+ return a.Prefix.Length == 0 ? string.Empty : a.LocalName;
+ }
+
+ internal static bool HasNamespacePrefix(XmlAttribute a, string nsPrefix)
+ {
+ return GetNamespacePrefix(a).Equals(nsPrefix);
+ }
+
+ internal static bool IsNonRedundantNamespaceDecl(XmlAttribute a, XmlAttribute nearestAncestorWithSamePrefix)
+ {
+ if (nearestAncestorWithSamePrefix == null)
+ return !IsEmptyDefaultNamespaceNode(a);
+ else
+ return !nearestAncestorWithSamePrefix.Value.Equals(a.Value);
+ }
+
+ internal static bool IsXmlPrefixDefinitionNode(XmlAttribute a)
+ {
+ return false;
+ // return a.Prefix.Equals("xmlns") && a.LocalName.Equals("xml") && a.Value.Equals(NamespaceUrlForXmlPrefix);
+ }
+
+ internal static string DiscardWhiteSpaces(string inputBuffer)
+ {
+ return DiscardWhiteSpaces(inputBuffer, 0, inputBuffer.Length);
+ }
+
+
+ internal static string DiscardWhiteSpaces(string inputBuffer, int inputOffset, int inputCount)
+ {
+ int i, iCount = 0;
+ for (i = 0; i < inputCount; i++)
+ if (Char.IsWhiteSpace(inputBuffer[inputOffset + i])) iCount++;
+ char[] rgbOut = new char[inputCount - iCount];
+ iCount = 0;
+ for (i = 0; i < inputCount; i++)
+ if (!Char.IsWhiteSpace(inputBuffer[inputOffset + i]))
+ {
+ rgbOut[iCount++] = inputBuffer[inputOffset + i];
+ }
+ return new string(rgbOut);
+ }
+
+ internal static void SBReplaceCharWithString(StringBuilder sb, char oldChar, string newString)
+ {
+ int i = 0;
+ int newStringLength = newString.Length;
+ while (i < sb.Length)
+ {
+ if (sb[i] == oldChar)
+ {
+ sb.Remove(i, 1);
+ sb.Insert(i, newString);
+ i += newStringLength;
+ }
+ else i++;
+ }
+ }
+
+ internal static XmlReader PreProcessStreamInput(Stream inputStream, XmlResolver xmlResolver, string baseUri)
+ {
+ XmlReaderSettings settings = GetSecureXmlReaderSettings(xmlResolver);
+ XmlReader reader = XmlReader.Create(inputStream, settings, baseUri);
+ return reader;
+ }
+
+ internal static XmlReaderSettings GetSecureXmlReaderSettings(XmlResolver xmlResolver)
+ {
+ XmlReaderSettings settings = new XmlReaderSettings();
+ settings.XmlResolver = xmlResolver;
+ settings.DtdProcessing = DtdProcessing.Parse;
+ settings.MaxCharactersFromEntities = GetMaxCharactersFromEntities();
+ settings.MaxCharactersInDocument = GetMaxCharactersInDocument();
+ return settings;
+ }
+
+ private static int? s_xmlDsigSearchDepth = null;
+ /// <summary>
+ /// Function get the XML Dsig recursion limit. This function defines the
+ /// default limit in case, limit is not defined by developer or admin then
+ /// it returns the default value.
+ /// </summary>
+ [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal static int GetXmlDsigSearchDepth()
+ {
+ if (s_xmlDsigSearchDepth.HasValue)
+ {
+ return s_xmlDsigSearchDepth.Value;
+ }
+ //Keeping the default recursion limit to 20. It should be
+ //within limits of real world scenarios. Keeping this number low
+ //will preserve some stack space
+ long maxXmlDsigSearchDepth = GetNetFxSecurityRegistryValue("SignedDigitalSignatureXmlMaxDepth", 20);
+
+ s_xmlDsigSearchDepth = (int)maxXmlDsigSearchDepth;
+ return s_xmlDsigSearchDepth.Value;
+ }
+
+ private static long? s_maxCharactersFromEntities = null;
+ // Allow machine admins to specify an entity expansion limit. This is used to prevent
+ // entity expansion denial of service attacks.
+ // Falls back to a default if none is specified.
+ [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal static long GetMaxCharactersFromEntities()
+ {
+ if (s_maxCharactersFromEntities.HasValue)
+ {
+ return s_maxCharactersFromEntities.Value;
+ }
+
+ long maxCharacters = GetNetFxSecurityRegistryValue("SignedXmlMaxCharactersFromEntities", (long)1e7);
+
+ s_maxCharactersFromEntities = maxCharacters;
+ return s_maxCharactersFromEntities.Value;
+ }
+
+ private static bool s_readMaxCharactersInDocument = false;
+ private static long s_maxCharactersInDocument = 0;
+
+ [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal static long GetMaxCharactersInDocument()
+ {
+ // Allow machine administrators to specify a maximum document load size for SignedXml.
+ if (s_readMaxCharactersInDocument)
+ {
+ return s_maxCharactersInDocument;
+ }
+
+ // The default value, 0, is "no limit"
+ long maxCharacters = GetNetFxSecurityRegistryValue("SignedXmlMaxCharactersInDocument", 0);
+
+ s_maxCharactersInDocument = maxCharacters;
+ Thread.MemoryBarrier();
+ s_readMaxCharactersInDocument = true;
+
+ return s_maxCharactersInDocument;
+ }
+
+ private static bool? s_allowAmbiguousReferenceTarget = null;
+
+ [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal static bool AllowAmbiguousReferenceTargets()
+ {
+ // Allow machine administrators to specify that the legacy behavior of matching the first element
+ // in an ambiguous reference situation should be persisted. The default behavior is to throw in that
+ // situation, but a REG_DWORD or REG_QWORD value of 1 will revert.
+ if (s_allowAmbiguousReferenceTarget.HasValue)
+ {
+ return s_allowAmbiguousReferenceTarget.Value;
+ }
+
+ long numericValue = GetNetFxSecurityRegistryValue("SignedXmlAllowAmbiguousReferenceTargets", 0);
+ bool allowAmbiguousReferenceTarget = numericValue != 0;
+
+ s_allowAmbiguousReferenceTarget = allowAmbiguousReferenceTarget;
+ return s_allowAmbiguousReferenceTarget.Value;
+ }
+
+ private static bool? s_allowDetachedSignature = null;
+
+ [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal static bool AllowDetachedSignature()
+ {
+ // Allow machine administrators to specify that detached signatures can be processed.
+ // The default behavior is to throw when processing a detached signature,
+ // but a REG_DWORD or REG_QWORD value of 1 will revert.
+ if (s_allowDetachedSignature.HasValue)
+ {
+ return s_allowDetachedSignature.Value;
+ }
+
+ long numericValue = GetNetFxSecurityRegistryValue("SignedXmlAllowDetachedSignature", 0);
+ bool allowDetachedSignature = numericValue != 0;
+
+ s_allowDetachedSignature = allowDetachedSignature;
+ return s_allowDetachedSignature.Value;
+ }
+
+ private static bool s_readRequireNCNameIdentifier = false;
+ private static bool s_requireNCNameIdentifier = true;
+
+ [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
+ internal static bool RequireNCNameIdentifier()
+ {
+ if (s_readRequireNCNameIdentifier)
+ {
+ return s_requireNCNameIdentifier;
+ }
+
+ long numericValue = GetNetFxSecurityRegistryValue("SignedXmlRequireNCNameIdentifier", 1);
+ bool requireNCName = numericValue != 0;
+
+ s_requireNCNameIdentifier = requireNCName;
+ Thread.MemoryBarrier();
+ s_readRequireNCNameIdentifier = true;
+
+ return s_requireNCNameIdentifier;
+ }
+
+ private static long GetNetFxSecurityRegistryValue(string regValueName, long defaultValue)
+ {
+ try
+ {
+ using (RegistryKey securityRegKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework\Security", false))
+ {
+ if (securityRegKey != null)
+ {
+ object regValue = securityRegKey.GetValue(regValueName);
+ if (regValue != null)
+ {
+ RegistryValueKind valueKind = securityRegKey.GetValueKind(regValueName);
+ if (valueKind == RegistryValueKind.DWord || valueKind == RegistryValueKind.QWord)
+ {
+ return Convert.ToInt64(regValue, CultureInfo.InvariantCulture);
+ }
+ }
+ }
+ }
+ }
+ catch (SecurityException) { /* we could not open the key - that's fine, we can proceed with the default value */ }
+
+ return defaultValue;
+ }
+
+ internal static XmlDocument PreProcessDocumentInput(XmlDocument document, XmlResolver xmlResolver, string baseUri)
+ {
+ if (document == null)
+ throw new ArgumentNullException("document");
+
+ MyXmlDocument doc = new MyXmlDocument();
+ doc.PreserveWhitespace = document.PreserveWhitespace;
+
+ // Normalize the document
+ using (TextReader stringReader = new StringReader(document.OuterXml))
+ {
+ XmlReaderSettings settings = new XmlReaderSettings();
+ settings.XmlResolver = xmlResolver;
+ settings.DtdProcessing = DtdProcessing.Parse;
+ settings.MaxCharactersFromEntities = GetMaxCharactersFromEntities();
+ settings.MaxCharactersInDocument = GetMaxCharactersInDocument();
+ XmlReader reader = XmlReader.Create(stringReader, settings, baseUri);
+ doc.Load(reader);
+ }
+ return doc;
+ }
+
+ internal static XmlDocument PreProcessElementInput(XmlElement elem, XmlResolver xmlResolver, string baseUri)
+ {
+ if (elem == null)
+ throw new ArgumentNullException("elem");
+
+ MyXmlDocument doc = new MyXmlDocument();
+ doc.PreserveWhitespace = true;
+ // Normalize the document
+ using (TextReader stringReader = new StringReader(elem.OuterXml))
+ {
+ XmlReaderSettings settings = new XmlReaderSettings();
+ settings.XmlResolver = xmlResolver;
+ settings.DtdProcessing = DtdProcessing.Parse;
+ settings.MaxCharactersFromEntities = GetMaxCharactersFromEntities();
+ settings.MaxCharactersInDocument = GetMaxCharactersInDocument();
+ XmlReader reader = XmlReader.Create(stringReader, settings, baseUri);
+ doc.Load(reader);
+ }
+ return doc;
+ }
+
+ internal static XmlDocument DiscardComments(XmlDocument document)
+ {
+ XmlNodeList nodeList = document.SelectNodes("//comment()");
+ if (nodeList != null)
+ {
+ foreach (XmlNode node1 in nodeList)
+ {
+ node1.ParentNode.RemoveChild(node1);
+ }
+ }
+ return document;
+ }
+
+ internal static XmlNodeList AllDescendantNodes(XmlNode node, bool includeComments)
+ {
+ CanonicalXmlNodeList nodeList = new CanonicalXmlNodeList();
+ CanonicalXmlNodeList elementList = new CanonicalXmlNodeList();
+ CanonicalXmlNodeList attribList = new CanonicalXmlNodeList();
+ CanonicalXmlNodeList namespaceList = new CanonicalXmlNodeList();
+
+ int index = 0;
+ elementList.Add(node);
+
+ do
+ {
+ XmlNode rootNode = (XmlNode)elementList[index];
+ // Add the children nodes
+ XmlNodeList childNodes = rootNode.ChildNodes;
+ if (childNodes != null)
+ {
+ foreach (XmlNode node1 in childNodes)
+ {
+ if (includeComments || (!(node1 is XmlComment)))
+ {
+ elementList.Add(node1);
+ }
+ }
+ }
+ // Add the attribute nodes
+ XmlAttributeCollection attribNodes = rootNode.Attributes;
+ if (attribNodes != null)
+ {
+ foreach (XmlNode attribNode in rootNode.Attributes)
+ {
+ if (attribNode.LocalName == "xmlns" || attribNode.Prefix == "xmlns")
+ namespaceList.Add(attribNode);
+ else
+ attribList.Add(attribNode);
+ }
+ }
+ index++;
+ } while (index < elementList.Count);
+ foreach (XmlNode elementNode in elementList)
+ {
+ nodeList.Add(elementNode);
+ }
+ foreach (XmlNode attribNode in attribList)
+ {
+ nodeList.Add(attribNode);
+ }
+ foreach (XmlNode namespaceNode in namespaceList)
+ {
+ nodeList.Add(namespaceNode);
+ }
+
+ return nodeList;
+ }
+
+ internal static bool NodeInList(XmlNode node, XmlNodeList nodeList)
+ {
+ foreach (XmlNode nodeElem in nodeList)
+ {
+ if (nodeElem == node) return true;
+ }
+ return false;
+ }
+
+ internal static string GetIdFromLocalUri(string uri, out bool discardComments)
+ {
+ string idref = uri.Substring(1);
+ // initialize the return value
+ discardComments = true;
+
+ // Deal with XPointer of type #xpointer(id("ID")). Other XPointer support isn't handled here and is anyway optional
+ if (idref.StartsWith("xpointer(id(", StringComparison.Ordinal))
+ {
+ int startId = idref.IndexOf("id(", StringComparison.Ordinal);
+ int endId = idref.IndexOf(")", StringComparison.Ordinal);
+ if (endId < 0 || endId < startId + 3)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidReference"));
+ idref = idref.Substring(startId + 3, endId - startId - 3);
+ idref = idref.Replace("\'", "");
+ idref = idref.Replace("\"", "");
+ discardComments = false;
+ }
+ return idref;
+ }
+
+ internal static string ExtractIdFromLocalUri(string uri)
+ {
+ string idref = uri.Substring(1);
+
+ // Deal with XPointer of type #xpointer(id("ID")). Other XPointer support isn't handled here and is anyway optional
+ if (idref.StartsWith("xpointer(id(", StringComparison.Ordinal))
+ {
+ int startId = idref.IndexOf("id(", StringComparison.Ordinal);
+ int endId = idref.IndexOf(")", StringComparison.Ordinal);
+ if (endId < 0 || endId < startId + 3)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidReference"));
+ idref = idref.Substring(startId + 3, endId - startId - 3);
+ idref = idref.Replace("\'", "");
+ idref = idref.Replace("\"", "");
+ }
+ return idref;
+ }
+
+ // This removes all children of an element.
+ internal static void RemoveAllChildren(XmlElement inputElement)
+ {
+ XmlNode child = inputElement.FirstChild;
+ XmlNode sibling = null;
+
+ while (child != null)
+ {
+ sibling = child.NextSibling;
+ inputElement.RemoveChild(child);
+ child = sibling;
+ }
+ }
+
+ // Writes one stream (starting from the current position) into
+ // an output stream, connecting them up and reading until
+ // hitting the end of the input stream.
+ // returns the number of bytes copied
+ internal static long Pump(Stream input, Stream output)
+ {
+ // Use MemoryStream's WriteTo(Stream) method if possible
+ MemoryStream inputMS = input as MemoryStream;
+ if (inputMS != null && inputMS.Position == 0)
+ {
+ inputMS.WriteTo(output);
+ return inputMS.Length;
+ }
+
+ const int count = 4096;
+ byte[] bytes = new byte[count];
+ int numBytes;
+ long totalBytes = 0;
+
+ while ((numBytes = input.Read(bytes, 0, count)) > 0)
+ {
+ output.Write(bytes, 0, numBytes);
+ totalBytes += numBytes;
+ }
+
+ return totalBytes;
+ }
+
+ internal static Hashtable TokenizePrefixListString(string s)
+ {
+ Hashtable set = new Hashtable();
+ if (s != null)
+ {
+ string[] prefixes = s.Split(null);
+ foreach (string prefix in prefixes)
+ {
+ if (prefix.Equals("#default"))
+ {
+ set.Add(string.Empty, true);
+ }
+ else if (prefix.Length > 0)
+ {
+ set.Add(prefix, true);
+ }
+ }
+ }
+ return set;
+ }
+
+ internal static string EscapeWhitespaceData(string data)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(data);
+ Utils.SBReplaceCharWithString(sb, (char)13, "&#xD;");
+ return sb.ToString(); ;
+ }
+
+ internal static string EscapeTextData(string data)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(data);
+ sb.Replace("&", "&amp;");
+ sb.Replace("<", "&lt;");
+ sb.Replace(">", "&gt;");
+ SBReplaceCharWithString(sb, (char)13, "&#xD;");
+ return sb.ToString(); ;
+ }
+
+ internal static string EscapeCData(string data)
+ {
+ return EscapeTextData(data);
+ }
+
+ internal static string EscapeAttributeValue(string value)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(value);
+ sb.Replace("&", "&amp;");
+ sb.Replace("<", "&lt;");
+ sb.Replace("\"", "&quot;");
+ SBReplaceCharWithString(sb, (char)9, "&#x9;");
+ SBReplaceCharWithString(sb, (char)10, "&#xA;");
+ SBReplaceCharWithString(sb, (char)13, "&#xD;");
+ return sb.ToString();
+ }
+
+ internal static XmlDocument GetOwnerDocument(XmlNodeList nodeList)
+ {
+ foreach (XmlNode node in nodeList)
+ {
+ if (node.OwnerDocument != null)
+ return node.OwnerDocument;
+ }
+ return null;
+ }
+
+ internal static void AddNamespaces(XmlElement elem, CanonicalXmlNodeList namespaces)
+ {
+ if (namespaces != null)
+ {
+ foreach (XmlNode attrib in namespaces)
+ {
+ string name = ((attrib.Prefix.Length > 0) ? attrib.Prefix + ":" + attrib.LocalName : attrib.LocalName);
+ // Skip the attribute if one with the same qualified name already exists
+ if (elem.HasAttribute(name) || (name.Equals("xmlns") && elem.Prefix.Length == 0)) continue;
+ XmlAttribute nsattrib = (XmlAttribute)elem.OwnerDocument.CreateAttribute(name);
+ nsattrib.Value = attrib.Value;
+ elem.SetAttributeNode(nsattrib);
+ }
+ }
+ }
+
+ internal static void AddNamespaces(XmlElement elem, Hashtable namespaces)
+ {
+ if (namespaces != null)
+ {
+ foreach (string key in namespaces.Keys)
+ {
+ if (elem.HasAttribute(key)) continue;
+ XmlAttribute nsattrib = (XmlAttribute)elem.OwnerDocument.CreateAttribute(key);
+ nsattrib.Value = namespaces[key] as string;
+ elem.SetAttributeNode(nsattrib);
+ }
+ }
+ }
+
+ // This method gets the attributes that should be propagated
+ internal static CanonicalXmlNodeList GetPropagatedAttributes(XmlElement elem)
+ {
+ if (elem == null)
+ return null;
+
+ CanonicalXmlNodeList namespaces = new CanonicalXmlNodeList();
+ XmlNode ancestorNode = elem;
+
+ if (ancestorNode == null) return null;
+
+ bool bDefNamespaceToAdd = true;
+
+ while (ancestorNode != null)
+ {
+ XmlElement ancestorElement = ancestorNode as XmlElement;
+ if (ancestorElement == null)
+ {
+ ancestorNode = ancestorNode.ParentNode;
+ continue;
+ }
+ if (!Utils.IsCommittedNamespace(ancestorElement, ancestorElement.Prefix, ancestorElement.NamespaceURI))
+ {
+ // Add the namespace attribute to the collection if needed
+ if (!Utils.IsRedundantNamespace(ancestorElement, ancestorElement.Prefix, ancestorElement.NamespaceURI))
+ {
+ string name = ((ancestorElement.Prefix.Length > 0) ? "xmlns:" + ancestorElement.Prefix : "xmlns");
+ XmlAttribute nsattrib = elem.OwnerDocument.CreateAttribute(name);
+ nsattrib.Value = ancestorElement.NamespaceURI;
+ namespaces.Add(nsattrib);
+ }
+ }
+ if (ancestorElement.HasAttributes)
+ {
+ XmlAttributeCollection attribs = ancestorElement.Attributes;
+ foreach (XmlAttribute attrib in attribs)
+ {
+ // Add a default namespace if necessary
+ if (bDefNamespaceToAdd && attrib.LocalName == "xmlns")
+ {
+ XmlAttribute nsattrib = elem.OwnerDocument.CreateAttribute("xmlns");
+ nsattrib.Value = attrib.Value;
+ namespaces.Add(nsattrib);
+ bDefNamespaceToAdd = false;
+ continue;
+ }
+ // retain the declarations of type 'xml:*' as well
+ if (attrib.Prefix == "xmlns" || attrib.Prefix == "xml")
+ {
+ namespaces.Add(attrib);
+ continue;
+ }
+ if (attrib.NamespaceURI.Length > 0)
+ {
+ if (!Utils.IsCommittedNamespace(ancestorElement, attrib.Prefix, attrib.NamespaceURI))
+ {
+ // Add the namespace attribute to the collection if needed
+ if (!Utils.IsRedundantNamespace(ancestorElement, attrib.Prefix, attrib.NamespaceURI))
+ {
+ string name = ((attrib.Prefix.Length > 0) ? "xmlns:" + attrib.Prefix : "xmlns");
+ XmlAttribute nsattrib = elem.OwnerDocument.CreateAttribute(name);
+ nsattrib.Value = attrib.NamespaceURI;
+ namespaces.Add(nsattrib);
+ }
+ }
+ }
+ }
+ }
+ ancestorNode = ancestorNode.ParentNode;
+ }
+
+ return namespaces;
+ }
+
+ // output of this routine is always big endian
+ internal static byte[] ConvertIntToByteArray(int dwInput)
+ {
+ byte[] rgbTemp = new byte[8]; // int can never be greater than Int64
+ int t1; // t1 is remaining value to account for
+ int t2; // t2 is t1 % 256
+ int i = 0;
+
+ if (dwInput == 0) return new byte[1];
+ t1 = dwInput;
+ while (t1 > 0)
+ {
+ t2 = t1 % 256;
+ rgbTemp[i] = (byte)t2;
+ t1 = (t1 - t2) / 256;
+ i++;
+ }
+ // Now, copy only the non-zero part of rgbTemp and reverse
+ byte[] rgbOutput = new byte[i];
+ // copy and reverse in one pass
+ for (int j = 0; j < i; j++)
+ {
+ rgbOutput[j] = rgbTemp[i - j - 1];
+ }
+ return rgbOutput;
+ }
+
+ internal static int GetHexArraySize(byte[] hex)
+ {
+ int index = hex.Length;
+ while (index-- > 0)
+ {
+ if (hex[index] != 0)
+ break;
+ }
+ return index + 1;
+ }
+
+ internal static X509Certificate2Collection BuildBagOfCerts(KeyInfoX509Data keyInfoX509Data, CertUsageType certUsageType)
+ {
+ X509Certificate2Collection collection = new X509Certificate2Collection();
+ ArrayList decryptionIssuerSerials = (certUsageType == CertUsageType.Decryption ? new ArrayList() : null);
+ if (keyInfoX509Data.Certificates != null)
+ {
+ foreach (X509Certificate2 certificate in keyInfoX509Data.Certificates)
+ {
+ switch (certUsageType)
+ {
+ case CertUsageType.Verification:
+ collection.Add(certificate);
+ break;
+ case CertUsageType.Decryption:
+ decryptionIssuerSerials.Add(new X509IssuerSerial(certificate.IssuerName.Name, certificate.SerialNumber));
+ break;
+ }
+ }
+ }
+
+ if (keyInfoX509Data.SubjectNames == null && keyInfoX509Data.IssuerSerials == null &&
+ keyInfoX509Data.SubjectKeyIds == null && decryptionIssuerSerials == null)
+ return collection;
+
+ // Open LocalMachine and CurrentUser "Other People"/"My" stores.
+
+ // Assert OpenStore since we are not giving back any certificates to the user.
+ StorePermission sp = new StorePermission(StorePermissionFlags.OpenStore);
+ sp.Assert();
+
+ X509Store[] stores = new X509Store[2];
+ string storeName = (certUsageType == CertUsageType.Verification ? "AddressBook" : "My");
+ stores[0] = new X509Store(storeName, StoreLocation.CurrentUser);
+ stores[1] = new X509Store(storeName, StoreLocation.LocalMachine);
+
+ for (int index = 0; index < stores.Length; index++)
+ {
+ if (stores[index] != null)
+ {
+ X509Certificate2Collection filters = null;
+ // We don't care if we can't open the store.
+ try
+ {
+ stores[index].Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
+ filters = stores[index].Certificates;
+ stores[index].Close();
+ if (keyInfoX509Data.SubjectNames != null)
+ {
+ foreach (string subjectName in keyInfoX509Data.SubjectNames)
+ {
+ filters = filters.Find(X509FindType.FindBySubjectDistinguishedName, subjectName, false);
+ }
+ }
+ if (keyInfoX509Data.IssuerSerials != null)
+ {
+ foreach (X509IssuerSerial issuerSerial in keyInfoX509Data.IssuerSerials)
+ {
+ filters = filters.Find(X509FindType.FindByIssuerDistinguishedName, issuerSerial.IssuerName, false);
+ filters = filters.Find(X509FindType.FindBySerialNumber, issuerSerial.SerialNumber, false);
+ }
+ }
+ if (keyInfoX509Data.SubjectKeyIds != null)
+ {
+ foreach (byte[] ski in keyInfoX509Data.SubjectKeyIds)
+ {
+ string hex = X509Utils.EncodeHexString(ski);
+ filters = filters.Find(X509FindType.FindBySubjectKeyIdentifier, hex, false);
+ }
+ }
+ if (decryptionIssuerSerials != null)
+ {
+ foreach (X509IssuerSerial issuerSerial in decryptionIssuerSerials)
+ {
+ filters = filters.Find(X509FindType.FindByIssuerDistinguishedName, issuerSerial.IssuerName, false);
+ filters = filters.Find(X509FindType.FindBySerialNumber, issuerSerial.SerialNumber, false);
+ }
+ }
+ }
+ catch (CryptographicException) { }
+
+ if (filters != null)
+ collection.AddRange(filters);
+ }
+ }
+
+ return collection;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/X509IssuerSerial.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/X509IssuerSerial.cs
new file mode 100644
index 0000000000..263c4b2e04
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/X509IssuerSerial.cs
@@ -0,0 +1,55 @@
+// 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.Collections;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Xml;
+
+namespace System.Security.Cryptography.Xml
+{
+ public struct X509IssuerSerial
+ {
+ private string _issuerName;
+ private string _serialNumber;
+
+ internal X509IssuerSerial(string issuerName, string serialNumber)
+ {
+ if (issuerName == null || issuerName.Length == 0)
+ throw new ArgumentException(SecurityResources.GetResourceString("Arg_EmptyOrNullString"), "issuerName");
+ if (serialNumber == null || serialNumber.Length == 0)
+ throw new ArgumentException(SecurityResources.GetResourceString("Arg_EmptyOrNullString"), "serialNumber");
+ _issuerName = issuerName;
+ _serialNumber = serialNumber;
+ }
+
+
+ public string IssuerName
+ {
+ get
+ {
+ return _issuerName;
+ }
+ set
+ {
+ _issuerName = value;
+ }
+ }
+
+ public string SerialNumber
+ {
+ get
+ {
+ return _serialNumber;
+ }
+ set
+ {
+ _serialNumber = value;
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs
new file mode 100644
index 0000000000..ebec75c529
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs
@@ -0,0 +1,272 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ // XML Decryption Transform is used to specify the order of XML Digital Signature
+ // and XML Encryption when performed on the same document.
+
+ public class XmlDecryptionTransform : Transform
+ {
+ private Type[] _inputTypes = { typeof(Stream), typeof(XmlDocument) };
+ private Type[] _outputTypes = { typeof(XmlDocument) };
+ private XmlNodeList _encryptedDataList = null;
+ private ArrayList _arrayListUri = null; // this ArrayList object represents the Uri's to be excluded
+ private EncryptedXml _exml = null; // defines the XML encryption processing rules
+ private XmlDocument _containingDocument = null;
+ private XmlNamespaceManager _nsm = null;
+ private const string XmlDecryptionTransformNamespaceUrl = "http://www.w3.org/2002/07/decrypt#";
+
+ public XmlDecryptionTransform()
+ {
+ Algorithm = SignedXml.XmlDecryptionTransformUrl;
+ }
+
+ private ArrayList ExceptUris
+ {
+ get
+ {
+ if (_arrayListUri == null)
+ _arrayListUri = new ArrayList();
+ return _arrayListUri;
+ }
+ }
+
+ protected virtual bool IsTargetElement(XmlElement inputElement, string idValue)
+ {
+ if (inputElement == null)
+ return false;
+ if (inputElement.GetAttribute("Id") == idValue || inputElement.GetAttribute("id") == idValue ||
+ inputElement.GetAttribute("ID") == idValue)
+ return true;
+
+ return false;
+ }
+
+ public EncryptedXml EncryptedXml
+ {
+ get
+ {
+ if (_exml != null)
+ return _exml;
+
+ Reference reference = Reference;
+ SignedXml signedXml = (reference == null ? SignedXml : reference.SignedXml);
+ if (signedXml == null || signedXml.EncryptedXml == null)
+ _exml = new EncryptedXml(_containingDocument); // default processing rules
+ else
+ _exml = signedXml.EncryptedXml;
+
+ return _exml;
+ }
+ set { _exml = value; }
+ }
+
+ public override Type[] InputTypes
+ {
+ get { return _inputTypes; }
+ }
+
+ public override Type[] OutputTypes
+ {
+ get { return _outputTypes; }
+ }
+
+ public void AddExceptUri(string uri)
+ {
+ if (uri == null)
+ throw new ArgumentNullException("uri");
+ ExceptUris.Add(uri);
+ }
+
+ public override void LoadInnerXml(XmlNodeList nodeList)
+ {
+ if (nodeList == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UnknownTransform"));
+ ExceptUris.Clear();
+ foreach (XmlNode node in nodeList)
+ {
+ XmlElement elem = node as XmlElement;
+ if (elem != null && elem.LocalName == "Except" && elem.NamespaceURI == XmlDecryptionTransformNamespaceUrl)
+ {
+ // the Uri is required
+ string uri = Utils.GetAttribute(elem, "URI", XmlDecryptionTransformNamespaceUrl);
+ if (uri == null || uri.Length == 0 || uri[0] != '#')
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriRequired"));
+ string idref = Utils.ExtractIdFromLocalUri(uri);
+ ExceptUris.Add(idref);
+ }
+ }
+ }
+
+ protected override XmlNodeList GetInnerXml()
+ {
+ if (ExceptUris.Count == 0)
+ return null;
+ XmlDocument document = new XmlDocument();
+ XmlElement element = document.CreateElement("Transform", SignedXml.XmlDsigNamespaceUrl);
+ if (!string.IsNullOrEmpty(Algorithm))
+ element.SetAttribute("Algorithm", Algorithm);
+ foreach (string uri in ExceptUris)
+ {
+ XmlElement exceptUriElement = document.CreateElement("Except", XmlDecryptionTransformNamespaceUrl);
+ exceptUriElement.SetAttribute("URI", uri);
+ element.AppendChild(exceptUriElement);
+ }
+ return element.ChildNodes;
+ }
+
+ public override void LoadInput(object obj)
+ {
+ if (obj is Stream)
+ {
+ LoadStreamInput((Stream)obj);
+ }
+ else if (obj is XmlDocument)
+ {
+ LoadXmlDocumentInput((XmlDocument)obj);
+ }
+ }
+
+ private void LoadStreamInput(Stream stream)
+ {
+ XmlDocument document = new XmlDocument();
+ document.PreserveWhitespace = true;
+ XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI));
+ XmlReader xmlReader = Utils.PreProcessStreamInput(stream, resolver, BaseURI);
+ document.Load(xmlReader);
+ _containingDocument = document;
+ _nsm = new XmlNamespaceManager(_containingDocument.NameTable);
+ _nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+ // select all EncryptedData elements
+ _encryptedDataList = document.SelectNodes("//enc:EncryptedData", _nsm);
+ }
+
+ private void LoadXmlDocumentInput(XmlDocument document)
+ {
+ if (document == null)
+ throw new ArgumentNullException("document");
+ _containingDocument = document;
+ _nsm = new XmlNamespaceManager(document.NameTable);
+ _nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+ // select all EncryptedData elements
+ _encryptedDataList = document.SelectNodes("//enc:EncryptedData", _nsm);
+ }
+
+ // Replace the encrytped XML element with the decrypted data for signature verification
+ private void ReplaceEncryptedData(XmlElement encryptedDataElement, byte[] decrypted)
+ {
+ XmlNode parent = encryptedDataElement.ParentNode;
+ if (parent.NodeType == XmlNodeType.Document)
+ {
+ // We're replacing the root element. In order to correctly reflect the semantics of the
+ // decryption transform, we need to replace the entire document with the decrypted data.
+ // However, EncryptedXml.ReplaceData will preserve other top-level elements such as the XML
+ // entity declaration and top level comments. So, in this case we must do the replacement
+ // ourselves.
+ parent.InnerXml = EncryptedXml.Encoding.GetString(decrypted);
+ }
+ else
+ {
+ // We're replacing a node in the middle of the document - EncryptedXml knows how to handle
+ // this case in conformance with the transform's requirements, so we'll just defer to it.
+ EncryptedXml.ReplaceData(encryptedDataElement, decrypted);
+ }
+ }
+
+ private bool ProcessEncryptedDataItem(XmlElement encryptedDataElement)
+ {
+ // first see whether we want to ignore this one
+ if (ExceptUris.Count > 0)
+ {
+ for (int index = 0; index < ExceptUris.Count; index++)
+ {
+ if (IsTargetElement(encryptedDataElement, (string)ExceptUris[index]))
+ return false;
+ }
+ }
+ EncryptedData ed = new EncryptedData();
+ ed.LoadXml(encryptedDataElement);
+ SymmetricAlgorithm symAlg = EncryptedXml.GetDecryptionKey(ed, null);
+ if (symAlg == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingDecryptionKey"));
+ byte[] decrypted = EncryptedXml.DecryptData(ed, symAlg);
+
+ ReplaceEncryptedData(encryptedDataElement, decrypted);
+ return true;
+ }
+
+ private void ProcessElementRecursively(XmlNodeList encryptedDatas)
+ {
+ if (encryptedDatas == null || encryptedDatas.Count == 0)
+ return;
+ Queue encryptedDatasQueue = new Queue();
+ foreach (XmlNode value in encryptedDatas)
+ {
+ encryptedDatasQueue.Enqueue(value);
+ }
+ XmlNode node = encryptedDatasQueue.Dequeue() as XmlNode;
+ while (node != null)
+ {
+ XmlElement encryptedDataElement = node as XmlElement;
+ if (encryptedDataElement != null && encryptedDataElement.LocalName == "EncryptedData" &&
+ encryptedDataElement.NamespaceURI == EncryptedXml.XmlEncNamespaceUrl)
+ {
+ XmlNode sibling = encryptedDataElement.NextSibling;
+ XmlNode parent = encryptedDataElement.ParentNode;
+ if (ProcessEncryptedDataItem(encryptedDataElement))
+ {
+ // find the new decrypted element.
+ XmlNode child = parent.FirstChild;
+ while (child != null && child.NextSibling != sibling)
+ child = child.NextSibling;
+ if (child != null)
+ {
+ XmlNodeList nodes = child.SelectNodes("//enc:EncryptedData", _nsm);
+ if (nodes.Count > 0)
+ {
+ foreach (XmlNode value in nodes)
+ {
+ encryptedDatasQueue.Enqueue(value);
+ }
+ }
+ }
+ }
+ }
+ if (encryptedDatasQueue.Count == 0)
+ break;
+ node = encryptedDatasQueue.Dequeue() as XmlNode;
+ }
+ }
+
+ public override object GetOutput()
+ {
+ // decrypt the encrypted sections
+ if (_encryptedDataList != null)
+ ProcessElementRecursively(_encryptedDataList);
+ // propagate namespaces
+ Utils.AddNamespaces(_containingDocument.DocumentElement, PropagatedNamespaces);
+ return _containingDocument;
+ }
+
+ public override object GetOutput(Type type)
+ {
+ if (type == typeof(XmlDocument))
+ return (XmlDocument)GetOutput();
+ else
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"), "type");
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigBase64Transform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigBase64Transform.cs
new file mode 100644
index 0000000000..fc387764e8
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigBase64Transform.cs
@@ -0,0 +1,139 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ // A class representing conversion from Base64 using CryptoStream
+ public class XmlDsigBase64Transform : Transform
+ {
+ private Type[] _inputTypes = { typeof(Stream), typeof(XmlNodeList), typeof(XmlDocument) };
+ private Type[] _outputTypes = { typeof(Stream) };
+ private CryptoStream _cs = null;
+
+ public XmlDsigBase64Transform()
+ {
+ Algorithm = SignedXml.XmlDsigBase64TransformUrl;
+ }
+
+ public override Type[] InputTypes
+ {
+ get { return _inputTypes; }
+ }
+
+ public override Type[] OutputTypes
+ {
+ get { return _outputTypes; }
+ }
+
+ public override void LoadInnerXml(XmlNodeList nodeList)
+ {
+ }
+
+ protected override XmlNodeList GetInnerXml()
+ {
+ return null;
+ }
+
+ public override void LoadInput(object obj)
+ {
+ if (obj is Stream)
+ {
+ LoadStreamInput((Stream)obj);
+ return;
+ }
+ if (obj is XmlNodeList)
+ {
+ LoadXmlNodeListInput((XmlNodeList)obj);
+ return;
+ }
+ if (obj is XmlDocument)
+ {
+ LoadXmlNodeListInput(((XmlDocument)obj).SelectNodes("//."));
+ return;
+ }
+ }
+
+ private void LoadStreamInput(Stream inputStream)
+ {
+ if (inputStream == null) throw new ArgumentException("obj");
+ MemoryStream ms = new MemoryStream();
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ do
+ {
+ bytesRead = inputStream.Read(buffer, 0, 1024);
+ if (bytesRead > 0)
+ {
+ int i = 0;
+ int j = 0;
+ while ((j < bytesRead) && (!Char.IsWhiteSpace((char)buffer[j]))) j++;
+ i = j; j++;
+ while (j < bytesRead)
+ {
+ if (!Char.IsWhiteSpace((char)buffer[j]))
+ {
+ buffer[i] = buffer[j];
+ i++;
+ }
+ j++;
+ }
+ ms.Write(buffer, 0, i);
+ }
+ } while (bytesRead > 0);
+ ms.Position = 0;
+ _cs = new CryptoStream(ms, new FromBase64Transform(), CryptoStreamMode.Read);
+ }
+
+ private void LoadXmlNodeListInput(XmlNodeList nodeList)
+ {
+ StringBuilder sb = new StringBuilder();
+ foreach (XmlNode node in nodeList)
+ {
+ XmlNode result = node.SelectSingleNode("self::text()");
+ if (result != null)
+ sb.Append(result.OuterXml);
+ }
+ UTF8Encoding utf8 = new UTF8Encoding(false);
+ byte[] buffer = utf8.GetBytes(sb.ToString());
+ int i = 0;
+ int j = 0;
+ while ((j < buffer.Length) && (!Char.IsWhiteSpace((char)buffer[j]))) j++;
+ i = j; j++;
+ while (j < buffer.Length)
+ {
+ if (!Char.IsWhiteSpace((char)buffer[j]))
+ {
+ buffer[i] = buffer[j];
+ i++;
+ }
+ j++;
+ }
+ MemoryStream ms = new MemoryStream(buffer, 0, i);
+ _cs = new CryptoStream(ms, new FromBase64Transform(), CryptoStreamMode.Read);
+ }
+
+ public override object GetOutput()
+ {
+ return _cs;
+ }
+
+ public override object GetOutput(Type type)
+ {
+ if (type != typeof(Stream) && !type.IsSubclassOf(typeof(Stream)))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"), "type");
+ return _cs;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs
new file mode 100644
index 0000000000..90ff154bdd
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs
@@ -0,0 +1,93 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class XmlDsigC14NTransform : Transform
+ {
+ private Type[] _inputTypes = { typeof(Stream), typeof(XmlDocument), typeof(XmlNodeList) };
+ private Type[] _outputTypes = { typeof(Stream) };
+ private CanonicalXml _cXml;
+ private bool _includeComments = false;
+
+ public XmlDsigC14NTransform()
+ {
+ Algorithm = SignedXml.XmlDsigC14NTransformUrl;
+ }
+
+ public XmlDsigC14NTransform(bool includeComments)
+ {
+ _includeComments = includeComments;
+ Algorithm = (includeComments ? SignedXml.XmlDsigC14NWithCommentsTransformUrl : SignedXml.XmlDsigC14NTransformUrl);
+ }
+
+ public override Type[] InputTypes
+ {
+ get { return _inputTypes; }
+ }
+
+ public override Type[] OutputTypes
+ {
+ get { return _outputTypes; }
+ }
+
+ public override void LoadInnerXml(XmlNodeList nodeList) { }
+
+ protected override XmlNodeList GetInnerXml()
+ {
+ return null;
+ }
+
+ public override void LoadInput(object obj)
+ {
+ XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI));
+ if (obj is Stream)
+ {
+ _cXml = new CanonicalXml((Stream)obj, _includeComments, resolver, BaseURI);
+ return;
+ }
+ if (obj is XmlDocument)
+ {
+ _cXml = new CanonicalXml((XmlDocument)obj, resolver, _includeComments);
+ return;
+ }
+ if (obj is XmlNodeList)
+ {
+ _cXml = new CanonicalXml((XmlNodeList)obj, resolver, _includeComments);
+ }
+ else
+ {
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "obj");
+ }
+ }
+
+ public override object GetOutput()
+ {
+ return new MemoryStream(_cXml.GetBytes());
+ }
+
+ public override object GetOutput(Type type)
+ {
+ if (type != typeof(Stream) && !type.IsSubclassOf(typeof(Stream)))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"), "type");
+ return new MemoryStream(_cXml.GetBytes());
+ }
+
+ public override byte[] GetDigestedOutput(HashAlgorithm hash)
+ {
+ return _cXml.GetDigestedBytes(hash);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NWithCommentsTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NWithCommentsTransform.cs
new file mode 100644
index 0000000000..1e15344e2f
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NWithCommentsTransform.cs
@@ -0,0 +1,26 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class XmlDsigC14NWithCommentsTransform : XmlDsigC14NTransform
+ {
+ public XmlDsigC14NWithCommentsTransform()
+ : base(true)
+ {
+ Algorithm = SignedXml.XmlDsigC14NWithCommentsTransformUrl;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs
new file mode 100644
index 0000000000..f539bfeb1a
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs
@@ -0,0 +1,199 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class XmlDsigEnvelopedSignatureTransform : Transform
+ {
+ private Type[] _inputTypes = { typeof(Stream), typeof(XmlNodeList), typeof(XmlDocument) };
+ private Type[] _outputTypes = { typeof(XmlNodeList), typeof(XmlDocument) };
+ private XmlNodeList _inputNodeList;
+ private bool _includeComments = false;
+ private XmlNamespaceManager _nsm = null;
+ private XmlDocument _containingDocument = null;
+ private int _signaturePosition = 0;
+
+ internal int SignaturePosition
+ {
+ set { _signaturePosition = value; }
+ }
+
+ public XmlDsigEnvelopedSignatureTransform()
+ {
+ Algorithm = SignedXml.XmlDsigEnvelopedSignatureTransformUrl;
+ }
+
+ /// <internalonly/>
+ public XmlDsigEnvelopedSignatureTransform(bool includeComments)
+ {
+ _includeComments = includeComments;
+ Algorithm = SignedXml.XmlDsigEnvelopedSignatureTransformUrl;
+ }
+
+ public override Type[] InputTypes
+ {
+ get { return _inputTypes; }
+ }
+
+ public override Type[] OutputTypes
+ {
+ get { return _outputTypes; }
+ }
+
+ // An enveloped signature has no inner XML elements
+ public override void LoadInnerXml(XmlNodeList nodeList) { }
+
+ // An enveloped signature has no inner XML elements
+ protected override XmlNodeList GetInnerXml()
+ {
+ return null;
+ }
+
+ public override void LoadInput(object obj)
+ {
+ if (obj is Stream)
+ {
+ LoadStreamInput((Stream)obj);
+ return;
+ }
+ if (obj is XmlNodeList)
+ {
+ LoadXmlNodeListInput((XmlNodeList)obj);
+ return;
+ }
+ if (obj is XmlDocument)
+ {
+ LoadXmlDocumentInput((XmlDocument)obj);
+ return;
+ }
+ }
+
+ private void LoadStreamInput(Stream stream)
+ {
+ XmlDocument doc = new XmlDocument();
+ doc.PreserveWhitespace = true;
+ XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI));
+ XmlReader xmlReader = Utils.PreProcessStreamInput(stream, resolver, BaseURI);
+ doc.Load(xmlReader);
+ _containingDocument = doc;
+ if (_containingDocument == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_EnvelopedSignatureRequiresContext"));
+ _nsm = new XmlNamespaceManager(_containingDocument.NameTable);
+ _nsm.AddNamespace("dsig", SignedXml.XmlDsigNamespaceUrl);
+ }
+
+ private void LoadXmlNodeListInput(XmlNodeList nodeList)
+ {
+ // Empty node list is not acceptable
+ if (nodeList == null)
+ throw new ArgumentNullException("nodeList");
+ _containingDocument = Utils.GetOwnerDocument(nodeList);
+ if (_containingDocument == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_EnvelopedSignatureRequiresContext"));
+
+ _nsm = new XmlNamespaceManager(_containingDocument.NameTable);
+ _nsm.AddNamespace("dsig", SignedXml.XmlDsigNamespaceUrl);
+ _inputNodeList = nodeList;
+ }
+
+ private void LoadXmlDocumentInput(XmlDocument doc)
+ {
+ if (doc == null)
+ throw new ArgumentNullException("doc");
+ _containingDocument = doc;
+ _nsm = new XmlNamespaceManager(_containingDocument.NameTable);
+ _nsm.AddNamespace("dsig", SignedXml.XmlDsigNamespaceUrl);
+ }
+
+ public override object GetOutput()
+ {
+ if (_containingDocument == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_EnvelopedSignatureRequiresContext"));
+
+ // If we have received an XmlNodeList as input
+ if (_inputNodeList != null)
+ {
+ // If the position has not been set, then we don't want to remove any signature tags
+ if (_signaturePosition == 0) return _inputNodeList;
+ XmlNodeList signatureList = _containingDocument.SelectNodes("//dsig:Signature", _nsm);
+ if (signatureList == null) return _inputNodeList;
+
+ CanonicalXmlNodeList resultNodeList = new CanonicalXmlNodeList();
+ foreach (XmlNode node in _inputNodeList)
+ {
+ if (node == null) continue;
+ // keep namespaces
+ if (Utils.IsXmlNamespaceNode(node) || Utils.IsNamespaceNode(node))
+ {
+ resultNodeList.Add(node);
+ }
+ else
+ {
+ // SelectSingleNode throws an exception for xmldecl PI for example, so we will just ignore those exceptions
+ try
+ {
+ // Find the nearest signature ancestor tag
+ XmlNode result = node.SelectSingleNode("ancestor-or-self::dsig:Signature[1]", _nsm);
+ int position = 0;
+ foreach (XmlNode node1 in signatureList)
+ {
+ position++;
+ if (node1 == result) break;
+ }
+ if (result == null || (result != null && position != _signaturePosition))
+ {
+ resultNodeList.Add(node);
+ }
+ }
+ catch { }
+ }
+ }
+ return resultNodeList;
+ }
+ // Else we have received either a stream or a document as input
+ else
+ {
+ XmlNodeList signatureList = _containingDocument.SelectNodes("//dsig:Signature", _nsm);
+ if (signatureList == null) return _containingDocument;
+ if (signatureList.Count < _signaturePosition || _signaturePosition <= 0) return _containingDocument;
+
+ // Remove the signature node with all its children nodes
+ signatureList[_signaturePosition - 1].ParentNode.RemoveChild(signatureList[_signaturePosition - 1]);
+ return _containingDocument;
+ }
+ }
+
+ public override object GetOutput(Type type)
+ {
+ if (type == typeof(XmlNodeList) || type.IsSubclassOf(typeof(XmlNodeList)))
+ {
+ if (_inputNodeList == null)
+ {
+ _inputNodeList = Utils.AllDescendantNodes(_containingDocument, true);
+ }
+ return (XmlNodeList)GetOutput();
+ }
+ else if (type == typeof(XmlDocument) || type.IsSubclassOf(typeof(XmlDocument)))
+ {
+ if (_inputNodeList != null) throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"), "type");
+ return (XmlDocument)GetOutput();
+ }
+ else
+ {
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"), "type");
+ }
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs
new file mode 100644
index 0000000000..9707d0e10c
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs
@@ -0,0 +1,123 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class XmlDsigExcC14NTransform : Transform
+ {
+ private Type[] _inputTypes = { typeof(Stream), typeof(XmlDocument), typeof(XmlNodeList) };
+ private Type[] _outputTypes = { typeof(Stream) };
+ private bool _includeComments = false;
+ private string _inclusiveNamespacesPrefixList;
+ private ExcCanonicalXml _excCanonicalXml;
+
+ public XmlDsigExcC14NTransform() : this(false, null) { }
+
+ public XmlDsigExcC14NTransform(bool includeComments) : this(includeComments, null) { }
+
+ public XmlDsigExcC14NTransform(string inclusiveNamespacesPrefixList) : this(false, inclusiveNamespacesPrefixList) { }
+
+ public XmlDsigExcC14NTransform(bool includeComments, string inclusiveNamespacesPrefixList)
+ {
+ _includeComments = includeComments;
+ _inclusiveNamespacesPrefixList = inclusiveNamespacesPrefixList;
+ Algorithm = (includeComments ? SignedXml.XmlDsigExcC14NWithCommentsTransformUrl : SignedXml.XmlDsigExcC14NTransformUrl);
+ }
+
+ public string InclusiveNamespacesPrefixList
+ {
+ get { return _inclusiveNamespacesPrefixList; }
+ set { _inclusiveNamespacesPrefixList = value; }
+ }
+
+ public override Type[] InputTypes
+ {
+ get { return _inputTypes; }
+ }
+
+ public override Type[] OutputTypes
+ {
+ get { return _outputTypes; }
+ }
+
+ public override void LoadInnerXml(XmlNodeList nodeList)
+ {
+ if (nodeList != null)
+ {
+ foreach (XmlNode n in nodeList)
+ {
+ XmlElement e = n as XmlElement;
+ if (e != null && e.LocalName.Equals("InclusiveNamespaces") &&
+ e.NamespaceURI.Equals(SignedXml.XmlDsigExcC14NTransformUrl) &&
+ Utils.HasAttribute(e, "PrefixList", SignedXml.XmlDsigNamespaceUrl))
+ {
+ InclusiveNamespacesPrefixList = Utils.GetAttribute(e, "PrefixList", SignedXml.XmlDsigNamespaceUrl);
+ return;
+ }
+ }
+ }
+ }
+
+ public override void LoadInput(object obj)
+ {
+ XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI));
+ if (obj is Stream)
+ {
+ _excCanonicalXml = new ExcCanonicalXml((Stream)obj, _includeComments, _inclusiveNamespacesPrefixList, resolver, BaseURI);
+ }
+ else if (obj is XmlDocument)
+ {
+ _excCanonicalXml = new ExcCanonicalXml((XmlDocument)obj, _includeComments, _inclusiveNamespacesPrefixList, resolver);
+ }
+ else if (obj is XmlNodeList)
+ {
+ _excCanonicalXml = new ExcCanonicalXml((XmlNodeList)obj, _includeComments, _inclusiveNamespacesPrefixList, resolver);
+ }
+ else
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_IncorrectObjectType"), "obj");
+ }
+
+ protected override XmlNodeList GetInnerXml()
+ {
+ if (InclusiveNamespacesPrefixList == null)
+ return null;
+ XmlDocument document = new XmlDocument();
+ XmlElement element = document.CreateElement("Transform", SignedXml.XmlDsigNamespaceUrl);
+ if (!string.IsNullOrEmpty(Algorithm))
+ element.SetAttribute("Algorithm", Algorithm);
+ XmlElement prefixListElement = document.CreateElement("InclusiveNamespaces", SignedXml.XmlDsigExcC14NTransformUrl);
+ prefixListElement.SetAttribute("PrefixList", InclusiveNamespacesPrefixList);
+ element.AppendChild(prefixListElement);
+ return element.ChildNodes;
+ }
+
+ public override object GetOutput()
+ {
+ return new MemoryStream(_excCanonicalXml.GetBytes());
+ }
+
+ public override object GetOutput(Type type)
+ {
+ if (type != typeof(Stream) && !type.IsSubclassOf(typeof(Stream)))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"), "type");
+ return new MemoryStream(_excCanonicalXml.GetBytes());
+ }
+
+ public override byte[] GetDigestedOutput(HashAlgorithm hash)
+ {
+ return _excCanonicalXml.GetDigestedBytes(hash);
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NWithCommentsTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NWithCommentsTransform.cs
new file mode 100644
index 0000000000..1b91c1720c
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NWithCommentsTransform.cs
@@ -0,0 +1,34 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ // <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
+ // <ec:InclusiveNamespaces PrefixList="dsig soap #default" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ // </ds:Transform>
+
+ public class XmlDsigExcC14NWithCommentsTransform : XmlDsigExcC14NTransform
+ {
+ public XmlDsigExcC14NWithCommentsTransform() : base(true)
+ {
+ Algorithm = SignedXml.XmlDsigExcC14NWithCommentsTransformUrl;
+ }
+
+ public XmlDsigExcC14NWithCommentsTransform(string inclusiveNamespacesPrefixList) : base(true, inclusiveNamespacesPrefixList)
+ {
+ Algorithm = SignedXml.XmlDsigExcC14NWithCommentsTransformUrl;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs
new file mode 100644
index 0000000000..5b972a2abd
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs
@@ -0,0 +1,195 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ // A class representing DSIG XPath Transforms
+
+ public class XmlDsigXPathTransform : Transform
+ {
+ private Type[] _inputTypes = { typeof(Stream), typeof(XmlNodeList), typeof(XmlDocument) };
+ private Type[] _outputTypes = { typeof(XmlNodeList) };
+ private string _xpathexpr;
+ private XmlDocument _document;
+ private XmlNamespaceManager _nsm;
+
+ public XmlDsigXPathTransform()
+ {
+ Algorithm = SignedXml.XmlDsigXPathTransformUrl;
+ }
+
+ public override Type[] InputTypes
+ {
+ get { return _inputTypes; }
+ }
+
+ public override Type[] OutputTypes
+ {
+ get { return _outputTypes; }
+ }
+
+ public override void LoadInnerXml(XmlNodeList nodeList)
+ {
+ // XPath transform is specified by text child of first XPath child
+ if (nodeList == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UnknownTransform"));
+
+ foreach (XmlNode node in nodeList)
+ {
+ string prefix = null;
+ string namespaceURI = null;
+ XmlElement elem = node as XmlElement;
+ if ((elem != null) && (elem.LocalName == "XPath"))
+ {
+ _xpathexpr = elem.InnerXml.Trim(null);
+ XmlNodeReader nr = new XmlNodeReader(elem);
+ XmlNameTable nt = nr.NameTable;
+ _nsm = new XmlNamespaceManager(nt);
+ // Look for a namespace in the attributes
+ foreach (XmlAttribute attrib in elem.Attributes)
+ {
+ if (attrib.Prefix == "xmlns")
+ {
+ prefix = attrib.LocalName;
+ namespaceURI = attrib.Value;
+ if (prefix == null)
+ {
+ prefix = elem.Prefix;
+ namespaceURI = elem.NamespaceURI;
+ }
+ _nsm.AddNamespace(prefix, namespaceURI);
+ }
+ }
+ break;
+ }
+ }
+
+ if (_xpathexpr == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UnknownTransform"));
+ }
+
+ protected override XmlNodeList GetInnerXml()
+ {
+ XmlDocument document = new XmlDocument();
+ XmlElement element = document.CreateElement(null, "XPath", SignedXml.XmlDsigNamespaceUrl);
+
+ if (_nsm != null)
+ {
+ // Add each of the namespaces as attributes of the element
+ foreach (string prefix in _nsm)
+ {
+ switch (prefix)
+ {
+ // Ignore the xml namespaces
+ case "xml":
+ case "xmlns":
+ break;
+
+ // Other namespaces
+ default:
+ // Ignore the default namespace
+ if (prefix != null && prefix.Length > 0)
+ element.SetAttribute("xmlns:" + prefix, _nsm.LookupNamespace(prefix));
+ break;
+ }
+ }
+ }
+ // Add the XPath as the inner xml of the element
+ element.InnerXml = _xpathexpr;
+ document.AppendChild(element);
+ return document.ChildNodes;
+ }
+
+ public override void LoadInput(object obj)
+ {
+ if (obj is Stream)
+ {
+ LoadStreamInput((Stream)obj);
+ }
+ else if (obj is XmlNodeList)
+ {
+ LoadXmlNodeListInput((XmlNodeList)obj);
+ }
+ else if (obj is XmlDocument)
+ {
+ LoadXmlDocumentInput((XmlDocument)obj);
+ }
+ }
+
+ private void LoadStreamInput(Stream stream)
+ {
+ XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI));
+ XmlReader valReader = Utils.PreProcessStreamInput(stream, resolver, BaseURI);
+ _document = new XmlDocument();
+ _document.PreserveWhitespace = true;
+ _document.Load(valReader);
+ }
+
+ private void LoadXmlNodeListInput(XmlNodeList nodeList)
+ {
+ // Use C14N to get a document
+ XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI));
+ CanonicalXml c14n = new CanonicalXml((XmlNodeList)nodeList, resolver, true);
+ using (MemoryStream ms = new MemoryStream(c14n.GetBytes()))
+ {
+ LoadStreamInput(ms);
+ }
+ }
+
+ private void LoadXmlDocumentInput(XmlDocument doc)
+ {
+ _document = doc;
+ }
+
+ public override object GetOutput()
+ {
+ CanonicalXmlNodeList resultNodeList = new CanonicalXmlNodeList();
+ if (!string.IsNullOrEmpty(_xpathexpr))
+ {
+ XPathNavigator navigator = _document.CreateNavigator();
+ XPathNodeIterator it = navigator.Select("//. | //@*");
+
+ XPathExpression xpathExpr = navigator.Compile("boolean(" + _xpathexpr + ")");
+ xpathExpr.SetContext(_nsm);
+
+ while (it.MoveNext())
+ {
+ XmlNode node = ((IHasXmlNode)it.Current).GetNode();
+
+ bool include = (bool)it.Current.Evaluate(xpathExpr);
+ if (include == true)
+ resultNodeList.Add(node);
+ }
+
+ // keep namespaces
+ it = navigator.Select("//namespace::*");
+ while (it.MoveNext())
+ {
+ XmlNode node = ((IHasXmlNode)it.Current).GetNode();
+ resultNodeList.Add(node);
+ }
+ }
+
+ return resultNodeList;
+ }
+
+ public override object GetOutput(Type type)
+ {
+ if (type != typeof(XmlNodeList) && !type.IsSubclassOf(typeof(XmlNodeList)))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"), "type");
+ return (XmlNodeList)GetOutput();
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXsltTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXsltTransform.cs
new file mode 100644
index 0000000000..51b68bfdf7
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXsltTransform.cs
@@ -0,0 +1,156 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class XmlDsigXsltTransform : Transform
+ {
+ private Type[] _inputTypes = { typeof(Stream), typeof(XmlDocument), typeof(XmlNodeList) };
+ private Type[] _outputTypes = { typeof(Stream) };
+ private XmlNodeList _xslNodes;
+ private string _xslFragment;
+ private Stream _inputStream;
+ private bool _includeComments = false;
+
+ public XmlDsigXsltTransform()
+ {
+ Algorithm = SignedXml.XmlDsigXsltTransformUrl;
+ }
+
+ public XmlDsigXsltTransform(bool includeComments)
+ {
+ _includeComments = includeComments;
+ Algorithm = SignedXml.XmlDsigXsltTransformUrl;
+ }
+
+ public override Type[] InputTypes
+ {
+ get
+ {
+ return _inputTypes;
+ }
+ }
+
+ public override Type[] OutputTypes
+ {
+ get
+ {
+ return _outputTypes;
+ }
+ }
+
+ public override void LoadInnerXml(XmlNodeList nodeList)
+ {
+ if (nodeList == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UnknownTransform"));
+ // check that the XSLT element is well formed
+ XmlElement firstDataElement = null;
+ int count = 0;
+ foreach (XmlNode node in nodeList)
+ {
+ // ignore white spaces, but make sure only one child element is present
+ if (node is XmlWhitespace) continue;
+ if (node is XmlElement)
+ {
+ if (count != 0)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UnknownTransform"));
+ firstDataElement = node as XmlElement;
+ count++;
+ continue;
+ }
+ // Only allow white spaces
+ count++;
+ }
+ if (count != 1 || firstDataElement == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UnknownTransform"));
+ _xslNodes = nodeList;
+ _xslFragment = firstDataElement.OuterXml.Trim(null);
+ }
+
+ protected override XmlNodeList GetInnerXml()
+ {
+ return _xslNodes;
+ }
+
+ public override void LoadInput(object obj)
+ {
+ if (_inputStream != null)
+ _inputStream.Close();
+ _inputStream = new MemoryStream();
+ if (obj is Stream)
+ {
+ _inputStream = (Stream)obj;
+ }
+ else if (obj is XmlNodeList)
+ {
+ CanonicalXml xmlDoc = new CanonicalXml((XmlNodeList)obj, null, _includeComments);
+ byte[] buffer = xmlDoc.GetBytes();
+ if (buffer == null) return;
+ _inputStream.Write(buffer, 0, buffer.Length);
+ _inputStream.Flush();
+ _inputStream.Position = 0;
+ }
+ else if (obj is XmlDocument)
+ {
+ CanonicalXml xmlDoc = new CanonicalXml((XmlDocument)obj, null, _includeComments);
+ byte[] buffer = xmlDoc.GetBytes();
+ if (buffer == null) return;
+ _inputStream.Write(buffer, 0, buffer.Length);
+ _inputStream.Flush();
+ _inputStream.Position = 0;
+ }
+ }
+
+ public override object GetOutput()
+ {
+ // XSL transforms expose many powerful features by default:
+ // 1- we need to pass a null evidence to prevent script execution.
+ // 2- XPathDocument will expand entities, we don't want this, so set the resolver to null
+ // 3- We don't want the document function feature of XslTransforms.
+
+ // load the XSL Transform
+ XslCompiledTransform xslt = new XslCompiledTransform();
+ XmlReaderSettings settings = new XmlReaderSettings();
+ settings.XmlResolver = null;
+ settings.MaxCharactersFromEntities = Utils.GetMaxCharactersFromEntities();
+ settings.MaxCharactersInDocument = Utils.GetMaxCharactersInDocument();
+ using (StringReader sr = new StringReader(_xslFragment))
+ {
+ XmlReader readerXsl = XmlReader.Create(sr, settings, (string)null);
+ xslt.Load(readerXsl, XsltSettings.Default, null);
+
+ // Now load the input stream, XmlDocument can be used but is less efficient
+ XmlReader reader = XmlReader.Create(_inputStream, settings, BaseURI);
+ XPathDocument inputData = new XPathDocument(reader, XmlSpace.Preserve);
+
+ // Create an XmlTextWriter
+ MemoryStream ms = new MemoryStream();
+ XmlWriter writer = new XmlTextWriter(ms, null);
+
+ // Transform the data and send the output to the memory stream
+ xslt.Transform(inputData, null, writer);
+ ms.Position = 0;
+ return ms;
+ }
+ }
+
+ public override object GetOutput(Type type)
+ {
+ if (type != typeof(Stream) && !type.IsSubclassOf(typeof(Stream)))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"), "type");
+ return (Stream)GetOutput();
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs
new file mode 100644
index 0000000000..cd97c5dd42
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs
@@ -0,0 +1,195 @@
+// 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.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Policy;
+using System.Text;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace System.Security.Cryptography.Xml
+{
+ public class XmlLicenseTransform : Transform
+ {
+ private Type[] _inputTypes = { typeof(XmlDocument) };
+ private Type[] _outputTypes = { typeof(XmlDocument) };
+ private XmlNamespaceManager _namespaceManager = null;
+ private XmlDocument _license = null;
+ private IRelDecryptor _relDecryptor = null;
+ private const string ElementIssuer = "issuer";
+ private const string NamespaceUriCore = "urn:mpeg:mpeg21:2003:01-REL-R-NS";
+
+ public XmlLicenseTransform()
+ {
+ Algorithm = SignedXml.XmlLicenseTransformUrl;
+ }
+
+ public override Type[] InputTypes
+ {
+ get { return _inputTypes; }
+ }
+
+ public override Type[] OutputTypes
+ {
+ get { return _outputTypes; }
+ }
+
+ public IRelDecryptor Decryptor
+ {
+ get { return _relDecryptor; }
+ set { _relDecryptor = value; }
+ }
+
+ private void DecryptEncryptedGrants(XmlNodeList encryptedGrantList, IRelDecryptor decryptor)
+ {
+ XmlElement encryptionMethod = null;
+ XmlElement keyInfo = null;
+ XmlElement cipherData = null;
+ EncryptionMethod encryptionMethodObj = null;
+ KeyInfo keyInfoObj = null;
+ CipherData cipherDataObj = null;
+
+ for (int i = 0, count = encryptedGrantList.Count; i < count; i++)
+ {
+ encryptionMethod = encryptedGrantList[i].SelectSingleNode("//r:encryptedGrant/enc:EncryptionMethod", _namespaceManager) as XmlElement;
+ keyInfo = encryptedGrantList[i].SelectSingleNode("//r:encryptedGrant/dsig:KeyInfo", _namespaceManager) as XmlElement;
+ cipherData = encryptedGrantList[i].SelectSingleNode("//r:encryptedGrant/enc:CipherData", _namespaceManager) as XmlElement;
+ if ((encryptionMethod != null) &&
+ (keyInfo != null) &&
+ (cipherData != null))
+ {
+ encryptionMethodObj = new EncryptionMethod();
+ keyInfoObj = new KeyInfo();
+ cipherDataObj = new CipherData();
+
+ encryptionMethodObj.LoadXml(encryptionMethod);
+ keyInfoObj.LoadXml(keyInfo);
+ cipherDataObj.LoadXml(cipherData);
+
+ MemoryStream toDecrypt = null;
+ Stream decryptedContent = null;
+ StreamReader streamReader = null;
+
+ try
+ {
+ toDecrypt = new MemoryStream(cipherDataObj.CipherValue);
+ decryptedContent = _relDecryptor.Decrypt(encryptionMethodObj,
+ keyInfoObj, toDecrypt);
+
+ if ((decryptedContent == null) || (decryptedContent.Length == 0))
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_XrmlUnableToDecryptGrant"));
+
+ streamReader = new StreamReader(decryptedContent);
+ string clearContent = streamReader.ReadToEnd();
+
+ encryptedGrantList[i].ParentNode.InnerXml = clearContent;
+ }
+ finally
+ {
+ if (toDecrypt != null)
+ toDecrypt.Close();
+
+ if (decryptedContent != null)
+ decryptedContent.Close();
+
+ if (streamReader != null)
+ streamReader.Close();
+ }
+
+ encryptionMethodObj = null;
+ keyInfoObj = null;
+ cipherDataObj = null;
+ }
+
+ encryptionMethod = null;
+ keyInfo = null;
+ cipherData = null;
+ }
+ }
+
+ // License transform has no inner XML elements
+ protected override XmlNodeList GetInnerXml()
+ {
+ return null;
+ }
+
+ public override object GetOutput()
+ {
+ return _license;
+ }
+
+ public override object GetOutput(Type type)
+ {
+ if ((type != typeof(XmlDocument)) || (!type.IsSubclassOf(typeof(XmlDocument))))
+ throw new ArgumentException(SecurityResources.GetResourceString("Cryptography_Xml_TransformIncorrectInputType"), "type");
+
+ return GetOutput();
+ }
+
+ // License transform has no inner XML elements
+ public override void LoadInnerXml(XmlNodeList nodeList) { }
+
+ public override void LoadInput(object obj)
+ {
+ // Check if the Context property is set before this transform is invoked.
+ if (Context == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_XrmlMissingContext"));
+
+ _license = new XmlDocument();
+ _license.PreserveWhitespace = true;
+ _namespaceManager = new XmlNamespaceManager(_license.NameTable);
+ _namespaceManager.AddNamespace("dsig", SignedXml.XmlDsigNamespaceUrl);
+ _namespaceManager.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+ _namespaceManager.AddNamespace("r", NamespaceUriCore);
+
+ XmlElement currentIssuerContext = null;
+ XmlElement currentLicenseContext = null;
+ XmlNode signatureNode = null;
+
+ // Get the nearest issuer node
+ currentIssuerContext = Context.SelectSingleNode("ancestor-or-self::r:issuer[1]", _namespaceManager) as XmlElement;
+ if (currentIssuerContext == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_XrmlMissingIssuer"));
+
+ signatureNode = currentIssuerContext.SelectSingleNode("descendant-or-self::dsig:Signature[1]", _namespaceManager) as XmlElement;
+ if (signatureNode != null)
+ signatureNode.ParentNode.RemoveChild(signatureNode);
+
+ // Get the nearest license node
+ currentLicenseContext = currentIssuerContext.SelectSingleNode("ancestor-or-self::r:license[1]", _namespaceManager) as XmlElement;
+ if (currentLicenseContext == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_XrmlMissingLicence"));
+
+ XmlNodeList issuerList = currentLicenseContext.SelectNodes("descendant-or-self::r:license[1]/r:issuer", _namespaceManager);
+
+ // Remove all issuer nodes except current
+ for (int i = 0, count = issuerList.Count; i < count; i++)
+ {
+ if (issuerList[i] == currentIssuerContext)
+ continue;
+
+ if ((issuerList[i].LocalName == ElementIssuer) &&
+ (issuerList[i].NamespaceURI == NamespaceUriCore))
+ issuerList[i].ParentNode.RemoveChild(issuerList[i]);
+ }
+
+ XmlNodeList encryptedGrantList = currentLicenseContext.SelectNodes("/r:license/r:grant/r:encryptedGrant", _namespaceManager);
+
+ if (encryptedGrantList.Count > 0)
+ {
+ if (_relDecryptor == null)
+ throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_XrmlMissingIRelDecryptor"));
+
+ DecryptEncryptedGrants(encryptedGrantList, _relDecryptor);
+ }
+
+ _license.InnerXml = currentLicenseContext.OuterXml;
+ }
+ }
+}
diff --git a/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.builds b/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.builds
new file mode 100644
index 0000000000..1c628f1242
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.builds
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <ItemGroup>
+ <!-- Disabling the builds for Xml until we get it up and running. This excludes it from being built by build.cmd
+ <Project Include="System.Security.Cryptography.Xml.Tests.csproj"/>
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project>
+
diff --git a/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj b/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj
new file mode 100644
index 0000000000..3dbd1449d4
--- /dev/null
+++ b/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <Import Project="$(CommonTestPath)\Tests.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{3C32659A-6DB9-410A-8E24-BE91BFF4C024}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AssemblyName>System.Security.Cryptography.Xml.Tests</AssemblyName>
+ <RootNamespace>System.Security.Cryptography.Xml.Tests</RootNamespace>
+ <NugetTargetMoniker Condition="'$(TargetGroup)'==''">.NETStandard,Version=v1.7</NugetTargetMoniker>
+ </PropertyGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\pkg\System.Security.Cryptography.Xml.pkgproj">
+ <Project>{B0328E2E-E985-4C0B-A808-30C85620FE07}</Project>
+ <Name>System.Security.Cryptography.Xml</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <!--
+ <Compile Include="(addyourtest).cs" />
+ -->
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.Security.Permissions/pkg/System.Security.Permissions.pkgproj b/src/System.Security.Permissions/pkg/System.Security.Permissions.pkgproj
index b4f423ffca..3c5efa6ff4 100644
--- a/src/System.Security.Permissions/pkg/System.Security.Permissions.pkgproj
+++ b/src/System.Security.Permissions/pkg/System.Security.Permissions.pkgproj
@@ -3,7 +3,7 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Security.Permissions.csproj">
- <SupportedFramework>netcoreapp1.1;net463;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>netcoreapp1.1;net461;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Security.Permissions.builds" />
</ItemGroup>
diff --git a/src/System.Security.Permissions/src/Configurations.props b/src/System.Security.Permissions/src/Configurations.props
index 9c336c0be9..53b62c64fe 100644
--- a/src/System.Security.Permissions/src/Configurations.props
+++ b/src/System.Security.Permissions/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Security.Permissions/src/System.Security.Permissions.csproj b/src/System.Security.Permissions/src/System.Security.Permissions.csproj
index 871e8eec3d..e58498ceef 100644
--- a/src/System.Security.Permissions/src/System.Security.Permissions.csproj
+++ b/src/System.Security.Permissions/src/System.Security.Permissions.csproj
@@ -7,13 +7,13 @@
<AssemblyName>System.Security.Permissions</AssemblyName>
<PackageTargetFramework Condition="'$(TargetGroup)' == 'netstandard'">netstandard1.7</PackageTargetFramework>
<IsPartialFacadeAssembly>true</IsPartialFacadeAssembly>
- <PackageAsRefAndLib Condition="'$(TargetGroup)' == 'net463'">true</PackageAsRefAndLib>
+ <PackageAsRefAndLib Condition="'$(TargetGroup)' == 'net461'">true</PackageAsRefAndLib>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard'">
<Compile Include="System\Net\NetworkInformation\NetworkInformationAccess.cs" />
<Compile Include="System\Net\NetworkInformation\NetworkInformationPermission.cs" />
@@ -114,7 +114,7 @@
<Compile Include="System\Security\HostSecurityManager.cs" />
<Compile Include="System\Security\HostProtectionException.cs" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System" />
</ItemGroup>
diff --git a/src/System.Security.Principal/src/Configurations.props b/src/System.Security.Principal/src/Configurations.props
index 9c336c0be9..f013d10b8c 100644
--- a/src/System.Security.Principal/src/Configurations.props
+++ b/src/System.Security.Principal/src/Configurations.props
@@ -3,6 +3,7 @@
<PropertyGroup>
<BuildConfigurations>
net463-Windows_NT;
+ uap101aot-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Text.Encoding.CodePages/pkg/System.Text.Encoding.CodePages.pkgproj b/src/System.Text.Encoding.CodePages/pkg/System.Text.Encoding.CodePages.pkgproj
index 07cc91c01f..6f246a87d3 100644
--- a/src/System.Text.Encoding.CodePages/pkg/System.Text.Encoding.CodePages.pkgproj
+++ b/src/System.Text.Encoding.CodePages/pkg/System.Text.Encoding.CodePages.pkgproj
@@ -3,7 +3,7 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Text.Encoding.CodePages.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Text.Encoding.CodePages.builds" />
</ItemGroup>
diff --git a/src/System.Text.Encoding.CodePages/src/System.Text.Encoding.CodePages.csproj b/src/System.Text.Encoding.CodePages/src/System.Text.Encoding.CodePages.csproj
index 409c4f80a9..7cc0a4ec82 100644
--- a/src/System.Text.Encoding.CodePages/src/System.Text.Encoding.CodePages.csproj
+++ b/src/System.Text.Encoding.CodePages/src/System.Text.Encoding.CodePages.csproj
@@ -11,7 +11,7 @@
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
<PackageTargetFramework Include="netstandard1.7" />
<!-- need to support rid-less restore for packages.config -->
- <PackageTargetFramework Include="net463">
+ <PackageTargetFramework Include="net461">
<TargetRuntime></TargetRuntime>
</PackageTargetFramework>
</ItemGroup>
@@ -44,6 +44,9 @@
</ItemGroup>
<ItemGroup Condition=" '$(TargetsWindows)' == 'true' ">
<Compile Include="System\Text\CodePagesEncodingProvider.Windows.cs" />
+ <Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.Encoding.Constants.cs">
+ <Link>Common\Interop\Windows\kernel32\Interop.Encoding.Constants.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs">
<Link>Common\Interop\Windows\Interop.Libraries.cs</Link>
</Compile>
diff --git a/src/System.Text.Encoding.CodePages/src/System/Text/GB18030Encoding.cs b/src/System.Text.Encoding.CodePages/src/System/Text/GB18030Encoding.cs
index 07599d6c21..e4654cd2b5 100644
--- a/src/System.Text.Encoding.CodePages/src/System/Text/GB18030Encoding.cs
+++ b/src/System.Text.Encoding.CodePages/src/System/Text/GB18030Encoding.cs
@@ -106,8 +106,8 @@ namespace System.Text
{
// This is the table of 4 byte conversions.
private const int GBLast4ByteCode = 0x99FB;
- unsafe internal char* map4BytesToUnicode = null; // new char[GBLast4ByteCode + 1]; // Need to map all 4 byte sequences to Unicode
- unsafe internal byte* mapUnicodeTo4BytesFlags = null; // new byte[0x10000 / 8]; // Need 1 bit for each code point to say if its 4 byte or not
+ internal unsafe char* map4BytesToUnicode = null; // new char[GBLast4ByteCode + 1]; // Need to map all 4 byte sequences to Unicode
+ internal unsafe byte* mapUnicodeTo4BytesFlags = null; // new byte[0x10000 / 8]; // Need 1 bit for each code point to say if its 4 byte or not
private const int GB18030 = 54936;
diff --git a/src/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj b/src/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj
index 2bccfc313d..3d2d071fb1 100644
--- a/src/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj
+++ b/src/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj
@@ -84,5 +84,10 @@
<Link>Common\System\RuntimeDetection.cs</Link>
</Compile>
</ItemGroup>
+ <ItemGroup>
+ <Compile Include="$(CommonTestPath)\System\RuntimeDetection.cs">
+ <Link>Common\System\RuntimeDetection.cs</Link>
+ </Compile>
+ </ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/BufferInternal.cs b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/BufferInternal.cs
index 5159f0c970..f9e3235630 100644
--- a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/BufferInternal.cs
+++ b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/BufferInternal.cs
@@ -15,7 +15,7 @@ namespace System {
{
// This method has different signature for x64 and other platforms and is done for performance reasons.
[System.Security.SecurityCritical]
- private unsafe static void Memmove(byte* dest, byte* src, uint len)
+ private static unsafe void Memmove(byte* dest, byte* src, uint len)
{
if (AreOverlapping(dest, src, len))
{
diff --git a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/HtmlEncoder.cs b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/HtmlEncoder.cs
index f4d5b9d76c..1a0079b047 100644
--- a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/HtmlEncoder.cs
+++ b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/HtmlEncoder.cs
@@ -48,7 +48,7 @@ namespace System.Text.Encodings.Web
internal sealed class DefaultHtmlEncoder : HtmlEncoder
{
private AllowedCharactersBitmap _allowedCharacters;
- internal readonly static DefaultHtmlEncoder Singleton = new DefaultHtmlEncoder(new TextEncoderSettings(UnicodeRanges.BasicLatin));
+ internal static readonly DefaultHtmlEncoder Singleton = new DefaultHtmlEncoder(new TextEncoderSettings(UnicodeRanges.BasicLatin));
public DefaultHtmlEncoder(TextEncoderSettings filter)
{
@@ -117,7 +117,7 @@ namespace System.Text.Encodings.Web
else { return TryWriteEncodedScalarAsNumericEntity(unicodeScalar, buffer, bufferLength, out numberOfCharactersWritten); }
}
- private unsafe static bool TryWriteEncodedScalarAsNumericEntity(int unicodeScalar, char* buffer, int bufferLength, out int numberOfCharactersWritten)
+ private static unsafe bool TryWriteEncodedScalarAsNumericEntity(int unicodeScalar, char* buffer, int bufferLength, out int numberOfCharactersWritten)
{
Debug.Assert(buffer != null && bufferLength >= 0);
diff --git a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/JavaScriptEncoder.cs b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/JavaScriptEncoder.cs
index 390f233e7c..cfa099d745 100644
--- a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/JavaScriptEncoder.cs
+++ b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/JavaScriptEncoder.cs
@@ -49,7 +49,7 @@ namespace System.Text.Encodings.Web
{
private AllowedCharactersBitmap _allowedCharacters;
- internal readonly static DefaultJavaScriptEncoder Singleton = new DefaultJavaScriptEncoder(new TextEncoderSettings(UnicodeRanges.BasicLatin));
+ internal static readonly DefaultJavaScriptEncoder Singleton = new DefaultJavaScriptEncoder(new TextEncoderSettings(UnicodeRanges.BasicLatin));
public DefaultJavaScriptEncoder(TextEncoderSettings filter)
{
@@ -148,7 +148,7 @@ namespace System.Text.Encodings.Web
return TryCopyCharacters(toCopy, buffer, bufferLength, out numberOfCharactersWritten);
}
- private unsafe static bool TryWriteEncodedScalarAsNumericEntity(int unicodeScalar, char* buffer, int length, out int numberOfCharactersWritten)
+ private static unsafe bool TryWriteEncodedScalarAsNumericEntity(int unicodeScalar, char* buffer, int length, out int numberOfCharactersWritten)
{
Debug.Assert(buffer != null && length >= 0);
@@ -179,7 +179,7 @@ namespace System.Text.Encodings.Web
}
// Writes an encoded scalar value (in the BMP) as a JavaScript-escaped character.
- private unsafe static bool TryWriteEncodedSingleCharacter(int unicodeScalar, char* buffer, int length, out int numberOfCharactersWritten)
+ private static unsafe bool TryWriteEncodedSingleCharacter(int unicodeScalar, char* buffer, int length, out int numberOfCharactersWritten)
{
Debug.Assert(buffer != null && length >= 0);
Debug.Assert(!UnicodeHelpers.IsSupplementaryCodePoint(unicodeScalar), "The incoming value should've been in the BMP.");
diff --git a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs
index ad813c42bc..62b26b92bc 100644
--- a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs
+++ b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/TextEncoder.cs
@@ -377,7 +377,7 @@ namespace System.Text.Encodings.Web
}
}
- internal unsafe static bool TryCopyCharacters(char[] source, char* destination, int destinationLength, out int numberOfCharactersWritten)
+ internal static unsafe bool TryCopyCharacters(char[] source, char* destination, int destinationLength, out int numberOfCharactersWritten)
{
Debug.Assert(source != null && destination != null && destinationLength >= 0);
@@ -397,7 +397,7 @@ namespace System.Text.Encodings.Web
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal unsafe static bool TryWriteScalarAsChar(int unicodeScalar, char* destination, int destinationLength, out int numberOfCharactersWritten)
+ internal static unsafe bool TryWriteScalarAsChar(int unicodeScalar, char* destination, int destinationLength, out int numberOfCharactersWritten)
{
Debug.Assert(destination != null && destinationLength >= 0);
diff --git a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UnicodeHelpers.cs b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UnicodeHelpers.cs
index b3a73d6b06..f335beb3e4 100644
--- a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UnicodeHelpers.cs
+++ b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UnicodeHelpers.cs
@@ -13,7 +13,7 @@ namespace System.Text.Unicode
/// <summary>
/// Contains helpers for dealing with Unicode code points.
/// </summary>
- internal unsafe static class UnicodeHelpers
+ internal static unsafe class UnicodeHelpers
{
/// <summary>
/// Used for invalid Unicode sequences or other unrepresentable values.
diff --git a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UrlEncoder.cs b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UrlEncoder.cs
index 6c8909bb46..96aeef670f 100644
--- a/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UrlEncoder.cs
+++ b/src/System.Text.Encodings.Web/src/System/Text/Encodings/Web/UrlEncoder.cs
@@ -48,7 +48,7 @@ namespace System.Text.Encodings.Web
{
private AllowedCharactersBitmap _allowedCharacters;
- internal readonly static DefaultUrlEncoder Singleton = new DefaultUrlEncoder(new TextEncoderSettings(UnicodeRanges.BasicLatin));
+ internal static readonly DefaultUrlEncoder Singleton = new DefaultUrlEncoder(new TextEncoderSettings(UnicodeRanges.BasicLatin));
// We perform UTF8 conversion of input, which means that the worst case is
// 12 output chars per input surrogate char: [input] U+FFFF U+FFFF -> [output] "%XX%YY%ZZ%WW".
diff --git a/src/System.Text.RegularExpressions/pkg/System.Text.RegularExpressions.pkgproj b/src/System.Text.RegularExpressions/pkg/System.Text.RegularExpressions.pkgproj
index c134914c49..602af001ca 100644
--- a/src/System.Text.RegularExpressions/pkg/System.Text.RegularExpressions.pkgproj
+++ b/src/System.Text.RegularExpressions/pkg/System.Text.RegularExpressions.pkgproj
@@ -3,7 +3,7 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Text.RegularExpressions.builds">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Text.RegularExpressions.builds" />
<InboxOnTargetFramework Include="MonoAndroid10" />
@@ -19,6 +19,10 @@
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
+ <!-- the previous version of this package supported a different API version for
+ net463, but since netstandard2.0 supports the latest and net461 supports
+ netstandard2.0 we need to suppress the old net463 assembly. -->
+ <HarvestSuppressPaths Include="ref/net463;lib/net463" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/System.Text.RegularExpressions/src/Configurations.props b/src/System.Text.RegularExpressions/src/Configurations.props
index 9c336c0be9..53b62c64fe 100644
--- a/src/System.Text.RegularExpressions/src/Configurations.props
+++ b/src/System.Text.RegularExpressions/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Text.RegularExpressions/src/System.Text.RegularExpressions.csproj b/src/System.Text.RegularExpressions/src/System.Text.RegularExpressions.csproj
index c620a972b2..efe1463b87 100644
--- a/src/System.Text.RegularExpressions/src/System.Text.RegularExpressions.csproj
+++ b/src/System.Text.RegularExpressions/src/System.Text.RegularExpressions.csproj
@@ -4,15 +4,15 @@
<PropertyGroup>
<ProjectGuid>{BE28323E-327A-4E0F-B7F9-16AB7EAB59DD}</ProjectGuid>
<AssemblyName>System.Text.RegularExpressions</AssemblyName>
- <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net463'">true</IsPartialFacadeAssembly>
- <ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net463'">None</ResourcesSourceOutputDirectory>
+ <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net461'">true</IsPartialFacadeAssembly>
+ <ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net461'">None</ResourcesSourceOutputDirectory>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'netstandard_Debug|AnyCPU' " />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'netstandard_Release|AnyCPU' " />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<ContractProject Include="..\ref\System.Text.RegularExpressions.csproj">
<TargetGroup>netstandard</TargetGroup>
</ContractProject>
@@ -49,7 +49,7 @@
<Link>Common\System\IO\StringBuilderCache.cs</Link>
</Compile>
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System" />
</ItemGroup>
diff --git a/src/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs b/src/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs
index 76109a40f0..530e89cc85 100644
--- a/src/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs
+++ b/src/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs
@@ -175,6 +175,7 @@ namespace System.Text.RegularExpressions
&& (options & ~(RegexOptions.ECMAScript |
RegexOptions.IgnoreCase |
RegexOptions.Multiline |
+ RegexOptions.Compiled |
RegexOptions.CultureInvariant
#if DEBUG
| RegexOptions.Debug
diff --git a/src/System.Text.RegularExpressions/tests/Regex.Ctor.Tests.cs b/src/System.Text.RegularExpressions/tests/Regex.Ctor.Tests.cs
index 31fd3ee34f..5ca6058c45 100644
--- a/src/System.Text.RegularExpressions/tests/Regex.Ctor.Tests.cs
+++ b/src/System.Text.RegularExpressions/tests/Regex.Ctor.Tests.cs
@@ -14,7 +14,9 @@ namespace System.Text.RegularExpressions.Tests
{
yield return new object[] { "foo", RegexOptions.None, Timeout.InfiniteTimeSpan };
yield return new object[] { "foo", RegexOptions.RightToLeft, Timeout.InfiniteTimeSpan };
+ yield return new object[] { "foo", RegexOptions.Compiled, Timeout.InfiniteTimeSpan };
yield return new object[] { "foo", RegexOptions.ECMAScript | RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant, Timeout.InfiniteTimeSpan };
+ yield return new object[] { "foo", RegexOptions.ECMAScript | RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.Compiled, Timeout.InfiniteTimeSpan };
yield return new object[] { "foo", RegexOptions.None, new TimeSpan(1) };
yield return new object[] { "foo", RegexOptions.None, TimeSpan.FromMilliseconds(int.MaxValue - 1) };
}
diff --git a/src/System.Threading.AccessControl/src/System/Security/AccessControl/SemaphoreSecurity.cs b/src/System.Threading.AccessControl/src/System/Security/AccessControl/SemaphoreSecurity.cs
index 1c98403a3f..2cbe39d7e4 100644
--- a/src/System.Threading.AccessControl/src/System/Security/AccessControl/SemaphoreSecurity.cs
+++ b/src/System.Threading.AccessControl/src/System/Security/AccessControl/SemaphoreSecurity.cs
@@ -25,7 +25,7 @@ namespace System.Security.AccessControl
// Win32's interesting values are SEMAPHORE_MODIFY_STATE (0x2) and
// SEMAPHORE_ALL_ACCESS (0x1F0003). I don't know what 0x1 is.
- [Flags, ComVisible(false)]
+ [Flags]
public enum SemaphoreRights
{
Modify = 0x000002,
diff --git a/src/System.Threading.Overlapped/ref/System.Threading.Overlapped.cs b/src/System.Threading.Overlapped/ref/System.Threading.Overlapped.cs
index 72ae0b6b7d..37728114f1 100644
--- a/src/System.Threading.Overlapped/ref/System.Threading.Overlapped.cs
+++ b/src/System.Threading.Overlapped/ref/System.Threading.Overlapped.cs
@@ -39,7 +39,7 @@ namespace System.Threading
[System.CLSCompliantAttribute(false)]
public unsafe void FreeNativeOverlapped(System.Threading.NativeOverlapped* overlapped) { }
[System.CLSCompliantAttribute(false)]
- public unsafe static object GetNativeOverlappedState(System.Threading.NativeOverlapped* overlapped) { throw null; }
+ public static unsafe object GetNativeOverlappedState(System.Threading.NativeOverlapped* overlapped) { throw null; }
}
public partial class Overlapped
{
@@ -54,14 +54,14 @@ namespace System.Threading
public int OffsetHigh { get { throw null; } set { } }
public int OffsetLow { get { throw null; } set { } }
[System.CLSCompliantAttribute(false)]
- public unsafe static void Free(System.Threading.NativeOverlapped* nativeOverlappedPtr) { }
+ public static unsafe void Free(System.Threading.NativeOverlapped* nativeOverlappedPtr) { }
[System.CLSCompliantAttribute(false)]
[System.ObsoleteAttribute("This method is not safe. Use Pack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
public unsafe System.Threading.NativeOverlapped* Pack(System.Threading.IOCompletionCallback iocb) { throw null; }
[System.CLSCompliantAttribute(false)]
public unsafe System.Threading.NativeOverlapped* Pack(System.Threading.IOCompletionCallback iocb, object userData) { throw null; }
[System.CLSCompliantAttribute(false)]
- public unsafe static System.Threading.Overlapped Unpack(System.Threading.NativeOverlapped* nativeOverlappedPtr) { throw null; }
+ public static unsafe System.Threading.Overlapped Unpack(System.Threading.NativeOverlapped* nativeOverlappedPtr) { throw null; }
[System.CLSCompliantAttribute(false)]
[System.ObsoleteAttribute("This method is not safe. Use UnsafePack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
public unsafe System.Threading.NativeOverlapped* UnsafePack(System.Threading.IOCompletionCallback iocb) { throw null; }
diff --git a/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandle.cs b/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandle.cs
index d0cc5afbae..3242835b81 100644
--- a/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandle.cs
+++ b/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandle.cs
@@ -275,7 +275,7 @@ namespace System.Threading
/// <paramref name="overlapped"/> is <see langword="null"/>.
/// </exception>
[CLSCompliant(false)]
- public unsafe static object GetNativeOverlappedState(NativeOverlapped* overlapped)
+ public static unsafe object GetNativeOverlappedState(NativeOverlapped* overlapped)
{
if (overlapped == null)
throw new ArgumentNullException(nameof(overlapped));
diff --git a/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandleOverlapped.cs b/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandleOverlapped.cs
index 1aea2a294b..7ce8936bf7 100644
--- a/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandleOverlapped.cs
+++ b/src/System.Threading.Overlapped/src/System/Threading/ClrThreadPoolBoundHandleOverlapped.cs
@@ -29,7 +29,7 @@ namespace System.Threading
_nativeOverlapped->OffsetHigh = 0;
}
- private unsafe static void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
+ private static unsafe void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
{
ThreadPoolBoundHandleOverlapped overlapped = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(nativeOverlapped);
diff --git a/src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolBoundHandle.cs b/src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolBoundHandle.cs
index 401cbb624a..ab21d1c13e 100644
--- a/src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolBoundHandle.cs
+++ b/src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolBoundHandle.cs
@@ -141,7 +141,7 @@ namespace System.Threading
}
[CLSCompliant(false)]
- public unsafe static object GetNativeOverlappedState(NativeOverlapped* overlapped)
+ public static unsafe object GetNativeOverlappedState(NativeOverlapped* overlapped)
{
if (overlapped == null)
throw new ArgumentNullException(nameof(overlapped));
diff --git a/src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs b/src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs
index 9551a580d6..93f46d4f6b 100644
--- a/src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs
+++ b/src/System.Threading.Overlapped/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs
@@ -30,7 +30,7 @@ namespace System.Threading
get { return s_dataArray[_dataIndex]; }
}
- internal unsafe static Win32ThreadPoolNativeOverlapped* Allocate(IOCompletionCallback callback, object state, object pinData, PreAllocatedOverlapped preAllocated)
+ internal static unsafe Win32ThreadPoolNativeOverlapped* Allocate(IOCompletionCallback callback, object state, object pinData, PreAllocatedOverlapped preAllocated)
{
Win32ThreadPoolNativeOverlapped* overlapped = AllocateNew();
try
@@ -45,7 +45,7 @@ namespace System.Threading
return overlapped;
}
- private unsafe static Win32ThreadPoolNativeOverlapped* AllocateNew()
+ private static unsafe Win32ThreadPoolNativeOverlapped* AllocateNew()
{
IntPtr freePtr;
Win32ThreadPoolNativeOverlapped* overlapped;
@@ -158,7 +158,7 @@ namespace System.Threading
}
}
- internal unsafe static void Free(Win32ThreadPoolNativeOverlapped* overlapped)
+ internal static unsafe void Free(Win32ThreadPoolNativeOverlapped* overlapped)
{
// Reset all data.
overlapped->Data.Reset();
@@ -175,17 +175,17 @@ namespace System.Threading
}
}
- internal unsafe static NativeOverlapped* ToNativeOverlapped(Win32ThreadPoolNativeOverlapped* overlapped)
+ internal static unsafe NativeOverlapped* ToNativeOverlapped(Win32ThreadPoolNativeOverlapped* overlapped)
{
return (NativeOverlapped*)overlapped;
}
- internal unsafe static Win32ThreadPoolNativeOverlapped* FromNativeOverlapped(NativeOverlapped* overlapped)
+ internal static unsafe Win32ThreadPoolNativeOverlapped* FromNativeOverlapped(NativeOverlapped* overlapped)
{
return (Win32ThreadPoolNativeOverlapped*)overlapped;
}
- internal unsafe static void CompleteWithCallback(uint errorCode, uint bytesWritten, Win32ThreadPoolNativeOverlapped* overlapped)
+ internal static unsafe void CompleteWithCallback(uint errorCode, uint bytesWritten, Win32ThreadPoolNativeOverlapped* overlapped)
{
OverlappedData data = overlapped->Data;
@@ -211,7 +211,7 @@ namespace System.Threading
ExecutionContext.Run(data._executionContext, callback, args);
}
- private unsafe static void OnExecutionContextCallback(object state)
+ private static unsafe void OnExecutionContextCallback(object state)
{
ExecutionContextCallbackArgs args = (ExecutionContextCallbackArgs)state;
diff --git a/src/System.Threading.Overlapped/tests/DllImport.cs b/src/System.Threading.Overlapped/tests/DllImport.cs
index c4f3f92379..c6fc73a8f6 100644
--- a/src/System.Threading.Overlapped/tests/DllImport.cs
+++ b/src/System.Threading.Overlapped/tests/DllImport.cs
@@ -15,7 +15,7 @@ internal static class DllImport
FileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("api-ms-win-core-file-l1-1-0.dll", SetLastError = true)]
- internal static unsafe extern int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, IntPtr numBytesWritten_mustBeZero, NativeOverlapped* lpOverlapped);
+ internal static extern unsafe int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, IntPtr numBytesWritten_mustBeZero, NativeOverlapped* lpOverlapped);
[DllImport("api-ms-win-core-handle-l1-1-0.dll", SetLastError = true)]
diff --git a/src/System.Threading.Overlapped/tests/OverlappedTests.cs b/src/System.Threading.Overlapped/tests/OverlappedTests.cs
index 2697b80ef8..9ec0bed8ca 100644
--- a/src/System.Threading.Overlapped/tests/OverlappedTests.cs
+++ b/src/System.Threading.Overlapped/tests/OverlappedTests.cs
@@ -77,7 +77,7 @@ public static partial class OverlappedTests
Assert.Equal(obj.OffsetLow, 1);
}
[Fact]
- public unsafe static void PackNegTest()
+ public static unsafe void PackNegTest()
{
var helper = new AsyncHelper();
IOCompletionCallback callback = MyCallback(helper);
@@ -99,7 +99,7 @@ public static partial class OverlappedTests
[Fact]
- public unsafe static void PackNegTest1()
+ public static unsafe void PackNegTest1()
{
#pragma warning disable 618
var helper = new AsyncHelper();
@@ -122,7 +122,7 @@ public static partial class OverlappedTests
}
[Fact]
- public unsafe static void UnPackTest()
+ public static unsafe void UnPackTest()
{
Assert.Throws<ArgumentNullException>(() => Overlapped.Unpack(null));
@@ -144,7 +144,7 @@ public static partial class OverlappedTests
}
[Fact]
- public unsafe static void PackPosTest()
+ public static unsafe void PackPosTest()
{
#pragma warning disable 618
Overlapped ov = new Overlapped();
@@ -167,7 +167,7 @@ public static partial class OverlappedTests
#pragma warning restore 618
}
[Fact]
- public unsafe static void PackPosTest1()
+ public static unsafe void PackPosTest1()
{
Overlapped ov = new Overlapped();
var helper = new AsyncHelper();
@@ -188,7 +188,7 @@ public static partial class OverlappedTests
}
}
- unsafe internal static IOCompletionCallback MyCallback(AsyncHelper helper)
+ internal static unsafe IOCompletionCallback MyCallback(AsyncHelper helper)
{
IOCompletionCallback del = delegate (uint param1, uint param2, NativeOverlapped* overlapped)
{
@@ -216,7 +216,7 @@ internal class AsyncHelper
{
return this._event.WaitOne();
}
- unsafe internal void Callback(uint errorCode, uint numBytes, NativeOverlapped* _overlapped)
+ internal unsafe void Callback(uint errorCode, uint numBytes, NativeOverlapped* _overlapped)
{
try
{
diff --git a/src/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs b/src/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs
index a686286a50..08e6b7ba7d 100644
--- a/src/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs
+++ b/src/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs
@@ -568,7 +568,7 @@ namespace System.Threading.Tasks.Dataflow
}
/// <summary>Cached delegate used to cancel a send in response to a cancellation request.</summary>
- private readonly static Action<object> _cancellationCallback = CancellationHandler;
+ private static readonly Action<object> _cancellationCallback = CancellationHandler;
/// <summary>Attempts to cancel the source passed as state in response to a cancellation request.</summary>
/// <param name="state">
@@ -1157,7 +1157,7 @@ namespace System.Threading.Tasks.Dataflow
{
/// <summary>Cached delegate used in ReceiveCoreByLinking on the created timer. Passed the ReceiveTarget as the argument.</summary>
/// <remarks>The C# compiler will not cache this delegate by default due to it being a generic method on a non-generic class.</remarks>
- internal readonly static TimerCallback CachedLinkingTimerCallback = state =>
+ internal static readonly TimerCallback CachedLinkingTimerCallback = state =>
{
var receiveTarget = (ReceiveTarget<T>)state;
receiveTarget.TryCleanupAndComplete(ReceiveCoreByLinkingCleanupReason.Timer);
@@ -1165,7 +1165,7 @@ namespace System.Threading.Tasks.Dataflow
/// <summary>Cached delegate used in ReceiveCoreByLinking on the cancellation token. Passed the ReceiveTarget as the state argument.</summary>
/// <remarks>The C# compiler will not cache this delegate by default due to it being a generic method on a non-generic class.</remarks>
- internal readonly static Action<object> CachedLinkingCancellationCallback = state =>
+ internal static readonly Action<object> CachedLinkingCancellationCallback = state =>
{
var receiveTarget = (ReceiveTarget<T>)state;
receiveTarget.TryCleanupAndComplete(ReceiveCoreByLinkingCleanupReason.Cancellation);
@@ -1538,7 +1538,7 @@ namespace System.Threading.Tasks.Dataflow
/// Cached continuation delegate that unregisters from cancellation and
/// marshals the antecedent's result to the return value.
/// </summary>
- internal readonly static Func<Task<bool>, object, bool> s_handleCompletion = (antecedent, state) =>
+ internal static readonly Func<Task<bool>, object, bool> s_handleCompletion = (antecedent, state) =>
{
var target = state as OutputAvailableAsyncTarget<T>;
Debug.Assert(target != null, "Expected non-null target");
@@ -1550,7 +1550,7 @@ namespace System.Threading.Tasks.Dataflow
/// Cached delegate that cancels the target and unlinks the target from the source.
/// Expects an OutputAvailableAsyncTarget as the state argument.
/// </summary>
- internal readonly static Action<object> s_cancelAndUnlink = CancelAndUnlink;
+ internal static readonly Action<object> s_cancelAndUnlink = CancelAndUnlink;
/// <summary>Cancels the target and unlinks the target from the source.</summary>
/// <param name="state">An OutputAvailableAsyncTarget.</param>
diff --git a/src/System.Threading.Tasks.Dataflow/src/Internal/ActionOnDispose.cs b/src/System.Threading.Tasks.Dataflow/src/Internal/ActionOnDispose.cs
index 825a29ba7c..250088bd03 100644
--- a/src/System.Threading.Tasks.Dataflow/src/Internal/ActionOnDispose.cs
+++ b/src/System.Threading.Tasks.Dataflow/src/Internal/ActionOnDispose.cs
@@ -20,7 +20,7 @@ namespace System.Threading.Tasks.Dataflow.Internal
internal sealed class Disposables
{
/// <summary>An IDisposable that does nothing.</summary>
- internal readonly static IDisposable Nop = new NopDisposable();
+ internal static readonly IDisposable Nop = new NopDisposable();
/// <summary>Creates an IDisposable that runs an action when disposed.</summary>
/// <typeparam name="T1">Specifies the type of the first argument.</typeparam>
diff --git a/src/System.Threading.Tasks.Dataflow/src/Internal/Common.cs b/src/System.Threading.Tasks.Dataflow/src/Internal/Common.cs
index c30f1bca6a..ff6ae30b67 100644
--- a/src/System.Threading.Tasks.Dataflow/src/Internal/Common.cs
+++ b/src/System.Threading.Tasks.Dataflow/src/Internal/Common.cs
@@ -595,12 +595,12 @@ namespace System.Threading.Tasks.Dataflow.Internal
static class CachedGenericDelegates<T>
{
/// <summary>A function that returns the default value of T.</summary>
- internal readonly static Func<T> DefaultTResultFunc = () => default(T);
+ internal static readonly Func<T> DefaultTResultFunc = () => default(T);
/// <summary>
/// A function to use as the body of ActionOnDispose in CreateUnlinkerShim.
/// Passed a tuple of the sync obj, the target registry, and the target block as the state parameter.
/// </summary>
- internal readonly static Action<object, TargetRegistry<T>, ITargetBlock<T>> CreateUnlinkerShimAction =
+ internal static readonly Action<object, TargetRegistry<T>, ITargetBlock<T>> CreateUnlinkerShimAction =
(syncObj, registry, target) =>
{
lock (syncObj) registry.Remove(target);
diff --git a/src/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs b/src/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs
index f9491ed982..caf8a54985 100644
--- a/src/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs
+++ b/src/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs
@@ -33,7 +33,7 @@ namespace System.Threading.Tasks.Dataflow.Internal
/// Defines the singleton instance for the dataflow ETW provider.
/// The dataflow provider GUID is {16F53577-E41D-43D4-B47E-C17025BF4025}.
/// </summary>
- internal readonly static DataflowEtwProvider Log = new DataflowEtwProvider();
+ internal static readonly DataflowEtwProvider Log = new DataflowEtwProvider();
/// <summary>Prevent external instantiation. All logging should go through the Log instance.</summary>
private DataflowEtwProvider() { }
diff --git a/src/System.Threading.Tasks.Dataflow/src/Internal/ImmutableArray.cs b/src/System.Threading.Tasks.Dataflow/src/Internal/ImmutableArray.cs
index fbf3141355..f9213e5b88 100644
--- a/src/System.Threading.Tasks.Dataflow/src/Internal/ImmutableArray.cs
+++ b/src/System.Threading.Tasks.Dataflow/src/Internal/ImmutableArray.cs
@@ -26,7 +26,7 @@ namespace System.Threading.Tasks.Dataflow.Internal
internal struct ImmutableArray<T>
{
/// <summary>An empty array.</summary>
- private readonly static ImmutableArray<T> s_empty = new ImmutableArray<T>(new T[0]);
+ private static readonly ImmutableArray<T> s_empty = new ImmutableArray<T>(new T[0]);
/// <summary>The immutable data in this array instance.</summary>
private readonly T[] _array;
diff --git a/src/System.Threading.Tasks.Extensions/tests/AsyncValueTaskMethodBuilderTests.cs b/src/System.Threading.Tasks.Extensions/tests/AsyncValueTaskMethodBuilderTests.cs
index a8230a11bd..6e47ae1d0e 100644
--- a/src/System.Threading.Tasks.Extensions/tests/AsyncValueTaskMethodBuilderTests.cs
+++ b/src/System.Threading.Tasks.Extensions/tests/AsyncValueTaskMethodBuilderTests.cs
@@ -184,6 +184,26 @@ namespace System.Threading.Tasks.Tests
Assert.False(WrapsTask(vt));
}
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(2)]
+ [InlineData(10)]
+ public static async Task UsedWithAsyncMethod_CompletesSuccessfully(int yields)
+ {
+ Assert.Equal(42, await ValueTaskReturningAsyncMethod(42));
+
+ ValueTask<int> vt = ValueTaskReturningAsyncMethod(84);
+ Assert.Equal(yields > 0, WrapsTask(vt));
+ Assert.Equal(84, await vt);
+
+ async ValueTask<int> ValueTaskReturningAsyncMethod(int result)
+ {
+ for (int i = 0; i < yields; i++) await Task.Yield();
+ return result;
+ }
+ }
+
/// <summary>Gets whether the ValueTask has a non-null Task.</summary>
private static bool WrapsTask<T>(ValueTask<T> vt) => ReferenceEquals(vt.AsTask(), vt.AsTask());
diff --git a/src/System.Threading.Tasks/tests/Task/TaskContinueWhenAnyTests.cs b/src/System.Threading.Tasks/tests/Task/TaskContinueWhenAnyTests.cs
index 1b801adf84..dd1f708a35 100644
--- a/src/System.Threading.Tasks/tests/Task/TaskContinueWhenAnyTests.cs
+++ b/src/System.Threading.Tasks/tests/Task/TaskContinueWhenAnyTests.cs
@@ -220,7 +220,7 @@ namespace Test
public static void TestContinueWhenAnyException(Task[] antecedents, bool FutureFactory, bool continuationIsFuture)
{
- bool antecedentsAreFutures = antecedents is Task<int>[];
+ bool antecedentsAreFutures = (antecedents as Task<int>[]) != null;
Debug.WriteLine(" * Test Exceptions in TaskFactory{0}.ContinueWhenAny(Task{1}[],Task{2})",
FutureFactory ? "<TResult>" : "",
diff --git a/src/System.Threading.Thread/pkg/System.Threading.Thread.pkgproj b/src/System.Threading.Thread/pkg/System.Threading.Thread.pkgproj
index ecb42c59fc..7cf0777ac9 100644
--- a/src/System.Threading.Thread/pkg/System.Threading.Thread.pkgproj
+++ b/src/System.Threading.Thread/pkg/System.Threading.Thread.pkgproj
@@ -3,7 +3,7 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Threading.Thread.csproj">
- <SupportedFramework>net463;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;uap10.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Threading.Thread.builds" />
</ItemGroup>
diff --git a/src/System.Threading.Thread/ref/System.Threading.Thread.cs b/src/System.Threading.Thread/ref/System.Threading.Thread.cs
index 54bc32203c..561a4695ef 100644
--- a/src/System.Threading.Thread/ref/System.Threading.Thread.cs
+++ b/src/System.Threading.Thread/ref/System.Threading.Thread.cs
@@ -30,9 +30,7 @@ namespace System.Threading
public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public static void Run(System.Threading.CompressedStack compressedStack, System.Threading.ContextCallback callback, object state) { }
}
- [System.Runtime.InteropServices.ComVisibleAttribute(false)]
public delegate void ParameterizedThreadStart(object obj);
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public sealed partial class Thread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
{
public Thread(System.Threading.ParameterizedThreadStart start) { }
@@ -156,14 +154,12 @@ namespace System.Threading
Lowest = 0,
Normal = 2,
}
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public delegate void ThreadStart();
public sealed partial class ThreadStartException : System.SystemException
{
internal ThreadStartException() { }
}
[System.FlagsAttribute]
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public enum ThreadState
{
Aborted = 256,
@@ -177,7 +173,6 @@ namespace System.Threading
Unstarted = 8,
WaitSleepJoin = 32,
}
- [System.Runtime.InteropServices.ComVisibleAttribute(true)]
public partial class ThreadStateException : System.SystemException
{
public ThreadStateException() { }
diff --git a/src/System.Threading.Thread/src/Configurations.props b/src/System.Threading.Thread/src/Configurations.props
index 449c3c6dbf..d9529542a7 100644
--- a/src/System.Threading.Thread/src/Configurations.props
+++ b/src/System.Threading.Thread/src/Configurations.props
@@ -5,7 +5,7 @@
uap101aot-Windows_NT;
netstandard-Windows_NT;
netstandard-Unix;
- net463-Windows_NT;
+ net461-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>
diff --git a/src/System.Threading.Thread/src/System.Threading.Thread.csproj b/src/System.Threading.Thread/src/System.Threading.Thread.csproj
index 91e248f8bc..c0ded57219 100644
--- a/src/System.Threading.Thread/src/System.Threading.Thread.csproj
+++ b/src/System.Threading.Thread/src/System.Threading.Thread.csproj
@@ -16,14 +16,14 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Unix_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Unix_Release|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net461_Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101aot_Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101aot_Release|AnyCPU'" />
<PropertyGroup Condition="'$(TargetGroup)' == 'uap101aot'">
<DefineConstants>$(DefineConstants);NETNATIVE</DefineConstants>
</PropertyGroup>
- <ItemGroup Condition="'$(TargetGroup)' != 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' != 'net461'">
<Compile Include="System\LocalDataStoreSlot.cs" />
<Compile Include="System\Threading\CompressedStack.cs" />
<Compile Include="System\Threading\Thread.cs" />
@@ -44,14 +44,14 @@
</ProjectReference>
<ProjectReference Include="..\..\System.Diagnostics.Debug\src\System.Diagnostics.Debug.csproj" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' != 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' != 'net461'">
<TargetingPackReference Include="System.Private.CoreLib" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'uap101aot'">
<ProjectReference Include="..\..\System.Runtime\src\System.Runtime.csproj" />
<ProjectReference Include="..\..\System.Resources.ResourceManager\src\System.Resources.ResourceManager.csproj" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System" />
<TargetingPackReference Include="System.Core" />
diff --git a/src/System.Threading.Thread/src/System/Threading/ThreadAbortException.cs b/src/System.Threading.Thread/src/System/Threading/ThreadAbortException.cs
index 51237bc8fd..54c1eba370 100644
--- a/src/System.Threading.Thread/src/System/Threading/ThreadAbortException.cs
+++ b/src/System.Threading.Thread/src/System/Threading/ThreadAbortException.cs
@@ -18,7 +18,7 @@ namespace System.Threading
{
}
- internal ThreadAbortException(SerializationInfo info, StreamingContext context) : base(info, context)
+ private ThreadAbortException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
diff --git a/src/System.Threading.ThreadPool/ref/System.Threading.ThreadPool.cs b/src/System.Threading.ThreadPool/ref/System.Threading.ThreadPool.cs
index f615cd2879..e74a38807e 100644
--- a/src/System.Threading.ThreadPool/ref/System.Threading.ThreadPool.cs
+++ b/src/System.Threading.ThreadPool/ref/System.Threading.ThreadPool.cs
@@ -32,7 +32,7 @@ namespace System.Threading
public static bool SetMaxThreads(int workerThreads, int completionPortThreads) { throw null; }
public static bool SetMinThreads(int workerThreads, int completionPortThreads) { throw null; }
[System.CLSCompliantAttribute(false)]
- public unsafe static bool UnsafeQueueNativeOverlapped(System.Threading.NativeOverlapped* overlapped) { throw null; }
+ public static unsafe bool UnsafeQueueNativeOverlapped(System.Threading.NativeOverlapped* overlapped) { throw null; }
public static bool UnsafeQueueUserWorkItem(System.Threading.WaitCallback callBack, object state) { throw null; }
public static System.Threading.RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) { throw null; }
public static System.Threading.RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) { throw null; }
diff --git a/src/System.Threading.ThreadPool/tests/ThreadPoolTests.cs b/src/System.Threading.ThreadPool/tests/ThreadPoolTests.cs
index 614f525f70..615e011bef 100644
--- a/src/System.Threading.ThreadPool/tests/ThreadPoolTests.cs
+++ b/src/System.Threading.ThreadPool/tests/ThreadPoolTests.cs
@@ -108,8 +108,7 @@ namespace System.Threading.ThreadPools.Tests
}
}
- // TODO: Enable this test after CoreCLR packages including the fix for this issue are updated
- //[Fact]
+ [Fact]
// Desktop framework doesn't check for this and instead, hits an assertion failure
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)]
public static void SetMinMaxThreadsTest_ChangedInDotNetCore()
diff --git a/src/System.Threading.Timer/ref/System.Threading.Timer.Manual.cs b/src/System.Threading.Timer/ref/System.Threading.Timer.Manual.cs
deleted file mode 100644
index 0f823519a4..0000000000
--- a/src/System.Threading.Timer/ref/System.Threading.Timer.Manual.cs
+++ /dev/null
@@ -1,23 +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.
-// ------------------------------------------------------------------------------
-// Changes to this file must follow the http://aka.ms/api-review process.
-// ------------------------------------------------------------------------------
-
-
-using System.Runtime.InteropServices;
-
-namespace System.Threading
-{
- // The ComVisible attributes are here to ensure there is no delta when rebuilding
- // the contract vs. the manual source code that was originally used for this contract.
- // The attributes are not actually meaningful since we don't emit ComVisible(false) at
- // the assembly level in contracts.
- [ComVisible(true)]
- public partial class Timer { }
-
- // This is providedInSource as it's the only way to add an attribute to a delegate.
- [ComVisible(true)]
- public delegate void TimerCallback(object state);
-}
diff --git a/src/System.Threading.Timer/ref/System.Threading.Timer.cs b/src/System.Threading.Timer/ref/System.Threading.Timer.cs
index 5d198568c0..b418976379 100644
--- a/src/System.Threading.Timer/ref/System.Threading.Timer.cs
+++ b/src/System.Threading.Timer/ref/System.Threading.Timer.cs
@@ -8,7 +8,7 @@
namespace System.Threading
{
- public sealed partial class Timer : System.MarshalByRefObject, System.IDisposable
+ public sealed class Timer : System.MarshalByRefObject, System.IDisposable
{
public Timer(System.Threading.TimerCallback callback) { }
public Timer(System.Threading.TimerCallback callback, object state, int dueTime, int period) { }
@@ -24,4 +24,6 @@ namespace System.Threading
public void Dispose() { }
public bool Dispose(System.Threading.WaitHandle notifyObject) { throw null; }
}
+
+ public delegate void TimerCallback(object state);
}
diff --git a/src/System.Threading.Timer/ref/System.Threading.Timer.csproj b/src/System.Threading.Timer/ref/System.Threading.Timer.csproj
index 06138470c7..8fb34f13dc 100644
--- a/src/System.Threading.Timer/ref/System.Threading.Timer.csproj
+++ b/src/System.Threading.Timer/ref/System.Threading.Timer.csproj
@@ -3,7 +3,6 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Compile Include="System.Threading.Timer.cs" />
- <Compile Include="System.Threading.Timer.Manual.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
diff --git a/src/System.Threading/src/System/Collections/Concurrent/LowLevelConcurrentQueue.cs b/src/System.Threading/src/System/Collections/Concurrent/LowLevelConcurrentQueue.cs
deleted file mode 100644
index 81229e0ab7..0000000000
--- a/src/System.Threading/src/System/Collections/Concurrent/LowLevelConcurrentQueue.cs
+++ /dev/null
@@ -1,615 +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.
-#pragma warning disable 0420
-
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-// A lock-free, concurrent queue primitive, and its associated debugger view type.
-//
-// This is a stripped-down version of ConcurrentQueue, for use from within the System.Threading
-// surface to eliminate a dependency on System.Collections.Concurrent.
-// Please try to keep this in sync with the public ConcurrentQueue implementation.
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Threading;
-
-namespace System.Collections.Concurrent
-{
- /// <summary>
- /// Represents a thread-safe first-in, first-out collection of objects.
- /// </summary>
- /// <typeparam name="T">Specifies the type of elements in the queue.</typeparam>
- /// <remarks>
- /// All public and protected members of <see cref="ConcurrentQueue{T}"/> are thread-safe and may be used
- /// concurrently from multiple threads.
- /// </remarks>
- internal class LowLevelConcurrentQueue<T> /*: IProducerConsumerCollection<T>*/ : IEnumerable<T>
- {
- //fields of ConcurrentQueue
- private volatile Segment _head;
-
- private volatile Segment _tail;
-
- private const int SEGMENT_SIZE = 32;
-
- //number of snapshot takers, GetEnumerator(), ToList() and ToArray() operations take snapshot.
- internal volatile int m_numSnapshotTakers = 0;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class.
- /// </summary>
- public LowLevelConcurrentQueue()
- {
- _head = _tail = new Segment(0, this);
- }
-
- /// <summary>
- /// Returns an enumerator that iterates through a collection.
- /// </summary>
- /// <returns>An <see cref="T:System.Collections.IEnumerator"/> that can be used to iterate through the collection.</returns>
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable<T>)this).GetEnumerator();
- }
-
- /// <summary>
- /// Gets a value that indicates whether the <see cref="ConcurrentQueue{T}"/> is empty.
- /// </summary>
- /// <value>true if the <see cref="ConcurrentQueue{T}"/> is empty; otherwise, false.</value>
- /// <remarks>
- /// For determining whether the collection contains any items, use of this property is recommended
- /// rather than retrieving the number of items from the <see cref="Count"/> property and comparing it
- /// to 0. However, as this collection is intended to be accessed concurrently, it may be the case
- /// that another thread will modify the collection after <see cref="IsEmpty"/> returns, thus invalidating
- /// the result.
- /// </remarks>
- public bool IsEmpty
- {
- get
- {
- Segment head = _head;
- if (!head.IsEmpty)
- //fast route 1:
- //if current head is not empty, then queue is not empty
- return false;
- else if (head.Next == null)
- //fast route 2:
- //if current head is empty and it's the last segment
- //then queue is empty
- return true;
- else
- //slow route:
- //current head is empty and it is NOT the last segment,
- //it means another thread is growing new segment
- {
- SpinWait spin = new SpinWait();
- while (head.IsEmpty)
- {
- if (head.Next == null)
- return true;
-
- spin.SpinOnce();
- head = _head;
- }
- return false;
- }
- }
- }
-
- /// <summary>
- /// Store the position of the current head and tail positions.
- /// </summary>
- /// <param name="head">return the head segment</param>
- /// <param name="tail">return the tail segment</param>
- /// <param name="headLow">return the head offset, value range [0, SEGMENT_SIZE]</param>
- /// <param name="tailHigh">return the tail offset, value range [-1, SEGMENT_SIZE-1]</param>
- private void GetHeadTailPositions(out Segment head, out Segment tail,
- out int headLow, out int tailHigh)
- {
- head = _head;
- tail = _tail;
- headLow = head.Low;
- tailHigh = tail.High;
- SpinWait spin = new SpinWait();
-
- //we loop until the observed values are stable and sensible.
- //This ensures that any update order by other methods can be tolerated.
- while (
- //if head and tail changed, retry
- head != _head || tail != _tail
- //if low and high pointers, retry
- || headLow != head.Low || tailHigh != tail.High
- //if head jumps ahead of tail because of concurrent grow and dequeue, retry
- || head.m_index > tail.m_index)
- {
- spin.SpinOnce();
- head = _head;
- tail = _tail;
- headLow = head.Low;
- tailHigh = tail.High;
- }
- }
-
-
- /// <summary>
- /// Gets the number of elements contained in the <see cref="ConcurrentQueue{T}"/>.
- /// </summary>
- /// <value>The number of elements contained in the <see cref="ConcurrentQueue{T}"/>.</value>
- /// <remarks>
- /// For determining whether the collection contains any items, use of the <see cref="IsEmpty"/>
- /// property is recommended rather than retrieving the number of items from the <see cref="Count"/>
- /// property and comparing it to 0.
- /// </remarks>
- public int Count
- {
- get
- {
- //store head and tail positions in buffer,
- Segment head, tail;
- int headLow, tailHigh;
- GetHeadTailPositions(out head, out tail, out headLow, out tailHigh);
-
- if (head == tail)
- {
- return tailHigh - headLow + 1;
- }
-
- //head segment
- int count = SEGMENT_SIZE - headLow;
-
- //middle segment(s), if any, are full.
- //We don't deal with overflow to be consistent with the behavior of generic types in CLR.
- count += SEGMENT_SIZE * ((int)(tail.m_index - head.m_index - 1));
-
- //tail segment
- count += tailHigh + 1;
-
- return count;
- }
- }
-
- /// <summary>
- /// Returns an enumerator that iterates through the <see
- /// cref="ConcurrentQueue{T}"/>.
- /// </summary>
- /// <returns>An enumerator for the contents of the <see
- /// cref="ConcurrentQueue{T}"/>.</returns>
- /// <remarks>
- /// The enumeration represents a moment-in-time snapshot of the contents
- /// of the queue. It does not reflect any updates to the collection after
- /// <see cref="GetEnumerator"/> was called. The enumerator is safe to use
- /// concurrently with reads from and writes to the queue.
- /// </remarks>
- public IEnumerator<T> GetEnumerator()
- {
- // Increments the number of active snapshot takers. This increment must happen before the snapshot is
- // taken. At the same time, Decrement must happen after the enumeration is over. Only in this way, can it
- // eliminate race condition when Segment.TryRemove() checks whether m_numSnapshotTakers == 0.
- Interlocked.Increment(ref m_numSnapshotTakers);
-
- // Takes a snapshot of the queue.
- // A design flaw here: if a Thread.Abort() happens, we cannot decrement m_numSnapshotTakers. But we cannot
- // wrap the following with a try/finally block, otherwise the decrement will happen before the yield return
- // statements in the GetEnumerator (head, tail, headLow, tailHigh) method.
- Segment head, tail;
- int headLow, tailHigh;
- GetHeadTailPositions(out head, out tail, out headLow, out tailHigh);
-
- //If we put yield-return here, the iterator will be lazily evaluated. As a result a snapshot of
- // the queue is not taken when GetEnumerator is initialized but when MoveNext() is first called.
- // This is inconsistent with existing generic collections. In order to prevent it, we capture the
- // value of m_head in a buffer and call out to a helper method.
- //The old way of doing this was to return the ToList().GetEnumerator(), but ToList() was an
- // unnecessary perfomance hit.
- return GetEnumerator(head, tail, headLow, tailHigh);
- }
-
- /// <summary>
- /// Helper method of GetEnumerator to seperate out yield return statement, and prevent lazy evaluation.
- /// </summary>
- private IEnumerator<T> GetEnumerator(Segment head, Segment tail, int headLow, int tailHigh)
- {
- try
- {
- SpinWait spin = new SpinWait();
-
- if (head == tail)
- {
- for (int i = headLow; i <= tailHigh; i++)
- {
- // If the position is reserved by an Enqueue operation, but the value is not written into,
- // spin until the value is available.
- spin.Reset();
- while (!head.m_state[i].m_value)
- {
- spin.SpinOnce();
- }
- yield return head.m_array[i];
- }
- }
- else
- {
- //iterate on head segment
- for (int i = headLow; i < SEGMENT_SIZE; i++)
- {
- // If the position is reserved by an Enqueue operation, but the value is not written into,
- // spin until the value is available.
- spin.Reset();
- while (!head.m_state[i].m_value)
- {
- spin.SpinOnce();
- }
- yield return head.m_array[i];
- }
- //iterate on middle segments
- Segment curr = head.Next;
- while (curr != tail)
- {
- for (int i = 0; i < SEGMENT_SIZE; i++)
- {
- // If the position is reserved by an Enqueue operation, but the value is not written into,
- // spin until the value is available.
- spin.Reset();
- while (!curr.m_state[i].m_value)
- {
- spin.SpinOnce();
- }
- yield return curr.m_array[i];
- }
- curr = curr.Next;
- }
-
- //iterate on tail segment
- for (int i = 0; i <= tailHigh; i++)
- {
- // If the position is reserved by an Enqueue operation, but the value is not written into,
- // spin until the value is available.
- spin.Reset();
- while (!tail.m_state[i].m_value)
- {
- spin.SpinOnce();
- }
- yield return tail.m_array[i];
- }
- }
- }
- finally
- {
- // This Decrement must happen after the enumeration is over.
- Interlocked.Decrement(ref m_numSnapshotTakers);
- }
- }
-
- /// <summary>
- /// Adds an object to the end of the <see cref="ConcurrentQueue{T}"/>.
- /// </summary>
- /// <param name="item">The object to add to the end of the <see
- /// cref="ConcurrentQueue{T}"/>. The value can be a null reference
- /// (Nothing in Visual Basic) for reference types.
- /// </param>
- public void Enqueue(T item)
- {
- SpinWait spin = new SpinWait();
- while (true)
- {
- Segment tail = _tail;
- if (tail.TryAppend(item))
- return;
- spin.SpinOnce();
- }
- }
-
-
- /// <summary>
- /// Attempts to remove and return the object at the beginning of the <see
- /// cref="ConcurrentQueue{T}"/>.
- /// </summary>
- /// <param name="result">
- /// When this method returns, if the operation was successful, <paramref name="result"/> contains the
- /// object removed. If no object was available to be removed, the value is unspecified.
- /// </param>
- /// <returns>true if an element was removed and returned from the beggining of the <see
- /// cref="ConcurrentQueue{T}"/>
- /// succesfully; otherwise, false.</returns>
- public bool TryDequeue(out T result)
- {
- while (!IsEmpty)
- {
- Segment head = _head;
- if (head.TryRemove(out result))
- return true;
- //since method IsEmpty spins, we don't need to spin in the while loop
- }
- result = default(T);
- return false;
- }
-
- /// <summary>
- /// private class for ConcurrentQueue.
- /// a queue is a linked list of small arrays, each node is called a segment.
- /// A segment contains an array, a pointer to the next segment, and m_low, m_high indices recording
- /// the first and last valid elements of the array.
- /// </summary>
- private class Segment
- {
- //we define two volatile arrays: m_array and m_state. Note that the accesses to the array items
- //do not get volatile treatment. But we don't need to worry about loading adjacent elements or
- //store/load on adjacent elements would suffer reordering.
- // - Two stores: these are at risk, but CLRv2 memory model guarantees store-release hence we are safe.
- // - Two loads: because one item from two volatile arrays are accessed, the loads of the array references
- // are sufficient to prevent reordering of the loads of the elements.
- internal volatile T[] m_array;
-
- // For each entry in m_array, the corresponding entry in m_state indicates whether this position contains
- // a valid value. m_state is initially all false.
- internal volatile VolatileBool[] m_state;
-
- //pointer to the next segment. null if the current segment is the last segment
- private volatile Segment _next;
-
- //We use this zero based index to track how many segments have been created for the queue, and
- //to compute how many active segments are there currently.
- // * The number of currently active segments is : m_tail.m_index - m_head.m_index + 1;
- // * m_index is incremented with every Segment.Grow operation. We use Int64 type, and we can safely
- // assume that it never overflows. To overflow, we need to do 2^63 increments, even at a rate of 4
- // billion (2^32) increments per second, it takes 2^31 seconds, which is about 64 years.
- internal readonly long m_index;
-
- //indices of where the first and last valid values
- // - m_low points to the position of the next element to pop from this segment, range [0, infinity)
- // m_low >= SEGMENT_SIZE implies the segment is disposable
- // - m_high points to the position of the latest pushed element, range [-1, infinity)
- // m_high == -1 implies the segment is new and empty
- // m_high >= SEGMENT_SIZE-1 means this segment is ready to grow.
- // and the thread who sets m_high to SEGMENT_SIZE-1 is responsible to grow the segment
- // - Math.Min(m_low, SEGMENT_SIZE) > Math.Min(m_high, SEGMENT_SIZE-1) implies segment is empty
- // - initially m_low =0 and m_high=-1;
- private volatile int _low;
- private volatile int _high;
-
- private volatile LowLevelConcurrentQueue<T> _source;
-
- /// <summary>
- /// Create and initialize a segment with the specified index.
- /// </summary>
- internal Segment(long index, LowLevelConcurrentQueue<T> source)
- {
- m_array = new T[SEGMENT_SIZE];
- m_state = new VolatileBool[SEGMENT_SIZE]; //all initialized to false
- _high = -1;
- Debug.Assert(index >= 0);
- m_index = index;
- _source = source;
- }
-
- /// <summary>
- /// return the next segment
- /// </summary>
- internal Segment Next
- {
- get { return _next; }
- }
-
-
- /// <summary>
- /// return true if the current segment is empty (doesn't have any element available to dequeue,
- /// false otherwise
- /// </summary>
- internal bool IsEmpty
- {
- get { return (Low > High); }
- }
-
- /// <summary>
- /// Add an element to the tail of the current segment
- /// exclusively called by ConcurrentQueue.InitializedFromCollection
- /// InitializeFromCollection is responsible to guaratee that there is no index overflow,
- /// and there is no contention
- /// </summary>
- /// <param name="value"></param>
- internal void UnsafeAdd(T value)
- {
- Debug.Assert(_high < SEGMENT_SIZE - 1);
- _high++;
- m_array[_high] = value;
- m_state[_high].m_value = true;
- }
-
- /// <summary>
- /// Create a new segment and append to the current one
- /// Does not update the m_tail pointer
- /// exclusively called by ConcurrentQueue.InitializedFromCollection
- /// InitializeFromCollection is responsible to guaratee that there is no index overflow,
- /// and there is no contention
- /// </summary>
- /// <returns>the reference to the new Segment</returns>
- internal Segment UnsafeGrow()
- {
- Debug.Assert(_high >= SEGMENT_SIZE - 1);
- Segment newSegment = new Segment(m_index + 1, _source); //m_index is Int64, we don't need to worry about overflow
- _next = newSegment;
- return newSegment;
- }
-
- /// <summary>
- /// Create a new segment and append to the current one
- /// Update the m_tail pointer
- /// This method is called when there is no contention
- /// </summary>
- internal void Grow()
- {
- //no CAS is needed, since there is no contention (other threads are blocked, busy waiting)
- Segment newSegment = new Segment(m_index + 1, _source); //m_index is Int64, we don't need to worry about overflow
- _next = newSegment;
- Debug.Assert(_source._tail == this);
- _source._tail = _next;
- }
-
-
- /// <summary>
- /// Try to append an element at the end of this segment.
- /// </summary>
- /// <param name="value">the element to append</param>
- /// <param name="tail">The tail.</param>
- /// <returns>true if the element is appended, false if the current segment is full</returns>
- /// <remarks>if appending the specified element succeeds, and after which the segment is full,
- /// then grow the segment</remarks>
- internal bool TryAppend(T value)
- {
- //quickly check if m_high is already over the boundary, if so, bail out
- if (_high >= SEGMENT_SIZE - 1)
- {
- return false;
- }
-
- //Now we will use a CAS to increment m_high, and store the result in newhigh.
- //Depending on how many free spots left in this segment and how many threads are doing this Increment
- //at this time, the returning "newhigh" can be
- // 1) < SEGMENT_SIZE - 1 : we took a spot in this segment, and not the last one, just insert the value
- // 2) == SEGMENT_SIZE - 1 : we took the last spot, insert the value AND grow the segment
- // 3) > SEGMENT_SIZE - 1 : we failed to reserve a spot in this segment, we return false to
- // Queue.Enqueue method, telling it to try again in the next segment.
-
- int newhigh = SEGMENT_SIZE; //initial value set to be over the boundary
-
- //We need do Interlocked.Increment and value/state update in a finally block to ensure that they run
- //without interruption. This is to prevent anything from happening between them, and another dequeue
- //thread maybe spinning forever to wait for m_state[] to be true;
- try
- { }
- finally
- {
- newhigh = Interlocked.Increment(ref _high);
- if (newhigh <= SEGMENT_SIZE - 1)
- {
- m_array[newhigh] = value;
- m_state[newhigh].m_value = true;
- }
-
- //if this thread takes up the last slot in the segment, then this thread is responsible
- //to grow a new segment. Calling Grow must be in the finally block too for reliability reason:
- //if thread abort during Grow, other threads will be left busy spinning forever.
- if (newhigh == SEGMENT_SIZE - 1)
- {
- Grow();
- }
- }
-
- //if newhigh <= SEGMENT_SIZE-1, it means the current thread successfully takes up a spot
- return newhigh <= SEGMENT_SIZE - 1;
- }
-
-
- /// <summary>
- /// try to remove an element from the head of current segment
- /// </summary>
- /// <param name="result">The result.</param>
- /// <param name="head">The head.</param>
- /// <returns>return false only if the current segment is empty</returns>
- internal bool TryRemove(out T result)
- {
- SpinWait spin = new SpinWait();
- int lowLocal = Low, highLocal = High;
- while (lowLocal <= highLocal)
- {
- //try to update m_low
- if (Interlocked.CompareExchange(ref _low, lowLocal + 1, lowLocal) == lowLocal)
- {
- //if the specified value is not available (this spot is taken by a push operation,
- // but the value is not written into yet), then spin
- SpinWait spinLocal = new SpinWait();
- while (!m_state[lowLocal].m_value)
- {
- spinLocal.SpinOnce();
- }
- result = m_array[lowLocal];
-
- // If there is no other thread taking snapshot (GetEnumerator(), ToList(), etc), reset the deleted entry to null.
- // It is ok if after this conditional check m_numSnapshotTakers becomes > 0, because new snapshots won't include
- // the deleted entry at m_array[lowLocal].
- if (_source.m_numSnapshotTakers <= 0)
- {
- m_array[lowLocal] = default(T); //release the reference to the object.
- }
-
- //if the current thread sets m_low to SEGMENT_SIZE, which means the current segment becomes
- //disposable, then this thread is responsible to dispose this segment, and reset m_head
- if (lowLocal + 1 >= SEGMENT_SIZE)
- {
- // Invariant: we only dispose the current m_head, not any other segment
- // In usual situation, disposing a segment is simply seting m_head to m_head.m_next
- // But there is one special case, where m_head and m_tail points to the same and ONLY
- //segment of the queue: Another thread A is doing Enqueue and finds that it needs to grow,
- //while the *current* thread is doing *this* Dequeue operation, and finds that it needs to
- //dispose the current (and ONLY) segment. Then we need to wait till thread A finishes its
- //Grow operation, this is the reason of having the following while loop
- spinLocal = new SpinWait();
- while (_next == null)
- {
- spinLocal.SpinOnce();
- }
- Debug.Assert(_source._head == this);
- _source._head = _next;
- }
- return true;
- }
- else
- {
- //CAS failed due to contention: spin briefly and retry
- spin.SpinOnce();
- lowLocal = Low; highLocal = High;
- }
- }//end of while
- result = default(T);
- return false;
- }
-
- /// <summary>
- /// return the position of the head of the current segment
- /// Value range [0, SEGMENT_SIZE], if it's SEGMENT_SIZE, it means this segment is exhausted and thus empty
- /// </summary>
- internal int Low
- {
- get
- {
- return Math.Min(_low, SEGMENT_SIZE);
- }
- }
-
- /// <summary>
- /// return the logical position of the tail of the current segment
- /// Value range [-1, SEGMENT_SIZE-1]. When it's -1, it means this is a new segment and has no element yet
- /// </summary>
- internal int High
- {
- get
- {
- //if m_high > SEGMENT_SIZE, it means it's out of range, we should return
- //SEGMENT_SIZE-1 as the logical position
- return Math.Min(_high, SEGMENT_SIZE - 1);
- }
- }
- }
- }//end of class Segment
-
- /// <summary>
- /// A wrapper struct for volatile bool, please note the copy of the struct it self will not be volatile
- /// for example this statement will not include in volatilness operation volatileBool1 = volatileBool2 the jit will copy the struct and will ignore the volatile
- /// </summary>
- internal struct VolatileBool
- {
- public VolatileBool(bool value)
- {
- m_value = value;
- }
- public volatile bool m_value;
- }
-}
diff --git a/src/System.Transactions/pkg/System.Transactions.pkgproj b/src/System.Transactions/pkg/System.Transactions.pkgproj
index 329f56dfa9..54752ef1d6 100644
--- a/src/System.Transactions/pkg/System.Transactions.pkgproj
+++ b/src/System.Transactions/pkg/System.Transactions.pkgproj
@@ -3,11 +3,11 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Transactions.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Transactions.builds" />
- <InboxOnTargetFramework Include="net463">
+ <InboxOnTargetFramework Include="net461">
<AsFrameworkReference>true</AsFrameworkReference>
</InboxOnTargetFramework>
diff --git a/src/System.Transactions/src/System/Transactions/TransactionException.cs b/src/System.Transactions/src/System/Transactions/TransactionException.cs
index 99a25085db..0efd82194f 100644
--- a/src/System.Transactions/src/System/Transactions/TransactionException.cs
+++ b/src/System.Transactions/src/System/Transactions/TransactionException.cs
@@ -23,7 +23,7 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.TransactionException, message, innerException.ToString());
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.TransactionException, message, innerException==null?String.Empty:innerException.ToString());
}
return new TransactionException(message, innerException);
@@ -34,7 +34,7 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.TransactionException, message, innerException.ToString());
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.TransactionException, message, innerException==null?String.Empty:innerException.ToString());
}
return new TransactionException(message, innerException);
@@ -53,7 +53,7 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, messagewithTxId, innerException.ToString());
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, messagewithTxId, innerException==null?String.Empty:innerException.ToString());
}
return new InvalidOperationException(messagewithTxId, innerException);
}
@@ -63,7 +63,7 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(traceSource, TransactionExceptionType.InvalidOperationException, message, innerException.ToString());
+ etwLog.TransactionExceptionTrace(traceSource, TransactionExceptionType.InvalidOperationException, message, innerException==null?String.Empty:innerException.ToString());
}
return new InvalidOperationException(message, innerException);
@@ -189,7 +189,7 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.TransactionAbortedException, message, innerException.ToString());
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.TransactionAbortedException, message, innerException==null?String.Empty:innerException.ToString());
}
return new TransactionAbortedException(message, innerException);
@@ -264,7 +264,7 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(traceSource, TransactionExceptionType.TransactionInDoubtException, message, innerException.ToString());
+ etwLog.TransactionExceptionTrace(traceSource, TransactionExceptionType.TransactionInDoubtException, message, innerException==null?String.Empty:innerException.ToString());
}
return new TransactionInDoubtException(message, innerException);
@@ -315,7 +315,7 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.TransactionManagerCommunicationException, message, innerException.ToString());
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.TransactionManagerCommunicationException, message, innerException==null?String.Empty:innerException.ToString());
}
return new TransactionManagerCommunicationException(message, innerException);
diff --git a/src/System.Transactions/src/System/Transactions/TransactionState.cs b/src/System.Transactions/src/System/Transactions/TransactionState.cs
index 763e17febe..1afe9adbd0 100644
--- a/src/System.Transactions/src/System/Transactions/TransactionState.cs
+++ b/src/System.Transactions/src/System/Transactions/TransactionState.cs
@@ -877,7 +877,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), e.ToString());
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), e.ToString());
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, e.ToString());
}
throw new InvalidOperationException();
@@ -889,7 +892,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, string.Empty);
}
throw new InvalidOperationException();
@@ -901,7 +907,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, string.Empty);
}
throw new InvalidOperationException();
@@ -913,7 +922,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, string.Empty);
}
throw new InvalidOperationException();
@@ -925,7 +937,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, string.Empty);
}
throw new InvalidOperationException();
@@ -937,7 +952,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, string.Empty);
}
throw new InvalidOperationException();
@@ -949,7 +967,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, string.Empty);
}
throw new InvalidOperationException();
@@ -961,7 +982,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, string.Empty);
}
throw new InvalidOperationException();
@@ -973,7 +997,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, string.Empty);
}
throw new InvalidOperationException();
@@ -1001,7 +1028,10 @@ namespace System.Transactions
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
- etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ if (tx != null && tx.TransactionTraceId != null && tx.TransactionTraceId.TransactionIdentifier != null)
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, tx.TransactionTraceId.TransactionIdentifier.ToString(), string.Empty);
+ else
+ etwLog.TransactionExceptionTrace(TransactionExceptionType.InvalidOperationException, string.Empty, string.Empty);
}
throw new InvalidOperationException();
diff --git a/src/System.Transactions/src/System/Transactions/TransactionsEtwProvider.cs b/src/System.Transactions/src/System/Transactions/TransactionsEtwProvider.cs
index b54e9b08ea..73787886a0 100644
--- a/src/System.Transactions/src/System/Transactions/TransactionsEtwProvider.cs
+++ b/src/System.Transactions/src/System/Transactions/TransactionsEtwProvider.cs
@@ -83,7 +83,7 @@ namespace System.Transactions
///
- internal readonly static TransactionsEtwProvider Log = new TransactionsEtwProvider();
+ internal static readonly TransactionsEtwProvider Log = new TransactionsEtwProvider();
/// <summary>Prevent external instantiation. All logging should go through the Log instance.</summary>
private TransactionsEtwProvider() { }
@@ -203,14 +203,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
- TransactionCreated(
- transaction.TransactionTraceId.TransactionIdentifier, type);
+ if (transaction != null && transaction.TransactionTraceId != null)
+ TransactionCreated(transaction.TransactionTraceId.TransactionIdentifier, type);
+ else
+ TransactionCreated(string.Empty, type);
}
}
[Event(TRANSACTION_CREATED_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Informational, Task = Tasks.Transaction, Opcode = Opcodes.Create, Message = "Transaction Created. ID is {0}, type is {1}")]
private void TransactionCreated(string transactionIdentifier, string type)
{
+ SetActivityId(transactionIdentifier);
WriteEvent(TRANSACTION_CREATED_EVENTID, transactionIdentifier, type);
}
#endregion
@@ -226,14 +229,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
- TransactionCloneCreate(
- transaction.TransactionTraceId.TransactionIdentifier, type);
+ if (transaction != null && transaction.TransactionTraceId != null)
+ TransactionCloneCreate(transaction.TransactionTraceId.TransactionIdentifier, type);
+ else
+ TransactionCloneCreate(string.Empty, type);
}
}
[Event(TRANSACTION_CLONECREATE_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Informational, Task = Tasks.Transaction, Opcode = Opcodes.CloneCreate, Message = "Transaction Clone Created. ID is {0}, type is {1}")]
private void TransactionCloneCreate(string transactionIdentifier, string type)
{
+ SetActivityId(transactionIdentifier);
WriteEvent(TRANSACTION_CLONECREATE_EVENTID, transactionIdentifier, type);
}
#endregion
@@ -249,14 +255,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
- TransactionSerialized(
- transaction.TransactionTraceId.TransactionIdentifier, type);
+ if (transaction != null && transaction.TransactionTraceId != null)
+ TransactionSerialized(transaction.TransactionTraceId.TransactionIdentifier, type);
+ else
+ TransactionSerialized(string.Empty, type);
}
}
[Event(TRANSACTION_SERIALIZED_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Informational, Task = Tasks.Transaction, Opcode = Opcodes.Serialized, Message = "Transaction Serialized. ID is {0}, type is {1}")]
private void TransactionSerialized(string transactionIdentifier, string type)
{
+ SetActivityId(transactionIdentifier);
WriteEvent(TRANSACTION_SERIALIZED_EVENTID, transactionIdentifier, type);
}
#endregion
@@ -299,12 +308,14 @@ namespace System.Transactions
[Event(TRANSACTION_EXCEPTION_BASE_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Error, Task = Tasks.TransactionException, Message = "Transaction Exception. Type is {0}, message is {1}, InnerException is {2}")]
private void TransactionExceptionBase(string type, string message, string innerExceptionStr)
{
+ SetActivityId(string.Empty);
WriteEvent(TRANSACTION_EXCEPTION_BASE_EVENTID, type, message, innerExceptionStr);
}
[Event(TRANSACTION_EXCEPTION_LTM_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Error, Task = Tasks.TransactionException, Message = "Transaction Exception. Type is {0}, message is {1}, InnerException is {2}")]
private void TransactionExceptionLtm(string type, string message, string innerExceptionStr)
{
+ SetActivityId(string.Empty);
WriteEvent(TRANSACTION_EXCEPTION_LTM_EVENTID, type, message, innerExceptionStr);
}
#endregion
@@ -325,6 +336,7 @@ namespace System.Transactions
[Event(TRANSACTION_INVALID_OPERATION_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Error, Task = Tasks.Transaction, Opcode = Opcodes.InvalidOperation, Message = "Transaction Invalid Operation. ID is {0}, type is {1} and operation is {2}")]
private void TransactionInvalidOperation(string transactionIdentifier, string type, string operation)
{
+ SetActivityId(string.Empty);
WriteEvent(TRANSACTION_INVALID_OPERATION_EVENTID, transactionIdentifier, type, operation);
}
#endregion
@@ -340,14 +352,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- TransactionRollback(
- transaction.TransactionTraceId.TransactionIdentifier, type);
+ if (transaction != null && transaction.TransactionTraceId != null)
+ TransactionRollback(transaction.TransactionTraceId.TransactionIdentifier, type);
+ else
+ TransactionRollback(string.Empty, type);
}
}
[Event(TRANSACTION_ROLLBACK_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Warning, Task = Tasks.Transaction, Opcode = Opcodes.Rollback, Message = "Transaction Rollback. ID is {0}, type is {1}")]
private void TransactionRollback(string transactionIdentifier, string type)
{
+ SetActivityId(transactionIdentifier);
WriteEvent(TRANSACTION_ROLLBACK_EVENTID, transactionIdentifier, type);
}
#endregion
@@ -363,14 +378,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
- TransactionDependentCloneComplete(
- transaction.TransactionTraceId.TransactionIdentifier, type);
+ if (transaction != null && transaction.TransactionTraceId != null)
+ TransactionDependentCloneComplete(transaction.TransactionTraceId.TransactionIdentifier, type);
+ else
+ TransactionDependentCloneComplete(string.Empty, type);
}
}
[Event(TRANSACTION_DEPENDENT_CLONE_COMPLETE_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Informational, Task = Tasks.Transaction, Opcode = Opcodes.DependentCloneComplete, Message = "Transaction Dependent Clone Completed. ID is {0}, type is {1}")]
private void TransactionDependentCloneComplete(string transactionIdentifier, string type)
{
+ SetActivityId(transactionIdentifier);
WriteEvent(TRANSACTION_DEPENDENT_CLONE_COMPLETE_EVENTID, transactionIdentifier, type);
}
#endregion
@@ -386,14 +404,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
{
- TransactionCommit(
- transaction.TransactionTraceId.TransactionIdentifier, type);
+ if (transaction != null && transaction.TransactionTraceId != null)
+ TransactionCommit(transaction.TransactionTraceId.TransactionIdentifier, type);
+ else
+ TransactionCommit(string.Empty, type);
}
}
[Event(TRANSACTION_COMMIT_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Verbose, Task = Tasks.Transaction, Opcode = Opcodes.Commit, Message = "Transaction Commit: ID is {0}, type is {1}")]
private void TransactionCommit(string transactionIdentifier, string type)
{
+ SetActivityId(transactionIdentifier);
WriteEvent(TRANSACTION_COMMIT_EVENTID, transactionIdentifier, type);
}
#endregion
@@ -409,13 +430,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
{
- EnlistmentStatus(enlistment.EnlistmentTraceId.EnlistmentIdentifier, notificationCall.ToString());
+ if (enlistment != null && enlistment.EnlistmentTraceId != null)
+ EnlistmentStatus(enlistment.EnlistmentTraceId.EnlistmentIdentifier, notificationCall.ToString());
+ else
+ EnlistmentStatus(0, notificationCall.ToString());
}
}
[Event(ENLISTMENT_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Verbose, Task = Tasks.Enlistment, Message = "Enlistment status: ID is {0}, notificationcall is {1}")]
private void EnlistmentStatus(int enlistmentIdentifier, string notificationCall)
{
+ SetActivityId(string.Empty);
WriteEvent(ENLISTMENT_EVENTID, enlistmentIdentifier, notificationCall);
}
#endregion
@@ -430,14 +455,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
{
- EnlistmentDone(
- enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ if (enlistment != null && enlistment.EnlistmentTraceId != null)
+ EnlistmentDone(enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ else
+ EnlistmentDone(0);
}
}
[Event(ENLISTMENT_DONE_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Verbose, Task = Tasks.Enlistment, Opcode = Opcodes.Done, Message = "Enlistment.Done: ID is {0}")]
private void EnlistmentDone(int enlistmentIdentifier)
{
+ SetActivityId(string.Empty);
WriteEvent(ENLISTMENT_DONE_EVENTID, enlistmentIdentifier);
}
#endregion
@@ -452,14 +480,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
{
- EnlistmentPrepared(
- enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ if (enlistment != null && enlistment.EnlistmentTraceId != null)
+ EnlistmentPrepared(enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ else
+ EnlistmentPrepared(0);
}
}
[Event(ENLISTMENT_PREPARED_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Verbose, Task = Tasks.Enlistment, Opcode = Opcodes.Prepared, Message = "PreparingEnlistment.Prepared: ID is {0}")]
private void EnlistmentPrepared(int enlistmentIdentifier)
{
+ SetActivityId(string.Empty);
WriteEvent(ENLISTMENT_PREPARED_EVENTID, enlistmentIdentifier);
}
#endregion
@@ -474,14 +505,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- EnlistmentForceRollback(
- enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ if (enlistment != null && enlistment.EnlistmentTraceId != null)
+ EnlistmentForceRollback(enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ else
+ EnlistmentForceRollback(0);
}
}
[Event(ENLISTMENT_FORCEROLLBACK_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Warning, Task = Tasks.Enlistment, Opcode = Opcodes.ForceRollback, Message = "Enlistment forceRollback: ID is {0}")]
private void EnlistmentForceRollback(int enlistmentIdentifier)
{
+ SetActivityId(string.Empty);
WriteEvent(ENLISTMENT_FORCEROLLBACK_EVENTID, enlistmentIdentifier);
}
#endregion
@@ -496,14 +530,18 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- EnlistmentAborted(
- enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ if (enlistment != null && enlistment.EnlistmentTraceId != null)
+ EnlistmentAborted(enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ else
+ EnlistmentAborted(0);
+
}
}
[Event(ENLISTMENT_ABORTED_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Warning, Task = Tasks.Enlistment, Opcode = Opcodes.Aborted, Message = "Enlistment SinglePhase Aborted: ID is {0}")]
private void EnlistmentAborted(int enlistmentIdentifier)
{
+ SetActivityId(string.Empty);
WriteEvent(ENLISTMENT_ABORTED_EVENTID, enlistmentIdentifier);
}
#endregion
@@ -518,14 +556,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
{
- EnlistmentCommitted(
- enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ if (enlistment != null && enlistment.EnlistmentTraceId != null)
+ EnlistmentCommitted(enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ else
+ EnlistmentCommitted(0);
}
}
[Event(ENLISTMENT_COMMITTED_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Verbose, Task = Tasks.Enlistment, Opcode = Opcodes.Committed, Message = "Enlistment Committed: ID is {0}")]
private void EnlistmentCommitted(int enlistmentIdentifier)
{
+ SetActivityId(string.Empty);
WriteEvent(ENLISTMENT_COMMITTED_EVENTID, enlistmentIdentifier);
}
#endregion
@@ -540,14 +581,17 @@ namespace System.Transactions
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- EnlistmentInDoubt(
- enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ if (enlistment != null && enlistment.EnlistmentTraceId != null)
+ EnlistmentInDoubt(enlistment.EnlistmentTraceId.EnlistmentIdentifier);
+ else
+ EnlistmentInDoubt(0);
}
}
[Event(ENLISTMENT_INDOUBT_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Warning, Task = Tasks.Enlistment, Opcode = Opcodes.InDoubt, Message = "Enlistment SinglePhase InDoubt: ID is {0}")]
private void EnlistmentInDoubt(int enlistmentIdentifier)
{
+ SetActivityId(string.Empty);
WriteEvent(ENLISTMENT_INDOUBT_EVENTID, enlistmentIdentifier);
}
#endregion
@@ -603,16 +647,19 @@ namespace System.Transactions
[Event(METHOD_ENTER_LTM_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Verbose, Task = Tasks.Method, Opcode = Opcodes.Enter, Message = "Enter method : {0}.{1}")]
private void MethodEnterTraceLtm(string thisOrContextObject, string methodname)
{
+ SetActivityId(string.Empty);
WriteEvent(METHOD_ENTER_LTM_EVENTID, thisOrContextObject, methodname);
}
[Event(METHOD_ENTER_BASE_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Verbose, Task = Tasks.Method, Opcode = Opcodes.Enter, Message = "Enter method : {0}.{1}")]
private void MethodEnterTraceBase(string thisOrContextObject, string methodname)
{
+ SetActivityId(string.Empty);
WriteEvent(METHOD_ENTER_BASE_EVENTID, thisOrContextObject, methodname);
}
[Event(METHOD_ENTER_DISTRIBUTED_EVENTID, Keywords = Keywords.TraceDistributed, Level = EventLevel.Verbose, Task = Tasks.Method, Opcode = Opcodes.Enter, Message = "Enter method : {0}.{1}")]
private void MethodEnterTraceDistributed(string thisOrContextObject, string methodname)
{
+ SetActivityId(string.Empty);
WriteEvent(METHOD_ENTER_DISTRIBUTED_EVENTID, thisOrContextObject, methodname);
}
#endregion
@@ -668,16 +715,19 @@ namespace System.Transactions
[Event(METHOD_EXIT_LTM_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Verbose, Task = Tasks.Method, Opcode = Opcodes.Exit, Message = "Exit method: {0}.{1}")]
private void MethodExitTraceLtm(string thisOrContextObject, string methodname)
{
+ SetActivityId(string.Empty);
WriteEvent(METHOD_EXIT_LTM_EVENTID, thisOrContextObject, methodname);
}
[Event(METHOD_EXIT_BASE_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Verbose, Task = Tasks.Method, Opcode = Opcodes.Exit, Message = "Exit method: {0}.{1}")]
private void MethodExitTraceBase(string thisOrContextObject, string methodname)
{
+ SetActivityId(string.Empty);
WriteEvent(METHOD_EXIT_BASE_EVENTID, thisOrContextObject, methodname);
}
[Event(METHOD_EXIT_DISTRIBUTED_EVENTID, Keywords = Keywords.TraceDistributed, Level = EventLevel.Verbose, Task = Tasks.Method, Opcode = Opcodes.Exit, Message = "Exit method: {0}.{1}")]
private void MethodExitTraceDistributed(string thisOrContextObject, string methodname)
{
+ SetActivityId(string.Empty);
WriteEvent(METHOD_EXIT_DISTRIBUTED_EVENTID, thisOrContextObject, methodname);
}
@@ -716,11 +766,13 @@ namespace System.Transactions
[Event(EXCEPTION_CONSUMED_BASE_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Verbose, Opcode = Opcodes.ExceptionConsumed, Message = "Exception consumed: {0}")]
private void ExceptionConsumedBase(string exceptionStr)
{
+ SetActivityId(string.Empty);
WriteEvent(EXCEPTION_CONSUMED_BASE_EVENTID, exceptionStr);
}
[Event(EXCEPTION_CONSUMED_LTM_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Verbose, Opcode = Opcodes.ExceptionConsumed, Message = "Exception consumed: {0}")]
private void ExceptionConsumedLtm(string exceptionStr)
{
+ SetActivityId(string.Empty);
WriteEvent(EXCEPTION_CONSUMED_LTM_EVENTID, exceptionStr);
}
#endregion
@@ -740,6 +792,7 @@ namespace System.Transactions
[Event(TRANSACTIONMANAGER_REENLIST_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Informational, Task = Tasks.TransactionManager, Opcode = Opcodes.Reenlist, Message = "Reenlist in: {0}")]
private void TransactionManagerReenlistTrace(string rmID)
{
+ SetActivityId(string.Empty);
WriteEvent(TRANSACTIONMANAGER_REENLIST_EVENTID, rmID);
}
#endregion
@@ -759,6 +812,7 @@ namespace System.Transactions
[Event(TRANSACTIONMANAGER_RECOVERY_COMPLETE_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Informational, Task = Tasks.TransactionManager, Opcode = Opcodes.RecoveryComplete, Message = "Recovery complete: {0}")]
private void TransactionManagerRecoveryComplete(string rmID)
{
+ SetActivityId(string.Empty);
WriteEvent(TRANSACTIONMANAGER_RECOVERY_COMPLETE_EVENTID, rmID);
}
#endregion
@@ -777,6 +831,7 @@ namespace System.Transactions
[Event(CONFIGURED_DEFAULT_TIMEOUT_ADJUSTED_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Warning, Task = Tasks.ConfiguredDefaultTimeout, Opcode = Opcodes.Adjusted, Message = "Configured Default Timeout Adjusted")]
private void ConfiguredDefaultTimeoutAdjustedTrace()
{
+ SetActivityId(string.Empty);
WriteEvent(CONFIGURED_DEFAULT_TIMEOUT_ADJUSTED_EVENTID);
}
#endregion
@@ -790,13 +845,17 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
- TransactionScopeCreated(transactionID.TransactionIdentifier.ToString(), transactionScopeResult);
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ TransactionScopeCreated(transactionID.TransactionIdentifier.ToString(), transactionScopeResult);
+ else
+ TransactionScopeCreated(String.Empty, transactionScopeResult);
}
}
[Event(TRANSACTIONSCOPE_CREATED_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Informational, Task = Tasks.TransactionScope, Opcode = Opcodes.Created, Message = "Transactionscope was created: Transaction ID is {0}, TransactionScope Result is {1}")]
private void TransactionScopeCreated(string transactionID, TransactionScopeResult transactionScopeResult)
{
+ SetActivityId(transactionID);
WriteEvent(TRANSACTIONSCOPE_CREATED_EVENTID, transactionID, transactionScopeResult);
}
#endregion
@@ -810,13 +869,24 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- TransactionScopeCurrentChanged(currenttransactionID.TransactionIdentifier.ToString(), newtransactionID.TransactionIdentifier.ToString());
+ String currentId = String.Empty;
+ String newId = String.Empty;
+ if (currenttransactionID != null && currenttransactionID.TransactionIdentifier != null)
+ {
+ currentId = currenttransactionID.TransactionIdentifier.ToString();
+ }
+ if (newtransactionID!= null && newtransactionID.TransactionIdentifier != null)
+ {
+ newId = newtransactionID.TransactionIdentifier.ToString();
+ }
+ TransactionScopeCurrentChanged(currentId, newId);
}
}
[Event(TRANSACTIONSCOPE_CURRENT_CHANGED_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Warning, Task = Tasks.TransactionScope, Opcode = Opcodes.CurrentChanged, Message = "Transactionscope current transaction ID changed from {0} to {1}")]
private void TransactionScopeCurrentChanged(string currenttransactionID, string newtransactionID)
{
+ SetActivityId(newtransactionID);
WriteEvent(TRANSACTIONSCOPE_CURRENT_CHANGED_EVENTID, currenttransactionID, newtransactionID);
}
#endregion
@@ -829,13 +899,17 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- TransactionScopeNestedIncorrectly(transactionID.TransactionIdentifier.ToString());
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ TransactionScopeNestedIncorrectly(transactionID.TransactionIdentifier.ToString());
+ else
+ TransactionScopeNestedIncorrectly(String.Empty);
}
}
[Event(TRANSACTIONSCOPE_NESTED_INCORRECTLY_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Warning, Task = Tasks.TransactionScope, Opcode = Opcodes.NestedIncorrectly, Message = "Transactionscope nested incorrectly: transaction ID is {0}")]
private void TransactionScopeNestedIncorrectly(string transactionID)
{
+ SetActivityId(transactionID);
WriteEvent(TRANSACTIONSCOPE_NESTED_INCORRECTLY_EVENTID, transactionID);
}
#endregion
@@ -848,13 +922,17 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
- TransactionScopeDisposed(transactionID.TransactionIdentifier.ToString());
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ TransactionScopeDisposed(transactionID.TransactionIdentifier.ToString());
+ else
+ TransactionScopeDisposed(String.Empty);
}
}
[Event(TRANSACTIONSCOPE_DISPOSED_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Informational, Task = Tasks.TransactionScope, Opcode = Opcodes.Disposed, Message = "Transactionscope disposed: transaction ID is {0}")]
private void TransactionScopeDisposed(string transactionID)
{
+ SetActivityId(transactionID);
WriteEvent(TRANSACTIONSCOPE_DISPOSED_EVENTID, transactionID);
}
#endregion
@@ -867,13 +945,17 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- TransactionScopeIncomplete(transactionID.TransactionIdentifier.ToString());
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ TransactionScopeIncomplete(transactionID.TransactionIdentifier.ToString());
+ else
+ TransactionScopeIncomplete(String.Empty);
}
}
[Event(TRANSACTIONSCOPE_INCOMPLETE_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Warning, Task = Tasks.TransactionScope, Opcode = Opcodes.Incomplete, Message = "Transactionscope incomplete: transaction ID is {0}")]
private void TransactionScopeIncomplete(string transactionID)
{
+ SetActivityId(transactionID);
WriteEvent(TRANSACTIONSCOPE_INCOMPLETE_EVENTID, transactionID);
}
#endregion
@@ -893,6 +975,7 @@ namespace System.Transactions
[Event(TRANSACTIONSCOPE_INTERNAL_ERROR_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Critical, Task = Tasks.TransactionScope, Opcode = Opcodes.InternalError, Message = "Transactionscope internal error: {0}")]
private void TransactionScopeInternalErrorTrace(string error)
{
+ SetActivityId(string.Empty);
WriteEvent(TRANSACTIONSCOPE_INTERNAL_ERROR_EVENTID, error);
}
#endregion
@@ -905,13 +988,17 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- TransactionScopeTimeout(transactionID.TransactionIdentifier.ToString());
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ TransactionScopeTimeout(transactionID.TransactionIdentifier.ToString());
+ else
+ TransactionScopeTimeout(String.Empty);
}
}
[Event(TRANSACTIONSCOPE_TIMEOUT_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Warning, Task = Tasks.TransactionScope, Opcode = Opcodes.Timeout, Message = "Transactionscope timeout: transaction ID is {0}")]
private void TransactionScopeTimeout(string transactionID)
{
+ SetActivityId(transactionID);
WriteEvent(TRANSACTIONSCOPE_TIMEOUT_EVENTID, transactionID);
}
#endregion
@@ -924,13 +1011,17 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- TransactionTimeout(transactionID.TransactionIdentifier.ToString());
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ TransactionTimeout(transactionID.TransactionIdentifier.ToString());
+ else
+ TransactionTimeout(String.Empty);
}
}
[Event(TRANSACTION_TIMEOUT_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Warning, Task = Tasks.Transaction, Opcode = Opcodes.Timeout, Message = "Transaction timeout: transaction ID is {0}")]
private void TransactionTimeout(string transactionID)
{
+ SetActivityId(transactionID);
WriteEvent(TRANSACTION_TIMEOUT_EVENTID, transactionID);
}
#endregion
@@ -945,13 +1036,17 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
- TransactionstateEnlist(enlistmentID.EnlistmentIdentifier.ToString(), enlistmentType.ToString(), enlistmentOption.ToString());
+ if (enlistmentID != null)
+ TransactionstateEnlist(enlistmentID.EnlistmentIdentifier.ToString(), enlistmentType.ToString(), enlistmentOption.ToString());
+ else
+ TransactionstateEnlist(String.Empty, enlistmentType.ToString(), enlistmentOption.ToString());
}
}
[Event(TRANSACTIONSTATE_ENLIST_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Informational, Task = Tasks.TransactionState, Opcode = Opcodes.Enlist, Message = "Transactionstate enlist: Enlistment ID is {0}, type is {1} and options is {2}")]
private void TransactionstateEnlist(string enlistmentID, string type, string option)
{
+ SetActivityId(string.Empty);
WriteEvent(TRANSACTIONSTATE_ENLIST_EVENTID, enlistmentID, type, option);
}
#endregion
@@ -964,13 +1059,17 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
{
- TransactionCommitted(transactionID.TransactionIdentifier.ToString());
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ TransactionCommitted(transactionID.TransactionIdentifier.ToString());
+ else
+ TransactionCommitted(String.Empty);
}
}
[Event(TRANSACTION_COMMITTED_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Verbose, Task = Tasks.Transaction, Opcode = Opcodes.Committed, Message = "Transaction committed: transaction ID is {0}")]
private void TransactionCommitted(string transactionID)
{
+ SetActivityId(transactionID);
WriteEvent(TRANSACTION_COMMITTED_EVENTID, transactionID);
}
#endregion
@@ -983,53 +1082,68 @@ namespace System.Transactions
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- TransactionInDoubt(transactionID.TransactionIdentifier.ToString());
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ TransactionInDoubt(transactionID.TransactionIdentifier.ToString());
+ else
+ TransactionInDoubt(String.Empty);
}
}
[Event(TRANSACTION_INDOUBT_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Warning, Task = Tasks.Transaction, Opcode = Opcodes.InDoubt, Message = "Transaction indoubt: transaction ID is {0}")]
private void TransactionInDoubt(string transactionID)
{
+ SetActivityId(transactionID);
WriteEvent(TRANSACTION_INDOUBT_EVENTID, transactionID);
}
#endregion
#region Transactionstate promoted
/// <summary>Trace an event when transaction is promoted.</summary>
- /// <param name="txID">The transaction ID.</param>
+ /// <param name="transactionID">The transaction ID.</param>
/// <param name="distributedTxID">The distributed transaction ID.</param>
[NonEvent]
- internal void TransactionPromoted(TransactionTraceIdentifier txID, TransactionTraceIdentifier distributedTxID)
+ internal void TransactionPromoted(TransactionTraceIdentifier transactionID, TransactionTraceIdentifier distributedTxID)
{
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
- TransactionPromoted(txID.TransactionIdentifier.ToString(), distributedTxID.TransactionIdentifier.ToString());
+ String id = String.Empty;
+ String distributedId = String.Empty;
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ id= transactionID.TransactionIdentifier.ToString();
+ if (distributedTxID != null && distributedTxID.TransactionIdentifier != null)
+ distributedId = distributedTxID.TransactionIdentifier.ToString();
+ TransactionPromoted(id, distributedId);
}
}
[Event(TRANSACTION_PROMOTED_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Informational, Task = Tasks.Transaction, Opcode = Opcodes.Promoted, Message = "Transaction promoted: transaction ID is {0} and distributed transaction ID is {1}")]
- private void TransactionPromoted(string txID, string distributedTxID)
+ private void TransactionPromoted(string transactionID, string distributedTxID)
{
- WriteEvent(TRANSACTION_PROMOTED_EVENTID, txID, distributedTxID);
+ SetActivityId(transactionID);
+ WriteEvent(TRANSACTION_PROMOTED_EVENTID, transactionID, distributedTxID);
}
#endregion
#region Transactionstate aborted
/// <summary>Trace an event when transaction is aborted.</summary>
- /// <param name="txID">The transaction ID.</param>
+ /// <param name="transactionID">The transaction ID.</param>
[NonEvent]
- internal void TransactionAborted(TransactionTraceIdentifier txID)
+ internal void TransactionAborted(TransactionTraceIdentifier transactionID)
{
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
{
- TransactionAborted(txID.TransactionIdentifier.ToString());
+ if (transactionID != null && transactionID.TransactionIdentifier != null)
+ TransactionAborted(transactionID.TransactionIdentifier.ToString());
+ else
+ TransactionAborted(String.Empty);
}
- }
+ }
[Event(TRANSACTION_ABORTED_EVENTID, Keywords = Keywords.TraceLtm, Level = EventLevel.Warning, Task = Tasks.Transaction, Opcode = Opcodes.Aborted, Message = "Transaction aborted: transaction ID is {0}")]
- private void TransactionAborted(string txID)
+ private void TransactionAborted(string transactionID)
{
- WriteEvent(TRANSACTION_ABORTED_EVENTID, txID);
+ SetActivityId(transactionID);
+ WriteEvent(TRANSACTION_ABORTED_EVENTID, transactionID);
}
#endregion
public class Opcodes
@@ -1084,5 +1198,28 @@ namespace System.Transactions
public const EventKeywords TraceLtm = (EventKeywords)0x0002;
public const EventKeywords TraceDistributed = (EventKeywords)0x0004;
}
+
+ void SetActivityId(string str)
+ {
+ Guid guid = Guid.Empty;
+
+ if (str.IndexOf('-')>=0)
+ { // GUID with dash
+ if (str.Length>=36)
+ {
+ string str_part1 = str.Substring(0,36);
+ Guid.TryParse(str_part1, out guid);
+ }
+ }
+ else
+ {
+ if (str.Length>=32)
+ {
+ string str_part1 = str.Substring(0,32);
+ Guid.TryParse(str_part1, out guid);
+ }
+ }
+ SetCurrentThreadActivityId(guid);
+ }
}
}
diff --git a/src/System.Transactions/tests/AsyncTransactionScopeTests.cs b/src/System.Transactions/tests/AsyncTransactionScopeTests.cs
index b41af670d2..76555df305 100644
--- a/src/System.Transactions/tests/AsyncTransactionScopeTests.cs
+++ b/src/System.Transactions/tests/AsyncTransactionScopeTests.cs
@@ -4,14 +4,18 @@
using System.Collections.Concurrent;
using System.Diagnostics;
+using System.Diagnostics.Tracing;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
+using Xunit.Abstractions;
namespace System.Transactions.Tests
{
public class AsyncTransactionScopeTests
{
+ private readonly ITestOutputHelper output;
+
// Number of threads to create
private const int iterations = 5;
@@ -21,101 +25,405 @@ namespace System.Transactions.Tests
private static bool s_throwExceptionDefaultOrBeforeAwait;
private static bool s_throwExceptionAfterAwait;
+ public AsyncTransactionScopeTests(ITestOutputHelper output)
+ {
+ this.output = output;
+ }
+
/// <summary>
/// This test case will verify various Async TransactionScope usage with task and async/await and also nested mixed mode(legacy TS and async TS) usage.
/// </summary>
- [Fact]
- public void AsyncTSTest()
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(2)]
+ [InlineData(3)]
+ [InlineData(4)]
+ [InlineData(5)]
+ [InlineData(6)]
+ [InlineData(7)]
+ [InlineData(8)]
+ [InlineData(9)]
+ [InlineData(10)]
+ [InlineData(11)]
+ [InlineData(12)]
+ [InlineData(13)]
+ [InlineData(14)]
+ [InlineData(15)]
+ [InlineData(16)]
+ [InlineData(17)]
+ [InlineData(18)]
+ [InlineData(19)]
+ [InlineData(20)]
+ [InlineData(21)]
+ [InlineData(22)]
+ [InlineData(23)]
+ [InlineData(24)]
+ [InlineData(25)]
+ [InlineData(26)]
+ [InlineData(27)]
+ [InlineData(28)]
+ [InlineData(29)]
+ [InlineData(30)]
+ [InlineData(31)]
+ [InlineData(32)]
+ [InlineData(33)]
+ [InlineData(34)]
+ [InlineData(35)]
+ [InlineData(36)]
+ [InlineData(37)]
+ [InlineData(38)]
+ [InlineData(39)]
+ [InlineData(40)]
+ [InlineData(41)]
+ [InlineData(42)]
+ [InlineData(43)]
+ [InlineData(44)]
+ [InlineData(45)]
+ [InlineData(46)]
+ [InlineData(47)]
+ [InlineData(48)]
+ [InlineData(49)]
+ [InlineData(50)]
+ [InlineData(51)]
+ [InlineData(52)]
+ [InlineData(53)]
+ [InlineData(54)]
+
+ public void AsyncTSTest(int variation)
{
- // Running exception test first to make sure any unintentional leak in ambient transaction during exception will be detected when subsequent test are run.
- HandleException(true, false, () => DoSyncTxWork(true, null));
- HandleException(true, false, () => AssertTransactionNullAndWaitTask(DoAsyncTxWorkAsync(true, null)));
- HandleException(true, false, () => SyncTSL2NestedTxWork(false, false, true, null));
- HandleException(false, true, () => AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, true, false, null)));
- HandleException(true, false, () => AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, true, false, false, null)));
- HandleException(true, false, () => AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, true, false, null)));
- HandleException(false, true, () => AssertTransactionNullAndWaitTask(DoTaskWorkAsync(false, false, null)));
- HandleException(false, true, () => SyncTSTaskWork(false, null));
-
- // The following test has Task under TransactionScope and has few variations.
- DoTaskUnderAsyncTS(false, null);
- Task.Factory.StartNew(() => DoTaskUnderAsyncTS(false, null)).Wait();
- SyncTSDoTaskUnderAsyncTS(false, false, null);
- SyncTSDoTaskUnderAsyncTS(false, true, null);
- Task.Factory.StartNew(() => SyncTSDoTaskUnderAsyncTS(false, true, null)).Wait();
-
- // Simple Sync TS test
- DoSyncTxWork(false, null);
- DoSyncTxWork(true, null);
-
- // Simple Async TS test. "await" points explicitly switches threads across continuations.
- AssertTransactionNullAndWaitTask(DoAsyncTxWorkAsync(false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTxWorkAsync(true, null));
-
- // Nested TS test. Parent is Sync TS, child TS can be sync or async.
- SyncTSL2NestedTxWork(false, false, false, null);
- SyncTSL2NestedTxWork(false, false, true, null);
- SyncTSL2NestedTxWork(false, true, false, null);
- SyncTSL2NestedTxWork(false, true, true, null);
- SyncTSL2NestedTxWork(true, false, false, null);
- SyncTSL2NestedTxWork(true, false, true, null);
- SyncTSL2NestedTxWork(true, true, false, null);
- SyncTSL2NestedTxWork(true, true, true, null);
-
- // 2 level deep nested TS test. Parent is Aync TS, child TS can be sync or async.
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, false, false, false, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, false, true, false, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, false, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, true, false, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(true, false, false, false, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(true, false, true, false, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(true, true, false, false, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(true, true, true, false, false, null));
-
- // Introduce various "await" points to switch threads before/after child TransactionScope.
- // Introduce some Task variations by running the test under Task.
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, true, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, false, true, null));
- Task.Factory.StartNew(() => AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, false, true, null))).Wait();
- AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, true, true, null));
-
- // 3 level deep nested TS test.
- SyncTSL3AsyncTSL2NestedTxWork(false, false, true, false, false, true, null);
- Task.Factory.StartNew(() => SyncTSL3AsyncTSL2NestedTxWork(false, false, true, false, false, true, null)).Wait();
- SyncTSL3AsyncTSL2NestedTxWork(false, false, true, false, true, false, null);
-
- AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, false, true, false, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, true, false, false, true, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, true, false, true, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, true, false, true, true, null));
- Task.Factory.StartNew(() => AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, true, false, true, true, null))).Wait();
-
- AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, false, true, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, true, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, true, true, null));
- Task.Factory.StartNew(() => AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, true, true, null))).Wait();
-
- // Have bunch of parallel tasks running various nested TS test cases. There parallel tasks are wrapped by a TransactionScope.
- AssertTransactionNullAndWaitTask(DoTaskWorkAsync(false, false, null));
- SyncTSTaskWork(false, null);
- SyncTSTaskWork(true, null);
- AssertTransactionNullAndWaitTask(DoAsyncTSTaskWorkAsync(false, false, null));
- AssertTransactionNullAndWaitTask(DoAsyncTSTaskWorkAsync(true, false, null));
-
- // Final test - wrap the DoAsyncTSTaskWorkAsync in syncronous scope
- string txId1 = null;
- string txId2 = null;
-
- using (TransactionScope scope = new TransactionScope())
+ using (var listener = new TestEventListener(new Guid("8ac2d80a-1f1a-431b-ace4-bff8824aef0b"), System.Diagnostics.Tracing.EventLevel.Verbose))
{
- txId1 = AssertAndGetCurrentTransactionId();
- Task task = DoAsyncTSTaskWorkAsync(false, false, txId1);
- txId2 = AssertAndGetCurrentTransactionId();
- task.Wait();
- scope.Complete();
- }
+ var events = new ConcurrentQueue<EventWrittenEventArgs>();
- VerifyTxId(false, null, txId1, txId2);
+ bool success = false;
+ try
+ {
+ listener.RunWithCallback(events.Enqueue, () =>
+ {
+ switch (variation)
+ {
+ // Running exception test first to make sure any unintentional leak in ambient transaction during exception will be detected when subsequent test are run.
+ case 0:
+ {
+ HandleException(true, false, () => DoSyncTxWork(true, null));
+ break;
+ }
+ case 1:
+ {
+ HandleException(true, false, () => AssertTransactionNullAndWaitTask(DoAsyncTxWorkAsync(true, null)));
+ break;
+ }
+ case 2:
+ {
+ HandleException(true, false, () => SyncTSL2NestedTxWork(false, false, true, null));
+ break;
+ }
+ case 3:
+ {
+ HandleException(false, true, () => AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, true, false, null)));
+ break;
+ }
+ case 4:
+ {
+ HandleException(true, false, () => AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, true, false, false, null)));
+ break;
+ }
+ case 5:
+ {
+ HandleException(true, false, () => AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, true, false, null)));
+ break;
+ }
+ case 6:
+ {
+ HandleException(false, true, () => AssertTransactionNullAndWaitTask(DoTaskWorkAsync(false, false, null)));
+ break;
+ }
+ case 7:
+ {
+ HandleException(false, true, () => SyncTSTaskWork(false, null));
+ break;
+ }
+
+ // The following test has Task under TransactionScope and has few variations.
+ case 8:
+ {
+ DoTaskUnderAsyncTS(false, null);
+ break;
+ }
+ case 9:
+ {
+ Task.Factory.StartNew(() => DoTaskUnderAsyncTS(false, null)).Wait();
+ break;
+ }
+ case 10:
+ {
+ SyncTSDoTaskUnderAsyncTS(false, false, null);
+ break;
+ }
+ case 11:
+ {
+ SyncTSDoTaskUnderAsyncTS(false, true, null);
+ break;
+ }
+ case 12:
+ {
+ Task.Factory.StartNew(() => SyncTSDoTaskUnderAsyncTS(false, true, null)).Wait();
+ break;
+ }
+
+ // Simple Sync TS test
+ case 13:
+ {
+ DoSyncTxWork(false, null);
+ break;
+ }
+ case 14:
+ {
+ DoSyncTxWork(true, null);
+ break;
+ }
+
+ // Simple Async TS test. "await" points explicitly switches threads across continuations.
+ case 15:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTxWorkAsync(false, null));
+ break;
+ }
+ case 16:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTxWorkAsync(true, null));
+ break;
+ }
+
+ // Nested TS test. Parent is Sync TS, child TS can be sync or async.
+ case 17:
+ {
+ SyncTSL2NestedTxWork(false, false, false, null);
+ break;
+ }
+ case 18:
+ {
+ SyncTSL2NestedTxWork(false, false, true, null);
+ break;
+ }
+ case 19:
+ {
+ SyncTSL2NestedTxWork(false, true, false, null);
+ break;
+ }
+ case 20:
+ {
+ SyncTSL2NestedTxWork(false, true, true, null);
+ break;
+ }
+ case 21:
+ {
+ SyncTSL2NestedTxWork(true, false, false, null);
+ break;
+ }
+ case 22:
+ {
+ SyncTSL2NestedTxWork(true, false, true, null);
+ break;
+ }
+ case 23:
+ {
+ SyncTSL2NestedTxWork(true, true, false, null);
+ break;
+ }
+ case 24:
+ {
+ SyncTSL2NestedTxWork(true, true, true, null);
+ break;
+ }
+
+ // 2 level deep nested TS test. Parent is Aync TS, child TS can be sync or async.
+ case 25:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, false, false, false, false, null));
+ break;
+ }
+ case 26:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, false, true, false, false, null));
+ break;
+ }
+ case 27:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, false, false, null));
+ break;
+ }
+ case 28:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, true, false, false, null));
+ break;
+ }
+ case 29:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(true, false, false, false, false, null));
+ break;
+ }
+ case 30:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(true, false, true, false, false, null));
+ break;
+ }
+ case 31:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(true, true, false, false, false, null));
+ break;
+ }
+ case 32:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(true, true, true, false, false, null));
+ break;
+ }
+
+ // Introduce various "await" points to switch threads before/after child TransactionScope.
+ // Introduce some Task variations by running the test under Task.
+ case 33:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, true, false, null));
+ break;
+ }
+ case 34:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, false, true, null));
+ break;
+ }
+ case 35:
+ {
+ Task.Factory.StartNew(() => AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, false, true, null))).Wait();
+ break;
+ }
+ case 36:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL2NestedTxWorkAsync(false, true, false, true, true, null));
+ break;
+ }
+
+ // 3 level deep nested TS test.
+ case 37:
+ {
+ SyncTSL3AsyncTSL2NestedTxWork(false, false, true, false, false, true, null);
+ break;
+ }
+ case 38:
+ {
+ Task.Factory.StartNew(() => SyncTSL3AsyncTSL2NestedTxWork(false, false, true, false, false, true, null)).Wait();
+ break;
+ }
+ case 39:
+ {
+ SyncTSL3AsyncTSL2NestedTxWork(false, false, true, false, true, false, null);
+ break;
+ }
+
+ case 40:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, false, true, false, false, null));
+ break;
+ }
+ case 41:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, true, false, false, true, null));
+ break;
+ }
+ case 42:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, true, false, true, false, null));
+ break;
+ }
+ case 43:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, true, false, true, true, null));
+ break;
+ }
+ case 44:
+ {
+ Task.Factory.StartNew(() => AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, false, true, false, true, true, null))).Wait();
+ break;
+ }
+
+ case 45:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, false, true, null));
+ break;
+ }
+ case 46:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, true, false, null));
+ break;
+ }
+ case 47:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, true, true, null));
+ break;
+ }
+ case 48:
+ {
+ Task.Factory.StartNew(() => AssertTransactionNullAndWaitTask(DoAsyncTSL3SyncTSL2NestedTxWorkAsync(false, true, true, false, true, true, null))).Wait();
+ break;
+ }
+
+ // Have bunch of parallel tasks running various nested TS test cases. There parallel tasks are wrapped by a TransactionScope.
+ case 49:
+ {
+ AssertTransactionNullAndWaitTask(DoTaskWorkAsync(false, false, null));
+ break;
+ }
+ case 50:
+ {
+ SyncTSTaskWork(false, null);
+ break;
+ }
+ case 51:
+ {
+ SyncTSTaskWork(true, null);
+ break;
+ }
+ case 52:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSTaskWorkAsync(false, false, null));
+ break;
+ }
+ case 53:
+ {
+ AssertTransactionNullAndWaitTask(DoAsyncTSTaskWorkAsync(true, false, null));
+ break;
+ }
+
+ // Final test - wrap the DoAsyncTSTaskWorkAsync in syncronous scope
+ case 54:
+ {
+ string txId1 = null;
+ string txId2 = null;
+
+ using (TransactionScope scope = new TransactionScope())
+ {
+ txId1 = AssertAndGetCurrentTransactionId();
+ Task task = DoAsyncTSTaskWorkAsync(false, false, txId1);
+ txId2 = AssertAndGetCurrentTransactionId();
+ task.Wait();
+ scope.Complete();
+ }
+
+ VerifyTxId(false, null, txId1, txId2);
+ break;
+ }
+ }
+ });
+ success = true;
+ }
+ finally
+ {
+ if (!success)
+ {
+ HelperFunctions.DisplaySysTxTracing(output, events);
+ }
+ }
+ }
}
[Theory]
@@ -642,7 +950,7 @@ namespace System.Transactions.Tests
Assert.NotEqual(txId1, txId2);
if (child1ScopeOption == TransactionScopeOption.Suppress)
{
- Assert.Equal(txId2, null);
+ Assert.Equal(null, txId2);
}
}
@@ -655,7 +963,7 @@ namespace System.Transactions.Tests
Assert.NotEqual(txId1, txId4);
if (child2ScopeOption == TransactionScopeOption.Suppress)
{
- Assert.Equal(txId4, null);
+ Assert.Equal(null, txId4);
}
}
}
@@ -746,7 +1054,7 @@ namespace System.Transactions.Tests
if (scopeOption == TransactionScopeOption.Suppress)
{
- Assert.Equal(txId1, null);
+ Assert.Equal(null, txId1);
Assert.Equal(txId1, txId2);
Assert.Equal(txId2, txId3);
}
@@ -1351,12 +1659,12 @@ namespace System.Transactions.Tests
}
public static void AssertTransactionNull()
{
- Assert.Equal(Transaction.Current, null);
+ Assert.Equal(null, Transaction.Current);
}
public static void AssertTransactionNotNull()
{
- Assert.NotEqual(Transaction.Current, null);
+ Assert.NotEqual(null, Transaction.Current);
}
public static string AssertAndGetCurrentTransactionId()
diff --git a/src/System.Transactions/tests/HelperFunctions.cs b/src/System.Transactions/tests/HelperFunctions.cs
index 5c54ab7fef..627e9478ed 100644
--- a/src/System.Transactions/tests/HelperFunctions.cs
+++ b/src/System.Transactions/tests/HelperFunctions.cs
@@ -2,11 +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.Concurrent;
using System.Diagnostics;
+using System.Diagnostics.Tracing;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
+using Xunit.Abstractions;
namespace System.Transactions.Tests
{
@@ -16,5 +19,52 @@ namespace System.Transactions.Tests
{
TransactionInterop.GetDtcTransaction(tx);
}
+
+ public static void DisplaySysTxTracing(ITestOutputHelper output, ConcurrentQueue<EventWrittenEventArgs> events)
+ {
+ if (output == null)
+ {
+ return;
+ }
+
+ string outputString = null;
+ foreach (var actualevent in events)
+ {
+ switch (actualevent.Payload.Count)
+ {
+ case 0:
+ {
+ outputString = actualevent.Message;
+ break;
+ }
+ case 1:
+ {
+ outputString = String.Format(actualevent.Message, actualevent.Payload[0]);
+ break;
+ }
+ case 2:
+ {
+ outputString = String.Format(actualevent.Message, actualevent.Payload[0], actualevent.Payload[1]);
+ break;
+ }
+ case 3:
+ {
+ outputString = String.Format(actualevent.Message, actualevent.Payload[0], actualevent.Payload[1], actualevent.Payload[2]);
+ break;
+ }
+ case 4:
+ {
+ outputString = String.Format(actualevent.Message, actualevent.Payload[0], actualevent.Payload[1], actualevent.Payload[2], actualevent.Payload[3]);
+ break;
+ }
+ default:
+ {
+ outputString = String.Format(actualevent.Message, actualevent.Payload[0], actualevent.Payload[1], actualevent.Payload[2], actualevent.Payload[3], actualevent.Payload[4]);
+ break;
+ }
+ }
+ output.WriteLine(actualevent.Opcode + " : " + outputString);
+ }
+ }
}
} \ No newline at end of file
diff --git a/src/System.Transactions/tests/System.Transactions.Tests.csproj b/src/System.Transactions/tests/System.Transactions.Tests.csproj
index 935eeca3ad..c49582d01d 100644
--- a/src/System.Transactions/tests/System.Transactions.Tests.csproj
+++ b/src/System.Transactions/tests/System.Transactions.Tests.csproj
@@ -15,6 +15,7 @@
<Compile Include="LTMEnlistmentTests.cs" />
<Compile Include="HelperFunctions.cs" />
<Compile Include="TestEnlistments.cs" />
+ <Compile Include="TransactionTracingEventListener.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/System.Transactions/tests/TransactionTracingEventListener.cs b/src/System.Transactions/tests/TransactionTracingEventListener.cs
new file mode 100644
index 0000000000..84a2f56b59
--- /dev/null
+++ b/src/System.Transactions/tests/TransactionTracingEventListener.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using System.Diagnostics.Tracing;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Transactions.Tests
+{
+ public class TransactionsTracingEventListener : EventListener
+ {
+ private List<EventWrittenEventArgs> _recordedEvents = new List<EventWrittenEventArgs>();
+
+ public List<EventWrittenEventArgs> RecordedEvents { get { return _recordedEvents; } }
+
+ protected override void OnEventWritten(EventWrittenEventArgs eventData)
+ {
+ _recordedEvents.Add(eventData);
+ }
+ }
+
+ public sealed class TestEventListener : EventListener
+ {
+ private readonly string _targetSourceName;
+ private readonly Guid _targetSourceGuid;
+ private readonly EventLevel _level;
+
+ private Action<EventWrittenEventArgs> _eventWritten;
+ private List<EventSource> _tmpEventSourceList = new List<EventSource>();
+
+ public TestEventListener(string targetSourceName, EventLevel level)
+ {
+ // Store the arguments
+ _targetSourceName = targetSourceName;
+ _level = level;
+
+ LoadSourceList();
+ }
+
+ public TestEventListener(Guid targetSourceGuid, EventLevel level)
+ {
+ // Store the arguments
+ _targetSourceGuid = targetSourceGuid;
+ _level = level;
+
+ LoadSourceList();
+ }
+
+ private void LoadSourceList()
+ {
+ // The base constructor, which is called before this constructor,
+ // will invoke the virtual OnEventSourceCreated method for each
+ // existing EventSource, which means OnEventSourceCreated will be
+ // called before _targetSourceGuid and _level have been set. As such,
+ // we store a temporary list that just exists from the moment this instance
+ // is created (instance field initializers run before the base constructor)
+ // and until we finish construction... in that window, OnEventSourceCreated
+ // will store the sources into the list rather than try to enable them directly,
+ // and then here we can enumerate that list, then clear it out.
+ List<EventSource> sources;
+ lock (_tmpEventSourceList)
+ {
+ sources = _tmpEventSourceList;
+ _tmpEventSourceList = null;
+ }
+ foreach (EventSource source in sources)
+ {
+ EnableSourceIfMatch(source);
+ }
+ }
+
+ protected override void OnEventSourceCreated(EventSource eventSource)
+ {
+ List<EventSource> tmp = _tmpEventSourceList;
+ if (tmp != null)
+ {
+ lock (tmp)
+ {
+ if (_tmpEventSourceList != null)
+ {
+ _tmpEventSourceList.Add(eventSource);
+ return;
+ }
+ }
+ }
+
+ EnableSourceIfMatch(eventSource);
+ }
+
+ private void EnableSourceIfMatch(EventSource source)
+ {
+ if (source.Name.Equals(_targetSourceName) ||
+ source.Guid.Equals(_targetSourceGuid))
+ {
+ EnableEvents(source, _level);
+ }
+ }
+
+ public void RunWithCallback(Action<EventWrittenEventArgs> handler, Action body)
+ {
+ _eventWritten = handler;
+ try { body(); }
+ finally { _eventWritten = null; }
+ }
+
+ public async Task RunWithCallbackAsync(Action<EventWrittenEventArgs> handler, Func<Task> body)
+ {
+ _eventWritten = handler;
+ try { await body().ConfigureAwait(false); }
+ finally { _eventWritten = null; }
+ }
+
+ protected override void OnEventWritten(EventWrittenEventArgs eventData)
+ {
+ _eventWritten?.Invoke(eventData);
+ }
+ }
+
+}
+
diff --git a/src/System.ValueTuple/src/System/ValueTuple/ValueTuple.cs b/src/System.ValueTuple/src/System/ValueTuple/ValueTuple.cs
index 9903f38987..ea4d35082e 100644
--- a/src/System.ValueTuple/src/System/ValueTuple/ValueTuple.cs
+++ b/src/System.ValueTuple/src/System/ValueTuple/ValueTuple.cs
@@ -246,40 +246,37 @@ namespace System
internal static int CombineHashCodes(int h1, int h2)
{
- // Forward to helper class in Common for this
- // We keep the actual hashing logic there, so
- // other classes can use it for hashing
- return HashHelpers.Combine(h1, h2);
+ return HashHelpers.Combine(HashHelpers.Combine(HashHelpers.RandomSeed, h1), h2);
}
internal static int CombineHashCodes(int h1, int h2, int h3)
{
- return CombineHashCodes(CombineHashCodes(h1, h2), h3);
+ return HashHelpers.Combine(CombineHashCodes(h1, h2), h3);
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4)
{
- return CombineHashCodes(CombineHashCodes(h1, h2, h3), h4);
+ return HashHelpers.Combine(CombineHashCodes(h1, h2, h3), h4);
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5)
{
- return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), h5);
+ return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4), h5);
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6)
{
- return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4, h5), h6);
+ return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4, h5), h6);
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7)
{
- return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4, h5, h6), h7);
+ return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4, h5, h6), h7);
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8)
{
- return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4, h5, h6, h7), h8);
+ return HashHelpers.Combine(CombineHashCodes(h1, h2, h3, h4, h5, h6, h7), h8);
}
}
diff --git a/src/System.ValueTuple/tests/TupleElementNamesTests.cs b/src/System.ValueTuple/tests/TupleElementNamesTests.cs
index d131fb5afe..78fe158c4c 100644
--- a/src/System.ValueTuple/tests/TupleElementNamesTests.cs
+++ b/src/System.ValueTuple/tests/TupleElementNamesTests.cs
@@ -19,28 +19,5 @@ namespace System.Tests
Assert.Throws<ArgumentNullException>(() => new TupleElementNamesAttribute(null));
}
-
- [TupleElementNames(new string[] { null, "name1", "name2" })]
- public object appliedToField = null;
-
- public static void AppliedToParameter([TupleElementNames(new string[] { "name1", null })] object parameter) { }
-
- [TupleElementNames(new string[] { null, "name1", "name2" })]
- public static object AppliedToProperty { get; set; }
-
- [event: TupleElementNames(new[] { null, "name1", "name2" })]
- public static event Func<int> AppliedToEvent;
-
- [return: TupleElementNames(new[] { null, "name1", "name2" })]
- public static void AppliedToReturn()
- {
- AppliedToEvent();
- }
-
- [TupleElementNames(new string[] { null, "name1", "name2" })]
- public class AppliedToClass { }
-
- [TupleElementNames(new string[] { null, "name1", "name2" })]
- public class AppliedToStruct { }
}
}
diff --git a/src/System.ValueTuple/tests/ValueTupleTests.cs b/src/System.ValueTuple/tests/ValueTupleTests.cs
index 0c136e383a..cb4cb2fc0d 100644
--- a/src/System.ValueTuple/tests/ValueTupleTests.cs
+++ b/src/System.ValueTuple/tests/ValueTupleTests.cs
@@ -1030,28 +1030,6 @@ namespace System.Tests
Assert.Equal(1, sc.CompareTo(CreateLong(1, 1, 1, 1, 1, 1, 3, ValueTuple.Create(1)), TestComparer.Instance));
Assert.Equal(1, sc.CompareTo(CreateLong(1, 1, 1, 1, 1, 1, 1, ValueTuple.Create(3)), TestComparer.Instance));
- Assert.Equal(2138941962, CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create()).GetHashCode());
- Assert.Equal(2138941954, CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8)).GetHashCode());
- Assert.Equal(-1746596640, CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9)).GetHashCode());
- Assert.Equal(121964360, CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10)).GetHashCode());
- Assert.Equal(4363008, CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10, 11)).GetHashCode());
- Assert.Equal(9413384, CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10, 11, 12)).GetHashCode());
- Assert.Equal(305131744, CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10, 11, 12, 13)).GetHashCode());
- Assert.Equal(1479338186, CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10, 11, 12, 13, 14)).GetHashCode());
- Assert.Equal(1573514559, CreateLong(1, 2, 3, 4, 5, 6, 7, CreateLong(8, 9, 10, 11, 12, 13, 14, ValueTuple.Create())).GetHashCode());
- Assert.Equal(1573514711, CreateLong(1, 2, 3, 4, 5, 6, 7, CreateLong(8, 9, 10, 11, 12, 13, 14, ValueTuple.Create(15))).GetHashCode());
-
- Assert.Equal(2138941962, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create())).GetHashCode(TestEqualityComparer.Instance));
- Assert.Equal(2138941954, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8))).GetHashCode(TestEqualityComparer.Instance));
- Assert.Equal(-1746596640, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9))).GetHashCode(TestEqualityComparer.Instance));
- Assert.Equal(121964360, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10))).GetHashCode(TestEqualityComparer.Instance));
- Assert.Equal(4363008, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10, 11))).GetHashCode(TestEqualityComparer.Instance));
- Assert.Equal(9413384, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10, 11, 12))).GetHashCode(TestEqualityComparer.Instance));
- Assert.Equal(305131744, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10, 11, 12, 13))).GetHashCode(TestEqualityComparer.Instance));
- Assert.Equal(1479338186, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, ValueTuple.Create(8, 9, 10, 11, 12, 13, 14))).GetHashCode(TestEqualityComparer.Instance));
- Assert.Equal(1573514559, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, CreateLong(8, 9, 10, 11, 12, 13, 14, ValueTuple.Create()))).GetHashCode(TestEqualityComparer.Instance));
- Assert.Equal(1573514711, ((IStructuralEquatable)CreateLong(1, 2, 3, 4, 5, 6, 7, CreateLong(8, 9, 10, 11, 12, 13, 14, ValueTuple.Create(15)))).GetHashCode(TestEqualityComparer.Instance));
-
Assert.False(se.Equals(t, DummyTestEqualityComparer.Instance));
// Notice that 0-tuple prints as empty position
@@ -1128,19 +1106,11 @@ namespace System.Tests
[Fact]
public static void EightTuplesWithBadRest()
{
- // Change as necessary if in the future
- // the hash algorithm is modified again.
- const int ExpectedHash = 1291467969;
-
var d = default(ValueTuple<int, int, int, int, int, int, int, int>);
d.Item1 = 1;
d.Rest = 42;
- Assert.Equal(ExpectedHash, d.GetHashCode());
- Assert.Equal(ExpectedHash, ((IStructuralEquatable)d).GetHashCode());
Assert.Equal("(1, 0, 0, 0, 0, 0, 0, 42)", d.ToString());
- Assert.Equal(ExpectedHash, CreateLong(1, 2, 3, 4, 5, 6, 7, d).GetHashCode());
-
// GetHashCode only tries to hash the first 7 elements when rest is not ITupleInternal
Assert.Equal(ValueTuple.Create(1, 0, 0, 0, 0, 0, 0).GetHashCode(), d.GetHashCode());
Assert.Equal(((IStructuralEquatable)ValueTuple.Create(1, 0, 0, 0, 0, 0, 0)).GetHashCode(TestEqualityComparer.Instance), ((IStructuralEquatable)d).GetHashCode(TestEqualityComparer.Instance));
diff --git a/src/System.Xml.XDocument/ref/Configurations.props b/src/System.Xml.XDocument/ref/Configurations.props
new file mode 100644
index 0000000000..33939fe089
--- /dev/null
+++ b/src/System.Xml.XDocument/ref/Configurations.props
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <BuildConfigurations>
+ netstandard;
+ netcoreapp;
+ </BuildConfigurations>
+ </PropertyGroup>
+</Project>
diff --git a/src/System.Xml.XDocument/ref/System.Xml.XDocument.cs b/src/System.Xml.XDocument/ref/System.Xml.XDocument.cs
index 26f13b069e..67eacced90 100644
--- a/src/System.Xml.XDocument/ref/System.Xml.XDocument.cs
+++ b/src/System.Xml.XDocument/ref/System.Xml.XDocument.cs
@@ -121,6 +121,9 @@ namespace System.Xml.Linq
public XCData(System.Xml.Linq.XCData other) : base(default(string)) { }
public override System.Xml.XmlNodeType NodeType { get { throw null; } }
public override void WriteTo(System.Xml.XmlWriter writer) { }
+#if netcoreapp11
+ public override System.Threading.Tasks.Task WriteToAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
}
public partial class XComment : System.Xml.Linq.XNode
{
@@ -129,6 +132,9 @@ namespace System.Xml.Linq
public override System.Xml.XmlNodeType NodeType { get { throw null; } }
public string Value { get { throw null; } set { } }
public override void WriteTo(System.Xml.XmlWriter writer) { }
+#if netcoreapp11
+ public override System.Threading.Tasks.Task WriteToAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
}
public abstract partial class XContainer : System.Xml.Linq.XNode
{
@@ -178,6 +184,11 @@ namespace System.Xml.Linq
public static System.Xml.Linq.XDocument Load(string uri, System.Xml.Linq.LoadOptions options) { throw null; }
public static System.Xml.Linq.XDocument Load(System.Xml.XmlReader reader) { throw null; }
public static System.Xml.Linq.XDocument Load(System.Xml.XmlReader reader, System.Xml.Linq.LoadOptions options) { throw null; }
+#if netcoreapp11
+ public static System.Threading.Tasks.Task<System.Xml.Linq.XDocument> LoadAsync(System.IO.Stream stream, System.Xml.Linq.LoadOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public static System.Threading.Tasks.Task<System.Xml.Linq.XDocument> LoadAsync(System.IO.TextReader textReader, System.Xml.Linq.LoadOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public static System.Threading.Tasks.Task<System.Xml.Linq.XDocument> LoadAsync(System.Xml.XmlReader reader, System.Xml.Linq.LoadOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
public static System.Xml.Linq.XDocument Parse(string text) { throw null; }
public static System.Xml.Linq.XDocument Parse(string text, System.Xml.Linq.LoadOptions options) { throw null; }
public void Save(System.IO.Stream stream) { }
@@ -187,7 +198,15 @@ namespace System.Xml.Linq
public void Save(System.Xml.XmlWriter writer) { }
public void Save(System.String fileName) { }
public void Save(System.String fileName, System.Xml.Linq.SaveOptions options) { }
+#if netcoreapp11
+ public System.Threading.Tasks.Task SaveAsync(System.IO.Stream stream, System.Xml.Linq.SaveOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public System.Threading.Tasks.Task SaveAsync(System.IO.TextWriter textWriter, System.Xml.Linq.SaveOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public System.Threading.Tasks.Task SaveAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
public override void WriteTo(System.Xml.XmlWriter writer) { }
+#if netcoreapp11
+ public override System.Threading.Tasks.Task WriteToAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
}
public partial class XDocumentType : System.Xml.Linq.XNode
{
@@ -199,6 +218,9 @@ namespace System.Xml.Linq
public string PublicId { get { throw null; } set { } }
public string SystemId { get { throw null; } set { } }
public override void WriteTo(System.Xml.XmlWriter writer) { }
+#if netcoreapp11
+ public override System.Threading.Tasks.Task WriteToAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
}
public partial class XElement : System.Xml.Linq.XContainer, System.Xml.Serialization.IXmlSerializable
{
@@ -235,6 +257,11 @@ namespace System.Xml.Linq
public static System.Xml.Linq.XElement Load(string uri, System.Xml.Linq.LoadOptions options) { throw null; }
public static System.Xml.Linq.XElement Load(System.Xml.XmlReader reader) { throw null; }
public static System.Xml.Linq.XElement Load(System.Xml.XmlReader reader, System.Xml.Linq.LoadOptions options) { throw null; }
+#if netcoreapp11
+ public static System.Threading.Tasks.Task<System.Xml.Linq.XElement> LoadAsync(System.IO.Stream stream, System.Xml.Linq.LoadOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public static System.Threading.Tasks.Task<System.Xml.Linq.XElement> LoadAsync(System.IO.TextReader textReader, System.Xml.Linq.LoadOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public static System.Threading.Tasks.Task<System.Xml.Linq.XElement> LoadAsync(System.Xml.XmlReader reader, System.Xml.Linq.LoadOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
[System.CLSCompliantAttribute(false)]
public static explicit operator bool (System.Xml.Linq.XElement element) { throw null; }
[System.CLSCompliantAttribute(false)]
@@ -300,6 +327,11 @@ namespace System.Xml.Linq
public void Save(System.Xml.XmlWriter writer) { }
public void Save(System.String fileName) { }
public void Save(System.String fileName, System.Xml.Linq.SaveOptions options) { }
+#if netcoreapp11
+ public System.Threading.Tasks.Task SaveAsync(System.IO.Stream stream, System.Xml.Linq.SaveOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public System.Threading.Tasks.Task SaveAsync(System.IO.TextWriter textWriter, System.Xml.Linq.SaveOptions options, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public System.Threading.Tasks.Task SaveAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
public void SetAttributeValue(System.Xml.Linq.XName name, object value) { }
public void SetElementValue(System.Xml.Linq.XName name, object value) { }
public void SetValue(object value) { }
@@ -307,6 +339,9 @@ namespace System.Xml.Linq
void System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader reader) { }
void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) { }
public override void WriteTo(System.Xml.XmlWriter writer) { }
+#if netcoreapp11
+ public override System.Threading.Tasks.Task WriteToAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
}
public sealed partial class XName : System.IEquatable<System.Xml.Linq.XName>, System.Runtime.Serialization.ISerializable
{
@@ -370,12 +405,18 @@ namespace System.Xml.Linq
public System.Collections.Generic.IEnumerable<System.Xml.Linq.XNode> NodesAfterSelf() { throw null; }
public System.Collections.Generic.IEnumerable<System.Xml.Linq.XNode> NodesBeforeSelf() { throw null; }
public static System.Xml.Linq.XNode ReadFrom(System.Xml.XmlReader reader) { throw null; }
+#if netcoreapp11
+ public static System.Threading.Tasks.Task<System.Xml.Linq.XNode> ReadFromAsync(System.Xml.XmlReader reader, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
public void Remove() { }
public void ReplaceWith(object content) { }
public void ReplaceWith(params object[] content) { }
public override string ToString() { throw null; }
public string ToString(System.Xml.Linq.SaveOptions options) { throw null; }
public abstract void WriteTo(System.Xml.XmlWriter writer);
+#if netcoreapp11
+ public abstract System.Threading.Tasks.Task WriteToAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken);
+#endif
}
public sealed partial class XNodeDocumentOrderComparer : System.Collections.Generic.IComparer<System.Xml.Linq.XNode>, System.Collections.IComparer
{
@@ -435,6 +476,9 @@ namespace System.Xml.Linq
public override System.Xml.XmlNodeType NodeType { get { throw null; } }
public string Target { get { throw null; } set { } }
public override void WriteTo(System.Xml.XmlWriter writer) { }
+#if netcoreapp11
+ public override System.Threading.Tasks.Task WriteToAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
}
public partial class XStreamingElement
{
@@ -462,6 +506,9 @@ namespace System.Xml.Linq
public override System.Xml.XmlNodeType NodeType { get { throw null; } }
public string Value { get { throw null; } set { } }
public override void WriteTo(System.Xml.XmlWriter writer) { }
+#if netcoreapp11
+ public override System.Threading.Tasks.Task WriteToAsync(System.Xml.XmlWriter writer, System.Threading.CancellationToken cancellationToken) { throw null; }
+#endif
}
}
namespace System.Xml.Schema
diff --git a/src/System.Xml.XDocument/ref/System.Xml.XDocument.csproj b/src/System.Xml.XDocument/ref/System.Xml.XDocument.csproj
index 204d47cae5..412c6c3bb5 100644
--- a/src/System.Xml.XDocument/ref/System.Xml.XDocument.csproj
+++ b/src/System.Xml.XDocument/ref/System.Xml.XDocument.csproj
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <DefineConstants Condition="'$(TargetGroup)'=='netcoreapp'">$(DefineConstants);netcoreapp11</DefineConstants>
+ </PropertyGroup>
<ItemGroup>
<Compile Include="System.Xml.XDocument.cs" />
<Compile Include="System.Xml.XDocument.Manual.cs" />
diff --git a/src/System.Xml.XDocument/src/ApiCompatBaseline.net463.txt b/src/System.Xml.XDocument/src/ApiCompatBaseline.net463.txt
new file mode 100644
index 0000000000..bf1bfce8ae
--- /dev/null
+++ b/src/System.Xml.XDocument/src/ApiCompatBaseline.net463.txt
@@ -0,0 +1,23 @@
+Compat issues with assembly System.Xml.XDocument:
+MembersMustExist : Member 'System.Xml.Linq.XCData.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XComment.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XDocument.LoadAsync(System.IO.Stream, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XDocument.LoadAsync(System.IO.TextReader, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XDocument.LoadAsync(System.Xml.XmlReader, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XDocument.SaveAsync(System.IO.Stream, System.Xml.Linq.SaveOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XDocument.SaveAsync(System.IO.TextWriter, System.Xml.Linq.SaveOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XDocument.SaveAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XDocument.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XDocumentType.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XElement.LoadAsync(System.IO.Stream, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XElement.LoadAsync(System.IO.TextReader, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XElement.LoadAsync(System.Xml.XmlReader, System.Xml.Linq.LoadOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XElement.SaveAsync(System.IO.Stream, System.Xml.Linq.SaveOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XElement.SaveAsync(System.IO.TextWriter, System.Xml.Linq.SaveOptions, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XElement.SaveAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XElement.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XNode.ReadFromAsync(System.Xml.XmlReader, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XNode.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XProcessingInstruction.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Xml.Linq.XText.WriteToAsync(System.Xml.XmlWriter, System.Threading.CancellationToken)' does not exist in the implementation but it does exist in the contract.
+Total Issues: 21 \ No newline at end of file
diff --git a/src/System.Xml.XPath.XmlDocument/pkg/System.Xml.XPath.XmlDocument.pkgproj b/src/System.Xml.XPath.XmlDocument/pkg/System.Xml.XPath.XmlDocument.pkgproj
index 32ed0768c2..ded2e805d2 100644
--- a/src/System.Xml.XPath.XmlDocument/pkg/System.Xml.XPath.XmlDocument.pkgproj
+++ b/src/System.Xml.XPath.XmlDocument/pkg/System.Xml.XPath.XmlDocument.pkgproj
@@ -3,7 +3,7 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.Xml.XPath.XmlDocument.csproj">
- <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
+ <SupportedFramework>net461;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Xml.XPath.XmlDocument.builds" />
<!-- nothing special required for desktop - pure plib with no type conflicts. -->
diff --git a/src/System.Xml.XPath.XmlDocument/src/Configurations.props b/src/System.Xml.XPath.XmlDocument/src/Configurations.props
index 9c336c0be9..53b62c64fe 100644
--- a/src/System.Xml.XPath.XmlDocument/src/Configurations.props
+++ b/src/System.Xml.XPath.XmlDocument/src/Configurations.props
@@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
- net463-Windows_NT;
+ net461-Windows_NT;
netstandard;
</BuildConfigurations>
</PropertyGroup>
diff --git a/src/System.Xml.XPath.XmlDocument/src/System.Xml.XPath.XmlDocument.csproj b/src/System.Xml.XPath.XmlDocument/src/System.Xml.XPath.XmlDocument.csproj
index 1bd0b45811..aebd7878d6 100644
--- a/src/System.Xml.XPath.XmlDocument/src/System.Xml.XPath.XmlDocument.csproj
+++ b/src/System.Xml.XPath.XmlDocument/src/System.Xml.XPath.XmlDocument.csproj
@@ -11,7 +11,7 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net463'">
+ <ItemGroup Condition="'$(TargetGroup)' == 'net461'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System.Xml" />
</ItemGroup>